Merge "BUG-4117: add support of Old Notif. for Statistics"
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / services / batch / FlatBatchFlowAdapters.java
1 /*
2  * Copyright (c) 2016 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
9 package org.opendaylight.openflowplugin.impl.services.batch;
10
11 import com.google.common.annotations.VisibleForTesting;
12 import com.google.common.base.Function;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.JdkFutureAdapters;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import java.util.ArrayList;
17 import java.util.List;
18 import java.util.concurrent.Future;
19 import javax.annotation.Nullable;
20 import org.opendaylight.openflowplugin.impl.util.FlatBatchUtil;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchOutput;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchOutputBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.add.flow._case.FlatBatchAddFlow;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.remove.flow._case.FlatBatchRemoveFlow;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.update.flow._case.FlatBatchUpdateFlow;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.output.BatchFailure;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.output.BatchFailureBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.output.batch.failure.batch.item.id.choice.FlatBatchFailureFlowIdCaseBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.AddFlowsBatchInput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.AddFlowsBatchInputBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.BatchFlowOutputListGrouping;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.RemoveFlowsBatchInput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.RemoveFlowsBatchInputBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.UpdateFlowsBatchInput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.UpdateFlowsBatchInputBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.add.flows.batch.input.BatchAddFlows;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.add.flows.batch.input.BatchAddFlowsBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.batch.flow.output.list.grouping.BatchFailedFlowsOutput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.remove.flows.batch.input.BatchRemoveFlows;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.remove.flows.batch.input.BatchRemoveFlowsBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.update.flows.batch.input.BatchUpdateFlows;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.update.flows.batch.input.BatchUpdateFlowsBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
45 import org.opendaylight.yangtools.yang.common.RpcResult;
46 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
47
48 /**
49  * transform between FlatBatch API and flow batch API
50  */
51 public class FlatBatchFlowAdapters {
52
53     private FlatBatchFlowAdapters() {
54         throw new IllegalStateException("This class should not be instantiated.");
55     }
56
57     /**
58      * @param planStep batch step containing changes of the same type
59      * @param node     pointer for RPC routing
60      * @return input suitable for {@link org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.SalFlowsBatchService#addFlowsBatch(AddFlowsBatchInput)}
61      */
62     public static AddFlowsBatchInput adaptFlatBatchAddFlow(final BatchPlanStep planStep, final NodeRef node) {
63         final List<BatchAddFlows> batchFlows = new ArrayList<>();
64         for (FlatBatchAddFlow batchAddFlows : planStep.<FlatBatchAddFlow>getTaskBag()) {
65             final BatchAddFlows addFlows = new BatchAddFlowsBuilder((Flow) batchAddFlows)
66                     .setFlowId(batchAddFlows.getFlowId())
67                     .build();
68             batchFlows.add(addFlows);
69         }
70
71         return new AddFlowsBatchInputBuilder()
72                 .setBarrierAfter(planStep.isBarrierAfter())
73                 .setNode(node)
74                 .setBatchAddFlows(batchFlows)
75                 .build();
76     }
77
78     /**
79      * @param planStep batch step containing changes of the same type
80      * @param node     pointer for RPC routing
81      * @return input suitable for {@link org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.SalFlowsBatchService#removeFlowsBatch(RemoveFlowsBatchInput)}
82      */
83     public static RemoveFlowsBatchInput adaptFlatBatchRemoveFlow(final BatchPlanStep planStep, final NodeRef node) {
84         final List<BatchRemoveFlows> batchFlows = new ArrayList<>();
85         for (FlatBatchRemoveFlow batchRemoveFlow : planStep.<FlatBatchRemoveFlow>getTaskBag()) {
86             final BatchRemoveFlows removeFlows = new BatchRemoveFlowsBuilder((Flow) batchRemoveFlow)
87                     .setFlowId(batchRemoveFlow.getFlowId())
88                     .build();
89             batchFlows.add(removeFlows);
90         }
91
92         return new RemoveFlowsBatchInputBuilder()
93                 .setBarrierAfter(planStep.isBarrierAfter())
94                 .setNode(node)
95                 .setBatchRemoveFlows(batchFlows)
96                 .build();
97     }
98
99     /**
100      * @param planStep batch step containing changes of the same type
101      * @param node     pointer for RPC routing
102      * @return input suitable for {@link org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.SalFlowsBatchService#updateFlowsBatch(UpdateFlowsBatchInput)}
103      */
104     public static UpdateFlowsBatchInput adaptFlatBatchUpdateFlow(final BatchPlanStep planStep, final NodeRef node) {
105         final List<BatchUpdateFlows> batchFlows = new ArrayList<>();
106         for (FlatBatchUpdateFlow batchUpdateFlow : planStep.<FlatBatchUpdateFlow>getTaskBag()) {
107             final BatchUpdateFlows updateFlows = new BatchUpdateFlowsBuilder(batchUpdateFlow)
108                     .build();
109             batchFlows.add(updateFlows);
110         }
111
112         return new UpdateFlowsBatchInputBuilder()
113                 .setBarrierAfter(planStep.isBarrierAfter())
114                 .setNode(node)
115                 .setBatchUpdateFlows(batchFlows)
116                 .build();
117     }
118
119     /**
120      * @param chainInput here all partial results are collected (values + errors)
121      * @param stepOffset offset of current batch plan step
122      * @return next chained result incorporating results of this step's batch
123      */
124     @VisibleForTesting
125     static <T extends BatchFlowOutputListGrouping> Function<RpcResult<T>, RpcResult<ProcessFlatBatchOutput>>
126     createBatchFlowChainingFunction(final RpcResult<ProcessFlatBatchOutput> chainInput,
127                                     final int stepOffset) {
128         return new Function<RpcResult<T>, RpcResult<ProcessFlatBatchOutput>>() {
129             @Nullable
130             @Override
131             public RpcResult<ProcessFlatBatchOutput> apply(@Nullable final RpcResult<T> input) {
132                 // create rpcResult builder honoring both success/failure of current input and chained input + join errors
133                 final RpcResultBuilder<ProcessFlatBatchOutput> output = FlatBatchUtil.mergeRpcResults(chainInput, input);
134                 // convert values and add to chain values
135                 final ProcessFlatBatchOutputBuilder outputBuilder = new ProcessFlatBatchOutputBuilder(chainInput.getResult());
136                 final List<BatchFailure> batchFailures = wrapBatchFlowFailuresForFlat(input, stepOffset);
137                 // join values
138                 if (outputBuilder.getBatchFailure() == null) {
139                     outputBuilder.setBatchFailure(new ArrayList<BatchFailure>(batchFailures.size()));
140                 }
141                 outputBuilder.getBatchFailure().addAll(batchFailures);
142
143                 return output.withResult(outputBuilder.build()).build();
144             }
145         };
146     }
147
148     private static <T extends BatchFlowOutputListGrouping> List<BatchFailure> wrapBatchFlowFailuresForFlat(
149             final RpcResult<T> input, final int stepOffset) {
150         final List<BatchFailure> batchFailures = new ArrayList<>();
151         if (input.getResult().getBatchFailedFlowsOutput() != null) {
152             for (BatchFailedFlowsOutput stepOutput : input.getResult().getBatchFailedFlowsOutput()) {
153                 final BatchFailure batchFailure = new BatchFailureBuilder()
154                         .setBatchOrder(stepOffset + stepOutput.getBatchOrder())
155                         .setBatchItemIdChoice(new FlatBatchFailureFlowIdCaseBuilder()
156                                 .setFlowId(stepOutput.getFlowId())
157                                 .build())
158                         .build();
159                 batchFailures.add(batchFailure);
160             }
161         }
162         return batchFailures;
163     }
164
165     /**
166      * shortcut for {@link #createBatchFlowChainingFunction(RpcResult, int)} with conversion {@link ListenableFuture}
167      *
168      * @param <T>                    exact type of batch flow output
169      * @param chainInput             here all partial results are collected (values + errors)
170      * @param resultUpdateFlowFuture batch flow rpc-result (add/remove/update)
171      * @param currentOffset          offset of current batch plan step with respect to entire chain of steps
172      * @return next chained result incorporating results of this step's batch
173      */
174     public static <T extends BatchFlowOutputListGrouping> ListenableFuture<RpcResult<ProcessFlatBatchOutput>>
175     adaptFlowBatchFutureForChain(final RpcResult<ProcessFlatBatchOutput> chainInput,
176                                  final Future<RpcResult<T>> resultUpdateFlowFuture,
177                                  final int currentOffset) {
178         return Futures.transform(JdkFutureAdapters.listenInPoolThread(resultUpdateFlowFuture),
179                 FlatBatchFlowAdapters.<T>createBatchFlowChainingFunction(chainInput, currentOffset));
180     }
181 }