1 |
| |
2 |
| |
3 |
| |
4 |
| |
5 |
| |
6 |
| |
7 |
| package org.jboss.cache.loader; |
8 |
| |
9 |
| import org.apache.commons.logging.Log; |
10 |
| import org.apache.commons.logging.LogFactory; |
11 |
| import org.jboss.cache.CacheImpl; |
12 |
| import org.jboss.cache.CacheSPI; |
13 |
| import org.jboss.cache.DefaultCacheFactory; |
14 |
| import org.jboss.cache.Fqn; |
15 |
| import org.jboss.cache.config.CacheLoaderConfig; |
16 |
| import org.jboss.cache.config.Configuration; |
17 |
| import org.jboss.cache.factories.XmlConfigurationParser; |
18 |
| import org.jboss.cache.xml.XmlHelper; |
19 |
| import org.w3c.dom.Element; |
20 |
| |
21 |
| |
22 |
| |
23 |
| |
24 |
| |
25 |
| |
26 |
| public class SingletonStoreCacheLoaderTest extends AbstractCacheLoaderTestBase |
27 |
| { |
28 |
| private CacheSPI cache1, cache2, cache3; |
29 |
| private static final Log log = LogFactory.getLog(SingletonStoreCacheLoaderTest.class); |
30 |
| |
31 |
3
| protected void setUp() throws Exception
|
32 |
| { |
33 |
3
| log.info("*** test:" + getName() + " ***");
|
34 |
| |
35 |
3
| cache1 = (CacheImpl) DefaultCacheFactory.getInstance().createCache(false);
|
36 |
3
| cache2 = (CacheImpl) DefaultCacheFactory.getInstance().createCache(false);
|
37 |
3
| cache3 = (CacheImpl) DefaultCacheFactory.getInstance().createCache(false);
|
38 |
| |
39 |
3
| cache1.getConfiguration().setCacheMode(Configuration.CacheMode.REPL_SYNC);
|
40 |
3
| cache2.getConfiguration().setCacheMode(Configuration.CacheMode.REPL_SYNC);
|
41 |
3
| cache3.getConfiguration().setCacheMode(Configuration.CacheMode.REPL_SYNC);
|
42 |
| } |
43 |
| |
44 |
1
| public void testPutCacheLoaderWithNoPush() throws Exception
|
45 |
| { |
46 |
1
| initSingletonNonPushCache(cache1);
|
47 |
1
| initSingletonNonPushCache(cache2);
|
48 |
1
| initSingletonNonPushCache(cache3);
|
49 |
| |
50 |
1
| createCaches();
|
51 |
1
| statCaches();
|
52 |
| |
53 |
1
| cache1.put(fqn("/test1"), "key", "value");
|
54 |
1
| cache2.put(fqn("/test2"), "key", "value");
|
55 |
1
| cache3.put(fqn("/test3"), "key", "value");
|
56 |
| |
57 |
1
| CacheLoader cl1 = getDelegatingCacheLoader(cache1);
|
58 |
1
| CacheLoader cl2 = getDelegatingCacheLoader(cache2);
|
59 |
1
| CacheLoader cl3 = getDelegatingCacheLoader(cache3);
|
60 |
| |
61 |
1
| assertTrue("/test1 should have been entered in cl1", cl1.exists(fqn("/test1")));
|
62 |
1
| assertTrue("/test2 should have been entered in cl1", cl1.exists(fqn("/test2")));
|
63 |
1
| assertTrue("/test3 should have been entered in cl1", cl1.exists(fqn("/test3")));
|
64 |
| |
65 |
1
| assertFalse("/test1 should not be in cl2", cl2.exists(fqn("/test1")));
|
66 |
1
| assertFalse("/test2 should not be in cl2", cl2.exists(fqn("/test2")));
|
67 |
1
| assertFalse("/test3 should not be in cl2", cl2.exists(fqn("/test3")));
|
68 |
| |
69 |
1
| assertFalse("/test1 should not be in cl3", cl3.exists(fqn("/test1")));
|
70 |
1
| assertFalse("/test2 should not be in cl3", cl3.exists(fqn("/test2")));
|
71 |
1
| assertFalse("/test3 should not be in cl3", cl3.exists(fqn("/test3")));
|
72 |
| |
73 |
1
| stopCache1();
|
74 |
| |
75 |
1
| cache2.put(fqn("/test4"), "key", "value");
|
76 |
1
| cache3.put(fqn("/test5"), "key", "value");
|
77 |
| |
78 |
1
| assertTrue("/test4 should have been entered in cl2", cl2.exists(fqn("/test4")));
|
79 |
1
| assertTrue("/test5 should have been entered in cl2", cl2.exists(fqn("/test5")));
|
80 |
| |
81 |
1
| assertFalse("/test4 should not be in cl3", cl3.exists(fqn("/test4")));
|
82 |
1
| assertFalse("/test5 should not be in cl3", cl3.exists(fqn("/test5")));
|
83 |
| |
84 |
1
| stopCache2();
|
85 |
| |
86 |
1
| cache3.put(fqn("/test6"), "key", "value");
|
87 |
1
| assertTrue("/test5 should have been entered in cl3", cl3.exists(Fqn.fromString("/test6")));
|
88 |
| } |
89 |
| |
90 |
1
| public void testPutCacheLoaderWithPush() throws Exception
|
91 |
| { |
92 |
1
| initSingletonWithPushCache(cache1);
|
93 |
1
| initSingletonWithPushCache(cache2);
|
94 |
1
| initSingletonWithPushCache(cache3);
|
95 |
| |
96 |
1
| createCaches();
|
97 |
1
| statCaches();
|
98 |
| |
99 |
1
| cache1.put(fqn("/a"), "a-key", "a-value");
|
100 |
1
| cache1.put(fqn("/a"), "aa-key", "aa-value");
|
101 |
1
| cache1.put(fqn("/a/b"), "b-key", "b-value");
|
102 |
1
| cache1.put(fqn("/a/b"), "bb-key", "bb-value");
|
103 |
1
| cache1.put(fqn("/a/b/c"), "c-key", "c-value");
|
104 |
1
| cache1.put(fqn("/a/b/d"), "d-key", "d-value");
|
105 |
1
| cache1.put(fqn("/e"), "e-key", "e-value");
|
106 |
1
| cache1.put(fqn("/e/f/g"), "g-key", "g-value");
|
107 |
| |
108 |
1
| CacheLoader cl1 = getDelegatingCacheLoader(cache1);
|
109 |
1
| CacheLoader cl2 = getDelegatingCacheLoader(cache2);
|
110 |
1
| CacheLoader cl3 = getDelegatingCacheLoader(cache3);
|
111 |
| |
112 |
1
| assertTrue(cl1.get(fqn("/a")).containsKey("a-key"));
|
113 |
1
| assertTrue(cl1.get(fqn("/a")).containsKey("aa-key"));
|
114 |
1
| assertTrue(cl1.get(fqn("/a/b")).containsKey("b-key"));
|
115 |
1
| assertTrue(cl1.get(fqn("/a/b")).containsKey("bb-key"));
|
116 |
1
| assertTrue(cl1.get(fqn("/a/b/c")).containsKey("c-key"));
|
117 |
1
| assertTrue(cl1.get(fqn("/a/b/d")).containsKey("d-key"));
|
118 |
1
| assertTrue(cl1.get(fqn("/e")).containsKey("e-key"));
|
119 |
1
| assertTrue(cl1.get(fqn("/e/f/g")).containsKey("g-key"));
|
120 |
| |
121 |
1
| assertFalse(cl2.exists(fqn("/a")));
|
122 |
1
| assertFalse(cl2.exists(fqn("/a")));
|
123 |
1
| assertFalse(cl2.exists(fqn("/a/b")));
|
124 |
1
| assertFalse(cl2.exists(fqn("/a/b")));
|
125 |
1
| assertFalse(cl2.exists(fqn("/a/b/c")));
|
126 |
1
| assertFalse(cl2.exists(fqn("/a/b/d")));
|
127 |
1
| assertFalse(cl2.exists(fqn("/e")));
|
128 |
1
| assertFalse(cl2.exists(fqn("/e/f/g")));
|
129 |
| |
130 |
1
| assertFalse(cl3.exists(fqn("/a")));
|
131 |
1
| assertFalse(cl3.exists(fqn("/a")));
|
132 |
1
| assertFalse(cl3.exists(fqn("/a/b")));
|
133 |
1
| assertFalse(cl3.exists(fqn("/a/b")));
|
134 |
1
| assertFalse(cl3.exists(fqn("/a/b/c")));
|
135 |
1
| assertFalse(cl3.exists(fqn("/a/b/d")));
|
136 |
1
| assertFalse(cl3.exists(fqn("/e")));
|
137 |
1
| assertFalse(cl3.exists(fqn("/e/f/g")));
|
138 |
| |
139 |
1
| stopCache1();
|
140 |
1
| Thread.sleep(1000);
|
141 |
| |
142 |
1
| SingletonStoreCacheLoader scl2 = (SingletonStoreCacheLoader) cache2.getCacheLoaderManager().getCacheLoader();
|
143 |
1
| joinPushThread(scl2.getPushStateThread());
|
144 |
| |
145 |
1
| assertTrue(cl2.get(fqn("/a")).containsKey("a-key"));
|
146 |
1
| assertTrue(cl2.get(fqn("/a")).containsKey("aa-key"));
|
147 |
1
| assertTrue(cl2.get(fqn("/a/b")).containsKey("b-key"));
|
148 |
1
| assertTrue(cl2.get(fqn("/a/b")).containsKey("bb-key"));
|
149 |
1
| assertTrue(cl2.get(fqn("/a/b/c")).containsKey("c-key"));
|
150 |
1
| assertTrue(cl2.get(fqn("/a/b/d")).containsKey("d-key"));
|
151 |
1
| assertTrue(cl2.get(fqn("/e")).containsKey("e-key"));
|
152 |
1
| assertTrue(cl2.get(fqn("/e/f/g")).containsKey("g-key"));
|
153 |
| |
154 |
1
| cache2.put(fqn("/e/f/h"), "h-key", "h-value");
|
155 |
1
| cache3.put(fqn("/i"), "i-key", "i-value");
|
156 |
| |
157 |
1
| assertTrue(cl2.get(fqn("/e/f/h")).containsKey("h-key"));
|
158 |
1
| assertTrue(cl2.get(fqn("/i")).containsKey("i-key"));
|
159 |
| |
160 |
1
| assertFalse(cl3.exists(fqn("/a")));
|
161 |
1
| assertFalse(cl3.exists(fqn("/a")));
|
162 |
1
| assertFalse(cl3.exists(fqn("/a/b")));
|
163 |
1
| assertFalse(cl3.exists(fqn("/a/b")));
|
164 |
1
| assertFalse(cl3.exists(fqn("/a/b/c")));
|
165 |
1
| assertFalse(cl3.exists(fqn("/a/b/d")));
|
166 |
1
| assertFalse(cl3.exists(fqn("/e")));
|
167 |
1
| assertFalse(cl3.exists(fqn("/e/f/g")));
|
168 |
1
| assertFalse(cl3.exists(fqn("/e/f/h")));
|
169 |
1
| assertFalse(cl3.exists(fqn("/i")));
|
170 |
| |
171 |
1
| stopCache2();
|
172 |
1
| Thread.sleep(1000);
|
173 |
| |
174 |
1
| SingletonStoreCacheLoader scl3 = (SingletonStoreCacheLoader) cache3.getCacheLoaderManager().getCacheLoader();
|
175 |
1
| joinPushThread(scl3.getPushStateThread());
|
176 |
| |
177 |
1
| assertTrue(cl3.get(fqn("/a")).containsKey("a-key"));
|
178 |
1
| assertTrue(cl3.get(fqn("/a")).containsKey("aa-key"));
|
179 |
1
| assertTrue(cl3.get(fqn("/a/b")).containsKey("b-key"));
|
180 |
1
| assertTrue(cl3.get(fqn("/a/b")).containsKey("bb-key"));
|
181 |
1
| assertTrue(cl3.get(fqn("/a/b/c")).containsKey("c-key"));
|
182 |
1
| assertTrue(cl3.get(fqn("/a/b/d")).containsKey("d-key"));
|
183 |
1
| assertTrue(cl3.get(fqn("/e")).containsKey("e-key"));
|
184 |
1
| assertTrue(cl3.get(fqn("/e/f/g")).containsKey("g-key"));
|
185 |
1
| assertTrue(cl3.get(fqn("/e/f/h")).containsKey("h-key"));
|
186 |
1
| assertTrue(cl3.get(fqn("/i")).containsKey("i-key"));
|
187 |
| |
188 |
1
| cache3.put(fqn("/a"), "aaa-key", "aaa-value");
|
189 |
| |
190 |
1
| assertTrue(cl3.get(fqn("/a")).containsKey("aaa-key"));
|
191 |
| |
192 |
1
| stopCache3();
|
193 |
| } |
194 |
| |
195 |
1
| public void testAvoidConcurrentStatePush() throws InterruptedException
|
196 |
| { |
197 |
1
| MockSingletonStoreCacheLoader mscl = new MockSingletonStoreCacheLoader(null, true, 3000);
|
198 |
| |
199 |
1
| Thread t1 = new Thread(createActiveStatusChanger(mscl));
|
200 |
1
| Thread t2 = new Thread(createActiveStatusChanger(mscl));
|
201 |
| |
202 |
1
| t1.start();
|
203 |
1
| Thread.sleep(1000);
|
204 |
1
| t2.start();
|
205 |
| |
206 |
1
| t1.join();
|
207 |
1
| t2.join();
|
208 |
| |
209 |
1
| assertEquals(1, mscl.getNumberCreatedThreads());
|
210 |
| } |
211 |
| |
212 |
2
| private void createCaches() throws Exception
|
213 |
| { |
214 |
2
| cache1.create();
|
215 |
2
| cache2.create();
|
216 |
2
| cache3.create();
|
217 |
| } |
218 |
| |
219 |
2
| private void statCaches() throws Exception
|
220 |
| { |
221 |
2
| cache1.start();
|
222 |
2
| cache2.start();
|
223 |
2
| cache3.start();
|
224 |
| } |
225 |
| |
226 |
2
| private void joinPushThread(Thread pushThread) throws InterruptedException
|
227 |
| { |
228 |
2
| if (pushThread != null)
|
229 |
| { |
230 |
2
| pushThread.join();
|
231 |
| } |
232 |
| } |
233 |
| |
234 |
2
| private Runnable createActiveStatusChanger(SingletonStoreCacheLoader mscl)
|
235 |
| { |
236 |
2
| return new ActiveStatusModifier(mscl);
|
237 |
| } |
238 |
| |
239 |
6
| protected CacheLoaderConfig getSingletonStoreCacheLoaderConfig(String cacheloaderClass, boolean singleton,
|
240 |
| boolean pushStateWhenCoordinator) throws Exception |
241 |
| { |
242 |
6
| String xml = "<config>\n" +
|
243 |
| "<passivation>false</passivation>\n" + |
244 |
| "<preload></preload>\n" + |
245 |
| "<cacheloader>\n" + |
246 |
| "<class>" + cacheloaderClass + "</class>\n" + |
247 |
| "<properties></properties>\n" + |
248 |
| |
249 |
| |
250 |
| |
251 |
| |
252 |
| "<singletonStore pushStateWhenCoordinator=\"" + pushStateWhenCoordinator + "\">" + singleton + "</singletonStore>\n" + |
253 |
| "</cacheloader>\n" + |
254 |
| "</config>"; |
255 |
6
| Element element = XmlHelper.stringToElement(xml);
|
256 |
6
| return XmlConfigurationParser.parseCacheLoaderConfig(element);
|
257 |
| } |
258 |
| |
259 |
3
| private void initSingletonNonPushCache(CacheSPI cache) throws Exception
|
260 |
| { |
261 |
3
| cache.getConfiguration().setCacheLoaderConfig(getSingletonStoreCacheLoaderConfig(
|
262 |
| DummyInMemoryCacheLoader.class.getName(), true, false)); |
263 |
| } |
264 |
| |
265 |
3
| private void initSingletonWithPushCache(CacheSPI cache) throws Exception
|
266 |
| { |
267 |
3
| cache.getConfiguration().setCacheLoaderConfig(getSingletonStoreCacheLoaderConfig(
|
268 |
| DummyInMemoryCacheLoader.class.getName(), true, true)); |
269 |
| } |
270 |
| |
271 |
6
| private CacheLoader getDelegatingCacheLoader(CacheSPI cache)
|
272 |
| { |
273 |
6
| AbstractDelegatingCacheLoader acl = (AbstractDelegatingCacheLoader) cache.getCacheLoaderManager().getCacheLoader();
|
274 |
6
| return acl.getCacheLoader();
|
275 |
| } |
276 |
| |
277 |
85
| private Fqn fqn(String fqn)
|
278 |
| { |
279 |
85
| return Fqn.fromString(fqn);
|
280 |
| } |
281 |
| |
282 |
5
| private void stopCache1()
|
283 |
| { |
284 |
5
| if (cache1 != null)
|
285 |
| { |
286 |
3
| cache1.stop();
|
287 |
| } |
288 |
| |
289 |
5
| cache1 = null;
|
290 |
| } |
291 |
| |
292 |
5
| private void stopCache2()
|
293 |
| { |
294 |
5
| if (cache2 != null)
|
295 |
| { |
296 |
3
| cache2.stop();
|
297 |
| } |
298 |
| |
299 |
5
| cache2 = null;
|
300 |
| } |
301 |
| |
302 |
4
| private void stopCache3()
|
303 |
| { |
304 |
4
| if (cache3 != null)
|
305 |
| { |
306 |
3
| cache3.stop();
|
307 |
| } |
308 |
| |
309 |
4
| cache3 = null;
|
310 |
| } |
311 |
| |
312 |
3
| protected void tearDown()
|
313 |
| { |
314 |
3
| stopCache1();
|
315 |
3
| stopCache2();
|
316 |
3
| stopCache3();
|
317 |
| } |
318 |
| |
319 |
| class MockSingletonStoreCacheLoader extends SingletonStoreCacheLoader |
320 |
| { |
321 |
| private int numberCreatedThreads = 0; |
322 |
| private long busyPeriod; |
323 |
| |
324 |
1
| public MockSingletonStoreCacheLoader(CacheLoader loader, boolean pushConfiguration, long busyPeriodTime)
|
325 |
| { |
326 |
1
| super(loader, pushConfiguration);
|
327 |
1
| busyPeriod = busyPeriodTime;
|
328 |
| } |
329 |
| |
330 |
1
| public int getNumberCreatedThreads()
|
331 |
| { |
332 |
1
| return numberCreatedThreads;
|
333 |
| } |
334 |
| |
335 |
0
| public void setNumberCreatedThreads(int numberCreatedThreads)
|
336 |
| { |
337 |
0
| this.numberCreatedThreads = numberCreatedThreads;
|
338 |
| } |
339 |
| |
340 |
1
| protected Thread createPushStateThread()
|
341 |
| { |
342 |
1
| return new Thread(new Runnable()
|
343 |
| { |
344 |
1
| public void run()
|
345 |
| { |
346 |
1
| numberCreatedThreads++;
|
347 |
1
| try
|
348 |
| { |
349 |
1
| Thread.sleep(busyPeriod);
|
350 |
| } |
351 |
| catch (InterruptedException e) |
352 |
| { |
353 |
0
| fail("ActiveStatusModifier interrupted");
|
354 |
| } |
355 |
| } |
356 |
| }); |
357 |
| } |
358 |
| } |
359 |
| |
360 |
| class ActiveStatusModifier implements Runnable |
361 |
| { |
362 |
| private SingletonStoreCacheLoader scl; |
363 |
| |
364 |
2
| public ActiveStatusModifier(SingletonStoreCacheLoader singleton)
|
365 |
| { |
366 |
2
| scl = singleton;
|
367 |
| } |
368 |
| |
369 |
2
| public void run()
|
370 |
| { |
371 |
2
| scl.activeStatusChanged(true);
|
372 |
2
| try
|
373 |
| { |
374 |
2
| scl.getPushStateThread().join();
|
375 |
| } |
376 |
| catch (InterruptedException e) |
377 |
| { |
378 |
0
| throw new RuntimeException(e);
|
379 |
| } |
380 |
| } |
381 |
| } |
382 |
| } |