2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.controller.cluster.datastore.jmx.mbeans.shard;
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;
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;
38 * Maintains statistics for a shard.
40 * @author Basheeruddin syedbahm@cisco.com
42 public class ShardStats extends AbstractMXBean implements ShardStatsMXBean {
43 public static String JMX_CATEGORY_SHARD = "Shards";
45 private static final Logger LOG = LoggerFactory.getLogger(ShardStats.class);
47 private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
49 private static final Cache<String, OnDemandRaftState> onDemandRaftStateCache =
50 CacheBuilder.newBuilder().expireAfterWrite(2, TimeUnit.SECONDS).build();
52 private long committedTransactionsCount;
54 private long readOnlyTransactionCount;
56 private long writeOnlyTransactionCount;
58 private long readWriteTransactionCount;
60 private long lastCommittedTransactionTime;
62 private long failedTransactionsCount;
64 private final AtomicLong failedReadTransactionsCount = new AtomicLong();
66 private long abortTransactionsCount;
68 private ThreadExecutorStatsMXBeanImpl notificationExecutorStatsBean;
70 private QueuedNotificationManagerMXBeanImpl notificationManagerStatsBean;
72 private boolean followerInitialSyncStatus = false;
74 private ActorRef shardActor;
76 private String statRetrievalError;
78 private String statRetrievalTime;
80 private long leadershipChangeCount;
82 private long lastLeadershipChangeTime;
84 public ShardStats(final String shardName, final String mxBeanType) {
85 super(shardName, mxBeanType, JMX_CATEGORY_SHARD);
88 public void setNotificationManager(final QueuedNotificationManager<?, ?> manager) {
89 this.notificationManagerStatsBean = new QueuedNotificationManagerMXBeanImpl(manager,
90 "notification-manager", getMBeanType(), getMBeanCategory());
92 this.notificationExecutorStatsBean = ThreadExecutorStatsMXBeanImpl.create(manager.getExecutor());
95 public void setShardActor(ActorRef shardActor) {
96 this.shardActor = shardActor;
99 private OnDemandRaftState getOnDemandRaftState() {
100 String name = getShardName();
101 OnDemandRaftState state = onDemandRaftStateCache.getIfPresent(name);
103 statRetrievalError = null;
104 statRetrievalTime = null;
106 if(shardActor != null) {
107 Timeout timeout = new Timeout(10, TimeUnit.SECONDS);
109 Stopwatch timer = Stopwatch.createStarted();
111 state = (OnDemandRaftState) Await.result(Patterns.ask(shardActor,
112 GetOnDemandRaftState.INSTANCE, timeout), timeout.duration());
114 statRetrievalTime = timer.stop().toString();
115 onDemandRaftStateCache.put(name, state);
116 } catch (Exception e) {
117 statRetrievalError = e.toString();
121 state = state != null ? state : OnDemandRaftState.builder().build();
128 public String getShardName() {
129 return getMBeanName();
133 public long getCommittedTransactionsCount() {
134 return committedTransactionsCount;
138 public String getLeader() {
139 return getOnDemandRaftState().getLeader();
143 public String getRaftState() {
144 return getOnDemandRaftState().getRaftState();
148 public long getReadOnlyTransactionCount() {
149 return readOnlyTransactionCount;
153 public long getWriteOnlyTransactionCount() {
154 return writeOnlyTransactionCount;
158 public long getReadWriteTransactionCount() {
159 return readWriteTransactionCount;
163 public long getLastLogIndex() {
164 return getOnDemandRaftState().getLastLogIndex();
168 public long getLastLogTerm() {
169 return getOnDemandRaftState().getLastLogTerm();
173 public long getCurrentTerm() {
174 return getOnDemandRaftState().getCurrentTerm();
178 public long getCommitIndex() {
179 return getOnDemandRaftState().getCommitIndex();
183 public long getLastApplied() {
184 return getOnDemandRaftState().getLastApplied();
188 public long getLastIndex() {
189 return getOnDemandRaftState().getLastIndex();
193 public long getLastTerm() {
194 return getOnDemandRaftState().getLastTerm();
198 public long getSnapshotIndex() {
199 return getOnDemandRaftState().getSnapshotIndex();
203 public long getSnapshotTerm() {
204 return getOnDemandRaftState().getSnapshotTerm();
208 public long getReplicatedToAllIndex() {
209 return getOnDemandRaftState().getReplicatedToAllIndex();
213 public String getVotedFor() {
214 return getOnDemandRaftState().getVotedFor();
218 public boolean isSnapshotCaptureInitiated() {
219 return getOnDemandRaftState().isSnapshotCaptureInitiated();
223 public String getLastCommittedTransactionTime() {
224 return DATE_FORMAT.format(new Date(lastCommittedTransactionTime));
228 public long getFailedTransactionsCount() {
229 return failedTransactionsCount;
233 public long getFailedReadTransactionsCount() {
234 return failedReadTransactionsCount.get();
238 public long getAbortTransactionsCount() {
239 return abortTransactionsCount;
242 public long incrementCommittedTransactionCount() {
243 return ++committedTransactionsCount;
246 public long incrementReadOnlyTransactionCount() {
247 return ++readOnlyTransactionCount;
250 public long incrementWriteOnlyTransactionCount() {
251 return ++writeOnlyTransactionCount;
254 public long incrementReadWriteTransactionCount() {
255 return ++readWriteTransactionCount;
258 public long incrementFailedTransactionsCount() {
259 return ++failedTransactionsCount;
262 public long incrementFailedReadTransactionsCount() {
263 return failedReadTransactionsCount.incrementAndGet();
266 public long incrementAbortTransactionsCount ()
268 return ++abortTransactionsCount;
271 public void setLastCommittedTransactionTime(final long lastCommittedTransactionTime) {
272 this.lastCommittedTransactionTime = lastCommittedTransactionTime;
276 public long getInMemoryJournalDataSize(){
277 return getOnDemandRaftState().getInMemoryJournalDataSize();
281 public long getInMemoryJournalLogSize() {
282 return getOnDemandRaftState().getInMemoryJournalLogSize();
286 public ThreadExecutorStats getDataStoreExecutorStats() {
287 // FIXME: this particular thing does not work, as it really is DS-specific
292 public ThreadExecutorStats getNotificationMgrExecutorStats() {
293 return notificationExecutorStatsBean.toThreadExecutorStats();
297 public List<ListenerNotificationQueueStats> getCurrentNotificationMgrListenerQueueStats() {
298 return notificationManagerStatsBean.getCurrentListenerQueueStats();
302 public int getMaxNotificationMgrListenerQueueSize() {
303 return notificationManagerStatsBean.getMaxListenerQueueSize();
307 * resets the counters related to transactions
310 public void resetTransactionCounters(){
311 committedTransactionsCount = 0;
313 readOnlyTransactionCount = 0;
315 writeOnlyTransactionCount = 0;
317 readWriteTransactionCount = 0;
319 lastCommittedTransactionTime = 0;
321 failedTransactionsCount = 0;
323 failedReadTransactionsCount.set(0);
325 abortTransactionsCount = 0;
329 public void setDataStore(final InMemoryDOMDataStore store) {
330 setNotificationManager(store.getDataChangeListenerNotificationManager());
333 public void setFollowerInitialSyncStatus(boolean followerInitialSyncStatus) {
334 this.followerInitialSyncStatus = followerInitialSyncStatus;
338 public boolean getFollowerInitialSyncStatus() {
339 return followerInitialSyncStatus;
343 public List<FollowerInfo> getFollowerInfo() {
344 return getOnDemandRaftState().getFollowerInfoList();
348 public String getPeerAddresses() {
349 StringBuilder builder = new StringBuilder();
351 for(Map.Entry<String, String> e: getOnDemandRaftState().getPeerAddresses().entrySet()) {
353 builder.append(", ");
356 builder.append(e.getKey()).append(": ").append(e.getValue());
359 return builder.toString();
363 public String getStatRetrievalTime() {
364 getOnDemandRaftState();
365 return statRetrievalTime;
369 public String getStatRetrievalError() {
370 getOnDemandRaftState();
371 return statRetrievalError;
375 public long getLeadershipChangeCount() {
376 return leadershipChangeCount;
379 public void incrementLeadershipChangeCount() {
380 leadershipChangeCount++;
381 lastLeadershipChangeTime = System.currentTimeMillis();
385 public String getLastLeadershipChangeTime() {
386 return DATE_FORMAT.format(new Date(lastLeadershipChangeTime));