From 2cb1aee696251b6a61205023aa94143e3b42af57 Mon Sep 17 00:00:00 2001
From: Subrata Banerjee <subrata.banerjee@bigswitch.com>
Date: Thu, 12 Jan 2012 01:30:01 -0800
Subject: [PATCH] Cleanup of performance monitoring, custom json serializers,
 and CLI display support.

---
 .../core/web/JacksonCustomConverter.java      |   5 +
 .../serializers/OFMatchJSONSerializer.java    |  42 +-
 .../OFPhysicalPortJSONSerializer.java         |   2 +-
 ...MonCumulativeTimeBucketJSONSerializer.java |  60 +++
 ...PerfMonOneComponentTimeJSONSerializer.java |  45 ++
 .../perfmon/CumulativeTimeBucket.java         | 205 ++++++++++
 .../perfmon/OneComponentTime.java             |  68 +++
 .../perfmon/PktinProcessingTime.java          | 386 ++++--------------
 8 files changed, 502 insertions(+), 311 deletions(-)
 create mode 100644 src/main/java/net/floodlightcontroller/core/web/serializers/PerfMonCumulativeTimeBucketJSONSerializer.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/web/serializers/PerfMonOneComponentTimeJSONSerializer.java
 create mode 100644 src/main/java/net/floodlightcontroller/perfmon/CumulativeTimeBucket.java
 create mode 100644 src/main/java/net/floodlightcontroller/perfmon/OneComponentTime.java

diff --git a/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java b/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java
index 452d6f1de..a9de95bf3 100644
--- a/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java
+++ b/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java
@@ -24,6 +24,8 @@ import net.floodlightcontroller.core.web.serializers.EventHistoryBaseInfoJSONSer
 import net.floodlightcontroller.core.web.serializers.OFFeaturesReplyJSONSerializer;
 import net.floodlightcontroller.core.web.serializers.OFMatchJSONSerializer;
 import net.floodlightcontroller.core.web.serializers.OFPhysicalPortJSONSerializer;
+import net.floodlightcontroller.core.web.serializers.PerfMonCumulativeTimeBucketJSONSerializer;
+import net.floodlightcontroller.core.web.serializers.PerfMonOneComponentTimeJSONSerializer;
 
 import org.codehaus.jackson.JsonFactory;
 import org.codehaus.jackson.Version;
@@ -62,6 +64,9 @@ public class JacksonCustomConverter extends JacksonConverter {
         jsonModule.addSerializer(new EventHistoryBaseInfoJSONSerializer());
         jsonModule.addSerializer(
                             new EventHistoryAttachmentPointJSONSerializer());
+        jsonModule.addSerializer(new PerfMonOneComponentTimeJSONSerializer());
+        jsonModule.addSerializer(
+                            new PerfMonCumulativeTimeBucketJSONSerializer());
         jsonObjectMapper.registerModule(jsonModule);
     }
     
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/OFMatchJSONSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/OFMatchJSONSerializer.java
index 42693c8a0..303750c4d 100644
--- a/src/main/java/net/floodlightcontroller/core/web/serializers/OFMatchJSONSerializer.java
+++ b/src/main/java/net/floodlightcontroller/core/web/serializers/OFMatchJSONSerializer.java
@@ -39,32 +39,46 @@ public class OFMatchJSONSerializer extends JsonSerializer<OFMatch> {
                ((i >>  8 ) & 0xFF) + "." +
                ( i        & 0xFF);
     }
-    
+
     /**
      * Performs the serialization of a OFMatch object
      */
     @Override
-    public void serialize(OFMatch match, JsonGenerator jGen, SerializerProvider serializer) throws IOException, JsonProcessingException {
+    public void serialize(OFMatch match, JsonGenerator jGen, 
+                                SerializerProvider serializer) 
+                                throws IOException, JsonProcessingException {
         jGen.writeStartObject();
-        jGen.writeStringField("dataLayerDestination", HexString.toHexString(match.getDataLayerDestination()));
-        jGen.writeStringField("dataLayerSource", HexString.toHexString(match.getDataLayerSource()));
+        jGen.writeStringField("dataLayerDestination", 
+                    HexString.toHexString(match.getDataLayerDestination()));
+        jGen.writeStringField("dataLayerSource", 
+                    HexString.toHexString(match.getDataLayerSource()));
         String dataType = Integer.toHexString(match.getDataLayerType());
         while (dataType.length() < 4) {
             dataType = "0".concat(dataType);
         }
         jGen.writeStringField("dataLayerType", "0x" + dataType);
-        jGen.writeNumberField("dataLayerVirtualLan", match.getDataLayerVirtualLan());
-        jGen.writeNumberField("dataLayerVirtualLanPriorityCodePoint", match.getDataLayerVirtualLanPriorityCodePoint());
-        jGen.writeStringField("inputSwitch", HexString.toHexString(match.getSwitchDataPathId()));
+        jGen.writeNumberField("dataLayerVirtualLan", 
+                    match.getDataLayerVirtualLan());
+        jGen.writeNumberField("dataLayerVirtualLanPriorityCodePoint", 
+                    match.getDataLayerVirtualLanPriorityCodePoint());
+        jGen.writeStringField("inputSwitch", 
+                    HexString.toHexString(match.getSwitchDataPathId()));
         jGen.writeNumberField("inputPort", match.getInputPort());
-        jGen.writeStringField("networkDestination", intToIp(match.getNetworkDestination()));
-        jGen.writeNumberField("networkDestinationMaskLen", match.getNetworkDestinationMaskLen());
+        jGen.writeStringField("networkDestination", 
+                    intToIp(match.getNetworkDestination()));
+        jGen.writeNumberField("networkDestinationMaskLen", 
+                    match.getNetworkDestinationMaskLen());
         jGen.writeNumberField("networkProtocol", match.getNetworkProtocol());
-        jGen.writeStringField("networkSource", intToIp(match.getNetworkSource()));
-        jGen.writeNumberField("networkSourceMaskLen", match.getNetworkSourceMaskLen());
-        jGen.writeNumberField("networkTypeOfService", match.getNetworkTypeOfService());
-        jGen.writeNumberField("transportDestination", match.getTransportDestination());
-        jGen.writeNumberField("transportSource", match.getTransportSource());
+        jGen.writeStringField("networkSource", 
+                    intToIp(match.getNetworkSource()));
+        jGen.writeNumberField("networkSourceMaskLen", 
+                    match.getNetworkSourceMaskLen());
+        jGen.writeNumberField("networkTypeOfService", 
+                    match.getNetworkTypeOfService());
+        jGen.writeNumberField("transportDestination", 
+                    match.getTransportDestination());
+        jGen.writeNumberField("transportSource", 
+                    match.getTransportSource());
         jGen.writeNumberField("wildcards", match.getWildcards());
         jGen.writeEndObject();
     }
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/OFPhysicalPortJSONSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/OFPhysicalPortJSONSerializer.java
index 66f24c063..5500f49d8 100644
--- a/src/main/java/net/floodlightcontroller/core/web/serializers/OFPhysicalPortJSONSerializer.java
+++ b/src/main/java/net/floodlightcontroller/core/web/serializers/OFPhysicalPortJSONSerializer.java
@@ -45,7 +45,7 @@ public class OFPhysicalPortJSONSerializer extends JsonSerializer<OFPhysicalPort>
         jGen.writeNumberField("supportedFeatures", port.getSupportedFeatures());
         jGen.writeEndObject();
     }
