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  package net.sf.ehcache.statistics.sampled;
17  
18  import java.util.concurrent.atomic.AtomicBoolean;
19  import java.util.concurrent.atomic.AtomicInteger;
20  
21  import net.sf.ehcache.CacheException;
22  import net.sf.ehcache.Statistics;
23  import net.sf.ehcache.statistics.CacheUsageListener;
24  import net.sf.ehcache.util.FailSafeTimer;
25  import net.sf.ehcache.util.counter.CounterConfig;
26  import net.sf.ehcache.util.counter.CounterManager;
27  import net.sf.ehcache.util.counter.CounterManagerImpl;
28  import net.sf.ehcache.util.counter.sampled.SampledCounter;
29  import net.sf.ehcache.util.counter.sampled.SampledCounterConfig;
30  import net.sf.ehcache.util.counter.sampled.SampledRateCounter;
31  import net.sf.ehcache.util.counter.sampled.SampledRateCounterConfig;
32  
33  /***
34   * An implementation of {@link SampledCacheStatistics} This also implements {@link CacheUsageListener} and depends on the notification
35   * received from
36   * these to update the stats
37   * <p />
38   *
39   * @author <a href="mailto:asanoujam@terracottatech.com">Abhishek Sanoujam</a>
40   * @since 1.7
41   */
42  public class SampledCacheStatisticsImpl implements CacheUsageListener, SampledCacheStatistics {
43  
44      private static final int AVERAGE_SEARCH_SAMPLE_INTERVAL = 10;
45      private static final int DEFAULT_HISTORY_SIZE = 30;
46      private static final int DEFAULT_INTERVAL_SECS = 1;
47      private static final SampledCounterConfig DEFAULT_SAMPLED_COUNTER_CONFIG = new SampledCounterConfig(DEFAULT_INTERVAL_SECS,
48              DEFAULT_HISTORY_SIZE, true, 0L);
49      private static final SampledRateCounterConfig DEFAULT_SAMPLED_RATE_COUNTER_CONFIG = new SampledRateCounterConfig(DEFAULT_INTERVAL_SECS,
50              DEFAULT_HISTORY_SIZE, true);
51  
52      private volatile CounterManager counterManager;
53      private final SampledCounter cacheHitCount;
54      private final SampledCounter cacheHitInMemoryCount;
55      private final SampledCounter cacheHitOffHeapCount;
56      private final SampledCounter cacheHitOnDiskCount;
57      private final SampledCounter cacheMissCount;
58      private final SampledCounter cacheMissInMemoryCount;
59      private final SampledCounter cacheMissOffHeapCount;
60      private final SampledCounter cacheMissOnDiskCount;
61      private final SampledCounter cacheMissExpiredCount;
62      private final SampledCounter cacheMissNotFoundCount;
63      private final SampledCounter cacheElementEvictedCount;
64      private final SampledCounter cacheElementRemoved;
65      private final SampledCounter cacheElementExpired;
66      private final SampledCounter cacheElementPut;
67      private final SampledCounter cacheElementUpdated;
68      private final SampledCounter cacheSearchCount;
69      private final SampledCounter cacheXaCommitCount;
70      private final SampledCounter cacheXaRollbackCount;
71      private final SampledRateCounter averageGetTime;
72      private final SampledRateCounter averageSearchTime;
73  
74      private final AtomicBoolean sampledStatisticsEnabled;
75      private final AtomicInteger statisticsAccuracy;
76  
77      /***
78       * Constructor that accepts a timer which will be used to schedule the
79       * sampled counters
80       */
81      public SampledCacheStatisticsImpl(FailSafeTimer timer) {
82          counterManager = new CounterManagerImpl(timer);
83          cacheHitCount = createSampledCounter(DEFAULT_SAMPLED_COUNTER_CONFIG);
84          cacheHitInMemoryCount = createSampledCounter(DEFAULT_SAMPLED_COUNTER_CONFIG);
85          cacheHitOffHeapCount = createSampledCounter(DEFAULT_SAMPLED_COUNTER_CONFIG);
86          cacheHitOnDiskCount = createSampledCounter(DEFAULT_SAMPLED_COUNTER_CONFIG);
87          cacheMissCount = createSampledCounter(DEFAULT_SAMPLED_COUNTER_CONFIG);
88          cacheMissInMemoryCount = createSampledCounter(DEFAULT_SAMPLED_COUNTER_CONFIG);
89          cacheMissOffHeapCount = createSampledCounter(DEFAULT_SAMPLED_COUNTER_CONFIG);
90          cacheMissOnDiskCount = createSampledCounter(DEFAULT_SAMPLED_COUNTER_CONFIG);
91          cacheMissExpiredCount = createSampledCounter(DEFAULT_SAMPLED_COUNTER_CONFIG);
92          cacheMissNotFoundCount = createSampledCounter(DEFAULT_SAMPLED_COUNTER_CONFIG);
93          cacheElementEvictedCount = createSampledCounter(DEFAULT_SAMPLED_COUNTER_CONFIG);
94          cacheElementRemoved = createSampledCounter(DEFAULT_SAMPLED_COUNTER_CONFIG);
95          cacheElementExpired = createSampledCounter(DEFAULT_SAMPLED_COUNTER_CONFIG);
96          cacheElementPut = createSampledCounter(DEFAULT_SAMPLED_COUNTER_CONFIG);
97          cacheElementUpdated = createSampledCounter(DEFAULT_SAMPLED_COUNTER_CONFIG);
98          cacheSearchCount = createSampledCounter(DEFAULT_SAMPLED_COUNTER_CONFIG);
99          cacheXaCommitCount = createSampledCounter(DEFAULT_SAMPLED_COUNTER_CONFIG);
100         cacheXaRollbackCount = createSampledCounter(DEFAULT_SAMPLED_COUNTER_CONFIG);
101 
102         averageGetTime = (SampledRateCounter) createSampledCounter(DEFAULT_SAMPLED_RATE_COUNTER_CONFIG);
103         averageSearchTime = (SampledRateCounter) createSampledCounter(
104                 new SampledRateCounterConfig(AVERAGE_SEARCH_SAMPLE_INTERVAL, DEFAULT_HISTORY_SIZE, true));
105 
106         this.sampledStatisticsEnabled = new AtomicBoolean(true);
107         this.statisticsAccuracy = new AtomicInteger(Statistics.STATISTICS_ACCURACY_BEST_EFFORT);
108     }
109 
110     private SampledCounter createSampledCounter(CounterConfig defaultCounterConfig) {
111         return (SampledCounter) counterManager.createCounter(defaultCounterConfig);
112     }
113 
114     private void incrementIfStatsEnabled(SampledCounter... counters) {
115         if (!sampledStatisticsEnabled.get()) {
116             return;
117         }
118         for (SampledCounter counter : counters) {
119             counter.increment();
120         }
121     }
122 
123     /***
124      * Clears the collected statistics. Resets all counters to zero
125      */
126     public void clearStatistics() {
127         cacheHitCount.getAndReset();
128         cacheHitInMemoryCount.getAndReset();
129         cacheHitOffHeapCount.getAndReset();
130         cacheHitOnDiskCount.getAndReset();
131         cacheMissCount.getAndReset();
132         cacheMissInMemoryCount.getAndReset();
133         cacheMissOffHeapCount.getAndReset();
134         cacheMissOnDiskCount.getAndReset();
135         cacheMissExpiredCount.getAndReset();
136         cacheMissNotFoundCount.getAndReset();
137         cacheElementEvictedCount.getAndReset();
138         cacheElementRemoved.getAndReset();
139         cacheElementExpired.getAndReset();
140         cacheElementPut.getAndReset();
141         cacheElementUpdated.getAndReset();
142         cacheSearchCount.getAndReset();
143         cacheXaCommitCount.getAndReset();
144         cacheXaRollbackCount.getAndReset();
145         averageGetTime.getAndReset();
146         averageSearchTime.getAndReset();
147     }
148 
149     /***
150      * {@inheritDoc}
151      */
152     public void notifyCacheElementEvicted() {
153         incrementIfStatsEnabled(cacheElementEvictedCount);
154     }
155 
156     /***
157      * {@inheritDoc}
158      */
159     public void notifyCacheHitInMemory() {
160         incrementIfStatsEnabled(cacheHitCount, cacheHitInMemoryCount);
161     }
162 
163     /***
164      * {@inheritDoc}
165      */
166     public void notifyCacheHitOffHeap() {
167         incrementIfStatsEnabled(cacheHitCount, cacheHitOffHeapCount);
168     }
169 
170     /***
171      * {@inheritDoc}
172      */
173     public void notifyCacheHitOnDisk() {
174         incrementIfStatsEnabled(cacheHitCount, cacheHitOnDiskCount);
175     }
176 
177     /***
178      * {@inheritDoc}
179      */
180     public void notifyCacheMissedWithExpired() {
181         incrementIfStatsEnabled(cacheMissCount, cacheMissExpiredCount);
182     }
183 
184     /***
185      * {@inheritDoc}
186      */
187     public void notifyCacheMissedWithNotFound() {
188         incrementIfStatsEnabled(cacheMissCount, cacheMissNotFoundCount);
189     }
190 
191     /***
192      * {@inheritDoc}
193      */
194     public void notifyCacheMissInMemory() {
195         incrementIfStatsEnabled(cacheMissCount, cacheMissInMemoryCount);
196     }
197 
198     /***
199      * {@inheritDoc}
200      */
201     public void notifyCacheMissOffHeap() {
202         incrementIfStatsEnabled(cacheMissCount, cacheMissOffHeapCount);
203     }
204 
205     /***
206      * {@inheritDoc}
207      */
208     public void notifyCacheMissOnDisk() {
209         incrementIfStatsEnabled(cacheMissCount, cacheMissOnDiskCount);
210     }
211 
212     /***
213      * {@inheritDoc}
214      */
215     public void dispose() {
216         counterManager.shutdown();
217     }
218 
219     /***
220      * {@inheritDoc}
221      */
222     public void notifyCacheElementExpired() {
223         incrementIfStatsEnabled(cacheElementExpired);
224     }
225 
226     /***
227      * {@inheritDoc}
228      */
229     public void notifyCacheElementPut() throws CacheException {
230         incrementIfStatsEnabled(cacheElementPut);
231     }
232 
233     /***
234      * {@inheritDoc}
235      */
236     public void notifyCacheElementRemoved() throws CacheException {
237         incrementIfStatsEnabled(cacheElementRemoved);
238     }
239 
240     /***
241      * {@inheritDoc}
242      */
243     public void notifyCacheElementUpdated() throws CacheException {
244         incrementIfStatsEnabled(cacheElementUpdated);
245     }
246 
247     /***
248      * {@inheritDoc}
249      */
250     public void notifyTimeTakenForGet(long millis) {
251         if (!sampledStatisticsEnabled.get()) {
252             return;
253         }
254         averageGetTime.increment(millis, 1);
255     }
256 
257     /***
258      * {@inheritDoc}
259      */
260     public void notifyRemoveAll() {
261         // no-op
262     }
263 
264     /***
265      * {@inheritDoc}
266      */
267     @Override
268     public Object clone() throws CloneNotSupportedException {
269         super.clone();
270         throw new CloneNotSupportedException();
271     }
272 
273     /***
274      * {@inheritDoc}
275      */
276     public void notifyStatisticsEnabledChanged(boolean enableStatistics) {
277         if (!enableStatistics) {
278             sampledStatisticsEnabled.set(false);
279         }
280     }
281 
282     /***
283      * {@inheritDoc}
284      */
285     public void notifyStatisticsAccuracyChanged(int statisticsAccuracyValue) {
286         if (Statistics.isValidStatisticsAccuracy(statisticsAccuracyValue)) {
287             statisticsAccuracy.set(statisticsAccuracyValue);
288             return;
289         }
290         throw new IllegalArgumentException("Invalid statistics accuracy value: " + statisticsAccuracyValue);
291     }
292 
293     /***
294      * {@inheritDoc}
295      */
296     public void notifyStatisticsCleared() {
297         cacheHitCount.getAndReset();
298         cacheHitInMemoryCount.getAndReset();
299         cacheHitOffHeapCount.getAndReset();
300         cacheHitOnDiskCount.getAndReset();
301         cacheMissCount.getAndReset();
302         cacheMissInMemoryCount.getAndReset();
303         cacheMissOffHeapCount.getAndReset();
304         cacheMissOnDiskCount.getAndReset();
305         cacheMissExpiredCount.getAndReset();
306         cacheMissNotFoundCount.getAndReset();
307         cacheElementEvictedCount.getAndReset();
308         cacheElementRemoved.getAndReset();
309         cacheElementExpired.getAndReset();
310         cacheElementPut.getAndReset();
311         cacheElementUpdated.getAndReset();
312         cacheXaCommitCount.getAndReset();
313         cacheXaRollbackCount.getAndReset();
314         averageGetTime.getAndReset();
315     }
316 
317     /***
318      * {@inheritDoc}
319      */
320     public long getCacheHitMostRecentSample() {
321         return cacheHitCount.getMostRecentSample().getCounterValue();
322     }
323 
324     /***
325      * {@inheritDoc}
326      */
327     public long getAverageGetTimeMostRecentSample() {
328         return averageGetTime.getMostRecentSample().getCounterValue();
329     }
330 
331     /***
332      * {@inheritDoc}
333      */
334     public long getCacheElementEvictedMostRecentSample() {
335         return cacheElementEvictedCount.getMostRecentSample().getCounterValue();
336     }
337 
338     /***
339      * {@inheritDoc}
340      */
341     public long getCacheHitInMemoryMostRecentSample() {
342         return cacheHitInMemoryCount.getMostRecentSample().getCounterValue();
343     }
344 
345     /***
346      * {@inheritDoc}
347      */
348     public long getCacheHitOffHeapMostRecentSample() {
349         return cacheHitOffHeapCount.getMostRecentSample().getCounterValue();
350     }
351 
352     /***
353      * {@inheritDoc}
354      */
355     public long getCacheHitOnDiskMostRecentSample() {
356         return cacheHitOnDiskCount.getMostRecentSample().getCounterValue();
357     }
358 
359     /***
360      * {@inheritDoc}
361      */
362     public long getCacheMissExpiredMostRecentSample() {
363         return cacheMissExpiredCount.getMostRecentSample().getCounterValue();
364     }
365 
366     /***
367      * {@inheritDoc}
368      */
369     public long getCacheMissMostRecentSample() {
370         return cacheMissCount.getMostRecentSample().getCounterValue();
371     }
372 
373     /***
374      * {@inheritDoc}
375      */
376     public long getCacheMissInMemoryMostRecentSample() {
377         return cacheMissInMemoryCount.getMostRecentSample().getCounterValue();
378     }
379 
380     /***
381      * {@inheritDoc}
382      */
383     public long getCacheMissOffHeapMostRecentSample() {
384         return cacheMissOffHeapCount.getMostRecentSample().getCounterValue();
385     }
386 
387     /***
388      * {@inheritDoc}
389      */
390     public long getCacheMissOnDiskMostRecentSample() {
391         return cacheMissOnDiskCount.getMostRecentSample().getCounterValue();
392     }
393 
394     /***
395      * {@inheritDoc}
396      */
397     public long getCacheMissNotFoundMostRecentSample() {
398         return cacheMissNotFoundCount.getMostRecentSample().getCounterValue();
399     }
400 
401     /***
402      * {@inheritDoc}
403      */
404     public long getCacheElementExpiredMostRecentSample() {
405         return cacheElementExpired.getMostRecentSample().getCounterValue();
406     }
407 
408     /***
409      * {@inheritDoc}
410      */
411     public long getCacheElementPutMostRecentSample() {
412         return cacheElementPut.getMostRecentSample().getCounterValue();
413     }
414 
415     /***
416      * {@inheritDoc}
417      */
418     public long getCacheElementRemovedMostRecentSample() {
419         return cacheElementRemoved.getMostRecentSample().getCounterValue();
420     }
421 
422     /***
423      * {@inheritDoc}
424      */
425     public long getCacheElementUpdatedMostRecentSample() {
426         return cacheElementUpdated.getMostRecentSample().getCounterValue();
427     }
428 
429     /***
430      * {@inheritDoc}
431      */
432     public int getStatisticsAccuracy() {
433         return statisticsAccuracy.get();
434     }
435 
436     /***
437      * {@inheritDoc}
438      */
439     public String getStatisticsAccuracyDescription() {
440         int value = statisticsAccuracy.get();
441         if (value == 0) {
442             return "None";
443         } else if (value == 1) {
444             return "Best Effort";
445         } else {
446             return "Guaranteed";
447         }
448     }
449 
450     /***
451      * {@inheritDoc}
452      */
453     public boolean isSampledStatisticsEnabled() {
454         return sampledStatisticsEnabled.get();
455     }
456 
457     /***
458      * {@inheritDoc}
459      */
460     public long getAverageSearchTime() {
461         return this.averageSearchTime.getMostRecentSample().getCounterValue();
462     }
463 
464     /***
465      * {@inheritDoc}
466      */
467     public long getSearchesPerSecond() {
468         return cacheSearchCount.getMostRecentSample().getCounterValue();
469     }
470 
471     /***
472      * {@inheritDoc}
473      */
474     public void notifyCacheSearch(long executeTime) {
475         this.cacheSearchCount.increment();
476         this.averageSearchTime.increment(executeTime, 1);
477     }
478 
479     /***
480      * {@inheritDoc}
481      */
482     public long getCacheXaCommitsMostRecentSample() {
483         return cacheXaCommitCount.getMostRecentSample().getCounterValue();
484     }
485 
486     /***
487      * {@inheritDoc}
488      */
489     public void notifyXaCommit() {
490         incrementIfStatsEnabled(cacheXaCommitCount);
491     }
492 
493     /***
494      * {@inheritDoc}
495      */
496     public long getCacheXaRollbacksMostRecentSample() {
497         return cacheXaRollbackCount.getMostRecentSample().getCounterValue();
498     }
499 
500     /***
501      * {@inheritDoc}
502      */
503     public void notifyXaRollback() {
504         incrementIfStatsEnabled(cacheXaRollbackCount);
505     }
506 }