115f9205ead2a4c6af552624df5e36d42b2321e0
[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 java.util.Collections;
16 import org.opendaylight.controller.sal.common.util.RpcErrors;
17 import org.opendaylight.controller.sal.common.util.Rpcs;
18 import org.opendaylight.yangtools.yang.common.RpcError;
19 import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
20 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
21 import org.opendaylight.yangtools.yang.common.RpcResult;
22 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
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 static final String APPLICATION_TAG = "OPENFLOW_LIBRARY";
34     private static final String TAG = "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      * @param info
42      * @param severity - error severity
43      * @param message
44      * @param cause - details of reason
45      * @return
46      */
47     static RpcError buildRpcError(final String info, final ErrorSeverity severity, final String message,
48             final Throwable cause) {
49         RpcError error = RpcErrors.getRpcError(APPLICATION_TAG, TAG, info, severity, message,
50                 ErrorType.RPC, cause);
51         return error;
52     }
53
54     AbstractRpcListener(final Object message, final String failureInfo) {
55         this.failureInfo = Preconditions.checkNotNull(failureInfo);
56         this.message = Preconditions.checkNotNull(message);
57     }
58
59     public final ListenableFuture<RpcResult<T>> getResult() {
60         return result;
61     }
62
63     @Override
64     public final void operationComplete(final Future<Void> future) {
65         if (!future.isSuccess()) {
66             LOG.debug("operation failed");
67             failedRpc(future.cause());
68         } else {
69             LOG.debug("operation complete");
70             operationSuccessful();
71         }
72     }
73
74     @Override
75     public final Object takeMessage() {
76         final Object ret = message;
77         Preconditions.checkState(ret != null, "Message has already been taken");
78         message = null;
79         return ret;
80     }
81
82     @Override
83     public final GenericFutureListener<Future<Void>> takeListener() {
84         return this;
85     }
86
87     protected abstract void operationSuccessful();
88
89     protected final void failedRpc(final Throwable cause) {
90         final RpcError rpcError = buildRpcError(
91                 failureInfo, ErrorSeverity.ERROR, "check switch connection", cause);
92         result.set(Rpcs.getRpcResult(
93                 false,
94                 (T)null,
95                 Collections.singletonList(rpcError)));
96     }
97
98     protected final void successfulRpc(final T value) {
99         result.set(RpcResultBuilder.success(value).build());
100     }
101 }