View Javadoc

1   package net.sf.ehcache.store;
2   
3   import net.sf.ehcache.Cache;
4   import net.sf.ehcache.CacheException;
5   import net.sf.ehcache.Ehcache;
6   import net.sf.ehcache.Element;
7   import net.sf.ehcache.config.CacheConfiguration;
8   import net.sf.ehcache.event.CacheEventListener;
9   import net.sf.ehcache.pool.impl.BoundedPool;
10  import net.sf.ehcache.pool.impl.ConstantSizeOfEngine;
11  import net.sf.ehcache.pool.impl.RoundRobinOnHeapPoolEvictor;
12  
13  import org.junit.After;
14  import org.junit.Before;
15  import org.junit.Ignore;
16  import org.junit.Test;
17  
18  import java.util.Collection;
19  import java.util.concurrent.ConcurrentLinkedQueue;
20  import java.util.concurrent.ExecutorService;
21  import java.util.concurrent.Executors;
22  import java.util.concurrent.Future;
23  
24  import static org.junit.Assert.assertEquals;
25  import static org.junit.Assert.assertTrue;
26  import static org.junit.Assert.fail;
27  
28  /***
29   * @author Ludovic Orban
30   */
31  public class PoolableMemoryStoreTest {
32  
33      private volatile Cache cache;
34      private volatile BoundedPool onHeapPool;
35      private volatile MemoryStore memoryStore;
36      private volatile Element lastEvicted;
37  
38      private static Collection<Object> keysOfOnHeapElements(MemoryStore store) {
39          return (Collection<Object>) store.getKeys();
40      }
41  
42      private static int countElementsOnHeap(MemoryStore store) {
43          return keysOfOnHeapElements(store).size();
44      }
45  
46      private void dump() {
47          System.out.println("# # # # # #");
48          System.out.println(memoryStore.getSize() + " elements in cache");
49          System.out.println("on heap: " + keysOfOnHeapElements(memoryStore));
50          System.out.println("on heap size: " + onHeapPool.getSize());
51          System.out.println("# # # # # #");
52      }
53  
54      @Before
55      public void setUp() {
56          cache = new Cache(new CacheConfiguration("myCache1", 0).eternal(true));
57  
58          lastEvicted = null;
59          cache.getCacheEventNotificationService().registerListener(new CacheEventListener() {
60              public void notifyElementRemoved(Ehcache cache, Element element) throws CacheException { }
61  
62              public void notifyElementPut(Ehcache cache, Element element) throws CacheException { }
63  
64              public void notifyElementUpdated(Ehcache cache, Element element) throws CacheException { }
65  
66              public void notifyElementExpired(Ehcache cache, Element element) { }
67  
68              public void notifyElementEvicted(Ehcache cache, Element element) {
69                  lastEvicted = element;
70              }
71  
72              public void notifyRemoveAll(Ehcache cache) { }
73  
74              public void dispose() { }
75  
76              @Override
77              public Object clone() throws CloneNotSupportedException {
78                  return super.clone();
79              }
80          });
81  
82          onHeapPool = new BoundedPool(
83                  16384 * 2, // == 2 elements
84                  new RoundRobinOnHeapPoolEvictor(),
85                  new ConstantSizeOfEngine(
86                          1536,  /* 1.5 KB*/
87                          14336, /* 14 KB */
88                          512    /* 0.5 KB */
89                  )
90          );
91  
92          memoryStore = MemoryStore.create(cache, onHeapPool);
93      }
94  
95      @After
96      public void tearDown() {
97          cache.dispose();
98          memoryStore.dispose();
99      }
100 
101 
102     @Test
103     public void testPutNew() throws Exception {
104         // put 20 new elements in, making sure eviction is working
105         for (int i = 0; i < 20; i++) {
106             Element e = new Element(i, "" + i);
107             memoryStore.put(e);
108             assertTrue("#" + i, countElementsOnHeap(memoryStore) <= 2);
109         }
110 
111         assertEquals(2, countElementsOnHeap(memoryStore));
112         assertEquals(16384 * 2, onHeapPool.getSize());
113 
114         // get an on-heap element
115         Object key = keysOfOnHeapElements(memoryStore).iterator().next();
116         memoryStore.get(key);
117 
118         assertEquals(2, countElementsOnHeap(memoryStore));
119         assertEquals(16384 * 2, onHeapPool.getSize());
120 
121         // put a new element on-heap
122         memoryStore.put(new Element(-1, "-1"));
123 
124         assertEquals(2, countElementsOnHeap(memoryStore));
125         assertEquals(16384 * 2, onHeapPool.getSize());
126     }
127 
128     @Test
129     public void testPutUpdate() throws Exception {
130         // warm up
131         memoryStore.put(new Element(1, "1"));
132         memoryStore.put(new Element(2, "2"));
133         memoryStore.put(new Element(3, "3"));
134 
135         assertEquals(2, memoryStore.getSize());
136         assertEquals(16384 * 2, onHeapPool.getSize());
137 
138         // update element in memory
139         Object key = keysOfOnHeapElements(memoryStore).iterator().next();
140         memoryStore.put(new Element(key, key.toString()));
141 
142         // size can be 1 or 2, depending if the evicted element is the updated one or not
143         if (memoryStore.getSize() == 2) {
144             assertEquals(16384 * 2, onHeapPool.getSize());
145         } else if (memoryStore.getSize() == 1) {
146             assertEquals(16384, onHeapPool.getSize());
147         } else {
148             fail();
149         }
150     }
151 
152     @Test
153     public void testRemove() throws Exception {
154         // warm up
155         memoryStore.put(new Element(1, "1"));
156         memoryStore.put(new Element(2, "2"));
157         memoryStore.put(new Element(3, "3"));
158 
159         assertEquals(2, memoryStore.getSize());
160         assertEquals(16384 * 2, onHeapPool.getSize());
161 
162         // remove element on heap
163         Object key = keysOfOnHeapElements(memoryStore).iterator().next();
164         memoryStore.remove(key);
165 
166         assertEquals(1, memoryStore.getSize());
167         assertEquals(16384, onHeapPool.getSize());
168     }
169 
170     @Test
171     public void testRemoveAll() throws Exception {
172         // warm up
173         memoryStore.put(new Element(1, "1"));
174         memoryStore.put(new Element(2, "2"));
175         memoryStore.put(new Element(3, "3"));
176 
177         assertEquals(2, memoryStore.getSize());
178         assertEquals(16384 * 2, onHeapPool.getSize());
179 
180         memoryStore.removeAll();
181 
182         assertEquals(0, memoryStore.getSize());
183         assertEquals(0, onHeapPool.getSize());
184     }
185 
186     @Test
187     @Ignore
188     public void testMultithreaded() throws Exception {
189         final int nThreads = 16;
190 
191         final ExecutorService executor = Executors.newFixedThreadPool(nThreads);
192         final ConcurrentLinkedQueue<Future<?>> queue = new ConcurrentLinkedQueue<Future<?>>();
193 
194         for (int i = 0; i < nThreads; i++) {
195             final int threadId = i;
196             Future<?> f = executor.submit(new Runnable() {
197                 public void run() {
198                     for (int i = 0; i < 10000; i++) {
199                         Element e = new Element(i, "" + i);
200                         memoryStore.put(e);
201 
202                         assertTrue(threadId + "#" + i + " - " + onHeapPool.getSize(), 16384 * 2 >= onHeapPool.getSize());
203 
204                         Thread.yield();
205                         if ((i + 1) % 1000 == 0) { dump(); memoryStore.removeAll(); }
206                     }
207                 }
208             });
209             queue.add(f);
210         }
211 
212         while (!queue.isEmpty()) {
213             Future<?> f = queue.poll();
214             f.get();
215         }
216     }
217 
218 }