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.statistics;
18  
19  import static org.junit.Assert.assertEquals;
20  import static org.junit.Assert.assertNotNull;
21  import static org.junit.Assert.assertTrue;
22  import static org.junit.Assert.fail;
23  
24  import java.util.Random;
25  import org.slf4j.Logger;
26  import org.slf4j.LoggerFactory;
27  
28  import net.sf.ehcache.AbstractCacheTest;
29  import net.sf.ehcache.Cache;
30  import net.sf.ehcache.Ehcache;
31  import net.sf.ehcache.Element;
32  import net.sf.ehcache.Statistics;
33  
34  import org.junit.Test;
35  
36  /***
37   * Tests for the CacheUsageListener
38   * 
39   * @author Abhishek Sanoujam
40   * @version $Id: CacheUsageListenerTest.java 2268 2010-04-16 19:50:30Z cdennis $
41   */
42  public class CacheUsageListenerTest extends AbstractCacheTest {
43  
44      private static final Logger LOG = LoggerFactory.getLogger(CacheUsageListenerTest.class);
45  
46      /***
47       * Test statistics enabling/disabling/clearing
48       * 
49       * @throws InterruptedException
50       */
51      @Test
52      public void testCacheUsageStatistics() throws InterruptedException {
53          // Set size so the second element overflows to disk.
54          Cache cache = new Cache("test", 1, true, false, 5, 2);
55          manager.addCache(cache);
56  
57          // add as a listener
58          AnotherStatistics anotherStats = new AnotherStatistics();
59          cache.registerCacheUsageListener(anotherStats);
60  
61          cache.setStatisticsEnabled(true);
62          doTestCacheUsageStatistics(cache, true, anotherStats);
63  
64          // test enable/disable statistics
65          cache.setStatisticsEnabled(false);
66          doTestCacheUsageStatistics(cache, false, anotherStats);
67  
68          // remove the listener
69          cache.removeCacheUsageListener(anotherStats);
70          // enable statistics but don't check stats as no longer a listener
71          cache.setStatisticsEnabled(true);
72          doTestCacheUsageStatistics(cache, false, anotherStats);
73  
74          assertEquals(Statistics.STATISTICS_ACCURACY_BEST_EFFORT, cache
75                  .getLiveCacheStatistics().getStatisticsAccuracy());
76          assertEquals("Best Effort", cache.getLiveCacheStatistics()
77                  .getStatisticsAccuracyDescription());
78      }
79  
80      /***
81       * Test statistics directly. Tests
82       * - cacheHitCount
83       * - onDiskHitCount
84       * - inMemoryHitCount
85       * - cacheMissCount
86       * - size
87       * - inMemorySize
88       * - onDiskSize
89       * - clearing statistics
90       * - average get time
91       * 
92       */
93      public void doTestCacheUsageStatistics(Cache cache, boolean checkStats,
94              AnotherStatistics anotherStats) throws InterruptedException {
95  
96          cache.put(new Element("key1", "value1"));
97          cache.put(new Element("key2", "value1"));
98          // key1 should be in the Disk Store
99          cache.get("key1");
100 
101         if (checkStats) {
102             assertEquals(1, anotherStats.getCacheHitCount());
103             assertEquals(1, anotherStats.getOnDiskHitCount());
104             assertEquals(0, anotherStats.getInMemoryHitCount());
105             assertEquals(0, anotherStats.getCacheMissCount());
106             // assertEquals(2, anotherStats.getSize());
107             // assertEquals(1, anotherStats.getInMemorySize());
108             // assertEquals(1, anotherStats.getOnDiskSize());
109         } else {
110             assertEquals(0, anotherStats.getCacheHitCount());
111             assertEquals(0, anotherStats.getOnDiskHitCount());
112             assertEquals(0, anotherStats.getInMemoryHitCount());
113             assertEquals(0, anotherStats.getCacheMissCount());
114             // assertEquals(0, anotherStats.getSize());
115             // assertEquals(0, anotherStats.getInMemorySize());
116             // assertEquals(0, anotherStats.getOnDiskSize());
117         }
118 
119         // key 1 should now be in the LruMemoryStore
120         cache.get("key1");
121 
122         if (checkStats) {
123             assertEquals(2, anotherStats.getCacheHitCount());
124             assertEquals(1, anotherStats.getOnDiskHitCount());
125             assertEquals(1, anotherStats.getInMemoryHitCount());
126             assertEquals(0, anotherStats.getCacheMissCount());
127         } else {
128             assertEquals(0, anotherStats.getCacheHitCount());
129             assertEquals(0, anotherStats.getOnDiskHitCount());
130             assertEquals(0, anotherStats.getInMemoryHitCount());
131             assertEquals(0, anotherStats.getCacheMissCount());
132         }
133 
134         // Let the idle expire
135         Thread.sleep(6000);
136 
137         // key 1 should now be expired
138         cache.get("key1");
139         if (checkStats) {
140             assertEquals(2, anotherStats.getCacheHitCount());
141             assertEquals(1, anotherStats.getOnDiskHitCount());
142             assertEquals(1, anotherStats.getInMemoryHitCount());
143             assertEquals(1, anotherStats.getCacheMissCount());
144         } else {
145             assertEquals(0, anotherStats.getCacheHitCount());
146             assertEquals(0, anotherStats.getOnDiskHitCount());
147             assertEquals(0, anotherStats.getInMemoryHitCount());
148             assertEquals(0, anotherStats.getCacheMissCount());
149         }
150 
151         // key 2 should also be expired
152         cache.get("key1");
153         if (checkStats) {
154             assertEquals(2, anotherStats.getCacheHitCount());
155             assertEquals(1, anotherStats.getOnDiskHitCount());
156             assertEquals(1, anotherStats.getInMemoryHitCount());
157             assertEquals(2, anotherStats.getCacheMissCount());
158         } else {
159             assertEquals(0, anotherStats.getCacheHitCount());
160             assertEquals(0, anotherStats.getOnDiskHitCount());
161             assertEquals(0, anotherStats.getInMemoryHitCount());
162             assertEquals(0, anotherStats.getCacheMissCount());
163         }
164 
165         cache.clearStatistics();
166         // everything should be zero now
167         assertEquals(0, anotherStats.getCacheHitCount());
168         assertEquals(0, anotherStats.getOnDiskHitCount());
169         assertEquals(0, anotherStats.getInMemoryHitCount());
170         assertEquals(0, anotherStats.getCacheMissCount());
171 
172         assertNotNull(anotherStats.toString());
173     }
174 
175     /***
176      * Test average get time
177      * 
178      * @throws InterruptedException
179      */
180     @Test
181     public void testAverageGetTime() throws InterruptedException {
182         Cache cache = new Cache("test", 0, true, false, 5, 2);
183         manager.addCache(cache);
184 
185         // add as a listener
186         AnotherStatistics anotherStats = new AnotherStatistics();
187         cache.registerCacheUsageListener(anotherStats);
188 
189         cache.setStatisticsEnabled(true);
190         doTestAverageGetTime(cache, true, anotherStats);
191 
192         // test enable/disable statistics
193         cache.setStatisticsEnabled(false);
194         doTestAverageGetTime(cache, false, anotherStats);
195 
196         // remove the listener
197         cache.removeCacheUsageListener(anotherStats);
198         // enable statistics but don't check stats as no longer a listener
199         cache.setStatisticsEnabled(true);
200         doTestAverageGetTime(cache, false, anotherStats);
201 
202     }
203 
204     /***
205      * Tests average get time
206      */
207     public void doTestAverageGetTime(Cache cache, boolean checkStats,
208             AnotherStatistics anotherStats) {
209         float averageGetTime = anotherStats.getAverageGetTimeMillis();
210         assertTrue(0 == anotherStats.getAverageGetTimeMillis());
211 
212         for (int i = 0; i < 10000; i++) {
213             cache.put(new Element("" + i, "value1"));
214         }
215         cache.put(new Element("key1", "value1"));
216         cache.put(new Element("key2", "value1"));
217         for (int i = 0; i < 110000; i++) {
218             cache.get("" + i);
219         }
220 
221         averageGetTime = anotherStats.getAverageGetTimeMillis();
222         if (checkStats) {
223             assertTrue(averageGetTime >= .000001);
224         } else {
225             assertTrue(0 == averageGetTime);
226         }
227         cache.clearStatistics();
228         assertTrue(0 == anotherStats.getAverageGetTimeMillis());
229     }
230 
231     /***
232      * Test cache eviction/expiry stats
233      * 
234      * @throws InterruptedException
235      */
236     @Test
237     public void testEvictionStatistics() throws InterruptedException {
238         // stats enabled, non-zero stats expected, as listener
239         doTestEvictionStatistics(true, true, true);
240 
241         // stats disabled, non-zero stats NOT expected, as listener
242         doTestEvictionStatistics(false, false, true);
243 
244         // stats enabled, non-zero stats NOT expected, NOT a listener
245         doTestEvictionStatistics(true, false, false);
246     }
247 
248     /***
249      * Tests eviction statistics
250      * - evictedCount
251      * - missCountNotFound
252      * - missCountExpired
253      * - missCount
254      * - expiredCount
255      * - size
256      */
257     public void doTestEvictionStatistics(boolean statsEnabled,
258             boolean nonZeroStatsExpected, boolean asListener)
259             throws InterruptedException {
260         // run 5 times with random total and capacity values
261         Random rand = new Random();
262         int min = 100;
263         for (int loop = 0; loop < 5; loop++) {
264             int a = rand.nextInt(10000) + min;
265             int b = rand.nextInt(10000) + min;
266             if (a == b) {
267                 a += min;
268             }
269             int total = Math.max(a, b);
270             int capacity = Math.min(a, b);
271             Ehcache ehcache = new net.sf.ehcache.Cache("test-"
272                     + nonZeroStatsExpected + "-" + loop, capacity, false,
273                     false, 2, 2);
274             manager.addCache(ehcache);
275             AnotherStatistics anotherStats = new AnotherStatistics();
276             if (asListener) {
277                 ehcache.registerCacheUsageListener(anotherStats);
278             } else {
279                 // register and remove as we want to test remove listener
280                 ehcache.registerCacheUsageListener(anotherStats);
281                 ehcache.removeCacheUsageListener(anotherStats);
282             }
283             ehcache.setStatisticsEnabled(statsEnabled);
284 
285             assertEquals(0, anotherStats.getEvictedCount());
286 
287             for (int i = 0; i < total; i++) {
288                 ehcache.put(new Element("" + i, "value1"));
289             }
290             if (nonZeroStatsExpected) {
291                 assertEquals(total - capacity, anotherStats.getEvictedCount());
292             } else {
293                 assertEquals(0, anotherStats.getEvictedCount());
294             }
295 
296             Thread.sleep(3010);
297 
298             // expiries do not count as eviction
299             if (nonZeroStatsExpected) {
300                 assertEquals(total - capacity, anotherStats.getEvictedCount());
301             } else {
302                 assertEquals(0, anotherStats.getEvictedCount());
303             }
304 
305             // no expiration till a get is tried
306             assertEquals(0, anotherStats.getCacheMissCount());
307             assertEquals(0, anotherStats.getCacheMissCountExpired());
308             assertEquals(0, anotherStats.getExpiredCount());
309             assertEquals(0, anotherStats.getCacheMissCount());
310 
311             for (int i = 0; i < total; i++) {
312                 ehcache.get("" + i);
313             }
314 
315             if (nonZeroStatsExpected) {
316                 assertEquals(total, anotherStats.getCacheMissCount());
317                 assertEquals(capacity, anotherStats.getCacheMissCountExpired());
318                 assertEquals(capacity, anotherStats.getExpiredCount());
319                 assertEquals(total, anotherStats.getCacheMissCount());
320                 // assertEquals(0, anotherStats.getSize());
321             } else {
322                 assertEquals(0, anotherStats.getCacheMissCount());
323                 assertEquals(0, anotherStats.getCacheMissCountExpired());
324                 assertEquals(0, anotherStats.getExpiredCount());
325                 assertEquals(0, anotherStats.getCacheMissCount());
326                 // assertEquals(0, anotherStats.getSize());
327             }
328 
329             ehcache.clearStatistics();
330 
331             assertEquals(0, anotherStats.getCacheMissCount());
332             assertEquals(0, anotherStats.getCacheMissCountExpired());
333             assertEquals(0, anotherStats.getExpiredCount());
334             assertEquals(0, anotherStats.getCacheMissCount());
335             // assertEquals(0, anotherStats.getSize());
336             
337             manager.removeCache(ehcache.getName());
338         }
339 
340     }
341 
342     /***
343      * Test element put/update/remove
344      * - putCount
345      * - updateCount
346      * - removeCount
347      */
348     @Test
349     public void testPutUpdateRemoveStats() throws InterruptedException {
350 
351         // stats enabled, non-zero stats expected, as listener
352         doTestElementUpdateRemove(true, true, true);
353 
354         // stats disabled, non-zero stats NOT expected, as listener
355         doTestElementUpdateRemove(false, false, true);
356 
357         // stats enabled, non-zero stats NOT expected, NOT a listener
358         doTestElementUpdateRemove(true, false, false);
359     }
360 
361     public void doTestElementUpdateRemove(boolean statsEnabled,
362             boolean nonZeroStatsExpected, boolean asListener)
363             throws InterruptedException {
364         Random rand = new Random();
365         int min = 100;
366         for (int loop = 0; loop < 5; loop++) {
367             int total = rand.nextInt(10000) + min;
368 
369             // always ensure enough capacity. Otherwise cannot predict
370             // updateCount with eviction (based on capacity)
371             Ehcache ehcache = new net.sf.ehcache.Cache("test-"
372                     + nonZeroStatsExpected + "-" + loop, total + 1, false,
373                     false, 1200, 1200);
374             manager.addCache(ehcache);
375             // add as a listener
376             AnotherStatistics anotherStats = new AnotherStatistics();
377             if (asListener) {
378                 ehcache.registerCacheUsageListener(anotherStats);
379             } else {
380                 // register and remove as we want to test remove listener
381                 ehcache.registerCacheUsageListener(anotherStats);
382                 ehcache.removeCacheUsageListener(anotherStats);
383             }
384             ehcache.setStatisticsEnabled(statsEnabled);
385 
386             assertEquals(0, anotherStats.getEvictedCount());
387             assertEquals(0, anotherStats.getPutCount());
388             assertEquals(0, anotherStats.getRemovedCount());
389             assertEquals(0, anotherStats.getUpdateCount());
390 
391             for (int i = 0; i < total; i++) {
392                 ehcache.put(new Element("" + i, "value1"));
393             }
394             if (nonZeroStatsExpected) {
395                 assertEquals(total, anotherStats.getPutCount());
396                 assertEquals(0, anotherStats.getEvictedCount());
397                 // assertEquals(total, anotherStats.getSize());
398                 assertEquals(0, anotherStats.getUpdateCount());
399                 assertEquals(0, anotherStats.getRemovedCount());
400             } else {
401                 assertEquals(0, anotherStats.getPutCount());
402                 assertEquals(0, anotherStats.getEvictedCount());
403                 // assertEquals(0, anotherStats.getSize());
404                 assertEquals(0, anotherStats.getRemovedCount());
405                 assertEquals(0, anotherStats.getUpdateCount());
406             }
407 
408             // minimum 1 update
409             int updates = rand.nextInt(total - 1) + 1;
410             assertTrue(updates >= 1);
411             for (int i = 0; i < updates; i++) {
412                 ehcache.put(new Element("" + i, "value1"));
413             }
414             if (nonZeroStatsExpected) {
415                 // assertEquals(total, anotherStats.getSize());
416                 assertEquals(updates, anotherStats.getUpdateCount());
417                 assertEquals(total, anotherStats.getPutCount());
418                 assertEquals(0, anotherStats.getEvictedCount());
419                 assertEquals(0, anotherStats.getRemovedCount());
420             } else {
421                 // assertEquals(0, anotherStats.getSize());
422                 assertEquals(0, anotherStats.getPutCount());
423                 assertEquals(0, anotherStats.getRemovedCount());
424                 assertEquals(0, anotherStats.getEvictedCount());
425                 assertEquals(0, anotherStats.getUpdateCount());
426             }
427 
428             // minimum 1 remove
429             int remove = rand.nextInt(total - 1) + 1;
430             assertTrue(updates >= 1);
431             for (int i = 0; i < remove; i++) {
432                 ehcache.remove("" + i);
433             }
434             if (nonZeroStatsExpected) {
435                 // assertEquals(total - remove, anotherStats.getSize());
436                 assertEquals(updates, anotherStats.getUpdateCount());
437                 assertEquals(remove, anotherStats.getRemovedCount());
438                 assertEquals(total, anotherStats.getPutCount());
439                 assertEquals(0, anotherStats.getEvictedCount());
440             } else {
441                 // assertEquals(0, anotherStats.getSize());
442                 assertEquals(0, anotherStats.getPutCount());
443                 assertEquals(0, anotherStats.getRemovedCount());
444                 assertEquals(0, anotherStats.getEvictedCount());
445                 assertEquals(0, anotherStats.getUpdateCount());
446             }
447 
448             ehcache.clearStatistics();
449 
450             assertEquals(0, anotherStats.getPutCount());
451             assertEquals(0, anotherStats.getRemovedCount());
452             assertEquals(0, anotherStats.getEvictedCount());
453             assertEquals(0, anotherStats.getUpdateCount());
454             
455             manager.removeCache(ehcache.getName());
456         }
457 
458     }
459 
460     /***
461      * CacheStatistics should always be sensible when the cache has not
462      * started.
463      */
464     @Test
465     public void testCacheAlive() {
466         Cache cache = new Cache("test", 1, true, false, 5, 2);
467         String string = cache.toString();
468         assertTrue(string.contains("test"));
469         try {
470             LiveCacheStatistics statistics = cache.getLiveCacheStatistics();
471             fail();
472         } catch (IllegalStateException e) {
473             assertEquals("The test Cache is not alive.", e.getMessage());
474         }
475         // initialize cache now
476         manager.addCache(cache);
477         // add as a listener
478         AnotherStatistics anotherStats = new AnotherStatistics();
479         cache.registerCacheUsageListener(anotherStats);
480         assertEquals(0, anotherStats.getCacheHitCount());
481     }
482 
483 }