From c89c6d750fd4e3c9e93427b9a863a6e3c146bfdb Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Sat, 15 Feb 2014 07:36:09 +0100 Subject: [PATCH] Disconnect node statistics tracking 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 --- .../manager/MultipartMessageManager.java | 15 ++++++----- .../manager/NodeStatisticsHandler.java | 24 ++++++++++++++--- .../manager/StatisticsProvider.java | 27 +------------------ 3 files changed, 30 insertions(+), 36 deletions(-) diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MultipartMessageManager.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MultipartMessageManager.java index 257684a400..56b205216f 100644 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MultipartMessageManager.java +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MultipartMessageManager.java @@ -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 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() { diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeStatisticsHandler.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeStatisticsHandler.java index ecf2cf3665..6796b4eb87 100644 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeStatisticsHandler.java +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeStatisticsHandler.java @@ -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 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(); diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java index 8ffa5d6732..892d304daa 100644 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java @@ -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 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()); } -- 2.36.6