Add LeadershipChangeCount to ShardStats
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / jmx / mbeans / shard / ShardStats.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  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
9 package org.opendaylight.controller.cluster.datastore.jmx.mbeans.shard;
10
11 import akka.actor.ActorRef;
12 import akka.pattern.Patterns;
13 import akka.util.Timeout;
14 import com.google.common.base.Stopwatch;
15 import com.google.common.cache.Cache;
16 import com.google.common.cache.CacheBuilder;
17 import java.text.SimpleDateFormat;
18 import java.util.Date;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.concurrent.TimeUnit;
22 import java.util.concurrent.atomic.AtomicLong;
23 import org.opendaylight.controller.cluster.raft.client.messages.FollowerInfo;
24 import org.opendaylight.controller.cluster.raft.client.messages.GetOnDemandRaftState;
25 import org.opendaylight.controller.cluster.raft.client.messages.OnDemandRaftState;
26 import org.opendaylight.controller.md.sal.common.util.jmx.AbstractMXBean;
27 import org.opendaylight.controller.md.sal.common.util.jmx.QueuedNotificationManagerMXBeanImpl;
28 import org.opendaylight.controller.md.sal.common.util.jmx.ThreadExecutorStats;
29 import org.opendaylight.controller.md.sal.common.util.jmx.ThreadExecutorStatsMXBeanImpl;
30 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
31 import org.opendaylight.yangtools.util.concurrent.ListenerNotificationQueueStats;
32 import org.opendaylight.yangtools.util.concurrent.QueuedNotificationManager;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35 import scala.concurrent.Await;
36
37 /**
38  * Maintains statistics for a shard.
39  *
40  * @author  Basheeruddin syedbahm@cisco.com
41  */
42 public class ShardStats extends AbstractMXBean implements ShardStatsMXBean {
43     public static String JMX_CATEGORY_SHARD = "Shards";
44
45     private static final Logger LOG = LoggerFactory.getLogger(ShardStats.class);
46
47     private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
48
49     private static final Cache<String, OnDemandRaftState> onDemandRaftStateCache =
50             CacheBuilder.newBuilder().expireAfterWrite(2, TimeUnit.SECONDS).build();
51
52     private long committedTransactionsCount;
53
54     private long readOnlyTransactionCount;
55
56     private long writeOnlyTransactionCount;
57
58     private long readWriteTransactionCount;
59
60     private long lastCommittedTransactionTime;
61
62     private long failedTransactionsCount;
63
64     private final AtomicLong failedReadTransactionsCount = new AtomicLong();
65
66     private long abortTransactionsCount;
67
68     private ThreadExecutorStatsMXBeanImpl notificationExecutorStatsBean;
69
70     private QueuedNotificationManagerMXBeanImpl notificationManagerStatsBean;
71
72     private boolean followerInitialSyncStatus = false;
73
74     private ActorRef shardActor;
75
76     private String statRetrievalError;
77
78     private String statRetrievalTime;
79
80     private long leadershipChangeCount;
81
82     private long lastLeadershipChangeTime;
83
84     public ShardStats(final String shardName, final String mxBeanType) {
85         super(shardName, mxBeanType, JMX_CATEGORY_SHARD);
86     }
87
88     public void setNotificationManager(final QueuedNotificationManager<?, ?> manager) {
89         this.notificationManagerStatsBean = new QueuedNotificationManagerMXBeanImpl(manager,
90                 "notification-manager", getMBeanType(), getMBeanCategory());
91
92         this.notificationExecutorStatsBean = ThreadExecutorStatsMXBeanImpl.create(manager.getExecutor());
93     }
94
95     public void setShardActor(ActorRef shardActor) {
96         this.shardActor = shardActor;
97     }
98
99     private OnDemandRaftState getOnDemandRaftState() {
100         String name = getShardName();
101         OnDemandRaftState state = onDemandRaftStateCache.getIfPresent(name);
102         if(state == null) {
103             statRetrievalError = null;
104             statRetrievalTime = null;
105
106             if(shardActor != null) {
107                 Timeout timeout = new Timeout(10, TimeUnit.SECONDS);
108                 try {
109                     Stopwatch timer = Stopwatch.createStarted();
110
111                     state = (OnDemandRaftState) Await.result(Patterns.ask(shardActor,
112                             GetOnDemandRaftState.INSTANCE, timeout), timeout.duration());
113
114                     statRetrievalTime = timer.stop().toString();
115                     onDemandRaftStateCache.put(name, state);
116                 } catch (Exception e) {
117                     statRetrievalError = e.toString();
118                 }
119             }
120
121             state = state != null ? state : OnDemandRaftState.builder().build();
122         }
123
124         return state;
125     }
126
127     @Override
128     public String getShardName() {
129         return getMBeanName();
130     }
131
132     @Override
133     public long getCommittedTransactionsCount() {
134         return committedTransactionsCount;
135     }
136
137     @Override
138     public String getLeader() {
139         return getOnDemandRaftState().getLeader();
140     }
141
142     @Override
143     public String getRaftState() {
144         return getOnDemandRaftState().getRaftState();
145     }
146
147     @Override
148     public long getReadOnlyTransactionCount() {
149         return readOnlyTransactionCount;
150     }
151
152     @Override
153     public long getWriteOnlyTransactionCount() {
154         return writeOnlyTransactionCount;
155     }
156
157     @Override
158     public long getReadWriteTransactionCount() {
159         return readWriteTransactionCount;
160     }
161
162     @Override
163     public long getLastLogIndex() {
164         return getOnDemandRaftState().getLastLogIndex();
165     }
166
167     @Override
168     public long getLastLogTerm() {
169         return getOnDemandRaftState().getLastLogTerm();
170     }
171
172     @Override
173     public long getCurrentTerm() {
174         return getOnDemandRaftState().getCurrentTerm();
175     }
176
177     @Override
178     public long getCommitIndex() {
179         return getOnDemandRaftState().getCommitIndex();
180     }
181
182     @Override
183     public long getLastApplied() {
184         return getOnDemandRaftState().getLastApplied();
185     }
186
187     @Override
188     public long getLastIndex() {
189         return getOnDemandRaftState().getLastIndex();
190     }
191
192     @Override
193     public long getLastTerm() {
194         return getOnDemandRaftState().getLastTerm();
195     }
196
197     @Override
198     public long getSnapshotIndex() {
199         return getOnDemandRaftState().getSnapshotIndex();
200     }
201
202     @Override
203     public long getSnapshotTerm() {
204         return getOnDemandRaftState().getSnapshotTerm();
205     }
206
207     @Override
208     public long getReplicatedToAllIndex() {
209         return getOnDemandRaftState().getReplicatedToAllIndex();
210     }
211
212     @Override
213     public String getVotedFor() {
214         return getOnDemandRaftState().getVotedFor();
215     }
216
217     @Override
218     public boolean isSnapshotCaptureInitiated() {
219         return getOnDemandRaftState().isSnapshotCaptureInitiated();
220     }
221
222     @Override
223     public String getLastCommittedTransactionTime() {
224         return DATE_FORMAT.format(new Date(lastCommittedTransactionTime));
225     }
226
227     @Override
228     public long getFailedTransactionsCount() {
229         return failedTransactionsCount;
230     }
231
232     @Override
233     public long getFailedReadTransactionsCount() {
234         return failedReadTransactionsCount.get();
235     }
236
237     @Override
238     public long getAbortTransactionsCount() {
239         return abortTransactionsCount;
240     }
241
242     public long incrementCommittedTransactionCount() {
243         return ++committedTransactionsCount;
244     }
245
246     public long incrementReadOnlyTransactionCount() {
247         return ++readOnlyTransactionCount;
248     }
249
250     public long incrementWriteOnlyTransactionCount() {
251         return ++writeOnlyTransactionCount;
252     }
253
254     public long incrementReadWriteTransactionCount() {
255         return ++readWriteTransactionCount;
256     }
257
258     public long incrementFailedTransactionsCount() {
259         return ++failedTransactionsCount;
260     }
261
262     public long incrementFailedReadTransactionsCount() {
263         return failedReadTransactionsCount.incrementAndGet();
264     }
265
266     public long incrementAbortTransactionsCount ()
267     {
268         return ++abortTransactionsCount;
269     }
270
271     public void setLastCommittedTransactionTime(final long lastCommittedTransactionTime) {
272         this.lastCommittedTransactionTime = lastCommittedTransactionTime;
273     }
274
275     @Override
276     public long getInMemoryJournalDataSize(){
277         return getOnDemandRaftState().getInMemoryJournalDataSize();
278     }
279
280     @Override
281     public long getInMemoryJournalLogSize() {
282         return getOnDemandRaftState().getInMemoryJournalLogSize();
283     }
284
285     @Override
286     public ThreadExecutorStats getDataStoreExecutorStats() {
287         // FIXME: this particular thing does not work, as it really is DS-specific
288         return null;
289     }
290
291     @Override
292     public ThreadExecutorStats getNotificationMgrExecutorStats() {
293         return notificationExecutorStatsBean.toThreadExecutorStats();
294     }
295
296     @Override
297     public List<ListenerNotificationQueueStats> getCurrentNotificationMgrListenerQueueStats() {
298         return notificationManagerStatsBean.getCurrentListenerQueueStats();
299     }
300
301     @Override
302     public int getMaxNotificationMgrListenerQueueSize() {
303         return notificationManagerStatsBean.getMaxListenerQueueSize();
304     }
305
306     /**
307      * resets the counters related to transactions
308      */
309     @Override
310     public void resetTransactionCounters(){
311         committedTransactionsCount = 0;
312
313         readOnlyTransactionCount = 0;
314
315         writeOnlyTransactionCount = 0;
316
317         readWriteTransactionCount = 0;
318
319         lastCommittedTransactionTime = 0;
320
321         failedTransactionsCount = 0;
322
323         failedReadTransactionsCount.set(0);
324
325         abortTransactionsCount = 0;
326
327     }
328
329     public void setDataStore(final InMemoryDOMDataStore store) {
330         setNotificationManager(store.getDataChangeListenerNotificationManager());
331     }
332
333     public void setFollowerInitialSyncStatus(boolean followerInitialSyncStatus) {
334         this.followerInitialSyncStatus = followerInitialSyncStatus;
335     }
336
337     @Override
338     public boolean getFollowerInitialSyncStatus() {
339         return followerInitialSyncStatus;
340     }
341
342     @Override
343     public List<FollowerInfo> getFollowerInfo() {
344         return getOnDemandRaftState().getFollowerInfoList();
345     }
346
347     @Override
348     public String getPeerAddresses() {
349         StringBuilder builder = new StringBuilder();
350         int i = 0;
351         for(Map.Entry<String, String> e: getOnDemandRaftState().getPeerAddresses().entrySet()) {
352             if(i++ > 0) {
353                 builder.append(", ");
354             }
355
356             builder.append(e.getKey()).append(": ").append(e.getValue());
357         }
358
359         return builder.toString();
360     }
361
362     @Override
363     public String getStatRetrievalTime() {
364         getOnDemandRaftState();
365         return statRetrievalTime;
366     }
367
368     @Override
369     public String getStatRetrievalError() {
370         getOnDemandRaftState();
371         return statRetrievalError;
372     }
373
374     @Override
375     public long getLeadershipChangeCount() {
376         return leadershipChangeCount;
377     }
378
379     public void incrementLeadershipChangeCount() {
380         leadershipChangeCount++;
381         lastLeadershipChangeTime = System.currentTimeMillis();
382     }
383
384     @Override
385     public String getLastLeadershipChangeTime() {
386         return DATE_FORMAT.format(new Date(lastLeadershipChangeTime));
387     }
388 }