@Test public void shouldListLocksHeldByTheCurrentClient() { // given clientA.acquireExclusive( LockTracer.NONE, NODE, 1, 2, 3 ); clientA.acquireShared( LockTracer.NONE, NODE, 3, 4, 5 ); // when Stream<? extends ActiveLock> locks = clientA.activeLocks(); // then assertEquals( new HashSet<>( asList( exclusiveLock( NODE, 1 ), exclusiveLock( NODE, 2 ), exclusiveLock( NODE, 3 ), sharedLock( NODE, 3 ), sharedLock( NODE, 4 ), sharedLock( NODE, 5 ) ) ), locks.collect( toSet() ) ); }
@Test public void shouldTraceWaitTimeWhenTryingToAcquireSharedLockAndExclusiveIsHeld() throws Exception { // given Tracer tracerA = new Tracer(); Tracer tracerB = new Tracer(); clientA.acquireExclusive( tracerA, NODE, 17 ); // when Future<Object> future = acquireShared( clientB, tracerB, NODE, 17 ).callAndAssertWaiting(); // then clientA.releaseExclusive( NODE, 17 ); future.get(); tracerA.assertCalls( 0 ); tracerB.assertCalls( 1 ); }
@Override public void close() { localClient.close(); }
@Override public void stop() { localClient.stop(); }
@Override public long activeLockCount() { return localClient.activeLockCount(); } }
@Override public void prepare() { localClient.prepare(); }
@Override public long activeLockCount() { return client.activeLockCount(); } }
@Override public Stream<? extends ActiveLock> activeLocks() { return localClient.activeLocks(); }
@Override public void close() { localClient.close(); }
@Override public void prepareForCommit( LockTracer lockTracer ) { // Locks where grabbed eagerly by client so no need to prepare client.prepare(); }
@Override public void close() { client.close(); }
@Override public Stream<? extends ActiveLock> activeLocks() { return client.activeLocks(); }
@Override public void stop() { client.stop(); }
@Test public void closeShouldWaitAllOperationToFinish() { // given clientA.acquireShared( LockTracer.NONE, NODE, 1L ); clientA.acquireShared( LockTracer.NONE, NODE, 3L ); clientB.acquireShared( LockTracer.NONE, NODE, 1L ); acquireShared( clientC, LockTracer.NONE, NODE, 2L ); acquireExclusive( clientB, LockTracer.NONE, NODE, 1L ).callAndAssertWaiting(); acquireExclusive( clientC, LockTracer.NONE, NODE, 1L ).callAndAssertWaiting(); // when clientB.close(); clientC.close(); clientA.close(); // all locks should be closed at this point regardless of // reader/writer waiter in any threads // those should be gracefully finish and client should be closed LockCountVisitor lockCountVisitor = new LockCountVisitor(); locks.accept( lockCountVisitor ); assertEquals( 0, lockCountVisitor.getLockCount() ); }
@Test public void mustReleaseWriteLockWaitersOnStop() { // Given clientA.acquireShared( TRACER, NODE, 1L ); clientB.acquireShared( TRACER, NODE, 2L ); clientC.acquireShared( TRACER, NODE, 3L ); acquireExclusive( clientB, TRACER, NODE, 1L ).callAndAssertWaiting(); acquireExclusive( clientC, TRACER, NODE, 1L ).callAndAssertWaiting(); // When clientC.stop(); clientB.stop(); clientA.stop(); // All locks clients should be stopped at this point, and all all locks should be released because none of the // clients entered the prepare phase LockCountVisitor lockCountVisitor = new LockCountVisitor(); locks.accept( lockCountVisitor ); assertEquals( 0, lockCountVisitor.getLockCount() ); }
@Test public void exclusiveLocksShouldBeReentrantAndBlockOtherSharedLocks() { // When clientA.acquireExclusive( LockTracer.NONE, NODE, 1L ); clientA.acquireShared( LockTracer.NONE, NODE, 1L ); clientA.tryExclusiveLock( NODE, 1L ); // Then exclusive locks should wait Future<Object> clientBLock = acquireShared( clientB, LockTracer.NONE, NODE, 1L ).callAndAssertWaiting(); // And when clientA.releaseExclusive( NODE, 1L ); clientA.releaseShared( NODE, 1L ); // Then other thread should still wait assertWaiting( clientB, clientBLock ); // But when clientA.releaseExclusive( NODE, 1L ); // Then assertNotWaiting( clientB, clientBLock ); }
@Test public void sharedLocksShouldStack() { // When clientA.acquireShared( LockTracer.NONE, NODE, 1L ); clientA.acquireShared( LockTracer.NONE, NODE, 1L ); clientA.acquireShared( LockTracer.NONE, NODE, 1L ); // Then exclusive locks should wait Future<Object> clientBLock = acquireExclusive( clientB, LockTracer.NONE, NODE, 1L ).callAndAssertWaiting(); // And when clientA.releaseShared( NODE, 1L ); clientA.releaseShared( NODE, 1L ); // Then other thread should still wait assertWaiting( clientB, clientBLock ); // But when clientA.releaseShared( NODE, 1L ); // Then assertNotWaiting( clientB, clientBLock ); }
@Test public void sharedLocksShouldNotReplaceExclusiveLocks() { // When clientA.acquireExclusive( LockTracer.NONE, NODE, 1L ); clientA.acquireShared( LockTracer.NONE, NODE, 1L ); // Then shared locks should wait Future<Object> clientBLock = acquireShared( clientB, LockTracer.NONE, NODE, 1L ).callAndAssertWaiting(); // And when clientA.releaseShared( NODE, 1L ); // Then other thread should still wait assertWaiting( clientB, clientBLock ); // But when clientA.releaseExclusive( NODE, 1L ); // Then assertNotWaiting( clientB, clientBLock ); }
@Test public void mustReleaseReadLockWaitersOnStop() { // Given clientA.acquireExclusive( TRACER, NODE, 1L ); clientB.acquireExclusive( TRACER, NODE, 2L ); acquireShared( clientB, TRACER, NODE, 1L ).callAndAssertWaiting(); // When clientB.stop(); clientA.stop(); // All locks clients should be stopped at this point, and all all locks should be released because none of the // clients entered the prepare phase LockCountVisitor lockCountVisitor = new LockCountVisitor(); locks.accept( lockCountVisitor ); assertEquals( 0, lockCountVisitor.getLockCount() ); }