1 |
| |
2 |
| |
3 |
| |
4 |
| |
5 |
| |
6 |
| |
7 |
| |
8 |
| |
9 |
| |
10 |
| |
11 |
| |
12 |
| |
13 |
| |
14 |
| |
15 |
| |
16 |
| |
17 |
| |
18 |
| |
19 |
| |
20 |
| |
21 |
| |
22 |
| |
23 |
| package org.jboss.cache.statetransfer; |
24 |
| |
25 |
| import org.jboss.cache.Cache; |
26 |
| import org.jboss.cache.CacheSPI; |
27 |
| import org.jboss.cache.DefaultCacheFactory; |
28 |
| import org.jboss.cache.Fqn; |
29 |
| import org.jboss.cache.config.Configuration; |
30 |
| import org.jboss.cache.config.Configuration.CacheMode; |
31 |
| import org.jboss.cache.factories.UnitTestCacheConfigurationFactory; |
32 |
| import org.jboss.cache.loader.AbstractCacheLoaderTestBase; |
33 |
| import org.jboss.cache.loader.CacheLoader; |
34 |
| import org.jboss.cache.marshall.SelectedClassnameClassLoader; |
35 |
| import org.jboss.cache.misc.TestingUtil; |
36 |
| |
37 |
| import java.io.File; |
38 |
| import java.util.HashMap; |
39 |
| import java.util.Map; |
40 |
| import java.util.Properties; |
41 |
| import java.util.concurrent.Semaphore; |
42 |
| import java.util.concurrent.TimeUnit; |
43 |
| |
44 |
| |
45 |
| |
46 |
| |
47 |
| |
48 |
| |
49 |
| |
50 |
| public abstract class StateTransferTestBase extends AbstractCacheLoaderTestBase |
51 |
| { |
52 |
| public static final Fqn A_B = Fqn.fromString("/a/b"); |
53 |
| public static final Fqn A_C = Fqn.fromString("/a/c"); |
54 |
| public static final Fqn A_D = Fqn.fromString("/a/d"); |
55 |
| public static final String JOE = "JOE"; |
56 |
| public static final String BOB = "BOB"; |
57 |
| public static final String JANE = "JANE"; |
58 |
| public static final Integer TWENTY = 20; |
59 |
| public static final Integer FORTY = 40; |
60 |
| |
61 |
| protected Map<String, Cache> caches; |
62 |
| private ClassLoader orig_TCL; |
63 |
| |
64 |
| |
65 |
| protected abstract String getReplicationVersion(); |
66 |
| |
67 |
46
| protected CacheSPI createCache(String cacheID,
|
68 |
| boolean sync, |
69 |
| boolean useMarshalling, |
70 |
| boolean useCacheLoader) |
71 |
| throws Exception |
72 |
| { |
73 |
46
| return createCache(cacheID, sync, useMarshalling, useCacheLoader, false, true);
|
74 |
| } |
75 |
| |
76 |
71
| protected CacheSPI createCache(String cacheID,
|
77 |
| boolean sync, |
78 |
| boolean useMarshalling, |
79 |
| boolean useCacheLoader, |
80 |
| boolean cacheLoaderAsync, |
81 |
| boolean startCache) |
82 |
| throws Exception |
83 |
| { |
84 |
71
| if (useCacheLoader)
|
85 |
| { |
86 |
14
| return createCache(cacheID, sync, useMarshalling, "org.jboss.cache.loader.FileCacheLoader", cacheLoaderAsync, startCache);
|
87 |
| } |
88 |
| else |
89 |
| { |
90 |
57
| return createCache(cacheID, sync, useMarshalling, null, cacheLoaderAsync, startCache);
|
91 |
| } |
92 |
| } |
93 |
| |
94 |
105
| protected CacheSPI createCache(String cacheID, boolean sync, boolean useMarshalling, String cacheLoaderClass,
|
95 |
| boolean cacheLoaderAsync, boolean startCache) throws Exception |
96 |
| { |
97 |
105
| if (caches.get(cacheID) != null)
|
98 |
| { |
99 |
0
| throw new IllegalStateException(cacheID + " already created");
|
100 |
| } |
101 |
| |
102 |
105
| CacheMode mode = sync ? CacheMode.REPL_SYNC : CacheMode.REPL_ASYNC;
|
103 |
105
| Configuration c = UnitTestCacheConfigurationFactory.createConfiguration(mode);
|
104 |
105
| if (sync)
|
105 |
| { |
106 |
15
| c.setSyncRollbackPhase(true);
|
107 |
15
| c.setSyncCommitPhase(true);
|
108 |
| } |
109 |
105
| c.setClusterName("VersionedTestBase");
|
110 |
105
| c.setReplVersionString(getReplicationVersion());
|
111 |
| |
112 |
105
| c.setStateRetrievalTimeout(60000);
|
113 |
105
| if (useMarshalling)
|
114 |
| { |
115 |
45
| c.setUseRegionBasedMarshalling(true);
|
116 |
45
| c.setInactiveOnStartup(true);
|
117 |
| } |
118 |
105
| if (cacheLoaderClass != null && cacheLoaderClass.length() > 0)
|
119 |
| { |
120 |
48
| configureCacheLoader(c, cacheLoaderClass, cacheID, useMarshalling, cacheLoaderAsync);
|
121 |
| } |
122 |
| |
123 |
| |
124 |
| |
125 |
105
| CacheSPI tree = (CacheSPI) DefaultCacheFactory.getInstance().createCache(c, false);
|
126 |
| |
127 |
| |
128 |
105
| configureMultiplexer(tree);
|
129 |
| |
130 |
| |
131 |
| |
132 |
105
| caches.put(cacheID, tree);
|
133 |
| |
134 |
105
| if (startCache)
|
135 |
| { |
136 |
66
| tree.create();
|
137 |
66
| tree.start();
|
138 |
| } |
139 |
| |
140 |
104
| return tree;
|
141 |
| } |
142 |
| |
143 |
| |
144 |
| |
145 |
| |
146 |
| |
147 |
| |
148 |
| |
149 |
| |
150 |
71
| protected void configureMultiplexer(Cache cache) throws Exception
|
151 |
| { |
152 |
| |
153 |
| } |
154 |
| |
155 |
| |
156 |
| |
157 |
| |
158 |
| |
159 |
| |
160 |
| |
161 |
| |
162 |
1
| protected void validateMultiplexer(Cache cache)
|
163 |
| { |
164 |
1
| assertFalse("Cache is not using multiplexer", cache.getConfiguration().isUsingMultiplexer());
|
165 |
| } |
166 |
| |
167 |
2
| protected void startCache(Cache cache) throws Exception
|
168 |
| { |
169 |
2
| cache.create();
|
170 |
2
| cache.start();
|
171 |
| |
172 |
2
| validateMultiplexer(cache);
|
173 |
| } |
174 |
| |
175 |
0
| protected void configureCacheLoader(Configuration c,
|
176 |
| String cacheID, |
177 |
| boolean useExtended, |
178 |
| boolean async) |
179 |
| throws Exception |
180 |
| { |
181 |
0
| configureCacheLoader(c, "org.jboss.cache.loader.FileCacheLoader", cacheID, useExtended, async);
|
182 |
| } |
183 |
| |
184 |
48
| protected void configureCacheLoader(Configuration c, String cacheloaderClass, String cacheID, boolean useExtended,
|
185 |
| boolean async) throws Exception |
186 |
| { |
187 |
48
| if (cacheloaderClass != null)
|
188 |
| { |
189 |
48
| if (cacheloaderClass.equals("org.jboss.cache.loader.JDBCCacheLoader"))
|
190 |
| { |
191 |
6
| Properties prop = new Properties();
|
192 |
6
| try
|
193 |
| { |
194 |
6
| prop.load(this.getClass().getClassLoader().getResourceAsStream("cache-jdbc.properties"));
|
195 |
| } |
196 |
| catch (Exception e) |
197 |
| { |
198 |
0
| System.out.println("Error loading jdbc properties ");
|
199 |
| } |
200 |
6
| String props = "cache.jdbc.driver =" + prop.getProperty("cache.jdbc.driver") + "\n" + "cache.jdbc.url="
|
201 |
| + prop.getProperty("cache.jdbc.url") + "\n" + "cache.jdbc.user=" |
202 |
| + prop.getProperty("cache.jdbc.user") + "\n" + "cache.jdbc.password=" |
203 |
| + prop.getProperty("cache.jdbc.password") + "\n" + "cache.jdbc.node.type=" |
204 |
| + prop.getProperty("cache.jdbc.node.type") + "\n" + "cache.jdbc.sql-concat=" |
205 |
| + prop.getProperty("cache.jdbc.sql-concat"); |
206 |
| |
207 |
6
| c.setCacheLoaderConfig(getSingleCacheLoaderConfig("", "org.jboss.cache.loader.JDBCCacheLoader",
|
208 |
| props, false, true, false)); |
209 |
| } |
210 |
| else |
211 |
| { |
212 |
| |
213 |
42
| String tmp_location = getTempLocation(cacheID);
|
214 |
| |
215 |
| |
216 |
42
| File file = new File(tmp_location);
|
217 |
42
| cleanFile(file);
|
218 |
| |
219 |
42
| file.mkdir();
|
220 |
| |
221 |
42
| tmp_location = escapeWindowsPath(tmp_location);
|
222 |
42
| String props = "location = " + tmp_location + "\n";
|
223 |
42
| c.setCacheLoaderConfig(getSingleCacheLoaderConfig("", cacheloaderClass, props, async, true, false));
|
224 |
| } |
225 |
| } |
226 |
| } |
227 |
| |
228 |
16
| protected void initialStateTferWithLoaderTest(String cacheLoaderClass1, String cacheLoaderClass2, boolean asyncLoader) throws Exception
|
229 |
| { |
230 |
16
| CacheSPI cache1 = createCache("cache1", false, false, cacheLoaderClass1, false, true);
|
231 |
| |
232 |
16
| cache1.put(A_B, "name", JOE);
|
233 |
16
| cache1.put(A_B, "age", TWENTY);
|
234 |
16
| cache1.put(A_C, "name", BOB);
|
235 |
16
| cache1.put(A_C, "age", FORTY);
|
236 |
| |
237 |
16
| CacheSPI cache2 = createCache("cache2", false, false, cacheLoaderClass2, asyncLoader, false);
|
238 |
| |
239 |
16
| cache2.start();
|
240 |
| |
241 |
| |
242 |
16
| TestingUtil.blockUntilViewsReceived(new CacheSPI[]{cache1, cache2}, 60000);
|
243 |
| |
244 |
16
| if (asyncLoader)
|
245 |
| { |
246 |
2
| TestingUtil.sleepThread((long) 100);
|
247 |
| } |
248 |
| |
249 |
16
| CacheLoader loader = cache2.getCacheLoaderManager().getCacheLoader();
|
250 |
| |
251 |
16
| assertEquals("Incorrect loader name for /a/b", JOE, loader.get(A_B).get("name"));
|
252 |
16
| assertEquals("Incorrect loader age for /a/b", TWENTY, loader.get(A_B).get("age"));
|
253 |
16
| assertEquals("Incorrect loader name for /a/c", BOB, loader.get(A_C).get("name"));
|
254 |
16
| assertEquals("Incorrect loader age for /a/c", FORTY, loader.get(A_C).get("age"));
|
255 |
| |
256 |
16
| assertEquals("Incorrect name for /a/b", JOE, cache2.get(A_B, "name"));
|
257 |
16
| assertEquals("Incorrect age for /a/b", TWENTY, cache2.get(A_B, "age"));
|
258 |
16
| assertEquals("Incorrect name for /a/c", BOB, cache2.get(A_C, "name"));
|
259 |
16
| assertEquals("Incorrect age for /a/c", FORTY, cache2.get(A_C, "age"));
|
260 |
| } |
261 |
| |
262 |
157
| protected String getTempLocation(String cacheID)
|
263 |
| { |
264 |
157
| String tmp_location = System.getProperty("java.io.tmpdir", "c:\\tmp");
|
265 |
157
| File file = new File(tmp_location);
|
266 |
157
| file = new File(file, cacheID);
|
267 |
157
| return file.getAbsolutePath();
|
268 |
| } |
269 |
| |
270 |
42
| protected String escapeWindowsPath(String path)
|
271 |
| { |
272 |
42
| if ('/' == File.separatorChar)
|
273 |
| { |
274 |
42
| return path;
|
275 |
| } |
276 |
| |
277 |
0
| char[] chars = path.toCharArray();
|
278 |
0
| StringBuffer sb = new StringBuffer();
|
279 |
0
| for (char aChar : chars)
|
280 |
| { |
281 |
0
| if (aChar == '\\')
|
282 |
| { |
283 |
0
| sb.append('\\');
|
284 |
| } |
285 |
0
| sb.append(aChar);
|
286 |
| } |
287 |
0
| return sb.toString();
|
288 |
| } |
289 |
| |
290 |
58
| protected void setUp() throws Exception
|
291 |
| { |
292 |
58
| super.setUp();
|
293 |
| |
294 |
58
| caches = new HashMap<String, Cache>();
|
295 |
| |
296 |
| |
297 |
58
| orig_TCL = Thread.currentThread().getContextClassLoader();
|
298 |
| } |
299 |
| |
300 |
58
| protected void tearDown() throws Exception
|
301 |
| { |
302 |
| |
303 |
58
| System.out.println("*** in tearDown()");
|
304 |
| |
305 |
58
| super.tearDown();
|
306 |
| |
307 |
| |
308 |
58
| Thread.currentThread().setContextClassLoader(orig_TCL);
|
309 |
| |
310 |
58
| for (String cacheID : caches.keySet())
|
311 |
| { |
312 |
115
| stopCache(caches.get(cacheID));
|
313 |
115
| TestingUtil.sleepThread(1500);
|
314 |
115
| File file = new File(getTempLocation(cacheID));
|
315 |
115
| cleanFile(file);
|
316 |
| } |
317 |
| } |
318 |
| |
319 |
115
| protected void stopCache(Cache cache)
|
320 |
| { |
321 |
115
| if (cache != null)
|
322 |
| { |
323 |
115
| try
|
324 |
| { |
325 |
115
| cache.stop();
|
326 |
115
| cache.destroy();
|
327 |
| } |
328 |
| catch (Exception e) |
329 |
| { |
330 |
0
| System.out.println("Exception stopping cache " + e.getMessage());
|
331 |
0
| e.printStackTrace(System.out);
|
332 |
| } |
333 |
| } |
334 |
| } |
335 |
| |
336 |
341
| protected void cleanFile(File file)
|
337 |
| { |
338 |
341
| File[] children = file.listFiles();
|
339 |
341
| if (children != null)
|
340 |
| { |
341 |
126
| for (File child : children)
|
342 |
| { |
343 |
184
| cleanFile(child);
|
344 |
| } |
345 |
| } |
346 |
| |
347 |
341
| if (file.exists())
|
348 |
| { |
349 |
226
| file.delete();
|
350 |
| } |
351 |
341
| if (file.exists())
|
352 |
| { |
353 |
0
| file.deleteOnExit();
|
354 |
| } |
355 |
| } |
356 |
| |
357 |
4
| protected ClassLoader getClassLoader() throws Exception
|
358 |
| { |
359 |
4
| String[] includesClasses = {"org.jboss.cache.marshall.Person",
|
360 |
| "org.jboss.cache.marshall.Address"}; |
361 |
4
| String[] excludesClasses = {};
|
362 |
4
| ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
363 |
4
| return new SelectedClassnameClassLoader(includesClasses, excludesClasses, cl);
|
364 |
| } |
365 |
| |
366 |
2
| protected ClassLoader getNotFoundClassLoader() throws Exception
|
367 |
| { |
368 |
2
| String[] notFoundClasses = {"org.jboss.cache.marshall.Person",
|
369 |
| "org.jboss.cache.marshall.Address"}; |
370 |
2
| ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
371 |
2
| return new SelectedClassnameClassLoader(null, null, notFoundClasses, cl);
|
372 |
| } |
373 |
| |
374 |
| protected abstract class CacheUser implements Runnable |
375 |
| { |
376 |
| protected Semaphore semaphore; |
377 |
| protected CacheSPI cache; |
378 |
| protected String name; |
379 |
| protected Exception exception; |
380 |
| protected Thread thread; |
381 |
| |
382 |
0
| CacheUser()
|
383 |
| { |
384 |
| } |
385 |
| |
386 |
28
| CacheUser(Semaphore semaphore,
|
387 |
| String name, |
388 |
| boolean sync, |
389 |
| boolean activateRoot) |
390 |
| throws Exception |
391 |
| { |
392 |
28
| this.cache = createCache(name, sync, true, false);
|
393 |
28
| this.semaphore = semaphore;
|
394 |
28
| this.name = name;
|
395 |
| |
396 |
28
| if (activateRoot)
|
397 |
| { |
398 |
0
| cache.getRegion(Fqn.ROOT, true).activate();
|
399 |
| } |
400 |
| } |
401 |
| |
402 |
28
| public void run()
|
403 |
| { |
404 |
28
| boolean acquired = false;
|
405 |
28
| try
|
406 |
| { |
407 |
28
| acquired = semaphore.tryAcquire(60, TimeUnit.SECONDS);
|
408 |
28
| if (!acquired)
|
409 |
| { |
410 |
0
| throw new Exception(name + " cannot acquire semaphore");
|
411 |
| } |
412 |
| |
413 |
| |
414 |
28
| useCache();
|
415 |
| |
416 |
| } |
417 |
| catch (Exception e) |
418 |
| { |
419 |
0
| System.out.println(name + ": " + e.getLocalizedMessage());
|
420 |
0
| e.printStackTrace(System.out);
|
421 |
| |
422 |
| |
423 |
0
| exception = e;
|
424 |
| } |
425 |
| finally |
426 |
| { |
427 |
28
| if (acquired)
|
428 |
| { |
429 |
28
| semaphore.release();
|
430 |
| } |
431 |
| } |
432 |
| |
433 |
| } |
434 |
| |
435 |
| abstract void useCache() throws Exception; |
436 |
| |
437 |
28
| public Exception getException()
|
438 |
| { |
439 |
28
| return exception;
|
440 |
| } |
441 |
| |
442 |
28
| public CacheSPI getCacheSPI()
|
443 |
| { |
444 |
28
| return cache;
|
445 |
| } |
446 |
| |
447 |
0
| public String getName()
|
448 |
| { |
449 |
0
| return name;
|
450 |
| } |
451 |
| |
452 |
28
| public void start()
|
453 |
| { |
454 |
28
| thread = new Thread(this);
|
455 |
28
| thread.start();
|
456 |
| } |
457 |
| |
458 |
28
| public void cleanup()
|
459 |
| { |
460 |
28
| if (thread != null && thread.isAlive())
|
461 |
| { |
462 |
1
| thread.interrupt();
|
463 |
| } |
464 |
| } |
465 |
| } |
466 |
| } |