BGPCEP-578: Introduce PeerGroup configuration
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / config / AppPeer.java
index 2c12a617dabae47f271ab02304b9a3338e8e7bd1..adbbd046399e3943b4ee19f2bc9bec1e10e942c2 100644 (file)
@@ -12,115 +12,142 @@ 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 javax.annotation.concurrent.GuardedBy;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
-import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
-import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
-import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
-import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenConfigMappingService;
+import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
 import org.opendaylight.protocol.bgp.rib.impl.ApplicationPeer;
-import org.opendaylight.protocol.bgp.rib.impl.spi.BgpDeployer.WriteConfiguration;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
+import org.opendaylight.protocol.bgp.rib.spi.state.BGPPeerState;
+import org.opendaylight.protocol.bgp.rib.spi.state.BGPPeerStateConsumer;
 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.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.ApplicationRib;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.ApplicationRibId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.ApplicationRib;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.ApplicationRibId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.rib.Tables;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.osgi.framework.ServiceRegistration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class AppPeer implements PeerBean {
+public final class AppPeer implements PeerBean, BGPPeerStateConsumer {
     private static final Logger LOG = LoggerFactory.getLogger(AppPeer.class);
     private static final QName APP_ID_QNAME = QName.create(ApplicationRib.QNAME, "id").intern();
+    @GuardedBy("this")
     private Neighbor currentConfiguration;
+    @GuardedBy("this")
     private BgpAppPeerSingletonService bgpAppPeerSingletonService;
+    @GuardedBy("this")
+    private ServiceRegistration<?> serviceRegistration;
+
+    private static ApplicationRibId createAppRibId(final Neighbor neighbor) {
+        final Config config = neighbor.getConfig();
+        if (config != null && !Strings.isNullOrEmpty(config.getDescription())) {
+            return new ApplicationRibId(config.getDescription());
+        }
+        return new ApplicationRibId(neighbor.getNeighborAddress().getIpv4Address().getValue());
+    }
 
     @Override
-    public void start(final RIB rib, final Neighbor neighbor, final BGPOpenConfigMappingService mappingService, final WriteConfiguration configurationWriter) {
+    public 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), neighbor.getNeighborAddress().getIpv4Address());
+        this.bgpAppPeerSingletonService = new BgpAppPeerSingletonService(rib, createAppRibId(neighbor),
+                neighbor.getNeighborAddress().getIpv4Address());
     }
 
     @Override
-    public void restart(final RIB rib, final BGPOpenConfigMappingService mappingService) {
+    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, mappingService, null);
+        start(rib, this.currentConfiguration, bgpIid, peerGroupLoader, tableTypeRegistry);
     }
 
     @Override
