Bump upstreams
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / config / RibImpl.java
index 63cb077d20aff35ae0243c949c7adfa005aba51f..038e43cb16ebc52e96ef463c255e2b5155b8c04b 100644 (file)
  * 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.config;
 
+import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
 import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUtil.getAfiSafiWithDefault;
+import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUtil.getGlobalClusterIdentifier;
+import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUtil.toTableTypes;
 
-import com.google.common.base.Preconditions;
-import java.util.List;
+import com.google.common.util.concurrent.FluentFuture;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collection;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
-import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
-import org.opendaylight.controller.sal.core.api.model.SchemaService;
-import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeFactory;
-import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
-import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
-import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
-import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
+import org.checkerframework.checker.lock.qual.GuardedBy;
+import org.opendaylight.mdsal.common.api.CommitInfo;
+import org.opendaylight.mdsal.dom.api.DOMDataBroker;
+import org.opendaylight.mdsal.dom.api.DOMDataBroker.DataTreeChangeExtension;
+import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
 import org.opendaylight.protocol.bgp.mode.api.PathSelectionMode;
+import org.opendaylight.protocol.bgp.openconfig.routing.policy.spi.BGPRibRoutingPolicyFactory;
 import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
 import org.opendaylight.protocol.bgp.rib.impl.RIBImpl;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
-import org.opendaylight.protocol.bgp.rib.impl.spi.BgpDeployer;
 import org.opendaylight.protocol.bgp.rib.impl.spi.CodecsRegistry;
-import org.opendaylight.protocol.bgp.rib.impl.spi.ImportPolicyPeerTracker;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
-import org.opendaylight.protocol.bgp.rib.impl.stats.rib.impl.BGPRenderStats;
-import org.opendaylight.protocol.bgp.rib.spi.ExportPolicyPeerTracker;
+import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
 import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
+import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRibRoutingPolicy;
+import org.opendaylight.protocol.bgp.rib.spi.state.BGPRibState;
+import org.opendaylight.protocol.bgp.rib.spi.state.BGPRibStateProvider;
+import org.opendaylight.protocol.bgp.rib.spi.state.BGPStateProviderRegistry;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafi;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.global.base.Config;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Global;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
 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.multiprotocol.rev130919.BgpTableType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.RibId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.Rib;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.RibKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ClusterIdentifier;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.BgpTableType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.PeerId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.RibId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.Rib;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.RibKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.BgpId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.ClusterIdentifier;
