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