-    public void close() {
-        try {
-            this.bgpAppPeerSingletonService.close();
-        } catch (final Exception e) {
-            LOG.warn("Failed to close application peer instance", e);
+    public synchronized void close() {
+        if (this.bgpAppPeerSingletonService != null) {
+            this.bgpAppPeerSingletonService = null;
+        }
+        if (this.serviceRegistration != null) {
+            this.serviceRegistration.unregister();
+            this.serviceRegistration = null;
         }
     }
 
     @Override
-    public Boolean containsEqualConfiguration(final Neighbor neighbor) {
-        return this.currentConfiguration.equals(neighbor);
+    public synchronized void instantiateServiceInstance() {
+        if (this.bgpAppPeerSingletonService != null) {
+            this.bgpAppPeerSingletonService.instantiateServiceInstance();
+        }
     }
 
-    private static ApplicationRibId createAppRibId(final Neighbor neighbor) {
-        final Config config = neighbor.getConfig();
-        if (config != null && !Strings.isNullOrEmpty(config.getDescription())) {
-            return new ApplicationRibId(config.getDescription());
+    @Override
+    public synchronized ListenableFuture<Void> closeServiceInstance() {
+        if (this.bgpAppPeerSingletonService != null) {
+            return this.bgpAppPeerSingletonService.closeServiceInstance();
         }
-        return new ApplicationRibId(neighbor.getNeighborAddress().getIpv4Address().getValue());
+
+        return Futures.immediateFuture(null);
+    }
+
+    @Override
+    public synchronized Boolean containsEqualConfiguration(final Neighbor neighbor) {
+        return Objects.equals(this.currentConfiguration.getKey(), neighbor.getKey())
+                && OpenConfigMappingUtil.isApplicationPeer(neighbor);
+    }
+
+    @Override
+    public synchronized BGPPeerState getPeerState() {
+        return this.bgpAppPeerSingletonService.getPeerState();
+    }
+
+    synchronized void setServiceRegistration(final ServiceRegistration<?> serviceRegistration) {
+        this.serviceRegistration = serviceRegistration;
     }
 
-    private final class BgpAppPeerSingletonService implements ClusterSingletonService, AutoCloseable {
+    private static final class BgpAppPeerSingletonService implements BGPPeerStateConsumer {
         private final ApplicationPeer applicationPeer;
         private final DOMDataTreeChangeService dataTreeChangeService;
         private final ApplicationRibId appRibId;
-        private ClusterSingletonServiceRegistration singletonServiceRegistration;
-        private ListenerRegistration<ApplicationPeer> registration;
-        private final ServiceGroupIdentifier serviceGroupIdentifier;
+        @GuardedBy("this")
+        private boolean isServiceInstantiated;
 
         BgpAppPeerSingletonService(final RIB rib, final ApplicationRibId appRibId, final Ipv4Address neighborAddress) {
             this.applicationPeer = new ApplicationPeer(appRibId, neighborAddress, rib);
             this.appRibId = appRibId;
             this.dataTreeChangeService = rib.getService();
-            this.serviceGroupIdentifier = rib.getRibIServiceGroupIdentifier();
-            LOG.info("Application Peer Singleton Service {} registered", getIdentifier());
-            //this need to be always the last step
-            this.singletonServiceRegistration = rib.registerClusterSingletonService(this);
-        }
-
-        @Override
-        public void close() throws Exception {
-            if (this.singletonServiceRegistration != null) {
-                this.singletonServiceRegistration.close();
-                this.singletonServiceRegistration = null;
-            }
         }
 
-        @Override
-        public void instantiateServiceInstance() {
-            LOG.info("Application Peer Singleton Service {} instantiated", getIdentifier());
+        public synchronized void instantiateServiceInstance() {
+            this.isServiceInstantiated = true;
             final YangInstanceIdentifier yangIId = YangInstanceIdentifier.builder().node(ApplicationRib.QNAME)
-                .nodeWithKey(ApplicationRib.QNAME, APP_ID_QNAME, appRibId.getValue()).node(Tables.QNAME).node(Tables.QNAME).build();
-            this.applicationPeer.instantiateServiceInstance();
-            this.registration = this.dataTreeChangeService
-                .registerDataTreeChangeListener(new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, yangIId), this.applicationPeer);
+                    .nodeWithKey(ApplicationRib.QNAME, APP_ID_QNAME, this.appRibId.getValue())
+                    .node(Tables.QNAME).node(Tables.QNAME).build();
+            this.applicationPeer.instantiateServiceInstance(this.dataTreeChangeService,
+                    new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, yangIId));
         }
 
-        @Override
-        public ListenableFuture<Void> closeServiceInstance() {
-            LOG.info("Application Peer Singleton Service {} instance closed", getIdentifier());
-            this.registration.close();
-            this.applicationPeer.close();
-            return Futures.immediateFuture(null);
+        public synchronized ListenableFuture<Void> closeServiceInstance() {
+            if (!this.isServiceInstantiated) {
+                LOG.trace("Application peer already closed {}", this.appRibId.getValue());
+                return Futures.immediateFuture(null);
+            }
+            LOG.info("Application peer instance closed {}", this.appRibId.getValue());
+            this.isServiceInstantiated = false;
+            return this.applicationPeer.close();
         }
 
         @Override
-        public ServiceGroupIdentifier getIdentifier() {
-            return this.serviceGroupIdentifier;
+        public BGPPeerState getPeerState() {
+            return this.applicationPeer.getPeerState();
         }
     }
-}
\ No newline at end of file
+}