Add isComplete callback to commitEntry
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / core / connection / AbstractRpcListener.java
1 /*
2  * Copyright (c) 2014 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.ListenableFuture;
12 import com.google.common.util.concurrent.SettableFuture;
13 import io.netty.util.concurrent.Future;
14 import io.netty.util.concurrent.GenericFutureListener;
15 import org.opendaylight.yangtools.yang.common.RpcError;
16 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
17 import org.opendaylight.yangtools.yang.common.RpcResult;
18 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 /**
23  * This class holds all the context we need for sending a single message down the tube.
24  * A MessageHolder (used in queue) and the actual listener. It is not a thing of beauty,
25  * but it keeps us from allocating unnecessary objects in the egress path.
26  */
27 abstract class AbstractRpcListener<T> implements GenericFutureListener<Future<Void>>, ChannelOutboundQueue.MessageHolder<Object> {
28     private static final Logger LOG = LoggerFactory.getLogger(AbstractRpcListener.class);
29     private static final String APPLICATION_TAG = "OPENFLOW_LIBRARY";
30     private static final String TAG = "OPENFLOW";
31     private final SettableFuture<RpcResult<T>> result = SettableFuture.create();
32     private final String failureInfo;
33     private Object message;
34
35     /**
36      * Create RcpError object
37      * @param info
38      * @param severity - error severity
39      * @param message
40      * @param cause - details of reason
41      * @return
42      */
43     static RpcError buildRpcError(final String info, final String message, final Throwable cause) {
44         return RpcResultBuilder.newError(ErrorType.RPC, TAG, message, APPLICATION_TAG, info, cause);
45     }
46
47     AbstractRpcListener(final Object message, final String failureInfo) {
48         this.failureInfo = Preconditions.checkNotNull(failureInfo);
49         this.message = Preconditions.checkNotNull(message);
50     }
51
52     public final ListenableFuture<RpcResult<T>> getResult() {
53         return result;
54     }
55
56     @Override
57     public final void operationComplete(final Future<Void> future) {
58         if (!future.isSuccess()) {
59             LOG.debug("operation failed");
60             failedRpc(future.cause());
61         } else {
62             LOG.debug("operation complete");
63             operationSuccessful();
64         }
65     }
66
67     @Override
68     public final Object takeMessage() {
69         final Object ret = message;
70         Preconditions.checkState(ret != null, "Message has already been taken");
71         message = null;
72         return ret;
73     }
74
75     @Override
76     public final GenericFutureListener<Future<Void>> takeListener() {
77         return this;
78     }
79
80     protected abstract void operationSuccessful();
81
82     protected final void failedRpc(final Throwable cause) {
83         final RpcError rpcError = buildRpcError(failureInfo, "check switch connection", cause);
84         result.set(RpcResultBuilder.<T>failed().withRpcError(rpcError).build());
85     }
86
87     protected final void successfulRpc(final T value) {
88         result.set(RpcResultBuilder.success(value).build());
89     }
90 }