Merge "BUG 408"
[controller.git] / opendaylight / md-sal / statistics-manager / src / main / java / org / opendaylight / controller / md / statistics / manager / StatisticsUpdateCommiter.java
index 19f25944b45f0ce34a94c9224ce4b107da4f467b..a7c00d45913ccb4d5c9c44504f252735d17340a1 100644 (file)
@@ -127,13 +127,17 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
         OpendaylightFlowTableStatisticsListener,
         OpendaylightQueueStatisticsListener{
     
-    public final static Logger sucLogger = LoggerFactory.getLogger(StatisticsUpdateCommiter.class);
+    private final static Logger sucLogger = LoggerFactory.getLogger(StatisticsUpdateCommiter.class);
 
     private final StatisticsProvider statisticsManager;
     private final MultipartMessageManager messageManager;
     
     private int unaccountedFlowsCounter = 1;
 
+    /**
+     * default ctor
+     * @param manager
+     */
     public StatisticsUpdateCommiter(final StatisticsProvider manager){
 
         this.statisticsManager = manager;
@@ -412,8 +416,6 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
                 cache.put(notification.getId(), new NodeStatisticsAger(statisticsManager,key));
             }
             NodeStatisticsAger nsa = cache.get(notification.getId());
-            FlowEntry flowStatsEntry = nsa.new FlowEntry(tableId,flowRule);
-            cache.get(notification.getId()).updateFlowStats(flowStatsEntry);
                 
             //Augment the data to the flow node
 
@@ -466,6 +468,11 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
                         flowBuilder.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
                         sucLogger.debug("Found matching flow in the datastore, augmenting statistics");
                         foundOriginalFlow = true;
+                        // Update entry with timestamp of latest response 
+                        flow.setKey(existingFlow.getKey());
+                        FlowEntry flowStatsEntry = nsa.new FlowEntry(tableId,flow.build());
+                        cache.get(notification.getId()).updateFlowStats(flowStatsEntry);
+
                         it.putOperationalData(flowRef, flowBuilder.build());
                         it.commit();
                     }
@@ -490,6 +497,12 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
                             flowBuilder.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
                             sucLogger.debug("Found matching unaccounted flow in the operational datastore, augmenting statistics");
                             foundOriginalFlow = true;
+                            
+                            // Update entry with timestamp of latest response 
+                            flow.setKey(existingFlow.getKey());
+                            FlowEntry flowStatsEntry = nsa.new FlowEntry(tableId,flow.build());
+                            cache.get(notification.getId()).updateFlowStats(flowStatsEntry);
+
                             it.putOperationalData(flowRef, flowBuilder.build());
                             it.commit();
                             break;
@@ -498,9 +511,9 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
                 }
             }
             if(!foundOriginalFlow){
-                long flowKey = Long.parseLong(new String("1"+Short.toString(tableId)+"0"+Integer.toString(this.unaccountedFlowsCounter)));
+                String flowKey = "#UF$TABLE*"+Short.toString(tableId)+"*"+Integer.toString(this.unaccountedFlowsCounter);
                 this.unaccountedFlowsCounter++;
-                FlowKey newFlowKey = new FlowKey(new FlowId(Long.toString(flowKey)));
+                FlowKey newFlowKey = new FlowKey(new FlowId(flowKey));
                 InstanceIdentifier<Flow> flowRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, key)
                         .augmentation(FlowCapableNode.class)
                         .child(Table.class, new TableKey(tableId))
@@ -508,6 +521,12 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
                 flowBuilder.setKey(newFlowKey);
                 flowBuilder.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
                 sucLogger.debug("Flow {} is not present in config data store, augmenting statistics as an unaccounted flow",flowBuilder.build());
+                
+                // Update entry with timestamp of latest response 
+                flow.setKey(newFlowKey);
+                FlowEntry flowStatsEntry = nsa.new FlowEntry(tableId,flow.build());
+                cache.get(notification.getId()).updateFlowStats(flowStatsEntry);
+
                 it.putOperationalData(flowRef, flowBuilder.build());
                 it.commit();
             }
@@ -686,7 +705,7 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
         
     }
 
-    private NodeRef getNodeRef(NodeKey nodeKey){
+    private static NodeRef getNodeRef(NodeKey nodeKey){
         InstanceIdentifierBuilder<?> builder = InstanceIdentifier.builder(Nodes.class).child(Node.class, nodeKey);
         return new NodeRef(builder.toInstance());
     }
@@ -846,34 +865,65 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
         return true;
     }
 
