Disconnect node statistics tracking 46/5346/1
authorRobert Varga <rovarga@cisco.com>
Sat, 15 Feb 2014 06:36:09 +0000 (07:36 +0100)
committerRobert Varga <rovarga@cisco.com>
Sat, 15 Feb 2014 07:19:25 +0000 (08:19 +0100)
This patch moves scheduling into the node handlers themselves. This
should allow for spreading out of the statistics collection, preventing
spikes. Additionally delay the initial collection by up to 5 seconds to
deal with multiple switches connecting at the same time.

Change-Id: I6ea039b405595b3756263bddd9cf8997bc73a038
Signed-off-by: Robert Varga <rovarga@cisco.com>
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MultipartMessageManager.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeStatisticsHandler.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java

index 257684a400b0b36d53844b1f090047db55f14f3f..56b205216f2b8768fe66606808ec83c7906859e8 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.controller.md.statistics.manager;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeUnit;
 
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
@@ -24,9 +23,7 @@ import com.google.common.base.Preconditions;
  * @author avishnoi@in.ibm.com
  *
  */
-public class MultipartMessageManager {
-    private static final int NUMBER_OF_WAIT_CYCLES = 2;
-
+class MultipartMessageManager {
     /*
      *  Map for tx id and type of request, to keep track of all the request sent
      *  by Statistics Manager. Statistics Manager won't entertain any multipart
@@ -38,6 +35,11 @@ public class MultipartMessageManager {
      * Because flow table statistics multi part response do not contains the table id.
      */
     private final Map<TxIdEntry,Short> txIdTotableIdMap = new ConcurrentHashMap<>();
+    private final long lifetimeNanos;
+
+    public MultipartMessageManager(long lifetimeNanos) {
+        this.lifetimeNanos = lifetimeNanos;
+    }
 
     private static final class TxIdEntry {
         private final TransactionId txId;
@@ -116,9 +118,8 @@ public class MultipartMessageManager {
         }
     }
 
-    private static Long getExpiryTime(){
-        return System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(
-                StatisticsProvider.STATS_COLLECTION_MILLIS*NUMBER_OF_WAIT_CYCLES);
+    private Long getExpiryTime() {
+        return System.nanoTime() + lifetimeNanos;
     }
 
     public void cleanStaleTransactionIds() {
index ecf2cf366591bc1f7383981c52957741d42cc669..6796b4eb8723d02064d31a56bfa479c9412a4246 100644 (file)
@@ -9,6 +9,8 @@ package org.opendaylight.controller.md.statistics.manager;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
 import java.util.concurrent.TimeUnit;
 
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
@@ -65,9 +67,12 @@ import com.google.common.base.Preconditions;
  */
 public final class NodeStatisticsHandler implements AutoCloseable, FlowCapableContext {
     private static final Logger logger = LoggerFactory.getLogger(NodeStatisticsHandler.class);
+
+    private static final long STATS_COLLECTION_MILLIS = TimeUnit.SECONDS.toMillis(15);
+    private static final long FIRST_COLLECTION_MILLIS = TimeUnit.SECONDS.toMillis(5);
     private static final int NUMBER_OF_WAIT_CYCLES = 2;
 
-    private final MultipartMessageManager msgManager = new MultipartMessageManager();
+    private final MultipartMessageManager msgManager;
     private final InstanceIdentifier<Node> targetNodeIdentifier;
     private final FlowStatsTracker flowStats;
     private final FlowTableStatsTracker flowTableStats;
@@ -80,6 +85,13 @@ public final class NodeStatisticsHandler implements AutoCloseable, FlowCapableCo
     private final DataProviderService dps;
     private final NodeRef targetNodeRef;
     private final NodeKey targetNodeKey;
+    private final TimerTask task = new TimerTask() {
+        @Override
+        public void run() {
+            requestPeriodicStatistics();
+            cleanStaleStatistics();
+        }
+    };
 
     public NodeStatisticsHandler(final DataProviderService dps, final NodeKey nodeKey,
             final OpendaylightFlowStatisticsService flowStatsService,
@@ -93,8 +105,9 @@ public final class NodeStatisticsHandler implements AutoCloseable, FlowCapableCo
         this.targetNodeIdentifier = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey).build();
         this.targetNodeRef = new NodeRef(targetNodeIdentifier);
 
-        final long lifetimeNanos = TimeUnit.MILLISECONDS.toNanos(StatisticsProvider.STATS_COLLECTION_MILLIS * NUMBER_OF_WAIT_CYCLES);
+        final long lifetimeNanos = TimeUnit.MILLISECONDS.toNanos(STATS_COLLECTION_MILLIS * NUMBER_OF_WAIT_CYCLES);
 
+        msgManager = new MultipartMessageManager(lifetimeNanos);
         flowStats = new FlowStatsTracker(flowStatsService, this, lifetimeNanos);
         flowTableStats = new FlowTableStatsTracker(flowTableStatsService, this, lifetimeNanos);
         groupDescStats = new GroupDescStatsTracker(groupStatsService, this, lifetimeNanos);
@@ -271,7 +284,7 @@ public final class NodeStatisticsHandler implements AutoCloseable, FlowCapableCo
         queueStats.request();
     }
 
-    public synchronized void start() {
+    public synchronized void start(final Timer timer) {
         flowStats.start(dps);
         groupDescStats.start(dps);
         groupStats.start(dps);
@@ -279,11 +292,16 @@ public final class NodeStatisticsHandler implements AutoCloseable, FlowCapableCo
         meterStats.start(dps);
         queueStats.start(dps);
 
+        timer.schedule(task, (long) (Math.random() * FIRST_COLLECTION_MILLIS), STATS_COLLECTION_MILLIS);
+
+        logger.debug("Statistics handler for node started with base interval {}ms", STATS_COLLECTION_MILLIS);
+
         requestPeriodicStatistics();
     }
 
     @Override
     public synchronized void close() {
+        task.cancel();
         flowStats.close();
         groupDescStats.close();
         groupStats.close();
index 8ffa5d673269f06954c70cffd483d5fa893e540d..892d304daa8d6cd20c7010082f2698cb8de90266 100644 (file)
@@ -9,10 +9,8 @@ package org.opendaylight.controller.md.statistics.manager;
 
 import java.util.Collection;
 import java.util.Timer;
-import java.util.TimerTask;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.TimeUnit;
 
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
 import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
@@ -51,8 +49,6 @@ import com.google.common.base.Preconditions;
  *
  */
 public class StatisticsProvider implements AutoCloseable {
-    public static final long STATS_COLLECTION_MILLIS = TimeUnit.SECONDS.toMillis(15);
-
     private static final Logger spLogger = LoggerFactory.getLogger(StatisticsProvider.class);
 
     private final ConcurrentMap<NodeId, NodeStatisticsHandler> handlers = new ConcurrentHashMap<>();
@@ -101,27 +97,6 @@ public class StatisticsProvider implements AutoCloseable {
         this.flowCapableTrackerRegistration = dps.registerDataChangeListener(fcnId,
                 new FlowCapableTracker(this, fcnId));
 
-        timer.schedule(new TimerTask() {
-            @Override
-            public void run() {
-                try {
-                    // Send stats requests
-                    for (NodeStatisticsHandler h : handlers.values()) {
-                        h.requestPeriodicStatistics();
-                    }
-
-                    // Perform cleanup
-                    for(NodeStatisticsHandler nodeStatisticsAger : handlers.values()){
-                        nodeStatisticsAger.cleanStaleStatistics();
-                    }
-
-                } catch (RuntimeException e) {
-                    spLogger.warn("Failed to request statistics", e);
-                }
-            }
-        }, 0, STATS_COLLECTION_MILLIS);
-
-        spLogger.debug("Statistics timer task with timer interval : {}ms", STATS_COLLECTION_MILLIS);
         spLogger.info("Statistics Provider started.");
     }
 
@@ -173,7 +148,7 @@ public class StatisticsProvider implements AutoCloseable {
             final NodeStatisticsHandler old = handlers.putIfAbsent(key.getId(), h);
             if (old == null) {
                 spLogger.debug("Started node handler for {}", key.getId());
-                h.start();
+                h.start(timer);
             } else {
                 spLogger.debug("Prevented race on handler for {}", key.getId());
             }