Use a single Timer instead of two threads
[controller.git] / opendaylight / md-sal / statistics-manager / src / main / java / org / opendaylight / controller / md / statistics / manager / MultipartMessageManager.java
1 /*
2  * Copyright IBM Corporation, 2013.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.md.statistics.manager;
9
10 import java.util.Iterator;
11 import java.util.Map;
12 import java.util.concurrent.ConcurrentHashMap;
13 import java.util.concurrent.TimeUnit;
14
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
17
18 /**
19  * Main responsibility of the class is to manage multipart response
20  * for multipart request. It also handles the flow aggregate request
21  * and response mapping.
22  * @author avishnoi@in.ibm.com
23  *
24  */
25 public class MultipartMessageManager {
26
27     /*
28      *  Map for tx id and type of request, to keep track of all the request sent
29      *  by Statistics Manager. Statistics Manager won't entertain any multipart
30      *  response for which it didn't send the request.
31      */
32     private final Map<TxIdEntry,Long> txIdToRequestTypeMap = new ConcurrentHashMap<>();
33     /*
34      * Map to keep track of the request tx id for flow table statistics request.
35      * Because flow table statistics multi part response do not contains the table id.
36      */
37     private final Map<TxIdEntry,Short> txIdTotableIdMap = new ConcurrentHashMap<>();
38
39     private static final int NUMBER_OF_WAIT_CYCLES =2;
40
41     private static final class TxIdEntry {
42         private final TransactionId txId;
43         private final NodeId nodeId;
44         private final StatsRequestType requestType;
45
46         public TxIdEntry(NodeId nodeId, TransactionId txId, StatsRequestType requestType){
47             this.txId = txId;
48             this.nodeId = nodeId;
49             this.requestType = requestType;
50         }
51         public TransactionId getTxId() {
52             return txId;
53         }
54         public NodeId getNodeId() {
55             return nodeId;
56         }
57         public StatsRequestType getRequestType() {
58             return requestType;
59         }
60         @Override
61         public int hashCode() {
62             final int prime = 31;
63             int result = 1;
64             result = prime * result + ((nodeId == null) ? 0 : nodeId.hashCode());
65             result = prime * result + ((txId == null) ? 0 : txId.hashCode());
66             return result;
67         }
68         @Override
69         public boolean equals(Object obj) {
70             if (this == obj) {
71                 return true;
72             }
73             if (obj == null) {
74                 return false;
75             }
76             if (!(obj instanceof TxIdEntry)) {
77                 return false;
78             }
79             TxIdEntry other = (TxIdEntry) obj;
80
81             if (nodeId == null) {
82                 if (other.nodeId != null) {
83                     return false;
84                 }
85             } else if (!nodeId.equals(other.nodeId)) {
86                 return false;
87             }
88             if (txId == null) {
89                 if (other.txId != null) {
90                     return false;
91                 }
92             } else if (!txId.equals(other.txId)) {
93                 return false;
94             }
95             return true;
96         }
97
98         @Override
99         public String toString() {
100             return "TxIdEntry [txId=" + txId + ", nodeId=" + nodeId + ", requestType=" + requestType + "]";
101         }
102     }
103
104     public Short getTableIdForTxId(NodeId nodeId,TransactionId id){
105         return txIdTotableIdMap.get(new TxIdEntry(nodeId,id,null));
106     }
107
108     public void setTxIdAndTableIdMapEntry(NodeId nodeId, TransactionId id,Short tableId){
109         if(id == null)
110             return;
111         txIdTotableIdMap.put(new TxIdEntry(nodeId,id,null), tableId);
112     }
113
114     public boolean isRequestTxIdExist(NodeId nodeId, TransactionId id, Boolean moreRepliesToFollow){
115         TxIdEntry entry = new TxIdEntry(nodeId,id,null);
116         if(moreRepliesToFollow.booleanValue()){
117             return txIdToRequestTypeMap.containsKey(entry);
118         }else{
119             return txIdToRequestTypeMap.remove(entry) != null;
120         }
121     }
122
123     public void addTxIdToRequestTypeEntry (NodeId nodeId, TransactionId id,StatsRequestType type){
124         if(id == null)
125             return;
126         TxIdEntry entry = new TxIdEntry(nodeId,id,type);
127         txIdToRequestTypeMap.put(entry, getExpiryTime());
128     }
129
130     private static Long getExpiryTime(){
131         return System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(
132                 StatisticsProvider.STATS_COLLECTION_MILLIS*NUMBER_OF_WAIT_CYCLES);
133     }
134
135     public enum StatsRequestType{
136         ALL_FLOW,
137         AGGR_FLOW,
138         ALL_PORT,
139         ALL_FLOW_TABLE,
140         ALL_QUEUE_STATS,
141         ALL_GROUP,
142         ALL_METER,
143         GROUP_DESC,
144         METER_CONFIG
145     }
146
147     public void cleanStaleTransactionIds(){
148         final long now = System.nanoTime();
149
150         for (Iterator<TxIdEntry> it = txIdToRequestTypeMap.keySet().iterator();it.hasNext();){
151             TxIdEntry txIdEntry = it.next();
152
153             Long expiryTime = txIdToRequestTypeMap.get(txIdEntry);
154             if(now > expiryTime){
155                 it.remove();
156                 txIdTotableIdMap.remove(txIdEntry);
157             }
158         }
159     }
160 }