|
30 | 30 | import java.util.concurrent.LinkedBlockingQueue; |
31 | 31 | import java.util.concurrent.ThreadPoolExecutor; |
32 | 32 | import java.util.concurrent.TimeUnit; |
| 33 | +import java.util.concurrent.atomic.AtomicBoolean; |
33 | 34 | import java.util.concurrent.atomic.AtomicInteger; |
34 | 35 | import java.util.concurrent.atomic.AtomicReference; |
35 | 36 |
|
@@ -422,12 +423,90 @@ public void testCallInReadTx() { |
422 | 423 | } |
423 | 424 |
|
424 | 425 | @Test |
425 | | - public void testRunInReadTxAndThenPut() { |
| 426 | + public void testRunInTx_closesActiveTxCursor() { |
426 | 427 | final Box<TestEntity> box = getTestEntityBox(); |
427 | | - store.runInReadTx(box::count); |
428 | | - // Verify that box does not hang on to the read-only TX by doing a put |
| 428 | + AtomicBoolean hasCursorInTx = new AtomicBoolean(false); |
| 429 | + store.runInTx(() -> { |
| 430 | + box.count(); // Call Box API that creates a reader/activeTxCursor |
| 431 | + hasCursorInTx.set(box.hasActiveTxCursorForCurrentThread()); |
| 432 | + }); |
| 433 | + // Verify a cursor for the active tx was created |
| 434 | + assertTrue(hasCursorInTx.get()); |
| 435 | + // Check it was released |
| 436 | + assertFalse(box.hasActiveTxCursorForCurrentThread()); |
| 437 | + |
| 438 | + // Verify the same in case the runnable throws |
| 439 | + try { |
| 440 | + store.runInTx(() -> { |
| 441 | + box.count(); |
| 442 | + throw new IllegalStateException("Throw in transaction"); |
| 443 | + }); |
| 444 | + } catch (IllegalStateException ignored) {} |
| 445 | + assertFalse(box.hasActiveTxCursorForCurrentThread()); |
| 446 | + } |
| 447 | + |
| 448 | + @Test |
| 449 | + public void testCallInTx_closesActiveTxCursor() throws Exception { |
| 450 | + final Box<TestEntity> box = getTestEntityBox(); |
| 451 | + Boolean hasCursorInTx = store.callInTx(() -> { |
| 452 | + box.count(); // Call Box API that creates a reader/activeTxCursor |
| 453 | + return box.hasActiveTxCursorForCurrentThread(); |
| 454 | + }); |
| 455 | + // Verify a cursor for the active tx was created |
| 456 | + assertTrue(hasCursorInTx); |
| 457 | + // Check it was released |
| 458 | + assertFalse(box.hasActiveTxCursorForCurrentThread()); |
| 459 | + |
| 460 | + // Verify the same in case the callable throws |
| 461 | + try { |
| 462 | + store.callInTx(() -> { |
| 463 | + box.count(); |
| 464 | + throw new IllegalStateException("Throw in transaction"); |
| 465 | + }); |
| 466 | + } catch (IllegalStateException ignored) {} |
| 467 | + assertFalse(box.hasActiveTxCursorForCurrentThread()); |
| 468 | + } |
| 469 | + |
| 470 | + @Test |
| 471 | + public void testRunInReadTx_closesActiveTxCursor() { |
| 472 | + final Box<TestEntity> box = getTestEntityBox(); |
| 473 | + store.runInReadTx(box::count); // Call Box API that creates a reader/activeTxCursor |
| 474 | + // Verify that box does not hang on to the read-only TX: if it would, count() would re-use the cursor/tx from |
| 475 | + // above and not see the put object. |
| 476 | + putTestEntityAndExpectCount(1); |
| 477 | + assertFalse(box.hasActiveTxCursorForCurrentThread()); |
| 478 | + |
| 479 | + // Verify the same in case the runnable throws |
| 480 | + assertThrows(IllegalStateException.class, () -> store.runInReadTx(() -> { |
| 481 | + box.count(); |
| 482 | + throw new IllegalStateException("Throw in transaction"); |
| 483 | + })); |
| 484 | + putTestEntityAndExpectCount(2); |
| 485 | + assertFalse(box.hasActiveTxCursorForCurrentThread()); |
| 486 | + } |
| 487 | + |
| 488 | + @Test |
| 489 | + public void testCallInReadTx_closesActiveTxCursor() { |
| 490 | + final Box<TestEntity> box = getTestEntityBox(); |
| 491 | + store.callInReadTx(box::count); // Call Box API that creates a reader/activeTxCursor |
| 492 | + // Verify that box does not hang on to the read-only TX: if it would, count() would re-use the cursor/tx from |
| 493 | + // above and not see the put object. |
| 494 | + putTestEntityAndExpectCount(1); |
| 495 | + assertFalse(box.hasActiveTxCursorForCurrentThread()); |
| 496 | + |
| 497 | + // Verify the same in case the callable throws |
| 498 | + assertThrows(IllegalStateException.class, () -> store.callInReadTx(() -> { |
| 499 | + box.count(); |
| 500 | + throw new IllegalStateException("Throw in transaction"); |
| 501 | + })); |
| 502 | + putTestEntityAndExpectCount(2); |
| 503 | + assertFalse(box.hasActiveTxCursorForCurrentThread()); |
| 504 | + } |
| 505 | + |
| 506 | + private void putTestEntityAndExpectCount(int expectedCount) { |
| 507 | + Box<TestEntity> box = getTestEntityBox(); |
429 | 508 | box.put(new TestEntity()); |
430 | | - assertEquals(1, box.count()); |
| 509 | + assertEquals(expectedCount, box.count()); |
431 | 510 | } |
432 | 511 |
|
433 | 512 | @Test |
|
0 commit comments