Skip to content

Commit

Permalink
Refactor deferred locks to only defer where it is needed
Browse files Browse the repository at this point in the history
Change perspective from "defer all locks and bypass where it is needed" to
"only defer lock where we actually want to".

This allow us to confine the logic of deferred locking to
KernelStatement, KernelTransactionImplementation, LockingStatementOperations.

It also allows for more conscious decisions to use implicit (deferred)
or explicit (not deferred) locking even if you are not sure if client is
wrapped by a deferring layer or not.
  • Loading branch information
burqen authored and lutovich committed Jul 21, 2016
1 parent 512d414 commit 9597366
Show file tree
Hide file tree
Showing 29 changed files with 527 additions and 423 deletions.
Expand Up @@ -156,7 +156,7 @@ private void validateNoExistingNodeWithLabelAndProperty( KernelStatement state,
{
IndexDescriptor indexDescriptor = new IndexDescriptor( labelId, propertyKeyId );
assertIndexOnline( state, indexDescriptor );
state.locks().acquireExclusive( INDEX_ENTRY,
state.locks().implicit().acquireExclusive( INDEX_ENTRY,
indexEntryResourceId( labelId, propertyKeyId, ObjectUtil.toString( value ) ) );

long existing = entityReadOperations.nodeGetFromUniqueIndexSeek( state, indexDescriptor, value );
Expand Down Expand Up @@ -328,7 +328,7 @@ public long nodeGetFromUniqueIndexSeek(
}

// If we find the node - hold a shared lock. If we don't find a node - hold an exclusive lock.
Locks.Client locks = state.locks();
Locks.Client locks = state.locks().implicit();
long indexEntryId = indexEntryResourceId( labelId, propertyKeyId, stringVal );

locks.acquireShared( INDEX_ENTRY, indexEntryId );
Expand Down
Expand Up @@ -37,11 +37,11 @@
import org.neo4j.kernel.api.txstate.TransactionState;
import org.neo4j.kernel.api.txstate.TxStateHolder;
import org.neo4j.kernel.impl.api.store.StoreStatement;
import org.neo4j.kernel.impl.locking.Locks;
import org.neo4j.kernel.impl.locking.StatementLocks;

public class KernelStatement implements TxStateHolder, Statement
{
protected final Locks.Client locks;
protected final StatementLocks statementLocks;
protected final TxStateHolder txStateHolder;
protected final IndexReaderFactory indexReaderFactory;
protected final LabelScanStore labelScanStore;
Expand All @@ -53,11 +53,11 @@ public class KernelStatement implements TxStateHolder, Statement
private boolean closed;

public KernelStatement( KernelTransactionImplementation transaction, IndexReaderFactory indexReaderFactory,
LabelScanStore labelScanStore, TxStateHolder txStateHolder, Locks.Client locks,
LabelScanStore labelScanStore, TxStateHolder txStateHolder, StatementLocks statementLocks,
StatementOperationParts operations, StoreStatement storeStatement )
{
this.transaction = transaction;
this.locks = locks;
this.statementLocks = statementLocks;
this.indexReaderFactory = indexReaderFactory;
this.txStateHolder = txStateHolder;
this.labelScanStore = labelScanStore;
Expand Down Expand Up @@ -135,9 +135,9 @@ void assertOpen()
}
}

public Locks.Client locks()
public StatementLocks locks()
{
return locks;
return statementLocks;
}

public IndexReader getIndexReader( IndexDescriptor descriptor ) throws IndexNotFoundKernelException
Expand Down
Expand Up @@ -71,6 +71,10 @@
import org.neo4j.kernel.impl.index.IndexEntityType;
import org.neo4j.kernel.impl.locking.LockGroup;
import org.neo4j.kernel.impl.locking.Locks;
import org.neo4j.kernel.impl.locking.SimpleStatementLocks;
import org.neo4j.kernel.impl.locking.StatementLocks;
import org.neo4j.kernel.impl.locking.deferred.DeferringLockClient;
import org.neo4j.kernel.impl.locking.deferred.DeferringStatementLocks;
import org.neo4j.kernel.impl.store.NeoStores;
import org.neo4j.kernel.impl.store.SchemaStorage;
import org.neo4j.kernel.impl.store.record.IndexRule;
Expand Down Expand Up @@ -163,12 +167,13 @@ TransactionType upgradeToSchemaTransaction() throws InvalidTransactionTypeKernel
private final Collection<Command> extractedCommands = new ArrayCollection<>( 32 );
private final Locks locksManager;
private final boolean txTerminationAwareLocks;
private final boolean deferringLocks;
private TransactionState txState;
private LegacyIndexTransactionState legacyIndexTransactionState;
private TransactionType transactionType = TransactionType.ANY;
private TransactionHooks.TransactionHooksState hooksState;
private boolean beforeHookInvoked;
private Locks.Client locks;
private StatementLocks statementLocks;
private StoreStatement storeStatement;
private boolean closing, closed;
private boolean failure, success;
Expand Down Expand Up @@ -220,7 +225,8 @@ public KernelTransactionImplementation( StatementOperationParts operations,
TransactionTracer tracer,
ProcedureCache procedureCache,
NeoStoreTransactionContext context,
boolean txTerminationAwareLocks )
boolean txTerminationAwareLocks,
boolean deferringLocks )
{
this.operations = operations;
this.schemaWriteGuard = schemaWriteGuard;
Expand All @@ -231,6 +237,7 @@ public KernelTransactionImplementation( StatementOperationParts operations,
this.schemaState = schemaState;
this.locksManager = locks;
this.txTerminationAwareLocks = txTerminationAwareLocks;
this.deferringLocks = deferringLocks;
this.hooks = hooks;
this.constraintIndexCreator = constraintIndexCreator;
this.headerInformationFactory = headerInformationFactory;
Expand All @@ -252,7 +259,8 @@ public KernelTransactionImplementation( StatementOperationParts operations,
*/
public KernelTransactionImplementation initialize( long lastCommittedTx, long lastTimeStamp )
{
this.locks = locksManager.newClient();
this.statementLocks = deferringLocks ? new DeferringStatementLocks( locksManager.newClient() )
: new SimpleStatementLocks( locksManager.newClient() );
this.terminationReason = null;
this.closing = closed = failure = success = false;
this.transactionType = TransactionType.ANY;
Expand Down Expand Up @@ -317,9 +325,9 @@ public void markForTermination( Status reason )
{
failure = true;
terminationReason = reason;
if ( txTerminationAwareLocks && locks != null )
if ( txTerminationAwareLocks && statementLocks != null )
{
locks.stop();
statementLocks.stop();
}
transactionMonitor.transactionTerminated();
}
Expand All @@ -343,12 +351,17 @@ public KernelStatement acquireStatement()
if ( currentStatement == null )
{
currentStatement = new KernelStatement( this, new IndexReaderFactory.Caching( indexService ),
labelScanStore, this, locks, operations, storeStatement );
labelScanStore, this, statementLocks, operations, storeStatement );
}
currentStatement.acquire();
return currentStatement;
}

private Locks.Client deferringLocks( Locks.Client locks )
{
return new DeferringLockClient( locks );
}

public void releaseStatement( Statement statement )
{
assert currentStatement == statement;
Expand Down Expand Up @@ -520,6 +533,7 @@ public void close() throws TransactionFailureException
finally
{
release();
release();
}
}
}
Expand Down Expand Up @@ -557,12 +571,12 @@ private void failOnNonExplicitRollbackIfNeeded() throws TransactionFailureExcept

protected void dispose()
{
if ( locks != null )
if ( statementLocks != null )
{
locks.close();
statementLocks.close();
}

this.locks = null;
this.statementLocks = null;
this.transactionType = null;
this.hooksState = null;
this.txState = null;
Expand Down Expand Up @@ -600,8 +614,8 @@ private void commit() throws TransactionFailureException
}
}

locks.prepare();
context.init( locks.delegate() );
statementLocks.prepareForCommit();
context.init( statementLocks.explicit() );
prepareRecordChangesFromTransactionState();
}

Expand Down Expand Up @@ -635,7 +649,7 @@ private void commit() throws TransactionFailureException
headerInformation.getMasterId(),
headerInformation.getAuthorId(),
startTimeMillis, lastTransactionIdWhenStarted, clock.currentTimeMillis(),
locks.getLockSessionId() );
statementLocks.explicit().getLockSessionId() );

