Java tutorial
/** * Copyright 2015 Leonid Bogdanov * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.mirantis.opendaylight.route; import static com.google.common.base.Functions.constant; import static com.google.common.util.concurrent.Futures.immediateFuture; import static com.google.common.util.concurrent.Futures.transform; import static com.mirantis.opendaylight.Utils.ROUTE_LIST_ID; import static com.mirantis.opendaylight.Utils.toNodeID; import static com.mirantis.opendaylight.Utils.toTpID; import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION; import java.util.Objects; import java.util.UUID; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException; import org.opendaylight.yang.gen.v1.urn.com.mirantis.opendaylight.rev150505.*; import org.opendaylight.yang.gen.v1.urn.com.mirantis.opendaylight.rev150505.route.list.Route; import org.opendaylight.yang.gen.v1.urn.com.mirantis.opendaylight.rev150505.route.list.RouteBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcError.ErrorType; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import com.google.common.base.Optional; import com.google.common.util.concurrent.ListenableFuture; import com.mirantis.opendaylight.Retrier; /** * @author Leonid Bogdanov */ public final class RouteBuilderServiceImpl implements RouteBuilderService { private final DataBroker dataBroker; private final ExecutorService executor; public RouteBuilderServiceImpl(DataBroker dataBroker, ExecutorService executor) { this.dataBroker = dataBroker; this.executor = executor; } /** * {@inheritDoc} */ @Override public Future<RpcResult<AddRouteOutput>> addRoute(AddRouteInput input) { try { String[] src = input.getSrc().split(":", 2); String[] dst = input.getDst().split(":", 2); Uri srcNode = new Uri(toNodeID(src[0])); Uri srcTp = new Uri(toTpID(src[0], src[1])); Uri dstNode = new Uri(toNodeID(dst[0])); Uri dstTp = new Uri(toTpID(dst[0], dst[1])); return Retrier.<RpcResult<AddRouteOutput>>create().using(executor) .when(e -> e instanceof OptimisticLockFailedException).code(() -> { ReadWriteTransaction tx = dataBroker.newReadWriteTransaction(); ListenableFuture<Short> vlanF = allocateVlan(tx, srcNode, dstNode); ListenableFuture<Route> routeF = transform(vlanF, (Short vlan) -> { Route route = new RouteBuilder().setId(new Uuid(UUID.randomUUID().toString())) .setSrcNode(srcNode).setSrcTp(srcTp).setDstNode(dstNode).setDstTp(dstTp) .setVlan(vlan).build(); tx.put(CONFIGURATION, ROUTE_LIST_ID, route, true); return route; }, executor); return transform(routeF, (Route route) -> { AddRouteOutput output = new AddRouteOutputBuilder().setId(route.getId()).build(); RpcResult<AddRouteOutput> result = RpcResultBuilder.success(output).build(); return transform(tx.submit(), constant(result)); }, executor); }).retry(); } catch (RuntimeException e) { RpcResult<AddRouteOutput> result = RpcResultBuilder.<AddRouteOutput>failed() .withError(ErrorType.APPLICATION, e.getMessage(), e).build(); return immediateFuture(result); } } private ListenableFuture<Short> allocateVlan(ReadWriteTransaction tx, Uri srcNode, Uri dstNode) { if (Objects.equals(srcNode, dstNode)) { return immediateFuture(null); } InstanceIdentifier<VlanCounter> counterId = InstanceIdentifier.create(VlanCounter.class); return transform(tx.read(CONFIGURATION, counterId), (Optional<VlanCounter> counter) -> { short curVal = counter.transform(cnt -> cnt.getNextVlan().getValue()).or(1L).shortValue(); Counter32 nextVal = new Counter32(curVal < 4094 ? curVal + 1L : 1L); tx.put(CONFIGURATION, counterId, new VlanCounterBuilder().setNextVlan(nextVal).build()); return curVal; }, executor); } }