Make sure RequestContext has a constant XID
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / callback / BaseCallback.java
1 /**
2  * Copyright (c) 2015 Cisco Systems, Inc. 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.openflowplugin.impl.callback;
9
10
11 import com.google.common.base.Preconditions;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
15 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
16 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
17 import org.opendaylight.openflowplugin.impl.services.RequestContextUtil;
18 import org.opendaylight.yangtools.yang.common.RpcError;
19 import org.opendaylight.yangtools.yang.common.RpcResult;
20 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 /**
25  * @author joe
26  */
27 public class BaseCallback<I, O> implements FutureCallback<RpcResult<I>> {
28
29     private static final Logger LOG = LoggerFactory.getLogger(BaseCallback.class);
30
31     private final DeviceContext deviceContext;
32     private final RequestContext<O> requestContext;
33     private final ListenableFuture<RpcResult<I>> futureResultFromOfLib;
34
35     public BaseCallback(final DeviceContext deviceContext, final RequestContext<O> requestContext, final ListenableFuture<RpcResult<I>> futureResultFromOfLib) {
36         this.deviceContext = Preconditions.checkNotNull(deviceContext);
37         this.requestContext = Preconditions.checkNotNull(requestContext);
38         this.futureResultFromOfLib = Preconditions.checkNotNull(futureResultFromOfLib);
39     }
40
41     protected final RequestContext<O> getRequestContext() {
42         return requestContext;
43     }
44
45     @Override
46     public void onSuccess(final RpcResult<I> fRpcResult) {
47         if (!fRpcResult.isSuccessful()) {
48             deviceContext.getMessageSpy().spyMessage(getRequestContext().getClass(), MessageSpy.STATISTIC_GROUP.TO_SWITCH_SUBMIT_FAILURE);
49
50             // remove current request from request cache in deviceContext
51             deviceContext.unhookRequestCtx(getRequestContext().getXid());
52
53             // handle requestContext failure
54             if (LOG.isTraceEnabled()) {
55                 StringBuilder rpcErrors = new StringBuilder();
56                 if (null != fRpcResult.getErrors() && fRpcResult.getErrors().size() > 0) {
57                     for (RpcError error : fRpcResult.getErrors()) {
58                         rpcErrors.append(error.getMessage());
59                             LOG.trace("Errors from rpc result.. ",error);
60                     }
61                 }
62                 LOG.trace("OF Java result for XID {} was not successful. Errors : {}", getRequestContext().getXid().getValue(), rpcErrors.toString());
63
64             }
65
66             getRequestContext().setResult(
67                     RpcResultBuilder.<O>failed().withRpcErrors(fRpcResult.getErrors()).build());
68             RequestContextUtil.closeRequstContext(getRequestContext());
69         } else {
70             // else: message was successfully sent - waiting for callback on requestContext.future to get invoked
71             // or can be implemented specific processing via processSuccess() method
72             deviceContext.getMessageSpy().spyMessage(getRequestContext().getClass(), MessageSpy.STATISTIC_GROUP.TO_SWITCH_SUBMIT_SUCCESS);
73             processSuccess(fRpcResult);
74         }
75     }
76
77
78     @Override
79     public void onFailure(final Throwable throwable) {
80         deviceContext.unhookRequestCtx(getRequestContext().getXid());
81
82         if (futureResultFromOfLib.isCancelled()) {
83             deviceContext.getMessageSpy().spyMessage(getRequestContext().getClass(), MessageSpy.STATISTIC_GROUP.TO_SWITCH_SUBMIT_SUCCESS_NO_RESPONSE);
84
85             LOG.trace("Asymmetric message - no response from OF Java expected for XID {}. Closing as successful.", getRequestContext().getXid().getValue());
86             getRequestContext().setResult(RpcResultBuilder.<O>success().build());
87         } else {
88             deviceContext.getMessageSpy().spyMessage(getRequestContext().getClass(), MessageSpy.STATISTIC_GROUP.TO_SWITCH_SUBMIT_ERROR);
89             LOG.trace("Exception occured while processing OF Java response for XID {}.", getRequestContext().getXid().getValue(), throwable);
90             getRequestContext().setResult(
91                     RpcResultBuilder.<O>failed()
92                             .withError(RpcError.ErrorType.APPLICATION, "OF JAVA operation failed.", throwable)
93                             .build());
94         }
95
96         RequestContextUtil.closeRequstContext(getRequestContext());
97     }
98
99     protected void processSuccess(final RpcResult<I> fRpcResult) {
100         //should be override in child class where is awaited processing of
101         //successfull future (e. g. transformation)
102     }
103 }