the return of the flowentry

Change-Id: I7dbeb6af2014a4df5b0beb7fe0157eaaac63bd0f
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 182e210..385e300 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
@@ -5,8 +5,6 @@
 
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
@@ -20,6 +18,7 @@
 import org.onlab.onos.net.Device;
 import org.onlab.onos.net.DeviceId;
 import org.onlab.onos.net.device.DeviceService;
+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;
@@ -61,8 +60,6 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DeviceService deviceService;
 
-    private final Map<FlowRule, Long> idleTime = new ConcurrentHashMap<>();
-
     @Activate
     public void activate() {
         store.setDelegate(delegate);
@@ -78,7 +75,7 @@
     }
 
     @Override
-    public Iterable<FlowRule> getFlowEntries(DeviceId deviceId) {
+    public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
         return store.getFlowEntries(deviceId);
     }
 
@@ -88,7 +85,6 @@
             FlowRule f = flowRules[i];
             final Device device = deviceService.getDevice(f.deviceId());
             final FlowRuleProvider frp = getProvider(device.providerId());
-            idleTime.put(f, System.currentTimeMillis());
             store.storeFlowRule(f);
             frp.applyFlowRule(f);
         }
@@ -103,7 +99,6 @@
             f = flowRules[i];
             device = deviceService.getDevice(f.deviceId());
             frp = getProvider(device.providerId());
-            idleTime.remove(f);
             store.deleteFlowRule(f);
             frp.removeFlowRule(f);
         }
@@ -125,7 +120,7 @@
 
     @Override
     public Iterable<FlowRule> getFlowRulesById(ApplicationId id) {
-        return store.getFlowEntriesByAppId(id);
+        return store.getFlowRulesByAppId(id);
     }
 
     @Override
@@ -153,15 +148,15 @@
         }
 
         @Override
