Minor fix in flow IP Matching
[controller.git] / opendaylight / md-sal / statistics-manager / src / main / java / org / opendaylight / controller / md / statistics / manager / MultipartMessageManager.java
index 11cce72ef1516655e26d7a5b28daaa37d880d5f9..6f58708e1b207edf898f606448147119ec3e106b 100644 (file)
@@ -7,10 +7,13 @@
  */
 package org.opendaylight.controller.md.statistics.manager;
 
+import java.util.Date;
+import java.util.Iterator;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 
 /**
  * Main responsibility of the class is to manage multipart response 
@@ -21,17 +24,149 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.
  */
 public class MultipartMessageManager {
 
-    private static Map<TransactionId,Short> txIdTotableIdMap = new ConcurrentHashMap<TransactionId,Short>();
+    /*
+     *  Map for tx id and type of request, to keep track of all the request sent 
+     *  by Statistics Manager. Statistics Manager won't entertain any multipart 
+     *  response for which it didn't send the request.  
+     */
     
+    private static Map<TxIdEntry,Date> txIdToRequestTypeMap = new ConcurrentHashMap<TxIdEntry,Date>();
+    /*
+     * Map to keep track of the request tx id for flow table statistics request.
+     * Because flow table statistics multi part response do not contains the table id.
+     */
+    private static Map<TxIdEntry,Short> txIdTotableIdMap = new ConcurrentHashMap<TxIdEntry,Short>();
+    
+    private final int NUMBER_OF_WAIT_CYCLES =2;
+
+    class TxIdEntry{
+        private final TransactionId txId;
+        private final NodeId nodeId;
+        private final StatsRequestType requestType;
+        
+        public TxIdEntry(NodeId nodeId, TransactionId txId, StatsRequestType requestType){
+            this.txId = txId;
+            this.nodeId = nodeId;
+            this.requestType = requestType;
+        }
+        public TransactionId getTxId() {
+            return txId;
+        }
+        public NodeId getNodeId() {
+            return nodeId;
+        }
+        public StatsRequestType getRequestType() {
+            return requestType;
+        }
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + getOuterType().hashCode();
+            result = prime * result + ((nodeId == null) ? 0 : nodeId.hashCode());
+            result = prime * result + ((txId == null) ? 0 : txId.hashCode());
+            return result;
+        }
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (!(obj instanceof TxIdEntry)) {
+                return false;
+            }
+            TxIdEntry other = (TxIdEntry) obj;
+            if (!getOuterType().equals(other.getOuterType())) {
+                return false;
+            }
+            if (nodeId == null) {
+                if (other.nodeId != null) {
+                    return false;
+                }
+            } else if (!nodeId.equals(other.nodeId)) {
+                return false;
+            }
+            if (txId == null) {
+                if (other.txId != null) {
+                    return false;
+                }
+            } else if (!txId.equals(other.txId)) {
+                return false;
+            }
+            return true;
+        }
+        private MultipartMessageManager getOuterType() {
+            return MultipartMessageManager.this;
+        }
+        @Override
+        public String toString() {
+            return "TxIdEntry [txId=" + txId + ", nodeId=" + nodeId + ", requestType=" + requestType + "]";
+        }
+    }
+
     public MultipartMessageManager(){}
     
-    public Short getTableIdForTxId(TransactionId id){
+    public Short getTableIdForTxId(NodeId nodeId,TransactionId id){
         
-        return txIdTotableIdMap.get(id);
+        return txIdTotableIdMap.get(new TxIdEntry(nodeId,id,null));
         
     }
     
-    public void setTxIdAndTableIdMapEntry(TransactionId id,Short tableId){
-        txIdTotableIdMap.put(id, tableId);
+    public void setTxIdAndTableIdMapEntry(NodeId nodeId, TransactionId id,Short tableId){
+        if(id == null)
+            return;
+        txIdTotableIdMap.put(new TxIdEntry(nodeId,id,null), tableId);
+    }
+    
+    public boolean isRequestTxIdExist(NodeId nodeId, TransactionId id, Boolean moreRepliesToFollow){
+        TxIdEntry entry = new TxIdEntry(nodeId,id,null);
+        if(moreRepliesToFollow.booleanValue()){
+            return txIdToRequestTypeMap.containsKey(entry);
+        }else{
+            return txIdToRequestTypeMap.remove(entry)==null?false:true;
+        }
+    }
+    public void addTxIdToRequestTypeEntry (NodeId nodeId, TransactionId id,StatsRequestType type){
+        if(id == null)
+            return;
+        TxIdEntry entry = new TxIdEntry(nodeId,id,type);
+        txIdToRequestTypeMap.put(entry, getExpiryTime());
+    }
+    public boolean removeTxId(NodeId nodeId, TransactionId id){
+        TxIdEntry entry = new TxIdEntry(nodeId,id,null);
+        return txIdToRequestTypeMap.remove(entry)==null?false:true;
+    }
+    
+    private Date getExpiryTime(){
+        Date expires = new Date();
+        expires.setTime(expires.getTime()+StatisticsProvider.STATS_THREAD_EXECUTION_TIME*NUMBER_OF_WAIT_CYCLES);
+        return expires;
+    }
+
+    public enum StatsRequestType{
+        ALL_FLOW,
+        AGGR_FLOW,
+        ALL_PORT,
+        ALL_FLOW_TABLE,
+        ALL_QUEUE_STATS,
+        ALL_GROUP,
+        ALL_METER,
+        GROUP_DESC,
+        METER_CONFIG
+    }
+    
+    public void cleanStaleTransactionIds(){
+        for (Iterator<TxIdEntry> it = txIdToRequestTypeMap.keySet().iterator();it.hasNext();){
+            TxIdEntry txIdEntry = it.next();
+            Date now = new Date();
+            Date expiryTime = txIdToRequestTypeMap.get(txIdEntry);
+            if(now.after(expiryTime)){
+                it.remove();
+                txIdTotableIdMap.remove(txIdEntry);
+            }            
+        }
     }
 }