Skip to content

Commit

Permalink
Added status code for AcquireLockTimeoutException
Browse files Browse the repository at this point in the history
to better help a client, i.e. a driver, to classify the error for end users.

AcquireLockTimeoutException is mainly used in CE to indicate that we cannot grab a lock on a `Leader`. There is a chance that we will get this exception if a leadership switch happened after we've checked the the server where we are going to get the lock is the `Leader`, but before we really start to take a lock.
  • Loading branch information
Zhen committed Oct 11, 2016
1 parent 5e4211f commit a08fc63
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 15 deletions.
Expand Up @@ -185,7 +185,9 @@ enum Transaction implements Status
LockClientStopped( TransientError,
"Transaction terminated, no more locks can be acquired." ),
Terminated( TransientError,
"Explicitly terminated by the user." );
"Explicitly terminated by the user." ),
Interrupted( TransientError,
"Interrupted while waiting." );

private final Code code;

Expand Down
Expand Up @@ -22,6 +22,8 @@
import org.neo4j.storageengine.api.lock.AcquireLockTimeoutException;
import org.neo4j.storageengine.api.lock.WaitStrategy;

import static org.neo4j.kernel.api.exceptions.Status.Transaction.Interrupted;

public enum LockWaitStrategies implements WaitStrategy<AcquireLockTimeoutException>
{
SPIN
Expand Down Expand Up @@ -73,7 +75,7 @@ public void apply( long iteration ) throws AcquireLockTimeoutException
catch(InterruptedException e)
{
Thread.interrupted();
throw new AcquireLockTimeoutException( e , "Interrupted while waiting.");
throw new AcquireLockTimeoutException( e , "Interrupted while waiting.", Interrupted );
}
}
};
Expand Down
Expand Up @@ -19,19 +19,31 @@
*/
package org.neo4j.storageengine.api.lock;

import org.neo4j.kernel.api.exceptions.Status;

/**
* Acquiring a lock failed. This is a runtime exception now to ease the transition from the old lock interface, but
* it should be made into a {@link org.neo4j.kernel.api.exceptions.KernelException} asap.
*/
public class AcquireLockTimeoutException extends RuntimeException
public class AcquireLockTimeoutException extends RuntimeException implements Status.HasStatus
{
public AcquireLockTimeoutException( Throwable cause, String message, Object... parameters )
private final Status statusCode;

public AcquireLockTimeoutException( Throwable cause, String message, Status statusCode )
{
super( String.format(message, parameters), cause );
super( message, cause );
this.statusCode = statusCode;
}

public AcquireLockTimeoutException( String message )
public AcquireLockTimeoutException( String message, Status statusCode )
{
super( message );
this.statusCode = statusCode;
}

@Override
public Status status()
{
return statusCode;
}
}
Expand Up @@ -21,18 +21,20 @@

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;

import org.neo4j.coreedge.core.consensus.LeaderLocator;
import org.neo4j.coreedge.core.consensus.NoLeaderFoundException;
import org.neo4j.coreedge.core.replication.Replicator;
import org.neo4j.coreedge.core.state.machines.tx.ReplicatedTransactionStateMachine;
import org.neo4j.coreedge.identity.MemberId;
import org.neo4j.kernel.api.exceptions.Status;
import org.neo4j.kernel.impl.locking.Locks;
import org.neo4j.storageengine.api.lock.AcquireLockTimeoutException;
import org.neo4j.storageengine.api.lock.ResourceType;

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.neo4j.kernel.api.exceptions.Status.Cluster.NoLeaderAvailable;
import static org.neo4j.kernel.api.exceptions.Status.Cluster.NotALeader;
import static org.neo4j.kernel.api.exceptions.Status.Transaction.Interrupted;

/**
* Each member of the cluster uses its own {@link LeaderOnlyLockManager} which wraps a local {@link Locks} manager.
Expand Down Expand Up @@ -109,7 +111,7 @@ private synchronized int acquireTokenOrThrow()
}
catch ( InterruptedException e )
{
throw new AcquireLockTimeoutException( e, "Interrupted acquiring token." );
throw new AcquireLockTimeoutException( e, "Interrupted acquiring token.", Interrupted );
}

try
Expand All @@ -121,17 +123,18 @@ private synchronized int acquireTokenOrThrow()
}
else
{
throw new AcquireLockTimeoutException( "Failed to acquire lock token. Was taken by another candidate." );
throw new AcquireLockTimeoutException( "Failed to acquire lock token. Was taken by another candidate.",
NotALeader);
}
}
catch ( ExecutionException e )
{
throw new AcquireLockTimeoutException( e, "Failed to acquire lock token." );
throw new AcquireLockTimeoutException( e, "Failed to acquire lock token.", NotALeader );
}
catch ( InterruptedException e )
{
Thread.currentThread().interrupt();
throw new AcquireLockTimeoutException( e, "Failed to acquire lock token." );
throw new AcquireLockTimeoutException( e, "Failed to acquire lock token.", Interrupted );
}
}

Expand All @@ -145,12 +148,12 @@ private void ensureLeader()
}
catch ( NoLeaderFoundException e )
{
throw new AcquireLockTimeoutException( e, "Could not acquire lock token." );
throw new AcquireLockTimeoutException( e, "Could not acquire lock token.", NoLeaderAvailable );
}

if ( !leader.equals( myself ) )
{
throw new AcquireLockTimeoutException( LOCK_NOT_ON_LEADER_ERROR_MESSAGE );
throw new AcquireLockTimeoutException( LOCK_NOT_ON_LEADER_ERROR_MESSAGE, NotALeader );
}
}

Expand Down Expand Up @@ -195,7 +198,7 @@ private void ensureHoldingToken()
}
else if ( lockTokenId != lockTokenStateMachine.currentToken().id() )
{
throw new AcquireLockTimeoutException( "Local instance lost lock token." );
throw new AcquireLockTimeoutException( "Local instance lost lock token.", NotALeader );
}
}

Expand Down

0 comments on commit a08fc63

Please sign in to comment.