1 8 9 package com.sleepycat.collections.test; 10 11 import java.util.Iterator ; 12 import java.util.List ; 13 import java.util.SortedSet ; 14 15 import junit.framework.Test; 16 import junit.framework.TestCase; 17 import junit.framework.TestSuite; 18 19 import com.sleepycat.collections.CurrentTransaction; 20 import com.sleepycat.collections.StoredCollections; 21 import com.sleepycat.collections.StoredContainer; 22 import com.sleepycat.collections.StoredIterator; 23 import com.sleepycat.collections.StoredList; 24 import com.sleepycat.collections.StoredSortedMap; 25 import com.sleepycat.collections.TransactionRunner; 26 import com.sleepycat.collections.TransactionWorker; 27 import com.sleepycat.compat.DbCompat; 28 import com.sleepycat.je.CursorConfig; 29 import com.sleepycat.je.Database; 30 import com.sleepycat.je.DatabaseConfig; 31 import com.sleepycat.je.DatabaseEntry; 32 import com.sleepycat.je.Environment; 33 import com.sleepycat.je.Transaction; 34 import com.sleepycat.je.TransactionConfig; 35 import com.sleepycat.util.RuntimeExceptionWrapper; 36 37 40 public class TransactionTest extends TestCase { 41 42 private static final Long ONE = new Long (1); 43 private static final Long TWO = new Long (2); 44 private static final Long THREE = new Long (3); 45 46 50 public static void main(String [] args) 51 throws Exception { 52 53 if (args.length == 1 && 54 (args[0].equals("-h") || args[0].equals("-help"))) { 55 usage(); 56 } else { 57 junit.framework.TestResult tr = 58 junit.textui.TestRunner.run(suite()); 59 if (tr.errorCount() > 0 || 60 tr.failureCount() > 0) { 61 System.exit(1); 62 } else { 63 System.exit(0); 64 } 65 } 66 } 67 68 private static void usage() { 69 70 System.out.println( 71 "Usage: java com.sleepycat.collections.test.TransactionTest" 72 + " [-h | -help]\n"); 73 System.exit(2); 74 } 75 76 public static Test suite() 77 throws Exception { 78 79 TestSuite suite = new TestSuite(TransactionTest.class); 80 return suite; 81 } 82 83 private Environment env; 84 private CurrentTransaction currentTxn; 85 private Database store; 86 private StoredSortedMap map; 87 private TestStore testStore = TestStore.BTREE_UNIQ; 88 89 public TransactionTest(String name) { 90 91 super(name); 92 } 93 94 public void setUp() 95 throws Exception { 96 97 DbTestUtil.printTestName(DbTestUtil.qualifiedTestName(this)); 98 env = TestEnv.TXN.open("TransactionTests"); 99 currentTxn = CurrentTransaction.getInstance(env); 100 store = testStore.open(env, dbName(0)); 101 map = new StoredSortedMap(store, testStore.getKeyBinding(), 102 testStore.getValueBinding(), true); 103 } 104 105 public void tearDown() { 106 107 try { 108 if (store != null) { 109 store.close(); 110 } 111 if (env != null) { 112 env.close(); 113 } 114 } catch (Exception e) { 115 System.out.println("Ignored exception during tearDown: " + e); 116 } finally { 117 118 store = null; 119 env = null; 120 currentTxn = null; 121 map = null; 122 testStore = null; 123 } 124 } 125 126 private String dbName(int i) { 127 128 return "txn-test-" + getName() + '-' + i; 129 } 130 131 public void testGetters() 132 throws Exception { 133 134 assertNotNull(env); 135 assertNotNull(currentTxn); 136 assertNull(currentTxn.getTransaction()); 137 138 currentTxn.beginTransaction(null); 139 assertNotNull(currentTxn.getTransaction()); 140 currentTxn.commitTransaction(); 141 assertNull(currentTxn.getTransaction()); 142 143 currentTxn.beginTransaction(null); 144 assertNotNull(currentTxn.getTransaction()); 145 currentTxn.abortTransaction(); 146 assertNull(currentTxn.getTransaction()); 147 148 150 assertTrue(!isReadUncommitted(map)); 151 assertTrue(!isReadUncommitted(map.values())); 152 assertTrue(!isReadUncommitted(map.keySet())); 153 assertTrue(!isReadUncommitted(map.entrySet())); 154 155 StoredSortedMap other = (StoredSortedMap) 156 StoredCollections.configuredMap 157 (map, CursorConfig.READ_UNCOMMITTED); 158 assertTrue(isReadUncommitted(other)); 159 assertTrue(isReadUncommitted(other.values())); 160 assertTrue(isReadUncommitted(other.keySet())); 161 assertTrue(isReadUncommitted(other.entrySet())); 162 assertTrue(!isReadUncommitted(map)); 163 assertTrue(!isReadUncommitted(map.values())); 164 assertTrue(!isReadUncommitted(map.keySet())); 165 assertTrue(!isReadUncommitted(map.entrySet())); 166 167 169 assertTrue(!isReadCommitted(map)); 170 assertTrue(!isReadCommitted(map.values())); 171 assertTrue(!isReadCommitted(map.keySet())); 172 assertTrue(!isReadCommitted(map.entrySet())); 173 174 other = (StoredSortedMap) 175 StoredCollections.configuredMap 176 (map, CursorConfig.READ_COMMITTED); 177 assertTrue(isReadCommitted(other)); 178 assertTrue(isReadCommitted(other.values())); 179 assertTrue(isReadCommitted(other.keySet())); 180 assertTrue(isReadCommitted(other.entrySet())); 181 assertTrue(!isReadCommitted(map)); 182 assertTrue(!isReadCommitted(map.values())); 183 assertTrue(!isReadCommitted(map.keySet())); 184 assertTrue(!isReadCommitted(map.entrySet())); 185 } 186 187 public void testTransactional() 188 throws Exception { 189 190 assertTrue(map.isTransactional()); 194 store.close(); 195 store = null; 196 197 DatabaseConfig dbConfig = new DatabaseConfig(); 200 DbCompat.setTypeBtree(dbConfig); 201 dbConfig.setAllowCreate(true); 202 Database db = DbCompat.openDatabase(env, null, 203 dbName(1), null, 204 dbConfig); 205 map = new StoredSortedMap(db, testStore.getKeyBinding(), 206 testStore.getValueBinding(), true); 207 assertTrue(!map.isTransactional()); 208 map.put(ONE, ONE); 209 readCheck(map, ONE, ONE); 210 db.close(); 211 212 dbConfig.setTransactional(true); 215 currentTxn.beginTransaction(null); 216 db = DbCompat.openDatabase(env, currentTxn.getTransaction(), 217 dbName(2), null, dbConfig); 218 currentTxn.commitTransaction(); 219 map = new StoredSortedMap(db, testStore.getKeyBinding(), 220 testStore.getValueBinding(), true); 221 assertTrue(map.isTransactional()); 222 currentTxn.beginTransaction(null); 223 map.put(ONE, ONE); 224 readCheck(map, ONE, ONE); 225 currentTxn.commitTransaction(); 226 db.close(); 227 } 228 229 public void testExceptions() 230 throws Exception { 231 232 try { 233 currentTxn.commitTransaction(); 234 fail(); 235 } catch (IllegalStateException expected) {} 236 237 try { 238 currentTxn.abortTransaction(); 239 fail(); 240 } catch (IllegalStateException expected) {} 241 } 242 243 public void testNested() 244 throws Exception { 245 246 if (!DbCompat.NESTED_TRANSACTIONS) { 247 return; 248 } 249 assertNull(currentTxn.getTransaction()); 250 251 Transaction txn1 = currentTxn.beginTransaction(null); 252 assertNotNull(txn1); 253 assertTrue(txn1 == currentTxn.getTransaction()); 254 255 assertNull(map.get(ONE)); 256 assertNull(map.put(ONE, ONE)); 257 assertEquals(ONE, map.get(ONE)); 258 259 Transaction txn2 = currentTxn.beginTransaction(null); 260 assertNotNull(txn2); 261 assertTrue(txn2 == currentTxn.getTransaction()); 262 assertTrue(txn1 != txn2); 263 264 assertNull(map.put(TWO, TWO)); 265 assertEquals(TWO, map.get(TWO)); 266 267 Transaction txn3 = currentTxn.beginTransaction(null); 268 assertNotNull(txn3); 269 assertTrue(txn3 == currentTxn.getTransaction()); 270 assertTrue(txn1 != txn2); 271 assertTrue(txn1 != txn3); 272 assertTrue(txn2 != txn3); 273 274 assertNull(map.put(THREE, THREE)); 275 assertEquals(THREE, map.get(THREE)); 276 277 Transaction txn = currentTxn.abortTransaction(); 278 assertTrue(txn == txn2); 279 assertTrue(txn == currentTxn.getTransaction()); 280 assertNull(map.get(THREE)); 281 assertEquals(TWO, map.get(TWO)); 282 283 txn3 = currentTxn.beginTransaction(null); 284 assertNotNull(txn3); 285 assertTrue(txn3 == currentTxn.getTransaction()); 286 assertTrue(txn1 != txn2); 287 assertTrue(txn1 != txn3); 288 assertTrue(txn2 != txn3); 289 290 assertNull(map.put(THREE, THREE)); 291 assertEquals(THREE, map.get(THREE)); 292 293 txn = currentTxn.commitTransaction(); 294 assertTrue(txn == txn2); 295 assertTrue(txn == currentTxn.getTransaction()); 296 assertEquals(THREE, map.get(THREE)); 297 assertEquals(TWO, map.get(TWO)); 298 299 txn = currentTxn.commitTransaction(); 300 assertTrue(txn == txn1); 301 assertTrue(txn == currentTxn.getTransaction()); 302 assertEquals(THREE, map.get(THREE)); 303 assertEquals(TWO, map.get(TWO)); 304 assertEquals(ONE, map.get(ONE)); 305 306 txn = currentTxn.commitTransaction(); 307 assertNull(txn); 308 assertNull(currentTxn.getTransaction()); 309 assertEquals(THREE, map.get(THREE)); 310 assertEquals(TWO, map.get(TWO)); 311 assertEquals(ONE, map.get(ONE)); 312 } 313 314 public void testRunnerCommit() 315 throws Exception { 316 317 commitTest(false); 318 } 319 320 public void testExplicitCommit() 321 throws Exception { 322 323 commitTest(true); 324 } 325 326 private void commitTest(final boolean explicit) 327 throws Exception { 328 329 final TransactionRunner runner = new TransactionRunner(env); 330 runner.setAllowNestedTransactions(DbCompat.NESTED_TRANSACTIONS); 331 332 assertNull(currentTxn.getTransaction()); 333 334 runner.run(new TransactionWorker() { 335 public void doWork() throws Exception { 336 final Transaction txn1 = currentTxn.getTransaction(); 337 assertNotNull(txn1); 338 assertNull(map.put(ONE, ONE)); 339 assertEquals(ONE, map.get(ONE)); 340 341 runner.run(new TransactionWorker() { 342 public void doWork() throws Exception { 343 final Transaction txn2 = currentTxn.getTransaction(); 344 assertNotNull(txn2); 345 if (DbCompat.NESTED_TRANSACTIONS) { 346 assertTrue(txn1 != txn2); 347 } else { 348 assertTrue(txn1 == txn2); 349 } 350 assertNull(map.put(TWO, TWO)); 351 assertEquals(TWO, map.get(TWO)); 352 assertEquals(ONE, map.get(ONE)); 353 if (DbCompat.NESTED_TRANSACTIONS && explicit) { 354 currentTxn.commitTransaction(); 355 } 356 } 357 }); 358 359 Transaction txn3 = currentTxn.getTransaction(); 360 assertSame(txn1, txn3); 361 362 assertEquals(TWO, map.get(TWO)); 363 assertEquals(ONE, map.get(ONE)); 364 } 365 }); 366 367 assertNull(currentTxn.getTransaction()); 368 } 369 370 public void testRunnerAbort() 371 throws Exception { 372 373 abortTest(false); 374 } 375 376 public void testExplicitAbort() 377 throws Exception { 378 379 abortTest(true); 380 } 381 382 private void abortTest(final boolean explicit) 383 throws Exception { 384 385 final TransactionRunner runner = new TransactionRunner(env); 386 runner.setAllowNestedTransactions(DbCompat.NESTED_TRANSACTIONS); 387 388 assertNull(currentTxn.getTransaction()); 389 390 runner.run(new TransactionWorker() { 391 public void doWork() throws Exception { 392 final Transaction txn1 = currentTxn.getTransaction(); 393 assertNotNull(txn1); 394 assertNull(map.put(ONE, ONE)); 395 assertEquals(ONE, map.get(ONE)); 396 397 if (DbCompat.NESTED_TRANSACTIONS) { 398 try { 399 runner.run(new TransactionWorker() { 400 public void doWork() throws Exception { 401 final Transaction txn2 = 402 currentTxn.getTransaction(); 403 assertNotNull(txn2); 404 assertTrue(txn1 != txn2); 405 assertNull(map.put(TWO, TWO)); 406 assertEquals(TWO, map.get(TWO)); 407 if (explicit) { 408 currentTxn.abortTransaction(); 409 } else { 410 throw new IllegalArgumentException ( 411 "test-abort"); 412 } 413 } 414 }); 415 assertTrue(explicit); 416 } catch (IllegalArgumentException e) { 417 assertTrue(!explicit); 418 assertEquals("test-abort", e.getMessage()); 419 } 420 } 421 422 Transaction txn3 = currentTxn.getTransaction(); 423 assertSame(txn1, txn3); 424 425 assertEquals(ONE, map.get(ONE)); 426 assertNull(map.get(TWO)); 427 } 428 }); 429 430 assertNull(currentTxn.getTransaction()); 431 } 432 433 public void testReadCommittedCollection() 434 throws Exception { 435 436 StoredSortedMap degree2Map = (StoredSortedMap) 437 StoredCollections.configuredSortedMap 438 (map, CursorConfig.READ_COMMITTED); 439 440 assertTrue(!isReadCommitted(map)); 442 443 assertTrue(isReadCommitted(degree2Map)); 445 assertTrue(isReadCommitted 446 (StoredCollections.configuredMap 447 (map, CursorConfig.READ_COMMITTED))); 448 assertTrue(isReadCommitted 449 (StoredCollections.configuredCollection 450 (map.values(), CursorConfig.READ_COMMITTED))); 451 assertTrue(isReadCommitted 452 (StoredCollections.configuredSet 453 (map.keySet(), CursorConfig.READ_COMMITTED))); 454 assertTrue(isReadCommitted 455 (StoredCollections.configuredSortedSet 456 ((SortedSet ) map.keySet(), 457 CursorConfig.READ_COMMITTED))); 458 459 if (DbCompat.RECNO_METHOD) { 460 Database listStore = TestStore.RECNO_RENUM.open(env, null); 462 List list = new StoredList(listStore, TestStore.VALUE_BINDING, 463 true); 464 assertTrue(isReadCommitted 465 (StoredCollections.configuredList 466 (list, CursorConfig.READ_COMMITTED))); 467 listStore.close(); 468 } 469 470 map.put(ONE, ONE); 471 doReadCommitted(degree2Map, null); 472 } 473 474 private static boolean isReadCommitted(Object container) { 475 StoredContainer storedContainer = (StoredContainer) container; 476 477 return storedContainer.getCursorConfig() != null && 478 storedContainer.getCursorConfig().getReadCommitted(); 479 } 480 481 public void testReadCommittedTransaction() 482 throws Exception { 483 484 TransactionConfig config = new TransactionConfig(); 485 config.setReadCommitted(true); 486 doReadCommitted(map, config); 487 } 488 489 private void doReadCommitted(final StoredSortedMap degree2Map, 490 TransactionConfig txnConfig) 491 throws Exception { 492 493 map.put(ONE, ONE); 494 TransactionRunner runner = new TransactionRunner(env); 495 runner.setTransactionConfig(txnConfig); 496 assertNull(currentTxn.getTransaction()); 497 runner.run(new TransactionWorker() { 498 public void doWork() throws Exception { 499 assertNotNull(currentTxn.getTransaction()); 500 501 502 assertEquals(ONE, degree2Map.get(ONE)); 503 504 511 DatabaseEntry key = new DatabaseEntry(); 512 DatabaseEntry value = new DatabaseEntry(); 513 testStore.getKeyBinding().objectToEntry(ONE, key); 514 testStore.getValueBinding().objectToEntry(TWO, value); 515 store.put(null, key, value); 516 } 517 }); 518 assertNull(currentTxn.getTransaction()); 519 } 520 521 public void testReadUncommittedCollection() 522 throws Exception { 523 524 StoredSortedMap dirtyMap = (StoredSortedMap) 525 StoredCollections.configuredSortedMap 526 (map, CursorConfig.READ_UNCOMMITTED); 527 528 assertTrue(!isReadUncommitted(map)); 530 531 assertTrue(isReadUncommitted(dirtyMap)); 533 assertTrue(isReadUncommitted 534 (StoredCollections.configuredMap 535 (map, CursorConfig.READ_UNCOMMITTED))); 536 assertTrue(isReadUncommitted 537 (StoredCollections.configuredCollection 538 (map.values(), CursorConfig.READ_UNCOMMITTED))); 539 assertTrue(isReadUncommitted 540 (StoredCollections.configuredSet 541 (map.keySet(), CursorConfig.READ_UNCOMMITTED))); 542 assertTrue(isReadUncommitted 543 (StoredCollections.configuredSortedSet 544 ((SortedSet ) map.keySet(), CursorConfig.READ_UNCOMMITTED))); 545 546 if (DbCompat.RECNO_METHOD) { 547 Database listStore = TestStore.RECNO_RENUM.open(env, null); 549 List list = new StoredList(listStore, TestStore.VALUE_BINDING, 550 true); 551 assertTrue(isReadUncommitted 552 (StoredCollections.configuredList 553 (list, CursorConfig.READ_UNCOMMITTED))); 554 listStore.close(); 555 } 556 557 doReadUncommitted(dirtyMap); 558 } 559 560 private static boolean isReadUncommitted(Object container) { 561 StoredContainer storedContainer = (StoredContainer) container; 562 return storedContainer.getCursorConfig() != null && 563 storedContainer.getCursorConfig().getReadUncommitted(); 564 } 565 566 public void testReadUncommittedTransaction() 567 throws Exception { 568 569 TransactionRunner runner = new TransactionRunner(env); 570 TransactionConfig config = new TransactionConfig(); 571 config.setReadUncommitted(true); 572 runner.setTransactionConfig(config); 573 assertNull(currentTxn.getTransaction()); 574 runner.run(new TransactionWorker() { 575 public void doWork() throws Exception { 576 assertNotNull(currentTxn.getTransaction()); 577 doReadUncommitted(map); 578 } 579 }); 580 assertNull(currentTxn.getTransaction()); 581 } 582 583 private synchronized void doReadUncommitted(StoredSortedMap dirtyMap) 584 throws Exception { 585 586 ReadUncommittedThreadOne t1 = new ReadUncommittedThreadOne(env, this); 588 t1.start(); 589 wait(); 590 591 synchronized (t1) { t1.notify(); } 593 wait(); 594 readCheck(dirtyMap, ONE, ONE); 595 assertTrue(!dirtyMap.isEmpty()); 596 597 synchronized (t1) { t1.notify(); } 599 t1.join(); 600 readCheck(dirtyMap, ONE, null); 601 assertTrue(dirtyMap.isEmpty()); 602 603 ReadUncommittedThreadTwo t2 = new ReadUncommittedThreadTwo(env, this); 605 t2.start(); 606 wait(); 607 608 synchronized (t2) { t2.notify(); } 610 wait(); 611 readCheck(dirtyMap, TWO, TWO); 612 assertTrue(!dirtyMap.isEmpty()); 613 614 synchronized (t2) { t2.notify(); } 616 t2.join(); 617 readCheck(dirtyMap, TWO, TWO); 618 assertTrue(!dirtyMap.isEmpty()); 619 } 620 621 private static class ReadUncommittedThreadOne extends Thread { 622 623 private CurrentTransaction currentTxn; 624 private TransactionTest parent; 625 private StoredSortedMap map; 626 627 private ReadUncommittedThreadOne(Environment env, 628 TransactionTest parent) { 629 630 this.currentTxn = CurrentTransaction.getInstance(env); 631 this.parent = parent; 632 this.map = parent.map; 633 } 634 635 public synchronized void run() { 636 637 try { 638 assertNull(currentTxn.getTransaction()); 639 assertNotNull(currentTxn.beginTransaction(null)); 640 assertNotNull(currentTxn.getTransaction()); 641 readCheck(map, ONE, null); 642 synchronized (parent) { parent.notify(); } 643 wait(); 644 645 assertNull(map.put(ONE, ONE)); 647 readCheck(map, ONE, ONE); 648 synchronized (parent) { parent.notify(); } 649 wait(); 650 651 assertNull(currentTxn.abortTransaction()); 653 assertNull(currentTxn.getTransaction()); 654 } catch (Exception e) { 655 throw new RuntimeExceptionWrapper(e); 656 } 657 } 658 } 659 660 private static class ReadUncommittedThreadTwo extends Thread { 661 662 private Environment env; 663 private CurrentTransaction currentTxn; 664 private TransactionTest parent; 665 private StoredSortedMap map; 666 667 private ReadUncommittedThreadTwo(Environment env, 668 TransactionTest parent) { 669 670 this.env = env; 671 this.currentTxn = CurrentTransaction.getInstance(env); 672 this.parent = parent; 673 this.map = parent.map; 674 } 675 676 public synchronized void run() { 677 678 try { 679 final TransactionRunner runner = new TransactionRunner(env); 680 final Object thread = this; 681 assertNull(currentTxn.getTransaction()); 682 683 runner.run(new TransactionWorker() { 684 public void doWork() throws Exception { 685 assertNotNull(currentTxn.getTransaction()); 686 readCheck(map, TWO, null); 687 synchronized (parent) { parent.notify(); } 688 thread.wait(); 689 690 assertNull(map.put(TWO, TWO)); 692 readCheck(map, TWO, TWO); 693 synchronized (parent) { parent.notify(); } 694 thread.wait(); 695 696 } 698 }); 699 assertNull(currentTxn.getTransaction()); 700 } catch (Exception e) { 701 throw new RuntimeExceptionWrapper(e); 702 } 703 } 704 } 705 706 private static void readCheck(StoredSortedMap checkMap, Object key, 707 Object expect) { 708 if (expect == null) { 709 assertNull(checkMap.get(key)); 710 assertTrue(checkMap.tailMap(key).isEmpty()); 711 assertTrue(!checkMap.tailMap(key).containsKey(key)); 712 assertTrue(!checkMap.keySet().contains(key)); 713 assertTrue(checkMap.duplicates(key).isEmpty()); 714 Iterator i = checkMap.keySet().iterator(); 715 try { 716 while (i.hasNext()) { 717 assertTrue(!key.equals(i.next())); 718 } 719 } finally { StoredIterator.close(i); } 720 } else { 721 assertEquals(expect, checkMap.get(key)); 722 assertEquals(expect, checkMap.tailMap(key).get(key)); 723 assertTrue(!checkMap.tailMap(key).isEmpty()); 724 assertTrue(checkMap.tailMap(key).containsKey(key)); 725 assertTrue(checkMap.keySet().contains(key)); 726 assertTrue(checkMap.values().contains(expect)); 727 assertTrue(!checkMap.duplicates(key).isEmpty()); 728 assertTrue(checkMap.duplicates(key).contains(expect)); 729 Iterator i = checkMap.keySet().iterator(); 730 try { 731 boolean found = false; 732 while (i.hasNext()) { 733 if (expect.equals(i.next())) { 734 found = true; 735 } 736 } 737 assertTrue(found); 738 } 739 finally { StoredIterator.close(i); } 740 } 741 } 742 } 743 | Popular Tags |