1 /***
2 * Copyright 2003-2010 Terracotta, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package net.sf.ehcache.management.sampled;
18
19 import java.util.HashMap;
20 import java.util.Map;
21
22 import javax.management.MBeanNotificationInfo;
23 import javax.management.NotCompliantMBeanException;
24 import javax.management.Notification;
25
26 import net.sf.ehcache.Cache;
27 import net.sf.ehcache.CacheException;
28 import net.sf.ehcache.CacheManager;
29 import net.sf.ehcache.Ehcache;
30 import net.sf.ehcache.Status;
31 import net.sf.ehcache.config.CacheWriterConfiguration;
32 import net.sf.ehcache.event.CacheManagerEventListener;
33 import net.sf.ehcache.hibernate.management.impl.BaseEmitterBean;
34 import net.sf.ehcache.statistics.LiveCacheStatistics;
35 import net.sf.ehcache.statistics.sampled.SampledCacheStatistics;
36 import net.sf.ehcache.writer.writebehind.WriteBehindManager;
37
38 /***
39 * An implementation of {@link SampledCacheManagerMBean}
40 *
41 * <p />
42 *
43 * @author <a href="mailto:asanoujam@terracottatech.com">Abhishek Sanoujam</a>
44 * @since 1.7
45 */
46 public class SampledCacheManager extends BaseEmitterBean implements SampledCacheManagerMBean {
47 private static final MBeanNotificationInfo[] NOTIFICATION_INFO;
48
49 private final CacheManager cacheManager;
50 private String mbeanRegisteredName;
51 private volatile boolean mbeanRegisteredNameSet;
52 private final EventListener cacheManagerEventListener;
53
54 static {
55 final String[] notifTypes = new String[] {CACHES_ENABLED, CACHES_CLEARED, STATISTICS_ENABLED, STATISTICS_RESET, };
56 final String name = Notification.class.getName();
57 final String description = "Ehcache SampledCacheManager Event";
58 NOTIFICATION_INFO = new MBeanNotificationInfo[] {new MBeanNotificationInfo(notifTypes, name, description), };
59 }
60
61 /***
62 * Constructor taking the backing {@link CacheManager}
63 *
64 * @param cacheManager
65 */
66 public SampledCacheManager(CacheManager cacheManager) throws NotCompliantMBeanException {
67 super(SampledCacheManagerMBean.class);
68 this.cacheManager = cacheManager;
69 cacheManagerEventListener = new EventListener();
70 cacheManager.setCacheManagerEventListener(cacheManagerEventListener);
71 }
72
73 /***
74 * {@inheritDoc}
75 */
76 @Override
77 protected void doDispose() {
78 cacheManager.getCacheManagerEventListenerRegistry().unregisterListener(cacheManagerEventListener);
79 }
80
81 /***
82 * Listen for caches coming and going so that we can add a PropertyChangeListener.
83 */
84 private static class EventListener implements CacheManagerEventListener {
85 private Status status = Status.STATUS_UNINITIALISED;
86
87 public void dispose() throws CacheException {
88 status = Status.STATUS_SHUTDOWN;
89 }
90
91 public Status getStatus() {
92 return status;
93 }
94
95 public void init() throws CacheException {
96 status = Status.STATUS_ALIVE;
97 }
98
99 public void notifyCacheAdded(String cacheName) {
100 /***/
101 }
102
103 public void notifyCacheRemoved(String cacheName) {
104 /***/
105 }
106 }
107
108 /***
109 * Set the name used to register this mbean. Can be called only once.
110 * Package protected method
111 */
112 void setMBeanRegisteredName(String name) {
113 if (mbeanRegisteredNameSet) {
114 throw new IllegalStateException("Name used for registering this mbean is already set");
115 }
116 mbeanRegisteredNameSet = true;
117 mbeanRegisteredName = name;
118 }
119
120 /***
121 * {@inheritDoc}
122 */
123 public void clearAll() {
124 cacheManager.clearAll();
125 sendNotification(CACHES_CLEARED);
126 }
127
128 /***
129 * {@inheritDoc}
130 */
131 public String[] getCacheNames() throws IllegalStateException {
132 return cacheManager.getCacheNames();
133 }
134
135 /***
136 * {@inheritDoc}
137 */
138 public String getStatus() {
139 return cacheManager.getStatus().toString();
140 }
141
142 /***
143 * {@inheritDoc}
144 */
145 public void shutdown() {
146
147 }
148
149 /***
150 * @return map of cache metrics (hits, misses)
151 */
152 public Map<String, long[]> getCacheMetrics() {
153 Map<String, long[]> result = new HashMap<String, long[]>();
154 for (String cacheName : getCacheNames()) {
155 Ehcache cache = cacheManager.getEhcache(cacheName);
156 if (cache != null) {
157 SampledCacheStatistics stats = cache.getSampledCacheStatistics();
158 result.put(cacheName, new long[] {stats.getCacheHitMostRecentSample(),
159 stats.getCacheMissNotFoundMostRecentSample()
160 + stats.getCacheMissExpiredMostRecentSample(),
161 stats.getCacheElementPutMostRecentSample(), });
162 }
163 }
164 return result;
165 }
166
167 /***
168 * @return aggregate hit rate
169 */
170 public long getCacheHitRate() {
171 long result = 0;
172 for (String cacheName : getCacheNames()) {
173 Ehcache cache = cacheManager.getEhcache(cacheName);
174 if (cache != null) {
175 SampledCacheStatistics stats = cache.getSampledCacheStatistics();
176 result += stats.getCacheHitMostRecentSample();
177 }
178 }
179 return result;
180 }
181
182 /***
183 * @return aggregate in-memory hit rate
184 */
185 public long getCacheInMemoryHitRate() {
186 long result = 0;
187 for (String cacheName : getCacheNames()) {
188 Ehcache cache = cacheManager.getEhcache(cacheName);
189 if (cache != null) {
190 SampledCacheStatistics stats = cache.getSampledCacheStatistics();
191 result += stats.getCacheHitInMemoryMostRecentSample();
192 }
193 }
194 return result;
195 }
196
197 /***
198 * @return aggregate off-heap hit rate
199 */
200 public long getCacheOffHeapHitRate() {
201 long result = 0;
202 for (String cacheName : getCacheNames()) {
203 Ehcache cache = cacheManager.getEhcache(cacheName);
204 if (cache != null) {
205 SampledCacheStatistics stats = cache.getSampledCacheStatistics();
206 result += stats.getCacheHitOffHeapMostRecentSample();
207 }
208 }
209 return result;
210 }
211
212 /***
213 * @return aggregate on-disk hit rate
214 */
215 public long getCacheOnDiskHitRate() {
216 long result = 0;
217 for (String cacheName : getCacheNames()) {
218 Ehcache cache = cacheManager.getEhcache(cacheName);
219 if (cache != null) {
220 SampledCacheStatistics stats = cache.getSampledCacheStatistics();
221 result += stats.getCacheHitOnDiskMostRecentSample();
222 }
223 }
224 return result;
225 }
226
227 /***
228 * @return aggregate miss rate
229 */
230 public long getCacheMissRate() {
231 long result = 0;
232 for (String cacheName : getCacheNames()) {
233 Ehcache cache = cacheManager.getEhcache(cacheName);
234 if (cache != null) {
235 SampledCacheStatistics stats = cache.getSampledCacheStatistics();
236 result += (stats.getCacheMissNotFoundMostRecentSample()
237 + stats.getCacheMissExpiredMostRecentSample());
238 }
239 }
240 return result;
241 }
242
243 /***
244 * @return aggregate in-memory miss rate
245 */
246 public long getCacheInMemoryMissRate() {
247 long result = 0;
248 for (String cacheName : getCacheNames()) {
249 Ehcache cache = cacheManager.getEhcache(cacheName);
250 if (cache != null) {
251 SampledCacheStatistics stats = cache.getSampledCacheStatistics();
252 result += stats.getCacheMissInMemoryMostRecentSample();
253 }
254 }
255 return result;
256 }
257
258 /***
259 * @return aggregate off-heap miss rate
260 */
261 public long getCacheOffHeapMissRate() {
262 long result = 0;
263 for (String cacheName : getCacheNames()) {
264 Ehcache cache = cacheManager.getEhcache(cacheName);
265 if (cache != null) {
266 SampledCacheStatistics stats = cache.getSampledCacheStatistics();
267 result += stats.getCacheMissOffHeapMostRecentSample();
268 }
269 }
270 return result;
271 }
272
273 /***
274 * @return aggregate on-disk miss rate
275 */
276 public long getCacheOnDiskMissRate() {
277 long result = 0;
278 for (String cacheName : getCacheNames()) {
279 Ehcache cache = cacheManager.getEhcache(cacheName);
280 if (cache != null) {
281 SampledCacheStatistics stats = cache.getSampledCacheStatistics();
282 result += stats.getCacheMissOnDiskMostRecentSample();
283 }
284 }
285 return result;
286 }
287
288 /***
289 * @return aggregate put rate
290 */
291 public long getCachePutRate() {
292 long result = 0;
293 for (String cacheName : getCacheNames()) {
294 Ehcache cache = cacheManager.getEhcache(cacheName);
295 if (cache != null) {
296 SampledCacheStatistics stats = cache.getSampledCacheStatistics();
297 result += stats.getCacheElementPutMostRecentSample();
298 }
299 }
300 return result;
301 }
302
303 /***
304 * @return aggregate update rate
305 */
306 public long getCacheUpdateRate() {
307 long result = 0;
308 for (String cacheName : getCacheNames()) {
309 Ehcache cache = cacheManager.getEhcache(cacheName);
310 if (cache != null) {
311 SampledCacheStatistics stats = cache.getSampledCacheStatistics();
312 result += stats.getCacheElementUpdatedMostRecentSample();
313 }
314 }
315 return result;
316 }
317
318 /***
319 * @return aggregate remove rate
320 */
321 public long getCacheRemoveRate() {
322 long result = 0;
323 for (String cacheName : getCacheNames()) {
324 Ehcache cache = cacheManager.getEhcache(cacheName);
325 if (cache != null) {
326 SampledCacheStatistics stats = cache.getSampledCacheStatistics();
327 result += stats.getCacheElementRemovedMostRecentSample();
328 }
329 }
330 return result;
331 }
332
333 /***
334 * @return aggregate eviction rate
335 */
336 public long getCacheEvictionRate() {
337 long result = 0;
338 for (String cacheName : getCacheNames()) {
339 Ehcache cache = cacheManager.getEhcache(cacheName);
340 if (cache != null) {
341 SampledCacheStatistics stats = cache.getSampledCacheStatistics();
342 result += stats.getCacheElementEvictedMostRecentSample();
343 }
344 }
345 return result;
346 }
347
348 /***
349 * @return aggregate expiration rate
350 */
351 public long getCacheExpirationRate() {
352 long result = 0;
353 for (String cacheName : getCacheNames()) {
354 Ehcache cache = cacheManager.getEhcache(cacheName);
355 if (cache != null) {
356 SampledCacheStatistics stats = cache.getSampledCacheStatistics();
357 result += stats.getCacheElementExpiredMostRecentSample();
358 }
359 }
360 return result;
361 }
362
363 /***
364 * @return aggregate average get time (ms.)
365 */
366 public float getCacheAverageGetTime() {
367 float result = 0;
368 int instances = 0;
369 for (String cacheName : getCacheNames()) {
370 Ehcache cache = cacheManager.getEhcache(cacheName);
371 if (cache != null) {
372 result += cache.getAverageGetTime();
373 instances++;
374 }
375 }
376 return instances > 0 ? result / instances : 0;
377 }
378
379 /***
380 * @return aggregate search rate
381 */
382 public long getCacheSearchRate() {
383 long result = 0;
384 for (String cacheName : getCacheNames()) {
385 Ehcache cache = cacheManager.getEhcache(cacheName);
386 if (cache != null) {
387 SampledCacheStatistics stats = cache.getSampledCacheStatistics();
388 result += stats.getSearchesPerSecond();
389 }
390 }
391 return result;
392 }
393
394 /***
395 * @return aggregate search time
396 */
397 public long getCacheAverageSearchTime() {
398 long result = 0;
399 for (String cacheName : getCacheNames()) {
400 Ehcache cache = cacheManager.getEhcache(cacheName);
401 if (cache != null) {
402 SampledCacheStatistics stats = cache.getSampledCacheStatistics();
403 result += stats.getAverageSearchTime();
404 }
405 }
406 return result;
407 }
408
409 /***
410 * {@inheritDoc}
411 */
412 public boolean getHasWriteBehindWriter() {
413 for (String cacheName : getCacheNames()) {
414 Ehcache cache = cacheManager.getEhcache(cacheName);
415 if (cache != null) {
416 if (cache.getWriterManager() instanceof WriteBehindManager &&
417 cache.getRegisteredCacheWriter() != null) {
418 return true;
419 }
420 }
421 }
422 return false;
423 }
424
425 /***
426 * @return aggregate writer queue length
427 */
428 public long getWriterQueueLength() {
429 long result = 0;
430 for (String cacheName : getCacheNames()) {
431 Ehcache cache = cacheManager.getEhcache(cacheName);
432 if (cache != null) {
433 LiveCacheStatistics stats = cache.getLiveCacheStatistics();
434 result += Math.max(stats.getWriterQueueLength(), 0);
435 }
436 }
437 return result;
438 }
439
440 /***
441 * {@inheritDoc}
442 */
443 public int getWriterMaxQueueSize() {
444 int result = 0;
445 for (String cacheName : getCacheNames()) {
446 Ehcache cache = cacheManager.getEhcache(cacheName);
447 if (cache != null) {
448 CacheWriterConfiguration writerConfig = cache.getCacheConfiguration().getCacheWriterConfiguration();
449 result += (writerConfig.getWriteBehindMaxQueueSize() * writerConfig.getWriteBehindConcurrency());
450 }
451 }
452 return result;
453 }
454
455 /***
456 * {@inheritDoc}
457 */
458 public long getMaxBytesLocalDisk() {
459 return cacheManager.getConfiguration().getMaxBytesLocalDisk();
460 }
461
462 /***
463 * {@inheritDoc}
464 */
465 public long getMaxBytesLocalHeap() {
466 return cacheManager.getConfiguration().getMaxBytesLocalHeap();
467 }
468
469 /***
470 * {@inheritDoc}
471 */
472 public long getMaxBytesLocalOffHeap() {
473 return cacheManager.getConfiguration().getMaxBytesLocalDisk();
474 }
475
476 /***
477 * {@inheritDoc}
478 *
479 * @see net.sf.ehcache.management.sampled.SampledCacheManagerMBean#getName()
480 */
481 public String getName() {
482 return cacheManager.getName();
483 }
484
485 /***
486 * {@inheritDoc}
487 *
488 * @see net.sf.ehcache.management.sampled.SampledCacheManagerMBean#getName()
489 */
490 public String getMBeanRegisteredName() {
491 return this.mbeanRegisteredName;
492 }
493
494 /***
495 * {@inheritDoc}
496 */
497 public void clearStatistics() {
498 for (String cacheName : getCacheNames()) {
499 Cache cache = cacheManager.getCache(cacheName);
500 if (cache != null) {
501 cache.clearStatistics();
502 }
503 }
504 sendNotification(STATISTICS_RESET);
505 }
506
507 /***
508 * {@inheritDoc}
509 */
510 public void enableStatistics() {
511 for (String cacheName : getCacheNames()) {
512 Cache cache = cacheManager.getCache(cacheName);
513 if (cache != null) {
514
515 cache.setSampledStatisticsEnabled(true);
516 }
517 }
518 sendNotification(STATISTICS_ENABLED, Boolean.TRUE);
519 }
520
521 /***
522 * {@inheritDoc}
523 */
524 public void disableStatistics() {
525 for (String cacheName : getCacheNames()) {
526 Cache cache = cacheManager.getCache(cacheName);
527 if (cache != null) {
528
529 cache.setStatisticsEnabled(false);
530 }
531 }
532 sendNotification(STATISTICS_ENABLED, Boolean.FALSE);
533 }
534
535 /***
536 * {@inheritDoc}
537 */
538 public void setStatisticsEnabled(boolean enabled) {
539 if (enabled) {
540 enableStatistics();
541 } else {
542 disableStatistics();
543 }
544 }
545
546 /***
547 * {@inheritDoc}
548 */
549 public boolean isStatisticsEnabled() {
550 for (String cacheName : getCacheNames()) {
551 Cache cache = cacheManager.getCache(cacheName);
552 if (cache != null) {
553 if (!cache.isSampledStatisticsEnabled()) {
554 return false;
555 }
556 }
557 }
558 return true;
559 }
560
561 /***
562 * @return is each cache's statistics enabled
563 */
564 private boolean determineStatisticsEnabled() {
565 for (String cacheName : getCacheNames()) {
566 Cache cache = cacheManager.getCache(cacheName);
567 if (cache != null) {
568 if (!cache.isStatisticsEnabled()) {
569 return false;
570 }
571 }
572 }
573 return true;
574 }
575
576 /***
577 * generateActiveConfigDeclaration
578 *
579 * @return CacheManager configuration as String
580 */
581 public String generateActiveConfigDeclaration() {
582 return this.cacheManager.getActiveConfigurationText();
583 }
584
585 /***
586 * generateActiveConfigDeclaration
587 *
588 * @return Cache configuration as String
589 */
590 public String generateActiveConfigDeclaration(String cacheName) {
591 return this.cacheManager.getActiveConfigurationText(cacheName);
592 }
593
594 /***
595 * {@inheritDoc}
596 */
597 public boolean getTransactional() {
598 for (String cacheName : getCacheNames()) {
599 Ehcache cache = cacheManager.getEhcache(cacheName);
600 if (cache != null && cache.getCacheConfiguration().getTransactionalMode().isTransactional()) {
601 return true;
602 }
603 }
604 return false;
605 }
606
607 /***
608 * {@inheritDoc}
609 */
610 public boolean getSearchable() {
611 for (String cacheName : getCacheNames()) {
612 Ehcache cache = cacheManager.getEhcache(cacheName);
613 if (cache != null && cache.getCacheConfiguration().getSearchable() != null) {
614 return true;
615 }
616 }
617 return false;
618 }
619
620 /***
621 * {@inheritDoc}
622 */
623 public long getTransactionCommittedCount() {
624 return this.cacheManager.getTransactionController().getTransactionCommittedCount();
625 }
626
627 /***
628 * {@inheritDoc}
629 */
630 public long getTransactionCommitRate() {
631 long result = 0;
632 for (String cacheName : getCacheNames()) {
633 Ehcache cache = cacheManager.getEhcache(cacheName);
634 if (cache != null) {
635 SampledCacheStatistics stats = cache.getSampledCacheStatistics();
636 result += stats.getCacheXaCommitsMostRecentSample();
637 }
638 }
639 return result;
640 }
641
642 /***
643 * {@inheritDoc}
644 */
645 public long getTransactionRolledBackCount() {
646 return this.cacheManager.getTransactionController().getTransactionRolledBackCount();
647 }
648
649 /***
650 * {@inheritDoc}
651 */
652 public long getTransactionRollbackRate() {
653 long result = 0;
654 for (String cacheName : getCacheNames()) {
655 Ehcache cache = cacheManager.getEhcache(cacheName);
656 if (cache != null) {
657 SampledCacheStatistics stats = cache.getSampledCacheStatistics();
658 result += stats.getCacheXaRollbacksMostRecentSample();
659 }
660 }
661 return result;
662 }
663
664 /***
665 * {@inheritDoc}
666 */
667 public long getTransactionTimedOutCount() {
668 return this.cacheManager.getTransactionController().getTransactionTimedOutCount();
669 }
670
671 /***
672 * Returns if each contained cache is enabled.
673 */
674 public boolean isEnabled() throws CacheException {
675 for (String cacheName : getCacheNames()) {
676 Ehcache cache = cacheManager.getEhcache(cacheName);
677 if (cache != null && cache.isDisabled()) {
678 return false;
679 }
680 }
681 return true;
682 }
683
684 /***
685 * Enables/disables each of the contained caches.
686 */
687 public void setEnabled(boolean enabled) {
688 for (String cacheName : getCacheNames()) {
689 Ehcache cache = cacheManager.getEhcache(cacheName);
690 if (cache != null) {
691 cache.setDisabled(!enabled);
692 }
693 }
694 sendNotification(CACHES_ENABLED, Boolean.valueOf(enabled));
695 }
696
697 /***
698 * @return is each cache enabled
699 */
700 private boolean determineEnabled() {
701 for (String cacheName : getCacheNames()) {
702 Cache cache = cacheManager.getCache(cacheName);
703 if (cache != null) {
704 if (cache.isDisabled()) {
705 return false;
706 }
707 }
708 }
709 return true;
710 }
711
712 /***
713 * @see BaseEmitterBean#getNotificationInfo()
714 */
715 @Override
716 public MBeanNotificationInfo[] getNotificationInfo() {
717 return NOTIFICATION_INFO;
718 }
719 }