Skip to content

Commit

Permalink
Fix exception propagation during lock upgrade
Browse files Browse the repository at this point in the history
Commit fixes the problem where TransactionTerminatedException would be wrapped
in RuntimeException if occurred during shared to exclusive lock upgrade in Forseti.
  • Loading branch information
lutovich committed May 30, 2016
1 parent b538360 commit 2b5173b
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 5 deletions.
Expand Up @@ -210,6 +210,27 @@ public void closeClientAfterExclusiveLockFailureOnTransactionTermination() throw
closeClientAfterLockFailureOnTransactionTermination( false );
}

@Test
public void acquireExclusiveLockWhileHoldingSharedLockCanBeTerminated() throws Exception
{
acquireSharedLockInThisThread();

CountDownLatch sharedLockAcquired = new CountDownLatch( 1 );
CountDownLatch startExclusiveLock = new CountDownLatch( 1 );
LockAcquisition acquisition = acquireSharedAndExclusiveLocksInAnotherThread( sharedLockAcquired,
startExclusiveLock );

await( sharedLockAcquired );
startExclusiveLock.countDown();
assertThreadIsWaitingForLock( acquisition );

acquisition.terminate();
assertLockAcquisitionFailed( acquisition );

releaseAllLocksInThisThread();
assertNoLocksHeld();
}

private void closeClientAfterLockFailureOnTransactionTermination( boolean shared ) throws Exception
{
acquireExclusiveLockInThisThread();
Expand Down Expand Up @@ -249,6 +270,12 @@ private void acquireLockAfterOtherLockFailureOnTransactionTerminationSameThread(
assertLockAcquisitionSucceeded( lockAcquisition );
}

private void acquireSharedLockInThisThread()
{
client.acquireShared( RESOURCE_TYPE, RESOURCE_ID );
assertLocksHeld( RESOURCE_ID );
}

private void acquireExclusiveLockInThisThread()
{
client.acquireExclusive( RESOURCE_TYPE, RESOURCE_ID );
Expand Down Expand Up @@ -349,6 +376,33 @@ public Void call() throws Exception
return lockAcquisition;
}

private LockAcquisition acquireSharedAndExclusiveLocksInAnotherThread( final CountDownLatch sharedLockAcquired,
final CountDownLatch startExclusiveLock )
{
final LockAcquisition lockAcquisition = new LockAcquisition();

Future<Void> future = executor.submit( new Callable<Void>()
{
@Override
public Void call() throws Exception
{
try ( Client client = newLockClient( lockAcquisition ) )
{
client.acquireShared( RESOURCE_TYPE, RESOURCE_ID );

sharedLockAcquired.countDown();
await( startExclusiveLock );

client.acquireExclusive( RESOURCE_TYPE, RESOURCE_ID );
}
return null;
}
} );
lockAcquisition.setFuture( future );

return lockAcquisition;
}

private LockAcquisition tryAcquireTwoLocksLockInAnotherThread( final boolean shared,
final CountDownLatch firstLockAcquired )
{
Expand Down
Expand Up @@ -615,21 +615,33 @@ private boolean tryUpgradeToExclusiveWithShareLockHeld(
return true;

}
catch(DeadlockDetectedException e)
catch ( DeadlockDetectedException e )
{
sharedLock.releaseUpdateLock(this);
sharedLock.releaseUpdateLock( this );
// wait list is not cleared here as in other catch blocks because it is cleared in
// markAsWaitingFor() before throwing DeadlockDetectedException
throw e;
}
catch(Throwable e)
catch ( TransactionTerminatedException e )
{
handleUpgradeToExclusiveFailure( sharedLock );
throw e;
}
catch ( Throwable e )
{
sharedLock.releaseUpdateLock(this);
clearWaitList();
handleUpgradeToExclusiveFailure( sharedLock );
throw new RuntimeException( e );
}
}
return false;
}

private void handleUpgradeToExclusiveFailure( SharedLock sharedLock )
{
sharedLock.releaseUpdateLock( this );
clearWaitList();
}

private void clearWaitList()
{
waitList.clear();
Expand Down

0 comments on commit 2b5173b

Please sign in to comment.