X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=bgp%2Frib-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fprotocol%2Fbgp%2Frib%2Fimpl%2FRIBImpl.java;h=622171aac35fe85ae52dc6f94ef55d07a26b52b5;hb=61e4a03e5554241bcb21dce49abe3e089e6e0237;hp=7d36f3ac08c94e8faa0303a14458a0092d69e52c;hpb=1441c59233fca7a55c16a121bd75a32ca67776a9;p=bgpcep.git diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java old mode 100755 new mode 100644 index 7d36f3ac08..622171aac3 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java @@ -7,89 +7,77 @@ */ package org.opendaylight.protocol.bgp.rib.impl; +import static com.google.common.base.Verify.verifyNotNull; import static java.util.Objects.requireNonNull; +import static org.opendaylight.protocol.bgp.rib.spi.RIBNodeIdentifiers.BGPRIB_NID; +import static org.opendaylight.protocol.bgp.rib.spi.RIBNodeIdentifiers.LOCRIB_NID; +import static org.opendaylight.protocol.bgp.rib.spi.RIBNodeIdentifiers.PEER_NID; +import static org.opendaylight.protocol.bgp.rib.spi.RIBNodeIdentifiers.RIB_NID; +import static org.opendaylight.protocol.bgp.rib.spi.RIBNodeIdentifiers.TABLES_NID; import com.google.common.base.MoreObjects; -import com.google.common.base.MoreObjects.ToStringHelper; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import com.google.common.util.concurrent.CheckedFuture; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.FluentFuture; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.MoreExecutors; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; -import javax.annotation.Nonnull; -import javax.annotation.concurrent.GuardedBy; -import javax.annotation.concurrent.ThreadSafe; -import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction; -import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.controller.md.sal.common.api.data.TransactionChain; -import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener; -import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; -import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; -import org.opendaylight.controller.md.sal.dom.api.DOMDataBrokerExtension; -import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService; -import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction; -import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain; -import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeFactory; -import org.opendaylight.mdsal.binding.generator.impl.GeneratedClassLoadingStrategy; -import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService; -import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider; -import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration; -import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; +import org.checkerframework.checker.lock.qual.GuardedBy; +import org.opendaylight.mdsal.common.api.CommitInfo; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.dom.api.DOMDataBroker; +import org.opendaylight.mdsal.dom.api.DOMDataBroker.DataTreeChangeExtension; +import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction; +import org.opendaylight.mdsal.dom.api.DOMTransactionChain; import org.opendaylight.protocol.bgp.mode.api.PathSelectionMode; import org.opendaylight.protocol.bgp.mode.impl.base.BasePathSelectionModeFactory; +import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer; import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher; -import org.opendaylight.protocol.bgp.rib.impl.spi.BgpDeployer; import org.opendaylight.protocol.bgp.rib.impl.spi.CodecsRegistry; -import org.opendaylight.protocol.bgp.rib.impl.spi.ImportPolicyPeerTracker; import org.opendaylight.protocol.bgp.rib.impl.spi.RIB; -import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContext; import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry; -import org.opendaylight.protocol.bgp.rib.impl.state.BGPRIBStateImpl; -import org.opendaylight.protocol.bgp.rib.spi.ExportPolicyPeerTracker; +import org.opendaylight.protocol.bgp.rib.impl.spi.RibOutRefresh; +import org.opendaylight.protocol.bgp.rib.impl.state.BGPRibStateImpl; +import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker; import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext; -import org.opendaylight.protocol.bgp.rib.spi.RibSupportUtils; -import org.opendaylight.protocol.bgp.rib.spi.util.ClusterSingletonServiceRegistrationHelper; +import org.opendaylight.protocol.bgp.rib.spi.RIBSupport; +import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRibRoutingPolicy; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.BgpRib; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.RibId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.Rib; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.RibKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.LocRib; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ClusterIdentifier; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.BgpTableType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.BgpRib; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.PeerId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.RibId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.Rib; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.RibKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.Tables; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.tables.Routes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.BgpId; +import org.opendaylight.yangtools.yang.binding.ChildOf; +import org.opendaylight.yangtools.yang.binding.ChoiceIn; +import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.Empty; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.InstanceIdentifierBuilder; -import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; -import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; import org.opendaylight.yangtools.yang.data.impl.schema.Builders; import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; -import org.opendaylight.yangtools.yang.model.api.SchemaContextListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@ThreadSafe -public final class RIBImpl extends BGPRIBStateImpl implements ClusterSingletonService, RIB, TransactionChainListener, - SchemaContextListener, AutoCloseable { +// This class is thread-safe +public final class RIBImpl extends BGPRibStateImpl implements RIB { private static final Logger LOG = LoggerFactory.getLogger(RIBImpl.class); private static final QName RIB_ID_QNAME = QName.create(Rib.QNAME, "id").intern(); - private static final ContainerNode EMPTY_TABLE_ATTRIBUTES = ImmutableNodes.containerNode(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.Attributes.QNAME); private final BGPDispatcher dispatcher; private final AsNumber localAs; @@ -100,289 +88,285 @@ public final class RIBImpl extends BGPRIBStateImpl implements ClusterSingletonSe private final RIBExtensionConsumerContext extensions; private final YangInstanceIdentifier yangRibId; private final RIBSupportContextRegistryImpl ribContextRegistry; - private final CodecsRegistryImpl codecsRegistry; - private final ServiceGroupIdentifier serviceGroupIdentifier; - private final ClusterSingletonServiceProvider provider; - private final BgpDeployer.WriteConfiguration configurationWriter; - private ClusterSingletonServiceRegistration registration; - private final DOMDataBrokerExtension service; - private final Map, LocRibWriter> txChainToLocRibWriter = new HashMap<>(); + private final CodecsRegistry codecsRegistry; + private final BGPTableTypeRegistryConsumer tableTypeRegistry; + private final DataTreeChangeExtension domService; + private final Map> txChainToLocRibWriter = new HashMap<>(); + private final Map vpnTableRefresher = new HashMap<>(); private final Map bestPathSelectionStrategies; - private final ImportPolicyPeerTracker importPolicyPeerTracker; private final RibId ribId; - private final Map exportPolicyPeerTrackerMap; - + private final BGPPeerTracker peerTracker = new BGPPeerTrackerImpl(); + private final BGPRibRoutingPolicy ribPolicies; + @GuardedBy("this") private DOMTransactionChain domChain; @GuardedBy("this") private boolean isServiceInstantiated; - public RIBImpl(final ClusterSingletonServiceProvider provider, final RibId ribId, final AsNumber localAs, final BgpId localBgpId, - final ClusterIdentifier clusterId, final RIBExtensionConsumerContext extensions, final BGPDispatcher dispatcher, - final BindingCodecTreeFactory codecFactory, final DOMDataBroker domDataBroker, final List localTables, - @Nonnull final Map bestPathSelectionStrategies, final GeneratedClassLoadingStrategy classStrategy, - final BgpDeployer.WriteConfiguration configurationWriter) { + public RIBImpl( + final BGPTableTypeRegistryConsumer tableTypeRegistry, + final RibId ribId, + final AsNumber localAs, + final BgpId localBgpId, + final RIBExtensionConsumerContext extensions, + final BGPDispatcher dispatcher, + final CodecsRegistry codecsRegistry, + final DOMDataBroker domDataBroker, + final BGPRibRoutingPolicy ribPolicies, + final List localTables, + final Map bestPathSelectionStrategies + ) { super(InstanceIdentifier.create(BgpRib.class).child(Rib.class, new RibKey(requireNonNull(ribId))), localBgpId, localAs); + this.tableTypeRegistry = requireNonNull(tableTypeRegistry); this.localAs = requireNonNull(localAs); - this.bgpIdentifier = requireNonNull(localBgpId); + bgpIdentifier = requireNonNull(localBgpId); this.dispatcher = requireNonNull(dispatcher); + this.localTables = ImmutableSet.copyOf(localTables); - this.localTablesKeys = new HashSet<>(); + // FIXME: can this be immutable? + localTablesKeys = localTables.stream() + .map(t -> new TablesKey(t.getAfi(), t.getSafi())) + .collect(Collectors.toCollection(HashSet::new)); + this.domDataBroker = requireNonNull(domDataBroker); - this.service = this.domDataBroker.getSupportedExtensions().get(DOMDataTreeChangeService.class); + domService = domDataBroker.extension(DataTreeChangeExtension.class); this.extensions = requireNonNull(extensions); - this.codecsRegistry = CodecsRegistryImpl.create(codecFactory, classStrategy); - this.ribContextRegistry = RIBSupportContextRegistryImpl.create(extensions, this.codecsRegistry); - final InstanceIdentifierBuilder yangRibIdBuilder = YangInstanceIdentifier.builder().node(BgpRib.QNAME).node(Rib.QNAME); - this.yangRibId = yangRibIdBuilder.nodeWithKey(Rib.QNAME, RIB_ID_QNAME, ribId.getValue()).build(); + this.ribPolicies = requireNonNull(ribPolicies); + this.codecsRegistry = codecsRegistry; + ribContextRegistry = RIBSupportContextRegistryImpl.create(extensions, codecsRegistry); + yangRibId = YangInstanceIdentifier.builder().node(BGPRIB_NID).node(RIB_NID) + .nodeWithKey(Rib.QNAME, RIB_ID_QNAME, ribId.getValue()).build(); this.bestPathSelectionStrategies = requireNonNull(bestPathSelectionStrategies); - final ClusterIdentifier cId = clusterId == null ? new ClusterIdentifier(localBgpId) : clusterId; this.ribId = ribId; - final PolicyDatabase policyDatabase = new PolicyDatabase(this.localAs.getValue(), localBgpId, cId); - this.importPolicyPeerTracker = new ImportPolicyPeerTrackerImpl(policyDatabase); - this.serviceGroupIdentifier = ServiceGroupIdentifier.create(this.ribId.getValue() + "-service-group"); - requireNonNull(provider, "ClusterSingletonServiceProvider is null"); - this.provider = provider; - this.configurationWriter = configurationWriter; - - final ImmutableMap.Builder exportPolicies = new ImmutableMap.Builder<>(); - for (final BgpTableType t : this.localTables) { - final TablesKey key = new TablesKey(t.getAfi(), t.getSafi()); - this.localTablesKeys.add(key); - exportPolicies.put(key, new ExportPolicyPeerTrackerImpl(policyDatabase, key)); - } - this.exportPolicyPeerTrackerMap = exportPolicies.build(); - LOG.info("RIB Singleton Service {} registered, RIB {}", getIdentifier().getValue(), this.ribId.getValue()); - //this need to be always the last step - this.registration = registerClusterSingletonService(this); } - private void startLocRib(final TablesKey key) { + // FIXME: make this asynchronous? + private synchronized void startLocRib(final TablesKey key) { LOG.debug("Creating LocRib table for {}", key); // create locRibWriter for each table - final DOMDataWriteTransaction tx = this.domChain.newWriteOnlyTransaction(); - - final DataContainerNodeBuilder table = ImmutableNodes.mapEntryBuilder(); - table.withNodeIdentifier(RibSupportUtils.toYangTablesKey(key)); - table.withChild(EMPTY_TABLE_ATTRIBUTES); + final DOMDataTreeWriteTransaction tx = domChain.newWriteOnlyTransaction(); - final NodeIdentifierWithPredicates tableKey = RibSupportUtils.toYangTablesKey(key); - final InstanceIdentifierBuilder tableId = YangInstanceIdentifier.builder(this.yangRibId.node(LocRib.QNAME).node(Tables.QNAME)); - tableId.nodeWithKey(tableKey.getNodeType(), tableKey.getKeyValues()); - for (final Entry e : tableKey.getKeyValues().entrySet()) { - table.withChild(ImmutableNodes.leafNode(e.getKey(), e.getValue())); - } - - final RIBSupportContext supportContext = this.ribContextRegistry.getRIBSupportContext(key); - if (supportContext != null) { - final ChoiceNode routes = supportContext.getRibSupport().emptyRoutes(); - table.withChild(routes); + final RIBSupport ribSupport = ribContextRegistry.getRIBSupport(key); + if (ribSupport != null) { + final MapEntryNode emptyTable = ribSupport.emptyTable(); + final InstanceIdentifierBuilder tableId = YangInstanceIdentifier + .builder(yangRibId.node(LOCRIB_NID).node(TABLES_NID)).node(emptyTable.name()); - tx.put(LogicalDatastoreType.OPERATIONAL, tableId.build(), table.build()); + tx.put(LogicalDatastoreType.OPERATIONAL, tableId.build(), emptyTable); try { - tx.submit().checkedGet(); - } catch (final TransactionCommitFailedException e1) { - LOG.error("Failed to initiate LocRIB for key {}", key, e1); + tx.commit().get(); + } catch (final InterruptedException | ExecutionException e) { + LOG.error("Failed to initiate LocRIB for key {}", key, e); } - createLocRibWriter(key); } else { LOG.warn("There's no registered RIB Context for {}", key.getAfi()); } } - private synchronized void createLocRibWriter(final TablesKey key) { + private synchronized , S extends ChildOf> + void createLocRibWriter(final TablesKey key) { + final RIBSupport ribSupport = ribContextRegistry.getRIBSupport(key); + if (ribSupport == null) { + return; + } LOG.debug("Creating LocRIB writer for key {}", key); - final DOMTransactionChain txChain = createPeerChain(this); - PathSelectionMode pathSelectionStrategy = this.bestPathSelectionStrategies.get(key); + final DOMTransactionChain txChain = createPeerDOMChain(); + addCallback(txChain); + PathSelectionMode pathSelectionStrategy = bestPathSelectionStrategies.get(key); if (pathSelectionStrategy == null) { pathSelectionStrategy = BasePathSelectionModeFactory.createBestPathSelectionStrategy(); } - final LocRibWriter locRibWriter = LocRibWriter.create(this.ribContextRegistry, key, txChain, - getYangRibId(), this.localAs, getService(), this.exportPolicyPeerTrackerMap.get(key), pathSelectionStrategy); + final LocRibWriter locRibWriter = LocRibWriter.create( + ribSupport, + verifyNotNull(tableTypeRegistry.getAfiSafiType(key)), + txChain, + yangRibId, + localAs, + getService(), + ribPolicies, + peerTracker, + pathSelectionStrategy); + vpnTableRefresher.put(key, locRibWriter); registerTotalPathCounter(key, locRibWriter); registerTotalPrefixesCounter(key, locRibWriter); - this.txChainToLocRibWriter.put(txChain, locRibWriter); + txChainToLocRibWriter.put(txChain, locRibWriter); } @Override public String toString() { - return addToStringAttributes(MoreObjects.toStringHelper(this)).toString(); - } - - protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) { - return toStringHelper; - } - - @Override - public synchronized void close() throws Exception { - if (this.registration != null) { - this.registration.close(); - this.registration = null; - } + return MoreObjects.toStringHelper(this).add("bgpId", bgpIdentifier).add("localTables", localTables).toString(); } @Override public AsNumber getLocalAs() { - return this.localAs; + return localAs; } @Override public BgpId getBgpIdentifier() { - return this.bgpIdentifier; + return bgpIdentifier; } - @Nonnull @Override public Set getLocalTables() { - return this.localTables; + return localTables; } @Override public BGPDispatcher getDispatcher() { - return this.dispatcher; + return dispatcher; } - @Override - public synchronized void onTransactionChainFailed(final TransactionChain chain, final AsyncTransaction transaction, final Throwable cause) { - LOG.error("Broken chain in RIB {} transaction {}", getInstanceIdentifier(), transaction != null ? transaction.getIdentifier() : null, cause); - if (this.txChainToLocRibWriter.containsKey(chain)) { - final LocRibWriter locRibWriter = this.txChainToLocRibWriter.remove(chain); - final DOMTransactionChain newChain = createPeerChain(this); + private void addCallback(final DOMTransactionChain txChain) { + txChain.addCallback(new FutureCallback() { + @Override + public void onSuccess(final Empty result) { + LOG.info("RIB {} closed successfully", getInstanceIdentifier()); + } + + @Override + public void onFailure(final Throwable cause) { + RIBImpl.this.onFailure(txChain, cause); + } + }); + } + + private synchronized void onFailure(final DOMTransactionChain chain, final Throwable cause) { + LOG.error("Broken chain in RIB {}", getInstanceIdentifier(), cause); + final LocRibWriter locRibWriter = txChainToLocRibWriter.remove(chain); + if (locRibWriter != null) { + final DOMTransactionChain newChain = createPeerDOMChain(); + addCallback(newChain); + startLocRib(locRibWriter.getTableKey()); locRibWriter.restart(newChain); - this.txChainToLocRibWriter.put(newChain, locRibWriter); + txChainToLocRibWriter.put(newChain, locRibWriter); } } @Override - public void onTransactionChainSuccessful(final TransactionChain chain) { - LOG.info("RIB {} closed successfully", getInstanceIdentifier()); + public Set getLocalTablesKeys() { + return localTablesKeys; } @Override - public Set getLocalTablesKeys() { - return this.localTablesKeys; + public boolean supportsTable(final TablesKey tableKey) { + return localTablesKeys.contains(tableKey); } @Override - public DOMDataTreeChangeService getService() { - return (DOMDataTreeChangeService) this.service; + public BGPRibRoutingPolicy getRibPolicies() { + return ribPolicies; } @Override - public YangInstanceIdentifier getYangRibId() { - return this.yangRibId; + public BGPPeerTracker getPeerTracker() { + return peerTracker; } @Override - public DOMTransactionChain createPeerChain(final TransactionChainListener listener) { - return this.domDataBroker.createTransactionChain(listener); + public void refreshTable(final TablesKey tk, final PeerId peerId) { + final RibOutRefresh table = vpnTableRefresher.get(tk); + if (table != null) { + table.refreshTable(tk, peerId); + } } @Override - public RIBExtensionConsumerContext getRibExtensions() { - return this.extensions; + public DataTreeChangeExtension getService() { + return domService; } @Override - public RIBSupportContextRegistry getRibSupportContext() { - return this.ribContextRegistry; + public YangInstanceIdentifier getYangRibId() { + return yangRibId; } @Override - public void onGlobalContextUpdated(final SchemaContext context) { - this.codecsRegistry.onSchemaContextUpdated(context); + public DOMTransactionChain createPeerDOMChain() { + return domDataBroker.createMergingTransactionChain(); } @Override - public CodecsRegistry getCodecsRegistry() { - return this.codecsRegistry; + public RIBExtensionConsumerContext getRibExtensions() { + return extensions; } @Override - public ImportPolicyPeerTracker getImportPolicyPeerTracker() { - return this.importPolicyPeerTracker; + public RIBSupportContextRegistry getRibSupportContext() { + return ribContextRegistry; } @Override - public ExportPolicyPeerTracker getExportPolicyPeerTracker(final TablesKey tablesKey) { - return this.exportPolicyPeerTrackerMap.get(tablesKey); + public CodecsRegistry getCodecsRegistry() { + return codecsRegistry; } - @Override public synchronized void instantiateServiceInstance() { - this.isServiceInstantiated = true; - this.domChain = this.domDataBroker.createTransactionChain(this); - if (this.configurationWriter != null) { - this.configurationWriter.apply(); - } - LOG.info("RIB Singleton Service {} instantiated, RIB {}", getIdentifier().getValue(), this.ribId.getValue()); - LOG.debug("Instantiating RIB table {} at {}", this.ribId, this.yangRibId); + LOG.debug("Instantiating RIB table {} at {}", ribId, yangRibId); + + isServiceInstantiated = true; + setActive(true); + domChain = domDataBroker.createMergingTransactionChain(); + addCallback(domChain); - final ContainerNode bgpRib = Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(BgpRib.QNAME)) - .addChild(ImmutableNodes.mapNodeBuilder(Rib.QNAME).build()).build(); + final ContainerNode bgpRib = Builders.containerBuilder().withNodeIdentifier(BGPRIB_NID) + .addChild(ImmutableNodes.mapNodeBuilder(RIB_NID).build()).build(); final MapEntryNode ribInstance = Builders.mapEntryBuilder().withNodeIdentifier( - new NodeIdentifierWithPredicates(Rib.QNAME, RIB_ID_QNAME, this.ribId.getValue())) - .addChild(ImmutableNodes.leafNode(RIB_ID_QNAME, this.ribId.getValue())) - .addChild(ImmutableNodes.mapNodeBuilder(Peer.QNAME).build()) - .addChild(Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(LocRib.QNAME)) - .addChild(ImmutableNodes.mapNodeBuilder(Tables.QNAME).build()) + NodeIdentifierWithPredicates.of(Rib.QNAME, RIB_ID_QNAME, ribId.getValue())) + .addChild(ImmutableNodes.leafNode(RIB_ID_QNAME, ribId.getValue())) + .addChild(ImmutableNodes.mapNodeBuilder(PEER_NID).build()) + .addChild(Builders.containerBuilder().withNodeIdentifier(LOCRIB_NID) + .addChild(ImmutableNodes.mapNodeBuilder(TABLES_NID).build()) .build()).build(); - - final DOMDataWriteTransaction trans = this.domChain.newWriteOnlyTransaction(); + final DOMDataTreeWriteTransaction trans = domChain.newWriteOnlyTransaction(); // merge empty BgpRib + Rib, to make sure the top-level parent structure is present - trans.merge(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.builder().node(BgpRib.QNAME).build(), bgpRib); - trans.put(LogicalDatastoreType.OPERATIONAL, this.yangRibId, ribInstance); + trans.merge(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.of(BGPRIB_NID), bgpRib); + trans.put(LogicalDatastoreType.OPERATIONAL, yangRibId, ribInstance); try { - trans.submit().checkedGet(); - } catch (final TransactionCommitFailedException e) { - LOG.error("Failed to initiate RIB {}", this.yangRibId, e); + trans.commit().get(); + } catch (final InterruptedException | ExecutionException e) { + LOG.error("Failed to initiate RIB {}", yangRibId, e); } LOG.debug("Effective RIB created."); - this.localTablesKeys.forEach(this::startLocRib); + localTablesKeys.forEach(this::startLocRib); + localTablesKeys.forEach(this::createLocRibWriter); } - @Override - public synchronized ListenableFuture closeServiceInstance() { - if (!this.isServiceInstantiated) { - LOG.trace("RIB Singleton Service {} already closed, RIB {}", getIdentifier().getValue(), - this.ribId.getValue()); - return Futures.immediateFuture(null); + public synchronized FluentFuture closeServiceInstance() { + if (!isServiceInstantiated) { + LOG.trace("RIB {} already closed", ribId.getValue()); + return CommitInfo.emptyFluentFuture(); } - LOG.info("Close RIB Singleton Service {}, RIB {}", getIdentifier().getValue(), this.ribId.getValue()); - this.isServiceInstantiated = false; + LOG.info("Close RIB {}", ribId.getValue()); + isServiceInstantiated = false; + setActive(false); - this.txChainToLocRibWriter.values().forEach(LocRibWriter::close); - this.txChainToLocRibWriter.clear(); + txChainToLocRibWriter.values().forEach(LocRibWriter::close); + txChainToLocRibWriter.clear(); - final DOMDataWriteTransaction t = this.domChain.newWriteOnlyTransaction(); + final DOMDataTreeWriteTransaction t = domChain.newWriteOnlyTransaction(); t.delete(LogicalDatastoreType.OPERATIONAL, getYangRibId()); - final CheckedFuture cleanFuture = t.submit(); + final FluentFuture cleanFuture = t.commit(); + cleanFuture.addCallback(new FutureCallback() { + @Override + public void onSuccess(final CommitInfo result) { + LOG.info("RIB cleaned {}", ribId.getValue()); + } - this.domChain.close(); + @Override + public void onFailure(final Throwable throwable) { + LOG.error("Failed to clean RIB {}", + ribId.getValue(), throwable); + } + }, MoreExecutors.directExecutor()); + domChain.close(); return cleanFuture; } - - @Override - public ServiceGroupIdentifier getIdentifier() { - return this.serviceGroupIdentifier; - } - - @Override - public ClusterSingletonServiceRegistration registerClusterSingletonService( - final ClusterSingletonService clusterSingletonService) { - return ClusterSingletonServiceRegistrationHelper - .registerSingletonService(this.provider, clusterSingletonService); - } - - @Override - public ServiceGroupIdentifier getRibIServiceGroupIdentifier() { - return getIdentifier(); - } }