In the method to get flow stats for a particular match, the match from the stats...
[controller.git] / opendaylight / protocol_plugins / openflow / src / main / java / org / opendaylight / controller / protocol_plugin / openflow / internal / OFStatisticsManager.java
index bae49d511a2f853f61d428f0751ea7b231539831..27a7ae6ffb125ebb42d8af542ca27348fa926bb0 100644 (file)
@@ -36,6 +36,7 @@ import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
 import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Match;
 import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6StatsReply;
 import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6StatsRequest;
+import org.opendaylight.controller.sal.connection.IPluginOutConnectionService;
 import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.core.NodeConnector;
 import org.opendaylight.controller.sal.core.Property;
@@ -62,12 +63,11 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * It periodically polls the different OF statistics from the OF switches and
- * caches them for quick retrieval for the above layers' modules It also
- * provides an API to directly query the switch about the statistics
+ * Periodically polls the different OF statistics from the OF switches, caches
+ * them, and publishes results towards SAL. It also provides an API to directly
+ * query the switch for any specific statistics.
  */
-public class OFStatisticsManager implements IOFStatisticsManager,
-IInventoryShimExternalListener, CommandProvider {
+public class OFStatisticsManager implements IOFStatisticsManager, IInventoryShimExternalListener, CommandProvider {
     private static final Logger log = LoggerFactory.getLogger(OFStatisticsManager.class);
     private static final int INITIAL_SIZE = 64;
     private static final long FLOW_STATS_PERIOD = 10000;
@@ -86,7 +86,6 @@ IInventoryShimExternalListener, CommandProvider {
     private ConcurrentMap<Long, List<OFStatistics>> descStatistics;
     private ConcurrentMap<Long, List<OFStatistics>> portStatistics;
     private ConcurrentMap<Long, List<OFStatistics>> tableStatistics;
-    private List<OFStatistics> dummyList;
     private ConcurrentMap<Long, StatisticsTicks> statisticsTimerTicks;
     protected BlockingQueue<StatsRequest> pendingStatsRequests;
     protected BlockingQueue<Long> switchPortStatsUpdated;
@@ -97,7 +96,7 @@ IInventoryShimExternalListener, CommandProvider {
     private ConcurrentMap<Long, Boolean> switchSupportsVendorExtStats;
     // Per port sampled (every portStatsPeriod) transmit rate
     private Map<Long, Map<Short, TxRates>> txRates;
-    private Set<IOFStatisticsListener> statisticsListeners;
+    private Set<IOFStatisticsListener> statisticsListeners = new CopyOnWriteArraySet<IOFStatisticsListener>();
 
     /**
      * The object containing the latest factoredSamples tx rate samples for a
@@ -169,6 +168,18 @@ IInventoryShimExternalListener, CommandProvider {
         }
         return statsQueueSize;
     }
+
+    IPluginOutConnectionService connectionPluginOutService;
+    void setIPluginOutConnectionService(IPluginOutConnectionService s) {
+        connectionPluginOutService = s;
+    }
+
+    void unsetIPluginOutConnectionService(IPluginOutConnectionService s) {
+        if (connectionPluginOutService == s) {
+            connectionPluginOutService = null;
+        }
+    }
+
     /**
      * Function called by the dependency manager when all the required
      * dependencies are satisfied
@@ -179,18 +190,16 @@ IInventoryShimExternalListener, CommandProvider {
         descStatistics = new ConcurrentHashMap<Long, List<OFStatistics>>();
         portStatistics = new ConcurrentHashMap<Long, List<OFStatistics>>();
         tableStatistics = new ConcurrentHashMap<Long, List<OFStatistics>>();
-        dummyList = new ArrayList<OFStatistics>(1);
         pendingStatsRequests = new LinkedBlockingQueue<StatsRequest>(getStatsQueueSize());
         statisticsTimerTicks = new ConcurrentHashMap<Long, StatisticsTicks>(INITIAL_SIZE);
         switchPortStatsUpdated = new LinkedBlockingQueue<Long>(INITIAL_SIZE);
         switchSupportsVendorExtStats = new ConcurrentHashMap<Long, Boolean>(INITIAL_SIZE);
         txRates = new HashMap<Long, Map<Short, TxRates>>(INITIAL_SIZE);
-        statisticsListeners = new CopyOnWriteArraySet<IOFStatisticsListener>();
 
         configStatsPollIntervals();
 
         // Initialize managed timers
-        statisticsTimer = new Timer();
+        statisticsTimer = new Timer("Statistics Timer Ticks");
         statisticsTimerTask = new TimerTask() {
             @Override
             public void run() {
@@ -209,6 +218,7 @@ IInventoryShimExternalListener, CommandProvider {
                     } catch (InterruptedException e) {
                         log.warn("Flow Statistics Collector thread "
                                 + "interrupted", e);
+                        return;
                     }
                 }
             }
@@ -224,6 +234,7 @@ IInventoryShimExternalListener, CommandProvider {
                         updatePortsTxRate(switchId);
                     } catch (InterruptedException e) {
                         log.warn("TX Rate Updater thread interrupted", e);
+                        return;
                     }
                 }
             }
@@ -237,6 +248,7 @@ IInventoryShimExternalListener, CommandProvider {
      *
      */
     void destroy() {
+        statisticsListeners.clear();
     }
 
     /**
@@ -508,7 +520,7 @@ IInventoryShimExternalListener, CommandProvider {
         List<OFStatistics> values = this.fetchStatisticsFromSwitch(switchId, statType, null);
 
         // If got a valid response update local cache and notify listeners
-        if (values != null && !values.isEmpty()) {
+        if (!values.isEmpty()) {
             switch (statType) {
                 case FLOW:
                 case VENDOR:
@@ -575,7 +587,7 @@ IInventoryShimExternalListener, CommandProvider {
     @SuppressWarnings("unchecked")
     private List<OFStatistics> fetchStatisticsFromSwitch(Long switchId,
             OFStatisticsType statsType, Object target) {
-        List<OFStatistics> values = null;
+        List<OFStatistics> values = Collections.emptyList();
         String type = null;
         ISwitch sw = controller.getSwitch(switchId);
 
@@ -594,7 +606,7 @@ IInventoryShimExternalListener, CommandProvider {
                     // Malformed request
                     log.warn("Invalid target type for Flow stats request: {}",
                             target.getClass());
-                    return null;
+                    return Collections.emptyList();
                 } else {
                     // Specific flow request
                     match = (OFMatch) target;
@@ -635,7 +647,7 @@ IInventoryShimExternalListener, CommandProvider {
                     // Malformed request
                     log.warn("Invalid target type for Port stats request: {}",
                             target.getClass());
-                    return null;
+                    return Collections.emptyList();
                 } else {
                     // Specific port request
                     targetPort = (Short) target;
@@ -662,7 +674,7 @@ IInventoryShimExternalListener, CommandProvider {
                         // Malformed request
                         log.warn("Invalid table id for table stats request: {}",
                                 target.getClass());
-                        return null;
+                        return Collections.emptyList();
                     }
                     byte targetTable = (Byte) target;
                     OFTableStatistics specificReq = new OFTableStatistics();
@@ -705,7 +717,7 @@ IInventoryShimExternalListener, CommandProvider {
          * Check on emptiness as interference between add and get is still
          * possible on the inner list (the concurrentMap entry's value)
          */
-        return (list == null || list.isEmpty()) ? this.dummyList
+        return (list == null || list.isEmpty()) ? Collections.<OFStatistics>emptyList()
                 : (list.get(0) instanceof OFVendorStatistics) ? this
                         .v6StatsListToOFStatsList(list) : list;
     }
@@ -719,7 +731,7 @@ IInventoryShimExternalListener, CommandProvider {
          * possible on the inner list (the concurrentMap entry's value)
          */
         if (statsList == null || statsList.isEmpty()) {
-            return this.dummyList;
+            return Collections.emptyList();
         }
 
         if (statsList.get(0) instanceof OFVendorStatistics) {
@@ -736,7 +748,7 @@ IInventoryShimExternalListener, CommandProvider {
             for (OFStatistics stats : targetList) {
                 V6StatsReply v6Stats = (V6StatsReply) stats;
                 V6Match v6Match = v6Stats.getMatch();
-                if (v6Stats.getPriority() == priority && v6Match.equals(targetMatch)) {
+                if (v6Stats.getPriority() == priority && targetMatch.equals(v6Match)) {
                     List<OFStatistics> list = new ArrayList<OFStatistics>();
                     list.add(stats);
                     return list;
@@ -745,29 +757,29 @@ IInventoryShimExternalListener, CommandProvider {
         } else {
             for (OFStatistics stats : statsList) {
                 OFFlowStatisticsReply flowStats = (OFFlowStatisticsReply) stats;
-                if (flowStats.getPriority() == priority && flowStats.getMatch().equals(ofMatch)) {
+                if (flowStats.getPriority() == priority && ofMatch.equals(flowStats.getMatch())) {
                     List<OFStatistics> list = new ArrayList<OFStatistics>();
                     list.add(stats);
                     return list;
                 }
             }
         }
-        return this.dummyList;
+        return Collections.emptyList();
     }
 
     /*
      * Converts the v6 vendor statistics to the OFStatistics
      */
-    private List<OFStatistics> v6StatsListToOFStatsList(
-            List<OFStatistics> statistics) {
+    private List<OFStatistics> v6StatsListToOFStatsList(List<OFStatistics> statistics) {
+        if (statistics == null || statistics.isEmpty()) {
+            return Collections.emptyList();
+        }
         List<OFStatistics> v6statistics = new ArrayList<OFStatistics>();
-        if (statistics != null && !statistics.isEmpty()) {
-            for (OFStatistics stats : statistics) {
-                if (stats instanceof OFVendorStatistics) {
-                    List<OFStatistics> r = getV6ReplyStatistics((OFVendorStatistics) stats);
-                    if (r != null) {
-                        v6statistics.addAll(r);
-                    }
+        for (OFStatistics stats : statistics) {
+            if (stats instanceof OFVendorStatistics) {
+                List<OFStatistics> r = getV6ReplyStatistics((OFVendorStatistics) stats);
+                if (r != null) {
+                    v6statistics.addAll(r);
                 }
             }
         }
@@ -778,8 +790,10 @@ IInventoryShimExternalListener, CommandProvider {
             OFVendorStatistics stat) {
         int length = stat.getLength();
         List<OFStatistics> results = new ArrayList<OFStatistics>();
-        if (length < 12)
-            return null; // Nicira Hdr is 12 bytes. We need atleast that much
+        if (length < 12) {
+            // Nicira Hdr is 12 bytes. We need at least that much
+            return Collections.emptyList();
+        }
         ByteBuffer data = ByteBuffer.allocate(length);
         stat.writeTo(data);
         data.rewind();
@@ -791,7 +805,7 @@ IInventoryShimExternalListener, CommandProvider {
         int vendor = data.getInt(); // first 4 bytes is vendor id.
         if (vendor != V6StatsRequest.NICIRA_VENDOR_ID) {
             log.warn("Unexpected vendor id: 0x{}", Integer.toHexString(vendor));
-            return null;
+            return Collections.emptyList();
         } else {
             // go ahead by 8 bytes which is 8 bytes of 0
             data.getLong(); // should be all 0's
@@ -804,12 +818,14 @@ IInventoryShimExternalListener, CommandProvider {
         while (length > 0) {
             v6statsreply = new V6StatsReply();
             min_len = v6statsreply.getLength();
-            if (length < v6statsreply.getLength())
+            if (length < v6statsreply.getLength()) {
                 break;
+            }
             v6statsreply.setActionFactory(stat.getActionFactory());
             v6statsreply.readFrom(data);
-            if (v6statsreply.getLength() < min_len)
+            if (v6statsreply.getLength() < min_len) {
                 break;
+            }
             v6statsreply.setVendorId(vendor);
             log.trace("V6StatsReply: {}", v6statsreply);
             length -= v6statsreply.getLength();
@@ -831,17 +847,16 @@ IInventoryShimExternalListener, CommandProvider {
             }
         }
 
-        List<OFStatistics> list = this.fetchStatisticsFromSwitch(switchId, statType,
-                target);
+        List<OFStatistics> list = this.fetchStatisticsFromSwitch(switchId, statType, target);
 
-        return (list == null) ? null :
-            (statType == OFStatisticsType.VENDOR) ? v6StatsListToOFStatsList(list) : list;
+        return (statType == OFStatisticsType.VENDOR) ? v6StatsListToOFStatsList(list) : list;
     }
 
     @Override
     public List<OFStatistics> getOFDescStatistics(Long switchId) {
-        if (!descStatistics.containsKey(switchId))
-            return this.dummyList;
+        if (!descStatistics.containsKey(switchId)) {
+            return Collections.emptyList();
+        }
 
         return descStatistics.get(switchId);
     }
@@ -849,7 +864,7 @@ IInventoryShimExternalListener, CommandProvider {
     @Override
     public List<OFStatistics> getOFPortStatistics(Long switchId) {
         if (!portStatistics.containsKey(switchId)) {
-            return this.dummyList;
+            return Collections.emptyList();
         }
 
         return portStatistics.get(switchId);
@@ -858,7 +873,7 @@ IInventoryShimExternalListener, CommandProvider {
     @Override
     public List<OFStatistics> getOFPortStatistics(Long switchId, short portId) {
         if (!portStatistics.containsKey(switchId)) {
-            return this.dummyList;
+            return Collections.emptyList();
         }
         List<OFStatistics> list = new ArrayList<OFStatistics>(1);
         for (OFStatistics stats : portStatistics.get(switchId)) {
@@ -873,7 +888,7 @@ IInventoryShimExternalListener, CommandProvider {
     @Override
     public List<OFStatistics> getOFTableStatistics(Long switchId) {
         if (!tableStatistics.containsKey(switchId)) {
-            return this.dummyList;
+            return Collections.emptyList();
         }
 
         return tableStatistics.get(switchId);
@@ -882,7 +897,7 @@ IInventoryShimExternalListener, CommandProvider {
     @Override
     public List<OFStatistics> getOFTableStatistics(Long switchId, Byte tableId) {
         if (!tableStatistics.containsKey(switchId)) {
-            return this.dummyList;
+            return Collections.emptyList();
         }
 
         List<OFStatistics> list = new ArrayList<OFStatistics>(1);