257684a400b0b36d53844b1f090047db55f14f3f
[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 TransactionId txId;
44
45         public TxIdEntry(TransactionId txId) {
46             this.txId = txId;
47         }
48         public TransactionId getTxId() {
49             return txId;
50         }
51         @Override
52         public int hashCode() {
53             final int prime = 31;
54             int result = 1;
55             result = prime * result + ((txId == null) ? 0 : txId.hashCode());
56             return result;
57         }
58         @Override
59         public boolean equals(Object obj) {
60             if (this == obj) {
61                 return true;
62             }
63             if (obj == null) {
64                 return false;
65             }
66             if (!(obj instanceof TxIdEntry)) {
67                 return false;
68             }
69             TxIdEntry other = (TxIdEntry) obj;
70
71             if (txId == null) {
72                 if (other.txId != null) {
73                     return false;
74                 }
75             } else if (!txId.equals(other.txId)) {
76                 return false;
77             }
78             return true;
79         }
80
81         @Override
82         public String toString() {
83             return "TxIdEntry [txId=" + txId + ']';
84         }
85     }
86
87     public void recordExpectedTableTransaction(TransactionId id, Short tableId) {
88         recordExpectedTransaction(id);
89         txIdTotableIdMap.put(new TxIdEntry(id), Preconditions.checkNotNull(tableId));
90     }
91
92     public Short isExpectedTableTransaction(TransactionAware transaction, Boolean more) {
93         if (!isExpectedTransaction(transaction, more)) {
94             return null;
95         }
96
97         final TxIdEntry key = new TxIdEntry(transaction.getTransactionId());
98         if (more != null && more.booleanValue()) {
99             return txIdTotableIdMap.get(key);
100         } else {
101             return txIdTotableIdMap.remove(key);
102         }
103     }
104
105     public void recordExpectedTransaction(TransactionId id) {
106         TxIdEntry entry = new TxIdEntry(Preconditions.checkNotNull(id));
107         txIdToRequestTypeMap.put(entry, getExpiryTime());
108     }
109
110     public boolean isExpectedTransaction(TransactionAware transaction, Boolean more) {
111         TxIdEntry entry = new TxIdEntry(transaction.getTransactionId());
112         if (more != null && more.booleanValue()) {
113             return txIdToRequestTypeMap.containsKey(entry);
114         } else {
115             return txIdToRequestTypeMap.remove(entry) != null;
116         }
117     }
118
119     private static Long getExpiryTime(){
120         return System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(
121                 StatisticsProvider.STATS_COLLECTION_MILLIS*NUMBER_OF_WAIT_CYCLES);
122     }
123
124     public void cleanStaleTransactionIds() {
125         final long now = System.nanoTime();
126
127         for (Iterator<TxIdEntry> it = txIdToRequestTypeMap.keySet().iterator();it.hasNext();){
128             TxIdEntry txIdEntry = it.next();
129
130             Long expiryTime = txIdToRequestTypeMap.get(txIdEntry);
131             if(now > expiryTime){
132                 it.remove();
133                 txIdTotableIdMap.remove(txIdEntry);
134             }
135         }
136     }
137 }