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,
84 new RoundRobinOnHeapPoolEvictor(),
85 new ConstantSizeOfEngine(
86 1536,
87 14336,
88 512
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
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
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
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
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
139 Object key = keysOfOnHeapElements(memoryStore).iterator().next();
140 memoryStore.put(new Element(key, key.toString()));
141
142
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
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
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
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 }