/* * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.openflowplugin.impl.services.batch; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.JdkFutureAdapters; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Future; import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.add.meter._case.FlatBatchAddMeter; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.remove.meter._case.FlatBatchRemoveMeter; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.update.meter._case.FlatBatchUpdateMeter; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.output.BatchFailure; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.output.BatchFailureBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.output.batch.failure.batch.item.id.choice.FlatBatchFailureMeterIdCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.AddMetersBatchInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.AddMetersBatchInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.BatchMeterOutputListGrouping; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.RemoveMetersBatchInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.RemoveMetersBatchInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.UpdateMetersBatchInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.UpdateMetersBatchInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.add.meters.batch.input.BatchAddMeters; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.add.meters.batch.input.BatchAddMetersBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.batch.meter.output.list.grouping.BatchFailedMetersOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.remove.meters.batch.input.BatchRemoveMeters; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.remove.meters.batch.input.BatchRemoveMetersBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.update.meters.batch.input.BatchUpdateMeters; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.update.meters.batch.input.BatchUpdateMetersBuilder; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; /** * Transform between FlatBatch API and meter batch API. */ public final class FlatBatchMeterAdapters { private FlatBatchMeterAdapters() { } /** * Adapt flat batch add meter. * @param planStep batch step containing changes of the same type * @param node pointer for RPC routing * @return input suitable for {@link org.opendaylight.yang.gen.v1.urn * .opendaylight.meters.service.rev160316.SalMetersBatchService#addMetersBatch(AddMetersBatchInput)} */ public static AddMetersBatchInput adaptFlatBatchAddMeter(final BatchPlanStep planStep, final NodeRef node) { final List batchMeters = new ArrayList<>(); for (FlatBatchAddMeter batchAddMeter : planStep.getTaskBag()) { final BatchAddMeters addMeters = new BatchAddMetersBuilder(batchAddMeter) .setMeterId(batchAddMeter.getMeterId()) .build(); batchMeters.add(addMeters); } return new AddMetersBatchInputBuilder() .setBarrierAfter(planStep.isBarrierAfter()) .setNode(node) .setBatchAddMeters(batchMeters) .build(); } /** * Adapt flat batch remove meter. * @param planStep batch step containing changes of the same type * @param node pointer for RPC routing * @return input suitable for {@link org.opendaylight.yang.gen.v1.urn * .opendaylight.meters.service.rev160316.SalMetersBatchService#removeMetersBatch(RemoveMetersBatchInput)} */ public static RemoveMetersBatchInput adaptFlatBatchRemoveMeter(final BatchPlanStep planStep, final NodeRef node) { final List batchMeters = new ArrayList<>(); for (FlatBatchRemoveMeter batchRemoveMeter : planStep.getTaskBag()) { final BatchRemoveMeters removeMeters = new BatchRemoveMetersBuilder(batchRemoveMeter) .setMeterId(batchRemoveMeter.getMeterId()) .build(); batchMeters.add(removeMeters); } return new RemoveMetersBatchInputBuilder() .setBarrierAfter(planStep.isBarrierAfter()) .setNode(node) .setBatchRemoveMeters(batchMeters) .build(); } /** * Adapt flat batch update meter. * @param planStep batch step containing changes of the same type * @param node pointer for RPC routing * @return input suitable for {@link org.opendaylight.yang.gen.v1.urn * .opendaylight.meters.service.rev160316.SalMetersBatchService#updateMetersBatch(UpdateMetersBatchInput)} */ public static UpdateMetersBatchInput adaptFlatBatchUpdateMeter(final BatchPlanStep planStep, final NodeRef node) { final List batchMeters = new ArrayList<>(); for (FlatBatchUpdateMeter batchUpdateMeter : planStep.getTaskBag()) { final BatchUpdateMeters updateMeters = new BatchUpdateMetersBuilder(batchUpdateMeter) .build(); batchMeters.add(updateMeters); } return new UpdateMetersBatchInputBuilder() .setBarrierAfter(planStep.isBarrierAfter()) .setNode(node) .setBatchUpdateMeters(batchMeters) .build(); } /** * Convert meter batch result. * @param stepOffset offset of current batch plan step * @return converted {@link ProcessFlatBatchOutput} RPC result */ @VisibleForTesting static Function, RpcResult> convertBatchMeterResult(final int stepOffset) { return new Function, RpcResult>() { @Nullable @Override public RpcResult apply(@Nonnull final RpcResult input) { List batchFailures = wrapBatchMeterFailuresForFlat(input, stepOffset); ProcessFlatBatchOutputBuilder outputBuilder = new ProcessFlatBatchOutputBuilder().setBatchFailure(batchFailures); return RpcResultBuilder.status(input.isSuccessful()) .withRpcErrors(input.getErrors()) .withResult(outputBuilder.build()) .build(); } }; } private static List wrapBatchMeterFailuresForFlat( final RpcResult input, final int stepOffset) { final List batchFailures = new ArrayList<>(); if (input.getResult().getBatchFailedMetersOutput() != null) { for (BatchFailedMetersOutput stepOutput : input.getResult().getBatchFailedMetersOutput()) { final BatchFailure batchFailure = new BatchFailureBuilder() .setBatchOrder(stepOffset + stepOutput.getBatchOrder()) .setBatchItemIdChoice(new FlatBatchFailureMeterIdCaseBuilder() .setMeterId(stepOutput.getMeterId()) .build()) .build(); batchFailures.add(batchFailure); } } return batchFailures; } /** * Shortcut for {@link #convertBatchMeterResult(int)} with conversion {@link ListenableFuture}. * * @param exact type of batch flow output * @param resultUpdateMeterFuture batch group rpc-result (add/remove/update) * @param currentOffset offset of current batch plan step with respect to entire chain of steps * @return ListenableFuture with converted result {@link ProcessFlatBatchOutput} */ public static ListenableFuture> convertMeterBatchFutureForChain(final Future> resultUpdateMeterFuture, final int currentOffset) { return Futures.transform(JdkFutureAdapters.listenInPoolThread(resultUpdateMeterFuture), FlatBatchMeterAdapters.convertBatchMeterResult(currentOffset), MoreExecutors.directExecutor()); } }