Move stats update timer 52/101952/8
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 3 Aug 2022 09:36:00 +0000 (11:36 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Fri, 5 Aug 2022 15:55:43 +0000 (17:55 +0200)
Update interval is a global tuneable, but we really want it to be
adjustable on per-topology basis. Move the definition and update it
route it towards scheduler.

JIRA: BGPCEP-1011
Change-Id: Ia6946782b91da964409d1c7786253fb6c7648460
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
pcep/topology/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/AbstractTopologySessionListener.java
pcep/topology/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/PCEPTopologyConfiguration.java
pcep/topology/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/PCEPTopologyProvider.java
pcep/topology/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/PCEPTopologyTracker.java
pcep/topology/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/ServerSessionManager.java
pcep/topology/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/SessionStateUpdater.java
pcep/topology/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/TopologySessionStats.java
pcep/topology/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/TopologyStatsProvider.java
pcep/topology/topology-provider/src/main/resources/OSGI-INF/blueprint/pcep-topology.xml
pcep/topology/topology-provider/src/main/yang/odl-pcep-stats-provider.yang
pcep/topology/topology-provider/src/test/java/org/opendaylight/bgpcep/pcep/topology/provider/AbstractPCEPSessionTest.java

index 81c7836c4631dd52472eeccb0e734640034c7e47..7678e405ce691274e433f52224739b7799778045 100644 (file)
@@ -675,6 +675,11 @@ public abstract class AbstractTopologySessionListener implements TopologySession
             .count());
     }
 