// Commit the transaction
commitProcess.commit( transactionRepresentation, lockGroup, commitEvent, INTERNAL );
Expand Down Expand Up @@ -751,8 +765,8 @@ private void release()
terminationReleaseLock.lock();
try
{
locks.close();
locks = null;
statementLocks.close();
statementLocks = null;
terminationReason = null;
pool.release( this );
if ( storeStatement != null )
Expand Down Expand Up @@ -1235,6 +1249,6 @@ public void registerCloseListener( CloseListener listener )
@Override
public String toString()
{
return "KernelTransaction[" + this.locks.getLockSessionId() + "]";
return "KernelTransaction[" + this.statementLocks.explicit().getLockSessionId() + "]";
}
}
Expand Up @@ -61,6 +61,7 @@

import static java.util.Collections.newSetFromMap;
import static org.neo4j.kernel.configuration.Settings.setting;
import static org.neo4j.kernel.impl.factory.GraphDatabaseFacadeFactory.Configuration.deferred_locking;

/**
* Central source of transactions in the database.
Expand All @@ -83,6 +84,7 @@ public class KernelTransactions extends LifecycleAdapter
private final NeoStores neoStores;
private final Locks locks;
private final boolean txTerminationAwareLocks;
private final boolean deferringLocks;
private final IntegrityValidator integrityValidator;
private final ConstraintIndexCreator constraintIndexCreator;
private final IndexingService indexingService;
Expand Down Expand Up @@ -144,6 +146,7 @@ public KernelTransactions( NeoStoreTransactionContextFactory neoStoreTransaction
this.neoStores = neoStores;
this.locks = locks;
this.txTerminationAwareLocks = config.get( tx_termination_aware_locks );
this.deferringLocks = config.get( deferred_locking );
this.integrityValidator = integrityValidator;
this.constraintIndexCreator = constraintIndexCreator;
this.indexingService = indexingService;
Expand Down Expand Up @@ -185,7 +188,7 @@ public KernelTransactionImplementation newInstance()
neoStores, locks, hooks, constraintIndexCreator, transactionHeaderInformationFactory,
transactionCommitProcess, transactionMonitor, storeLayer, legacyIndexTransactionState,
localTxPool, constraintSemantics, clock, tracers.transactionTracer, procedureCache,
context, txTerminationAwareLocks );
context, txTerminationAwareLocks, deferringLocks );
allTransactions.add( tx );

return tx;
Expand Down

0 comments on commit 9597366

Please sign in to comment.