-        public void flowRemoved(FlowRule flowRule) {
-            checkNotNull(flowRule, FLOW_RULE_NULL);
+        public void flowRemoved(FlowEntry flowEntry) {
+            checkNotNull(flowEntry, FLOW_RULE_NULL);
             checkValidity();
-            FlowRule stored = store.getFlowRule(flowRule);
+            FlowEntry stored = store.getFlowEntry(flowEntry);
             if (stored == null) {
-                log.info("Rule already evicted from store: {}", flowRule);
+                log.info("Rule already evicted from store: {}", flowEntry);
                 return;
             }
-            Device device = deviceService.getDevice(flowRule.deviceId());
+            Device device = deviceService.getDevice(flowEntry.deviceId());
             FlowRuleProvider frp = getProvider(device.providerId());
             FlowRuleEvent event = null;
             switch (stored.state()) {
@@ -171,20 +166,20 @@
                 break;
             case PENDING_REMOVE:
             case REMOVED:
-                event = store.removeFlowRule(flowRule);
+                event = store.removeFlowRule(stored);
                 break;
             default:
                 break;
 
             }
             if (event != null) {
-                log.debug("Flow {} removed", flowRule);
+                log.debug("Flow {} removed", flowEntry);
                 post(event);
             }
         }
 
 
-        private void flowMissing(FlowRule flowRule) {
+        private void flowMissing(FlowEntry flowRule) {
             checkNotNull(flowRule, FLOW_RULE_NULL);
             checkValidity();
             Device device = deviceService.getDevice(flowRule.deviceId());
@@ -220,36 +215,37 @@
         }
 
 
-        private void flowAdded(FlowRule flowRule) {
-            checkNotNull(flowRule, FLOW_RULE_NULL);
+        private void flowAdded(FlowEntry flowEntry) {
+            checkNotNull(flowEntry, FLOW_RULE_NULL);
             checkValidity();
 
-            if (idleTime.containsKey(flowRule) &&
-                    checkRuleLiveness(flowRule, store.getFlowRule(flowRule))) {
+            if (checkRuleLiveness(flowEntry, store.getFlowEntry(flowEntry))) {
 
-                FlowRuleEvent event = store.addOrUpdateFlowRule(flowRule);
+                FlowRuleEvent event = store.addOrUpdateFlowRule(flowEntry);
                 if (event == null) {
                     log.debug("No flow store event generated.");
                 } else {
-                    log.debug("Flow {} {}", flowRule, event.type());
+                    log.debug("Flow {} {}", flowEntry, event.type());
                     post(event);
                 }
             } else {
-                removeFlowRules(flowRule);
+                removeFlowRules(flowEntry);
             }
 
         }
 
-        private boolean checkRuleLiveness(FlowRule swRule, FlowRule storedRule) {
+        private boolean checkRuleLiveness(FlowEntry swRule, FlowEntry storedRule) {
+            if (storedRule == null) {
+                return false;
+            }
             long timeout = storedRule.timeout() * 1000;
             Long currentTime = System.currentTimeMillis();
             if (storedRule.packets() != swRule.packets()) {
-                idleTime.put(swRule, currentTime);
+                storedRule.setLastSeen();
                 return true;
             }
 
-            if ((currentTime - idleTime.get(swRule)) <= timeout) {
-                idleTime.put(swRule, currentTime);
+            if ((currentTime - storedRule.lastSeen()) <= timeout) {
                 return true;
             }
             return false;
@@ -263,13 +259,13 @@
         }
 
         @Override
-        public void pushFlowMetrics(DeviceId deviceId, Iterable<FlowRule> flowEntries) {
-            List<FlowRule> storedRules = Lists.newLinkedList(store.getFlowEntries(deviceId));
+        public void pushFlowMetrics(DeviceId deviceId, Iterable<FlowEntry> flowEntries) {
+            List<FlowEntry> storedRules = Lists.newLinkedList(store.getFlowEntries(deviceId));
 
-            Iterator<FlowRule> switchRulesIterator = flowEntries.iterator();
+            Iterator<FlowEntry> switchRulesIterator = flowEntries.iterator();
 
             while (switchRulesIterator.hasNext()) {
-                FlowRule rule = switchRulesIterator.next();
+                FlowEntry rule = switchRulesIterator.next();
                 if (storedRules.remove(rule)) {
                     // we both have the rule, let's update some info then.
                     flowAdded(rule);
@@ -278,7 +274,7 @@
                     extraneousFlow(rule);
                 }
             }
-            for (FlowRule rule : storedRules) {
+            for (FlowEntry rule : storedRules) {
                 // there are rules in the store that aren't on the switch
                 flowMissing(rule);
 
diff --git a/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java b/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java
index 8922fd9..7463671 100644
--- a/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java
+++ b/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java
@@ -27,9 +27,11 @@
 import org.onlab.onos.net.PortNumber;
 import org.onlab.onos.net.device.DeviceListener;
 import org.onlab.onos.net.device.DeviceService;
+import org.onlab.onos.net.flow.DefaultFlowEntry;
 import org.onlab.onos.net.flow.DefaultFlowRule;
+import org.onlab.onos.net.flow.FlowEntry;
+import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
 import org.onlab.onos.net.flow.FlowRule;
-import org.onlab.onos.net.flow.FlowRule.FlowRuleState;
 import org.onlab.onos.net.flow.FlowRuleEvent;
 import org.onlab.onos.net.flow.FlowRuleListener;
 import org.onlab.onos.net.flow.FlowRuleProvider;
@@ -103,9 +105,6 @@
         return new DefaultFlowRule(DID, ts, tr, 10, appId, TIMEOUT);
     }
 
-    private FlowRule flowRule(FlowRule rule, FlowRuleState state) {
-        return new DefaultFlowRule(rule, state);
-    }
 
     private FlowRule addFlowRule(int hval) {
         FlowRule rule = flowRule(hval, hval);
@@ -143,24 +142,26 @@
         FlowRule f1 = addFlowRule(1);
         FlowRule f2 = addFlowRule(2);
 
+        FlowEntry fe1 = new DefaultFlowEntry(f1);
+        FlowEntry fe2 = new DefaultFlowEntry(f2);
         assertEquals("2 rules should exist", 2, flowCount());
 
-        providerService.pushFlowMetrics(DID, ImmutableList.of(f1, f2));
+        providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
         validateEvents(RULE_ADDED, RULE_ADDED);
 
         addFlowRule(1);
         assertEquals("should still be 2 rules", 2, flowCount());
 
-        providerService.pushFlowMetrics(DID, ImmutableList.of(f1));
+        providerService.pushFlowMetrics(DID, ImmutableList.of(fe1));
         validateEvents(RULE_UPDATED);
     }
 
 
     //backing store is sensitive to the order of additions/removals
-    private boolean validateState(FlowRuleState... state) {
-        Iterable<FlowRule> rules = service.getFlowEntries(DID);
+    private boolean validateState(FlowEntryState... state) {
+        Iterable<FlowEntry> rules = service.getFlowEntries(DID);
         int i = 0;
-        for (FlowRule f : rules) {
+        for (FlowEntry f : rules) {
             if (f.state() != state[i]) {
                 return false;
             }
@@ -181,8 +182,8 @@
         mgr.applyFlowRules(r1, r2, r3);
         assertEquals("3 rules should exist", 3, flowCount());
         assertTrue("Entries should be pending add.",
-                validateState(FlowRuleState.PENDING_ADD, FlowRuleState.PENDING_ADD,
-                        FlowRuleState.PENDING_ADD));
+                validateState(FlowEntryState.PENDING_ADD, FlowEntryState.PENDING_ADD,
+                        FlowEntryState.PENDING_ADD));
     }
 
     @Test
@@ -192,20 +193,21 @@
         FlowRule f3 = addFlowRule(3);
         assertEquals("3 rules should exist", 3, flowCount());
 
-        providerService.pushFlowMetrics(DID, ImmutableList.of(f1, f2, f3));
+        FlowEntry fe1 = new DefaultFlowEntry(f1);
+        FlowEntry fe2 = new DefaultFlowEntry(f2);
+        FlowEntry fe3 = new DefaultFlowEntry(f3);
+        providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2, fe3));
         validateEvents(RULE_ADDED, RULE_ADDED, RULE_ADDED);
 
-        FlowRule rem1 = flowRule(f1, FlowRuleState.REMOVED);
-        FlowRule rem2 = flowRule(f2, FlowRuleState.REMOVED);
-        mgr.removeFlowRules(rem1, rem2);
+        mgr.removeFlowRules(f1, f2);
         //removing from north, so no events generated
         validateEvents();
         assertEquals("3 rule should exist", 3, flowCount());
         assertTrue("Entries should be pending remove.",
-                validateState(FlowRuleState.CREATED, FlowRuleState.PENDING_REMOVE,
-                        FlowRuleState.PENDING_REMOVE));
+                validateState(FlowEntryState.PENDING_REMOVE, FlowEntryState.PENDING_REMOVE,
+                        FlowEntryState.ADDED));
 
-        mgr.removeFlowRules(rem1);
+        mgr.removeFlowRules(f1);
         assertEquals("3 rule should still exist", 3, flowCount());
     }
 
@@ -213,21 +215,24 @@
     public void flowRemoved() {
         FlowRule f1 = addFlowRule(1);
         FlowRule f2 = addFlowRule(2);
-        providerService.pushFlowMetrics(f1.deviceId(), ImmutableList.of(f1, f2));
+        FlowEntry fe1 = new DefaultFlowEntry(f1);
+        FlowEntry fe2 = new DefaultFlowEntry(f2);
+        providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
         service.removeFlowRules(f1);
-        FlowRule rem1 = flowRule(f1, FlowRuleState.REMOVED);
-        providerService.flowRemoved(rem1);
+        fe1.setState(FlowEntryState.REMOVED);
+        providerService.flowRemoved(fe1);
         validateEvents(RULE_ADDED, RULE_ADDED, RULE_REMOVED);
 
-        providerService.flowRemoved(rem1);
+        providerService.flowRemoved(fe1);
         validateEvents();
 
         FlowRule f3 = flowRule(3, 3);
+        FlowEntry fe3 = new DefaultFlowEntry(f3);
         service.applyFlowRules(f3);
-        providerService.pushFlowMetrics(f3.deviceId(), Collections.singletonList(f3));
+        providerService.pushFlowMetrics(DID, Collections.singletonList(fe3));
         validateEvents(RULE_ADDED);
 
-        providerService.flowRemoved(f3);
+        providerService.flowRemoved(fe3);
         validateEvents();
     }
 
@@ -237,17 +242,20 @@
         FlowRule f2 = flowRule(2, 2);
         FlowRule f3 = flowRule(3, 3);
 
-
-
         mgr.applyFlowRules(f1, f2, f3);
-        FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
-        FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
 
-        providerService.pushFlowMetrics(DID, Lists.newArrayList(updatedF1, updatedF2));
+        FlowEntry fe1 = new DefaultFlowEntry(f1);
+        FlowEntry fe2 = new DefaultFlowEntry(f2);
+
+
+        //FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
+        //FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
+
+        providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
 
         assertTrue("Entries should be added.",
-                validateState(FlowRuleState.PENDING_ADD, FlowRuleState.ADDED,
-                        FlowRuleState.ADDED));
+                validateState(FlowEntryState.ADDED, FlowEntryState.ADDED,
+                        FlowEntryState.PENDING_ADD));
 
         validateEvents(RULE_ADDED, RULE_ADDED);
     }
@@ -259,11 +267,15 @@
         FlowRule f3 = flowRule(3, 3);
         mgr.applyFlowRules(f1, f2);
 
-        FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
-        FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
-        FlowRule updatedF3 = flowRule(f3, FlowRuleState.ADDED);
+//        FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
+//        FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
+//        FlowRule updatedF3 = flowRule(f3, FlowRuleState.ADDED);
+        FlowEntry fe1 = new DefaultFlowEntry(f1);
+        FlowEntry fe2 = new DefaultFlowEntry(f2);
+        FlowEntry fe3 = new DefaultFlowEntry(f3);
 
-        providerService.pushFlowMetrics(DID, Lists.newArrayList(updatedF1, updatedF2, updatedF3));
+
+        providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2, fe3));
 
         validateEvents(RULE_ADDED, RULE_ADDED);
 
@@ -279,13 +291,16 @@
         FlowRule f2 = flowRule(2, 2);
         FlowRule f3 = flowRule(3, 3);
 
-        FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
-        FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
+//        FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
+//        FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
+
+        FlowEntry fe1 = new DefaultFlowEntry(f1);
+        FlowEntry fe2 = new DefaultFlowEntry(f2);
         mgr.applyFlowRules(f1, f2, f3);
 
         mgr.removeFlowRules(f3);
 
-        providerService.pushFlowMetrics(DID, Lists.newArrayList(updatedF1, updatedF2));
+        providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
 
         validateEvents(RULE_ADDED, RULE_ADDED, RULE_REMOVED);
 
@@ -312,7 +327,7 @@
 
         //only check that we are in pending remove. Events and actual remove state will
         // be set by flowRemoved call.
-        validateState(FlowRuleState.PENDING_REMOVE, FlowRuleState.PENDING_REMOVE);
+        validateState(FlowEntryState.PENDING_REMOVE, FlowEntryState.PENDING_REMOVE);
     }
 
     private static class TestListener implements FlowRuleListener {