36062805c875f90120a163304fd7af57b814862e
[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.TransactionAware;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
17
18 import com.google.common.base.Preconditions;
19
20 /**
21  * Main responsibility of the class is to manage multipart response
22  * for multipart request. It also handles the flow aggregate request
23  * and response mapping.
24  * @author avishnoi@in.ibm.com
25  *
26  */
27 public class MultipartMessageManager {
28     private static final int NUMBER_OF_WAIT_CYCLES = 2;
29
30     /*
31      *  Map for tx id and type of request, to keep track of all the request sent
32      *  by Statistics Manager. Statistics Manager won't entertain any multipart
33      *  response for which it didn't send the request.
34      */
35     private final Map<TxIdEntry,Long> txIdToRequestTypeMap = new ConcurrentHashMap<>();
36     /*
37      * Map to keep track of the request tx id for flow table statistics request.
38      * Because flow table statistics multi part response do not contains the table id.
39      */
40     private final Map<TxIdEntry,Short> txIdTotableIdMap = new ConcurrentHashMap<>();
41
42     private static final class TxIdEntry {
43         private final StatsRequestType requestType;
44         private final TransactionId txId;
45
46         public TxIdEntry(TransactionId txId, StatsRequestType requestType){
47             this.txId = txId;
48             this.requestType = requestType;
49         }
50         public TransactionId getTxId() {
51             return txId;
52         }
53         public StatsRequestType getRequestType() {
54             return requestType;
55         }
56         @Override
57         public int hashCode() {
58             final int prime = 31;
59             int result = 1;
60             result = prime * result + ((txId == null) ? 0 : txId.hashCode());
61             return result;
62         }
63         @Override
64         public boolean equals(Object obj) {
65             if (this == obj) {
66                 return true;
67             }
68             if (obj == null) {
69                 return false;
70             }
71             if (!(obj instanceof TxIdEntry)) {
72                 return false;
73             }
74             TxIdEntry other = (TxIdEntry) obj;
75
76             if (txId == null) {
77                 if (other.txId != null) {
78                     return false;
79                 }
80             } else if (!txId.equals(other.txId)) {
81                 return false;
82             }
83             return true;
84         }
85
86         @Override
87         public String toString() {
88             return "TxIdEntry [txId=" + txId + ", requestType=" + requestType + "]";
89         }
90     }
91
92     public void recordExpectedTableTransaction(TransactionId id, StatsRequestType type, Short tableId) {
93         recordExpectedTransaction(id, type);
94         txIdTotableIdMap.put(new TxIdEntry(id, null), Preconditions.checkNotNull(tableId));
95     }
96
97     public Short isExpectedTableTransaction(TransactionAware transaction, Boolean more) {
98         if (!isExpectedTransaction(transaction, more)) {
99             return null;
100         }
101
102         final TxIdEntry key = new TxIdEntry(transaction.getTransactionId(), null);
103         if (more != null && more.booleanValue()) {
104             return txIdTotableIdMap.get(key);
105         } else {
106             return txIdTotableIdMap.remove(key);
107         }
108     }
109
110     public void recordExpectedTransaction(TransactionId id, StatsRequestType type) {
111         TxIdEntry entry = new TxIdEntry(Preconditions.checkNotNull(id), Preconditions.checkNotNull(type));
112         txIdToRequestTypeMap.put(entry, getExpiryTime());
113     }
114
115     public boolean isExpectedTransaction(TransactionAware transaction, Boolean more) {
116         TxIdEntry entry = new TxIdEntry(transaction.getTransactionId(), null);
117         if (more != null && more.booleanValue()) {
118             return txIdToRequestTypeMap.containsKey(entry);
119         } else {
120             return txIdToRequestTypeMap.remove(entry) != null;
121         }
122     }
123
124     private static Long getExpiryTime(){
125         return System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(
126                 StatisticsProvider.STATS_COLLECTION_MILLIS*NUMBER_OF_WAIT_CYCLES);
127     }
128
129     public enum StatsRequestType{
130         ALL_FLOW,
131         AGGR_FLOW,
132         ALL_PORT,
133         ALL_FLOW_TABLE,
134         ALL_QUEUE_STATS,
135         ALL_GROUP,
136         ALL_METER,
137         GROUP_DESC,
138         METER_CONFIG
139     }
140
141     public void cleanStaleTransactionIds(){
142         final long now = System.nanoTime();
143
144         for (Iterator<TxIdEntry> it = txIdToRequestTypeMap.keySet().iterator();it.hasNext();){
145             TxIdEntry txIdEntry = it.next();
146
147             Long expiryTime = txIdToRequestTypeMap.get(txIdEntry);
148             if(now > expiryTime){
149                 it.remove();
150                 txIdTotableIdMap.remove(txIdEntry);
151             }
152         }
153     }
154 }