02c838a3c6d900bc54162d913a3cc908f509043a
[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.Joiner;
15 import com.google.common.base.Joiner.MapJoiner;
16 import com.google.common.base.Stopwatch;
17 import com.google.common.cache.Cache;
18 import com.google.common.cache.CacheBuilder;
19 import java.text.SimpleDateFormat;
20 import java.util.Date;
21 import java.util.List;
22 import java.util.concurrent.TimeUnit;
23 import java.util.concurrent.atomic.AtomicLong;
24 import javax.annotation.Nullable;
25 import javax.annotation.concurrent.GuardedBy;
26 import org.opendaylight.controller.cluster.datastore.Shard;
27 import org.opendaylight.controller.cluster.raft.base.messages.InitiateCaptureSnapshot;
28 import org.opendaylight.controller.cluster.raft.client.messages.FollowerInfo;
29 import org.opendaylight.controller.cluster.raft.client.messages.GetOnDemandRaftState;
30 import org.opendaylight.controller.cluster.raft.client.messages.OnDemandRaftState;
31 import org.opendaylight.controller.md.sal.common.util.jmx.AbstractMXBean;
32 import scala.concurrent.Await;
33
34 /**
35  * Maintains statistics for a shard.
36  *
37  * @author  Basheeruddin syedbahm@cisco.com
38  */
39 public class ShardStats extends AbstractMXBean implements ShardStatsMXBean {
40     public static final String JMX_CATEGORY_SHARD = "Shards";
41
42     @GuardedBy("DATE_FORMAT")
43     private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
44
45     private static final Cache<String, OnDemandRaftState> ONDEMAND_RAFT_STATE_CACHE =
46             CacheBuilder.newBuilder().expireAfterWrite(2, TimeUnit.SECONDS).build();
47
48     private static final MapJoiner MAP_JOINER = Joiner.on(", ").withKeyValueSeparator(": ");
49
50     private long committedTransactionsCount;
51
52     private long readOnlyTransactionCount;
53
54     private long writeOnlyTransactionCount;
55
56     private long readWriteTransactionCount;
57
58     private long lastCommittedTransactionTime;
59
60     private long failedTransactionsCount;
61
62     private final AtomicLong failedReadTransactionsCount = new AtomicLong();
63
64     private long abortTransactionsCount;
65
66     private boolean followerInitialSyncStatus = false;
67
68     private final Shard shard;
69
70     private String statRetrievalError;
71
72     private String statRetrievalTime;
73
74     private long leadershipChangeCount;
75
76     private long lastLeadershipChangeTime;
77
78     public ShardStats(final String shardName, final String mxBeanType, @Nullable final Shard shard) {
79         super(shardName, mxBeanType, JMX_CATEGORY_SHARD);
80         this.shard = shard;
81     }
82
83     @SuppressWarnings("checkstyle:IllegalCatch")
84     private OnDemandRaftState getOnDemandRaftState() {
85         String name = getShardName();
86         OnDemandRaftState state = ONDEMAND_RAFT_STATE_CACHE.getIfPresent(name);
87         if (state == null) {
88             statRetrievalError = null;
89             statRetrievalTime = null;
90
91             if (shard != null) {
92                 Timeout timeout = new Timeout(10, TimeUnit.SECONDS);
93                 try {
94                     Stopwatch timer = Stopwatch.createStarted();
95
96                     state = (OnDemandRaftState) Await.result(Patterns.ask(shard.getSelf(),
97                             GetOnDemandRaftState.INSTANCE, timeout), timeout.duration());
98
99                     statRetrievalTime = timer.stop().toString();
100                     ONDEMAND_RAFT_STATE_CACHE.put(name, state);
101                 } catch (Exception e) {
102                     statRetrievalError = e.toString();
103                 }
104             }
105
106             state = state != null ? state : OnDemandRaftState.builder().build();
107         }
108
109         return state;
110     }
111
112     private static String formatMillis(final long timeMillis) {
113         synchronized (DATE_FORMAT) {
114             return DATE_FORMAT.format(new Date(timeMillis));
115         }
116     }
117
118     @Override
119     public String getShardName() {
120         return getMBeanName();
121     }
122
123     @Override
124     public long getCommittedTransactionsCount() {
125         return committedTransactionsCount;
126     }
127
128     @Override
129     public String getLeader() {
130         return getOnDemandRaftState().getLeader();
131     }
132
133     @Override
134     public String getRaftState() {
135         return getOnDemandRaftState().getRaftState();
136     }
137
138     @Override
139     public long getReadOnlyTransactionCount() {
140         return readOnlyTransactionCount;
141     }
142
143     @Override
144     public long getWriteOnlyTransactionCount() {
145         return writeOnlyTransactionCount;
146     }
147
148     @Override
149     public long getReadWriteTransactionCount() {
150         return readWriteTransactionCount;
151     }
152
153     @Override
154     public long getLastLogIndex() {
155         return getOnDemandRaftState().getLastLogIndex();
156     }
157
158     @Override
159     public long getLastLogTerm() {
160         return getOnDemandRaftState().getLastLogTerm();
161     }
162
163     @Override
164     public long getCurrentTerm() {
165         return getOnDemandRaftState().getCurrentTerm();
166     }
167
168     @Override
169     public long getCommitIndex() {
170         return getOnDemandRaftState().getCommitIndex();
171     }
172
173     @Override
174     public long getLastApplied() {
175         return getOnDemandRaftState().getLastApplied();
176     }
177
178     @Override
179     public long getLastIndex() {
180         return getOnDemandRaftState().getLastIndex();
181     }
182
183     @Override
184     public long getLastTerm() {
185         return getOnDemandRaftState().getLastTerm();
186     }
187
188     @Override
189     public long getSnapshotIndex() {
190         return getOnDemandRaftState().getSnapshotIndex();
191     }
192
193     @Override
194     public long getSnapshotTerm() {
195         return getOnDemandRaftState().getSnapshotTerm();
196     }
197
198     @Override
199     public long getReplicatedToAllIndex() {
200         return getOnDemandRaftState().getReplicatedToAllIndex();
201     }
202
203     @Override
204     public String getVotedFor() {
205         return getOnDemandRaftState().getVotedFor();
206     }
207
208     @Override
209     public boolean isVoting() {
210         return getOnDemandRaftState().isVoting();
211     }
212
213     @Override
214     public String getPeerVotingStates() {
215         return MAP_JOINER.join(getOnDemandRaftState().getPeerVotingStates());
216     }
217
218     @Override
219     public boolean isSnapshotCaptureInitiated() {
220         return getOnDemandRaftState().isSnapshotCaptureInitiated();
221     }
222
223     @Override
224     public String getLastCommittedTransactionTime() {
225         return formatMillis(lastCommittedTransactionTime);
226     }
227
228     @Override
229     public long getFailedTransactionsCount() {
230         return failedTransactionsCount;
231     }
232
233     @Override
234     public long getFailedReadTransactionsCount() {
235         return failedReadTransactionsCount.get();
236     }
237
238     @Override
239     public long getAbortTransactionsCount() {
240         return abortTransactionsCount;
241     }
242
243     public long incrementCommittedTransactionCount() {
244         return ++committedTransactionsCount;
245     }
246
247     public long incrementReadOnlyTransactionCount() {
248         return ++readOnlyTransactionCount;
249     }
250
251     public long incrementWriteOnlyTransactionCount() {
252         return ++writeOnlyTransactionCount;
253     }
254
255     public long incrementReadWriteTransactionCount() {
256         return ++readWriteTransactionCount;
257     }
258
259     public long incrementFailedTransactionsCount() {
260         return ++failedTransactionsCount;
261     }
262
263     public long incrementFailedReadTransactionsCount() {
264         return failedReadTransactionsCount.incrementAndGet();
265     }
266
267     public long incrementAbortTransactionsCount() {
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     /**
286      * Resets the counters related to transactions.
287      */
288     @Override
289     public void resetTransactionCounters() {
290         committedTransactionsCount = 0;
291
292         readOnlyTransactionCount = 0;
293
294         writeOnlyTransactionCount = 0;
295
296         readWriteTransactionCount = 0;
297
298         lastCommittedTransactionTime = 0;
299
300         failedTransactionsCount = 0;
301
302         failedReadTransactionsCount.set(0);
303
304         abortTransactionsCount = 0;
305
306     }
307
308     public void setFollowerInitialSyncStatus(final boolean followerInitialSyncStatus) {
309         this.followerInitialSyncStatus = followerInitialSyncStatus;
310     }
311
312     @Override
313     public boolean getFollowerInitialSyncStatus() {
314         return followerInitialSyncStatus;
315     }
316
317     @Override
318     public List<FollowerInfo> getFollowerInfo() {
319         return getOnDemandRaftState().getFollowerInfoList();
320     }
321
322     @Override
323     public String getPeerAddresses() {
324         return MAP_JOINER.join(getOnDemandRaftState().getPeerAddresses());
325     }
326
327     @Override
328     public String getStatRetrievalTime() {
329         getOnDemandRaftState();
330         return statRetrievalTime;
331     }
332
333     @Override
334     public String getStatRetrievalError() {
335         getOnDemandRaftState();
336         return statRetrievalError;
337     }
338
339     @Override
340     public long getLeadershipChangeCount() {
341         return leadershipChangeCount;
342     }
343
344     public void incrementLeadershipChangeCount() {
345         leadershipChangeCount++;
346         lastLeadershipChangeTime = System.currentTimeMillis();
347     }
348
349     @Override
350     public String getLastLeadershipChangeTime() {
351         return formatMillis(lastLeadershipChangeTime);
352     }
353
354     @Override
355     public int getPendingTxCommitQueueSize() {
356         return shard != null ? shard.getPendingTxCommitQueueSize() : -1;
357     }
358
359     @Override
360     public int getTxCohortCacheSize() {
361         return shard != null ? shard.getCohortCacheSize() : -1;
362     }
363
364     @Override
365     public void captureSnapshot() {
366         if (shard != null) {
367             shard.getSelf().tell(new InitiateCaptureSnapshot(), ActorRef.noSender());
368         }
369     }
370 }