1 |
| |
2 |
| |
3 |
| |
4 |
| |
5 |
| |
6 |
| |
7 |
| |
8 |
| |
9 |
| package org.jboss.cache.transaction; |
10 |
| |
11 |
| import junit.framework.Test; |
12 |
| import junit.framework.TestCase; |
13 |
| import junit.framework.TestSuite; |
14 |
| import org.jboss.cache.CacheException; |
15 |
| import org.jboss.cache.CacheImpl; |
16 |
| import org.jboss.cache.DefaultCacheFactory; |
17 |
| import org.jboss.cache.Fqn; |
18 |
| import org.jboss.cache.GlobalTransaction; |
19 |
| import org.jboss.cache.Node; |
20 |
| import org.jboss.cache.NodeSPI; |
21 |
| import org.jboss.cache.lock.IsolationLevel; |
22 |
| import org.jboss.cache.lock.NodeLock; |
23 |
| |
24 |
| import javax.naming.Context; |
25 |
| import javax.naming.InitialContext; |
26 |
| import javax.transaction.HeuristicMixedException; |
27 |
| import javax.transaction.HeuristicRollbackException; |
28 |
| import javax.transaction.NotSupportedException; |
29 |
| import javax.transaction.RollbackException; |
30 |
| import javax.transaction.SystemException; |
31 |
| import javax.transaction.Transaction; |
32 |
| import javax.transaction.UserTransaction; |
33 |
| import java.util.HashMap; |
34 |
| import java.util.Map; |
35 |
| import java.util.Properties; |
36 |
| import java.util.Set; |
37 |
| |
38 |
| |
39 |
| |
40 |
| |
41 |
| |
42 |
| |
43 |
| |
44 |
| public class TransactionTest extends TestCase |
45 |
| { |
46 |
| CacheImpl cache = null; |
47 |
| UserTransaction tx = null; |
48 |
| Properties p = null; |
49 |
| String old_factory = null; |
50 |
| final String FACTORY = "org.jboss.cache.transaction.DummyContextFactory"; |
51 |
| Exception thread_ex; |
52 |
| |
53 |
| |
54 |
34
| public TransactionTest(String name)
|
55 |
| { |
56 |
34
| super(name);
|
57 |
| } |
58 |
| |
59 |
34
| public void setUp() throws Exception
|
60 |
| { |
61 |
34
| super.setUp();
|
62 |
34
| old_factory = System.getProperty(Context.INITIAL_CONTEXT_FACTORY);
|
63 |
34
| System.setProperty(Context.INITIAL_CONTEXT_FACTORY, FACTORY);
|
64 |
34
| DummyTransactionManager.getInstance();
|
65 |
34
| if (p == null)
|
66 |
| { |
67 |
34
| p = new Properties();
|
68 |
34
| p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.cache.transaction.DummyContextFactory");
|
69 |
| } |
70 |
| |
71 |
34
| tx = (UserTransaction) new InitialContext(p).lookup("UserTransaction");
|
72 |
34
| cache = (CacheImpl) DefaultCacheFactory.getInstance().createCache(false);
|
73 |
34
| cache.getConfiguration().setClusterName("test");
|
74 |
34
| cache.getConfiguration().setInitialStateRetrievalTimeout(10000);
|
75 |
34
| cache.getConfiguration().setTransactionManagerLookupClass("org.jboss.cache.DummyTransactionManagerLookup");
|
76 |
34
| cache.getConfiguration().setIsolationLevel(IsolationLevel.SERIALIZABLE);
|
77 |
34
| cache.getConfiguration().setLockParentForChildInsertRemove(true);
|
78 |
34
| cache.create();
|
79 |
34
| cache.start();
|
80 |
34
| thread_ex = null;
|
81 |
| } |
82 |
| |
83 |
34
| public void tearDown() throws Exception
|
84 |
| { |
85 |
34
| super.tearDown();
|
86 |
34
| if (cache != null)
|
87 |
| { |
88 |
34
| cache.stop();
|
89 |
34
| cache = null;
|
90 |
| } |
91 |
| |
92 |
| |
93 |
34
| DummyTransactionManager.destroy();
|
94 |
34
| if (old_factory != null)
|
95 |
| { |
96 |
33
| System.setProperty(Context.INITIAL_CONTEXT_FACTORY, old_factory);
|
97 |
33
| old_factory = null;
|
98 |
| } |
99 |
| |
100 |
34
| if (tx != null)
|
101 |
| { |
102 |
34
| try
|
103 |
| { |
104 |
34
| tx.rollback();
|
105 |
| } |
106 |
| catch (Throwable t) |
107 |
| { |
108 |
| } |
109 |
34
| tx = null;
|
110 |
| } |
111 |
| } |
112 |
| |
113 |
| |
114 |
1
| public void testPutTx() throws Exception
|
115 |
| { |
116 |
1
| tx.begin();
|
117 |
1
| cache.put("/a/b/c", "age", 38);
|
118 |
| |
119 |
1
| assertEquals(cache.get("/a/b/c", "age"), 38);
|
120 |
| |
121 |
1
| cache.put("/a/b/c", "age", 39);
|
122 |
1
| tx.commit();
|
123 |
| |
124 |
| |
125 |
| |
126 |
1
| assertEquals(cache.get("/a/b/c", "age"), 39);
|
127 |
| } |
128 |
| |
129 |
| |
130 |
1
| public void testRollbackTx1()
|
131 |
| { |
132 |
1
| try
|
133 |
| { |
134 |
1
| tx.begin();
|
135 |
1
| cache.put("/a/b/c", "age", 38);
|
136 |
1
| cache.put("/a/b/c", "age", 39);
|
137 |
1
| tx.rollback();
|
138 |
| |
139 |
| |
140 |
| |
141 |
1
| assertNull(cache.get("/a/b/c", "age"));
|
142 |
| } |
143 |
| catch (Throwable t) |
144 |
| { |
145 |
0
| t.printStackTrace();
|
146 |
0
| fail(t.toString());
|
147 |
| } |
148 |
| } |
149 |
| |
150 |
| |
151 |
1
| public void testGetAfterRemovalRollback() throws Exception
|
152 |
| { |
153 |
1
| assertEquals(0, cache.getNumberOfLocksHeld());
|
154 |
1
| cache.put("/a/b", null);
|
155 |
1
| assertEquals(0, cache.getNumberOfLocksHeld());
|
156 |
1
| assertTrue(cache.exists("/a/b"));
|
157 |
1
| tx.begin();
|
158 |
1
| cache.remove("/a/b");
|
159 |
1
| assertFalse(cache.exists("/a/b"));
|
160 |
1
| tx.rollback();
|
161 |
1
| assertTrue(cache.exists("/a/b"));
|
162 |
1
| assertEquals(0, cache.getNumberOfLocksHeld());
|
163 |
| |
164 |
1
| Thread th = new Thread()
|
165 |
| { |
166 |
1
| public void run()
|
167 |
| { |
168 |
1
| try
|
169 |
| { |
170 |
1
| cache.getTransactionManager().begin();
|
171 |
1
| assertNotNull(cache.get("/a/b"));
|
172 |
1
| cache.getTransactionManager().rollback();
|
173 |
| } |
174 |
| catch (Exception e) |
175 |
| { |
176 |
0
| e.printStackTrace();
|
177 |
0
| fail("Caught exception");
|
178 |
| } |
179 |
| } |
180 |
| }; |
181 |
| |
182 |
1
| th.start();
|
183 |
1
| th.join();
|
184 |
| |
185 |
1
| assertEquals(0, cache.getNumberOfLocksHeld());
|
186 |
| } |
187 |
| |
188 |
1
| public void testRollbackTx2()
|
189 |
| { |
190 |
1
| try
|
191 |
| { |
192 |
1
| tx.begin();
|
193 |
1
| cache.put("/a/b/c", "age", 38);
|
194 |
1
| cache.remove("/a/b/c", "age");
|
195 |
1
| tx.rollback();
|
196 |
| |
197 |
| |
198 |
| |
199 |
1
| assertNull(cache.get("/a/b/c", "age"));
|
200 |
| } |
201 |
| catch (Throwable t) |
202 |
| { |
203 |
0
| t.printStackTrace();
|
204 |
0
| fail(t.toString());
|
205 |
| } |
206 |
| } |
207 |
| |
208 |
1
| public void testRollbackTx2a()
|
209 |
| { |
210 |
1
| try
|
211 |
| { |
212 |
1
| System.out.println("locks " + cache.printLockInfo());
|
213 |
1
| cache.put("/a/b/c", "age", 38);
|
214 |
1
| System.out.println("locks " + cache.printLockInfo());
|
215 |
1
| tx.begin();
|
216 |
1
| cache.remove("/a/b/c", "age");
|
217 |
1
| tx.rollback();
|
218 |
| |
219 |
| |
220 |
| |
221 |
1
| assertEquals(38, cache.get("/a/b/c", "age"));
|
222 |
| } |
223 |
| catch (Throwable t) |
224 |
| { |
225 |
0
| t.printStackTrace();
|
226 |
0
| fail(t.toString());
|
227 |
| } |
228 |
| } |
229 |
| |
230 |
1
| public void testRollbackTx3()
|
231 |
| { |
232 |
1
| try
|
233 |
| { |
234 |
1
| java.util.Map map1 = new java.util.HashMap();
|
235 |
1
| map1.put("age", 38);
|
236 |
1
| java.util.Map map2 = new java.util.HashMap();
|
237 |
1
| map2.put("age", 39);
|
238 |
1
| tx.begin();
|
239 |
1
| cache.put("/a/b/c", map1);
|
240 |
1
| cache.put("/a/b/c", map2);
|
241 |
1
| tx.rollback();
|
242 |
| |
243 |
| |
244 |
| |
245 |
1
| assertNull(cache.get("/a/b/c", "age"));
|
246 |
| } |
247 |
| catch (Throwable t) |
248 |
| { |
249 |
0
| t.printStackTrace();
|
250 |
0
| fail(t.toString());
|
251 |
| } |
252 |
| } |
253 |
| |
254 |
| |
255 |
1
| public void testRollbackTx4()
|
256 |
| { |
257 |
1
| try
|
258 |
| { |
259 |
1
| Map map = new HashMap();
|
260 |
1
| map.put("age", 38);
|
261 |
1
| tx.begin();
|
262 |
1
| cache.put("/a/b/c", map);
|
263 |
1
| cache.remove("/a/b/c");
|
264 |
1
| tx.rollback();
|
265 |
| |
266 |
| |
267 |
| |
268 |
1
| assertNull(cache.get("/a/b/c", "age"));
|
269 |
| } |
270 |
| catch (Throwable t) |
271 |
| { |
272 |
0
| t.printStackTrace();
|
273 |
0
| fail(t.toString());
|
274 |
| } |
275 |
| } |
276 |
| |
277 |
1
| public void testNodeCreationRollback()
|
278 |
| { |
279 |
1
| try
|
280 |
| { |
281 |
1
| tx.begin();
|
282 |
1
| System.out.println("initial state:\n" + cache);
|
283 |
1
| cache.put("/bela/ban", "key", "value");
|
284 |
1
| System.out.println("after put():\n" + cache);
|
285 |
1
| tx.rollback();
|
286 |
1
| System.out.println("after rollback():\n" + cache);
|
287 |
| |
288 |
1
| assertNull("node should be not existent", cache.get("/bela/ban"));
|
289 |
| } |
290 |
| catch (Throwable t) |
291 |
| { |
292 |
0
| t.printStackTrace();
|
293 |
0
| fail(t.toString());
|
294 |
| } |
295 |
| } |
296 |
| |
297 |
1
| public void testNodeCreationRollback2()
|
298 |
| { |
299 |
1
| try
|
300 |
| { |
301 |
1
| cache.put("/bela/ban", null);
|
302 |
1
| tx.begin();
|
303 |
1
| cache.put("/bela/ban/michelle", null);
|
304 |
1
| tx.rollback();
|
305 |
1
| assertNotNull("node should be not null", cache.get("/bela/ban"));
|
306 |
1
| assertNull("node should be not existent", cache.get("/bela/ban/michelle"));
|
307 |
| } |
308 |
| catch (Throwable t) |
309 |
| { |
310 |
0
| t.printStackTrace();
|
311 |
0
| fail(t.toString());
|
312 |
| } |
313 |
| } |
314 |
| |
315 |
1
| public void testNodeDeletionRollback()
|
316 |
| { |
317 |
1
| try
|
318 |
| { |
319 |
1
| cache.put("/a/b/c", null);
|
320 |
1
| tx.begin();
|
321 |
1
| cache.remove("/a/b/c");
|
322 |
1
| assertNull(cache.get("/a/b/c"));
|
323 |
1
| cache.remove("/a/b");
|
324 |
1
| assertNull(cache.get("/a/b"));
|
325 |
1
| cache.remove("/a");
|
326 |
1
| assertNull(cache.get("/a"));
|
327 |
1
| tx.rollback();
|
328 |
1
| assertNotNull(cache.get("/a/b/c"));
|
329 |
1
| assertNotNull(cache.get("/a/b"));
|
330 |
1
| assertNotNull(cache.get("/a"));
|
331 |
| } |
332 |
| catch (Throwable t) |
333 |
| { |
334 |
0
| t.printStackTrace();
|
335 |
0
| fail(t.toString());
|
336 |
| } |
337 |
| } |
338 |
| |
339 |
1
| public void testNodeDeletionRollback2() throws Exception
|
340 |
| { |
341 |
1
| cache.put("/a/b/c", null);
|
342 |
1
| cache.put("/a/b/c1", null);
|
343 |
1
| cache.put("/a/b/c2", null);
|
344 |
1
| tx.begin();
|
345 |
1
| cache.remove("/a");
|
346 |
1
| assertNull(cache.get("/a/b/c"));
|
347 |
1
| assertNull(cache.get("/a/b/c1"));
|
348 |
1
| assertNull(cache.get("/a/b/c2"));
|
349 |
1
| assertNull(cache.get("/a/b"));
|
350 |
1
| assertNull(cache.get("/a"));
|
351 |
1
| Set children = cache.getChildrenNames("/a/b");
|
352 |
1
| assertTrue(children.isEmpty());
|
353 |
1
| children = cache.getChildrenNames("/a");
|
354 |
1
| assertTrue(children.isEmpty());
|
355 |
1
| tx.rollback();
|
356 |
1
| assertNotNull(cache.get("/a"));
|
357 |
1
| assertNotNull(cache.get("/a/b"));
|
358 |
1
| assertNotNull(cache.get("/a/b/c"));
|
359 |
1
| assertNotNull(cache.get("/a/b/c1"));
|
360 |
1
| assertNotNull(cache.get("/a/b/c2"));
|
361 |
1
| children = cache.getChildrenNames("/a/b");
|
362 |
1
| assertEquals(3, children.size());
|
363 |
| } |
364 |
| |
365 |
| |
366 |
1
| public void testNodeCreation() throws Exception
|
367 |
| { |
368 |
1
| GlobalTransaction gtx;
|
369 |
1
| cache.put("/a/b", null);
|
370 |
1
| tx.begin();
|
371 |
1
| gtx = cache.getCurrentTransaction();
|
372 |
1
| cache.put("/a/b/c", null);
|
373 |
1
| assertLocked(gtx, "/a", false);
|
374 |
1
| assertLocked(gtx, "/a/b", true);
|
375 |
1
| assertLocked(gtx, "/a/b/c", true);
|
376 |
1
| System.out.println("locks: " + cache.printLockInfo());
|
377 |
| } |
378 |
| |
379 |
| |
380 |
1
| public void testNodeCreation2() throws Exception
|
381 |
| { |
382 |
1
| GlobalTransaction gtx;
|
383 |
1
| tx.begin();
|
384 |
1
| gtx = cache.getCurrentTransaction();
|
385 |
1
| cache.put("/a/b/c", null);
|
386 |
1
| assertLocked(gtx, "/a", true);
|
387 |
1
| assertLocked(gtx, "/a/b", true);
|
388 |
1
| assertLocked(gtx, "/a/b/c", true);
|
389 |
1
| System.out.println("locks: " + cache.printLockInfo());
|
390 |
| } |
391 |
| |
392 |
| |
393 |
1
| public void testNodeRemoval()
|
394 |
| { |
395 |
1
| GlobalTransaction gtx;
|
396 |
1
| try
|
397 |
| { |
398 |
1
| cache.put("/a/b/c", null);
|
399 |
1
| tx.begin();
|
400 |
1
| gtx = cache.getCurrentTransaction();
|
401 |
1
| cache.remove("/a/b/c");
|
402 |
1
| System.out.println("Locks: " + cache.printLockInfo());
|
403 |
1
| assertLocked(gtx, "/a", false);
|
404 |
1
| assertLocked(gtx, "/a/b", true);
|
405 |
1
| assertLocked(gtx, "/a/b/c", true);
|
406 |
1
| System.out.println("locks: " + cache.printLockInfo());
|
407 |
| } |
408 |
| catch (Throwable t) |
409 |
| { |
410 |
0
| t.printStackTrace();
|
411 |
0
| fail(t.toString());
|
412 |
| } |
413 |
| } |
414 |
| |
415 |
| |
416 |
1
| public void testNodeRemoval2()
|
417 |
| { |
418 |
1
| GlobalTransaction gtx;
|
419 |
1
| try
|
420 |
| { |
421 |
1
| cache.put("/a/b/c", null);
|
422 |
1
| tx.begin();
|
423 |
1
| gtx = cache.getCurrentTransaction();
|
424 |
1
| cache.remove("/a/b");
|
425 |
1
| assertLocked(gtx, "/a", true);
|
426 |
1
| assertLocked(gtx, "/a/b", true);
|
427 |
1
| assertLocked(gtx, "/a/b/c", true);
|
428 |
1
| System.out.println("locks: " + cache.printLockInfo());
|
429 |
| } |
430 |
| catch (Throwable t) |
431 |
| { |
432 |
0
| t.printStackTrace();
|
433 |
0
| fail(t.toString());
|
434 |
| } |
435 |
| } |
436 |
| |
437 |
1
| public void testIntermediateNodeCreationOnWrite() throws Exception
|
438 |
| { |
439 |
1
| cache.put("/a", null);
|
440 |
1
| tx.begin();
|
441 |
1
| cache.put("/a/b/c", null);
|
442 |
| |
443 |
1
| GlobalTransaction gtx = cache.getCurrentTransaction();
|
444 |
1
| assertLocked(gtx, "/a", true);
|
445 |
1
| assertLocked(gtx, "/a/b", true);
|
446 |
1
| assertLocked(gtx, "/a/b/c", true);
|
447 |
1
| tx.rollback();
|
448 |
| |
449 |
| } |
450 |
| |
451 |
1
| public void testIntermediateNodeCreationOnRead() throws Exception
|
452 |
| { |
453 |
1
| cache.put("/a", null);
|
454 |
1
| tx.begin();
|
455 |
1
| cache.get("/a/b/c");
|
456 |
| |
457 |
| |
458 |
| |
459 |
1
| GlobalTransaction gtx = cache.getCurrentTransaction();
|
460 |
1
| assertLocked(gtx, "/", false);
|
461 |
1
| assertLocked(gtx, "/a", false);
|
462 |
1
| assertNull("/a/b should not exist", cache.peek(Fqn.fromString("/a/b"), true));
|
463 |
1
| assertNull("/a/b/c should not exist", cache.peek(Fqn.fromString("/a/b/c"), true));
|
464 |
1
| tx.rollback();
|
465 |
1
| assertNull("/a/b should not exist", cache.peek(Fqn.fromString("/a/b"), true));
|
466 |
1
| assertNull("/a/b/c should not exist", cache.peek(Fqn.fromString("/a/b/c"), true));
|
467 |
| |
468 |
| } |
469 |
| |
470 |
| |
471 |
1
| public void testIntermediateNodeCreationOnRemove() throws Exception
|
472 |
| { |
473 |
1
| cache.put("/a", null);
|
474 |
1
| tx.begin();
|
475 |
1
| cache.remove("/a/b/c");
|
476 |
| |
477 |
| |
478 |
| |
479 |
1
| GlobalTransaction gtx = cache.getCurrentTransaction();
|
480 |
1
| assertLocked(gtx, "/", false);
|
481 |
1
| assertLocked(gtx, "/a", false);
|
482 |
1
| assertNull("/a/b should not exist", cache.peek(Fqn.fromString("/a/b"), true));
|
483 |
1
| assertNull("/a/b/c should not exist", cache.peek(Fqn.fromString("/a/b/c"), true));
|
484 |
1
| tx.rollback();
|
485 |
1
| assertNull("/a/b should not exist", cache.peek(Fqn.fromString("/a/b"), true));
|
486 |
1
| assertNull("/a/b/c should not exist", cache.peek(Fqn.fromString("/a/b/c"), true));
|
487 |
| |
488 |
| } |
489 |
| |
490 |
| |
491 |
1
| public void testNodeDeletionRollback3() throws Exception
|
492 |
| { |
493 |
1
| GlobalTransaction gtx;
|
494 |
1
| cache.put("/a/b/c1", null);
|
495 |
| |
496 |
1
| tx.begin();
|
497 |
1
| gtx = cache.getCurrentTransaction();
|
498 |
1
| cache.put("/a/b/c1", null);
|
499 |
1
| assertLocked(gtx, "/a", false);
|
500 |
1
| assertLocked(gtx, "/a/b", false);
|
501 |
1
| assertLocked(gtx, "/a/b/c1", true);
|
502 |
| |
503 |
1
| cache.put("/a/b/c2", null);
|
504 |
1
| assertLocked(gtx, "/a/b", true);
|
505 |
1
| assertLocked(gtx, "/a/b/c2", true);
|
506 |
| |
507 |
1
| cache.put("/a/b/c3", null);
|
508 |
1
| cache.put("/a/b/c1/one", null);
|
509 |
1
| assertLocked(gtx, "/a/b/c1", true);
|
510 |
1
| assertLocked(gtx, "/a/b/c1/one", true);
|
511 |
| |
512 |
1
| cache.put("/a/b/c1/two", null);
|
513 |
1
| cache.put("/a/b/c1/one/1", null);
|
514 |
1
| assertLocked(gtx, "/a/b/c1", true);
|
515 |
1
| assertLocked(gtx, "/a/b/c1/one", true);
|
516 |
1
| assertLocked(gtx, "/a/b/c1/one/1", true);
|
517 |
| |
518 |
1
| cache.put("/a/b/c1/two/2/3/4", null);
|
519 |
1
| assertLocked(gtx, "/a/b/c1", true);
|
520 |
1
| assertLocked(gtx, "/a/b/c1/two", true);
|
521 |
1
| assertLocked(gtx, "/a/b/c1/two/2", true);
|
522 |
1
| assertLocked(gtx, "/a/b/c1/two/2/3", true);
|
523 |
1
| assertLocked(gtx, "/a/b/c1/two/2/3/4", true);
|
524 |
| |
525 |
1
| System.out.println("locks: " + cache.printLockInfo());
|
526 |
| |
527 |
1
| cache.remove("/a/b");
|
528 |
1
| tx.rollback();
|
529 |
1
| assertTrue(cache.getChildrenNames("/a/b/c1").isEmpty());
|
530 |
1
| Set cn = cache.getChildrenNames("/a/b");
|
531 |
1
| assertEquals(1, cn.size());
|
532 |
1
| assertEquals("c1", cn.iterator().next());
|
533 |
| } |
534 |
| |
535 |
1
| public void testDoubleLocks() throws Exception
|
536 |
| { |
537 |
1
| tx.begin();
|
538 |
1
| GlobalTransaction gtx = cache.getCurrentTransaction();
|
539 |
1
| cache.put("/a/b/c", null);
|
540 |
1
| cache.put("/a/b/c", null);
|
541 |
| |
542 |
1
| NodeSPI n = (NodeSPI) cache.get("/a");
|
543 |
1
| NodeLock lock = n.getLock();
|
544 |
1
| int num = lock.getReaderOwners().size();
|
545 |
1
| assertEquals(0, num);
|
546 |
| |
547 |
1
| assertLocked(gtx, "/a", true);
|
548 |
| |
549 |
1
| n = (NodeSPI) cache.get("/a/b");
|
550 |
1
| lock = n.getLock();
|
551 |
1
| num = lock.getReaderOwners().size();
|
552 |
1
| assertEquals(0, num);
|
553 |
| |
554 |
1
| assertLocked(gtx, "/a/b", true);
|
555 |
| |
556 |
1
| n = (NodeSPI) cache.get("/a/b/c");
|
557 |
1
| lock = n.getLock();
|
558 |
1
| num = lock.getReaderOwners().size();
|
559 |
1
| assertEquals(0, num);
|
560 |
| |
561 |
1
| assertLocked(gtx, "/a/b/c", true);
|
562 |
| |
563 |
1
| tx.rollback();
|
564 |
1
| assertEquals(0, cache.getNumberOfLocksHeld());
|
565 |
| } |
566 |
| |
567 |
37
| private void assertLocked(Object owner, String fqn, boolean write_locked) throws Exception
|
568 |
| { |
569 |
37
| NodeSPI n = cache.peek(Fqn.fromString(fqn), true);
|
570 |
37
| NodeLock lock = n.getLock();
|
571 |
37
| if (owner == null)
|
572 |
| { |
573 |
0
| owner = Thread.currentThread();
|
574 |
| } |
575 |
37
| assertTrue("node " + fqn + " is not locked", lock.isLocked());
|
576 |
37
| if (write_locked)
|
577 |
| { |
578 |
29
| assertTrue("node " + fqn + " is not write-locked" + (lock.isReadLocked() ? " but is read-locked instead!" : "!"), lock.isWriteLocked());
|
579 |
| } |
580 |
| else |
581 |
| { |
582 |
8
| assertTrue("node " + fqn + " is not read-locked" + (lock.isWriteLocked() ? " but is write-locked instead!" : "!"), lock.isReadLocked());
|
583 |
| } |
584 |
37
| assertTrue("owner " + owner + "is not owner", lock.isOwner(owner));
|
585 |
| } |
586 |
| |
587 |
1
| public void testConcurrentNodeAccessOnRemovalWithTx() throws Exception
|
588 |
| { |
589 |
1
| cache.put("/a/b/c", null);
|
590 |
1
| tx.begin();
|
591 |
1
| cache.remove("/a/b/c");
|
592 |
| |
593 |
1
| Transaction t = cache.getTransactionManager().suspend();
|
594 |
1
| Transaction t2 = null;
|
595 |
1
| try
|
596 |
| { |
597 |
1
| System.out.println(cache.printLockInfo());
|
598 |
| |
599 |
1
| cache.getTransactionManager().begin();
|
600 |
1
| t2 = cache.getTransactionManager().getTransaction();
|
601 |
1
| cache.get("/a/b/c");
|
602 |
0
| t2.commit();
|
603 |
0
| fail("Should not be able to get a hold of /a/b/c until the deleting tx completes");
|
604 |
| } |
605 |
| catch (Exception e) |
606 |
| { |
607 |
| |
608 |
1
| t2.commit();
|
609 |
| } |
610 |
| |
611 |
1
| cache.getTransactionManager().resume(t);
|
612 |
1
| tx.rollback();
|
613 |
| |
614 |
1
| assertNotNull(cache.get("/a/b/c"));
|
615 |
1
| assertEquals(0, cache.getNumberOfLocksHeld());
|
616 |
| } |
617 |
| |
618 |
1
| public void testConcurrentNodeAccessOnRemovalWithoutTx() throws Exception
|
619 |
| { |
620 |
1
| cache.put("/a/b/c", null);
|
621 |
1
| tx.begin();
|
622 |
1
| cache.remove("/a/b/c");
|
623 |
| |
624 |
1
| Transaction t = cache.getTransactionManager().suspend();
|
625 |
1
| Thread th = new Thread()
|
626 |
| { |
627 |
1
| public void run()
|
628 |
| { |
629 |
1
| try
|
630 |
| { |
631 |
1
| System.out.println(cache.printLockInfo());
|
632 |
1
| cache.get("/a/b/c");
|
633 |
| |
634 |
0
| fail("Should not be able to get a hold of /a/b/c until the deleting tx completes");
|
635 |
| } |
636 |
| catch (Exception e) |
637 |
| { |
638 |
| |
639 |
| } |
640 |
| } |
641 |
| }; |
642 |
| |
643 |
1
| th.start();
|
644 |
1
| th.join();
|
645 |
| |
646 |
1
| cache.getTransactionManager().resume(t);
|
647 |
1
| tx.rollback();
|
648 |
| |
649 |
1
| assertNotNull(cache.get("/a/b/c"));
|
650 |
1
| assertEquals(0, cache.getNumberOfLocksHeld());
|
651 |
| } |
652 |
| |
653 |
| |
654 |
1
| public void testRemove() throws CacheException, SystemException, NotSupportedException, HeuristicMixedException, HeuristicRollbackException, RollbackException
|
655 |
| { |
656 |
1
| cache.put("/a/b/c", null);
|
657 |
1
| cache.put("/a/b/c/1", null);
|
658 |
1
| cache.put("/a/b/c/2", null);
|
659 |
1
| cache.put("/a/b/c/3", null);
|
660 |
1
| cache.put("/a/b/c/3/a/b/c", null);
|
661 |
| |
662 |
1
| assertEquals(0, cache.getNumberOfLocksHeld());
|
663 |
1
| assertEquals(0, cache.getLockTable().size());
|
664 |
| |
665 |
1
| tx.begin();
|
666 |
1
| cache.remove("/a/b/c");
|
667 |
1
| System.out.println("locks held (after removing /a/b/c): \n" + cache.printLockInfo());
|
668 |
| |
669 |
| |
670 |
1
| assertEquals(10, cache.getNumberOfLocksHeld());
|
671 |
1
| tx.commit();
|
672 |
1
| System.out.println("locks held (after committing /a/b/c): \n" + cache.printLockInfo());
|
673 |
1
| assertEquals(0, cache.getNumberOfLocksHeld());
|
674 |
| } |
675 |
| |
676 |
| |
677 |
1
| public void testRemoveAndRollback() throws CacheException, SystemException, NotSupportedException, HeuristicMixedException, HeuristicRollbackException, RollbackException
|
678 |
| { |
679 |
1
| cache.put("/a/b/c", null);
|
680 |
1
| cache.put("/a/b/c/1", null);
|
681 |
1
| cache.put("/a/b/c/2", null);
|
682 |
1
| cache.put("/a/b/c/3", null);
|
683 |
1
| cache.put("/a/b/c/3/a/b/c", null);
|
684 |
| |
685 |
1
| assertEquals(0, cache.getNumberOfLocksHeld());
|
686 |
1
| assertEquals(0, cache.getLockTable().size());
|
687 |
| |
688 |
1
| tx.begin();
|
689 |
1
| System.out.println("locks held (before removing /a/b/c): \n" + cache.printLockInfo());
|
690 |
1
| cache.remove("/a/b/c");
|
691 |
1
| System.out.println("locks held (after removing /a/b/c): \n" + cache.printLockInfo());
|
692 |
1
| assertEquals(10, cache.getNumberOfLocksHeld());
|
693 |
1
| tx.rollback();
|
694 |
1
| System.out.println("locks held (after rollback): \n" + cache.printLockInfo());
|
695 |
1
| assertEquals(0, cache.getNumberOfLocksHeld());
|
696 |
| |
697 |
1
| assertTrue(cache.exists("/a/b/c"));
|
698 |
1
| assertTrue(cache.exists("/a/b/c/1"));
|
699 |
1
| assertTrue(cache.exists("/a/b/c/2"));
|
700 |
1
| assertTrue(cache.exists("/a/b/c/3"));
|
701 |
1
| assertTrue(cache.exists("/a/b/c/3/a"));
|
702 |
1
| assertTrue(cache.exists("/a/b/c/3/a/b"));
|
703 |
1
| assertTrue(cache.exists("/a/b/c/3/a/b/c"));
|
704 |
| } |
705 |
| |
706 |
| |
707 |
1
| public void testRemoveKeyRollback() throws CacheException, SystemException, NotSupportedException
|
708 |
| { |
709 |
1
| cache.put("/bela/ban", "name", "Bela");
|
710 |
1
| tx.begin();
|
711 |
1
| cache.remove("/bela/ban", "name");
|
712 |
1
| assertNull(cache.get("/bela/ban", "name"));
|
713 |
1
| tx.rollback();
|
714 |
1
| assertEquals("Bela", cache.get("/bela/ban", "name"));
|
715 |
| } |
716 |
| |
717 |
| |
718 |
1
| public void testRemoveKeyRollback2()
|
719 |
| { |
720 |
1
| try
|
721 |
| { |
722 |
1
| Map m = new HashMap();
|
723 |
1
| m.put("name", "Bela");
|
724 |
1
| m.put("id", 322649);
|
725 |
1
| cache.put("/bela/ban", m);
|
726 |
1
| tx.begin();
|
727 |
1
| cache.remove("/bela/ban", "name");
|
728 |
1
| assertNull(cache.get("/bela/ban", "name"));
|
729 |
1
| tx.rollback();
|
730 |
1
| assertEquals("Bela", cache.get("/bela/ban", "name"));
|
731 |
| } |
732 |
| catch (Throwable t) |
733 |
| { |
734 |
0
| t.printStackTrace();
|
735 |
0
| fail(t.toString());
|
736 |
| } |
737 |
| } |
738 |
| |
739 |
1
| public void testRemoveKeyRollback3()
|
740 |
| { |
741 |
1
| try
|
742 |
| { |
743 |
1
| cache.put("/bela/ban", "name", "Bela");
|
744 |
1
| tx.begin();
|
745 |
1
| cache.put("/bela/ban", "name", "Michelle");
|
746 |
1
| cache.remove("/bela/ban", "name");
|
747 |
1
| assertNull(cache.get("/bela/ban", "name"));
|
748 |
1
| tx.rollback();
|
749 |
1
| assertEquals("Bela", cache.get("/bela/ban", "name"));
|
750 |
| } |
751 |
| catch (Throwable t) |
752 |
| { |
753 |
0
| t.printStackTrace();
|
754 |
0
| fail(t.toString());
|
755 |
| } |
756 |
| } |
757 |
| |
758 |
| |
759 |
1
| public void testDoubleRemovalOfSameData()
|
760 |
| { |
761 |
1
| try
|
762 |
| { |
763 |
1
| tx.begin();
|
764 |
1
| cache.put("/foo/1", "item", 1);
|
765 |
1
| assertEquals(cache.get("/foo/1", "item"), 1);
|
766 |
1
| cache.remove("/foo/1");
|
767 |
1
| assertNull(cache.get("/foo/1", "item"));
|
768 |
1
| cache.remove("/foo/1");
|
769 |
1
| assertNull(cache.get("/foo/1", "item"));
|
770 |
1
| tx.rollback();
|
771 |
1
| assertFalse(cache.exists("/foo/1"));
|
772 |
1
| assertNull(cache.get("/foo/1", "item"));
|
773 |
| } |
774 |
| catch (Throwable t) |
775 |
| { |
776 |
0
| t.printStackTrace();
|
777 |
0
| fail(t.toString());
|
778 |
| } |
779 |
| } |
780 |
| |
781 |
| |
782 |
| |
783 |
| |
784 |
1
| public void testPutDataRollback1()
|
785 |
| { |
786 |
1
| try
|
787 |
| { |
788 |
1
| cache.put("/bela/ban", null);
|
789 |
1
| tx.begin();
|
790 |
1
| Map m = new HashMap();
|
791 |
1
| m.put("name", "Bela");
|
792 |
1
| m.put("id", 322649);
|
793 |
1
| cache.put("/bela/ban", m);
|
794 |
1
| tx.rollback();
|
795 |
| |
796 |
1
| Node n = cache.get("/bela/ban");
|
797 |
0
| if (n.getData() == null) return;
|
798 |
1
| assertEquals("map should be empty", 0, n.getData().size());
|
799 |
| } |
800 |
| catch (Throwable t) |
801 |
| { |
802 |
0
| t.printStackTrace();
|
803 |
0
| fail(t.toString());
|
804 |
| } |
805 |
| } |
806 |
| |
807 |
| |
808 |
| |
809 |
| |
810 |
1
| public void testputDataRollback2()
|
811 |
| { |
812 |
1
| Map m1, m2;
|
813 |
1
| m1 = new HashMap();
|
814 |
1
| m1.put("name", "Bela");
|
815 |
1
| m1.put("id", 322649);
|
816 |
1
| m2 = new HashMap();
|
817 |
1
| m2.put("other", "bla");
|
818 |
1
| m2.put("name", "Michelle");
|
819 |
| |
820 |
1
| try
|
821 |
| { |
822 |
1
| cache.put("/bela/ban", m1);
|
823 |
1
| tx.begin();
|
824 |
| |
825 |
1
| cache.put("/bela/ban", m2);
|
826 |
1
| Map tmp = cache.get("/bela/ban").getData();
|
827 |
1
| assertEquals(3, tmp.size());
|
828 |
1
| assertEquals("Michelle", tmp.get("name"));
|
829 |
1
| assertEquals(tmp.get("id"), 322649);
|
830 |
1
| assertEquals("bla", tmp.get("other"));
|
831 |
1
| tx.rollback();
|
832 |
| |
833 |
1
| tmp = cache.get("/bela/ban").getData();
|
834 |
1
| assertEquals(2, tmp.size());
|
835 |
1
| assertEquals("Bela", tmp.get("name"));
|
836 |
1
| assertEquals(tmp.get("id"), 322649);
|
837 |
| } |
838 |
| catch (Throwable t) |
839 |
| { |
840 |
0
| t.printStackTrace();
|
841 |
0
| fail(t.toString());
|
842 |
| } |
843 |
| } |
844 |
| |
845 |
| |
846 |
1
| public void testPutRollback()
|
847 |
| { |
848 |
1
| try
|
849 |
| { |
850 |
1
| cache.put("/bela/ban", null);
|
851 |
1
| tx.begin();
|
852 |
1
| cache.put("/bela/ban", "name", "Bela");
|
853 |
1
| assertEquals("Bela", cache.get("/bela/ban", "name"));
|
854 |
1
| tx.rollback();
|
855 |
1
| assertNull(cache.get("/bela/ban", "name"));
|
856 |
| } |
857 |
| catch (Throwable t) |
858 |
| { |
859 |
0
| t.printStackTrace();
|
860 |
0
| fail(t.toString());
|
861 |
| } |
862 |
| } |
863 |
| |
864 |
| |
865 |
1
| public void testPutRollback2()
|
866 |
| { |
867 |
1
| try
|
868 |
| { |
869 |
1
| cache.put("/bela/ban", "name", "Bela");
|
870 |
1
| tx.begin();
|
871 |
1
| cache.put("/bela/ban", "name", "Michelle");
|
872 |
1
| assertEquals("Michelle", cache.get("/bela/ban", "name"));
|
873 |
1
| tx.rollback();
|
874 |
1
| assertEquals("Bela", cache.get("/bela/ban", "name"));
|
875 |
| } |
876 |
| catch (Throwable t) |
877 |
| { |
878 |
0
| t.printStackTrace();
|
879 |
0
| fail(t.toString());
|
880 |
| } |
881 |
| } |
882 |
| |
883 |
| |
884 |
1
| public void testSimpleRollbackTransactions() throws Exception
|
885 |
| { |
886 |
1
| final Fqn FQN = Fqn.fromString("/a/b/c");
|
887 |
1
| tx.begin();
|
888 |
1
| cache.put(FQN, "entry", "commit");
|
889 |
1
| tx.commit();
|
890 |
| |
891 |
1
| tx.begin();
|
892 |
1
| cache.put(FQN, "entry", "rollback");
|
893 |
1
| cache.remove(FQN);
|
894 |
1
| tx.rollback();
|
895 |
1
| assertEquals("Node should keep the commited value", "commit", cache.get(FQN).get("entry"));
|
896 |
| |
897 |
1
| tx.begin();
|
898 |
1
| cache.remove(FQN);
|
899 |
1
| cache.put(FQN, "entry", "rollback");
|
900 |
1
| tx.rollback();
|
901 |
1
| assertEquals("Node should keep the commited value", "commit", cache.get(FQN).get("entry"));
|
902 |
| } |
903 |
| |
904 |
| |
905 |
2
| private Transaction startTransaction() throws Exception
|
906 |
| { |
907 |
2
| DummyTransactionManager mgr = DummyTransactionManager.getInstance();
|
908 |
2
| mgr.begin();
|
909 |
2
| return mgr.getTransaction();
|
910 |
| } |
911 |
| |
912 |
| |
913 |
1
| public void testConcurrentReadAndWriteAccess() throws Exception
|
914 |
| { |
915 |
1
| cache.stop();
|
916 |
1
| cache.getConfiguration().setIsolationLevel(IsolationLevel.REPEATABLE_READ);
|
917 |
1
| cache.start();
|
918 |
| |
919 |
1
| cache.put("/1/2/3/4", "foo", "bar");
|
920 |
| |
921 |
| |
922 |
| class Reader extends Thread |
923 |
| { |
924 |
| Transaction thread_tx; |
925 |
| |
926 |
1
| public Reader()
|
927 |
| { |
928 |
1
| super("Reader");
|
929 |
| } |
930 |
| |
931 |
1
| public void run()
|
932 |
| { |
933 |
1
| try
|
934 |
| { |
935 |
1
| thread_tx = startTransaction();
|
936 |
1
| log("acquiring RL");
|
937 |
1
| cache.get("/1/2/3", "foo");
|
938 |
1
| log("RL acquired successfully");
|
939 |
1
| sleep(2000);
|
940 |
1
| log("committing TX");
|
941 |
1
| thread_tx.commit();
|
942 |
1
| log("committed TX");
|
943 |
| } |
944 |
| catch (Exception e) |
945 |
| { |
946 |
0
| thread_ex = e;
|
947 |
| } |
948 |
| } |
949 |
| } |
950 |
| |
951 |
| class Writer extends Thread |
952 |
| { |
953 |
| Transaction thread_tx; |
954 |
| |
955 |
1
| public Writer()
|
956 |
| { |
957 |
1
| super("Writer");
|
958 |
| } |
959 |
| |
960 |
1
| public void run()
|
961 |
| { |
962 |
1
| try
|
963 |
| { |
964 |
1
| sleep(500);
|
965 |
1
| thread_tx = startTransaction();
|
966 |
1
| log("acquiring WL");
|
967 |
1
| cache.put("/1", "foo", "bar2");
|
968 |
1
| log("acquired WL successfully");
|
969 |
1
| log("committing TX");
|
970 |
1
| thread_tx.commit();
|
971 |
1
| log("committed TX");
|
972 |
| } |
973 |
| catch (Exception e) |
974 |
| { |
975 |
0
| thread_ex = e;
|
976 |
| } |
977 |
| } |
978 |
| } |
979 |
| |
980 |
1
| Reader reader = new Reader();
|
981 |
1
| Writer writer = new Writer();
|
982 |
1
| reader.start();
|
983 |
1
| writer.start();
|
984 |
1
| reader.join();
|
985 |
1
| writer.join();
|
986 |
1
| if (thread_ex != null)
|
987 |
| { |
988 |
0
| throw thread_ex;
|
989 |
| } |
990 |
| } |
991 |
| |
992 |
| |
993 |
| |
994 |
| |
995 |
| |
996 |
| |
997 |
| |
998 |
| |
999 |
| |
1000 |
| |
1001 |
| |
1002 |
| |
1003 |
| |
1004 |
| |
1005 |
| |
1006 |
| |
1007 |
| |
1008 |
| |
1009 |
| |
1010 |
| |
1011 |
| |
1012 |
| |
1013 |
| |
1014 |
| |
1015 |
| |
1016 |
| |
1017 |
| |
1018 |
| |
1019 |
| |
1020 |
| |
1021 |
| |
1022 |
| |
1023 |
| |
1024 |
| |
1025 |
| |
1026 |
| |
1027 |
| |
1028 |
| |
1029 |
| |
1030 |
| |
1031 |
| |
1032 |
| |
1033 |
| |
1034 |
| |
1035 |
| |
1036 |
8
| private static void log(String msg)
|
1037 |
| { |
1038 |
8
| System.out.println(Thread.currentThread().getName() + ": " + msg);
|
1039 |
| } |
1040 |
| |
1041 |
| |
1042 |
| |
1043 |
| |
1044 |
| |
1045 |
| |
1046 |
| |
1047 |
| |
1048 |
| |
1049 |
| |
1050 |
| |
1051 |
| |
1052 |
| |
1053 |
| |
1054 |
| |
1055 |
| |
1056 |
| |
1057 |
| |
1058 |
| |
1059 |
| |
1060 |
| |
1061 |
| |
1062 |
| |
1063 |
| |
1064 |
| |
1065 |
| |
1066 |
| |
1067 |
| |
1068 |
| |
1069 |
| |
1070 |
| |
1071 |
| |
1072 |
| |
1073 |
| |
1074 |
| |
1075 |
| |
1076 |
| |
1077 |
| |
1078 |
| |
1079 |
| |
1080 |
| |
1081 |
| |
1082 |
| |
1083 |
| |
1084 |
| |
1085 |
| |
1086 |
| |
1087 |
| |
1088 |
| |
1089 |
| |
1090 |
| |
1091 |
| |
1092 |
| |
1093 |
| |
1094 |
| |
1095 |
| |
1096 |
| |
1097 |
| |
1098 |
| |
1099 |
| |
1100 |
| |
1101 |
| |
1102 |
| |
1103 |
| |
1104 |
| |
1105 |
| |
1106 |
| |
1107 |
| |
1108 |
| |
1109 |
| |
1110 |
| |
1111 |
| |
1112 |
| |
1113 |
| |
1114 |
| |
1115 |
| |
1116 |
| |
1117 |
| |
1118 |
| |
1119 |
| |
1120 |
| |
1121 |
| |
1122 |
| |
1123 |
| |
1124 |
| |
1125 |
| |
1126 |
| |
1127 |
| |
1128 |
| |
1129 |
| |
1130 |
| |
1131 |
| |
1132 |
| |
1133 |
| |
1134 |
| |
1135 |
| |
1136 |
| |
1137 |
| |
1138 |
| |
1139 |
| |
1140 |
| |
1141 |
| |
1142 |
| |
1143 |
| |
1144 |
| |
1145 |
| |
1146 |
| |
1147 |
| |
1148 |
| |
1149 |
| |
1150 |
| |
1151 |
| |
1152 |
| |
1153 |
| |
1154 |
| |
1155 |
| |
1156 |
| |
1157 |
| |
1158 |
| |
1159 |
| |
1160 |
| |
1161 |
| |
1162 |
| |
1163 |
1
| public static Test suite() throws Exception
|
1164 |
| { |
1165 |
1
| return new TestSuite(TransactionTest.class);
|
1166 |
| } |
1167 |
| |
1168 |
0
| public static void main(String[] args) throws Exception
|
1169 |
| { |
1170 |
0
| junit.textui.TestRunner.run(suite());
|
1171 |
| } |
1172 |
| |
1173 |
| |
1174 |
| } |