ONOS-1440: Implements port statistics feature, which polls port statistics of all devices every 10 seconds. Also, implemented a simple portstats ONOS CLI command to show the statistics.

Change-Id: I57e046ae2c2463a58b478d3a5b523422cde71ba2
diff --git a/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleDeviceStore.java b/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleDeviceStore.java
index 2814be9..d8c55ff 100644
--- a/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleDeviceStore.java
+++ b/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleDeviceStore.java
@@ -42,6 +42,7 @@
 import org.onosproject.net.device.DeviceStore;
 import org.onosproject.net.device.DeviceStoreDelegate;
 import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.device.PortStatistics;
 import org.onosproject.net.provider.ProviderId;
 import org.onosproject.store.AbstractStore;
 import org.onlab.packet.ChassisId;
@@ -49,6 +50,7 @@
 import org.slf4j.Logger;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -94,6 +96,8 @@
     private final ConcurrentMap<DeviceId, Device> devices = Maps.newConcurrentMap();
     private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, Port>>
             devicePorts = Maps.newConcurrentMap();
+    private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, PortStatistics>>
+            devicePortStats = Maps.newConcurrentMap();
 
     // Available (=UP) devices
     private final Set<DeviceId> availableDevices = Sets.newConcurrentHashSet();
@@ -416,12 +420,39 @@
     }
 
     @Override
+    public DeviceEvent updatePortStatistics(ProviderId providerId, DeviceId deviceId,
+                                            Collection<PortStatistics> portStats) {
+
+        ConcurrentMap<PortNumber, PortStatistics> statsMap = devicePortStats.get(deviceId);
+        if (statsMap == null) {
+            statsMap = Maps.newConcurrentMap();
+            devicePortStats.put(deviceId, statsMap);
+        }
+
+        for (PortStatistics stat: portStats) {
+            PortNumber portNumber = PortNumber.portNumber(stat.port());
+            statsMap.put(portNumber, stat);
+        }
+
+        return new DeviceEvent(PORT_STATS_UPDATED,  devices.get(deviceId), null);
+    }
+
+    @Override
     public Port getPort(DeviceId deviceId, PortNumber portNumber) {
         Map<PortNumber, Port> ports = devicePorts.get(deviceId);
         return ports == null ? null : ports.get(portNumber);
     }
 
     @Override
+    public List<PortStatistics> getPortStatistics(DeviceId deviceId) {
+        Map<PortNumber, PortStatistics> portStats = devicePortStats.get(deviceId);
+        if (portStats == null) {
+            return Collections.emptyList();
+        }
+        return ImmutableList.copyOf(portStats.values());
+    }
+
+    @Override
     public boolean isAvailable(DeviceId deviceId) {
         return availableDevices.contains(deviceId);
     }