BUG-7976: Race between peer removal and routes update
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / PeerExportGroupImpl.java
index 7a5b42f156f7389d77323054464ae4d878b6f978..dd6dbc66d21c390562e65a9bc7382adb969ba977 100644 (file)
@@ -9,18 +9,23 @@ package org.opendaylight.protocol.bgp.rib.impl;
 
 import com.google.common.base.Preconditions;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.Map;
-import org.opendaylight.protocol.bgp.rib.spi.PeerExportGroup;
+import java.util.function.BiConsumer;
+import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.protocol.bgp.rib.impl.spi.PeerExportGroupRegistry;
+import org.opendaylight.protocol.concepts.AbstractRegistration;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 
-final class PeerExportGroupImpl implements PeerExportGroup {
-    private final Map<PeerId, PeerExporTuple> peers;
+final class PeerExportGroupImpl implements PeerExportGroupRegistry {
+    @GuardedBy("this")
+    private final Map<PeerId, PeerExporTuple> peers = new HashMap<>();
     private final AbstractExportPolicy policy;
 
-    public PeerExportGroupImpl(final Map<PeerId, PeerExporTuple> peers, final AbstractExportPolicy policy) {
-        this.peers = Preconditions.checkNotNull(peers);
+    public PeerExportGroupImpl(final AbstractExportPolicy policy) {
         this.policy = Preconditions.checkNotNull(policy);
     }
 
@@ -31,11 +36,47 @@ final class PeerExportGroupImpl implements PeerExportGroup {
 
     @Override
     public Collection<Map.Entry<PeerId, PeerExporTuple>> getPeers() {
-        return this.peers.entrySet();
+        synchronized (this.peers) {
+            return this.peers.entrySet();
+        }
     }
 
     @Override
     public boolean containsPeer(final PeerId routePeerId) {
-        return this.peers.containsKey(routePeerId);
+        synchronized (this.peers) {
+            return this.peers.containsKey(routePeerId);
+        }
+    }
+
+    @Override
+    public void forEach(final BiConsumer<PeerId, YangInstanceIdentifier> action) {
+        synchronized (this.peers) {
+            for (final Map.Entry<PeerId, PeerExporTuple> pid : this.peers.entrySet()) {
+                action.accept(pid.getKey(), pid.getValue().getYii());
+            }
+        }
+    }
+
+    @Override
+    public AbstractRegistration registerPeer(final PeerId peerId, final PeerExporTuple peerExporTuple) {
+        synchronized (this.peers) {
+            this.peers.put(peerId, peerExporTuple);
+        }
+
+        return new AbstractRegistration() {
+            @Override
+            protected void removeRegistration() {
+                synchronized (PeerExportGroupImpl.this.peers) {
+                    PeerExportGroupImpl.this.peers.remove(peerId);
+                }
+            }
+        };
+    }
+
+    @Override
+    public boolean isEmpty() {
+        synchronized (this.peers) {
+            return this.peers.isEmpty();
+        }
     }
 }
\ No newline at end of file