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;
return pb.build();
}
- void removePeer() {
+ ListenableFuture<Void> removePeer() {
if(this.peerPath != null) {
final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction();
tx.delete(LogicalDatastoreType.OPERATIONAL, this.peerPath);
+ final CheckedFuture<Void, TransactionCommitFailedException> future = tx.submit();
+ Futures.addCallback(future, new FutureCallback<Void>() {
+ @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) {
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;
* For purposed of import policies such as Best Path Selection, application
* peer needs to have a BGP-ID that is configurable.
*/
-public class ApplicationPeer implements AutoCloseable, org.opendaylight.protocol.bgp.rib.spi.Peer, ClusteredDOMDataTreeChangeListener, TransactionChainListener {
+public class ApplicationPeer implements org.opendaylight.protocol.bgp.rib.spi.Peer, ClusteredDOMDataTreeChangeListener, TransactionChainListener {
private static final Logger LOG = LoggerFactory.getLogger(ApplicationPeer.class);
return this.name;
}
+ // FIXME ListenableFuture<?> should be used once closeServiceInstance uses wildcard too
@Override
- public synchronized void close() {
+ public synchronized ListenableFuture<Void> close() {
if (this.registration != null) {
this.registration.close();
this.registration = null;
if (this.effectiveRibInWriter != null) {
this.effectiveRibInWriter.close();
}
+ final ListenableFuture<Void> future;
if (this.adjRibInWriter != null) {
- this.adjRibInWriter.removePeer();
+ future = this.adjRibInWriter.removePeer();
+ }else {
+ future = Futures.immediateFuture(null);
}
if (this.chain != null) {
this.chain.close();
if (this.moduleTracker != null) {
this.moduleTracker.onInstanceClose();
}
+ return future;
}
@Override
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;
* Class representing a peer. We have a single instance for each peer, which provides translation from BGP events into
* RIB actions.
*/
-public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeerRuntimeMXBean, TransactionChainListener {
+public class BGPPeer implements BGPSessionListener, Peer, BGPPeerRuntimeMXBean, TransactionChainListener {
private static final Logger LOG = LoggerFactory.getLogger(BGPPeer.class);
public void instantiateServiceInstance() {
// add current peer to "configured BGP peer" stats
this.rib.getRenderStats().getConfiguredPeerCounter().increaseCount();
- this.ribWriter = AdjRibInWriter.create(rib.getYangRibId(), this.peerRole, this.simpleRoutingPolicy, this.chain);
+ 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<Void> close() {
+ final ListenableFuture<Void> future = releaseConnection();
this.chain.close();
+ return future;
}
@Override
}
}
- private void cleanup() {
+ private ListenableFuture<Void> 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
}
@Override
- @GuardedBy("this")
- public synchronized void releaseConnection() {
+ public synchronized ListenableFuture<Void> releaseConnection() {
if (this.rpcRegistration != null) {
this.rpcRegistration.close();
}
closeRegistration();
- cleanup();
+ final ListenableFuture<Void> future = cleanup();
dropConnection();
+ return future;
}
private void closeRegistration() {
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;
@Override
public ListenableFuture<Void> closeServiceInstance() {
LOG.info("Application Peer Singleton Service {} instance closed", getIdentifier());
- this.applicationPeer.close();
- return Futures.immediateFuture(null);
+ return this.applicationPeer.close();
}
@Override
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;
this.connection.cancel(true);
this.connection = null;
}
- this.bgpPeer.close();
+ final ListenableFuture<Void> future = this.bgpPeer.close();
if(BgpPeer.this.currentConfiguration != null) {
BgpPeer.this.peerRegistry.removePeer(BgpPeer.this.currentConfiguration.getNeighborAddress());
}
- return Futures.immediateFuture(null);
+ return future;
}
@Override
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());
assertEquals(3, this.routes.size());
//create new peer so that it gets advertized routes from RIB
- try (final BGPPeer testingPeer = new BGPPeer("testingPeer", getRib(), PeerRole.Ibgp, null)) {
- testingPeer.instantiateServiceInstance();
- testingPeer.onSessionUp(this.session);
- assertEquals(3, this.routes.size());
- assertEquals(1, testingPeer.getBgpPeerState().getSessionEstablishedCount().getValue().intValue());
- final List<RouteTable> 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("testingPeer", getRib(), PeerRole.Ibgp, null);
+ testingPeer.instantiateServiceInstance();
+ testingPeer.onSessionUp(this.session);
+ assertEquals(3, this.routes.size());
+ assertEquals(1, testingPeer.getBgpPeerState().getSessionEstablishedCount().getValue().intValue());
+ final List<RouteTable> 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<Ipv4Prefix> prefs2 = Lists.newArrayList(new Ipv4Prefix("8.0.1.0/28"), new Ipv4Prefix("8.0.1.16/28"));
ub.setNlri(new NlriBuilder().setNlri(prefs2).build());
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;
}
@Override
- public void releaseConnection() {
+ public ListenableFuture<Void> releaseConnection() {
LOG.debug("Releasing connection");
if (this.session != null) {
try {
LOG.warn("Error closing session", e);
}
}
+ return Futures.immediateFuture(null);
}
BGPSessionImpl.State getState() {
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;
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;
}
*/
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;
*/
void onMessage(BGPSession session, Notification notification) throws BGPDocumentedException;
- void releaseConnection();
+ ListenableFuture<?> releaseConnection();
}
*/
package org.opendaylight.protocol.bgp.rib.spi;
+import com.google.common.util.concurrent.ListenableFuture;
/**
* Marker interface identifying a BGP peer.
* @return byte[] raw identifier
*/
byte[] getRawIdentifier();
+
+ /**
+ * Close Peers and performs asynchronously DS clean up
+ *
+ * @return future
+ */
+ ListenableFuture<?> close();
}
*/
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 org.opendaylight.protocol.bgp.rib.impl.BGPSessionImpl;
import org.opendaylight.protocol.bgp.rib.spi.BGPSession;
}
@Override
- public void releaseConnection() {
+ public ListenableFuture<?> releaseConnection() {
LOG.info("Client Listener: Connection released.");
+ return Futures.immediateFuture(null);
}
void printCount(final String localAddress) {
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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public abstract class AbstractTopologyBuilder<T extends Route> implements AutoCloseable, ClusteredDataTreeChangeListener<T>, TopologyReference, TransactionChainListener {
+public abstract class AbstractTopologyBuilder<T extends Route> implements ClusteredDataTreeChangeListener<T>,
+ 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;
return this.topology;
}
- @Override
- public final synchronized void close() {
+ public final synchronized ListenableFuture<Void> 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<Void> future = destroyOperationalTopology();
destroyTransactionChain();
+ return future;
}
@Override
* Destroy the current operational topology data. Note a valid transaction must be provided
* @throws TransactionCommitFailedException
*/
- private synchronized void destroyOperationalTopology() {
+ private synchronized ListenableFuture<Void> 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<Void, TransactionCommitFailedException> future = trans.submit();
+ Futures.addCallback(future, new FutureCallback<Void>() {
+ @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;
}
/**
@Override
public ListenableFuture<Void> closeServiceInstance() {
LOG.info("Close Topology Singleton Service {}", getIdentifier());
- this.topologyBuilder.close();
- return Futures.immediateFuture(null);
+ return this.topologyBuilder.close();
}
@Override