Bug 1073: Implemented Transaction chain on InMemoryDOMDataStore level.
[controller.git] / opendaylight / md-sal / statistics-manager / src / main / java / org / opendaylight / controller / md / statistics / manager / StatisticsRequestScheduler.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.Collections;
11 import java.util.Iterator;
12 import java.util.LinkedHashMap;
13 import java.util.Map;
14 import java.util.Timer;
15 import java.util.TimerTask;
16 import java.util.concurrent.TimeUnit;
17
18 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
19 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
20 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction.DataTransactionListener;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 /**
25  * Main responsibility of the class is to check the MD-SAL data store read/write
26  * transaction accumulation level and send statistics request if number of pending 
27  * read/write transactions are zero.
28  * @author avishnoi@in.ibm.com
29  *
30  */
31 @SuppressWarnings("rawtypes")
32 public class StatisticsRequestScheduler implements DataTransactionListener {
33
34     private static final Logger srsLogger = LoggerFactory.getLogger(StatisticsRequestScheduler.class);
35     private final Timer timer = new Timer("request-monitor", true);
36
37     // We need ordered retrieval, and O(1) contains operation
38     private final Map<AbstractStatsTracker,Integer> requestQueue = 
39             Collections.synchronizedMap(new LinkedHashMap<AbstractStatsTracker,Integer>());
40     
41     private Long PendingTransactions;
42     
43     private long lastRequestTime = System.nanoTime();
44     
45     private static final long REQUEST_MONITOR_INTERVAL = 1000;
46     
47     private final TimerTask task = new TimerTask() {
48         @Override
49         public void run() {
50             long now = System.nanoTime();
51             if(now > lastRequestTime+TimeUnit.MILLISECONDS.toNanos(REQUEST_MONITOR_INTERVAL)){
52                 requestStatistics();
53             }
54         }
55     };
56
57     public StatisticsRequestScheduler(){
58         PendingTransactions = (long) 0;
59     }
60     
61     public void addRequestToSchedulerQueue(AbstractStatsTracker statsRequest){
62         requestQueue.put(statsRequest, null);
63     }
64     
65     public AbstractStatsTracker getNextRequestFromSchedulerQueue(){
66         //Remove first element
67         AbstractStatsTracker stats = null;
68         synchronized(requestQueue){
69             Iterator<Map.Entry<AbstractStatsTracker, Integer>> nodesItr = requestQueue.entrySet().iterator();
70             if(nodesItr.hasNext()){
71                 stats = nodesItr.next().getKey();
72                 srsLogger.debug("{} chosen up for execution",stats.getNodeRef());
73                 nodesItr.remove();
74                 return stats;
75             }
76         }
77         return stats;
78     }
79
80     private void requestStatistics(){
81         AbstractStatsTracker stats = this.getNextRequestFromSchedulerQueue();
82         if(stats != null) {
83             stats.request();
84             stats.increaseRequestCounter();
85         }
86     }
87     @Override
88     public void onStatusUpdated(DataModificationTransaction transaction, TransactionStatus status) {
89         
90         AbstractStatsTracker stats = null;
91         synchronized(PendingTransactions){
92             switch(status){
93             case SUBMITED:
94                 this.PendingTransactions++;
95                 break;
96             case COMMITED:
97             case FAILED:
98                 this.PendingTransactions--;
99                 if(PendingTransactions == 0){
100                     lastRequestTime = System.nanoTime();
101                     stats = this.getNextRequestFromSchedulerQueue();
102                 }
103                 srsLogger.debug("Pending MD-SAL transactions : {} & Scheduler queue size : {}",this.PendingTransactions,this.requestQueue.size());
104                 break;
105             default:
106                 break;
107             }
108         }
109         if(stats != null){
110             stats.request();
111             stats.increaseRequestCounter();
112         }
113     }
114     
115     public void start(){
116         timer.schedule(task, 0, REQUEST_MONITOR_INTERVAL);
117     }
118 }