BUG-5097: Error trying to update EffectiveRibIn from a removed Peer 97/33697/5
authorClaudio D. Gasparini <cgaspari@cisco.com>
Wed, 27 Jan 2016 18:51:13 +0000 (19:51 +0100)
committerClaudio D. Gasparini <cgaspari@cisco.com>
Sun, 31 Jan 2016 17:44:23 +0000 (18:44 +0100)
When more than one peer are removed at same time, cause a race
condition between remove Peer from DS and update removed routes.
Fix by creating a shared Singleton cache with removed peers between
listeners.

Change-Id: Ic4b2ab8283e07695203f9e4d9ceb245985104766
Signed-off-by: Claudio D. Gasparini <cgaspari@cisco.com>
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ConnectedPeers.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/LocRibWriter.java

index b33657c234edca8f539f5a70da1a737fed5b3947..94b429e95b64b9a848597ea12e0cbc56e477f35d 100644 (file)
@@ -197,7 +197,7 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
         this.session = session;
         this.rawIdentifier = InetAddresses.forString(session.getBgpId().getValue()).getAddress();
         final PeerId peerId = RouterIds.createPeerId(session.getBgpId());
-
+        ConnectedPeers.getInstance().reconnected(peerId);
         createAdjRibOutListener(peerId);
 
         this.ribWriter = this.ribWriter.transform(peerId, this.rib.getRibSupportContext(), this.tables, false);
@@ -276,10 +276,17 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
 
     @Override
     public void releaseConnection() {
+        addPeerToDisconnectedSharedList();
         cleanup();
         dropConnection();
     }
 
+    private void addPeerToDisconnectedSharedList() {
+        if(this.session != null) {
+            ConnectedPeers.getInstance().insertDesconectedPeer(this.session.getBgpId());
+        }
+    }
+
     @GuardedBy("this")
     private void dropConnection() {
         if (this.runtimeReg != null) {
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ConnectedPeers.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ConnectedPeers.java
new file mode 100644 (file)
index 0000000..af5ed11
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * 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;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import java.util.concurrent.TimeUnit;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerId;
+
+final class ConnectedPeers {
+    private static Cache<PeerId, Boolean> cache = CacheBuilder.
+        newBuilder()
+        .expireAfterAccess(30, TimeUnit.SECONDS)
+        .build();
+
+    private ConnectedPeers() {
+    }
+
+    private static class ConnectedPeersHolder {
+        public static final ConnectedPeers INSTANCE = new ConnectedPeers();
+    }
+
+    public static ConnectedPeers getInstance() {
+        return ConnectedPeersHolder.INSTANCE;
+    }
+
+    public boolean isPeerDisconnected(final PeerId peerId) {
+        if(this.cache.getIfPresent(peerId) != null) {
+            return true;
+        }
+        return false;
+    }
+
+    public void reconnected(final PeerId peerId) {
+        this.cache.asMap().remove(peerId);
+    }
+
+    public void insertDesconectedPeer(final Ipv4Address peerId) {
+        this.cache.put(RouterIds.createPeerId(peerId), true);
+    }
+}
index 3cac2a4300350267fdf10be6cfaee2e097f12649..abd8d6f81abe5d15cddc775c26f66ae023d52090 100644 (file)
@@ -325,7 +325,8 @@ final class LocRibWriter implements AutoCloseable, DOMDataTreeChangeListener {
                 final ContainerNode effectiveAttributes = peerGroup.effectiveAttributes(routePeerId, attributes);
                 for (final Entry<PeerId, YangInstanceIdentifier> pid : peerGroup.getPeers()) {
                     final PeerId peerDestiny = pid.getKey();
-                    if (!routePeerId.equals(peerDestiny) && isTableSupported(peerDestiny) && !deletedPeers.containsValue(peerDestiny)) {
+                    if (!routePeerId.equals(peerDestiny) && isTableSupported(peerDestiny) && !deletedPeers.containsValue(peerDestiny) &&
+                        !ConnectedPeers.getInstance().isPeerDisconnected(peerDestiny)) {
                         final YangInstanceIdentifier routeTarget = getRouteTarget(pid.getValue(), routeId);
                         if (value != null && effectiveAttributes != null) {
                             LOG.debug("Write route {} to peers AdjRibsOut {}", value, peerDestiny);