BUG-972: correct Precondition
[controller.git] / opendaylight / md-sal / statistics-manager / src / main / java / org / opendaylight / controller / md / statistics / manager / AbstractStatsTracker.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.HashMap;
11 import java.util.Iterator;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Map.Entry;
15 import java.util.concurrent.Future;
16
17 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
22 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
23 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
24 import org.opendaylight.yangtools.yang.common.RpcResult;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 import com.google.common.base.Preconditions;
29 import com.google.common.util.concurrent.FutureCallback;
30 import com.google.common.util.concurrent.Futures;
31 import com.google.common.util.concurrent.JdkFutureAdapters;
32
33 abstract class AbstractStatsTracker<I, K> {
34     private static final Logger logger = LoggerFactory.getLogger(AbstractStatsTracker.class);
35     
36     private static final int WAIT_FOR_REQUEST_CYCLE = 2;
37     
38     private final FutureCallback<RpcResult<? extends TransactionAware>> callback =
39             new FutureCallback<RpcResult<? extends TransactionAware>>() {
40         @Override
41         public void onSuccess(RpcResult<? extends TransactionAware> result) {
42             if (result.isSuccessful()) {
43                 final TransactionId id = result.getResult().getTransactionId();
44                 if (id == null) {
45                     final Throwable t = new UnsupportedOperationException("No protocol support");
46                     t.fillInStackTrace();
47                     onFailure(t);
48                 } else {
49                     context.registerTransaction(id);
50                 }
51             } else {
52                 logger.debug("Statistics request failed: {}", result.getErrors());
53
54                 final Throwable t = new RPCFailedException("Failed to send statistics request", result.getErrors());
55                 t.fillInStackTrace();
56                 onFailure(t);
57             }
58         }
59
60         @Override
61         public void onFailure(Throwable t) {
62             logger.debug("Failed to send statistics request", t);
63         }
64     };
65
66     private final Map<K, Long> trackedItems = new HashMap<>();
67     private final FlowCapableContext context;
68     private long requestCounter;
69
70     protected AbstractStatsTracker(final FlowCapableContext context) {
71         this.context = Preconditions.checkNotNull(context);
72         this.requestCounter = 0;
73     }
74
75     protected final InstanceIdentifierBuilder<Node> getNodeIdentifierBuilder() {
76         return InstanceIdentifier.builder(getNodeIdentifier());
77     }
78
79     protected final NodeRef getNodeRef() {
80         return context.getNodeRef();
81     }
82
83     protected final InstanceIdentifier<Node> getNodeIdentifier() {
84         return context.getNodeIdentifier();
85     }
86
87     protected final <T extends TransactionAware> void requestHelper(Future<RpcResult<T>> future) {
88         Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), callback);
89     }
90
91     protected final DataModificationTransaction startTransaction() {
92         return context.startDataModification();
93     }
94
95     public final synchronized void increaseRequestCounter(){
96         this.requestCounter++;
97     }
98     protected abstract void cleanupSingleStat(DataModificationTransaction trans, K item);
99     protected abstract K updateSingleStat(DataModificationTransaction trans, I item);
100     public abstract void request();
101
102     public final synchronized void updateStats(List<I> list) {
103
104         final DataModificationTransaction trans = startTransaction();
105
106         for (final I item : list) {
107             trackedItems.put(updateSingleStat(trans, item), requestCounter);
108         }
109
110         trans.commit();
111     }
112
113     /**
114      * Statistics will be cleaned up if not update in last two request cycles.
115      * @param trans
116      */
117     public final synchronized void cleanup(final DataModificationTransaction trans) {
118         for (Iterator<Entry<K, Long>> it = trackedItems.entrySet().iterator();it.hasNext();){
119             Entry<K, Long> e = it.next();
120             if (requestCounter >= e.getValue()+WAIT_FOR_REQUEST_CYCLE) {
121                 cleanupSingleStat(trans, e.getKey());
122                 it.remove();
123             }
124         }
125     }
126 }