From a5ac27fe2b5fb6d06fd3100c62510697a64c130d Mon Sep 17 00:00:00 2001 From: "Claudio D. Gasparini" Date: Wed, 15 Feb 2017 09:58:38 +0100 Subject: [PATCH] BUG-7222: Make BGP DS clean up asynchronous Close of the service must be done async, otherwise will bock the thread. Fix by make BGP DS clean up asynchronous Change-Id: Icb19ef7b7f118fbc6b07407d1df2cb5f6cffc0fb Signed-off-by: Claudio D. Gasparini --- .../protocol/bgp/rib/impl/AdjRibInWriter.java | 22 ++++++++---- .../bgp/rib/impl/ApplicationPeer.java | 15 +++++--- .../protocol/bgp/rib/impl/BGPPeer.java | 27 ++++++++------ .../protocol/bgp/rib/impl/config/AppPeer.java | 4 +-- .../protocol/bgp/rib/impl/config/BgpPeer.java | 6 ++-- .../protocol/bgp/rib/impl/PeerTest.java | 27 +++++++------- .../bgp/rib/impl/SimpleSessionListener.java | 5 ++- .../rib/impl/StrictBGPPeerRegistryTest.java | 3 +- .../bgp/rib/spi/BGPSessionListener.java | 3 +- .../protocol/bgp/rib/spi/Peer.java | 8 +++++ .../bgp/testtool/TestingListener.java | 5 ++- .../provider/AbstractTopologyBuilder.java | 36 ++++++++++++------- ...TopologyReferenceSingletonServiceImpl.java | 3 +- 13 files changed, 103 insertions(+), 61 deletions(-) diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibInWriter.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibInWriter.java index 6e6dee5e6e..11e96da691 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibInWriter.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibInWriter.java @@ -11,8 +11,10 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap.Builder; +import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; import java.util.Collections; import java.util.Map; import java.util.Map.Entry; @@ -252,17 +254,25 @@ final class AdjRibInWriter { return pb.build(); } - void removePeer() { + ListenableFuture removePeer() { if(this.peerPath != null) { final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction(); tx.delete(LogicalDatastoreType.OPERATIONAL, this.peerPath); + final CheckedFuture future = tx.submit(); + Futures.addCallback(future, new FutureCallback() { + @Override + public void onSuccess(final Void result) { + LOG.debug("Peer {} removed", AdjRibInWriter.this.peerPath); + } - try { - tx.submit().checkedGet(); - } catch (final TransactionCommitFailedException e) { - LOG.debug("Failed to remove Peer {}", this.peerPath, e); - } + @Override + public void onFailure(final Throwable t) { + LOG.warn("Failed to remove Peer {}", AdjRibInWriter.this.peerPath, t); + } + }); + return future; } + return Futures.immediateFuture(null); } void markTableUptodate(final TablesKey tableTypes) { diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ApplicationPeer.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ApplicationPeer.java index 3a02b9b789..45c3c1a2eb 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ApplicationPeer.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ApplicationPeer.java @@ -10,6 +10,8 @@ package org.opendaylight.protocol.bgp.rib.impl; import com.google.common.base.Preconditions; import com.google.common.base.Verify; import com.google.common.net.InetAddresses; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -73,8 +75,8 @@ import org.slf4j.LoggerFactory; * For purposed of import policies such as Best Path Selection, application * peer needs to have a BGP-ID that is configurable. */ -public class ApplicationPeer extends BGPPeerStateImpl implements AutoCloseable, - org.opendaylight.protocol.bgp.rib.spi.Peer, ClusteredDOMDataTreeChangeListener, TransactionChainListener { +public class ApplicationPeer extends BGPPeerStateImpl implements org.opendaylight.protocol.bgp.rib.spi.Peer, + ClusteredDOMDataTreeChangeListener, TransactionChainListener { private static final Logger LOG = LoggerFactory.getLogger(ApplicationPeer.class); @@ -249,8 +251,9 @@ public class ApplicationPeer extends BGPPeerStateImpl implements AutoCloseable, return this.name; } + // FIXME ListenableFuture should be used once closeServiceInstance uses wildcard too @Override - public synchronized void close() { + public synchronized ListenableFuture close() { if (this.registration != null) { this.registration.close(); this.registration = null; @@ -258,8 +261,11 @@ public class ApplicationPeer extends BGPPeerStateImpl implements AutoCloseable, if (this.effectiveRibInWriter != null) { this.effectiveRibInWriter.close(); } + final ListenableFuture future; if (this.adjRibInWriter != null) { - this.adjRibInWriter.removePeer(); + future = this.adjRibInWriter.removePeer(); + }else { + future = Futures.immediateFuture(null); } if (this.chain != null) { this.chain.close(); @@ -269,6 +275,7 @@ public class ApplicationPeer extends BGPPeerStateImpl implements AutoCloseable, this.writerChain.close(); this.writerChain = null; } + return future; } @Override diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java index fd8205233f..0f6696b914 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java @@ -15,6 +15,8 @@ import com.google.common.base.MoreObjects.ToStringHelper; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; import com.google.common.net.InetAddresses; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -103,8 +105,8 @@ import org.slf4j.LoggerFactory; * Class representing a peer. We have a single instance for each peer, which provides translation from BGP events into * RIB actions. */ -public class BGPPeer extends BGPPeerStateImpl implements BGPSessionListener, Peer, AutoCloseable, - BGPPeerRuntimeMXBean, TransactionChainListener { +public class BGPPeer extends BGPPeerStateImpl implements BGPSessionListener, Peer, BGPPeerRuntimeMXBean, + TransactionChainListener { private static final Logger LOG = LoggerFactory.getLogger(BGPPeer.class); @GuardedBy("this") @@ -161,10 +163,12 @@ public class BGPPeer extends BGPPeerStateImpl implements BGPSessionListener, Pee this.ribWriter = AdjRibInWriter.create(this.rib.getYangRibId(), this.peerRole, this.simpleRoutingPolicy, this.chain); } + // FIXME ListenableFuture should be used once closeServiceInstance uses wildcard too @Override - public synchronized void close() { - releaseConnection(); + public synchronized ListenableFuture close() { + final ListenableFuture future = releaseConnection(); this.chain.close(); + return future; } @Override @@ -386,17 +390,18 @@ public class BGPPeer extends BGPPeerStateImpl implements BGPSessionListener, Pee } } - private void cleanup() { + private ListenableFuture cleanup() { // FIXME: BUG-196: support graceful this.adjRibOutListenerSet.values().forEach(AdjRibOutListener::close); this.adjRibOutListenerSet.clear(); if (this.effRibInWriter != null) { this.effRibInWriter.close(); } - if(this.ribWriter != null) { - this.ribWriter.removePeer(); - } this.tables.clear(); + if (this.ribWriter != null) { + return this.ribWriter.removePeer(); + } + return Futures.immediateFuture(null); } @Override @@ -432,15 +437,15 @@ public class BGPPeer extends BGPPeerStateImpl implements BGPSessionListener, Pee } @Override - @GuardedBy("this") - public synchronized void releaseConnection() { + public synchronized ListenableFuture releaseConnection() { if (this.rpcRegistration != null) { this.rpcRegistration.close(); } closeRegistration(); - cleanup(); + final ListenableFuture future = cleanup(); dropConnection(); resetState(); + return future; } private void closeRegistration() { diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/AppPeer.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/AppPeer.java index 2a8ac86a86..aea1d61336 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/AppPeer.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/AppPeer.java @@ -10,7 +10,6 @@ package org.opendaylight.protocol.bgp.rib.impl.config; import com.google.common.base.Preconditions; import com.google.common.base.Strings; -import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import java.util.Objects; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; @@ -140,8 +139,7 @@ public final class AppPeer implements PeerBean, BGPPeerStateConsumer { @Override public ListenableFuture closeServiceInstance() { LOG.info("Application Peer Singleton Service {} instance closed", getIdentifier()); - this.applicationPeer.close(); - return Futures.immediateFuture(null); + return this.applicationPeer.close(); } @Override diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpPeer.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpPeer.java index dea2d865e2..ce2328217e 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpPeer.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpPeer.java @@ -15,7 +15,6 @@ import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUti import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.Iterables; -import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import io.netty.util.concurrent.Future; import java.net.InetSocketAddress; @@ -36,7 +35,6 @@ import org.opendaylight.protocol.bgp.parser.BgpExtendedMessageUtil; import org.opendaylight.protocol.bgp.parser.spi.MultiprotocolCapabilitiesUtil; import org.opendaylight.protocol.bgp.rib.impl.BGPPeer; import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher; -import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry; import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences; import org.opendaylight.protocol.bgp.rib.impl.spi.BgpDeployer.WriteConfiguration; import org.opendaylight.protocol.bgp.rib.impl.spi.RIB; @@ -273,11 +271,11 @@ public final class BgpPeer implements PeerBean, BGPPeerStateConsumer, BGPPeerRun this.connection.cancel(true); this.connection = null; } - this.bgpPeer.close(); + final ListenableFuture future = this.bgpPeer.close(); if(BgpPeer.this.currentConfiguration != null) { this.dispatcher.getBGPPeerRegistry().removePeer(BgpPeer.this.currentConfiguration.getNeighborAddress()); } - return Futures.immediateFuture(null); + return future; } @Override diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/PeerTest.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/PeerTest.java index 39167ebd39..aee98dc37a 100644 --- a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/PeerTest.java +++ b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/PeerTest.java @@ -152,7 +152,7 @@ public class PeerTest extends AbstractRIBTestSetup { try { this.classic.onMessage(this.session, ub.build()); fail(); - } catch (BGPDocumentedException e) { + } catch (final BGPDocumentedException e) { assertEquals(BGPError.MANDATORY_ATTR_MISSING_MSG + "LOCAL_PREF", e.getMessage()); assertEquals(BGPError.WELL_KNOWN_ATTR_MISSING.getCode(), e.getError().getCode()); assertEquals(BGPError.WELL_KNOWN_ATTR_MISSING.getSubcode(), e.getError().getSubcode()); @@ -166,19 +166,18 @@ public class PeerTest extends AbstractRIBTestSetup { assertEquals(3, this.routes.size()); //create new peer so that it gets advertized routes from RIB - try (final BGPPeer testingPeer = new BGPPeer(this.neighborAddress.getValue(), getRib(), PeerRole.Ibgp, null, - Collections.emptySet(), Collections.emptySet())) { - testingPeer.instantiateServiceInstance(); - testingPeer.onSessionUp(this.session); - assertEquals(3, this.routes.size()); - assertEquals(1, testingPeer.getBgpPeerState().getSessionEstablishedCount().getValue().intValue()); - final List routeTables = testingPeer.getBgpPeerState().getRouteTable(); - assertEquals(1, routeTables.size()); - final RouteTable routeTable = routeTables.get(0); - assertEquals(AFI_QNAME.toString(), routeTable.getAfi().getqNameOfIdentity()); - assertEquals(SAFI_QNAME.toString(), routeTable.getSafi().getqNameOfIdentity()); - assertNotNull(testingPeer.getBgpSessionState()); - } + final BGPPeer testingPeer = new BGPPeer(this.neighborAddress.getValue(), getRib(), PeerRole.Ibgp, null, + Collections.emptySet(), Collections.emptySet()); + testingPeer.instantiateServiceInstance(); + testingPeer.onSessionUp(this.session); + assertEquals(3, this.routes.size()); + assertEquals(1, testingPeer.getBgpPeerState().getSessionEstablishedCount().getValue().intValue()); + final List routeTables = testingPeer.getBgpPeerState().getRouteTable(); + assertEquals(1, routeTables.size()); + final RouteTable routeTable = routeTables.get(0); + assertEquals(AFI_QNAME.toString(), routeTable.getAfi().getqNameOfIdentity()); + assertEquals(SAFI_QNAME.toString(), routeTable.getSafi().getqNameOfIdentity()); + assertNotNull(testingPeer.getBgpSessionState()); final List prefs2 = Lists.newArrayList(new Ipv4Prefix("8.0.1.0/28"), new Ipv4Prefix("8.0.1.16/28")); ub.setNlri(new NlriBuilder().setNlri(prefs2).build()); diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SimpleSessionListener.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SimpleSessionListener.java index 1cc49d09e8..8745da8ea6 100644 --- a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SimpleSessionListener.java +++ b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SimpleSessionListener.java @@ -8,6 +8,8 @@ package org.opendaylight.protocol.bgp.rib.impl; import com.google.common.collect.Lists; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.Uninterruptibles; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -71,7 +73,7 @@ public final class SimpleSessionListener implements BGPSessionListener, Listener } @Override - public void releaseConnection() { + public ListenableFuture releaseConnection() { LOG.debug("Releasing connection"); if (this.session != null) { try { @@ -80,6 +82,7 @@ public final class SimpleSessionListener implements BGPSessionListener, Listener LOG.warn("Error closing session", e); } } + return Futures.immediateFuture(null); } public State getState() { diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/StrictBGPPeerRegistryTest.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/StrictBGPPeerRegistryTest.java index 154b79770f..694952c2eb 100644 --- a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/StrictBGPPeerRegistryTest.java +++ b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/StrictBGPPeerRegistryTest.java @@ -14,6 +14,7 @@ import static org.junit.Assert.fail; import com.google.common.base.Optional; import com.google.common.collect.Lists; +import com.google.common.util.concurrent.Futures; import java.net.InetSocketAddress; import java.util.Collections; import java.util.List; @@ -67,7 +68,7 @@ public class StrictBGPPeerRegistryTest { private static BGPSessionListener getMockSession() { final BGPSessionListener mock = Mockito.mock(BGPSessionListener.class); - Mockito.doNothing().when(mock).releaseConnection(); + Mockito.doReturn(Futures.immediateFuture(null)).when(mock).releaseConnection(); return mock; } diff --git a/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/BGPSessionListener.java b/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/BGPSessionListener.java index be65fb4e24..4b30eee531 100644 --- a/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/BGPSessionListener.java +++ b/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/BGPSessionListener.java @@ -7,6 +7,7 @@ */ package org.opendaylight.protocol.bgp.rib.spi; +import com.google.common.util.concurrent.ListenableFuture; import java.util.EventListener; import org.opendaylight.protocol.bgp.parser.BGPDocumentedException; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey; @@ -54,5 +55,5 @@ public interface BGPSessionListener extends EventListener { */ void onMessage(BGPSession session, Notification notification) throws BGPDocumentedException; - void releaseConnection(); + ListenableFuture releaseConnection(); } diff --git a/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/Peer.java b/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/Peer.java index eb8ab087ad..13ca868915 100644 --- a/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/Peer.java +++ b/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/Peer.java @@ -7,6 +7,7 @@ */ package org.opendaylight.protocol.bgp.rib.spi; +import com.google.common.util.concurrent.ListenableFuture; /** * Marker interface identifying a BGP peer. @@ -24,4 +25,11 @@ public interface Peer { * @return byte[] raw identifier */ byte[] getRawIdentifier(); + + /** + * Close Peers and performs asynchronously DS clean up + * + * @return future + */ + ListenableFuture close(); } diff --git a/bgp/testtool/src/main/java/org/opendaylight/protocol/bgp/testtool/TestingListener.java b/bgp/testtool/src/main/java/org/opendaylight/protocol/bgp/testtool/TestingListener.java index 8ad753feb4..de2b7ffc90 100644 --- a/bgp/testtool/src/main/java/org/opendaylight/protocol/bgp/testtool/TestingListener.java +++ b/bgp/testtool/src/main/java/org/opendaylight/protocol/bgp/testtool/TestingListener.java @@ -7,6 +7,8 @@ */ package org.opendaylight.protocol.bgp.testtool; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; import java.util.List; import java.util.concurrent.atomic.LongAdder; import org.opendaylight.protocol.bgp.rib.impl.BGPSessionImpl; @@ -72,8 +74,9 @@ final class TestingListener implements BGPSessionListener { } @Override - public void releaseConnection() { + public ListenableFuture releaseConnection() { LOG.info("Client Listener: Connection released."); + return Futures.immediateFuture(null); } void printCount(final String localAddress) { diff --git a/bgp/topology-provider/src/main/java/org/opendaylight/bgpcep/bgp/topology/provider/AbstractTopologyBuilder.java b/bgp/topology-provider/src/main/java/org/opendaylight/bgpcep/bgp/topology/provider/AbstractTopologyBuilder.java index 1a7aaa821f..63f4a9714a 100644 --- a/bgp/topology-provider/src/main/java/org/opendaylight/bgpcep/bgp/topology/provider/AbstractTopologyBuilder.java +++ b/bgp/topology-provider/src/main/java/org/opendaylight/bgpcep/bgp/topology/provider/AbstractTopologyBuilder.java @@ -9,8 +9,10 @@ package org.opendaylight.bgpcep.bgp.topology.provider; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; import java.util.Collection; import java.util.Collections; import java.util.concurrent.atomic.AtomicBoolean; @@ -41,15 +43,14 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology. import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypes; import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public abstract class AbstractTopologyBuilder implements AutoCloseable, ClusteredDataTreeChangeListener, TopologyReference, TransactionChainListener { +public abstract class AbstractTopologyBuilder implements ClusteredDataTreeChangeListener, + TopologyReference, TransactionChainListener { private static final Logger LOG = LoggerFactory.getLogger(AbstractTopologyBuilder.class); // we limit the listener reset interval to be 5 min at most private static final long LISTENER_RESET_LIMIT_IN_MILLSEC = 5 * 60 * 1000; @@ -147,17 +148,17 @@ public abstract class AbstractTopologyBuilder implements AutoCl return this.topology; } - @Override - public final synchronized void close() { + public final synchronized ListenableFuture close() { if (this.closed) { LOG.trace("Transaction chain was already closed."); - return; + Futures.immediateFuture(null); } this.closed = true; LOG.info("Shutting down builder for {}", getInstanceIdentifier()); unregisterDataChangeListener(); - destroyOperationalTopology(); + final ListenableFuture future = destroyOperationalTopology(); destroyTransactionChain(); + return future; } @Override @@ -252,16 +253,25 @@ public abstract class AbstractTopologyBuilder implements AutoCl * Destroy the current operational topology data. Note a valid transaction must be provided * @throws TransactionCommitFailedException */ - private synchronized void destroyOperationalTopology() { + private synchronized ListenableFuture destroyOperationalTopology() { Preconditions.checkNotNull(this.chain, "A valid transaction chain must be provided."); final WriteTransaction trans = this.chain.newWriteOnlyTransaction(); trans.delete(LogicalDatastoreType.OPERATIONAL, getInstanceIdentifier()); - try { - trans.submit().checkedGet(); - } catch (final TransactionCommitFailedException e) { - LOG.error("Unable to reset operational topology {} (transaction {})", this.topology, trans.getIdentifier(), e); - } + final CheckedFuture future = trans.submit(); + Futures.addCallback(future, new FutureCallback() { + @Override + public void onSuccess(final Void result) { + LOG.trace("Operational topology removed {}", AbstractTopologyBuilder.this.topology); + } + + @Override + public void onFailure(final Throwable t) { + LOG.error("Unable to reset operational topology {} (transaction {})", + AbstractTopologyBuilder.this.topology, trans.getIdentifier(), t); + } + }); clearTopology(); + return future; } /** diff --git a/bgp/topology-provider/src/main/java/org/opendaylight/bgpcep/bgp/topology/provider/config/TopologyReferenceSingletonServiceImpl.java b/bgp/topology-provider/src/main/java/org/opendaylight/bgpcep/bgp/topology/provider/config/TopologyReferenceSingletonServiceImpl.java index 655fd7705f..fe4e35a912 100644 --- a/bgp/topology-provider/src/main/java/org/opendaylight/bgpcep/bgp/topology/provider/config/TopologyReferenceSingletonServiceImpl.java +++ b/bgp/topology-provider/src/main/java/org/opendaylight/bgpcep/bgp/topology/provider/config/TopologyReferenceSingletonServiceImpl.java @@ -59,8 +59,7 @@ final class TopologyReferenceSingletonServiceImpl implements TopologyReferenceSi @Override public ListenableFuture closeServiceInstance() { LOG.info("Close Topology Singleton Service {}", getIdentifier()); - this.topologyBuilder.close(); - return Futures.immediateFuture(null); + return this.topologyBuilder.close(); } @Override -- 2.36.6