functional stats service

Change-Id: I90de3aa5d7721db8ef6a154e122af8b446243f60
diff --git a/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java b/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
index 01514d4..d8f89ae 100644
--- a/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
@@ -108,6 +108,9 @@
             if (local) {
                 // TODO: aggregate all local rules and push down once?
                 applyFlowRulesToProviders(f);
+                eventDispatcher.post(
+                        new FlowRuleEvent(FlowRuleEvent.Type.RULE_ADD_REQUESTED, f));
+
             }
         }
     }
@@ -136,6 +139,8 @@
             if (local) {
                 // TODO: aggregate all local rules and push down once?
                 removeFlowRulesFromProviders(f);
+                eventDispatcher.post(
+                        new FlowRuleEvent(FlowRuleEvent.Type.RULE_REMOVE_REQUESTED, f));
             }
         }
     }
diff --git a/core/net/src/main/java/org/onlab/onos/net/packet/impl/PacketManager.java b/core/net/src/main/java/org/onlab/onos/net/packet/impl/PacketManager.java
index e682c49..49d21e0 100644
--- a/core/net/src/main/java/org/onlab/onos/net/packet/impl/PacketManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/packet/impl/PacketManager.java
@@ -68,7 +68,9 @@
         checkNotNull(packet, "Packet cannot be null");
         final Device device = deviceService.getDevice(packet.sendThrough());
         final PacketProvider packetProvider = getProvider(device.providerId());
-        packetProvider.emit(packet);
+        if (packetProvider != null) {
+            packetProvider.emit(packet);
+        }
     }
 
     @Override
diff --git a/core/net/src/main/java/org/onlab/onos/net/statistic/impl/StatisticManager.java b/core/net/src/main/java/org/onlab/onos/net/statistic/impl/StatisticManager.java
index 9b1a2e0..90db729 100644
--- a/core/net/src/main/java/org/onlab/onos/net/statistic/impl/StatisticManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/statistic/impl/StatisticManager.java
@@ -10,15 +10,19 @@
 import org.onlab.onos.net.Link;
 import org.onlab.onos.net.Path;
 
+import org.onlab.onos.net.flow.FlowEntry;
 import org.onlab.onos.net.flow.FlowRule;
 import org.onlab.onos.net.flow.FlowRuleEvent;
 import org.onlab.onos.net.flow.FlowRuleListener;
 import org.onlab.onos.net.flow.FlowRuleService;
+import org.onlab.onos.net.statistic.DefaultLoad;
 import org.onlab.onos.net.statistic.Load;
 import org.onlab.onos.net.statistic.StatisticService;
 import org.onlab.onos.net.statistic.StatisticStore;
 import org.slf4j.Logger;
 
+import java.util.Set;
+
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
@@ -54,12 +58,12 @@
 
     @Override
     public Load load(Link link) {
-        return null;
+       return load(link.src());
     }
 
     @Override
     public Load load(ConnectPoint connectPoint) {
-        return null;
+        return loadInternal(connectPoint);
     }
 
     @Override
@@ -77,6 +81,35 @@
         return null;
     }
 
+    private Load loadInternal(ConnectPoint connectPoint) {
+        Set<FlowEntry> current;
+        Set<FlowEntry> previous;
+        synchronized (statisticStore) {
+            current = statisticStore.getCurrentStatistic(connectPoint);
+            previous = statisticStore.getPreviousStatistic(connectPoint);
+        }
+        if (current == null || previous == null) {
+            return new DefaultLoad();
+        }
+        long currentAggregate = aggregate(current);
+        long previousAggregate = aggregate(previous);
+
+        return new DefaultLoad(currentAggregate, previousAggregate);
+    }
+
+    /**
+     * Aggregates a set of values.
+     * @param values the values to aggregate
+     * @return a long value
+     */
+    private long aggregate(Set<FlowEntry> values) {
+        long sum = 0;
+        for (FlowEntry f : values) {
+            sum += f.bytes();
+        }
+        return sum;
+    }
+
     /**
      * Internal flow rule event listener.
      */
@@ -84,22 +117,29 @@
 
         @Override
         public void event(FlowRuleEvent event) {
-//            FlowRule rule = event.subject();
-//            switch (event.type()) {
-//                case RULE_ADDED:
-//                case RULE_UPDATED:
-//                    if (rule instanceof FlowEntry) {
-//                        statisticStore.addOrUpdateStatistic((FlowEntry) rule);
-//                    }
-//                    break;
-//                case RULE_ADD_REQUESTED:
-//                    statisticStore.prepareForStatistics(rule);
-//                    break;
-//                case RULE_REMOVE_REQUESTED:
-//                case RULE_REMOVED:
-//                    statisticStore.removeFromStatistics(rule);
-//                    break;
-//            }
+            FlowRule rule = event.subject();
+            switch (event.type()) {
+                case RULE_ADDED:
+                case RULE_UPDATED:
+                    if (rule instanceof FlowEntry) {
+                        statisticStore.addOrUpdateStatistic((FlowEntry) rule);
+                    } else {
+                        log.warn("IT AIN'T A FLOWENTRY");
+                    }
+                    break;
+                case RULE_ADD_REQUESTED:
+                    log.info("Preparing for stats");
+                    statisticStore.prepareForStatistics(rule);
+                    break;
+                case RULE_REMOVE_REQUESTED:
+                    log.info("Removing stats");
+                    statisticStore.removeFromStatistics(rule);
+                    break;
+                case RULE_REMOVED:
+                    break;
+                default:
+                    log.warn("Unknown flow rule event {}", event);
+            }
         }
     }