1 8 9 package org.jboss.cache.tests.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.GlobalTransaction; 16 import org.jboss.cache.Node; 17 import org.jboss.cache.TreeCache; 18 import org.jboss.cache.lock.IdentityLock; 19 import org.jboss.cache.lock.IsolationLevel; 20 import org.jboss.cache.transaction.DummyTransactionManager; 21 22 import javax.naming.Context ; 23 import javax.naming.InitialContext ; 24 import javax.transaction.*; 25 import java.util.HashMap ; 26 import java.util.Map ; 27 import java.util.Properties ; 28 import java.util.Set ; 29 30 36 public class TransactionTest extends TestCase { 37 TreeCache cache=null; 38 UserTransaction tx=null; 39 Properties p=null; 40 String old_factory=null; 41 final String FACTORY="org.jboss.cache.transaction.DummyContextFactory"; 42 Exception thread_ex; 43 44 45 public TransactionTest(String name) { 46 super(name); 47 } 48 49 public void setUp() throws Exception { 50 super.setUp(); 51 old_factory=System.getProperty(Context.INITIAL_CONTEXT_FACTORY); 52 System.setProperty(Context.INITIAL_CONTEXT_FACTORY, FACTORY); 53 DummyTransactionManager.getInstance(); 54 if(p == null) { 55 p=new Properties (); 56 p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.cache.transaction.DummyContextFactory"); 57 } 58 59 tx=(UserTransaction)new InitialContext (p).lookup("UserTransaction"); 60 cache=new TreeCache("test", null, 10000); 61 cache.setTransactionManagerLookupClass("org.jboss.cache.DummyTransactionManagerLookup"); 62 cache.setIsolationLevel(IsolationLevel.SERIALIZABLE); 63 cache.createService(); 64 cache.startService(); 65 thread_ex=null; 66 } 67 68 public void tearDown() throws Exception { 69 super.tearDown(); 70 if(cache != null) 71 cache.stopService(); 72 73 DummyTransactionManager.destroy(); 75 if(old_factory != null) { 76 System.setProperty(Context.INITIAL_CONTEXT_FACTORY, old_factory); 77 old_factory=null; 78 } 79 80 if(tx != null) { 81 try { 82 tx.rollback(); 83 } 84 catch(Throwable t) { 85 } 86 tx=null; 87 } 88 } 89 90 91 public void testPutTx() { 92 try { 93 tx.begin(); 94 cache.put("/a/b/c", "age", new Integer (38)); 95 assertEquals(new Integer (38), cache.get("/a/b/c", "age")); 96 97 cache.put("/a/b/c", "age", new Integer (39)); 98 tx.commit(); 99 100 assertEquals(new Integer (39), cache.get("/a/b/c", "age")); 103 } 104 catch(Throwable t) { 105 t.printStackTrace(); 106 fail(t.toString()); 107 } 108 } 109 110 111 public void testRollbackTx1() { 112 try { 113 tx.begin(); 114 cache.put("/a/b/c", "age", new Integer (38)); 115 cache.put("/a/b/c", "age", new Integer (39)); 116 tx.rollback(); 117 118 assertNull(cache.get("/a/b/c", "age")); 121 } 122 catch(Throwable t) { 123 t.printStackTrace(); 124 fail(t.toString()); 125 } 126 } 127 128 129 public void testRollbackTx2() { 130 try { 131 tx.begin(); 132 cache.put("/a/b/c", "age", new Integer (38)); 133 cache.remove("/a/b/c", "age"); 134 tx.rollback(); 135 136 assertNull(cache.get("/a/b/c", "age")); 139 } 140 catch(Throwable t) { 141 t.printStackTrace(); 142 fail(t.toString()); 143 } 144 } 145 146 public void testRollbackTx2a() { 147 try { 148 cache.put("/a/b/c", "age", new Integer (38)); 149 tx.begin(); 150 cache.remove("/a/b/c", "age"); 151 tx.rollback(); 152 153 assertEquals(new Integer (38), cache.get("/a/b/c", "age")); 156 } 157 catch(Throwable t) { 158 t.printStackTrace(); 159 fail(t.toString()); 160 } 161 } 162 163 public void testRollbackTx3() { 164 try { 165 java.util.Map map1=new java.util.HashMap (); 166 map1.put("age", new Integer (38)); 167 java.util.Map map2=new java.util.HashMap (); 168 map2.put("age", new Integer (39)); 169 tx.begin(); 170 cache.put("/a/b/c", map1); 171 cache.put("/a/b/c", map2); 172 tx.rollback(); 173 174 assertNull(cache.get("/a/b/c", "age")); 177 } 178 catch(Throwable t) { 179 t.printStackTrace(); 180 fail(t.toString()); 181 } 182 } 183 184 185 public void testRollbackTx4() { 186 try { 187 Map map=new HashMap (); 188 map.put("age", new Integer (38)); 189 tx.begin(); 190 cache.put("/a/b/c", map); 191 cache.remove("/a/b/c"); 192 tx.rollback(); 193 194 assertNull(cache.get("/a/b/c", "age")); 197 } 198 catch(Throwable t) { 199 t.printStackTrace(); 200 fail(t.toString()); 201 } 202 } 203 204 public void testNodeCreationRollback() { 205 try { 206 tx.begin(); 207 System.out.println("initial state:\n" + cache); 208 cache.put("/bela/ban", null); 209 System.out.println("after put():\n" + cache); 210 tx.rollback(); 211 System.out.println("after rollback():\n" + cache); 212 213 assertNull("node should be not existent", cache.get("/bela/ban")); 214 } 215 catch(Throwable t) { 216 t.printStackTrace(); 217 fail(t.toString()); 218 } 219 } 220 221 public void testNodeCreationRollback2() { 222 try { 223 cache.put("/bela/ban", null); 224 tx.begin(); 225 cache.put("/bela/ban/michelle", null); 226 tx.rollback(); 227 assertNotNull("node should be not null", cache.get("/bela/ban")); 228 assertNull("node should be not existent", cache.get("/bela/ban/michelle")); 229 } 230 catch(Throwable t) { 231 t.printStackTrace(); 232 fail(t.toString()); 233 } 234 } 235 236 public void testNodeDeletionRollback() { 237 try { 238 cache.put("/a/b/c", null); 239 tx.begin(); 240 cache.remove("/a/b/c"); 241 assertNull(cache.get("/a/b/c")); 242 cache.remove("/a/b"); 243 assertNull(cache.get("/a/b")); 244 cache.remove("/a"); 245 assertNull(cache.get("/a")); 246 tx.rollback(); 247 assertNotNull(cache.get("/a/b/c")); 248 assertNotNull(cache.get("/a/b")); 249 assertNotNull(cache.get("/a")); 250 } 251 catch(Throwable t) { 252 t.printStackTrace(); 253 fail(t.toString()); 254 } 255 } 256 257 public void testNodeDeletionRollback2() { 258 try { 259 cache.put("/a/b/c", null); 260 cache.put("/a/b/c1", null); 261 cache.put("/a/b/c2", null); 262 tx.begin(); 263 cache.remove("/a"); 264 assertNull(cache.get("/a/b/c")); 265 assertNull(cache.get("/a/b/c1")); 266 assertNull(cache.get("/a/b/c2")); 267 assertNull(cache.get("/a/b")); 268 assertNull(cache.get("/a")); 269 Set children=cache.getChildrenNames("/a/b"); 270 assertNull(children); 271 children=cache.getChildrenNames("/a"); 272 assertNull(children); 273 tx.rollback(); 274 assertNotNull(cache.get("/a")); 275 assertNotNull(cache.get("/a/b")); 276 assertNotNull(cache.get("/a/b/c")); 277 assertNotNull(cache.get("/a/b/c1")); 278 assertNotNull(cache.get("/a/b/c2")); 279 children=cache.getChildrenNames("/a/b"); 280 assertTrue(children.size() == 3); 281 } 282 catch(Throwable t) { 283 t.printStackTrace(); 284 fail(t.toString()); 285 } 286 } 287 288 289 290 public void testNodeDeletionRollback3() { 291 GlobalTransaction gtx; 292 try { 293 tx.begin(); 294 gtx=cache.getCurrentTransaction(); 295 cache.put("/a/b/c1", null); 296 checkLock(gtx, "/a", false); 297 checkLock(gtx, "/a/b", false); 298 checkLock(gtx, "/a/b/c1", true); 299 300 cache.put("/a/b/c2", null); 301 checkLock(gtx, "/a/b/c2", true); 302 303 cache.put("/a/b/c3", null); 304 cache.put("/a/b/c1/one", null); 305 checkLock(gtx, "/a/b/c1", true); 306 checkLock(gtx, "/a/b/c1/one", true); 307 308 cache.put("/a/b/c1/two", null); 309 cache.put("/a/b/c1/one/1", null); 310 checkLock(gtx, "/a/b/c1", true); 311 checkLock(gtx, "/a/b/c1/one", true); 312 checkLock(gtx, "/a/b/c1/one/1", true); 313 314 cache.put("/a/b/c1/two/2/3/4", null); 315 checkLock(gtx, "/a/b/c1", true); 316 checkLock(gtx, "/a/b/c1/two", true); 317 checkLock(gtx, "/a/b/c1/two/2", false); 318 checkLock(gtx, "/a/b/c1/two/2/3", false); 319 checkLock(gtx, "/a/b/c1/two/2/3/4", true); 320 321 System.out.println("locks: " + cache.printLockInfo()); 322 323 cache.remove("/a/b"); 324 tx.rollback(); 325 assertNull(cache.getChildrenNames("/a/b")); 326 } 327 catch(Throwable t) { 328 t.printStackTrace(); 329 fail(t.toString()); 330 } 331 } 332 333 public void testDoubleLocks() { 334 try { 335 tx.begin(); 336 cache.put("/a/b/c", null); 337 cache.put("/a/b/c", null); 338 339 Node n=cache.get("/a"); 340 IdentityLock lock=n.getLock(); 341 int num=lock.getReaderOwners().size(); 342 assertTrue(num == 1); 343 344 n=cache.get("/a/b"); 345 lock=n.getLock(); 346 num=lock.getReaderOwners().size(); 347 assertTrue(num == 1); 348 } 349 catch(Throwable t) { 350 t.printStackTrace(); 351 fail(t.toString()); 352 } 353 } 354 355 private void checkLock(Object owner, String fqn, boolean write_locked) throws Exception { 356 Node n=cache.get(fqn); 357 IdentityLock lock=n.getLock(); 358 if(owner == null) 359 owner=Thread.currentThread(); 360 if(lock.isLocked() == false) 361 throw new Exception ("node " + fqn + " is not locked"); 362 if(write_locked) { 363 if(lock.isWriteLocked() == false) 364 throw new Exception ("node " + fqn + " is not write-locked"); 365 } 366 else { 367 if(lock.isReadLocked() == false) 368 throw new Exception ("node " + fqn + " is not read-locked"); 369 } 370 if(lock.isOwner(owner) == false) 371 throw new Exception ("owner " + owner + "is not owner"); 372 } 373 374 375 public void testRemove() throws CacheException, SystemException, NotSupportedException, HeuristicMixedException, HeuristicRollbackException, RollbackException { 376 cache.put("/a/b/c", null); 377 cache.put("/a/b/c/1", null); 378 cache.put("/a/b/c/2", null); 379 cache.put("/a/b/c/3", null); 380 cache.put("/a/b/c/3/a/b/c", null); 381 382 assertEquals(0, cache.getNumberOfLocksHeld()); 383 assertEquals(0, cache.getLockTable().size()); 384 385 tx.begin(); 386 cache.remove("/a/b/c"); 387 System.out.println("locks held (after removing /a/b/c): \n" + cache.printLockInfo()); 388 assertEquals(2, cache.getNumberOfLocksHeld()); 389 tx.commit(); 390 System.out.println("locks held (after committing /a/b/c): \n" + cache.printLockInfo()); 391 assertEquals(0, cache.getNumberOfLocksHeld()); 392 } 393 394 395 public void testRemoveAndRollback() throws CacheException, SystemException, NotSupportedException, HeuristicMixedException, HeuristicRollbackException, RollbackException { 396 cache.put("/a/b/c", null); 397 cache.put("/a/b/c/1", null); 398 cache.put("/a/b/c/2", null); 399 cache.put("/a/b/c/3", null); 400 cache.put("/a/b/c/3/a/b/c", null); 401 402 assertEquals(0, cache.getNumberOfLocksHeld()); 403 assertEquals(0, cache.getLockTable().size()); 404 405 tx.begin(); 406 System.out.println("locks held (before removing /a/b/c): \n" + cache.printLockInfo()); 407 cache.remove("/a/b/c"); 408 System.out.println("locks held (after removing /a/b/c): \n" + cache.printLockInfo()); 409 assertEquals(2, cache.getNumberOfLocksHeld()); 410 tx.rollback(); 411 System.out.println("locks held (after rollback): \n" + cache.printLockInfo()); 412 assertEquals(0, cache.getNumberOfLocksHeld()); 413 414 assertTrue(cache.exists("/a/b/c")); 415 assertTrue(cache.exists("/a/b/c/1")); 416 assertTrue(cache.exists("/a/b/c/2")); 417 assertTrue(cache.exists("/a/b/c/3")); 418 assertTrue(cache.exists("/a/b/c/3/a")); 419 assertTrue(cache.exists("/a/b/c/3/a/b")); 420 assertTrue(cache.exists("/a/b/c/3/a/b/c")); 421 } 422 423 424 public void testRemoveKeyRollback() throws CacheException, SystemException, NotSupportedException { 425 cache.put("/bela/ban", "name", "Bela"); 426 tx.begin(); 427 cache.remove("/bela/ban", "name"); 428 assertNull(cache.get("/bela/ban", "name")); 429 tx.rollback(); 430 assertEquals("Bela", cache.get("/bela/ban", "name")); 431 } 432 433 434 public void testRemoveKeyRollback2() { 435 try { 436 Map m=new HashMap (); 437 m.put("name", "Bela"); 438 m.put("id", new Integer (322649)); 439 cache.put("/bela/ban", m); 440 tx.begin(); 441 cache.remove("/bela/ban", "name"); 442 assertNull(cache.get("/bela/ban", "name")); 443 tx.rollback(); 444 assertEquals("Bela", cache.get("/bela/ban", "name")); 445 } 446 catch(Throwable t) { 447 t.printStackTrace(); 448 fail(t.toString()); 449 } 450 } 451 452 public void testRemoveKeyRollback3() { 453 try { 454 cache.put("/bela/ban", "name", "Bela"); 455 tx.begin(); 456 cache.put("/bela/ban", "name", "Michelle"); 457 cache.remove("/bela/ban", "name"); 458 assertNull(cache.get("/bela/ban", "name")); 459 tx.rollback(); 460 assertEquals("Bela", cache.get("/bela/ban", "name")); 461 } 462 catch(Throwable t) { 463 t.printStackTrace(); 464 fail(t.toString()); 465 } 466 } 467 468 469 470 471 public void testDoubleRemovalOfSameData() { 472 try { 473 tx.begin(); 474 cache.put("/foo/1", "item", new Integer (1)); 475 assertEquals(cache.get("/foo/1", "item"), new Integer (1)); 476 cache.remove("/foo/1"); 477 assertNull(cache.get("/foo/1", "item")); 478 cache.remove("/foo/1"); 479 assertNull(cache.get("/foo/1", "item")); 480 tx.rollback(); 481 assertFalse(cache.exists("/foo/1")); 482 assertNull(cache.get("/foo/1", "item")); 483 } 484 catch(Throwable t) { 485 t.printStackTrace(); 486 fail(t.toString()); 487 } 488 } 489 490 493 public void testPutDataRollback1() { 494 try { 495 cache.put("/bela/ban", null); tx.begin(); 497 Map m=new HashMap (); 498 m.put("name", "Bela"); 499 m.put("id", new Integer (322649)); 500 cache.put("/bela/ban", m); 501 tx.rollback(); 502 503 Node n=cache.get("/bela/ban"); 504 if(n.getData() == null) return; 505 assertEquals("map should be empty", 0, n.getData().size()); 506 } 507 catch(Throwable t) { 508 t.printStackTrace(); 509 fail(t.toString()); 510 } 511 } 512 513 516 public void testputDataRollback2() { 517 Map m1, m2; 518 m1=new HashMap (); 519 m1.put("name", "Bela"); 520 m1.put("id", new Integer (322649)); 521 m2=new HashMap (); 522 m2.put("other", "bla"); 523 m2.put("name", "Michelle"); 524 525 try { 526 cache.put("/bela/ban", m1); 527 tx.begin(); 528 529 cache.put("/bela/ban", m2); 530 Map tmp=cache.get("/bela/ban").getData(); 531 assertTrue(tmp.size() == 3); 532 assertTrue(tmp.get("name").equals("Michelle")); 533 assertTrue(tmp.get("id").equals(new Integer (322649))); 534 assertTrue(tmp.get("other").equals("bla")); 535 tx.rollback(); 536 537 tmp=cache.get("/bela/ban").getData(); 538 assertTrue(tmp.size() == 2); 539 assertTrue(tmp.get("name").equals("Bela")); 540 assertTrue(tmp.get("id").equals(new Integer (322649))); 541 } 542 catch(Throwable t) { 543 t.printStackTrace(); 544 fail(t.toString()); 545 } 546 } 547 548 549 public void testPutRollback() { 550 try { 551 cache.put("/bela/ban", null); tx.begin(); 553 cache.put("/bela/ban", "name", "Bela"); 554 assertEquals("Bela", cache.get("/bela/ban", "name")); 555 tx.rollback(); 556 assertNull(cache.get("/bela/ban", "name")); 557 } 558 catch(Throwable t) { 559 t.printStackTrace(); 560 fail(t.toString()); 561 } 562 } 563 564 565 public void testPutRollback2() { 566 try { 567 cache.put("/bela/ban", "name", "Bela"); tx.begin(); 569 cache.put("/bela/ban", "name", "Michelle"); 570 assertEquals("Michelle", cache.get("/bela/ban", "name")); 571 tx.rollback(); 572 assertEquals("Bela", cache.get("/bela/ban", "name")); 573 } 574 catch(Throwable t) { 575 t.printStackTrace(); 576 fail(t.toString()); 577 } 578 } 579 580 private Transaction startTransaction() throws Exception { 581 DummyTransactionManager mgr=DummyTransactionManager.getInstance(); 582 mgr.begin(); 583 return mgr.getTransaction(); 584 } 585 586 587 public void testConcurrentReadAndWriteAccess() throws Exception { 588 cache.setIsolationLevel(IsolationLevel.REPEATABLE_READ); 589 590 cache.put("/1/2/3/4", "foo", "bar"); 592 593 class Reader extends Thread { 594 Transaction thread_tx; 595 596 public Reader() { 597 super("Reader"); 598 } 599 600 public void run() { 601 try { 602 thread_tx=startTransaction(); 603 log("acquiring RL"); 604 cache.get("/1/2/3", "foo"); log("RL acquired successfully"); 606 sleep(3000); 607 log("committing TX"); 608 thread_tx.commit(); log("committed TX"); 610 } 611 catch(Exception e) { 612 thread_ex=e; 613 } 614 } 615 } 616 617 class Writer extends Thread { 618 Transaction thread_tx; 619 620 public Writer() { 621 super("Writer"); 622 } 623 624 public void run() { 625 try { 626 sleep(1000); thread_tx=startTransaction(); 628 log("acquiring WL"); 629 cache.put("/1", "foo", "bar2"); log("acquired WL successfully"); 631 log("committing TX"); 632 thread_tx.commit(); 633 log("committed TX"); 634 } 635 catch(Exception e) { 636 thread_ex=e; 637 } 638 } 639 } 640 641 Reader reader=new Reader(); 642 Writer writer=new Writer(); 643 reader.start(); 644 writer.start(); 645 reader.join(); 646 writer.join(); 647 if(thread_ex != null) 648 throw thread_ex; 649 } 650 651 652 private static void log(String msg) { 653 System.out.println(Thread.currentThread().getName() + ": " + msg); 654 } 655 656 715 716 762 778 779 public static Test suite() throws Exception { 780 return new TestSuite(TransactionTest.class); 782 } 783 784 public static void main(String [] args) throws Exception { 785 junit.textui.TestRunner.run(suite()); 786 } 787 788 789 } 790 | Popular Tags |