View Javadoc

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         // no-op
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                 // enables regular statistics also
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                 // disables regular statistics also
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 }