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