X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fstatistics-manager%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fmd%2Fstatistics%2Fmanager%2FMultipartMessageManager.java;h=425a44946e064c97b44d27f42fdcdc8b1e2b9bc9;hp=11cce72ef1516655e26d7a5b28daaa37d880d5f9;hb=721b580748cb93b3dac952ff1f111d0ab0da0c79;hpb=2da26725be793b315794e751ecca009c7691008c diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MultipartMessageManager.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MultipartMessageManager.java index 11cce72ef1..425a44946e 100644 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MultipartMessageManager.java +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MultipartMessageManager.java @@ -7,31 +7,147 @@ */ package org.opendaylight.controller.md.statistics.manager; +import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.MultipartTransactionAware; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; +import com.google.common.base.Preconditions; + /** - * Main responsibility of the class is to manage multipart response + * Main responsibility of the class is to manage multipart response * for multipart request. It also handles the flow aggregate request - * and response mapping. + * and response mapping. * @author avishnoi@in.ibm.com * */ -public class MultipartMessageManager { - - private static Map txIdTotableIdMap = new ConcurrentHashMap(); - - public MultipartMessageManager(){} - - public Short getTableIdForTxId(TransactionId id){ - - return txIdTotableIdMap.get(id); - - } - - public void setTxIdAndTableIdMapEntry(TransactionId id,Short tableId){ - txIdTotableIdMap.put(id, tableId); +class MultipartMessageManager { + /* + * 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 final Map txIdToRequestTypeMap = new ConcurrentHashMap<>(); + /* + * 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 final Map txIdTotableIdMap = new ConcurrentHashMap<>(); + private final long lifetimeNanos; + + public MultipartMessageManager(long lifetimeNanos) { + this.lifetimeNanos = lifetimeNanos; + } + + private static final class TxIdEntry { + private final TransactionId txId; + + public TxIdEntry(TransactionId txId) { + this.txId = txId; + } + public TransactionId getTxId() { + return txId; + } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + 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 (txId == null) { + if (other.txId != null) { + return false; + } + } else if (!txId.equals(other.txId)) { + return false; + } + return true; + } + + @Override + public String toString() { + return "TxIdEntry [txId=" + txId + ']'; + } + } + + public void recordExpectedTableTransaction(TransactionId id, Short tableId) { + recordExpectedTransaction(id); + txIdTotableIdMap.put(new TxIdEntry(id), Preconditions.checkNotNull(tableId)); + } + + public Short isExpectedTableTransaction(TransactionAware transaction) { + Boolean more = null; + if (transaction instanceof MultipartTransactionAware) { + more = ((MultipartTransactionAware)transaction).isMoreReplies(); + } + + if (!isExpectedTransaction(transaction, more)) { + return null; + } + + final TxIdEntry key = new TxIdEntry(transaction.getTransactionId()); + if (more != null && more.booleanValue()) { + return txIdTotableIdMap.get(key); + } else { + return txIdTotableIdMap.remove(key); + } + } + + public void recordExpectedTransaction(TransactionId id) { + TxIdEntry entry = new TxIdEntry(Preconditions.checkNotNull(id)); + txIdToRequestTypeMap.put(entry, getExpiryTime()); + } + + private boolean isExpectedTransaction(TransactionAware transaction, Boolean more) { + final TxIdEntry entry = new TxIdEntry(transaction.getTransactionId()); + if (more != null && more.booleanValue()) { + return txIdToRequestTypeMap.containsKey(entry); + } else { + return txIdToRequestTypeMap.remove(entry) != null; + } + } + + public boolean isExpectedTransaction(TransactionAware transaction) { + Boolean more = null; + if (transaction instanceof MultipartTransactionAware) { + more = ((MultipartTransactionAware)transaction).isMoreReplies(); + } + + return isExpectedTransaction(transaction, more); + } + + private Long getExpiryTime() { + return System.nanoTime() + lifetimeNanos; + } + + public void cleanStaleTransactionIds() { + final long now = System.nanoTime(); + + for (Iterator it = txIdToRequestTypeMap.keySet().iterator();it.hasNext();){ + TxIdEntry txIdEntry = it.next(); + + Long expiryTime = txIdToRequestTypeMap.get(txIdEntry); + if(now > expiryTime){ + it.remove(); + txIdTotableIdMap.remove(txIdEntry); + } + } } }