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 public ShardStats(final String shardName, final String mxBeanType) {
81 super(shardName, mxBeanType, JMX_CATEGORY_SHARD);
84 public void setNotificationManager(final QueuedNotificationManager<?, ?> manager) {
85 this.notificationManagerStatsBean = new QueuedNotificationManagerMXBeanImpl(manager,
86 "notification-manager", getMBeanType(), getMBeanCategory());
88 this.notificationExecutorStatsBean = ThreadExecutorStatsMXBeanImpl.create(manager.getExecutor());
91 public void setShardActor(ActorRef shardActor) {
92 this.shardActor = shardActor;
95 private OnDemandRaftState getOnDemandRaftState() {
96 String name = getShardName();
97 OnDemandRaftState state = onDemandRaftStateCache.getIfPresent(name);
99 statRetrievalError = null;
100 statRetrievalTime = null;
102 if(shardActor != null) {
103 Timeout timeout = new Timeout(10, TimeUnit.SECONDS);
105 Stopwatch timer = Stopwatch.createStarted();
107 state = (OnDemandRaftState) Await.result(Patterns.ask(shardActor,
108 GetOnDemandRaftState.INSTANCE, timeout), timeout.duration());
110 statRetrievalTime = timer.stop().toString();
111 onDemandRaftStateCache.put(name, state);
112 } catch (Exception e) {
113 statRetrievalError = e.toString();
117 state = state != null ? state : OnDemandRaftState.builder().build();
124 public String getShardName() {
125 return getMBeanName();
129 public long getCommittedTransactionsCount() {
130 return committedTransactionsCount;
134 public String getLeader() {
135 return getOnDemandRaftState().getLeader();
139 public String getRaftState() {
140 return getOnDemandRaftState().getRaftState();
144 public long getReadOnlyTransactionCount() {
145 return readOnlyTransactionCount;
149 public long getWriteOnlyTransactionCount() {
150 return writeOnlyTransactionCount;
154 public long getReadWriteTransactionCount() {
155 return readWriteTransactionCount;
159 public long getLastLogIndex() {
160 return getOnDemandRaftState().getLastLogIndex();
164 public long getLastLogTerm() {
165 return getOnDemandRaftState().getLastLogTerm();
169 public long getCurrentTerm() {
170 return getOnDemandRaftState().getCurrentTerm();
174 public long getCommitIndex() {
175 return getOnDemandRaftState().getCommitIndex();
179 public long getLastApplied() {
180 return getOnDemandRaftState().getLastApplied();
184 public long getLastIndex() {
185 return getOnDemandRaftState().getLastIndex();
189 public long getLastTerm() {
190 return getOnDemandRaftState().getLastTerm();
194 public long getSnapshotIndex() {
195 return getOnDemandRaftState().getSnapshotIndex();
199 public long getSnapshotTerm() {
200 return getOnDemandRaftState().getSnapshotTerm();
204 public long getReplicatedToAllIndex() {
205 return getOnDemandRaftState().getReplicatedToAllIndex();
209 public String getVotedFor() {
210 return getOnDemandRaftState().getVotedFor();
214 public boolean isSnapshotCaptureInitiated() {
215 return getOnDemandRaftState().isSnapshotCaptureInitiated();
219 public String getLastCommittedTransactionTime() {
220 return DATE_FORMAT.format(new Date(lastCommittedTransactionTime));
224 public long getFailedTransactionsCount() {
225 return failedTransactionsCount;
229 public long getFailedReadTransactionsCount() {
230 return failedReadTransactionsCount.get();
234 public long getAbortTransactionsCount() {
235 return abortTransactionsCount;
238 public long incrementCommittedTransactionCount() {
239 return ++committedTransactionsCount;
242 public long incrementReadOnlyTransactionCount() {
243 return ++readOnlyTransactionCount;
246 public long incrementWriteOnlyTransactionCount() {
247 return ++writeOnlyTransactionCount;
250 public long incrementReadWriteTransactionCount() {
251 return ++readWriteTransactionCount;
254 public long incrementFailedTransactionsCount() {
255 return ++failedTransactionsCount;
258 public long incrementFailedReadTransactionsCount() {
259 return failedReadTransactionsCount.incrementAndGet();
262 public long incrementAbortTransactionsCount ()
264 return ++abortTransactionsCount;
267 public void setLastCommittedTransactionTime(final long lastCommittedTransactionTime) {
268 this.lastCommittedTransactionTime = lastCommittedTransactionTime;
272 public long getInMemoryJournalDataSize(){
273 return getOnDemandRaftState().getInMemoryJournalDataSize();
277 public long getInMemoryJournalLogSize() {
278 return getOnDemandRaftState().getInMemoryJournalLogSize();
282 public ThreadExecutorStats getDataStoreExecutorStats() {
283 // FIXME: this particular thing does not work, as it really is DS-specific
288 public ThreadExecutorStats getNotificationMgrExecutorStats() {
289 return notificationExecutorStatsBean.toThreadExecutorStats();
293 public List<ListenerNotificationQueueStats> getCurrentNotificationMgrListenerQueueStats() {
294 return notificationManagerStatsBean.getCurrentListenerQueueStats();
298 public int getMaxNotificationMgrListenerQueueSize() {
299 return notificationManagerStatsBean.getMaxListenerQueueSize();
303 * resets the counters related to transactions
306 public void resetTransactionCounters(){
307 committedTransactionsCount = 0;
309 readOnlyTransactionCount = 0;
311 writeOnlyTransactionCount = 0;
313 readWriteTransactionCount = 0;
315 lastCommittedTransactionTime = 0;
317 failedTransactionsCount = 0;
319 failedReadTransactionsCount.set(0);
321 abortTransactionsCount = 0;
325 public void setDataStore(final InMemoryDOMDataStore store) {
326 setNotificationManager(store.getDataChangeListenerNotificationManager());
329 public void setFollowerInitialSyncStatus(boolean followerInitialSyncStatus) {
330 this.followerInitialSyncStatus = followerInitialSyncStatus;
334 public boolean getFollowerInitialSyncStatus() {
335 return followerInitialSyncStatus;
339 public List<FollowerInfo> getFollowerInfo() {
340 return getOnDemandRaftState().getFollowerInfoList();
344 public String getPeerAddresses() {
345 StringBuilder builder = new StringBuilder();
347 for(Map.Entry<String, String> e: getOnDemandRaftState().getPeerAddresses().entrySet()) {
349 builder.append(", ");
352 builder.append(e.getKey()).append(": ").append(e.getValue());
355 return builder.toString();
359 public String getStatRetrievalTime() {
360 getOnDemandRaftState();
361 return statRetrievalTime;
365 public String getStatRetrievalError() {
366 getOnDemandRaftState();
367 return statRetrievalError;