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