+    @Override
+    public final long updateInterval() {
+        return serverSessionManager.updateInterval();
+    }
+
     @Override
     public final boolean isSessionSynchronized() {
         return synced.get();
index 56706d44551b3955d07bbf1327deeb81da737034..0692fa79c345cd82129a8b197a3a2abbae423628 100644 (file)
@@ -14,6 +14,7 @@ import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.protocol.concepts.KeyMapping;
@@ -21,6 +22,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.GraphKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.pcep.stats.provider.config.rev220730.TopologyPcep1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.Node1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.TopologyTypes1;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
@@ -29,17 +31,21 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 import org.opendaylight.yangtools.concepts.Immutable;
 
 final class PCEPTopologyConfiguration implements Immutable {
+    private static final long DEFAULT_UPDATE_INTERVAL = TimeUnit.SECONDS.toNanos(5);
+
     private final @NonNull InetSocketAddress address;
+    private final @NonNull GraphKey graphKey;
     private final @NonNull KeyMapping keys;
+    private final long updateIntervalNanos;
     private final short rpcTimeout;
-    private final GraphKey graphKey;
 
-    PCEPTopologyConfiguration(final @NonNull InetSocketAddress address, final short rpcTimeout,
-            final @NonNull KeyMapping keys, final @NonNull GraphKey graphKey) {
+    PCEPTopologyConfiguration(final @NonNull InetSocketAddress address, final @NonNull KeyMapping keys,
+            final @NonNull GraphKey graphKey, final short rpcTimeout, final long updateIntervalNanos) {
         this.address = requireNonNull(address);
         this.keys = requireNonNull(keys);
-        this.rpcTimeout = rpcTimeout;
         this.graphKey = requireNonNull(graphKey);
+        this.rpcTimeout = rpcTimeout;
+        this.updateIntervalNanos = updateIntervalNanos;
     }
 
     static @Nullable PCEPTopologyConfiguration of(final @NonNull Topology topology) {
@@ -60,16 +66,24 @@ final class PCEPTopologyConfiguration implements Immutable {
             return null;
         }
 
+        final var updateAug = topologyPcep.augmentation(TopologyPcep1.class);
+        final long updateInterval = updateAug != null ? TimeUnit.SECONDS.toNanos(updateAug.requireTimer().toJava())
+            : DEFAULT_UPDATE_INTERVAL;
+
         return new PCEPTopologyConfiguration(
             getInetSocketAddress(sessionConfig.getListenAddress(), sessionConfig.getListenPort()),
-            sessionConfig.getRpcTimeout(), constructKeys(topology.getNode()),
-            constructGraphKey(sessionConfig.getTedName()));
+            constructKeys(topology.getNode()), constructGraphKey(sessionConfig.getTedName()),
+            sessionConfig.getRpcTimeout(), updateInterval);
     }
 
     short getRpcTimeout() {
         return rpcTimeout;
     }
 
+    long getUpdateInterval() {
+        return updateIntervalNanos;
+    }
+
     @NonNull InetSocketAddress getAddress() {
         return address;
     }
@@ -96,7 +110,7 @@ final class PCEPTopologyConfiguration implements Immutable {
                     if (sessionConfig != null) {
                         final var rfc2385KeyPassword = sessionConfig.getPassword();
                         if (rfc2385KeyPassword != null) {
-                            final String password = rfc2385KeyPassword.getValue();
+                            final var password = rfc2385KeyPassword.getValue();
                             if (!password.isEmpty()) {
                                 passwords.put(nodeAddress(node), password);
                             }
index a59584deeafa73e2856ffb8b6dbe814ce6fef067..7eed9488b6d156bb0fd6cb1b396d49c4aafeb319 100644 (file)
@@ -152,6 +152,7 @@ final class PCEPTopologyProvider extends DefaultTopologyReference {
             .collect(Collectors.toUnmodifiableList());
 
         manager.setRpcTimeout(newConfiguration.getRpcTimeout());
+        manager.setUpdateInterval(newConfiguration.getUpdateInterval());
         if (!outdatedNodes.isEmpty()) {
             LOG.info("Topology Provider {} updating {} TCP-MD5 keys", topologyId(), outdatedNodes.size());
             if (channel.config().setOption(EpollChannelOption.TCP_MD5SIG, newKeys)) {
@@ -172,8 +173,8 @@ final class PCEPTopologyProvider extends DefaultTopologyReference {
         currentConfig = newConfiguration;
 
         // First start the manager
-        manager = new ServerSessionManager(instanceIdentifier, dependencies, newConfiguration.getRpcTimeout(),
-                newConfiguration.getGraphKey());
+        manager = new ServerSessionManager(instanceIdentifier, dependencies, newConfiguration.getGraphKey(),
+            newConfiguration.getRpcTimeout(), newConfiguration.getUpdateInterval());
         final var managerStart = manager.start();
         managerStart.addListener(() -> enableChannel(future, Futures.getUnchecked(managerStart)),
             MoreExecutors.directExecutor());
index 70a164369237c1f58d858e4ed902c7acc150a6be..8dac0d97fce8df58082fc7ff20d7708678a9d375 100644 (file)
@@ -106,15 +106,14 @@ public final class PCEPTopologyTracker
 
     public PCEPTopologyTracker(final DataBroker dataBroker, final ClusterSingletonServiceProvider singletonService,
             final RpcProviderService rpcProviderRegistry, final PCEPDispatcher pcepDispatcher,
-            final InstructionSchedulerFactory instructionSchedulerFactory, final PceServerProvider pceServerProvider,
-            final int updateIntervalSeconds) {
+            final InstructionSchedulerFactory instructionSchedulerFactory, final PceServerProvider pceServerProvider) {
         this.dataBroker = requireNonNull(dataBroker);
         this.singletonService = requireNonNull(singletonService);
         this.rpcProviderRegistry = requireNonNull(rpcProviderRegistry);
         this.pcepDispatcher = requireNonNull(pcepDispatcher);
         this.instructionSchedulerFactory = requireNonNull(instructionSchedulerFactory);
         this.pceServerProvider = requireNonNull(pceServerProvider);
-        statsProvider = new TopologyStatsProvider(timer, updateIntervalSeconds);
+        statsProvider = new TopologyStatsProvider(timer);
         statsRpcs = new TopologyStatsRpcServiceImpl(dataBroker);
         statsReg = rpcProviderRegistry.registerRpcImplementation(PcepTopologyStatsRpcService.class, statsRpcs);
 
index 502488774ef8736f300a0cdedd21b1a757e84570..a51bf285e12117ec6d0a918148d726c7743fbff4 100644 (file)
@@ -82,15 +82,18 @@ class ServerSessionManager implements PCEPSessionListenerFactory, TopologySessio
     @GuardedBy("this")
     private final Map<NodeId, TopologyNodeState> state = new HashMap<>();
 
+    private volatile long updateInterval;
     private volatile short rpcTimeout;
     private volatile boolean closed;
 
     ServerSessionManager(final KeyedInstanceIdentifier<Topology, TopologyKey> topology,
-            final PCEPTopologyProviderDependencies dependencies, final short rpcTimeout, final GraphKey graphKey) {
+            final PCEPTopologyProviderDependencies dependencies, final GraphKey graphKey,
+            final short rpcTimeout, final long updateInterval) {
         this.dependencies = requireNonNull(dependencies);
         this.topology = requireNonNull(topology);
-        this.rpcTimeout = rpcTimeout;
         this.graphKey = requireNonNull(graphKey);
+        this.rpcTimeout = rpcTimeout;
+        this.updateInterval = updateInterval;
     }
 
     // Initialize the operational view of the topology.
@@ -287,10 +290,18 @@ class ServerSessionManager implements PCEPSessionListenerFactory, TopologySessio
             : dependencies.getTimer().newTimeout(ignored -> task.run(requestId), localTimeout, TimeUnit.SECONDS);
     }
 
+    final long updateInterval() {
+        return isClosed() ? 0 : updateInterval;
+    }
+
     final void setRpcTimeout(final short rpcTimeout) {
         this.rpcTimeout = rpcTimeout;
     }
 
+    final void setUpdateInterval(final long updateInterval) {
+        this.updateInterval = updateInterval;
+    }
+
     final void tearDownSessions(final List<InetAddress> outdatedNodes) {
         for (var address : outdatedNodes) {
             tearDownSession(new TearDownSessionInputBuilder().setNode(createNodeId(address)).build());
index 0f174920fa42f5a8d4fe7fe5c8ff17da53aeef93..e39e9766b8f6b08941cf13d2076d9ff4fbf4c4f6 100644 (file)
@@ -99,6 +99,10 @@ final class SessionStateUpdater {
         return null;
     }
 
+    long updateInterval() {
+        return topologySessionStats.updateInterval();
+    }
+
     @NonNull FluentFuture<? extends @NonNull CommitInfo> updateStatistics() {
         // Lockless
         final var aug = new PcepTopologyNodeStatsAugBuilder().setPcepSessionState(toPcepSessionState()).build();
index 32abf416f74d25a94c7fcdee8b4c727f69d8adf6..7d06121de5f06e50705d5e5c5bcc8bbf013a208e 100644 (file)
@@ -8,14 +8,10 @@
 
 package org.opendaylight.bgpcep.pcep.topology.provider;
 
-import com.google.common.annotations.Beta;
-
 /**
  * Provide access to topology session stats without expose variables.
  */
-@Beta
-public interface TopologySessionStats {
-
+interface TopologySessionStats {
     /**
      * Returns true if session is synchronized.
      *
@@ -50,4 +46,6 @@ public interface TopologySessionStats {
      * @return status
      */
     int getDelegatedLspsCount();
+
+    long updateInterval();
 }
index c53ade83c30679ed1fc3879bf25ce09dbcf25407..42036bbd4572e3163201744b6ce8c1abfed702c2 100644 (file)
@@ -7,7 +7,6 @@
  */
 package org.opendaylight.bgpcep.pcep.topology.provider;
 
-import static com.google.common.base.Preconditions.checkArgument;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.base.Stopwatch;
@@ -39,20 +38,16 @@ final class TopologyStatsProvider implements SessionStateRegistry {
 
     private final Set<Task> tasks = ConcurrentHashMap.newKeySet();
     private final ExecutorService executor;
-    private final long updateIntervalNanos;
     private final Timer timer;
 
-    TopologyStatsProvider(final Timer timer, final int updateIntervalSeconds) {
+    TopologyStatsProvider(final Timer timer) {
         this.timer = requireNonNull(timer);
-        updateIntervalNanos = TimeUnit.SECONDS.toNanos(updateIntervalSeconds);
-        checkArgument(updateIntervalNanos > 0, "Invalid update interval %s", updateIntervalNanos);
-
         executor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder()
             .setDaemon(true)
             .setNameFormat("odl-pcep-stats-%d")
             .build());
 
-        LOG.info("TopologyStatsProvider updating every {} seconds", updateIntervalSeconds);
+        LOG.info("TopologyStatsProvider started");
     }
 
     void shutdown() {
@@ -96,7 +91,13 @@ final class TopologyStatsProvider implements SessionStateRegistry {
 
         Task(final @NonNull SessionStateUpdater instance) {
             super(instance);
-            state = timer.newTimeout(this, updateIntervalNanos, TimeUnit.NANOSECONDS);
+
+            final long updateInterval = instance.updateInterval();
+            if (updateInterval > 0) {
+                state = timer.newTimeout(this, updateInterval, TimeUnit.NANOSECONDS);
+            } else {
+                LOG.debug("Task {} has non-positive interval {}, not scheduling it", this, updateInterval);
+            }
         }
 
         @Override
@@ -157,11 +158,16 @@ final class TopologyStatsProvider implements SessionStateRegistry {
                 return;
             }
 
-            long remainingNanos = updateIntervalNanos - elapsedNanos;
-            if (remainingNanos < 0) {
-                remainingNanos = updateIntervalNanos;
+            final var updateInterval = getInstance().updateInterval();
+            if (updateInterval > 0) {
+                long remainingNanos = updateInterval - elapsedNanos;
+                if (remainingNanos < 0) {
+                    remainingNanos = updateInterval;
+                }
+                state = timer.newTimeout(this, remainingNanos, TimeUnit.NANOSECONDS);
+            } else {
+                LOG.debug("Task {} has non-positive interval {}, skipping reschedule", this, updateInterval);
             }
-            state = timer.newTimeout(this, remainingNanos, TimeUnit.NANOSECONDS);
         }
 
         @Override
index 91a525fd7d681e87b2b16b5b4aace3d347a9cc2e..737edb43483e07afef7ffa41a08a94f2e2902546 100644 (file)
@@ -6,8 +6,7 @@
   terms of the Eclipse Public License v1.0 which accompanies this distribution,
   and is available at http://www.eclipse.org/legal/epl-v10.html
 -->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
-           xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0">
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
     <reference id="dataBroker" interface="org.opendaylight.mdsal.binding.api.DataBroker"/>
     <reference id="rpcProviderService" interface="org.opendaylight.mdsal.binding.api.RpcProviderService"/>
     <reference id="pcepDispatcher" interface="org.opendaylight.protocol.pcep.PCEPDispatcher"/>
@@ -16,9 +15,6 @@
     <reference id="intructionFactory" interface="org.opendaylight.bgpcep.programming.spi.InstructionSchedulerFactory"/>
     <reference id="pceServerProvider" interface="org.opendaylight.bgpcep.pcep.server.PceServerProvider"/>
 
-    <odl:clustered-app-config id="pcepStatsConfig"
-        binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.pcep.stats.provider.config.rev171113.PcepProvider"/>
-
     <bean id="pcepTopologyTracker"
           class="org.opendaylight.bgpcep.pcep.topology.provider.PCEPTopologyTracker"
           destroy-method="close">
@@ -28,8 +24,5 @@
         <argument ref="pcepDispatcher"/>
         <argument ref="intructionFactory"/>
         <argument ref="pceServerProvider"/>
-        <argument>
-            <bean factory-ref="pcepStatsConfig" factory-method="getTimer"/>
-        </argument>
     </bean>
 </blueprint>
index fc69144932f3c136642331f4ef2acf78f731987a..3aad699ca3e6d3a8de579b1fd768320af5fee497 100644 (file)
@@ -4,6 +4,9 @@ module odl-pcep-stats-provider {
     namespace "urn:opendaylight:params:xml:ns:yang:odl:pcep:stats:provider:config";
     prefix pspc;
 
+    import network-topology { prefix nt; revision-date 2013-10-21; }
+    import network-topology-pcep { prefix pn; revision-date 2022-07-30; }
+
     description
         "This module contains the base YANG definitions for
          PCEP Stats Provider Configuration.
@@ -14,21 +17,23 @@ module odl-pcep-stats-provider {
          accompanies this distribution, and is available at
          http://www.eclipse.org/legal/epl-v10.html";
 
+    revision "2022-07-30" {
+        description
+            "Integrated with PCEP network topology";
+    }
+
     revision "2017-11-13" {
         description
             "Initial revision.";
     }
 
-    container pcep-provider {
-        leaf config-name {
-            type string;
-            mandatory true;
-        }
-
+    augment "/nt:network-topology/nt:topology/nt:topology-types/pn:topology-pcep" {
         leaf timer {
-            type uint16;
+            type uint16 {
+                range 1..max;
+            }
             default 5;
             units "seconds";
         }
     }
-}
\ No newline at end of file
+}
index c89e3149e0ff32335aa26dfdb9fdd7356f4b2873..56b09f58dada5abecfea3e0d48305164a6416eca 100644 (file)
@@ -135,8 +135,8 @@ public abstract class AbstractPCEPSessionTest extends AbstractConcurrentDataBrok
         doReturn(timer).when(topologyDependencies).getTimer();
         doReturn(null).when(topologyDependencies).getPceServerProvider();
 
-        manager = customizeSessionManager(new ServerSessionManager(TOPO_IID, topologyDependencies, RPC_TIMEOUT,
-                new GraphKey("graph-test")));
+        manager = customizeSessionManager(new ServerSessionManager(TOPO_IID, topologyDependencies,
+                new GraphKey("graph-test"), RPC_TIMEOUT, TimeUnit.SECONDS.toNanos(5)));
         startSessionManager();
         neg = new DefaultPCEPSessionNegotiator(promise, clientListener, manager.getSessionListener(), (short) 1, 5,
             localPrefs);