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