2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.openflowplugin.impl.services;
10 import com.google.common.base.Function;
11 import com.google.common.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.Futures;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
15 import org.opendaylight.openflowplugin.api.OFConstants;
16 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
17 import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
18 import org.opendaylight.openflowplugin.api.openflow.md.core.sal.NotificationComposer;
19 import org.opendaylight.openflowplugin.api.openflow.md.core.session.IMessageDispatchService;
20 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAddedBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemovedBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdatedBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionAware;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierOutput;
35 import org.opendaylight.yangtools.yang.binding.DataContainer;
36 import org.opendaylight.yangtools.yang.binding.Notification;
37 import org.opendaylight.yangtools.yang.common.RpcError;
38 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
39 import org.opendaylight.yangtools.yang.common.RpcResult;
40 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
41 import org.slf4j.Logger;
42 import java.math.BigInteger;
43 import java.util.ArrayList;
44 import java.util.List;
45 import java.util.concurrent.Future;
47 public class CommonService {
48 // protected OFRpcTaskContext rpcTaskContext;
49 protected short version;
50 protected BigInteger datapathId;
51 protected RpcContext rpcContext;
52 protected SwitchConnectionDistinguisher cookie;
53 // TODO should come from deviceContext
54 protected IMessageDispatchService messageService;
56 protected Boolean isBarrier;
58 protected NotificationProviderService notificationProviderService;
60 protected final static Future<RpcResult<Void>> errorRpcResult = Futures.immediateFuture(RpcResultBuilder
61 .<Void>failed().withError(ErrorType.APPLICATION, "", "Request quota exceeded.").build());
63 private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(CommonService.class);
65 public CommonService() {
72 public CommonService(final RpcContext rpcContext, final short version, final BigInteger datapathId,
73 final IMessageDispatchService service, final Xid xid, final SwitchConnectionDistinguisher cookie) {
74 this.rpcContext = rpcContext;
75 this.version = version;
76 this.datapathId = datapathId;
77 this.messageService = service;
83 * @param originalResult
84 * @param notificationProviderService
85 * @param notificationComposer lazy notification composer
87 protected <R extends RpcResult<? extends TransactionAware>, N extends Notification, I extends DataContainer> void hookFutureNotification(
88 final ListenableFuture<R> originalResult, final NotificationProviderService notificationProviderService,
89 final NotificationComposer<N> notificationComposer) {
91 class FutureCallbackImpl implements FutureCallback<R> {
93 public void onSuccess(final R result) {
94 if (null == notificationProviderService) {
95 LOG.warn("onSuccess(): notificationServiceProvider is null, could not publish result {}", result);
96 } else if (notificationComposer == null) {
97 LOG.warn("onSuccess(): notificationComposer is null, could not publish result {}", result);
98 } else if (result == null) {
99 LOG.warn("onSuccess(): result is null, could not publish result {}", result);
100 } else if (result.getResult() == null) {
101 LOG.warn("onSuccess(): result.getResult() is null, could not publish result {}", result);
102 } else if (result.getResult().getTransactionId() == null) {
103 LOG.warn("onSuccess(): result.getResult().getTransactionId() is null, could not publish result {}",
106 notificationProviderService.publish(notificationComposer.compose(result.getResult()
107 .getTransactionId()));
108 // TODO: solve without task
109 // task.getTaskContext().getMessageSpy().spyMessage(
110 // task.getInput(), MessageSpy.STATISTIC_GROUP.TO_SWITCH_SUBMITTED_SUCCESS);
115 public void onFailure(final Throwable t) {
116 // TODO: good place to notify MD-SAL about errors
117 // TODO: solve without task
118 // task.getTaskContext().getMessageSpy().spyMessage(
119 // task.getInput(), MessageSpy.STATISTIC_GROUP.TO_SWITCH_SUBMITTED_FAILURE);
123 Futures.addCallback(originalResult, new FutureCallbackImpl());
130 protected NotificationComposer<FlowAdded> createFlowAddedNotification(final AddFlowInput input) {
131 return new NotificationComposer<FlowAdded>() {
133 public FlowAdded compose(final TransactionId tXid) {
134 final FlowAddedBuilder newFlow = new FlowAddedBuilder((Flow) input);
135 newFlow.setTransactionId(tXid);
136 newFlow.setFlowRef(input.getFlowRef());
137 return newFlow.build();
142 protected NotificationComposer<FlowUpdated> createFlowUpdatedNotification(final UpdateFlowInput input) {
143 return new NotificationComposer<FlowUpdated>() {
145 public FlowUpdated compose(final TransactionId tXid) {
146 final FlowUpdatedBuilder updFlow = new FlowUpdatedBuilder(input.getUpdatedFlow());
147 updFlow.setTransactionId(tXid);
148 updFlow.setFlowRef(input.getFlowRef());
149 return updFlow.build();
154 protected static NotificationComposer<FlowRemoved> createFlowRemovedNotification(final RemoveFlowInput input) {
155 return new NotificationComposer<FlowRemoved>() {
157 public FlowRemoved compose(final TransactionId tXid) {
158 final FlowRemovedBuilder removedFlow = new FlowRemovedBuilder((Flow) input);
159 removedFlow.setTransactionId(tXid);
160 removedFlow.setFlowRef(input.getFlowRef());
161 return removedFlow.build();
167 * @param originalInput
170 protected static <T extends TransactionAware> Function<RpcResult<BarrierOutput>, RpcResult<T>> transformBarrierToTransactionAware(
171 final RpcResult<T> originalInput, final BarrierInput barrierInput) {
173 class FunctionImpl implements Function<RpcResult<BarrierOutput>, RpcResult<T>> {
176 public RpcResult<T> apply(final RpcResult<BarrierOutput> barrierResult) {
177 RpcResultBuilder<T> rpcBuilder = null;
178 if (barrierResult.isSuccessful()) {
179 rpcBuilder = RpcResultBuilder.<T>success();
181 rpcBuilder = RpcResultBuilder.<T>failed();
182 final RpcError rpcError = RpcResultBuilder
185 OFConstants.ERROR_TAG_TIMEOUT,
186 "barrier sending failed",
187 OFConstants.APPLICATION_TAG,
188 "switch failed to respond on barrier request, barrier.xid = "
189 + barrierInput.getXid(), null);
190 final List<RpcError> chainedErrors = new ArrayList<>();
191 chainedErrors.add(rpcError);
192 chainedErrors.addAll(barrierResult.getErrors());
193 rpcBuilder.withRpcErrors(chainedErrors);
196 rpcBuilder.withResult(originalInput.getResult());
198 return rpcBuilder.build();
202 return new FunctionImpl();