+import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
-import org.osgi.framework.ServiceRegistration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public final class RibImpl implements RIB, AutoCloseable {
+public final class RibImpl implements RIB, BGPRibStateProvider {
 
     private static final Logger LOG = LoggerFactory.getLogger(RibImpl.class);
 
-    private final RIBExtensionConsumerContext extensions;
+    private final RIBExtensionConsumerContext extensionProvider;
     private final BGPDispatcher dispatcher;
-    private final BindingCodecTreeFactory codecTreeFactory;
+    private final CodecsRegistry codecsRegistry;
     private final DOMDataBroker domBroker;
-    private final SchemaService schemaService;
+    private final BGPRibRoutingPolicyFactory policyProvider;
+    private final BGPStateProviderRegistry stateProviderRegistry;
+    @GuardedBy("this")
     private RIBImpl ribImpl;
-    private ServiceRegistration<?> serviceRegistration;
-    private ListenerRegistration<SchemaContextListener> schemaContextRegistration;
-    private final ClusterSingletonServiceProvider provider;
-    private List<AfiSafi> afiSafi;
+    @GuardedBy("this")
+    private Registration stateProviderRegistration;
+    @GuardedBy("this")
+    private Collection<AfiSafi> afiSafi;
+    @GuardedBy("this")
     private AsNumber asNumber;
-    private Ipv4Address routerId;
-
+    @GuardedBy("this")
+    private Ipv4AddressNoZone routerId;
+    @GuardedBy("this")
     private ClusterIdentifier clusterId;
+    @GuardedBy("this")
+    private RibId ribId;
 
-    public RibImpl(final ClusterSingletonServiceProvider provider, final RIBExtensionConsumerContext contextProvider, final BGPDispatcher dispatcher,
-            final BindingCodecTreeFactory codecTreeFactory, final DOMDataBroker domBroker, final SchemaService schemaService) {
-        this.provider = Preconditions.checkNotNull(provider);
-        this.extensions = contextProvider;
-        this.dispatcher = dispatcher;
-        this.codecTreeFactory = codecTreeFactory;
-        this.domBroker = domBroker;
-        this.schemaService = schemaService;
+    public RibImpl(
+            final RIBExtensionConsumerContext extensionProvider,
+            final BGPDispatcher dispatcher,
+            final BGPRibRoutingPolicyFactory policyProvider,
+            final CodecsRegistry codecsRegistry,
+            final BGPStateProviderRegistry stateProviderRegistry,
+            final DOMDataBroker domBroker) {
+        this.extensionProvider = requireNonNull(extensionProvider);
+        this.dispatcher = requireNonNull(dispatcher);
+        this.codecsRegistry = requireNonNull(codecsRegistry);
+        this.domBroker = requireNonNull(domBroker);
+        this.policyProvider = requireNonNull(policyProvider);
+        this.stateProviderRegistry = requireNonNull(stateProviderRegistry);
     }
 
-    void start(final Global global, final String instanceName, final BGPTableTypeRegistryConsumer tableTypeRegistry,
-        final BgpDeployer.WriteConfiguration configurationWriter) {
-        Preconditions.checkState(this.ribImpl == null, "Previous instance %s was not closed.", this);
-        this.ribImpl = createRib(this.provider, global, instanceName, tableTypeRegistry, configurationWriter);
-        this.schemaContextRegistration = this.schemaService.registerSchemaContextListener(this.ribImpl);
+    synchronized void start(final Global global, final String instanceName,
+            final BGPTableTypeRegistryConsumer tableTypeRegistry) {
+        checkState(ribImpl == null, "Previous instance %s was not closed.", this);
+        LOG.info("Starting BGP instance {}", instanceName);
+        ribId = new RibId(instanceName);
+        ribImpl = createRib(global, tableTypeRegistry);
+        stateProviderRegistration =  stateProviderRegistry.register(this);
     }
 
-    Boolean isGlobalEqual(final Global global) {
-        final List<AfiSafi> globalAfiSafi = getAfiSafiWithDefault(global.getAfiSafis(), true);
+    synchronized ListenableFuture<?> stop() {
+        if (ribImpl == null) {
+            LOG.info("RIB instance {} already closed, skipping", ribId);
+            return Futures.immediateVoidFuture();
+        }
+
+        LOG.info("Closing RIB instance {}", ribId);
+        if (stateProviderRegistration != null) {
+            LOG.info("Unregistering state provider for RIB instance {}", ribId);
+            stateProviderRegistration.close();
+            stateProviderRegistration = null;
+        }
+
+        final var future = ribImpl.closeServiceInstance();
+        ribImpl = null;
+        return future;
+    }
+
+    synchronized boolean isGlobalEqual(final Global global) {
+        final Collection<AfiSafi> globalAfiSafi = getAfiSafiWithDefault(global.getAfiSafis(), true).values();
         final Config globalConfig = global.getConfig();
         final AsNumber globalAs = globalConfig.getAs();
         final Ipv4Address globalRouterId = global.getConfig().getRouterId();
-        final ClusterIdentifier globalClusterId = OpenConfigMappingUtil.getClusterIdentifier(globalConfig);
-        return this.afiSafi.containsAll(globalAfiSafi) && globalAfiSafi.containsAll(this.afiSafi)
-            && globalAs.equals(this.asNumber)
-            && globalRouterId.getValue().equals(this.routerId.getValue())
-            && globalClusterId.getValue().equals(this.clusterId.getValue());
+        final ClusterIdentifier globalClusterId = getGlobalClusterIdentifier(globalConfig);
+        return afiSafi.containsAll(globalAfiSafi) && globalAfiSafi.containsAll(afiSafi)
+                && globalAs.equals(asNumber)
+                && globalRouterId.getValue().equals(routerId.getValue())
+                && globalClusterId.getValue().equals(clusterId.getValue());
     }
 
     @Override
-    public KeyedInstanceIdentifier<Rib, RibKey> getInstanceIdentifier() {
-        return this.ribImpl.getInstanceIdentifier();
+    public synchronized KeyedInstanceIdentifier<Rib, RibKey> getInstanceIdentifier() {
+        return ribImpl.getInstanceIdentifier();
     }
 
     @Override
-    public AsNumber getLocalAs() {
-        return this.ribImpl.getLocalAs();
+    public synchronized AsNumber getLocalAs() {
+        return ribImpl.getLocalAs();
     }
 
     @Override
-    public BgpId getBgpIdentifier() {
-        return this.ribImpl.getBgpIdentifier();
+    public synchronized BgpId getBgpIdentifier() {
+        return ribImpl.getBgpIdentifier();
     }
 
     @Override
-    public Set<? extends BgpTableType> getLocalTables() {
-        return this.ribImpl.getLocalTables();
+    public synchronized Set<? extends BgpTableType> getLocalTables() {
+        return ribImpl.getLocalTables();
     }
 
     @Override
-    public BGPDispatcher getDispatcher() {
-        return this.ribImpl.getDispatcher();
+    public synchronized BGPDispatcher getDispatcher() {
+        return ribImpl.getDispatcher();
     }
 
     @Override
-    public DOMTransactionChain createPeerChain(final TransactionChainListener listener) {
-        return this.ribImpl.createPeerChain(listener);
+    public synchronized DOMTransactionChain createPeerDOMChain() {
+        return ribImpl.createPeerDOMChain();
     }
 
     @Override
-    public RIBExtensionConsumerContext getRibExtensions() {
-        return this.ribImpl.getRibExtensions();
+    public synchronized RIBExtensionConsumerContext getRibExtensions() {
+        return ribImpl.getRibExtensions();
     }
 
     @Override
-    public RIBSupportContextRegistry getRibSupportContext() {
-        return this.ribImpl.getRibSupportContext();
+    public synchronized RIBSupportContextRegistry getRibSupportContext() {
+        return ribImpl.getRibSupportContext();
     }
 
     @Override
-    public YangInstanceIdentifier getYangRibId() {
-        return this.ribImpl.getYangRibId();
+    public synchronized YangInstanceIdentifier getYangRibId() {
+        return ribImpl.getYangRibId();
     }
 
     @Override
-    public CodecsRegistry getCodecsRegistry() {
-        return this.ribImpl.getCodecsRegistry();
+    public synchronized CodecsRegistry getCodecsRegistry() {
+        return ribImpl.getCodecsRegistry();
     }
 
     @Override
-    public DOMDataTreeChangeService getService() {
-        return this.ribImpl.getService();
+    public synchronized DataTreeChangeExtension getService() {
+        return ribImpl.getService();
     }
 
-    @Override
-    public void close() {
-        if (this.ribImpl != null) {
-            try {
-                this.ribImpl.close();
-            } catch (final Exception e) {
-                LOG.warn("Failed to close {} rib instance", this, e);
-            }
-            this.ribImpl = null;
-        }
-        if (this.schemaContextRegistration != null) {
-            this.schemaContextRegistration.close();
-            this.schemaContextRegistration = null;
-        }
-        if (this.serviceRegistration != null) {
-            try {
-                this.serviceRegistration.unregister();
-            } catch(final IllegalStateException e) {
-                LOG.warn("Failed to unregister {} service instance", this, e);
-            }
-            this.serviceRegistration = null;
+    synchronized FluentFuture<? extends CommitInfo> closeServiceInstance() {
+        if (ribImpl != null) {
+            return ribImpl.closeServiceInstance();
         }
+        return CommitInfo.emptyFluentFuture();
     }
 
-    void setServiceRegistration(final ServiceRegistration<?> serviceRegistration) {
-        this.serviceRegistration = serviceRegistration;
+    @Override
+    public synchronized Set<TablesKey> getLocalTablesKeys() {
+        return ribImpl.getLocalTablesKeys();
     }
 
     @Override
-    public BGPRenderStats getRenderStats() {
-        return this.ribImpl.getRenderStats();
+    public synchronized boolean supportsTable(final TablesKey tableKey) {
+        return ribImpl.supportsTable(tableKey);
     }
 
     @Override
-    public ImportPolicyPeerTracker getImportPolicyPeerTracker() {
-        return this.ribImpl.getImportPolicyPeerTracker();
+    public synchronized BGPRibRoutingPolicy getRibPolicies() {
+        return ribImpl.getRibPolicies();
     }
 
     @Override
-    public ExportPolicyPeerTracker getExportPolicyPeerTracker(final TablesKey tablesKey) {
-        return this.ribImpl.getExportPolicyPeerTracker(tablesKey);
+    public synchronized BGPPeerTracker getPeerTracker() {
+        return ribImpl.getPeerTracker();
     }
 
     @Override
-    public Set<TablesKey> getLocalTablesKeys() {
-        return this.ribImpl.getLocalTablesKeys();
+    public synchronized String toString() {
+        return ribImpl != null ? ribImpl.toString() : "";
     }
 
-    @Override
-    public ServiceGroupIdentifier getRibIServiceGroupIdentifier() {
-        return this.ribImpl.getRibIServiceGroupIdentifier();
+    private synchronized RIBImpl createRib(
+            final Global global,
+            final BGPTableTypeRegistryConsumer tableTypeRegistry) {
+        afiSafi = getAfiSafiWithDefault(global.getAfiSafis(), true).values();
+        final Config globalConfig = global.getConfig();
+        asNumber = globalConfig.getAs();
+        routerId = IetfInetUtil.ipv4AddressNoZoneFor(globalConfig.getRouterId());
+        clusterId = getGlobalClusterIdentifier(globalConfig);
+        final Map<TablesKey, PathSelectionMode> pathSelectionModes = OpenConfigMappingUtil
+                .toPathSelectionMode(afiSafi, tableTypeRegistry).entrySet()
+                .stream()
+                .collect(Collectors.toMap(entry ->
+                        new TablesKey(entry.getKey().getAfi(), entry.getKey().getSafi()), Map.Entry::getValue));
+
+        final BGPRibRoutingPolicy ribPolicy = policyProvider.buildBGPRibPolicy(asNumber.getValue().toJava(),
+                routerId, clusterId, RoutingPolicyUtil.getApplyPolicy(global.getApplyPolicy()));
+
+        return new RIBImpl(
+                tableTypeRegistry,
+                ribId,
+                asNumber,
+                new BgpId(routerId),
+                extensionProvider,
+                dispatcher,
+                codecsRegistry,
+                domBroker,
+                ribPolicy,
+                toTableTypes(afiSafi, tableTypeRegistry),
+                pathSelectionModes);
     }
 
     @Override
-    public String toString() {
-        return this.ribImpl != null ? this.ribImpl.toString() : null;
+    public synchronized BGPRibState getRIBState() {
+        return ribImpl.getRIBState();
     }
 
-    private RIBImpl createRib(final ClusterSingletonServiceProvider provider, final Global global, final String bgpInstanceName,
-        final BGPTableTypeRegistryConsumer tableTypeRegistry, final BgpDeployer.WriteConfiguration configurationWriter) {
-        this.afiSafi = getAfiSafiWithDefault(global.getAfiSafis(), true);
-        final Config globalConfig = global.getConfig();
-        this.asNumber = globalConfig.getAs();
-        this.routerId = globalConfig.getRouterId();
-        this.clusterId = OpenConfigMappingUtil.getClusterIdentifier(globalConfig);
-        final Map<TablesKey, PathSelectionMode> pathSelectionModes = OpenConfigMappingUtil.toPathSelectionMode(this.afiSafi, tableTypeRegistry).entrySet()
-                .stream().collect(Collectors.toMap(entry -> new TablesKey(entry.getKey().getAfi(), entry.getKey().getSafi()), Map.Entry::getValue));
-        return new RIBImpl(provider, new RibId(bgpInstanceName), this.asNumber, new BgpId(this.routerId), this.clusterId,
-                this.extensions, this.dispatcher, this.codecTreeFactory, this.domBroker, OpenConfigMappingUtil.toTableTypes(this.afiSafi, tableTypeRegistry), pathSelectionModes,
-                this.extensions.getClassLoadingStrategy(), configurationWriter);
+    public synchronized void instantiateServiceInstance() {
+        if (ribImpl != null) {
+            ribImpl.instantiateServiceInstance();
+        }
     }
 
     @Override
-    public ClusterSingletonServiceRegistration registerClusterSingletonService(final ClusterSingletonService clusterSingletonService) {
-        return this.ribImpl.registerClusterSingletonService(clusterSingletonService);
+    public synchronized void refreshTable(final TablesKey tk, final PeerId peerId) {
+        ribImpl.refreshTable(tk, peerId);
     }
 }