Fix closing of peers and rib 44/98444/25
authormarekzatko <Marek.Zatko@pantheon.tech>
Fri, 12 Nov 2021 10:29:45 +0000 (11:29 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Sun, 21 Nov 2021 13:34:59 +0000 (14:34 +0100)
Migration to OSGi DS has the side effect that we get proper component
restarts based on their dependencies changing. This exposes the fact
we are not properly shutting down our singleton instances.

Since RibImpl has a captive RIBImpl instance, which undergoes lifecycle,
we have to synchronize all access to it. This is unfortunate, but
addressing this (as well as their naming) will be subject to a separate
effort.

Properly track peers, so we understand when we need to restart them.
While doing such restarts, wait for each peer to properly go down before
starting it up again.

While we are in the area, also improve BGPClusterSingletonService method
names so their intent is a tad more readable. The same goes for BgpPeer,
which is now a package-private abstract class to hide internal machinery
from the outside world.

Also ditch use of ClusterSingletonServiceRegistrationHelper -- it is a
remnant of a bygone era where ClusterSingletonServiceProvider was
incorrectly managing state -- that issue has been resolved a few years
ago. Cutting it out allows us to properly manage our lifecycle,
especially with regards to multiple registrations/instantiations.

JIRA: BGPCEP-988
Change-Id: Idb6748042ddb9a5765c3cea80f15ef319c13368b
Signed-off-by: marekzatko <Marek.Zatko@pantheon.tech>
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
14 files changed:
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AbstractBGPSessionNegotiator.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AbstractPeer.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/AppPeer.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BGPClusterSingletonService.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpPeer.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/DefaultBgpDeployer.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/PeerBean.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/RibImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/protocol/BGPReconnectPromise.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/config/AppPeerTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpDeployerTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpPeerTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/config/RibImplTest.java

index da612b5ecae6e9b2ae42cfeaf0c23e2bdfe5ec58..3aebfa9f7993ecf370a87122505acf7128c7c0bf 100644 (file)
@@ -92,6 +92,7 @@ abstract class AbstractBGPSessionNegotiator extends ChannelInboundHandlerAdapter
 
     @SuppressWarnings("checkstyle:illegalCatch")
     private synchronized void startNegotiation() {
+        LOG.debug("Starting negotiating with {}, current state: {}", channel.remoteAddress(), state);
         if (!(this.state == State.IDLE || this.state == State.OPEN_CONFIRM)) {
             return;
         }
index 4d3c5c6d04718342abae6065b7d4a8b0292face1..85b1b42526b280a517d66907ec6223131956633a 100644 (file)
@@ -111,8 +111,8 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
             final Map<TablesKey, Integer> afiSafisLlGracefulAdvertized) {
         super(rib.getInstanceIdentifier(), groupId, neighborAddress, afiSafisAdvertized, afiSafisGracefulAdvertized,
                 afiSafisLlGracefulAdvertized);
-        this.name = peerName;
-        this.peerRole = role;
+        name = peerName;
+        peerRole = role;
         this.clusterId = clusterId;
         this.localAs = localAs;
         this.rib = rib;
@@ -135,7 +135,7 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
             return CommitInfo.emptyFluentFuture();
         }
         LOG.info("Closed per Peer {} removed", peerPath);
-        final DOMDataTreeWriteTransaction tx = this.domChain.newWriteOnlyTransaction();
+        final DOMDataTreeWriteTransaction tx = domChain.newWriteOnlyTransaction();
         tx.delete(LogicalDatastoreType.OPERATIONAL, peerPath);
         final FluentFuture<? extends CommitInfo> future = tx.commit();
         future.addCallback(new FutureCallback<CommitInfo>() {
@@ -158,12 +158,12 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
 
     @Override
     public final synchronized PeerId getPeerId() {
-        return this.peerId;
+        return peerId;
     }
 
     @Override
     public final PeerRole getRole() {
-        return this.peerRole;
+        return peerRole;
     }
 
     @Override
@@ -203,22 +203,22 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
 
     @Override
     public final String getName() {
-        return this.name;
+        return name;
     }
 
     @Override
     public final ClusterIdentifier getClusterId() {
-        return this.clusterId;
+        return clusterId;
     }
 
     @Override
     public final AsNumber getLocalAs() {
-        return this.localAs;
+        return localAs;
     }
 
     @Override
     public synchronized DOMTransactionChain getDomChain() {
-        return this.domChain;
+        return domChain;
     }
 
     /**
@@ -232,7 +232,7 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
     public final synchronized <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>>
             void initializeRibOut(final RouteEntryDependenciesContainer entryDep,
                     final List<ActualBestPathRoutes<C, S>> routesToStore) {
-        if (this.ribOutChain == null) {
+        if (ribOutChain == null) {
             LOG.debug("Session closed, skip changes to peer AdjRibsOut {}", getPeerId());
             return;
         }
@@ -241,7 +241,7 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
         final YangInstanceIdentifier tableRibout = getRibOutIId(ribSupport.tablesKey());
         final boolean addPathSupported = supportsAddPathSupported(ribSupport.getTablesKey());
 
-        final DOMDataTreeWriteTransaction tx = this.ribOutChain.newWriteOnlyTransaction();
+        final DOMDataTreeWriteTransaction tx = ribOutChain.newWriteOnlyTransaction();
         for (final ActualBestPathRoutes<C, S> initRoute : routesToStore) {
             if (!supportsLLGR() && initRoute.isDepreferenced()) {
                 // Stale Long-lived Graceful Restart routes should not be propagated
@@ -267,7 +267,7 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
         }
 
         final FluentFuture<? extends CommitInfo> future = tx.commit();
-        this.submitted = future;
+        submitted = future;
         future.addCallback(new FutureCallback<CommitInfo>() {
             @Override
             public void onSuccess(final CommitInfo result) {
@@ -285,17 +285,17 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
     public final synchronized <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>>
             void refreshRibOut(final RouteEntryDependenciesContainer entryDep,
                 final List<StaleBestPathRoute> staleRoutes, final List<AdvertizedRoute<C, S>> newRoutes) {
-        if (this.ribOutChain == null) {
+        if (ribOutChain == null) {
             LOG.debug("Session closed, skip changes to peer AdjRibsOut {}", getPeerId());
             return;
         }
-        final DOMDataTreeWriteTransaction tx = this.ribOutChain.newWriteOnlyTransaction();
+        final DOMDataTreeWriteTransaction tx = ribOutChain.newWriteOnlyTransaction();
         final RIBSupport<C, S> ribSupport = entryDep.getRIBSupport();
         deleteRouteRibOut(ribSupport, staleRoutes, tx);
         installRouteRibOut(entryDep, newRoutes, tx);
 
         final FluentFuture<? extends CommitInfo> future = tx.commit();
-        this.submitted = future;
+        submitted = future;
         future.addCallback(new FutureCallback<CommitInfo>() {
             @Override
             public void onSuccess(final CommitInfo result) {
@@ -313,7 +313,7 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
     public final synchronized <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>>
             void reEvaluateAdvertizement(final RouteEntryDependenciesContainer entryDep,
                 final List<ActualBestPathRoutes<C, S>> routesToStore) {
-        if (this.ribOutChain == null) {
+        if (ribOutChain == null) {
             LOG.debug("Session closed, skip changes to peer AdjRibsOut {}", getPeerId());
             return;
         }
@@ -322,7 +322,7 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
         final NodeIdentifierWithPredicates tk = ribSupport.tablesKey();
         final boolean addPathSupported = supportsAddPathSupported(ribSupport.getTablesKey());
 
-        final DOMDataTreeWriteTransaction tx = this.ribOutChain.newWriteOnlyTransaction();
+        final DOMDataTreeWriteTransaction tx = ribOutChain.newWriteOnlyTransaction();
         for (final ActualBestPathRoutes<C, S> actualBestRoute : routesToStore) {
             final PeerId fromPeerId = actualBestRoute.getFromPeerId();
             if (!filterRoutes(fromPeerId, ribSupport.getTablesKey())) {
@@ -347,7 +347,7 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
         }
 
         final FluentFuture<? extends CommitInfo> future = tx.commit();
-        this.submitted = future;
+        submitted = future;
         future.addCallback(new FutureCallback<CommitInfo>() {
             @Override
             public void onSuccess(final CommitInfo result) {
@@ -367,7 +367,7 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
         final Peer fromPeer = entryDep.getPeerTracker().getPeer(fromPeerId);
         final RIBSupport<?, ?> ribSupport = entryDep.getRIBSupport();
         final BGPRouteEntryExportParameters routeEntry = new BGPRouteEntryExportParametersImpl(fromPeer, this,
-            ribSupport.extractRouteKey(route.getIdentifier()), this.rtCache);
+            ribSupport.extractRouteKey(route.getIdentifier()), rtCache);
 
         final Attributes bindingAttrs = ribSupport.attributeFromContainerNode(attrs);
         final Optional<Attributes> optExportAttrs = entryDep.getRoutingPolicies().applyExportPolicies(routeEntry,
@@ -479,36 +479,37 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
         tx.delete(LogicalDatastoreType.OPERATIONAL, ribOutTarget);
     }
 
+    // FIXME: make this asynchronous?
     final synchronized void releaseRibOutChain(final boolean isWaitForSubmitted) {
         if (isWaitForSubmitted) {
-            if (this.submitted != null) {
+            if (submitted != null) {
                 try {
-                    this.submitted.get();
+                    submitted.get();
                 } catch (final InterruptedException | ExecutionException throwable) {
                     LOG.error("Write routes failed", throwable);
                 }
             }
         }
 
-        if (this.ribOutChain != null) {
+        if (ribOutChain != null) {
             LOG.info("Closing peer chain {}", getPeerId());
-            this.ribOutChain.close();
-            this.ribOutChain = null;
+            ribOutChain.close();
+            ribOutChain = null;
         }
     }
 
     final synchronized void createDomChain() {
-        if (this.domChain == null) {
+        if (domChain == null) {
             LOG.info("Creating DOM peer chain {}", getPeerId());
-            this.domChain = this.rib.createPeerDOMChain(this);
+            domChain = rib.createPeerDOMChain(this);
         }
     }
 
     final synchronized void closeDomChain() {
-        if (this.domChain != null) {
+        if (domChain != null) {
             LOG.info("Closing DOM peer chain {}", getPeerId());
-            this.domChain.close();
-            this.domChain = null;
+            domChain.close();
+            domChain = null;
         }
     }
 
index ea97fbe551bb9001799a2008560ce120576aea67..3cc0b02240506e8d61c6bda528ac5afa6651b4de 100644 (file)
@@ -26,6 +26,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 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;
@@ -36,7 +37,6 @@ import org.opendaylight.mdsal.dom.api.DOMDataTreeTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
-import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
 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;
@@ -77,7 +77,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 // This class is thread-safe
-public final class RIBImpl extends BGPRibStateImpl implements RIB, DOMTransactionChainListener, AutoCloseable {
+public final class RIBImpl extends BGPRibStateImpl implements RIB, DOMTransactionChainListener {
     private static final Logger LOG = LoggerFactory.getLogger(RIBImpl.class);
     private static final QName RIB_ID_QNAME = QName.create(Rib.QNAME, "id").intern();
 
@@ -100,8 +100,6 @@ public final class RIBImpl extends BGPRibStateImpl implements RIB, DOMTransactio
     private final BGPPeerTracker peerTracker = new BGPPeerTrackerImpl();
     private final BGPRibRoutingPolicy ribPolicies;
     @GuardedBy("this")
-    private ClusterSingletonServiceRegistration registration;
-    @GuardedBy("this")
     private DOMTransactionChain domChain;
     @GuardedBy("this")
     private boolean isServiceInstantiated;
@@ -123,43 +121,44 @@ public final class RIBImpl extends BGPRibStateImpl implements RIB, DOMTransactio
                 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.domService = this.domDataBroker.getExtensions().get(DOMDataTreeChangeService.class);
+        domService = domDataBroker.getExtensions().get(DOMDataTreeChangeService.class);
         this.extensions = requireNonNull(extensions);
         this.ribPolicies = requireNonNull(ribPolicies);
         this.codecsRegistry = codecsRegistry;
-        this.ribContextRegistry = RIBSupportContextRegistryImpl.create(extensions, this.codecsRegistry);
-        this.yangRibId = YangInstanceIdentifier.builder().node(BGPRIB_NID).node(RIB_NID)
+        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);
         this.ribId = ribId;
-
-        for (final BgpTableType t : this.localTables) {
-            final TablesKey key = new TablesKey(t.getAfi(), t.getSafi());
-            this.localTablesKeys.add(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 DOMDataTreeWriteTransaction tx = this.domChain.newWriteOnlyTransaction();
+        final DOMDataTreeWriteTransaction tx = domChain.newWriteOnlyTransaction();
 
-        final RIBSupport<? extends Routes, ?> ribSupport = this.ribContextRegistry.getRIBSupport(key);
+        final RIBSupport<? extends Routes, ?> ribSupport = ribContextRegistry.getRIBSupport(key);
         if (ribSupport != null) {
             final MapEntryNode emptyTable = ribSupport.emptyTable();
             final InstanceIdentifierBuilder tableId = YangInstanceIdentifier
-                    .builder(this.yangRibId.node(LOCRIB_NID).node(TABLES_NID)).node(emptyTable.getIdentifier());
+                    .builder(yangRibId.node(LOCRIB_NID).node(TABLES_NID)).node(emptyTable.getIdentifier());
 
             tx.put(LogicalDatastoreType.OPERATIONAL, tableId.build(), emptyTable);
             try {
                 tx.commit().get();
-            } catch (final InterruptedException | ExecutionException e1) {
-                LOG.error("Failed to initiate LocRIB for key {}", key, e1);
+            } catch (final InterruptedException | ExecutionException e) {
+                LOG.error("Failed to initiate LocRIB for key {}", key, e);
             }
         } else {
             LOG.warn("There's no registered RIB Context for {}", key.getAfi());
@@ -168,31 +167,31 @@ public final class RIBImpl extends BGPRibStateImpl implements RIB, DOMTransactio
 
     private synchronized <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>>
             void createLocRibWriter(final TablesKey key) {
-        final RIBSupport<C, S> ribSupport = this.ribContextRegistry.getRIBSupport(key);
+        final RIBSupport<C, S> ribSupport = ribContextRegistry.getRIBSupport(key);
         if (ribSupport == null) {
             return;
         }
         LOG.debug("Creating LocRIB writer for key {}", key);
         final DOMTransactionChain txChain = createPeerDOMChain(this);
-        PathSelectionMode pathSelectionStrategy = this.bestPathSelectionStrategies.get(key);
+        PathSelectionMode pathSelectionStrategy = bestPathSelectionStrategies.get(key);
         if (pathSelectionStrategy == null) {
             pathSelectionStrategy = BasePathSelectionModeFactory.createBestPathSelectionStrategy();
         }
 
         final LocRibWriter<C, S> locRibWriter = LocRibWriter.create(
                 ribSupport,
-                verifyNotNull(this.tableTypeRegistry.getAfiSafiType(key)),
+                verifyNotNull(tableTypeRegistry.getAfiSafiType(key)),
                 txChain,
                 yangRibId,
-                this.localAs,
+                localAs,
                 getService(),
-                this.ribPolicies,
-                this.peerTracker,
+                ribPolicies,
+                peerTracker,
                 pathSelectionStrategy);
-        this.vpnTableRefresher.put(key, locRibWriter);
+        vpnTableRefresher.put(key, locRibWriter);
         registerTotalPathCounter(key, locRibWriter);
         registerTotalPrefixesCounter(key, locRibWriter);
-        this.txChainToLocRibWriter.put(txChain, locRibWriter);
+        txChainToLocRibWriter.put(txChain, locRibWriter);
     }
 
     @Override
@@ -200,32 +199,24 @@ public final class RIBImpl extends BGPRibStateImpl implements RIB, DOMTransactio
         return MoreObjects.toStringHelper(this).add("bgpId", bgpIdentifier).add("localTables", localTables).toString();
     }
 
-    @Override
-    public synchronized void close() {
-        if (this.registration != null) {
-            this.registration.close();
-            this.registration = null;
-        }
-    }
-
     @Override
     public AsNumber getLocalAs() {
-        return this.localAs;
+        return localAs;
     }
 
     @Override
     public BgpId getBgpIdentifier() {
-        return this.bgpIdentifier;
+        return bgpIdentifier;
     }
 
     @Override
     public Set<? extends BgpTableType> getLocalTables() {
-        return this.localTables;
+        return localTables;
     }
 
     @Override
     public BGPDispatcher getDispatcher() {
-        return this.dispatcher;
+        return dispatcher;
     }
 
     @Override
@@ -233,12 +224,12 @@ public final class RIBImpl extends BGPRibStateImpl implements RIB, DOMTransactio
             final DOMDataTreeTransaction transaction, final Throwable cause) {
         LOG.error("Broken chain in RIB {} transaction {}",
             getInstanceIdentifier(), transaction != null ? transaction.getIdentifier() : null, cause);
-        final LocRibWriter<?, ?> locRibWriter = this.txChainToLocRibWriter.remove(chain);
+        final LocRibWriter<?, ?> locRibWriter = txChainToLocRibWriter.remove(chain);
         if (locRibWriter != null) {
             final DOMTransactionChain newChain = createPeerDOMChain(this);
             startLocRib(locRibWriter.getTableKey());
             locRibWriter.restart(newChain);
-            this.txChainToLocRibWriter.put(newChain, locRibWriter);
+            txChainToLocRibWriter.put(newChain, locRibWriter);
         }
     }
 
@@ -249,27 +240,27 @@ public final class RIBImpl extends BGPRibStateImpl implements RIB, DOMTransactio
 
     @Override
     public Set<TablesKey> getLocalTablesKeys() {
-        return this.localTablesKeys;
+        return localTablesKeys;
     }
 
     @Override
     public boolean supportsTable(final TablesKey tableKey) {
-        return this.localTablesKeys.contains(tableKey);
+        return localTablesKeys.contains(tableKey);
     }
 
     @Override
     public BGPRibRoutingPolicy getRibPolicies() {
-        return this.ribPolicies;
+        return ribPolicies;
     }
 
     @Override
     public BGPPeerTracker getPeerTracker() {
-        return this.peerTracker;
+        return peerTracker;
     }
 
     @Override
     public void refreshTable(final TablesKey tk, final PeerId peerId) {
-        final RibOutRefresh table = this.vpnTableRefresher.get(tk);
+        final RibOutRefresh table = vpnTableRefresher.get(tk);
         if (table != null) {
             table.refreshTable(tk, peerId);
         }
@@ -277,97 +268,97 @@ public final class RIBImpl extends BGPRibStateImpl implements RIB, DOMTransactio
 
     @Override
     public DOMDataTreeChangeService getService() {
-        return (DOMDataTreeChangeService) this.domService;
+        return (DOMDataTreeChangeService) domService;
     }
 
     @Override
     public YangInstanceIdentifier getYangRibId() {
-        return this.yangRibId;
+        return yangRibId;
     }
 
     @Override
     public DOMTransactionChain createPeerDOMChain(final DOMTransactionChainListener listener) {
-        return this.domDataBroker.createMergingTransactionChain(listener);
+        return domDataBroker.createMergingTransactionChain(listener);
     }
 
     @Override
     public RIBExtensionConsumerContext getRibExtensions() {
-        return this.extensions;
+        return extensions;
     }
 
     @Override
     public RIBSupportContextRegistry getRibSupportContext() {
-        return this.ribContextRegistry;
+        return ribContextRegistry;
     }
 
     @Override
     public CodecsRegistry getCodecsRegistry() {
-        return this.codecsRegistry;
+        return codecsRegistry;
     }
 
     public synchronized void instantiateServiceInstance() {
-        this.isServiceInstantiated = true;
+        isServiceInstantiated = true;
         setActive(true);
-        this.domChain = this.domDataBroker.createMergingTransactionChain(this);
-        LOG.debug("Instantiating RIB table {} at {}", this.ribId, this.yangRibId);
+        domChain = domDataBroker.createMergingTransactionChain(this);
+        LOG.debug("Instantiating RIB table {} at {}", ribId, yangRibId);
 
         final ContainerNode bgpRib = Builders.containerBuilder().withNodeIdentifier(BGPRIB_NID)
                 .addChild(ImmutableNodes.mapNodeBuilder(RIB_NID).build()).build();
 
         final MapEntryNode ribInstance = Builders.mapEntryBuilder().withNodeIdentifier(
-                NodeIdentifierWithPredicates.of(Rib.QNAME, RIB_ID_QNAME, this.ribId.getValue()))
-                .addChild(ImmutableNodes.leafNode(RIB_ID_QNAME, this.ribId.getValue()))
+                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 DOMDataTreeWriteTransaction 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.create(BGPRIB_NID), bgpRib);
-        trans.put(LogicalDatastoreType.OPERATIONAL, this.yangRibId, ribInstance);
+        trans.put(LogicalDatastoreType.OPERATIONAL, yangRibId, ribInstance);
 
         try {
             trans.commit().get();
         } catch (final InterruptedException | ExecutionException e) {
-            LOG.error("Failed to initiate RIB {}", this.yangRibId, e);
+            LOG.error("Failed to initiate RIB {}", yangRibId, e);
         }
 
         LOG.debug("Effective RIB created.");
 
-        this.localTablesKeys.forEach(this::startLocRib);
-        this.localTablesKeys.forEach(this::createLocRibWriter);
+        localTablesKeys.forEach(this::startLocRib);
+        localTablesKeys.forEach(this::createLocRibWriter);
     }
 
     public synchronized FluentFuture<? extends CommitInfo> closeServiceInstance() {
-        if (!this.isServiceInstantiated) {
-            LOG.trace("RIB {} already closed", this.ribId.getValue());
+        if (!isServiceInstantiated) {
+            LOG.trace("RIB {} already closed", ribId.getValue());
             return CommitInfo.emptyFluentFuture();
         }
-        LOG.info("Close RIB {}", 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 DOMDataTreeWriteTransaction t = this.domChain.newWriteOnlyTransaction();
+        final DOMDataTreeWriteTransaction t = domChain.newWriteOnlyTransaction();
         t.delete(LogicalDatastoreType.OPERATIONAL, getYangRibId());
         final FluentFuture<? extends CommitInfo> cleanFuture = t.commit();
         cleanFuture.addCallback(new FutureCallback<CommitInfo>() {
             @Override
             public void onSuccess(final CommitInfo result) {
-                LOG.info("RIB cleaned {}", RIBImpl.this.ribId.getValue());
+                LOG.info("RIB cleaned {}", ribId.getValue());
             }
 
             @Override
             public void onFailure(final Throwable throwable) {
                 LOG.error("Failed to clean RIB {}",
-                        RIBImpl.this.ribId.getValue(), throwable);
+                        ribId.getValue(), throwable);
             }
         }, MoreExecutors.directExecutor());
-        this.domChain.close();
+        domChain.close();
         return cleanFuture;
     }
 }
index b162d810fcda2186f56cc77b2482cce2b620b495..85209aa11957f93ed037115beac631c2b28e9be6 100644 (file)
@@ -7,15 +7,15 @@
  */
 package org.opendaylight.protocol.bgp.rib.impl.config;
 
+import static com.google.common.base.Preconditions.checkState;
 import static java.util.Objects.requireNonNull;
 import static org.opendaylight.protocol.bgp.rib.spi.RIBNodeIdentifiers.TABLES_NID;
 
-import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
-import com.google.common.util.concurrent.FluentFuture;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import java.util.Objects;
 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.DOMDataTreeChangeService;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
@@ -40,18 +40,20 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdent
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public final class AppPeer implements PeerBean, BGPPeerStateProvider {
+final class AppPeer extends PeerBean {
     private static final Logger LOG = LoggerFactory.getLogger(AppPeer.class);
     private static final NodeIdentifier APPRIB = NodeIdentifier.create(ApplicationRib.QNAME);
     private static final QName APP_ID_QNAME = QName.create(ApplicationRib.QNAME, "id").intern();
+
     private final BGPStateProviderRegistry stateProviderRegistry;
     @GuardedBy("this")
     private Neighbor currentConfiguration;
     @GuardedBy("this")
     private BgpAppPeerSingletonService bgpAppPeerSingletonService;
+    @GuardedBy("this")
     private Registration stateProviderRegistration;
 
-    public AppPeer(final BGPStateProviderRegistry stateProviderRegistry) {
+    AppPeer(final BGPStateProviderRegistry stateProviderRegistry) {
         this.stateProviderRegistry = requireNonNull(stateProviderRegistry);
     }
 
@@ -64,58 +66,62 @@ public final class AppPeer implements PeerBean, BGPPeerStateProvider {
     }
 
     @Override
-    public synchronized void start(final RIB rib, final Neighbor neighbor, final InstanceIdentifier<Bgp> bgpIid,
+    synchronized void start(final RIB rib, final Neighbor neighbor, final InstanceIdentifier<Bgp> bgpIid,
             final PeerGroupConfigLoader peerGroupLoader, final BGPTableTypeRegistryConsumer tableTypeRegistry) {
-        Preconditions.checkState(this.bgpAppPeerSingletonService == null,
-                "Previous peer instance was not closed.");
-        this.currentConfiguration = neighbor;
-        this.bgpAppPeerSingletonService = new BgpAppPeerSingletonService(rib, createAppRibId(neighbor),
+        checkState(bgpAppPeerSingletonService == null, "Previous peer instance was not closed.");
+        LOG.info("Starting AppPeer instance {}", neighbor.getNeighborAddress());
+        currentConfiguration = neighbor;
+        bgpAppPeerSingletonService = new BgpAppPeerSingletonService(rib, createAppRibId(neighbor),
             IetfInetUtil.INSTANCE.ipv4AddressNoZoneFor(neighbor.getNeighborAddress().getIpv4Address()),
             tableTypeRegistry);
-        this.stateProviderRegistration = this.stateProviderRegistry.register(this);
+        stateProviderRegistration = stateProviderRegistry.register(this);
     }
 
     @Override
-    public synchronized void restart(final RIB rib, final InstanceIdentifier<Bgp> bgpIid,
-            final PeerGroupConfigLoader peerGroupLoader, final BGPTableTypeRegistryConsumer tableTypeRegistry) {
-        Preconditions.checkState(this.currentConfiguration != null);
-        start(rib, this.currentConfiguration, bgpIid, peerGroupLoader, tableTypeRegistry);
-    }
+    synchronized ListenableFuture<?> stop() {
+        if (bgpAppPeerSingletonService == null) {
+            LOG.info("App Peer {} already closed, skipping", currentConfiguration.getNeighborAddress());
+            return Futures.immediateVoidFuture();
+        }
 
-    @Override
-    public synchronized void close() {
-        if (this.bgpAppPeerSingletonService != null) {
-            this.stateProviderRegistration.close();
-            this.stateProviderRegistration = null;
-            this.bgpAppPeerSingletonService = null;
+        LOG.info("Closing App Peer {}", currentConfiguration.getNeighborAddress());
+        if (stateProviderRegistration != null) {
+            stateProviderRegistration.close();
+            stateProviderRegistration = null;
         }
+
+        final var future = bgpAppPeerSingletonService.closeServiceInstance();
+        bgpAppPeerSingletonService = null;
+        return future;
     }
 
     @Override
-    public synchronized void instantiateServiceInstance() {
-        if (this.bgpAppPeerSingletonService != null) {
-            this.bgpAppPeerSingletonService.instantiateServiceInstance();
+    synchronized void instantiateServiceInstance() {
+        if (bgpAppPeerSingletonService != null) {
+            bgpAppPeerSingletonService.instantiateServiceInstance();
         }
     }
 
     @Override
-    public synchronized FluentFuture<? extends CommitInfo> closeServiceInstance() {
-        if (this.bgpAppPeerSingletonService != null) {
-            return this.bgpAppPeerSingletonService.closeServiceInstance();
-        }
-
-        return CommitInfo.emptyFluentFuture();
+    synchronized ListenableFuture<?> closeServiceInstance() {
+        return bgpAppPeerSingletonService != null ? bgpAppPeerSingletonService.closeServiceInstance()
+            : Futures.immediateVoidFuture();
     }
 
     @Override
-    public synchronized Boolean containsEqualConfiguration(final Neighbor neighbor) {
-        return Objects.equals(this.currentConfiguration.key(), neighbor.key())
+    synchronized boolean containsEqualConfiguration(final Neighbor neighbor) {
+        return Objects.equals(currentConfiguration.key(), neighbor.key())
                 && OpenConfigMappingUtil.isApplicationPeer(neighbor);
     }
 
+    @Override
+    synchronized Neighbor getCurrentConfiguration() {
+        return currentConfiguration;
+    }
+
     @Override
     public synchronized BGPPeerState getPeerState() {
-        return this.bgpAppPeerSingletonService.getPeerState();
+        return bgpAppPeerSingletonService.getPeerState();
     }
 
     private static final class BgpAppPeerSingletonService implements BGPPeerStateProvider {
@@ -127,33 +133,33 @@ public final class AppPeer implements PeerBean, BGPPeerStateProvider {
 
         BgpAppPeerSingletonService(final RIB rib, final ApplicationRibId appRibId,
                 final Ipv4AddressNoZone neighborAddress, final BGPTableTypeRegistryConsumer tableTypeRegistry) {
-            this.applicationPeer = new ApplicationPeer(tableTypeRegistry, appRibId, neighborAddress, rib);
+            applicationPeer = new ApplicationPeer(tableTypeRegistry, appRibId, neighborAddress, rib);
             this.appRibId = appRibId;
-            this.dataTreeChangeService = rib.getService();
+            dataTreeChangeService = rib.getService();
         }
 
-        public synchronized void instantiateServiceInstance() {
-            this.isServiceInstantiated = true;
+        synchronized void instantiateServiceInstance() {
+            isServiceInstantiated = true;
             final YangInstanceIdentifier yangIId = YangInstanceIdentifier.builder().node(APPRIB)
-                    .nodeWithKey(ApplicationRib.QNAME, APP_ID_QNAME, this.appRibId.getValue())
+                    .nodeWithKey(ApplicationRib.QNAME, APP_ID_QNAME, appRibId.getValue())
                     .node(TABLES_NID).node(TABLES_NID).build();
-            this.applicationPeer.instantiateServiceInstance(this.dataTreeChangeService,
+            applicationPeer.instantiateServiceInstance(dataTreeChangeService,
                     new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, yangIId));
         }
 
-        public synchronized FluentFuture<? extends CommitInfo> closeServiceInstance() {
-            if (!this.isServiceInstantiated) {
-                LOG.trace("Application peer already closed {}", this.appRibId.getValue());
-                return CommitInfo.emptyFluentFuture();
+        synchronized ListenableFuture<?> closeServiceInstance() {
+            if (!isServiceInstantiated) {
+                LOG.info("Application peer already closed {}", appRibId.getValue());
+                return Futures.immediateVoidFuture();
             }
-            LOG.info("Application peer instance closed {}", this.appRibId.getValue());
-            this.isServiceInstantiated = false;
-            return this.applicationPeer.close();
+            LOG.info("Application peer instance closed {}", appRibId.getValue());
+            isServiceInstantiated = false;
+            return applicationPeer.close();
         }
 
         @Override
         public BGPPeerState getPeerState() {
-            return this.applicationPeer.getPeerState();
+            return applicationPeer.getPeerState();
         }
     }
 }
index f21d776d334de375c36d65ab2b373a2307adc4a2..19a509ab409fd7f2db1b118ffa0fdfd847e6beec 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.protocol.bgp.rib.impl.config;
 
+import static java.util.Objects.requireNonNull;
 import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUtil.APPLICATION_PEER_GROUP_NAME;
 import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUtil.APPLICATION_PEER_GROUP_NAME_OPT;
 import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUtil.getNeighborInstanceIdentifier;
@@ -19,11 +20,12 @@ import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 import com.google.common.util.concurrent.SettableFuture;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
@@ -32,10 +34,10 @@ import org.checkerframework.checker.lock.qual.Holding;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.api.DataObjectModification;
 import org.opendaylight.mdsal.binding.api.RpcProviderService;
-import org.opendaylight.mdsal.common.api.CommitInfo;
 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
 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 org.opendaylight.protocol.bgp.openconfig.routing.policy.spi.BGPRibRoutingPolicyFactory;
 import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
@@ -43,31 +45,24 @@ import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
 import org.opendaylight.protocol.bgp.rib.impl.spi.CodecsRegistry;
 import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
 import org.opendaylight.protocol.bgp.rib.spi.state.BGPStateProviderRegistry;
-import org.opendaylight.protocol.bgp.rib.spi.util.ClusterSingletonServiceRegistrationHelper;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.Config;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.Neighbor;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.Bgp;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Global;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Neighbors;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.network.instance.protocol.NeighborPeerGroupConfig;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.Empty;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @VisibleForTesting
 public class BGPClusterSingletonService implements ClusterSingletonService, AutoCloseable {
-
     private static final Logger LOG = LoggerFactory.getLogger(BGPClusterSingletonService.class);
 
-    private static final long TIMEOUT_NS = TimeUnit.SECONDS.toNanos(5);
     private final InstanceIdentifier<Bgp> bgpIid;
-    @GuardedBy("this")
-    private final Map<InstanceIdentifier<Neighbor>, PeerBean> peers = new HashMap<>();
-    @GuardedBy("this")
-    private final Map<String, List<PeerBean>> peersGroups = new HashMap<>();
     private final BGPTableTypeRegistryConsumer tableTypeRegistry;
-    private final ServiceGroupIdentifier serviceGroupIdentifier;
+    private final @NonNull ServiceGroupIdentifier serviceGroupIdentifier;
     private final AtomicBoolean instantiated = new AtomicBoolean(false);
     private final PeerGroupConfigLoader peerGroupLoader;
     private final RpcProviderService rpcRegistry;
@@ -77,9 +72,15 @@ public class BGPClusterSingletonService implements ClusterSingletonService, Auto
     private final CodecsRegistry codecsRegistry;
     private final BGPStateProviderRegistry stateProviderRegistry;
     private final DOMDataBroker domDataBroker;
+
+    @GuardedBy("this")
+    private final Map<InstanceIdentifier<Neighbor>, PeerBean> peers = new HashMap<>();
+    @GuardedBy("this")
+    private final Map<String, List<PeerBean>> peersGroups = new HashMap<>();
     @GuardedBy("this")
     private RibImpl ribImpl;
-
+    @GuardedBy("this")
+    private ClusterSingletonServiceRegistration cssRegistration;
 
     BGPClusterSingletonService(
             final @NonNull PeerGroupConfigLoader peerGroupLoader,
@@ -103,43 +104,45 @@ public class BGPClusterSingletonService implements ClusterSingletonService, Auto
         this.stateProviderRegistry = stateProviderRegistry;
         this.domDataBroker = domDataBroker;
         this.bgpIid = bgpIid;
-        final String ribInstanceName = getRibInstanceName(bgpIid);
-        this.serviceGroupIdentifier = ServiceGroupIdentifier.create(ribInstanceName + "-service-group");
-        ClusterSingletonServiceRegistrationHelper
-                .registerSingletonService(provider, this);
-        LOG.info("BGPClusterSingletonService {} registered", this.serviceGroupIdentifier.getName());
+        serviceGroupIdentifier = ServiceGroupIdentifier.create(getRibInstanceName(bgpIid) + "-service-group");
+        cssRegistration = provider.registerClusterSingletonService(this);
+        LOG.info("BGPClusterSingletonService {} registered", serviceGroupIdentifier.getName());
+    }
+
+    @Override
+    public ServiceGroupIdentifier getIdentifier() {
+        return serviceGroupIdentifier;
     }
 
     @Override
     public synchronized void instantiateServiceInstance() {
-        if (this.ribImpl != null) {
-            this.ribImpl.instantiateServiceInstance();
-            this.peers.values().forEach(PeerBean::instantiateServiceInstance);
+        if (ribImpl != null) {
+            ribImpl.instantiateServiceInstance();
+            peers.values().forEach(PeerBean::instantiateServiceInstance);
         }
-        this.instantiated.set(true);
-        LOG.info("BGPClusterSingletonService {} instantiated", this.serviceGroupIdentifier.getName());
+        instantiated.set(true);
+        LOG.info("BGPClusterSingletonService {} instantiated", serviceGroupIdentifier.getName());
     }
 
     @Override
-    public synchronized ListenableFuture<? extends CommitInfo> closeServiceInstance() {
-        LOG.info("BGPClusterSingletonService {} close service instance", this.serviceGroupIdentifier.getName());
-        this.instantiated.set(false);
+    public synchronized ListenableFuture<?> closeServiceInstance() {
+        LOG.info("BGPClusterSingletonService {} close service instance", serviceGroupIdentifier.getName());
+        instantiated.set(false);
 
-        final List<ListenableFuture<? extends CommitInfo>> futurePeerCloseList = this.peers.values().stream()
+        final List<ListenableFuture<?>> futurePeerCloseList = peers.values().stream()
                 .map(PeerBean::closeServiceInstance).collect(Collectors.toList());
-        final SettableFuture<? extends CommitInfo> done = SettableFuture.create();
+        final SettableFuture<Empty> done = SettableFuture.create();
 
-        final ListenableFuture<List<CommitInfo>> futureResult = Futures.allAsList(futurePeerCloseList);
-        Futures.addCallback(futureResult, new FutureCallback<List<? extends CommitInfo>>() {
+        final ListenableFuture<List<Object>> futureResult = Futures.allAsList(futurePeerCloseList);
+        Futures.addCallback(futureResult, new FutureCallback<List<?>>() {
             @Override
-            public void onSuccess(final List<? extends CommitInfo> result) {
+            public void onSuccess(final List<?> result) {
                 synchronized (BGPClusterSingletonService.this) {
-                    if (BGPClusterSingletonService.this.ribImpl != null) {
-                        done.setFuture(Futures.transform(BGPClusterSingletonService.this.ribImpl.closeServiceInstance(),
-                            input -> null, MoreExecutors.directExecutor()));
+                    if (ribImpl != null) {
+                        done.setFuture(Futures.transform(ribImpl.closeServiceInstance(),
+                                input -> Empty.getInstance(), MoreExecutors.directExecutor()));
                     } else {
-                        done.setFuture(Futures.transform(CommitInfo.emptyFluentFuture(),
-                            input -> null, MoreExecutors.directExecutor()));
+                        done.set(Empty.getInstance());
                     }
                 }
             }
@@ -152,28 +155,23 @@ public class BGPClusterSingletonService implements ClusterSingletonService, Auto
         return done;
     }
 
-    @Override
-    public ServiceGroupIdentifier getIdentifier() {
-        return this.serviceGroupIdentifier;
-    }
-
     synchronized void onGlobalChanged(final DataObjectModification<Global> dataObjectModification) {
         switch (dataObjectModification.getModificationType()) {
             case DELETE:
-                LOG.debug("Removing RIB instance: {}", this.bgpIid);
-                if (this.ribImpl != null) {
-                    LOG.debug("RIB instance removed {}", this.ribImpl);
-                    closeAllBindedPeers();
-                    closeRibService();
-                    this.ribImpl = null;
+                LOG.debug("Removing RIB instance: {}", bgpIid);
+                if (ribImpl != null) {
+                    LOG.debug("RIB instance removed {}", ribImpl);
+                    closeBoundPeers();
+                    closeRibInstance();
+                    ribImpl = null;
                 }
                 break;
             case SUBTREE_MODIFIED:
             case WRITE:
                 final Global global = dataObjectModification.getDataAfter();
-                if (this.ribImpl == null) {
+                if (ribImpl == null) {
                     onGlobalCreated(global);
-                } else if (!this.ribImpl.isGlobalEqual(global)) {
+                } else if (!ribImpl.isGlobalEqual(requireNonNull(global))) {
                     onGlobalUpdated(global);
                 }
                 break;
@@ -182,77 +180,77 @@ public class BGPClusterSingletonService implements ClusterSingletonService, Auto
         }
     }
 
-    private synchronized void onGlobalCreated(final Global global) {
+    @Holding("this")
+    private void onGlobalCreated(final Global global) {
         LOG.debug("Creating RIB instance with configuration: {}", global);
-        this.ribImpl = new RibImpl(this.ribExtensionContext, this.bgpDispatcher, this.routingPolicyFactory,
-                this.codecsRegistry, this.stateProviderRegistry, this.domDataBroker);
+        ribImpl = new RibImpl(ribExtensionContext, bgpDispatcher, routingPolicyFactory, codecsRegistry,
+            stateProviderRegistry, domDataBroker);
         initiateRibInstance(global);
-        LOG.debug("RIB instance created: {}", this.ribImpl);
+        LOG.debug("RIB instance created: {}", ribImpl);
     }
 
-    private synchronized void onGlobalUpdated(final Global global) {
-        LOG.debug("Modifying RIB instance with configuration: {}", global);
-        final List<PeerBean> closedPeers = closeAllBindedPeers();
-        closeRibService();
+    @Holding("this")
+    private void onGlobalUpdated(final Global global) {
+        LOG.info("Global config {} updated, new configuration {}", global.getConfig().getRouterId(), global);
+        closeRibInstance();
         initiateRibInstance(global);
-        for (final PeerBean peer : closedPeers) {
-            peer.restart(this.ribImpl, this.bgpIid, this.peerGroupLoader, this.tableTypeRegistry);
-        }
-        if (this.instantiated.get()) {
-            closedPeers.forEach(PeerBean::instantiateServiceInstance);
-        }
-        LOG.debug("RIB instance created: {}", this.ribImpl);
+        restartPeers(peers.values());
     }
 
-    @Holding("this")
     @VisibleForTesting
-    @SuppressWarnings("checkstyle:illegalCatch")
-    void closeRibService() {
+    @Holding("this")
+    void closeRibInstance() {
         try {
-            this.ribImpl.closeServiceInstance().get(TIMEOUT_NS, TimeUnit.NANOSECONDS);
-        } catch (final Exception e) {
-            LOG.error("RIB instance failed to close service instance", e);
+            ribImpl.stop().get();
+        } catch (InterruptedException e) {
+            LOG.error("Interrupted while waiting for RIB instance {} to close", ribImpl.getBgpIdentifier(), e);
+        } catch (ExecutionException e) {
+            LOG.error("RIB instance {} failed to close", ribImpl.getBgpIdentifier(), e);
         }
-        this.ribImpl.close();
     }
 
-    @Holding("this")
     @VisibleForTesting
+    @Holding("this")
     void initiateRibInstance(final Global global) {
-        final String ribInstanceName = getRibInstanceName(this.bgpIid);
-        ribImpl.start(global, ribInstanceName, this.tableTypeRegistry);
-        if (this.instantiated.get()) {
-            this.ribImpl.instantiateServiceInstance();
+        final String ribInstanceName = getRibInstanceName(bgpIid);
+        ribImpl.start(global, ribInstanceName, tableTypeRegistry);
+        if (instantiated.get()) {
+            ribImpl.instantiateServiceInstance();
         }
     }
 
-    @SuppressWarnings("checkstyle:illegalCatch")
-    private synchronized List<PeerBean> closeAllBindedPeers() {
-        final List<PeerBean> filtered = new ArrayList<>();
-        this.peers.forEach((key, peer) -> {
-            try {
-                peer.closeServiceInstance().get();
-            } catch (final Exception e) {
-                LOG.error("Peer instance failed to close service instance", e);
+    @Holding("this")
+    private List<PeerBean> closeBoundPeers() {
+        final List<PeerBean> filtered = new ArrayList<>(peers.size());
+        peers.forEach((key, peer) -> {
+            if (closePeer(peer)) {
+                filtered.add(peer);
             }
-            peer.close();
-            filtered.add(peer);
         });
         return filtered;
     }
 
     @Override
     public synchronized void close() {
-        LOG.info("BGPClusterSingletonService {} close", this.serviceGroupIdentifier.getName());
-        this.peers.values().iterator().forEachRemaining(PeerBean::close);
-        this.ribImpl.close();
-        this.peers.clear();
-        this.ribImpl = null;
+        if (cssRegistration == null) {
+            // Idempotent as per AutoCloseable contract
+            return;
+        }
+
+        LOG.info("Closing BGPClusterSingletonService {}", serviceGroupIdentifier.getName());
+        cssRegistration.close();
+        cssRegistration = null;
+
+        closeBoundPeers();
+        peers.clear();
+        closeRibInstance();
+        ribImpl = null;
     }
 
-    synchronized void onNeighborsChanged(final DataObjectModification<Neighbors> dataObjectModification) {
-        for (final DataObjectModification<? extends DataObject> neighborModification :
-                dataObjectModification.getModifiedChildren()) {
+    @VisibleForTesting
+    @Holding("this")
+    void onNeighborsChanged(final DataObjectModification<Neighbors> dataObjectModification) {
+        for (final DataObjectModification<?> neighborModification : dataObjectModification.getModifiedChildren()) {
             switch (neighborModification.getModificationType()) {
                 case DELETE:
                     onNeighborRemoved((Neighbor) neighborModification.getDataBefore());
@@ -267,9 +265,10 @@ public class BGPClusterSingletonService implements ClusterSingletonService, Auto
         }
     }
 
-    private synchronized void onNeighborModified(final Neighbor neighbor) {
+    @Holding("this")
+    private void onNeighborModified(final Neighbor neighbor) {
         //restart peer instance with a new configuration
-        final PeerBean bgpPeer = this.peers.get(getNeighborInstanceIdentifier(this.bgpIid, neighbor.key()));
+        final PeerBean bgpPeer = peers.get(getNeighborInstanceIdentifier(bgpIid, neighbor.key()));
         if (bgpPeer == null) {
             onNeighborCreated(neighbor);
         } else if (!bgpPeer.containsEqualConfiguration(neighbor)) {
@@ -278,22 +277,31 @@ public class BGPClusterSingletonService implements ClusterSingletonService, Auto
     }
 
     @VisibleForTesting
-    synchronized void onNeighborCreated(final Neighbor neighbor) {
-        LOG.debug("Creating Peer instance with configuration: {}", neighbor);
+    @Holding("this")
+    void onNeighborCreated(final Neighbor neighbor) {
+        LOG.info("Creating Peer instance {} with configuration: {}", neighbor.getNeighborAddress(), neighbor);
         final PeerBean bgpPeer;
         if (OpenConfigMappingUtil.isApplicationPeer(neighbor)) {
-            bgpPeer = new AppPeer(this.stateProviderRegistry);
+            bgpPeer = new AppPeer(stateProviderRegistry);
         } else {
-            bgpPeer = new BgpPeer(this.rpcRegistry, this.stateProviderRegistry);
+            bgpPeer = new BgpPeer(rpcRegistry, stateProviderRegistry);
         }
         final InstanceIdentifier<Neighbor> neighborInstanceIdentifier =
-                getNeighborInstanceIdentifier(this.bgpIid, neighbor.key());
+                getNeighborInstanceIdentifier(bgpIid, neighbor.key());
         initiatePeerInstance(neighbor, bgpPeer);
-        this.peers.put(neighborInstanceIdentifier, bgpPeer);
+        peers.put(neighborInstanceIdentifier, bgpPeer);
 
         final Optional<String> peerGroupName = getPeerGroupName(neighbor.getConfig());
-        peerGroupName.ifPresent(s -> this.peersGroups.computeIfAbsent(s, k -> new ArrayList<>()).add(bgpPeer));
-        LOG.debug("Peer instance created {}", neighbor.key().getNeighborAddress());
+        peerGroupName.ifPresent(s -> peersGroups.computeIfAbsent(s, k -> new ArrayList<>()).add(bgpPeer));
+        LOG.info("Peer instance created {}", neighbor.getNeighborAddress());
+    }
+
+    @VisibleForTesting
+    @Holding("this")
+    void onNeighborUpdated(final PeerBean bgpPeer, final Neighbor neighbor) {
+        LOG.info("Updating Peer {} with new configuration: {}", neighbor.getNeighborAddress(), neighbor);
+        closePeer(bgpPeer);
+        initiatePeerInstance(neighbor, bgpPeer);
     }
 
     private static Optional<String> getPeerGroupName(final Config config) {
@@ -311,34 +319,33 @@ public class BGPClusterSingletonService implements ClusterSingletonService, Auto
         return Optional.of(StringUtils.substringBetween(peerGroupName, "=\"", "\""));
     }
 
-    @VisibleForTesting
-    synchronized void onNeighborUpdated(final PeerBean bgpPeer, final Neighbor neighbor) {
-        LOG.info("Updating Peer instance with configuration: {}", neighbor);
-        closePeer(bgpPeer);
-        initiatePeerInstance(neighbor, bgpPeer);
-        LOG.info("Peer instance updated {}", bgpPeer);
-    }
+    private static boolean closePeer(final PeerBean bgpPeer) {
+        if (bgpPeer == null) {
+            return false;
+        }
 
-    @SuppressWarnings("checkstyle:illegalCatch")
-    private static void closePeer(final PeerBean bgpPeer) {
-        if (bgpPeer != null) {
-            try {
-                bgpPeer.closeServiceInstance().get();
-                bgpPeer.close();
-                LOG.info("Peer instance closed {}", bgpPeer);
-            } catch (final Exception e) {
-                LOG.error("Peer instance failed to close service instance", e);
-            }
+        try {
+            bgpPeer.stop().get();
+        } catch (InterruptedException e) {
+            LOG.error("Interrupted while waiting for peer instance failed to close service", e);
+            return false;
+        } catch (ExecutionException e) {
+            LOG.error("Peer instance failed to close service instance", e);
+            return false;
         }
+
+        LOG.info("Peer instance {} closed", bgpPeer.getCurrentConfiguration().getNeighborAddress());
+        return true;
     }
 
     @VisibleForTesting
-    public synchronized void onNeighborRemoved(final Neighbor neighbor) {
-        LOG.debug("Removing Peer instance: {}", neighbor);
-        final PeerBean bgpPeer = this.peers.remove(getNeighborInstanceIdentifier(this.bgpIid, neighbor.key()));
+    @Holding("this")
+    public void onNeighborRemoved(final Neighbor neighbor) {
+        LOG.info("Removing Peer instance: {}", neighbor.getNeighborAddress());
+        final PeerBean bgpPeer = peers.remove(getNeighborInstanceIdentifier(bgpIid, neighbor.key()));
 
         final Optional<String> groupName = getPeerGroupName(neighbor.getConfig());
-        groupName.ifPresent(s -> this.peersGroups.computeIfPresent(s, (k, groupPeers) -> {
+        groupName.ifPresent(s -> peersGroups.computeIfPresent(s, (k, groupPeers) -> {
             groupPeers.remove(bgpPeer);
             return groupPeers.isEmpty() ? null : groupPeers;
         }));
@@ -346,29 +353,28 @@ public class BGPClusterSingletonService implements ClusterSingletonService, Auto
     }
 
     @VisibleForTesting
+    @Holding("this")
+    // FIXME: synchronized because SpotBugs does not understand @Holding with @VisibleForTesting (which we need for
+    //        Mockito.verify())
     synchronized void initiatePeerInstance(final Neighbor neighbor, final PeerBean bgpPeer) {
-        if (this.ribImpl != null) {
-            bgpPeer.start(this.ribImpl, neighbor, this.bgpIid, this.peerGroupLoader, this.tableTypeRegistry);
+        if (ribImpl != null) {
+            bgpPeer.start(ribImpl, neighbor, bgpIid, peerGroupLoader, tableTypeRegistry);
         }
-        if (this.instantiated.get()) {
+        if (instantiated.get()) {
             bgpPeer.instantiateServiceInstance();
         }
     }
 
-    @SuppressWarnings("checkstyle:illegalCatch")
-    synchronized void restartNeighbors(final String peerGroupName) {
-        final List<PeerBean> peerGroup = this.peersGroups.get(peerGroupName);
-        if (peerGroup == null) {
-            return;
-        }
-        for (final PeerBean peer : peerGroup) {
-            try {
-                peer.closeServiceInstance().get();
-            } catch (final Exception e) {
-                LOG.error("Peer instance failed to close service instance", e);
-            }
-            peer.restart(this.ribImpl, this.bgpIid, this.peerGroupLoader, this.tableTypeRegistry);
-            peer.instantiateServiceInstance();
+    @Holding("this")
+    private void restartPeers(final Collection<PeerBean> toRestart) {
+        toRestart.stream().filter(BGPClusterSingletonService::closePeer)
+            .forEach(peer -> initiatePeerInstance(peer.getCurrentConfiguration(), peer));
+    }
+
+    synchronized void restartPeerGroup(final String peerGroupName) {
+        final var toRestart = peersGroups.get(peerGroupName);
+        if (toRestart != null) {
+            restartPeers(toRestart);
         }
     }
 }
index 10c4766a6c9de5573da369021d8d215cbc3c011e..38e4b14b98848ee9028ce0254e838b76a3bfd396 100644 (file)
@@ -7,11 +7,12 @@
  */
 package org.opendaylight.protocol.bgp.rib.impl.config;
 
+import static com.google.common.base.Preconditions.checkState;
 import static java.util.Objects.requireNonNull;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.Iterables;
-import com.google.common.util.concurrent.FluentFuture;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import io.netty.util.concurrent.Future;
 import java.net.InetSocketAddress;
@@ -27,7 +28,6 @@ import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
 import org.checkerframework.checker.lock.qual.GuardedBy;
 import org.opendaylight.mdsal.binding.api.RpcProviderService;
-import org.opendaylight.mdsal.common.api.CommitInfo;
 import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
 import org.opendaylight.protocol.bgp.parser.BgpExtendedMessageUtil;
 import org.opendaylight.protocol.bgp.parser.spi.MultiprotocolCapabilitiesUtil;
@@ -71,16 +71,17 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class BgpPeer implements PeerBean, BGPPeerStateProvider {
-
+public class BgpPeer extends PeerBean {
     private static final Logger LOG = LoggerFactory.getLogger(BgpPeer.class);
 
     private final RpcProviderService rpcRegistry;
     private final BGPStateProviderRegistry stateProviderRegistry;
+
     @GuardedBy("this")
     private Neighbor currentConfiguration;
     @GuardedBy("this")
     private BgpPeerSingletonService bgpPeerSingletonService;
+    @GuardedBy("this")
     private Registration stateProviderRegistration;
 
     public BgpPeer(final RpcProviderService rpcRegistry, final BGPStateProviderRegistry stateProviderRegistry) {
@@ -135,11 +136,10 @@ public class BgpPeer implements PeerBean, BGPPeerStateProvider {
     }
 
     @Override
-    public synchronized void start(final RIB rib, final Neighbor neighbor, final InstanceIdentifier<Bgp> bgpIid,
+    synchronized void start(final RIB rib, final Neighbor neighbor, final InstanceIdentifier<Bgp> bgpIid,
             final PeerGroupConfigLoader peerGroupLoader, final BGPTableTypeRegistryConsumer tableTypeRegistry) {
-        Preconditions.checkState(bgpPeerSingletonService == null,
-                "Previous peer instance was not closed.");
-
+        checkState(bgpPeerSingletonService == null, "Previous peer instance was not closed.");
+        LOG.info("Starting BgPeer instance {}", neighbor.getNeighborAddress());
         bgpPeerSingletonService = new BgpPeerSingletonService(rib, neighbor, bgpIid, peerGroupLoader,
                 tableTypeRegistry);
         currentConfiguration = neighbor;
@@ -147,45 +147,37 @@ public class BgpPeer implements PeerBean, BGPPeerStateProvider {
     }
 
     @Override
-    public synchronized void restart(final RIB rib, final InstanceIdentifier<Bgp> bgpIid,
-            final PeerGroupConfigLoader peerGroupLoader, final BGPTableTypeRegistryConsumer tableTypeRegistry) {
-        Preconditions.checkState(currentConfiguration != null);
-        if (bgpPeerSingletonService != null) {
-            bgpPeerSingletonService.closeServiceInstance();
-            bgpPeerSingletonService = null;
-        }
-        start(rib, currentConfiguration, bgpIid, peerGroupLoader, tableTypeRegistry);
-    }
-
-    @Override
-    public synchronized void close() {
-        if (bgpPeerSingletonService != null) {
-            bgpPeerSingletonService.closeServiceInstance();
-            bgpPeerSingletonService = null;
+    synchronized ListenableFuture<?> stop() {
+        if (bgpPeerSingletonService == null) {
+            LOG.info("BGP Peer {} already closed, skipping", currentConfiguration.getNeighborAddress());
+            return Futures.immediateVoidFuture();
         }
+        LOG.info("Closing BGP Peer {}", currentConfiguration.getNeighborAddress());
         if (stateProviderRegistration != null) {
             stateProviderRegistration.close();
             stateProviderRegistration = null;
         }
+
+        final var future = bgpPeerSingletonService.closeServiceInstance();
+        bgpPeerSingletonService = null;
+        return future;
     }
 
     @Override
-    public synchronized void instantiateServiceInstance() {
+    synchronized void instantiateServiceInstance() {
         if (bgpPeerSingletonService != null) {
             bgpPeerSingletonService.instantiateServiceInstance();
         }
     }
 
     @Override
-    public synchronized FluentFuture<? extends CommitInfo> closeServiceInstance() {
-        if (bgpPeerSingletonService != null) {
-            return bgpPeerSingletonService.closeServiceInstance();
-        }
-        return CommitInfo.emptyFluentFuture();
+    synchronized ListenableFuture<?> closeServiceInstance() {
+        return bgpPeerSingletonService != null ? bgpPeerSingletonService.closeServiceInstance()
+            : Futures.immediateVoidFuture();
     }
 
     @Override
-    public synchronized Boolean containsEqualConfiguration(final Neighbor neighbor) {
+    synchronized boolean containsEqualConfiguration(final Neighbor neighbor) {
         if (currentConfiguration == null) {
             return false;
         }
@@ -211,6 +203,11 @@ public class BgpPeer implements PeerBean, BGPPeerStateProvider {
                 && Objects.equals(currentConfiguration.getTransport(), neighbor.getTransport());
     }
 
+    @Override
+    synchronized Neighbor getCurrentConfiguration() {
+        return currentConfiguration;
+    }
+
     @Override
     public synchronized BGPPeerState getPeerState() {
         if (bgpPeerSingletonService == null) {
@@ -310,6 +307,8 @@ public class BgpPeer implements PeerBean, BGPPeerStateProvider {
                 localAddress = null;
             }
             keys = keyMapping;
+            LOG.info("New BGP Peer {}:{} AS {} instance for BGP id {} created with activeConnection: {}",
+                    inetAddress, localAddress, neighborRemoteAs, prefs.getBgpId(), activeConnection);
         }
 
         private List<BgpParameters> getInitialBgpParameters(final Set<TablesKey> gracefulTables,
@@ -336,10 +335,10 @@ public class BgpPeer implements PeerBean, BGPPeerStateProvider {
             }
         }
 
-        synchronized FluentFuture<? extends CommitInfo> closeServiceInstance() {
+        synchronized ListenableFuture<?> closeServiceInstance() {
             if (!isServiceInstantiated) {
                 LOG.info("Peer {} already closed", neighborAddress);
-                return CommitInfo.emptyFluentFuture();
+                return Futures.immediateVoidFuture();
             }
             LOG.info("Close Peer {}", neighborAddress);
             isServiceInstantiated = false;
@@ -347,7 +346,7 @@ public class BgpPeer implements PeerBean, BGPPeerStateProvider {
                 connection.cancel(true);
                 connection = null;
             }
-            final FluentFuture<? extends CommitInfo> future = bgpPeer.close();
+            final var future = bgpPeer.close();
             removePeer(dispatcher.getBGPPeerRegistry());
             return future;
         }
index a7feb2fb5a673db96889133dd04c6a0810a6c885..01c51ecd2ad1bb60be5466398db1c27305442aff 100644 (file)
@@ -242,7 +242,7 @@ public class DefaultBgpDeployer implements ClusteredDataTreeChangeListener<Bgp>,
             return;
         }
         for (final PeerGroup peerGroup : extPeerGroups.nonnullPeerGroup().values()) {
-            bgpCss.values().forEach(css -> css.restartNeighbors(peerGroup.getPeerGroupName()));
+            bgpCss.values().forEach(css -> css.restartPeerGroup(peerGroup.getPeerGroupName()));
         }
     }
 
index d3bf90d9ea35f23420da01b2e9a89ea148ca6647..b80752bf2a2ba25c0fc75b6319bb08d01fb67ce6 100644 (file)
@@ -5,13 +5,12 @@
  * 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.protocol.bgp.rib.impl.config;
 
-import com.google.common.util.concurrent.FluentFuture;
-import org.opendaylight.mdsal.common.api.CommitInfo;
+import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
+import org.opendaylight.protocol.bgp.rib.spi.state.BGPPeerStateProvider;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.Neighbor;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.Bgp;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -19,20 +18,18 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 /**
  * Common interface for BgpPeer and AppPeer beans.
  */
-public interface PeerBean extends AutoCloseable {
+abstract class PeerBean implements BGPPeerStateProvider {
 
-    void start(RIB rib, Neighbor neighbor, InstanceIdentifier<Bgp> bgpIid, PeerGroupConfigLoader peerGroupLoader,
-            BGPTableTypeRegistryConsumer tableTypeRegistry);
+    abstract void start(RIB rib, Neighbor neighbor, InstanceIdentifier<Bgp> bgpIid,
+        PeerGroupConfigLoader peerGroupLoader, BGPTableTypeRegistryConsumer tableTypeRegistry);
 
-    void restart(RIB rib, InstanceIdentifier<Bgp> bgpIid, PeerGroupConfigLoader peerGroupLoader,
-            BGPTableTypeRegistryConsumer tableTypeRegistry);
+    abstract ListenableFuture<?> stop();
 
-    @Override
-    void close();
+    abstract void instantiateServiceInstance();
 
-    void instantiateServiceInstance();
+    abstract ListenableFuture<?> closeServiceInstance();
 
-    FluentFuture<? extends CommitInfo> closeServiceInstance();
+    abstract boolean containsEqualConfiguration(Neighbor neighbor);
 
-    Boolean containsEqualConfiguration(Neighbor neighbor);
+    abstract Neighbor getCurrentConfiguration();
 }
index 8b1bc897639bdd8a6a317163bd34b5457095fdae..ac09a0db9d3f218f9a184751c00a972783ef33d8 100644 (file)
@@ -7,17 +7,20 @@
  */
 package org.opendaylight.protocol.bgp.rib.impl.config;
 
+import static com.google.common.base.Preconditions.checkState;
 import static java.util.Objects.requireNonNull;
 import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUtil.getAfiSafiWithDefault;
 import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUtil.getGlobalClusterIdentifier;
 import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUtil.toTableTypes;
 
-import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.FluentFuture;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import java.util.Collection;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
+import org.checkerframework.checker.lock.qual.GuardedBy;
 import org.opendaylight.mdsal.common.api.CommitInfo;
 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeService;
@@ -58,31 +61,39 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public final class RibImpl implements RIB, BGPRibStateProvider, AutoCloseable {
+public final class RibImpl implements RIB, BGPRibStateProvider {
 
     private static final Logger LOG = LoggerFactory.getLogger(RibImpl.class);
 
-    private final RIBExtensionConsumerContext extensions;
+    private final RIBExtensionConsumerContext extensionProvider;
     private final BGPDispatcher dispatcher;
     private final CodecsRegistry codecsRegistry;
     private final DOMDataBroker domBroker;
     private final BGPRibRoutingPolicyFactory policyProvider;
     private final BGPStateProviderRegistry stateProviderRegistry;
+    @GuardedBy("this")
     private RIBImpl ribImpl;
+    @GuardedBy("this")
+    private Registration stateProviderRegistration;
+    @GuardedBy("this")
     private Collection<AfiSafi> afiSafi;
+    @GuardedBy("this")
     private AsNumber asNumber;
+    @GuardedBy("this")
     private Ipv4AddressNoZone routerId;
+    @GuardedBy("this")
     private ClusterIdentifier clusterId;
-    private Registration stateProviderRegistration;
+    @GuardedBy("this")
+    private RibId ribId;
 
     public RibImpl(
-            final RIBExtensionConsumerContext contextProvider,
+            final RIBExtensionConsumerContext extensionProvider,
             final BGPDispatcher dispatcher,
             final BGPRibRoutingPolicyFactory policyProvider,
             final CodecsRegistry codecsRegistry,
             final BGPStateProviderRegistry stateProviderRegistry,
             final DOMDataBroker domBroker) {
-        this.extensions = requireNonNull(contextProvider);
+        this.extensionProvider = requireNonNull(extensionProvider);
         this.dispatcher = requireNonNull(dispatcher);
         this.codecsRegistry = requireNonNull(codecsRegistry);
         this.domBroker = requireNonNull(domBroker);
@@ -90,168 +101,176 @@ public final class RibImpl implements RIB, BGPRibStateProvider, AutoCloseable {
         this.stateProviderRegistry = requireNonNull(stateProviderRegistry);
     }
 
-    void start(final Global global, final String instanceName, final BGPTableTypeRegistryConsumer tableTypeRegistry) {
-        Preconditions.checkState(this.ribImpl == null,
-                "Previous instance %s was not closed.", this);
-        this.ribImpl = createRib(global, instanceName, tableTypeRegistry);
-        this.stateProviderRegistration =  this.stateProviderRegistry.register(this);
+    synchronized void start(final Global global, final String instanceName,
+            final BGPTableTypeRegistryConsumer tableTypeRegistry) {
+        checkState(ribImpl == null, "Previous instance %s was not closed.", this);
+        LOG.info("Starting BGP instance {}", instanceName);
+        ribId = new RibId(instanceName);
+        ribImpl = createRib(global, tableTypeRegistry);
+        stateProviderRegistration =  stateProviderRegistry.register(this);
+    }
+
+    synchronized ListenableFuture<?> stop() {
+        if (ribImpl == null) {
+            LOG.info("RIB instance {} already closed, skipping", ribId);
+            return Futures.immediateVoidFuture();
+        }
+
+        LOG.info("Closing RIB instance {}", ribId);
+        if (stateProviderRegistration != null) {
+            LOG.info("Unregistering state provider for RIB instance {}", ribId);
+            stateProviderRegistration.close();
+            stateProviderRegistration = null;
+        }
+
+        final var future = ribImpl.closeServiceInstance();
+        ribImpl = null;
+        return future;
     }
 
-    Boolean isGlobalEqual(final Global global) {
+    synchronized boolean isGlobalEqual(final Global global) {
         final Collection<AfiSafi> globalAfiSafi = getAfiSafiWithDefault(global.getAfiSafis(), true).values();
         final Config globalConfig = global.getConfig();
         final AsNumber globalAs = globalConfig.getAs();
         final Ipv4Address globalRouterId = global.getConfig().getRouterId();
         final ClusterIdentifier globalClusterId = getGlobalClusterIdentifier(globalConfig);
-        return this.afiSafi.containsAll(globalAfiSafi) && globalAfiSafi.containsAll(this.afiSafi)
-                && globalAs.equals(this.asNumber)
-                && globalRouterId.getValue().equals(this.routerId.getValue())
-                && globalClusterId.getValue().equals(this.clusterId.getValue());
+        return afiSafi.containsAll(globalAfiSafi) && globalAfiSafi.containsAll(afiSafi)
+                && globalAs.equals(asNumber)
+                && globalRouterId.getValue().equals(routerId.getValue())
+                && globalClusterId.getValue().equals(clusterId.getValue());
     }
 
     @Override
-    public KeyedInstanceIdentifier<Rib, RibKey> getInstanceIdentifier() {
-        return this.ribImpl.getInstanceIdentifier();
+    public synchronized KeyedInstanceIdentifier<Rib, RibKey> getInstanceIdentifier() {
+        return ribImpl.getInstanceIdentifier();
     }
 
     @Override
-    public AsNumber getLocalAs() {
-        return this.ribImpl.getLocalAs();
+    public synchronized AsNumber getLocalAs() {
+        return ribImpl.getLocalAs();
     }
 
     @Override
-    public BgpId getBgpIdentifier() {
-        return this.ribImpl.getBgpIdentifier();
+    public synchronized BgpId getBgpIdentifier() {
+        return ribImpl.getBgpIdentifier();
     }
 
     @Override
-    public Set<? extends BgpTableType> getLocalTables() {
-        return this.ribImpl.getLocalTables();
+    public synchronized Set<? extends BgpTableType> getLocalTables() {
+        return ribImpl.getLocalTables();
     }
 
     @Override
-    public BGPDispatcher getDispatcher() {
-        return this.ribImpl.getDispatcher();
+    public synchronized BGPDispatcher getDispatcher() {
+        return ribImpl.getDispatcher();
     }
 
     @Override
-    public DOMTransactionChain createPeerDOMChain(final DOMTransactionChainListener listener) {
-        return this.ribImpl.createPeerDOMChain(listener);
+    public synchronized DOMTransactionChain createPeerDOMChain(final DOMTransactionChainListener listener) {
+        return ribImpl.createPeerDOMChain(listener);
     }
 
     @Override
-    public RIBExtensionConsumerContext getRibExtensions() {
-        return this.ribImpl.getRibExtensions();
+    public synchronized RIBExtensionConsumerContext getRibExtensions() {
+        return ribImpl.getRibExtensions();
     }
 
     @Override
-    public RIBSupportContextRegistry getRibSupportContext() {
-        return this.ribImpl.getRibSupportContext();
+    public synchronized RIBSupportContextRegistry getRibSupportContext() {
+        return ribImpl.getRibSupportContext();
     }
 
     @Override
-    public YangInstanceIdentifier getYangRibId() {
-        return this.ribImpl.getYangRibId();
+    public synchronized YangInstanceIdentifier getYangRibId() {
+        return ribImpl.getYangRibId();
     }
 
     @Override
-    public CodecsRegistry getCodecsRegistry() {
-        return this.ribImpl.getCodecsRegistry();
+    public synchronized CodecsRegistry getCodecsRegistry() {
+        return ribImpl.getCodecsRegistry();
     }
 
     @Override
-    public DOMDataTreeChangeService getService() {
-        return this.ribImpl.getService();
+    public synchronized DOMDataTreeChangeService getService() {
+        return ribImpl.getService();
     }
 
-    FluentFuture<? extends CommitInfo> closeServiceInstance() {
-        if (this.ribImpl != null) {
-            return this.ribImpl.closeServiceInstance();
+    synchronized FluentFuture<? extends CommitInfo> closeServiceInstance() {
+        if (ribImpl != null) {
+            return ribImpl.closeServiceInstance();
         }
         return CommitInfo.emptyFluentFuture();
     }
 
     @Override
-    public void close() {
-        if (this.ribImpl != null) {
-            this.stateProviderRegistration.close();
-            this.ribImpl.close();
-            this.stateProviderRegistration = null;
-            this.ribImpl = null;
-        }
-    }
-
-
-    @Override
-    public Set<TablesKey> getLocalTablesKeys() {
-        return this.ribImpl.getLocalTablesKeys();
+    public synchronized Set<TablesKey> getLocalTablesKeys() {
+        return ribImpl.getLocalTablesKeys();
     }
 
     @Override
-    public boolean supportsTable(final TablesKey tableKey) {
-        return this.ribImpl.supportsTable(tableKey);
+    public synchronized boolean supportsTable(final TablesKey tableKey) {
+        return ribImpl.supportsTable(tableKey);
     }
 
     @Override
-    public BGPRibRoutingPolicy getRibPolicies() {
-        return this.ribImpl.getRibPolicies();
+    public synchronized BGPRibRoutingPolicy getRibPolicies() {
+        return ribImpl.getRibPolicies();
     }
 
     @Override
-    public BGPPeerTracker getPeerTracker() {
-        return this.ribImpl.getPeerTracker();
+    public synchronized BGPPeerTracker getPeerTracker() {
+        return ribImpl.getPeerTracker();
     }
 
     @Override
-    public String toString() {
-        return this.ribImpl != null ? this.ribImpl.toString() : "";
+    public synchronized String toString() {
+        return ribImpl != null ? ribImpl.toString() : "";
     }
 
-    private RIBImpl createRib(
+    private synchronized RIBImpl createRib(
             final Global global,
-            final String bgpInstanceName,
             final BGPTableTypeRegistryConsumer tableTypeRegistry) {
-        this.afiSafi = getAfiSafiWithDefault(global.getAfiSafis(), true).values();
+        afiSafi = getAfiSafiWithDefault(global.getAfiSafis(), true).values();
         final Config globalConfig = global.getConfig();
-        this.asNumber = globalConfig.getAs();
-        this.routerId = IetfInetUtil.INSTANCE.ipv4AddressNoZoneFor(globalConfig.getRouterId());
-        this.clusterId = getGlobalClusterIdentifier(globalConfig);
+        asNumber = globalConfig.getAs();
+        routerId = IetfInetUtil.INSTANCE.ipv4AddressNoZoneFor(globalConfig.getRouterId());
+        clusterId = getGlobalClusterIdentifier(globalConfig);
         final Map<TablesKey, PathSelectionMode> pathSelectionModes = OpenConfigMappingUtil
-                .toPathSelectionMode(this.afiSafi, tableTypeRegistry).entrySet()
+                .toPathSelectionMode(afiSafi, tableTypeRegistry).entrySet()
                 .stream()
                 .collect(Collectors.toMap(entry ->
                         new TablesKey(entry.getKey().getAfi(), entry.getKey().getSafi()), Map.Entry::getValue));
 
-        final BGPRibRoutingPolicy ribPolicy = this.policyProvider.buildBGPRibPolicy(this.asNumber.getValue().toJava(),
-                this.routerId, this.clusterId, RoutingPolicyUtil.getApplyPolicy(global.getApplyPolicy()));
+        final BGPRibRoutingPolicy ribPolicy = policyProvider.buildBGPRibPolicy(asNumber.getValue().toJava(),
+                routerId, clusterId, RoutingPolicyUtil.getApplyPolicy(global.getApplyPolicy()));
 
         return new RIBImpl(
                 tableTypeRegistry,
-                new RibId(bgpInstanceName),
-                this.asNumber,
-                new BgpId(this.routerId),
-                this.extensions,
-                this.dispatcher,
+                ribId,
+                asNumber,
+                new BgpId(routerId),
+                extensionProvider,
+                dispatcher,
                 codecsRegistry,
-                this.domBroker,
+                domBroker,
                 ribPolicy,
-                toTableTypes(this.afiSafi, tableTypeRegistry),
+                toTableTypes(afiSafi, tableTypeRegistry),
                 pathSelectionModes);
     }
 
     @Override
-    public BGPRibState getRIBState() {
-        return this.ribImpl.getRIBState();
+    public synchronized BGPRibState getRIBState() {
+        return ribImpl.getRIBState();
     }
 
-    public void instantiateServiceInstance() {
-        if (this.ribImpl != null) {
-            this.ribImpl.instantiateServiceInstance();
+    public synchronized void instantiateServiceInstance() {
+        if (ribImpl != null) {
+            ribImpl.instantiateServiceInstance();
         }
     }
 
     @Override
-    public void refreshTable(final TablesKey tk, final PeerId peerId) {
-        this.ribImpl.refreshTable(tk, peerId);
+    public synchronized void refreshTable(final TablesKey tk, final PeerId peerId) {
+        ribImpl.refreshTable(tk, peerId);
     }
 }
index ceb813f5b96144e22f73aeb7937ac6ae94af7df0..fa1cd36133972884de181a3eced1f00961443da0 100644 (file)
@@ -81,6 +81,7 @@ public class BGPReconnectPromise<S extends BGPSession> extends DefaultPromise<Vo
         final ChannelHandler chInit = new ChannelInitializer<SocketChannel>() {
             @Override
             protected void initChannel(final SocketChannel channel) {
+                LOG.info("Initializing channel with {}", channel.remoteAddress());
                 initializer.initializeChannel(channel, sessionPromise);
             }
         };
index cd368716862d51a58c124c0829c91cbca93796a4..2f01da4f692ea213579ba832d32648b1e3e7798c 100644 (file)
@@ -10,11 +10,12 @@ package org.opendaylight.protocol.bgp.rib.impl.config;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
 import static org.mockito.internal.verification.VerificationModeFactory.times;
 
+import java.util.concurrent.ExecutionException;
 import org.junit.Before;
 import org.junit.Test;
-import org.mockito.Mockito;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
 import org.opendaylight.protocol.bgp.rib.impl.state.BGPStateCollector;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.ConfigBuilder;
@@ -28,12 +29,12 @@ public class AppPeerTest extends AbstractConfig {
     private final AppPeer appPeer = new AppPeer(new BGPStateCollector());
 
     private final Neighbor neighbor = new NeighborBuilder()
-            .setConfig(new ConfigBuilder()
-                .addAugmentation(new NeighborPeerGroupConfigBuilder()
-                    .setPeerGroup(OpenConfigMappingUtil.APPLICATION_PEER_GROUP_NAME)
-                    .build())
+        .setConfig(new ConfigBuilder()
+            .addAugmentation(new NeighborPeerGroupConfigBuilder()
+                .setPeerGroup(OpenConfigMappingUtil.APPLICATION_PEER_GROUP_NAME)
                 .build())
-            .setNeighborAddress(new IpAddress(new Ipv4Address("127.0.0.1"))).build();
+            .build())
+        .setNeighborAddress(new IpAddress(new Ipv4Address("127.0.0.1"))).build();
 
     @Override
     @Before
@@ -42,41 +43,42 @@ public class AppPeerTest extends AbstractConfig {
     }
 
     @Test
-    public void testAppPeer() {
-        appPeer.start(this.rib, this.neighbor, null, this.peerGroupLoader, this.tableTypeRegistry);
-        Mockito.verify(this.rib).getYangRibId();
-        Mockito.verify(this.rib).getService();
-        Mockito.verify(this.rib).createPeerDOMChain(any(DOMTransactionChainListener.class));
-        Mockito.verify(this.rib, times(1)).getLocalTablesKeys();
+    public void testAppPeer() throws ExecutionException, InterruptedException {
+        appPeer.start(rib, neighbor, null, peerGroupLoader, tableTypeRegistry);
+        verify(rib).getYangRibId();
+        verify(rib).getService();
+        verify(rib).createPeerDOMChain(any(DOMTransactionChainListener.class));
+        verify(rib, times(1)).getLocalTablesKeys();
 
         appPeer.instantiateServiceInstance();
-        Mockito.verify(this.rib, times(3)).getYangRibId();
-        Mockito.verify(this.rib, times(2)).getRibSupportContext();
-        Mockito.verify(this.rib, times(2)).getLocalTablesKeys();
-        Mockito.verify(this.rib, times(2)).createPeerDOMChain(any(DOMTransactionChainListener.class));
-        Mockito.verify(this.domTx).newWriteOnlyTransaction();
+        verify(rib, times(3)).getYangRibId();
+        verify(rib, times(2)).getRibSupportContext();
+        verify(rib, times(2)).getLocalTablesKeys();
+        verify(rib, times(2)).createPeerDOMChain(any(DOMTransactionChainListener.class));
+        verify(domTx).newWriteOnlyTransaction();
 
         appPeer.closeServiceInstance();
-        Mockito.verify(this.domTx, times(2)).close();
-        appPeer.close();
+        verify(domTx, times(2)).close();
+        appPeer.stop().get();
 
-        appPeer.restart(this.rib, null, this.peerGroupLoader, this.tableTypeRegistry);
+        appPeer.start(rib, appPeer.getCurrentConfiguration(), null, peerGroupLoader, tableTypeRegistry);
         appPeer.instantiateServiceInstance();
-        Mockito.verify(this.rib, times(6)).getYangRibId();
-        Mockito.verify(this.rib, times(4)).getService();
-        Mockito.verify(this.rib, times(4)).createPeerDOMChain(any(DOMTransactionChainListener.class));
-        Mockito.verify(this.listener, times(2)).close();
+        verify(rib, times(6)).getYangRibId();
+        verify(rib, times(4)).getService();
+        verify(rib, times(4)).createPeerDOMChain(any(DOMTransactionChainListener.class));
+        verify(listener, times(2)).close();
 
-        assertTrue(appPeer.containsEqualConfiguration(this.neighbor));
+        assertTrue(appPeer.containsEqualConfiguration(neighbor));
         assertFalse(appPeer.containsEqualConfiguration(new NeighborBuilder()
-                .setNeighborAddress(new IpAddress(new Ipv4Address("127.0.0.2"))).build()));
+                .setNeighborAddress(new IpAddress(new Ipv4Address("127.0.0.2")))
+                .build()));
         appPeer.closeServiceInstance();
-        Mockito.verify(this.domTx, times(4)).close();
+        verify(domTx, times(4)).close();
 
         appPeer.instantiateServiceInstance();
-        Mockito.verify(this.rib, times(6)).createPeerDOMChain(any(DOMTransactionChainListener.class));
+        verify(rib, times(6)).createPeerDOMChain(any(DOMTransactionChainListener.class));
         appPeer.closeServiceInstance();
-        Mockito.verify(this.domTx, times(6)).close();
-        appPeer.close();
+        verify(domTx, times(6)).close();
+        appPeer.stop().get();
     }
 }
index 0459e0a7479ab284ba9bb0b9548a55d310ac71a9..365877f7415c808919e0a0a051e41d9e97439f3c 100644 (file)
@@ -104,100 +104,94 @@ public class BgpDeployerTest extends DefaultRibPoliciesMockTest {
     public void setUp() throws Exception {
         super.setUp();
 
-        doReturn("mapping").when(this.tableTypeRegistry).toString();
-        doReturn(TABLE_TYPE).when(this.tableTypeRegistry).getTableType(any());
-        doReturn(TABLES_KEY).when(this.tableTypeRegistry).getTableKey(any());
+        doReturn("mapping").when(tableTypeRegistry).toString();
+        doReturn(TABLE_TYPE).when(tableTypeRegistry).getTableType(any());
+        doReturn(TABLES_KEY).when(tableTypeRegistry).getTableKey(any());
 
         final ClusterSingletonServiceRegistration serviceRegistration = mock(ClusterSingletonServiceRegistration.class);
-        doReturn(serviceRegistration).when(this.singletonServiceProvider).registerClusterSingletonService(any());
+        doReturn(serviceRegistration).when(singletonServiceProvider).registerClusterSingletonService(any());
         doNothing().when(serviceRegistration).close();
 
         final Future future = mock(BGPReconnectPromise.class);
         doReturn(true).when(future).cancel(true);
-        doReturn(future).when(this.dispatcher).createReconnectingClient(any(), any(), anyInt(), any());
-        this.deployer = spy(new DefaultBgpDeployer(NETWORK_INSTANCE_NAME, this.singletonServiceProvider,
-                this.rpcRegistry, this.extensionContext, this.dispatcher,
+        doReturn(future).when(dispatcher).createReconnectingClient(any(), any(), anyInt(), any());
+        deployer = spy(new DefaultBgpDeployer(NETWORK_INSTANCE_NAME, singletonServiceProvider,
+                rpcRegistry, extensionContext, dispatcher,
                 new DefaultBGPRibRoutingPolicyFactory(getDataBroker(), new StatementRegistry()),
-                this.codecsRegistry, getDomBroker(), getDataBroker(), this.tableTypeRegistry, stateProviderRegistry));
-        this.bgpSingletonObtainedLatch = new CountDownLatch(1);
+                codecsRegistry, getDomBroker(), getDataBroker(), tableTypeRegistry, stateProviderRegistry));
+        bgpSingletonObtainedLatch = new CountDownLatch(1);
         doAnswer(invocationOnMock -> {
                 final BGPClusterSingletonService real =
                         (BGPClusterSingletonService) invocationOnMock.callRealMethod();
-                if (this.spiedBgpSingletonService == null) {
-                    this.spiedBgpSingletonService = spy(real);
+                if (spiedBgpSingletonService == null) {
+                    spiedBgpSingletonService = spy(real);
                 }
-                this.bgpSingletonObtainedLatch.countDown();
-                return this.spiedBgpSingletonService;
+                bgpSingletonObtainedLatch.countDown();
+                return spiedBgpSingletonService;
             }
-        ).when(this.deployer).getBgpClusterSingleton(any());
+        ).when(deployer).getBgpClusterSingleton(any());
     }
 
     @Test
     public void testDeployerRib() throws Exception {
-        this.deployer.init();
+        deployer.init();
         checkPresentConfiguration(getDataBroker(), NETWORK_II);
         createRib(createGlobalIpv4());
         awaitForObtainedSingleton();
-        verify(this.spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS).times(1))
-                .initiateRibInstance(any());
+        verify(spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS).times(1)).initiateRibInstance(any());
 
         //change with same rib already existing
         createRib(createGlobalIpv4());
         awaitForObtainedSingleton();
-        verify(this.spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS).times(1))
-                .initiateRibInstance(any());
+        verify(spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS).times(1)).initiateRibInstance(any());
 
         //Update for existing rib
         createRib(createGlobalIpv6());
         awaitForObtainedSingleton();
-        verify(this.spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS).times(2))
-                .initiateRibInstance(any());
-        verify(this.spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS).times(1))
-                .closeRibService();
+        verify(spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS).times(2)).initiateRibInstance(any());
+        verify(spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS).times(1)).closeRibInstance();
 
         //Delete for existing rib
         deleteRib();
         awaitForObtainedSingleton();
-        verify(this.spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS).times(2))
-                .initiateRibInstance(any());
-        verify(this.spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS).times(2))
-                .closeRibService();
+        verify(spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS).times(2)).initiateRibInstance(any());
+        verify(spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS).times(2)).closeRibInstance();
 
-        this.deployer.close();
+        deployer.close();
     }
 
     @Test
     public void testDeployerCreateNeighbor() throws Exception {
-        this.deployer.init();
+        deployer.init();
         checkPresentConfiguration(getDataBroker(), NETWORK_II);
 
         createRib(createGlobalIpv4());
         createNeighbor(createNeighbors());
         awaitForObtainedSingleton();
-        verify(this.spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS)).onNeighborCreated(any());
+        verify(spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS)).onNeighborCreated(any());
 
         //change with same peer already existing
         createNeighbor(createNeighbors());
         awaitForObtainedSingleton();
-        verify(this.spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS)).onNeighborCreated(any());
-        verify(this.spiedBgpSingletonService, never()).onNeighborRemoved(any());
-        verify(this.spiedBgpSingletonService, never()).onNeighborUpdated(any(), any());
+        verify(spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS)).onNeighborCreated(any());
+        verify(spiedBgpSingletonService, never()).onNeighborRemoved(any());
+        verify(spiedBgpSingletonService, never()).onNeighborUpdated(any(), any());
 
         //Update for peer
         createNeighbor(createNeighborsNoRR());
         awaitForObtainedSingleton();
-        verify(this.spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS).times(1)).onNeighborUpdated(any(), any());
+        verify(spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS).times(1)).onNeighborUpdated(any(), any());
 
         deleteNeighbors();
         //Delete existing Peer
         awaitForObtainedSingleton();
-        verify(this.spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS).times(1)).onNeighborRemoved(any());
-        this.deployer.close();
+        verify(spiedBgpSingletonService, timeout(VERIFY_TIMEOUT_MILIS).times(1)).onNeighborRemoved(any());
+        deployer.close();
     }
 
     private void awaitForObtainedSingleton() throws InterruptedException {
-        this.bgpSingletonObtainedLatch = new CountDownLatch(1);
-        this.bgpSingletonObtainedLatch.await(VERIFY_TIMEOUT_MILIS, TimeUnit.MILLISECONDS);
+        bgpSingletonObtainedLatch = new CountDownLatch(1);
+        bgpSingletonObtainedLatch.await(VERIFY_TIMEOUT_MILIS, TimeUnit.MILLISECONDS);
     }
 
     private void createRib(final Global global) throws ExecutionException, InterruptedException {
@@ -223,5 +217,4 @@ public class BgpDeployerTest extends DefaultRibPoliciesMockTest {
         wr.delete(LogicalDatastoreType.CONFIGURATION, NEIGHBORS_II);
         wr.commit().get();
     }
-
 }
index 9bf476e32bbbef223495ae6e7db51db523f081fb..ab7234249e9ba9643507356ac3ac38ac48026ba6 100644 (file)
@@ -7,9 +7,9 @@
  */
 package org.opendaylight.protocol.bgp.rib.impl.config;
 
-import static junit.framework.TestCase.fail;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -19,8 +19,8 @@ import static org.mockito.Mockito.verify;
 
 import java.math.BigDecimal;
 import java.net.InetSocketAddress;
-import java.util.Collections;
 import java.util.Map;
+import java.util.concurrent.ExecutionException;
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.mdsal.binding.api.RpcProviderService;
@@ -63,7 +63,7 @@ public class BgpPeerTest extends AbstractConfig {
     static final AfiSafi AFI_SAFI_IPV4 = new AfiSafiBuilder().setAfiSafiName(IPV4UNICAST.class)
             .addAugmentation(new NeighborAddPathsConfigBuilder().setReceive(true).setSendMax(Uint8.ZERO).build())
             .build();
-    static final Map<AfiSafiKey, AfiSafi> AFI_SAFI = Collections.singletonMap(AFI_SAFI_IPV4.key(), AFI_SAFI_IPV4);
+    static final Map<AfiSafiKey, AfiSafi> AFI_SAFI = Map.of(AFI_SAFI_IPV4.key(), AFI_SAFI_IPV4);
     private static final BigDecimal DEFAULT_TIMERS = BigDecimal.valueOf(30);
     private BgpPeer bgpPeer;
 
@@ -80,8 +80,8 @@ public class BgpPeerTest extends AbstractConfig {
     }
 
     static Transport createTransport() {
-        return new TransportBuilder().setConfig(new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp
-                .rev151009.bgp.neighbor.group.transport.ConfigBuilder()
+        return new TransportBuilder().setConfig(new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009
+                .bgp.neighbor.group.transport.ConfigBuilder()
                     .setMtuDiscovery(false)
                     .setPassiveMode(false)
                     .addAugmentation(new NeighborTransportConfigBuilder().setRemotePort(PORT).build())
@@ -128,81 +128,86 @@ public class BgpPeerTest extends AbstractConfig {
     @Before
     public void setUp() throws Exception {
         super.setUp();
-        this.bgpPeer = new BgpPeer(mock(RpcProviderService.class), new BGPStateCollector());
+        bgpPeer = new BgpPeer(mock(RpcProviderService.class), new BGPStateCollector());
     }
 
     @Test
-    public void testBgpPeer() {
-        final Neighbor neighbor = new NeighborBuilder().setAfiSafis(createAfiSafi()).setConfig(createConfig())
-                .setNeighborAddress(NEIGHBOR_ADDRESS).setRouteReflector(createRR()).setTimers(createTimers())
-                .setTransport(createTransport()).setAddPaths(createAddPath()).build();
-
-        this.bgpPeer.start(this.rib, neighbor, null, this.peerGroupLoader, this.tableTypeRegistry);
-        verify(this.rib).createPeerDOMChain(any());
-        verify(this.rib, times(2)).getLocalAs();
-        verify(this.rib).getLocalTables();
-
-        this.bgpPeer.instantiateServiceInstance();
-        verify(this.bgpPeerRegistry).addPeer(any(), any(), any());
-        verify(this.dispatcher).createReconnectingClient(any(InetSocketAddress.class),
-                any(), anyInt(), any(KeyMapping.class));
-
-        try {
-            this.bgpPeer.start(this.rib, neighbor, null, this.peerGroupLoader, this.tableTypeRegistry);
-            fail("Expected Exception");
-        } catch (final IllegalStateException expected) {
-            assertEquals("Previous peer instance was not closed.", expected.getMessage());
-        }
-        this.bgpPeer.closeServiceInstance();
-        verify(this.bgpPeerRegistry).removePeer(any());
-        verify(this.future).cancel(true);
-        this.bgpPeer.close();
-
-        this.bgpPeer.restart(this.rib, null, this.peerGroupLoader, this.tableTypeRegistry);
-        verify(this.rib, times(2)).createPeerDOMChain(any());
-        verify(this.rib, times(4)).getLocalAs();
-        verify(this.rib, times(2)).getLocalTables();
-        this.bgpPeer.instantiateServiceInstance();
-        verify(this.bgpPeerRegistry, times(2)).addPeer(any(), any(), any());
-        verify(this.dispatcher, times(2)).createReconnectingClient(any(InetSocketAddress.class),
-                any(), anyInt(), any(KeyMapping.class));
+    public void testBgpPeer() throws ExecutionException, InterruptedException {
+        final Neighbor neighbor = new NeighborBuilder()
+            .setAfiSafis(createAfiSafi())
+            .setConfig(createConfig())
+            .setNeighborAddress(NEIGHBOR_ADDRESS)
+            .setRouteReflector(createRR())
+            .setTimers(createTimers())
+            .setTransport(createTransport())
+            .setAddPaths(createAddPath())
+            .build();
+
+        bgpPeer.start(rib, neighbor, null, peerGroupLoader, tableTypeRegistry);
+        verify(rib).createPeerDOMChain(any());
+        verify(rib, times(2)).getLocalAs();
+        verify(rib).getLocalTables();
+
+        bgpPeer.instantiateServiceInstance();
+        verify(bgpPeerRegistry).addPeer(any(), any(), any());
+        verify(dispatcher).createReconnectingClient(any(InetSocketAddress.class), any(), anyInt(),
+            any(KeyMapping.class));
+
+        final var ex = assertThrows(IllegalStateException.class,
+            () -> bgpPeer.start(rib, neighbor, null, peerGroupLoader, tableTypeRegistry));
+        assertEquals("Previous peer instance was not closed.", ex.getMessage());
+        bgpPeer.closeServiceInstance();
+        verify(bgpPeerRegistry).removePeer(any());
+        verify(future).cancel(true);
+        bgpPeer.stop().get();
+        bgpPeer.start(rib, bgpPeer.getCurrentConfiguration(), null, peerGroupLoader, tableTypeRegistry);
+        bgpPeer.instantiateServiceInstance();
+        verify(rib, times(2)).createPeerDOMChain(any());
+        verify(rib, times(4)).getLocalAs();
+        verify(rib, times(2)).getLocalTables();
+        verify(bgpPeerRegistry, times(2)).addPeer(any(), any(), any());
+        verify(dispatcher, times(2)).createReconnectingClient(any(InetSocketAddress.class), any(), anyInt(),
+            any(KeyMapping.class));
 
         final Neighbor neighborExpected = createNeighborExpected(NEIGHBOR_ADDRESS);
-        assertTrue(this.bgpPeer.containsEqualConfiguration(neighborExpected));
-        assertFalse(this.bgpPeer.containsEqualConfiguration(createNeighborExpected(
-                new IpAddress(new Ipv4Address("127.0.0.2")))));
-
-        this.bgpPeer.closeServiceInstance();
-        verify(this.bgpPeerRegistry, times(2)).removePeer(any());
-        verify(this.future, times(2)).cancel(true);
-
-        this.bgpPeer.instantiateServiceInstance();
-        verify(this.bgpPeerRegistry, times(3)).addPeer(any(), any(), any());
-        verify(this.dispatcher, times(3)).createReconnectingClient(any(InetSocketAddress.class),
-                any(), anyInt(), any(KeyMapping.class));
-
-        this.bgpPeer.closeServiceInstance();
-        verify(this.bgpPeerRegistry, times(3)).removePeer(any());
-        verify(this.future, times(3)).cancel(true);
-        verify(this.rib, times(3)).createPeerDOMChain(any());
-
-        this.bgpPeer.restart(this.rib, null, this.peerGroupLoader, this.tableTypeRegistry);
-        verify(this.rib, times(4)).createPeerDOMChain(any());
-        verify(this.rib, times(6)).getLocalAs();
-        verify(this.rib, times(3)).getLocalTables();
-        this.bgpPeer.instantiateServiceInstance();
-        verify(this.bgpPeerRegistry, times(4)).addPeer(any(), any(), any());
-        verify(this.dispatcher, times(4)).createReconnectingClient(any(InetSocketAddress.class),
-                any(), anyInt(), any(KeyMapping.class));
-        this.bgpPeer.closeServiceInstance();
-        verify(this.bgpPeerRegistry, times(4)).removePeer(any());
-        verify(this.future, times(4)).cancel(true);
-        this.bgpPeer.close();
-
-        final Neighbor neighborDiffConfig = new NeighborBuilder().setNeighborAddress(NEIGHBOR_ADDRESS)
-                .setAfiSafis(createAfiSafi()).build();
-        this.bgpPeer.start(this.rib, neighborDiffConfig, null, this.peerGroupLoader, this.tableTypeRegistry);
-        assertTrue(this.bgpPeer.containsEqualConfiguration(neighborDiffConfig));
-        this.bgpPeer.close();
+        assertTrue(bgpPeer.containsEqualConfiguration(neighborExpected));
+        assertFalse(bgpPeer.containsEqualConfiguration(createNeighborExpected(
+            new IpAddress(new Ipv4Address("127.0.0.2")))));
+
+        bgpPeer.closeServiceInstance();
+        verify(bgpPeerRegistry, times(2)).removePeer(any());
+        verify(future, times(2)).cancel(true);
+
+        bgpPeer.instantiateServiceInstance();
+        verify(bgpPeerRegistry, times(3)).addPeer(any(), any(), any());
+        verify(dispatcher, times(3)).createReconnectingClient(any(InetSocketAddress.class), any(), anyInt(),
+            any(KeyMapping.class));
+
+        bgpPeer.closeServiceInstance();
+        verify(bgpPeerRegistry, times(3)).removePeer(any());
+        verify(future, times(3)).cancel(true);
+        verify(rib, times(3)).createPeerDOMChain(any());
+
+        bgpPeer.stop().get();
+        bgpPeer.start(rib, bgpPeer.getCurrentConfiguration(), null, peerGroupLoader, tableTypeRegistry);
+        bgpPeer.instantiateServiceInstance();
+        verify(rib, times(4)).createPeerDOMChain(any());
+        verify(rib, times(6)).getLocalAs();
+        verify(rib, times(3)).getLocalTables();
+        verify(bgpPeerRegistry, times(4)).addPeer(any(), any(), any());
+        verify(dispatcher, times(4)).createReconnectingClient(any(InetSocketAddress.class), any(), anyInt(),
+            any(KeyMapping.class));
+        bgpPeer.closeServiceInstance();
+        verify(bgpPeerRegistry, times(4)).removePeer(any());
+        verify(future, times(4)).cancel(true);
+        bgpPeer.stop().get();
+
+        final Neighbor neighborDiffConfig = new NeighborBuilder()
+            .setNeighborAddress(NEIGHBOR_ADDRESS)
+            .setAfiSafis(createAfiSafi())
+            .build();
+        bgpPeer.start(rib, neighborDiffConfig, null, peerGroupLoader, tableTypeRegistry);
+        assertTrue(bgpPeer.containsEqualConfiguration(neighborDiffConfig));
+        bgpPeer.stop().get();
     }
 }
index 0ec3ce9a251d555124160201b115584b805ac4e7..60ca2394f8cab7586381c6e92c200ad6bbcea1b1 100644 (file)
@@ -18,6 +18,7 @@ import com.google.common.collect.ImmutableClassToInstanceMap;
 import com.google.common.collect.ImmutableSet;
 import java.util.Collections;
 import java.util.Map;
+import java.util.concurrent.ExecutionException;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
@@ -74,34 +75,29 @@ public class RibImplTest extends AbstractConfig {
     public void setUp() throws Exception {
         super.setUp();
 
-        doReturn(this.ribSupport).when(this.extension).getRIBSupport(any(TablesKey.class));
+        doReturn(ribSupport).when(extension).getRIBSupport(any(TablesKey.class));
         final NodeIdentifier nii = new NodeIdentifier(QName.create("", "test").intern());
-        doReturn(nii).when(this.ribSupport).routeAttributesIdentifier();
-        doReturn(ImmutableSet.of()).when(this.ribSupport).cacheableAttributeObjects();
+        doReturn(nii).when(ribSupport).routeAttributesIdentifier();
+        doReturn(ImmutableSet.of()).when(ribSupport).cacheableAttributeObjects();
         final MapEntryNode emptyTable = mock(MapEntryNode.class);
-        doReturn(emptyTable).when(this.ribSupport).emptyTable();
+        doReturn(emptyTable).when(ribSupport).emptyTable();
         final NodeIdentifierWithPredicates niie = NodeIdentifierWithPredicates.of(Rib.QNAME,
                 QName.create("", "test").intern(), "t");
         doReturn(niie).when(emptyTable).getIdentifier();
-        doReturn(this.domTx).when(this.domDataBroker).createMergingTransactionChain(any());
+        doReturn(domTx).when(domDataBroker).createMergingTransactionChain(any());
         final DOMDataTreeChangeService dOMDataTreeChangeService = mock(DOMDataTreeChangeService.class);
         doReturn(ImmutableClassToInstanceMap.of(DOMDataTreeChangeService.class, dOMDataTreeChangeService))
-                .when(this.domDataBroker).getExtensions();
+                .when(domDataBroker).getExtensions();
         doReturn(mock(ListenerRegistration.class)).when(dOMDataTreeChangeService)
                 .registerDataTreeChangeListener(any(), any());
     }
 
     @Test
-    public void testRibImpl() {
-        final RibImpl ribImpl = new RibImpl(
-                this.extension,
-                this.dispatcher,
-                this.policyProvider,
-                this.codecsRegistry,
-                new BGPStateCollector(),
-                this.domDataBroker);
-        ribImpl.start(createGlobal(), "rib-test", this.tableTypeRegistry);
-        verify(this.domDataBroker).getExtensions();
+    public void testRibImpl() throws ExecutionException, InterruptedException {
+        final RibImpl ribImpl = new RibImpl(extension, dispatcher, policyProvider, codecsRegistry,
+                new BGPStateCollector(), domDataBroker);
+        ribImpl.start(createGlobal(), "rib-test", tableTypeRegistry);
+        verify(domDataBroker).getExtensions();
         assertEquals("RIBImpl{bgpId=Ipv4Address{_value=127.0.0.1}, localTables=[BgpTableTypeImpl ["
                 + "getAfi()=interface org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types."
                 + "rev200120.Ipv4AddressFamily, "
@@ -114,12 +110,12 @@ public class RibImplTest extends AbstractConfig {
         assertEquals(AS, ribImpl.getLocalAs());
         assertEquals(BGP_ID, ribImpl.getBgpIdentifier());
         assertEquals(Collections.singleton(TABLE_TYPE), ribImpl.getLocalTables());
-        assertEquals(this.dispatcher, ribImpl.getDispatcher());
-        assertEquals(this.extension, ribImpl.getRibExtensions());
+        assertEquals(dispatcher, ribImpl.getDispatcher());
+        assertEquals(extension, ribImpl.getRibExtensions());
         assertNotNull(ribImpl.getRibSupportContext());
         assertNotNull(ribImpl.getCodecsRegistry());
 
-        ribImpl.close();
+        ribImpl.stop().get();
     }
 
     private static Global createGlobal() {