Use a single Timer instead of two threads
[controller.git] / opendaylight / md-sal / statistics-manager / src / main / java / org / opendaylight / controller / md / statistics / manager / NodeStatisticsHandler.java
index 6d0b5ea0e31bdb75046ff157071a4ded54bfcaa7..326da07c7321e388ac0aa615a73729f85c9a4e53 100644 (file)
@@ -7,14 +7,19 @@
  */
 package org.opendaylight.controller.md.statistics.manager;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
@@ -60,6 +65,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
@@ -103,7 +109,7 @@ import com.google.common.base.Preconditions;
  *
  * @author avishnoi@in.ibm.com
  */
-public class NodeStatisticsHandler {
+public final class NodeStatisticsHandler implements AutoCloseable {
     private static final Logger logger = LoggerFactory.getLogger(NodeStatisticsHandler.class);
     private static final int NUMBER_OF_WAIT_CYCLES = 2;
 
@@ -112,17 +118,20 @@ public class NodeStatisticsHandler {
     private final Map<FlowEntry,Long> flowStatsUpdate = new HashMap<>();
     private final Map<QueueEntry,Long> queuesStatsUpdate = new HashMap<>();
     private final InstanceIdentifier<Node> targetNodeIdentifier;
-    private final StatisticsProvider statisticsProvider;
+    private final DataProviderService dps;
+    private final NodeRef targetNodeRef;
     private final NodeKey targetNodeKey;
+    private Collection<TableKey> knownTables = Collections.emptySet();
     private int unaccountedFlowsCounter = 1;
 
-    public NodeStatisticsHandler(StatisticsProvider statisticsProvider, NodeKey nodeKey){
-        this.statisticsProvider = Preconditions.checkNotNull(statisticsProvider);
+    public NodeStatisticsHandler(final DataProviderService dps, final NodeKey nodeKey) {
+        this.dps = Preconditions.checkNotNull(dps);
         this.targetNodeKey = Preconditions.checkNotNull(nodeKey);
         this.targetNodeIdentifier = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey).build();
+        this.targetNodeRef = new NodeRef(targetNodeIdentifier);
     }
 
-    public class FlowEntry {
+    private static class FlowEntry {
         private final Short tableId;
         private final Flow flow;
 
@@ -143,7 +152,6 @@ public class NodeStatisticsHandler {
         public int hashCode() {
             final int prime = 31;
             int result = 1;
-            result = prime * result + getOuterType().hashCode();
             result = prime * result + ((flow == null) ? 0 : flow.hashCode());
             result = prime * result + ((tableId == null) ? 0 : tableId.hashCode());
             return result;
@@ -158,8 +166,6 @@ public class NodeStatisticsHandler {
             if (getClass() != obj.getClass())
                 return false;
             FlowEntry other = (FlowEntry) obj;
-            if (!getOuterType().equals(other.getOuterType()))
-                return false;
             if (flow == null) {
                 if (other.flow != null)
                     return false;
@@ -172,13 +178,9 @@ public class NodeStatisticsHandler {
                 return false;
             return true;
         }
-
-        private NodeStatisticsHandler getOuterType() {
-            return NodeStatisticsHandler.this;
-        }
     }
 
-    private static final class QueueEntry{
+    private static final class QueueEntry {
         private final NodeConnectorId nodeConnectorId;
         private final QueueId queueId;
         public QueueEntry(NodeConnectorId ncId, QueueId queueId){
@@ -233,9 +235,21 @@ public class NodeStatisticsHandler {
         return targetNodeKey;
     }
 
+    public Collection<TableKey> getKnownTables() {
+        return knownTables;
+    }
+
+    public InstanceIdentifier<Node> getTargetNodeIdentifier() {
+        return targetNodeIdentifier;
+    }
+
+    public NodeRef getTargetNodeRef() {
+        return targetNodeRef;
+    }
+
     public synchronized void updateGroupDescStats(List<GroupDescStats> list){
         final Long expiryTime = getExpiryTime();
-        final DataModificationTransaction trans = statisticsProvider.startChange();
+        final DataModificationTransaction trans = dps.beginTransaction();
 
         for (GroupDescStats groupDescStats : list) {
             GroupBuilder groupBuilder = new GroupBuilder();
@@ -261,9 +275,8 @@ public class NodeStatisticsHandler {
         trans.commit();
     }
 
-
     public synchronized void updateGroupStats(List<GroupStats> list) {
-        final DataModificationTransaction trans = statisticsProvider.startChange();
+        final DataModificationTransaction trans = dps.beginTransaction();
 
         for(GroupStats groupStats : list) {
             GroupBuilder groupBuilder = new GroupBuilder();
@@ -291,7 +304,7 @@ public class NodeStatisticsHandler {
 
     public synchronized void updateMeterConfigStats(List<MeterConfigStats> list) {
         final Long expiryTime = getExpiryTime();
-        final DataModificationTransaction trans = statisticsProvider.startChange();
+        final DataModificationTransaction trans = dps.beginTransaction();
 
         for(MeterConfigStats meterConfigStats : list) {
             MeterBuilder meterBuilder = new MeterBuilder();
@@ -319,7 +332,7 @@ public class NodeStatisticsHandler {
 
 
     public synchronized void updateMeterStats(List<MeterStats> list) {
-        final DataModificationTransaction trans = statisticsProvider.startChange();
+        final DataModificationTransaction trans = dps.beginTransaction();
 
         for(MeterStats meterStats : list) {
             MeterBuilder meterBuilder = new MeterBuilder();
@@ -347,7 +360,7 @@ public class NodeStatisticsHandler {
 
     public synchronized void updateQueueStats(List<QueueIdAndStatisticsMap> list) {
         final Long expiryTime = getExpiryTime();
-        final DataModificationTransaction trans = statisticsProvider.startChange();
+        final DataModificationTransaction trans = dps.beginTransaction();
 
         for (QueueIdAndStatisticsMap swQueueStats : list) {
 
@@ -386,21 +399,16 @@ public class NodeStatisticsHandler {
     }
 
     public synchronized void updateFlowTableStats(List<FlowTableAndStatisticsMap> list) {
-        final DataModificationTransaction trans = statisticsProvider.startChange();
+        final DataModificationTransaction trans = dps.beginTransaction();
 
+        final Set<TableKey> knownTables = new HashSet<>(list.size());
         for (FlowTableAndStatisticsMap ftStats : list) {
 
             InstanceIdentifier<Table> tableRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey)
                     .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(ftStats.getTableId().getValue())).toInstance();
 
             FlowTableStatisticsDataBuilder statisticsDataBuilder = new FlowTableStatisticsDataBuilder();
-
-            FlowTableStatisticsBuilder statisticsBuilder = new FlowTableStatisticsBuilder();
-            statisticsBuilder.setActiveFlows(ftStats.getActiveFlows());
-            statisticsBuilder.setPacketsLookedUp(ftStats.getPacketsLookedUp());
-            statisticsBuilder.setPacketsMatched(ftStats.getPacketsMatched());
-
-            final FlowTableStatistics stats = statisticsBuilder.build();
+            final FlowTableStatistics stats = new FlowTableStatisticsBuilder(ftStats).build();
             statisticsDataBuilder.setFlowTableStatistics(stats);
 
             logger.debug("Augment flow table statistics: {} for table {} on Node {}",
@@ -411,14 +419,15 @@ public class NodeStatisticsHandler {
             tableBuilder.addAugmentation(FlowTableStatisticsData.class, statisticsDataBuilder.build());
             trans.putOperationalData(tableRef, tableBuilder.build());
 
-            // FIXME: should we be tracking this data?
+            knownTables.add(tableBuilder.getKey());
         }
 
+        this.knownTables = Collections.unmodifiableCollection(knownTables);
         trans.commit();
     }
 
     public synchronized void updateNodeConnectorStats(List<NodeConnectorStatisticsAndPortNumberMap> list) {
-        final DataModificationTransaction trans = statisticsProvider.startChange();
+        final DataModificationTransaction trans = dps.beginTransaction();
 
         for(NodeConnectorStatisticsAndPortNumberMap portStats : list) {
 
@@ -464,7 +473,7 @@ public class NodeStatisticsHandler {
 
     public synchronized void updateAggregateFlowStats(Short tableId, AggregateFlowStatistics flowStats) {
         if (tableId != null) {
-            final DataModificationTransaction trans = statisticsProvider.startChange();
+            final DataModificationTransaction trans = dps.beginTransaction();
 
 
             InstanceIdentifier<Table> tableRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey)
@@ -489,7 +498,7 @@ public class NodeStatisticsHandler {
     }
 
     public synchronized void updateGroupFeatures(GroupFeatures notification) {
-        final DataModificationTransaction trans = statisticsProvider.startChange();
+        final DataModificationTransaction trans = dps.beginTransaction();
 
         final NodeBuilder nodeData = new NodeBuilder();
         nodeData.setKey(targetNodeKey);
@@ -507,7 +516,7 @@ public class NodeStatisticsHandler {
     }
 
     public synchronized void updateMeterFeatures(MeterFeatures features) {
-        final DataModificationTransaction trans = statisticsProvider.startChange();
+        final DataModificationTransaction trans = dps.beginTransaction();
 
         final NodeBuilder nodeData = new NodeBuilder();
         nodeData.setKey(targetNodeKey);
@@ -526,7 +535,7 @@ public class NodeStatisticsHandler {
 
     public synchronized void updateFlowStats(List<FlowAndStatisticsMapList> list) {
         final Long expiryTime = getExpiryTime();
-        final DataModificationTransaction trans = statisticsProvider.startChange();
+        final DataModificationTransaction trans = dps.beginTransaction();
 
         for(FlowAndStatisticsMapList map : list) {
             short tableId = map.getTableId();
@@ -682,11 +691,11 @@ public class NodeStatisticsHandler {
 
     private static Long getExpiryTime(){
         final long now = System.nanoTime();
-        return now + TimeUnit.MILLISECONDS.toNanos(StatisticsProvider.STATS_THREAD_EXECUTION_TIME * NUMBER_OF_WAIT_CYCLES);
+        return now + TimeUnit.MILLISECONDS.toNanos(StatisticsProvider.STATS_COLLECTION_MILLIS * NUMBER_OF_WAIT_CYCLES);
     }
 
     public synchronized void cleanStaleStatistics(){
-        final DataModificationTransaction trans = this.statisticsProvider.startChange();
+        final DataModificationTransaction trans = dps.beginTransaction();
         final long now = System.nanoTime();
 
         //Clean stale statistics related to group
@@ -774,4 +783,10 @@ public class NodeStatisticsHandler {
         InstanceIdentifier<?> nodeGroupStatisticsAugmentation = groupRef.augmentation(NodeGroupStatistics.class).toInstance();
         trans.removeOperationalData(nodeGroupStatisticsAugmentation);
     }
+
+    @Override
+    public void close() {
+        // FIXME: cleanup any resources we hold (registrations, etc.)
+        logger.debug("Statistics handler for {} shut down", targetNodeKey.getId());
+    }
 }