BUG-3219: Fix OutboundQueue cleanup on channel failure
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / core / connection / OutboundQueueEntry.java
1 /*
2  * Copyright (c) 2015 Pantheon Technologies s.r.o. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.openflowjava.protocol.impl.core.connection;
9
10 import com.google.common.base.Preconditions;
11 import com.google.common.util.concurrent.FutureCallback;
12 import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueException;
13 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput;
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
16 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory;
18
19 final class OutboundQueueEntry {
20     private static final Logger LOG = LoggerFactory.getLogger(OutboundQueueEntry.class);
21     private FutureCallback<OfHeader> callback;
22     private OfHeader message;
23     private boolean completed;
24     private volatile boolean committed;
25
26     void commit(final OfHeader message, final FutureCallback<OfHeader> callback) {
27         this.message = message;
28         this.callback = callback;
29
30         // Volatile write, needs to be last
31         committed = true;
32     }
33
34     void reset() {
35         callback = null;
36         message = null;
37         completed = false;
38
39         // Volatile write, needs to be last
40         committed = false;
41     }
42
43     boolean isBarrier() {
44         return message instanceof BarrierInput;
45     }
46
47     boolean isCommitted() {
48         return committed;
49     }
50
51     boolean isCompleted() {
52         return completed;
53     }
54
55     OfHeader getMessage() {
56         return message;
57     }
58
59     boolean complete(final OfHeader response) {
60         Preconditions.checkState(!completed, "Attempted to complete a completed message %s with response %s", message, response);
61
62         // Multipart requests are special, we have to look at them to see
63         // if there is something outstanding and adjust ourselves accordingly
64         final boolean reallyComplete;
65         if (response instanceof MultipartReplyMessage) {
66             reallyComplete = !((MultipartReplyMessage) response).getFlags().isOFPMPFREQMORE();
67             LOG.debug("Multipart reply {}", response);
68         } else {
69             reallyComplete = true;
70         }
71
72         completed = reallyComplete;
73         if (callback != null) {
74             callback.onSuccess(response);
75         }
76         LOG.debug("Entry {} completed {} with response {}", this, completed, response);
77         return reallyComplete;
78     }
79
80     void fail(final OutboundQueueException cause) {
81         if (!completed) {
82             completed = true;
83             if (callback != null) {
84                 callback.onFailure(cause);
85             }
86         } else {
87             LOG.warn("Ignoring failure {} for completed message {}", cause, message);
88         }
89     }
90
91 }