-    private boolean layer3MatchEquals(Layer3Match statsLayer3Match, Layer3Match storedLayer3Match){
-
+    protected static boolean layer3MatchEquals(Layer3Match statsLayer3Match, Layer3Match storedLayer3Match){
+        boolean verdict = true; 
         if(statsLayer3Match instanceof Ipv4Match && storedLayer3Match instanceof Ipv4Match){
             Ipv4Match statsIpv4Match = (Ipv4Match)statsLayer3Match;
             Ipv4Match storedIpv4Match = (Ipv4Match)storedLayer3Match;
-            
-            if (storedIpv4Match.getIpv4Destination()== null) {
-                if (statsIpv4Match.getIpv4Destination()!= null) {
-                    return false;
-                }
-            } else if(!IpAddressEquals(statsIpv4Match.getIpv4Destination(),storedIpv4Match.getIpv4Destination())){
-                return false;
+
+            if (verdict) {
+                verdict = compareNullSafe(
+                        storedIpv4Match.getIpv4Destination(), statsIpv4Match.getIpv4Destination());
             }
-            if (storedIpv4Match.getIpv4Source() == null) {
-                if (statsIpv4Match.getIpv4Source() != null) {
-                    return false;
-                }
-            } else if(!IpAddressEquals(statsIpv4Match.getIpv4Source(),storedIpv4Match.getIpv4Source())) {
-                return false;
+            if (verdict) {
+                verdict = compareNullSafe(
+                        statsIpv4Match.getIpv4Source(), storedIpv4Match.getIpv4Source());
+            }
+        } else {
+            Boolean nullCheckOut = checkNullValues(storedLayer3Match, statsLayer3Match);
+            if (nullCheckOut != null) {
+                verdict = nullCheckOut;
+            } else {
+                verdict = storedLayer3Match.equals(statsLayer3Match);
             }
-            
-            return true;
-        }else{
-            return storedLayer3Match.equals(statsLayer3Match);
         }
+        
+        return verdict;
+    }
+    
+    private static boolean compareNullSafe(Ipv4Prefix statsIpv4, Ipv4Prefix storedIpv4) {
+        boolean verdict = true;
+        Boolean checkDestNullValuesOut = checkNullValues(storedIpv4, statsIpv4);
+        if (checkDestNullValuesOut != null) {
+            verdict = checkDestNullValuesOut;
+        } else if(!IpAddressEquals(statsIpv4, storedIpv4)){
+            verdict = false;
+        }
+        
+        return verdict;
+    }
+    
+    private static Boolean checkNullValues(Object v1, Object v2) {
+        Boolean verdict = null;
+        if (v1 == null && v2 != null) {
+            verdict = Boolean.FALSE;
+        } else if (v1 != null && v2 == null) {
+            verdict = Boolean.FALSE;
+        } else if (v1 == null && v2 == null) {
+            verdict = Boolean.TRUE;
+        }
+        
+        return verdict;
     }
     
-    private boolean IpAddressEquals(Ipv4Prefix statsIpAddress, Ipv4Prefix storedIpAddress) {
+    /**
+     * TODO: why don't we use the default Ipv4Prefix.equals()?
+     * 
+     * @param statsIpAddress
+     * @param storedIpAddress
+     * @return true if IPv4prefixes equals 
+     */
+    private static boolean IpAddressEquals(Ipv4Prefix statsIpAddress, Ipv4Prefix storedIpAddress) {
         IntegerIpAddress statsIpAddressInt = StrIpToIntIp(statsIpAddress.getValue());
         IntegerIpAddress storedIpAddressInt = StrIpToIntIp(storedIpAddress.getValue());
 
@@ -886,19 +936,19 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
         return false;
     }
 
-    private boolean IpAndMaskBasedMatch(IntegerIpAddress statsIpAddressInt,IntegerIpAddress storedIpAddressInt){
+    private static boolean IpAndMaskBasedMatch(IntegerIpAddress statsIpAddressInt,IntegerIpAddress storedIpAddressInt){
         return ((statsIpAddressInt.getIp() & statsIpAddressInt.getMask()) ==  (storedIpAddressInt.getIp() & storedIpAddressInt.getMask()));
     }
 
-    private boolean IpBasedMatch(IntegerIpAddress statsIpAddressInt,IntegerIpAddress storedIpAddressInt){
+    private static boolean IpBasedMatch(IntegerIpAddress statsIpAddressInt,IntegerIpAddress storedIpAddressInt){
         return (statsIpAddressInt.getIp() == storedIpAddressInt.getIp());
     }
     
-    /*
+    /**
      * Method return integer version of ip address. Converted int will be mask if 
      * mask specified
      */
-    private IntegerIpAddress StrIpToIntIp(String ipAddresss){
+    private static IntegerIpAddress StrIpToIntIp(String ipAddresss){
         
         String[] parts = ipAddresss.split("/");
         String ip = parts[0];
@@ -910,23 +960,26 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
             prefix = Integer.parseInt(parts[1]);
         }
 
-        Inet4Address addr =null;
+        IntegerIpAddress integerIpAddress = null;
         try {
-            addr = (Inet4Address) InetAddress.getByName(ip);
-        } catch (UnknownHostException e){}
-
-        byte[] addrBytes = addr.getAddress();
-        int ipInt = ((addrBytes[0] & 0xFF) << 24) |
-                         ((addrBytes[1] & 0xFF) << 16) |
-                         ((addrBytes[2] & 0xFF) << 8)  |
-                         ((addrBytes[3] & 0xFF) << 0);
-
-        int mask = 0xffffffff << 32 - prefix;
+            Inet4Address addr = (Inet4Address) InetAddress.getByName(ip);
+            byte[] addrBytes = addr.getAddress();
+            int ipInt = ((addrBytes[0] & 0xFF) << 24) |
+                    ((addrBytes[1] & 0xFF) << 16) |
+                    ((addrBytes[2] & 0xFF) << 8)  |
+                    ((addrBytes[3] & 0xFF) << 0);
+            
+            int mask = 0xffffffff << 32 - prefix;
+            
+            integerIpAddress = new IntegerIpAddress(ipInt, mask);
+        } catch (UnknownHostException e){
+            sucLogger.error("Failed to determine host IP address by name: {}", e.getMessage(), e);
+        }
 
-        return new IntegerIpAddress(ipInt, mask);
+        return integerIpAddress;
     }
     
-    class IntegerIpAddress{
+    static class IntegerIpAddress{
         int ip;
         int mask;
         public IntegerIpAddress(int ip, int mask) {