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