Merge "CHange log level from warn to debug in ProtocolSessionPromise when connection...
[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
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
16
17 import com.google.common.base.Preconditions;
18
19 /**
20  * Main responsibility of the class is to manage multipart response
21  * for multipart request. It also handles the flow aggregate request
22  * and response mapping.
23  * @author avishnoi@in.ibm.com
24  *
25  */
26 class MultipartMessageManager {
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     private final long lifetimeNanos;
39
40     public MultipartMessageManager(long lifetimeNanos) {
41         this.lifetimeNanos = lifetimeNanos;
42     }
43
44     private static final class TxIdEntry {
45         private final TransactionId txId;
46
47         public TxIdEntry(TransactionId txId) {
48             this.txId = txId;
49         }
50         public TransactionId getTxId() {
51             return txId;
52         }
53         @Override
54         public int hashCode() {
55             final int prime = 31;
56             int result = 1;
57             result = prime * result + ((txId == null) ? 0 : txId.hashCode());
58             return result;
59         }
60         @Override
61         public boolean equals(Object obj) {
62             if (this == obj) {
63                 return true;
64             }
65             if (obj == null) {
66                 return false;
67             }
68             if (!(obj instanceof TxIdEntry)) {
69                 return false;
70             }
71             TxIdEntry other = (TxIdEntry) obj;
72
73             if (txId == null) {
74                 if (other.txId != null) {
75                     return false;
76                 }
77             } else if (!txId.equals(other.txId)) {
78                 return false;
79             }
80             return true;
81         }
82
83         @Override
84         public String toString() {
85             return "TxIdEntry [txId=" + txId + ']';
86         }
87     }
88
89     public void recordExpectedTableTransaction(TransactionId id, Short tableId) {
90         recordExpectedTransaction(id);
91         txIdTotableIdMap.put(new TxIdEntry(id), Preconditions.checkNotNull(tableId));
92     }
93
94     public Short isExpectedTableTransaction(TransactionAware transaction, Boolean more) {
95         if (!isExpectedTransaction(transaction, more)) {
96             return null;
97         }
98
99         final TxIdEntry key = new TxIdEntry(transaction.getTransactionId());
100         if (more != null && more.booleanValue()) {
101             return txIdTotableIdMap.get(key);
102         } else {
103             return txIdTotableIdMap.remove(key);
104         }
105     }
106
107     public void recordExpectedTransaction(TransactionId id) {
108         TxIdEntry entry = new TxIdEntry(Preconditions.checkNotNull(id));
109         txIdToRequestTypeMap.put(entry, getExpiryTime());
110     }
111
112     public boolean isExpectedTransaction(TransactionAware transaction, Boolean more) {
113         TxIdEntry entry = new TxIdEntry(transaction.getTransactionId());
114         if (more != null && more.booleanValue()) {
115             return txIdToRequestTypeMap.containsKey(entry);
116         } else {
117             return txIdToRequestTypeMap.remove(entry) != null;
118         }
119     }
120
121     private Long getExpiryTime() {
122         return System.nanoTime() + lifetimeNanos;
123     }
124
125     public void cleanStaleTransactionIds() {
126         final long now = System.nanoTime();
127
128         for (Iterator<TxIdEntry> it = txIdToRequestTypeMap.keySet().iterator();it.hasNext();){
129             TxIdEntry txIdEntry = it.next();
130
131             Long expiryTime = txIdToRequestTypeMap.get(txIdEntry);
132             if(now > expiryTime){
133                 it.remove();
134                 txIdTotableIdMap.remove(txIdEntry);
135             }
136         }
137     }
138 }