-    
+
     /**
      * Tells SimpleModule that we are the serializer for OFPhysicalPort
      */
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/PerfMonCumulativeTimeBucketJSONSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/PerfMonCumulativeTimeBucketJSONSerializer.java
new file mode 100644
index 000000000..5c07f8737
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/web/serializers/PerfMonCumulativeTimeBucketJSONSerializer.java
@@ -0,0 +1,60 @@
+package net.floodlightcontroller.core.web.serializers;
+
+import java.io.IOException;
+import java.sql.Timestamp;
+
+import net.floodlightcontroller.perfmon.CumulativeTimeBucket;
+import net.floodlightcontroller.perfmon.OneComponentTime;
+
+import org.codehaus.jackson.JsonGenerator;
+import org.codehaus.jackson.JsonProcessingException;
+import org.codehaus.jackson.map.JsonSerializer;
+import org.codehaus.jackson.map.SerializerProvider;
+
+public class PerfMonCumulativeTimeBucketJSONSerializer
+                                extends JsonSerializer<CumulativeTimeBucket> {
+    /**
+     * Performs the serialization of a OneComponentTime object
+     */
+   @Override
+   public void serialize(CumulativeTimeBucket cTB,
+                   JsonGenerator jGen,
+                   SerializerProvider serializer) 
+                   throws IOException, JsonProcessingException {
+       // Skip if the number of packets processed is zero
+       if (cTB.getTotalPktCnt() != 0) {
+           jGen.writeStartObject();
+           jGen.writeNumberField("BktNo",     cTB.getBucketNo());
+           Timestamp ts = new Timestamp(cTB.getStartTime_ms());
+           String tsStr = ts.toString();
+           while (tsStr.length() < 23) {
+               tsStr = tsStr.concat("0");
+           }
+           jGen.writeStringField("StartTime", tsStr);
+           jGen.writeNumberField("Duration",  cTB.getDuration_s());
+           jGen.writeNumberField("TotPkts",   cTB.getTotalPktCnt());
+           jGen.writeNumberField("Avg",       cTB.getAvgTotalProcTime_us());
+           jGen.writeNumberField("Min",       cTB.getMinTotalProcTime_us());
+           jGen.writeNumberField("Max",       cTB.getMaxTotalProcTime_us());
+           jGen.writeNumberField("StdDev",    cTB.getSigmaTotalProcTime_us());
+           int numComps = cTB.getNumComps();
+           for (int idx=0; idx < numComps; idx++) {
+               OneComponentTime oCT = cTB.getTComps().getOneComp()[idx];
+               if (oCT.getPktCnt() != 0) {
+                   serializer.defaultSerializeField(
+                                           Integer.toString(idx), oCT, jGen);
+               }
+           }
+           
+           jGen.writeEndObject();
+       }
+   }
+
+   /**
+    * Tells SimpleModule that we are the serializer for OFMatch
+    */
+   @Override
+   public Class<CumulativeTimeBucket> handledType() {
+       return CumulativeTimeBucket.class;
+   }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/PerfMonOneComponentTimeJSONSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/PerfMonOneComponentTimeJSONSerializer.java
new file mode 100644
index 000000000..5afe36c6d
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/web/serializers/PerfMonOneComponentTimeJSONSerializer.java
@@ -0,0 +1,45 @@
+package net.floodlightcontroller.core.web.serializers;
+
+import java.io.IOException;
+
+import net.floodlightcontroller.perfmon.OneComponentTime;
+
+import org.codehaus.jackson.JsonGenerator;
+import org.codehaus.jackson.JsonProcessingException;
+import org.codehaus.jackson.map.JsonSerializer;
+import org.codehaus.jackson.map.SerializerProvider;
+
+public class PerfMonOneComponentTimeJSONSerializer
+                                    extends JsonSerializer<OneComponentTime> {
+    /**
+     * Performs the serialization of a OneComponentTime object
+     */
+   @Override
+   public void serialize(OneComponentTime oCT, 
+                   JsonGenerator jGen,
+                   SerializerProvider serializer) 
+                   throws IOException, JsonProcessingException {
+       // Skip if the number of packets processed is zero
+       if (oCT.getPktCnt() != 0) {
+           jGen.writeStartObject(); // Called from higher layer
+           jGen.writeStringField("CompName", oCT.getCompName());
+           jGen.writeNumberField("Pkts",     oCT.getPktCnt());
+           jGen.writeNumberField("Avg",      oCT.getAvgProcTime_us());
+           jGen.writeNumberField("Max",      oCT.getMaxProcTime_us());
+           jGen.writeNumberField("Min",      oCT.getMinProcTime_us());
+           jGen.writeNumberField("StdDev",   oCT.getSigmaProcTime_us());
+           //jGen.writeNumberField("Sum",    oCT.getSumProcTime_us());
+           //jGen.writeNumberField("SumSq",  oCT.getSumSquaredProcTime_us2());
+           jGen.writeEndObject();
+       }
+   }
+
+   /**
+    * Tells SimpleModule that we are the serializer for OFMatch
+    */
+   @Override
+   public Class<OneComponentTime> handledType() {
+       return OneComponentTime.class;
+   }
+}
+
diff --git a/src/main/java/net/floodlightcontroller/perfmon/CumulativeTimeBucket.java b/src/main/java/net/floodlightcontroller/perfmon/CumulativeTimeBucket.java
new file mode 100644
index 000000000..9af4ba196
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/perfmon/CumulativeTimeBucket.java
@@ -0,0 +1,205 @@
+package net.floodlightcontroller.perfmon;
+
+import net.floodlightcontroller.core.IOFMessageListener.FlListenerID;
+
+public class CumulativeTimeBucket {
+    int      bucketNo;
+    long     startTime_ms;
+    long     startTime_ns; // First pkt time-stamp in this bucket
+    // duration for which pkts are put into this bucket in seconds
+    int      duration_s;
+    ProcTime tComps;              // processing times of each component
+    int      totalPktCnt;
+    int      totalSumProcTime_us; // total processing time for one pkt in
+    long     totalSumSquaredProcTime_us;
+    int      maxTotalProcTime_us;
+    int      minTotalProcTime_us;
+    int      avgTotalProcTime_us;
+    int      sigmaTotalProcTime_us; // std. deviation
+    int      numComps;
+
+    public int getBucketNo() {
+        return bucketNo;
+    }
+
+    public void setBucketNo(int bucketNo) {
+        this.bucketNo = bucketNo;
+    }
+
+    public long getStartTime_ms() {
+        return startTime_ms;
+    }
+
+    public void setStartTime_ms(long startTime_ms) {
+        this.startTime_ms = startTime_ms;
+    }
+
+    public long getStartTime_ns() {
+        return startTime_ns;
+    }
+
+    public void setStartTime_ns(long startTime_ns) {
+        this.startTime_ns = startTime_ns;
+    }
+
+    public int getDuration_s() {
+        return duration_s;
+    }
+
+    public void setDuration_s(int duration_s) {
+        this.duration_s = duration_s;
+    }
+
+    public ProcTime getTComps() {
+        return tComps;
+    }
+
+    public void setTComps(ProcTime tComps) {
+        this.tComps = tComps;
+    }
+
+    public int getTotalPktCnt() {
+        return totalPktCnt;
+    }
+
+    public void setTotalPktCnt(int totalPktCnt) {
+        this.totalPktCnt = totalPktCnt;
+    }
+
+    public int getTotalSumProcTime_us() {
+        return totalSumProcTime_us;
+    }
+
+    public void setTotalSumProcTime_us(int totalSumProcTime_us) {
+        this.totalSumProcTime_us = totalSumProcTime_us;
+    }
+
+    public Long getTotalSumSquaredProcTime_us() {
+        return totalSumSquaredProcTime_us;
+    }
+
+    public void setTotalSumSquaredProcTime_us(
+                        Long totalSumSquaredProcTime_us) {
+        this.totalSumSquaredProcTime_us = totalSumSquaredProcTime_us;
+    }
+
+    public int getMaxTotalProcTime_us() {
+        return maxTotalProcTime_us;
+    }
+
+    public void setMaxTotalProcTime_us(int maxTotalProcTime_us) {
+        this.maxTotalProcTime_us = maxTotalProcTime_us;
+    }
+
+    public int getMinTotalProcTime_us() {
+        return minTotalProcTime_us;
+    }
+
+    public void setMinTotalProcTime_us(int minTotalProcTime_us) {
+        this.minTotalProcTime_us = minTotalProcTime_us;
+    }
+
+    public int getAvgTotalProcTime_us() {
+        return avgTotalProcTime_us;
+    }
+
+    public void setAvgTotalProcTime_us(int avgTotalProcTime_us) {
+        this.avgTotalProcTime_us = avgTotalProcTime_us;
+    }
+
+    public int getSigmaTotalProcTime_us() {
+        return sigmaTotalProcTime_us;
+    }
+
+    public void setSigmaTotalProcTime_us(int sigmaTotalProcTime_us) {
+        this.sigmaTotalProcTime_us = sigmaTotalProcTime_us;
+    }
+
+    public ProcTime gettComps() {
+        return tComps;
+    }
+
+    public void settComps(ProcTime tComps) {
+        this.tComps = tComps;
+    }
+
+    public int getNumComps() {
+        return numComps;
+    }
+
+    public void setNumComps(int numComps) {
+        this.numComps = numComps;
+    }
+
+    public void setTotalSumSquaredProcTime_us(long totalSumSquaredProcTime_us) {
+        this.totalSumSquaredProcTime_us = totalSumSquaredProcTime_us;
+    }
+
+    public class ProcTime {
+        OneComponentTime [] oneComp;
+
+        public OneComponentTime[] getOneComp() {
+            return oneComp;
+        }
+
+        public void setOneComp(OneComponentTime[] oneComp) {
+            this.oneComp = oneComp;
+        }
+
+        public ProcTime(int numComponents) {
+            oneComp = new OneComponentTime[numComponents];
+            for (int idx = FlListenerID.FL_FIRST_LISTENER_ID;
+                    idx < numComponents; idx++) {
+                oneComp[idx] = new OneComponentTime();
+                // Initialize the min and max values;
+                oneComp[idx].maxProcTime_us = Integer.MIN_VALUE;
+                oneComp[idx].minProcTime_us = Integer.MAX_VALUE;  
+                // Set the component id and name
+                oneComp[idx].setCompId(idx);
+                oneComp[idx].setCompName(
+                        FlListenerID.getListenerNameFromId(idx));
+            }
+        }
+    }
+
+    public CumulativeTimeBucket(int numComponents) {
+        duration_s  = 0;
+        maxTotalProcTime_us = Integer.MIN_VALUE;
+        minTotalProcTime_us = Integer.MAX_VALUE; 
+        tComps = new ProcTime(numComponents);
+        numComps = numComponents;
+    }
+
+    // Initialize the time bucket so that it can be reused for the next 
+    // interval, thus not
+    // creating lots of garbage
+    public void initializeCumulativeTimeBucket(
+                        CumulativeTimeBucket cumulativeTimeBkt) {
+        assert(cumulativeTimeBkt != null);
+        if (cumulativeTimeBkt == null)  {
+            return;
+        }
+
+        cumulativeTimeBkt.startTime_ms = System.currentTimeMillis();
+        cumulativeTimeBkt.startTime_ns = System.nanoTime();
+        cumulativeTimeBkt.duration_s  = 0;
+        cumulativeTimeBkt.totalPktCnt  = 0;
+        cumulativeTimeBkt.totalSumProcTime_us            = 0;
+        cumulativeTimeBkt.totalSumSquaredProcTime_us     = 0L;
+        cumulativeTimeBkt.maxTotalProcTime_us = Integer.MIN_VALUE;
+        cumulativeTimeBkt.minTotalProcTime_us = Integer.MAX_VALUE;
+        cumulativeTimeBkt.avgTotalProcTime_us = 0;
+        cumulativeTimeBkt.sigmaTotalProcTime_us = 0;
+        for (int idx = FlListenerID.FL_FIRST_LISTENER_ID; 
+                        idx <= PktinProcessingTime.BB_LAST_LISTENER_ID; idx++) {
+            OneComponentTime oct = cumulativeTimeBkt.tComps.oneComp[idx];
+            oct.pktCnt = 0;
+            oct.sumProcTime_us = 0;
+            oct.sumSquaredProcTime_us2 = 0;
+            oct.maxProcTime_us = Integer.MIN_VALUE;
+            oct.minProcTime_us = Integer.MAX_VALUE;
+            oct.avgProcTime_us = 0;
+            oct.sigmaProcTime_us = 0;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/perfmon/OneComponentTime.java b/src/main/java/net/floodlightcontroller/perfmon/OneComponentTime.java
new file mode 100644
index 000000000..db29813e8
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/perfmon/OneComponentTime.java
@@ -0,0 +1,68 @@
+package net.floodlightcontroller.perfmon;
+
+public class OneComponentTime {
+    int    compId;
+    String compName;
+    int    pktCnt;
+    int    sumProcTime_us;
+    long   sumSquaredProcTime_us2;
+    int    maxProcTime_us;
+    int    minProcTime_us;
+    int    avgProcTime_us;
+    int    sigmaProcTime_us;  // std. deviation
+
+    public int getCompId() {
+        return compId;
+    }
+    public void setCompId(int compId) {
+        this.compId = compId;
+    }
+    public String getCompName() {
+        return compName;
+    }
+    public void setCompName(String compName) {
+        this.compName = compName;
+    }
+    public int getPktCnt() {
+        return pktCnt;
+    }
+    public void setPktCnt(int pktCnt) {
+        this.pktCnt = pktCnt;
+    }
+    public int getSumProcTime_us() {
+        return sumProcTime_us;
+    }
+    public void setSumProcTime_us(int sumProcTime_us) {
+        this.sumProcTime_us = sumProcTime_us;
+    }
+    public long getSumSquaredProcTime_us2() {
+        return sumSquaredProcTime_us2;
+    }
+    public void setSumSquaredProcTime_us2(long sumSquaredProcTime_us2) {
+        this.sumSquaredProcTime_us2 = sumSquaredProcTime_us2;
+    }
+    public int getMaxProcTime_us() {
+        return maxProcTime_us;
+    }
+    public void setMaxProcTime_us(int maxProcTime_us) {
+        this.maxProcTime_us = maxProcTime_us;
+    }
+    public int getMinProcTime_us() {
+        return minProcTime_us;
+    }
+    public void setMinProcTime_us(int minProcTime_us) {
+        this.minProcTime_us = minProcTime_us;
+    }
+    public int getAvgProcTime_us() {
+        return avgProcTime_us;
+    }
+    public void setAvgProcTime_us(int avgProcTime_us) {
+        this.avgProcTime_us = avgProcTime_us;
+    }
+    public int getSigmaProcTime_us() {
+        return sigmaProcTime_us;
+    }
+    public void setSigmaProcTime_us(int sigmaProcTime_us) {
+        this.sigmaProcTime_us = sigmaProcTime_us;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/perfmon/PktinProcessingTime.java b/src/main/java/net/floodlightcontroller/perfmon/PktinProcessingTime.java
index e68ed34c9..40074a3b9 100644
--- a/src/main/java/net/floodlightcontroller/perfmon/PktinProcessingTime.java
+++ b/src/main/java/net/floodlightcontroller/perfmon/PktinProcessingTime.java
@@ -13,7 +13,7 @@ import org.slf4j.LoggerFactory;
  *
  */
 public class PktinProcessingTime  {
-    
+
     /***
      * This class contains a set of buckets (called time buckets as the
      * primarily contain 'times' that are used in a circular way to 
@@ -38,24 +38,24 @@ public class PktinProcessingTime  {
      *    syslog is generated instead
      * 
      */   
-    
+
     protected static  Logger  logger = 
         LoggerFactory.getLogger(PktinProcessingTime.class);    
-    
+
     /***
      * procTimeMonitoringState: true if monitoring is on, default is false
      * this variable is controller using a cli under the controller node
      * (config-controller)> [no] performance-monitor processing-time
      */
-    
+
     public class PerfMonConfigs {
         // overall performance monitoring knob; turned off by default
         protected boolean procTimeMonitoringState;
         // overall per-component performance monitoring knob; off by default
-        protected boolean procTimePerCompMonitoringState;  
+        protected boolean procTimePerCompMonitoringState;
         // knob for database performance monitoring
         protected boolean dbTimePerfMonState;
-        
+
         public boolean isProcTimeMonitoringState() {
             return procTimeMonitoringState;
         }
@@ -77,14 +77,14 @@ public class PktinProcessingTime  {
         public void setDbTimePerfMonState(boolean dbTimePerfMonState) {
             this.dbTimePerfMonState = dbTimePerfMonState;
         }
-        
+
         public PerfMonConfigs() {
             procTimeMonitoringState        = false;
             procTimePerCompMonitoringState = false;
             dbTimePerfMonState             = false;
         }
     }
-    
+
     protected PerfMonConfigs  perfMonCfgs;
     // Maintains the time when the last packet was processed
     protected long lastPktTime_ns; 
@@ -92,141 +92,75 @@ public class PktinProcessingTime  {
     // Time bucket created once and reused as needed
     public CumulativeTimeBucket  ctb;   // Current time bucket being filled
     public CircularTimeBucketSet ctbs;  // Set of all time buckets
+    private int numComponents;
+
 
     public Long getLastPktTime_ns() {
         return lastPktTime_ns;
     }
-
     public void setLastPktTime_ns(Long lastPktTime_ns) {
         this.lastPktTime_ns = lastPktTime_ns;
     }
-
     public long getCurBucketStartTime() {
         return curBucketStartTime;
     }
-
     public void setCurBucketStartTime(long curBucketStartTime) {
         this.curBucketStartTime = curBucketStartTime;
     }
-
     public CumulativeTimeBucket getCtb() {
         return ctb;
     }
-
     public void setCtb(CumulativeTimeBucket ctb) {
         this.ctb = ctb;
     }
-
     public CircularTimeBucketSet getCtbs() {
         return ctbs;
     }
-
     public void setCtbs(CircularTimeBucketSet ctbs) {
         this.ctbs = ctbs;
     }
-
     public PerfMonConfigs getPerfMonCfgs() {
         return perfMonCfgs;
     }
-
     public void setPerfMonCfgs(PerfMonConfigs perfMonCfgs) {
         this.perfMonCfgs = perfMonCfgs;
     }
+    public int getNumComponents() {
+        return numComponents;
+    }
+    public void setNumComponents(int numComponents) {
+        this.numComponents = numComponents;
+    }
 
-    public PktinProcessingTime() {        
+    public PktinProcessingTime() {
         FlListenerID.populateCompNames();
+        setNumComponents(BB_LAST_LISTENER_ID + 1);
         perfMonCfgs = new PerfMonConfigs();
-        ctbs = new CircularTimeBucketSet();
+        ctbs = new CircularTimeBucketSet(getNumComponents());
         ctb  = ctbs.timeBucketSet[ctbs.curBucketIdx];
         ctb.startTime_ms = System.currentTimeMillis();
-        ctb.startTime_ns = System.nanoTime();        
+        ctb.startTime_ns = System.nanoTime();
     }
-    
+
     /***
      * 30 buckets each holding 10s of processing time data, a total
      * of 30*10s = 5mins of processing time data is maintained
      */
     protected static final long ONE_BUCKET_DURATION_SECONDS_LONG = 10;// seconds
     protected static final int  ONE_BUCKET_DURATION_SECONDS_INT  = 10;// seconds 
-    protected static final long ONE_BUCKET_DURATION_NANOSECONDS = 
+    protected static final long ONE_BUCKET_DURATION_NANOSECONDS  =
                                 ONE_BUCKET_DURATION_SECONDS_LONG * 1000000000;
     protected static final int  BUCKET_SET_SIZE = 30;
-    protected static final int  TOT_PROC_TIME_WARN_THRESHOLD_US =  5000;  // ms
-    protected static final int  TOT_PROC_TIME_ALERT_THRESHOLD_US = 10000; // ms, TBD, alert not in logger    
-    
+    protected static final int  TOT_PROC_TIME_WARN_THRESHOLD_US  =  5000;  // ms
+    protected static final int  TOT_PROC_TIME_ALERT_THRESHOLD_US = 10000;
+                                // ms, TBD, alert not in logger
+
     // TBD: Somehow need to get BB last listener id from BB
-    protected static final int BB_LAST_LISTENER_ID = 12;  
-    
-    public class OneComponentTime {   
-        int    compId;
-        String compName;
-        int    pktCnt;
-        int    sumProcTime_us;
-        long   sumSquaredProcTime_us2;
-        int    maxProcTime_us;
-        int    minProcTime_us;
-        int    avgProcTime_us;
-        int    sigmaProcTime_us;  // std. deviation
-        
-        public int getCompId() {
-            return compId;
-        }
-        public void setCompId(int compId) {
-            this.compId = compId;
-        }
-        public String getCompName() {
-            return compName;
-        }
-        public void setCompName(String compName) {
-            this.compName = compName;
-        }
-        public int getPktCnt() {
-            return pktCnt;
-        }
-        public void setPktCnt(int pktCnt) {
-            this.pktCnt = pktCnt;
-        }
-        public int getSumProcTime_us() {
-            return sumProcTime_us;
-        }
-        public void setSumProcTime_us(int sumProcTime_us) {
-            this.sumProcTime_us = sumProcTime_us;
-        }
-        public long getSumSquaredProcTime_us2() {
-            return sumSquaredProcTime_us2;
-        }
-        public void setSumSquaredProcTime_us2(long sumSquaredProcTime_us2) {
-            this.sumSquaredProcTime_us2 = sumSquaredProcTime_us2;
-        }
-        public int getMaxProcTime_us() {
-            return maxProcTime_us;
-        }
-        public void setMaxProcTime_us(int maxProcTime_us) {
-            this.maxProcTime_us = maxProcTime_us;
-        }
-        public int getMinProcTime_us() {
-            return minProcTime_us;
-        }
-        public void setMinProcTime_us(int minProcTime_us) {
-            this.minProcTime_us = minProcTime_us;
-        }
-        public int getAvgProcTime_us() {
-            return avgProcTime_us;
-        }
-        public void setAvgProcTime_us(int avgProcTime_us) {
-            this.avgProcTime_us = avgProcTime_us;
-        }
-        public int getSigmaProcTime_us() {
-            return sigmaProcTime_us;
-        }
-        public void setSigmaProcTime_us(int sigmaProcTime_us) {
-            this.sigmaProcTime_us = sigmaProcTime_us;
-        }       
-    }
-    
+    protected static final int BB_LAST_LISTENER_ID = 12;
+
     public class ProcTime {
         OneComponentTime [] oneComp;
-        
+
         public OneComponentTime[] getOneComp() {
             return oneComp;
         }
@@ -236,8 +170,8 @@ public class PktinProcessingTime  {
         }
 
         public ProcTime() {
-            oneComp = new OneComponentTime[BB_LAST_LISTENER_ID + 1];   
-            for (int idx = FlListenerID.FL_FIRST_LISTENER_ID; 
+            oneComp = new OneComponentTime[BB_LAST_LISTENER_ID + 1];
+            for (int idx = FlListenerID.FL_FIRST_LISTENER_ID;
                             idx <= BB_LAST_LISTENER_ID; idx++) {
                 oneComp[idx] = new OneComponentTime();
                 // Initialise the min and max values;
@@ -250,27 +184,30 @@ public class PktinProcessingTime  {
             }
         }
     }
-    
+
     /***
      * This function is called when a packet in processing  starts
      * Check if it is time to go to the next bucket
      * @param curTime_ns
      */
-    private void checkAndStartNextBucket(Long curTime_ns) {                    
-        // We are not running any timer, packet arrivals themselves drive the rotation of the buckets
+    private void checkAndStartNextBucket(Long curTime_ns) {
+        // We are not running any timer, packet arrivals themselves drive the 
+        // rotation of the buckets
         this.lastPktTime_ns = curTime_ns;
-        if ((curTime_ns - this.ctb.startTime_ns) >  ONE_BUCKET_DURATION_NANOSECONDS) {            
-            // Go to next bucket            
-            this.ctbs.fillTimeBucket();  
+        if ((curTime_ns - this.ctb.startTime_ns) >
+                                            ONE_BUCKET_DURATION_NANOSECONDS) {
+            // Go to next bucket
+            this.ctbs.fillTimeBucket();
             /***
-             * We might not have received packets for long time, in which case there would be
-             * a gap in the start-time of the timer buckets indicating that there was no data
-             * This should be a better utilization of resources instead of creating several empty
+             * We might not have received packets for long time, in which case
+             * there would be a gap in the start-time of the timer buckets
+             * indicating that there was no data. This should be a better
+             * utilization of resources instead of creating several empty
              * buckets.
-             */            
+             */
         }
     }
-    
+
     public long getStartTimeOnePkt() {
         if (this.perfMonCfgs.procTimeMonitoringState) {
             long startTime_ns = System.nanoTime();
@@ -279,168 +216,15 @@ public class PktinProcessingTime  {
         }
         return 0L;
     }
-    
+
     // Component refers to software component like forwarding
-    public long getStartTimeOneComponent() { 
-        if (this.perfMonCfgs.procTimeMonitoringState) {                 
+    public long getStartTimeOneComponent() {
+        if (this.perfMonCfgs.procTimeMonitoringState) {
             return System.nanoTime();
         }
         return 0L;
     }
-           
-    public class CumulativeTimeBucket {
-        int      bucketNo;
-        long     startTime_ms;
-        long     startTime_ns; // First pkt time-stamp in this bucket     
-        // duration for which pkts are put into this bucket in seconds
-        int      duration_s;   
-        ProcTime tComps;              // processing times of each component        
-        int      totalPktCnt;
-        int      totalSumProcTime_us; // total processing time for one pkt in
-        long     totalSumSquaredProcTime_us;
-        int      maxTotalProcTime_us;
-        int      minTotalProcTime_us;
-        int      avgTotalProcTime_us;
-        int      sigmaTotalProcTime_us; // std. deviation
-        
-        public int getBucketNo() {
-            return bucketNo;
-        }
-
-        public void setBucketNo(int bucketNo) {
-            this.bucketNo = bucketNo;
-        }
-
-        public long getStartTime_ms() {
-            return startTime_ms;
-        }
-
-        public void setStartTime_ms(long startTime_ms) {
-            this.startTime_ms = startTime_ms;
-        }
-
-        public long getStartTime_ns() {
-            return startTime_ns;
-        }
-
-        public void setStartTime_ns(long startTime_ns) {
-            this.startTime_ns = startTime_ns;
-        }
 
-        public int getDuration_s() {
-            return duration_s;
-        }
-
-        public void setDuration_s(int duration_s) {
-            this.duration_s = duration_s;
-        }
-
-        public ProcTime getTComps() {
-            return tComps;
-        }
-
-        public void setTComps(ProcTime tComps) {
-            this.tComps = tComps;
-        }
-
-        public int getTotalPktCnt() {
-            return totalPktCnt;
-        }
-
-        public void setTotalPktCnt(int totalPktCnt) {
-            this.totalPktCnt = totalPktCnt;
-        }
-
-        public int getTotalSumProcTime_us() {
-            return totalSumProcTime_us;
-        }
-
-        public void setTotalSumProcTime_us(int totalSumProcTime_us) {
-            this.totalSumProcTime_us = totalSumProcTime_us;
-        }
-
-        public Long getTotalSumSquaredProcTime_us() {
-            return totalSumSquaredProcTime_us;
-        }
-
-        public void setTotalSumSquaredProcTime_us(
-                            Long totalSumSquaredProcTime_us) {
-            this.totalSumSquaredProcTime_us = totalSumSquaredProcTime_us;
-        }
-
-        public int getMaxTotalProcTime_us() {
-            return maxTotalProcTime_us;
-        }
-
-        public void setMaxTotalProcTime_us(int maxTotalProcTime_us) {
-            this.maxTotalProcTime_us = maxTotalProcTime_us;
-        }
-
-        public int getMinTotalProcTime_us() {
-            return minTotalProcTime_us;
-        }
-
-        public void setMinTotalProcTime_us(int minTotalProcTime_us) {
-            this.minTotalProcTime_us = minTotalProcTime_us;
-        }
-
-        public int getAvgTotalProcTime_us() {
-            return avgTotalProcTime_us;
-        }
-
-        public void setAvgTotalProcTime_us(int avgTotalProcTime_us) {
-            this.avgTotalProcTime_us = avgTotalProcTime_us;
-        }
-
-        public int getSigmaTotalProcTime_us() {
-            return sigmaTotalProcTime_us;
-        }
-
-        public void setSigmaTotalProcTime_us(int sigmaTotalProcTime_us) {
-            this.sigmaTotalProcTime_us = sigmaTotalProcTime_us;
-        }
-
-        public CumulativeTimeBucket() {                     
-            duration_s  = 0;
-            maxTotalProcTime_us = Integer.MIN_VALUE;
-            minTotalProcTime_us = Integer.MAX_VALUE; 
-            tComps = new ProcTime();            
-        }
-        
-        // Initialize the time bucket so that it can be reused for the next 
-        // interval, thus not
-        // creating lots of garbage
-        public void initializeCumulativeTimeBucket(
-                            CumulativeTimeBucket cumulativeTimeBkt) {
-            assert(cumulativeTimeBkt != null);
-            if (cumulativeTimeBkt == null)  {
-                return;
-            }
-        
-            cumulativeTimeBkt.startTime_ms = System.currentTimeMillis();
-            cumulativeTimeBkt.startTime_ns = System.nanoTime();
-            cumulativeTimeBkt.duration_s  = 0;
-            cumulativeTimeBkt.totalPktCnt  = 0;
-            cumulativeTimeBkt.totalSumProcTime_us            = 0;
-            cumulativeTimeBkt.totalSumSquaredProcTime_us     = 0L;
-            cumulativeTimeBkt.maxTotalProcTime_us = Integer.MIN_VALUE;
-            cumulativeTimeBkt.minTotalProcTime_us = Integer.MAX_VALUE;
-            cumulativeTimeBkt.avgTotalProcTime_us = 0;
-            cumulativeTimeBkt.sigmaTotalProcTime_us = 0;
-            for (int idx = FlListenerID.FL_FIRST_LISTENER_ID; 
-                                    idx <= BB_LAST_LISTENER_ID; idx++) {
-                OneComponentTime oct = cumulativeTimeBkt.tComps.oneComp[idx];
-                oct.pktCnt = 0;
-                oct.sumProcTime_us = 0;
-                oct.sumSquaredProcTime_us2 = 0;
-                oct.maxProcTime_us = Integer.MIN_VALUE;
-                oct.minProcTime_us = Integer.MAX_VALUE;
-                oct.avgProcTime_us = 0;
-                oct.sigmaProcTime_us = 0;
-            }                
-        }
-    }
-    
     public void updateCumulativeTimeOneComp(
                                 long onePktOneCompProcTime_ns, int id) {
         if (this.perfMonCfgs.procTimeMonitoringState) {
@@ -449,48 +233,53 @@ public class PktinProcessingTime  {
             OneComponentTime t_temp = this.ctb.tComps.oneComp[id];
             t_temp.pktCnt++;
             t_temp.sumProcTime_us += onePktOneCompProcTime_us;
-            t_temp.sumSquaredProcTime_us2 += 
-                onePktOneCompProcTime_us * onePktOneCompProcTime_us;            
-            
+            t_temp.sumSquaredProcTime_us2 +=
+                onePktOneCompProcTime_us * onePktOneCompProcTime_us;
             if (onePktOneCompProcTime_us > t_temp.maxProcTime_us) {
                 t_temp.maxProcTime_us = onePktOneCompProcTime_us;
-            } else if (onePktOneCompProcTime_us < t_temp.minProcTime_us) {
+            }
+            if (onePktOneCompProcTime_us < t_temp.minProcTime_us) {
                 t_temp.minProcTime_us = onePktOneCompProcTime_us;
-            }   
+            }
         }
     }
-    
+
     public void updateCumulativeTimeTotal(long onePktStartTime_ns) {
         if (this.perfMonCfgs.procTimeMonitoringState) {
-            // There is no api to get time in microseconds, milliseconds is too coarse
-            // Hence we have to use nanoseconds and then divide by 1000 to get mucroseconds
-            int onePktProcTime_us = (int)((System.nanoTime() - onePktStartTime_ns) / 1000);
+            // There is no api to get time in microseconds, milliseconds is 
+            // too coarse hence we have to use nanoseconds and then divide by 
+            // 1000 to get microseconds
+            int onePktProcTime_us = 
+                        (int)((System.nanoTime() - onePktStartTime_ns) / 1000);
             if (onePktProcTime_us > TOT_PROC_TIME_WARN_THRESHOLD_US) {
-                logger.warn("Total processing time for one packet exceeded threshold: proc time: {}ms", onePktProcTime_us/1000);
+                logger.warn("Total processing time for one packet exceeded" +
+                        "threshold: proc time: {}ms", onePktProcTime_us/1000);
             }
             this.ctb.totalPktCnt++;
             this.ctb.totalSumProcTime_us += onePktProcTime_us;
-            this.ctb.totalSumSquaredProcTime_us += onePktProcTime_us * onePktProcTime_us;
-            
+            this.ctb.totalSumSquaredProcTime_us +=
+                                    onePktProcTime_us * onePktProcTime_us;
+
             if (onePktProcTime_us > this.ctb.maxTotalProcTime_us) {
                 this.ctb.maxTotalProcTime_us = onePktProcTime_us;
             } else if (onePktProcTime_us < this.ctb.minTotalProcTime_us) {
                 this.ctb.minTotalProcTime_us = onePktProcTime_us;
             }
         }
-        
+
     }
-    
-    public class CircularTimeBucketSet {    
-        
+
+    public class CircularTimeBucketSet {
+
         /**
          * How many timer buckets have valid data, initially it is false then it
          * stays at true after the circle is completed
          */
         boolean allBucketsValid;
         int     curBucketIdx; // most recent bucket *being* filled
+        int     numComps;
         CumulativeTimeBucket [] timeBucketSet;
-        
+
         public boolean isAllBucketsValid() {
             return allBucketsValid;
         }
@@ -507,6 +296,10 @@ public class PktinProcessingTime  {
             this.curBucketIdx = curBucketIdx;
         }
 
+        public int getNumComps() {
+            return numComps;
+        }
+
         public CumulativeTimeBucket[] getTimeBucketSet() {
             return timeBucketSet;
         }
@@ -521,44 +314,45 @@ public class PktinProcessingTime  {
             Long temp = (long) sum;
             temp = temp * temp / count;
             temp = (sumSquared - temp) / count;
-            return  (int) Math.sqrt((double)temp);            
+            return  (int) Math.sqrt((double)temp);
         }
-        
-        public CircularTimeBucketSet() {
+
+        public CircularTimeBucketSet(int numComps) {
             timeBucketSet   = new CumulativeTimeBucket[BUCKET_SET_SIZE];
             for (int idx= 0; idx < BUCKET_SET_SIZE; idx++) {
-                timeBucketSet[idx] = new CumulativeTimeBucket();
+                timeBucketSet[idx] = new CumulativeTimeBucket(numComps);
                 timeBucketSet[idx].setBucketNo(idx);
             }
-            allBucketsValid = false;   
+            allBucketsValid = false;
             curBucketIdx    = 0;
+            this.numComps   = numComps;
         }
-        
+
         // Called when the bucket time ends
-        public void fillTimeBucket() {        
+        public void fillTimeBucket() {
             // Wrap up computations on the current bucket data
-            // The following operation can be done in the front end instead of 
+            // The following operation can be done in the front end instead of
             // here if it turns out to be a performance issue
             if (ctb.totalPktCnt > 0) {
                 ctb.avgTotalProcTime_us = 
-                    ctb.totalSumProcTime_us / ctb.totalPktCnt;                
+                    ctb.totalSumProcTime_us / ctb.totalPktCnt;
                 ctb.sigmaTotalProcTime_us = 
                     computeSigma(ctb.totalSumProcTime_us, 
                             ctb.totalSumSquaredProcTime_us, ctb.totalPktCnt);
-                        
+
                 // Find the avg and std. dev. of each component's proc. time
                 for (int idx = FlListenerID.FL_FIRST_LISTENER_ID; 
                     idx <= BB_LAST_LISTENER_ID; idx++) {
                     OneComponentTime oct = ctb.tComps.oneComp[idx];
                     if (oct.pktCnt > 0) {
-                        oct.avgProcTime_us   = oct.sumProcTime_us / oct.pktCnt;                        
-                        oct.sigmaProcTime_us = computeSigma(oct.sumProcTime_us, 
+                        oct.avgProcTime_us   = oct.sumProcTime_us / oct.pktCnt;
+                        oct.sigmaProcTime_us = computeSigma(oct.sumProcTime_us,
                                 oct.sumSquaredProcTime_us2, oct.pktCnt);
                     }
                 }
-            }        
+            }
             ctb.duration_s = ONE_BUCKET_DURATION_SECONDS_INT;
-            
+
             // Move to the new bucket
             if (curBucketIdx >= BUCKET_SET_SIZE-1) {
                 curBucketIdx = 0; 
@@ -570,5 +364,5 @@ public class PktinProcessingTime  {
             ctb = timeBucketSet[curBucketIdx];
             ctb.initializeCumulativeTimeBucket(ctb);
         }
-    }   
+    }
 }
-- 
GitLab