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.Pool;
10 import net.sf.ehcache.pool.impl.ConstantSizeOfEngine;
11 import net.sf.ehcache.pool.impl.FromLargestCacheOnHeapPoolEvictor;
12 import net.sf.ehcache.pool.impl.StrictlyBoundedPool;
13 import org.junit.After;
14 import org.junit.Before;
15 import org.junit.Test;
16
17 import java.util.concurrent.ConcurrentLinkedQueue;
18 import java.util.concurrent.ExecutorService;
19 import java.util.concurrent.Executors;
20 import java.util.concurrent.Future;
21
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assert.assertNotNull;
25 import static org.junit.Assert.assertNull;
26 import static org.junit.Assert.assertTrue;
27 import static org.junit.Assert.fail;
28
29 /***
30 * @author Ludovic Orban
31 */
32 public class MemoryStorePoolingTest {
33
34 private static final int ITERATIONS = 10000;
35 private volatile Cache cache;
36 private volatile Pool onHeapPool;
37 private volatile MemoryStore memoryStore;
38 private volatile Element lastEvicted;
39
40 private void dump() {
41 System.out.println("# # # # # #");
42 System.out.println(memoryStore.getSize() + " elements in cache");
43 System.out.println("on heap: " + memoryStore.getKeys());
44 System.out.println("on heap size: " + onHeapPool.getSize());
45 System.out.println("# # # # # #");
46 }
47
48 @Before
49 public void setUp() {
50 cache = new Cache(new CacheConfiguration("myCache1", 0).eternal(true));
51
52 lastEvicted = null;
53 cache.getCacheEventNotificationService().registerListener(new CacheEventListener() {
54 public void notifyElementRemoved(Ehcache cache, Element element) throws CacheException { }
55
56 public void notifyElementPut(Ehcache cache, Element element) throws CacheException { }
57
58 public void notifyElementUpdated(Ehcache cache, Element element) throws CacheException { }
59
60 public void notifyElementExpired(Ehcache cache, Element element) { }
61
62 public void notifyElementEvicted(Ehcache cache, Element element) {
63 lastEvicted = element;
64 }
65
66 public void notifyRemoveAll(Ehcache cache) { }
67
68 public void dispose() { }
69
70 @Override
71 public Object clone() throws CloneNotSupportedException {
72 return super.clone();
73 }
74 });
75
76 onHeapPool = new StrictlyBoundedPool(
77 16384 * 2,
78 new FromLargestCacheOnHeapPoolEvictor(),
79 new ConstantSizeOfEngine(
80 1536,
81 14336,
82 512
83 )
84 );
85
86 memoryStore = MemoryStore.create(cache, onHeapPool);
87 }
88
89 @After
90 public void tearDown() {
91 cache.dispose();
92 memoryStore.dispose();
93 }
94
95
96 @Test
97 public void testElementPinning() throws Exception {
98 Cache cache2 = new Cache(new CacheConfiguration("myCache2", 0).eternal(true));
99 MemoryStore memoryOnlyStore2 = MemoryStore.create(cache2, onHeapPool);
100
101 for (int i = 0; i < 100; i++) {
102 memoryStore.put(new Element(i, i));
103 }
104
105 assertEquals(0, memoryOnlyStore2.getSize());
106 assertEquals(0, memoryOnlyStore2.getInMemorySizeInBytes());
107 assertEquals(2, memoryStore.getSize());
108 assertEquals(16384 * 2, memoryStore.getInMemorySizeInBytes());
109
110 for (int i = 0; i < 100; i++) {
111 Element element = new Element(i, i);
112 element.setTimeToIdle(1);
113 element.setTimeToLive(1);
114 element.setPinned(true);
115
116 memoryOnlyStore2.put(element);
117 }
118
119 assertEquals(0, memoryStore.getSize());
120 assertEquals(0, memoryStore.getInMemorySizeInBytes());
121 assertEquals(100, memoryOnlyStore2.getSize());
122 assertEquals(16384 * 100, memoryOnlyStore2.getInMemorySizeInBytes());
123
124
125 Thread.sleep(1200);
126
127 for (int i = 0; i < 100; i++) {
128 memoryStore.put(new Element(i, i));
129 }
130
131 assertEquals(1, memoryOnlyStore2.getSize());
132 assertEquals(16384, memoryOnlyStore2.getInMemorySizeInBytes());
133 assertEquals(1, memoryStore.getSize());
134 assertEquals(16384, memoryStore.getInMemorySizeInBytes());
135 assertEquals(16384 * 2, onHeapPool.getSize());
136 }
137
138 @Test
139 public void testPutNew() throws Exception {
140 for (int i = 0; i < ITERATIONS; i++) {
141 putNew();
142
143 tearDown();
144 setUp();
145 }
146 }
147
148 public void putNew() throws Exception {
149
150 for (int i = 0; i < 20; i++) {
151 Element e = new Element(i, "" + i);
152 memoryStore.put(e);
153 assertTrue("#" + i, memoryStore.getInMemorySize() <= 2);
154 }
155
156 assertEquals(2, memoryStore.getInMemorySize());
157 assertEquals(16384 * 2, onHeapPool.getSize());
158
159
160 Object key = memoryStore.getKeys().iterator().next();
161 memoryStore.get(key);
162
163 assertEquals(2, memoryStore.getInMemorySize());
164 assertEquals(16384 * 2, onHeapPool.getSize());
165
166
167 memoryStore.put(new Element(-1, "-1"));
168
169 assertEquals(2, memoryStore.getInMemorySize());
170 assertEquals(16384 * 2, onHeapPool.getSize());
171 }
172
173 @Test
174 public void testPutThenRemove() throws Exception {
175 for (int i = 0; i < ITERATIONS; i++) {
176 putThenRemove();
177
178 tearDown();
179 setUp();
180 }
181 }
182
183 public void putThenRemove() throws Exception {
184 for (int i = 0; i < 20; i++) {
185 memoryStore.put(new Element(i, "" + i));
186 assertTrue(memoryStore.getSize() <= 2);
187
188 if (i % 2 == 1) {
189 memoryStore.remove(i);
190 }
191 assertTrue(memoryStore.getSize() <= 2);
192 }
193
194 assertTrue(memoryStore.getSize() >= 1);
195 assertTrue(memoryStore.getSize() <= 2);
196 assertTrue(onHeapPool.getSize() >= 16384);
197 assertTrue(onHeapPool.getSize() <= 16384 * 2);
198
199 for (int i = 0; i < 20; i++) {
200 if (i % 2 == 0) {
201 memoryStore.remove(i);
202 }
203 }
204
205 assertEquals(0, memoryStore.getSize());
206 assertEquals(0, onHeapPool.getSize());
207 }
208
209 @Test
210 public void testPutIfAbsentNew() throws Exception {
211 for (int i = 0; i < ITERATIONS; i++) {
212 putIfAbsentNew();
213
214 tearDown();
215 setUp();
216 }
217 }
218
219 public void putIfAbsentNew() throws Exception {
220
221 for (int i = 0; i < 20; i++) {
222 Element e = new Element(i, "" + i);
223 assertNull(memoryStore.putIfAbsent(e));
224 assertTrue("#" + i, memoryStore.getInMemorySize() <= 2);
225 }
226
227 assertEquals(2, memoryStore.getInMemorySize());
228 assertEquals(16384 * 2, onHeapPool.getSize());
229
230
231 Object key = memoryStore.getKeys().iterator().next();
232 memoryStore.get(key);
233
234 assertEquals(2, memoryStore.getInMemorySize());
235 assertEquals(16384 * 2, onHeapPool.getSize());
236
237
238
239 assertNull(memoryStore.putIfAbsent(new Element(-1, "-1")));
240
241 assertEquals(2, memoryStore.getInMemorySize());
242 assertEquals(16384 * 2, onHeapPool.getSize());
243 }
244
245 @Test
246 public void testPutUpdate() throws Exception {
247 for (int i = 0; i < ITERATIONS; i++) {
248 putUpdate();
249
250 tearDown();
251 setUp();
252 }
253 }
254
255 public void putUpdate() throws Exception {
256
257 memoryStore.put(new Element(1, "1"));
258 memoryStore.put(new Element(2, "2"));
259 memoryStore.put(new Element(3, "3"));
260
261 assertEquals(2, memoryStore.getSize());
262 assertEquals(16384 * 2, onHeapPool.getSize());
263
264
265 Object key = memoryStore.getKeys().iterator().next();
266 memoryStore.put(new Element(key, key.toString()));
267
268
269 if (memoryStore.getSize() == 2) {
270 assertEquals(16384 * 2, onHeapPool.getSize());
271 } else if (memoryStore.getSize() == 1) {
272 assertEquals(16384, onHeapPool.getSize());
273 } else {
274 fail();
275 }
276 }
277
278 @Test
279 public void testPutIfAbsentUpdate() throws Exception {
280 for (int i = 0; i < ITERATIONS; i++) {
281 putIfAbsentUpdate();
282
283 tearDown();
284 setUp();
285 }
286 }
287
288 public void putIfAbsentUpdate() throws Exception {
289
290 Element element;
291 assertNull(memoryStore.putIfAbsent(new Element(1, "1#1")));
292 assertNotNull(memoryStore.putIfAbsent(new Element(1, "1#2")));
293 assertNull(memoryStore.putIfAbsent(new Element(2, "2#1")));
294 element = memoryStore.putIfAbsent(new Element(2, "2#2"));
295 if (lastEvicted.getObjectKey().equals(2)) {
296 assertNull(element);
297 } else {
298 assertNotNull(element);
299 }
300 assertNull(memoryStore.putIfAbsent(new Element(3, "3#1")));
301 element = memoryStore.putIfAbsent(new Element(3, "3#2"));
302 if (lastEvicted.getObjectKey().equals(3)) {
303 assertNull(element);
304 assertEquals(2, memoryStore.getSize());
305 assertEquals(16384 * 2, onHeapPool.getSize());
306 } else {
307 assertNotNull(element);
308 assertEquals(1, memoryStore.getSize());
309 assertEquals(16384, onHeapPool.getSize());
310 }
311
312 Object key;
313
314
315 key = memoryStore.getKeys().iterator().next();
316 element = memoryStore.putIfAbsent(new Element(key, key.toString()));
317
318 if (lastEvicted.getObjectKey().equals(key)) {
319 assertNull(element);
320 assertEquals(2, memoryStore.getSize());
321 assertEquals(16384 * 2, onHeapPool.getSize());
322 } else {
323 assertNotNull(element);
324 assertEquals(1, memoryStore.getSize());
325 assertEquals(16384, onHeapPool.getSize());
326 }
327 }
328
329 @Test
330 public void testRemove() throws Exception {
331 for (int i = 0; i < ITERATIONS; i++) {
332 remove();
333
334 tearDown();
335 setUp();
336 }
337 }
338
339 public void remove() throws Exception {
340
341 memoryStore.put(new Element(1, "1"));
342 memoryStore.put(new Element(2, "2"));
343 memoryStore.put(new Element(3, "3"));
344
345 assertEquals(2, memoryStore.getSize());
346 assertEquals(16384 * 2, onHeapPool.getSize());
347
348
349 Object key = memoryStore.getKeys().iterator().next();
350 memoryStore.remove(key);
351
352 assertEquals(1, memoryStore.getSize());
353 assertEquals(16384, onHeapPool.getSize());
354 }
355
356 @Test
357 public void testReplace1Arg() throws Exception {
358 for (int i = 0; i < ITERATIONS; i++) {
359 replace1Arg();
360
361 tearDown();
362 setUp();
363 }
364 }
365
366 public void replace1Arg() throws Exception {
367
368 memoryStore.put(new Element(1, "1#1"));
369 memoryStore.put(new Element(2, "2#1"));
370 memoryStore.put(new Element(3, "3#1"));
371
372 assertEquals(2, memoryStore.getSize());
373 assertEquals(16384 * 2, onHeapPool.getSize());
374
375
376 Object key = memoryStore.getKeys().iterator().next();
377 Element element = memoryStore.replace(new Element(key, key + "#2"));
378
379 if (lastEvicted.getObjectKey().equals(key)) {
380 assertNull(element);
381 } else {
382 assertEquals(new Element(key, key + "#1"), element);
383 }
384 assertEquals(1, memoryStore.getSize());
385 assertEquals(16384, onHeapPool.getSize());
386
387
388 assertNull(memoryStore.replace(new Element(-1, -1 + "#2")));
389
390 assertEquals(1, memoryStore.getSize());
391 assertEquals(16384, onHeapPool.getSize());
392 }
393
394 @Test
395 public void testReplace3Args() throws Exception {
396 for (int i = 0; i < ITERATIONS; i++) {
397 replace3Arg();
398
399 tearDown();
400 setUp();
401 }
402 }
403
404 public void replace3Arg() throws Exception {
405
406 memoryStore.put(new Element(1, "1#1"));
407 memoryStore.put(new Element(2, "2#1"));
408 memoryStore.put(new Element(3, "3#1"));
409
410 assertEquals(2, memoryStore.getSize());
411 assertEquals(16384 * 2, onHeapPool.getSize());
412
413
414 Object key = memoryStore.getKeys().iterator().next();
415 boolean replaced = memoryStore.replace(new Element(key, key + "#1"), new Element(key, key + "#2"), new DefaultElementValueComparator());
416
417 if (lastEvicted.getObjectKey().equals(key)) {
418 assertFalse(replaced);
419 } else {
420 assertTrue(replaced);
421 }
422 assertEquals(1, memoryStore.getSize());
423 assertEquals(16384, onHeapPool.getSize());
424
425 memoryStore.put(new Element(4, "4#1"));
426
427
428 assertFalse(memoryStore.replace(new Element(-1, -1 + "#2"), new Element(-1, -1 + "#2"), new DefaultElementValueComparator()));
429
430 assertEquals(1, memoryStore.getSize());
431 assertEquals(16384, onHeapPool.getSize());
432 }
433
434 @Test
435 public void testRemoveElement() throws Exception {
436 for (int i = 0; i < ITERATIONS; i++) {
437 removeElement();
438
439 tearDown();
440 setUp();
441 }
442 }
443
444 public void removeElement() throws Exception {
445
446 memoryStore.put(new Element(1, "1"));
447 memoryStore.put(new Element(2, "2"));
448 memoryStore.put(new Element(3, "3"));
449
450 assertEquals(2, memoryStore.getSize());
451 assertEquals(16384 * 2, onHeapPool.getSize());
452
453
454 assertNull(memoryStore.removeElement(new Element(-1, -1 + ""), new DefaultElementValueComparator()));
455
456 assertEquals(2, memoryStore.getSize());
457 assertEquals(16384 * 2, onHeapPool.getSize());
458
459
460 Object key = memoryStore.getKeys().iterator().next();
461 assertEquals(new Element(key, key + ""), memoryStore.removeElement(new Element(key, key + ""), new DefaultElementValueComparator()));
462
463 assertEquals(1, memoryStore.getSize());
464 assertEquals(16384, onHeapPool.getSize());
465 }
466
467 @Test
468 public void testRemoveAll() throws Exception {
469 for (int i = 0; i < ITERATIONS; i++) {
470 removeAll();
471
472 tearDown();
473 setUp();
474 }
475 }
476
477 public void removeAll() throws Exception {
478
479 memoryStore.put(new Element(1, "1"));
480 memoryStore.put(new Element(2, "2"));
481 memoryStore.put(new Element(3, "3"));
482
483 assertEquals(2, memoryStore.getSize());
484 assertEquals(16384 * 2, onHeapPool.getSize());
485
486 memoryStore.removeAll();
487
488 assertEquals(0, memoryStore.getSize());
489 assertEquals(0, onHeapPool.getSize());
490 }
491
492 @Test
493 public void testMultithreaded() throws Exception {
494 final int nThreads = 1;
495
496 final ExecutorService executor = Executors.newFixedThreadPool(nThreads);
497 final ConcurrentLinkedQueue<Future<?>> queue = new ConcurrentLinkedQueue<Future<?>>();
498
499 for (int i = 0; i < nThreads; i++) {
500 Future<?> f = executor.submit(new Runnable() {
501 public void run() {
502 for (int i = 0; i < 100000; i++) {
503 Element e = new Element(i, "" + i);
504 memoryStore.put(e);
505
506 memoryStore.replace(new Element(i, "2#" + i));
507
508 Thread.yield();
509 }
510 }
511 });
512 queue.add(f);
513 }
514
515 while (!queue.isEmpty()) {
516 Future<?> f = queue.poll();
517 f.get();
518 }
519
520 assertEquals(16384, onHeapPool.getSize());
521 assertEquals(1, memoryStore.getSize());
522 }
523
524 }