Skip to content

Commit

Permalink
Remove DbmsOperations from KernelStatement
Browse files Browse the repository at this point in the history
- QueryTransactionalContext is extended with dbms operations
- DbmsOperations are made independent of the kernel transaction as a separate
dependency.
- A NonTransactionalDbmsOperations implementation is provided by
DataSourceModule.
- The context for dbms procedure calls are set up with only AuthSubject
(as AccessMode), and no kernel transaction. (This context could instead
be extended in the future with a new type of dbms transaction when needed.)
  • Loading branch information
henriknyman committed Mar 10, 2016
1 parent 6f6ddb4 commit 4a78781
Show file tree
Hide file tree
Showing 19 changed files with 129 additions and 116 deletions.
Expand Up @@ -230,8 +230,12 @@ class DelegatingQueryTransactionalContext(val inner: QueryTransactionalContext)


override type ReadOps = inner.ReadOps override type ReadOps = inner.ReadOps


override type DbmsOps = inner.DbmsOps

override def readOperations: ReadOps = inner.readOperations override def readOperations: ReadOps = inner.readOperations


override def dbmsOperations: DbmsOps = inner.dbmsOperations

override def commitAndRestartTx() { inner.commitAndRestartTx() } override def commitAndRestartTx() { inner.commitAndRestartTx() }


override def isTopLevelTx: Boolean = inner.isTopLevelTx override def isTopLevelTx: Boolean = inner.isTopLevelTx
Expand Down
Expand Up @@ -196,9 +196,12 @@ trait Operations[T <: PropertyContainer] {
trait QueryTransactionalContext { trait QueryTransactionalContext {


type ReadOps type ReadOps
type DbmsOps


def readOperations: ReadOps def readOperations: ReadOps


def dbmsOperations: DbmsOps

def isTopLevelTx: Boolean def isTopLevelTx: Boolean


def close(success: Boolean) def close(success: Boolean)
Expand Down
Expand Up @@ -138,7 +138,7 @@ class ExecutionEngine(val queryService: GraphDatabaseQueryService, logProvider:
val tc = externalTransactionalContext.provideContext() val tc = externalTransactionalContext.provideContext()


// Temporarily change access mode during query planning // Temporarily change access mode during query planning
val revertable = tc.restrict(AccessMode.Static.READ) val revertable = tc.restrictCurrentTransaction(AccessMode.Static.READ)


val ((plan: ExecutionPlan, extractedParameters), touched) = try { val ((plan: ExecutionPlan, extractedParameters), touched) = try {
// fetch plan cache // fetch plan cache
Expand Down
Expand Up @@ -25,13 +25,15 @@ import org.neo4j.kernel.GraphDatabaseQueryService
import org.neo4j.kernel.api.KernelTransaction.Revertable import org.neo4j.kernel.api.KernelTransaction.Revertable
import org.neo4j.kernel.api.security.AccessMode import org.neo4j.kernel.api.security.AccessMode
import org.neo4j.kernel.api.txstate.TxStateHolder import org.neo4j.kernel.api.txstate.TxStateHolder
import org.neo4j.kernel.api.{ReadOperations, Statement} import org.neo4j.kernel.api.{DbmsOperations, ReadOperations, Statement}
import org.neo4j.kernel.impl.query.TransactionalContext import org.neo4j.kernel.impl.query.TransactionalContext


case class TransactionalContextWrapper(tc: TransactionalContext) extends QueryTransactionalContext { case class TransactionalContextWrapper(tc: TransactionalContext) extends QueryTransactionalContext {


override type ReadOps = ReadOperations override type ReadOps = ReadOperations


override type DbmsOps = DbmsOperations

def provideContext(): TransactionalContextWrapper = TransactionalContextWrapper(tc.provideContext()) def provideContext(): TransactionalContextWrapper = TransactionalContextWrapper(tc.provideContext())


def isOpen: Boolean = tc.isOpen def isOpen: Boolean = tc.isOpen
Expand All @@ -49,11 +51,15 @@ case class TransactionalContextWrapper(tc: TransactionalContext) extends QueryTr


override def readOperations: ReadOperations = tc.readOperations() override def readOperations: ReadOperations = tc.readOperations()


override def dbmsOperations: DbmsOperations = tc.dbmsOperations()

override def commitAndRestartTx() { tc.commitAndRestartTx() } override def commitAndRestartTx() { tc.commitAndRestartTx() }


override def isTopLevelTx: Boolean = tc.isTopLevelTx override def isTopLevelTx: Boolean = tc.isTopLevelTx


override def close(success: Boolean) { tc.close(success) } override def close(success: Boolean) { tc.close(success) }


def restrict(accessMode: AccessMode): Revertable = tc.restrict(accessMode) def restrictCurrentTransaction(accessMode: AccessMode): Revertable = tc.restrictCurrentTransaction(accessMode)

def accessMode: AccessMode = tc.accessMode
} }
Expand Up @@ -554,7 +554,9 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional
callProcedure(name, args, transactionalContext.statement.dataWriteOperations().procedureCallWrite ) callProcedure(name, args, transactionalContext.statement.dataWriteOperations().procedureCallWrite )


override def callDbmsProcedure(name: ProcedureName, args: Seq[Any]) = override def callDbmsProcedure(name: ProcedureName, args: Seq[Any]) =
callProcedure(name, args, transactionalContext.statement.dbmsOperations().procedureCallDbms ) callProcedure(name, args,
(kn: proc.ProcedureSignature.ProcedureName, input: Array[AnyRef]) =>
transactionalContext.dbmsOperations.procedureCallDbms(kn, input, transactionalContext.accessMode))


private def callProcedure(name: ProcedureName, args: Seq[Any], private def callProcedure(name: ProcedureName, args: Seq[Any],
call: (proc.ProcedureSignature.ProcedureName, Array[AnyRef]) => RawIterator[Array[AnyRef], ProcedureException]) = { call: (proc.ProcedureSignature.ProcedureName, Array[AnyRef]) => RawIterator[Array[AnyRef], ProcedureException]) = {
Expand Down
Expand Up @@ -245,8 +245,8 @@ class LazyTest extends ExecutionEngineFunSuite {


val tx = fakeGraph.beginTransaction(KernelTransaction.Type.`implicit`, AccessMode.Static.FULL) val tx = fakeGraph.beginTransaction(KernelTransaction.Type.`implicit`, AccessMode.Static.FULL)
val context = new Neo4jTransactionalContext(service, tx, fakeStatement, new PropertyContainerLocker) val context = new Neo4jTransactionalContext(service, tx, fakeStatement, new PropertyContainerLocker)
val revertableRestrict = mock[Revertable] val revertable = mock[Revertable]
when(context.restrict(anyObject())).thenReturn(revertableRestrict) when(context.restrictCurrentTransaction(anyObject())).thenReturn(revertable)
val session = QueryEngineProvider.embeddedSession(context) val session = QueryEngineProvider.embeddedSession(context)


//When: //When:
Expand Down
Expand Up @@ -19,41 +19,10 @@
*/ */
package org.neo4j.kernel.api; package org.neo4j.kernel.api;


import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

import org.neo4j.collection.RawIterator; import org.neo4j.collection.RawIterator;
import org.neo4j.collection.primitive.PrimitiveIntIterator;
import org.neo4j.collection.primitive.PrimitiveLongIterator;
import org.neo4j.cursor.Cursor;
import org.neo4j.graphdb.Direction;
import org.neo4j.kernel.api.constraints.NodePropertyConstraint;
import org.neo4j.kernel.api.constraints.PropertyConstraint;
import org.neo4j.kernel.api.constraints.RelationshipPropertyConstraint;
import org.neo4j.kernel.api.exceptions.EntityNotFoundException;
import org.neo4j.kernel.api.exceptions.LabelNotFoundKernelException;
import org.neo4j.kernel.api.exceptions.ProcedureException; import org.neo4j.kernel.api.exceptions.ProcedureException;
import org.neo4j.kernel.api.exceptions.PropertyKeyIdNotFoundKernelException;
import org.neo4j.kernel.api.exceptions.RelationshipTypeIdNotFoundKernelException;
import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException;
import org.neo4j.kernel.api.exceptions.legacyindex.LegacyIndexNotFoundKernelException;
import org.neo4j.kernel.api.exceptions.schema.DuplicateIndexSchemaRuleException;
import org.neo4j.kernel.api.exceptions.schema.IndexBrokenKernelException;
import org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException;
import org.neo4j.kernel.api.index.IndexDescriptor;
import org.neo4j.kernel.api.index.InternalIndexState;
import org.neo4j.kernel.api.proc.CallableProcedure;
import org.neo4j.kernel.api.proc.ProcedureSignature; import org.neo4j.kernel.api.proc.ProcedureSignature;
import org.neo4j.kernel.impl.api.RelationshipVisitor; import org.neo4j.kernel.api.security.AccessMode;
import org.neo4j.kernel.impl.api.store.RelationshipIterator;
import org.neo4j.register.Register.DoubleLongRegister;
import org.neo4j.storageengine.api.NodeItem;
import org.neo4j.storageengine.api.RelationshipItem;
import org.neo4j.storageengine.api.Token;
import org.neo4j.storageengine.api.lock.ResourceType;
import org.neo4j.storageengine.api.schema.PopulationProgress;


/** /**
* Defines all types of system-oriented operations - i.e. those which do not read from or write to the graph - that can be done from the {@link KernelAPI}. * Defines all types of system-oriented operations - i.e. those which do not read from or write to the graph - that can be done from the {@link KernelAPI}.
Expand All @@ -66,9 +35,6 @@ public interface DbmsOperations
//================================================= //=================================================


/** Invoke a DBMS procedure by name */ /** Invoke a DBMS procedure by name */
RawIterator<Object[], ProcedureException> procedureCallDbms( ProcedureSignature.ProcedureName name, Object[] input ) throws ProcedureException; RawIterator<Object[],ProcedureException> procedureCallDbms( ProcedureSignature.ProcedureName name, Object[] input,

AccessMode accessMode ) throws ProcedureException;
//=================================================
//== AUTH OPERATIONS ==
//=================================================
} }
Expand Up @@ -58,9 +58,4 @@ public interface Statement extends Resource
* and it's of a different type, e.g {@link #dataWriteOperations()}. * and it's of a different type, e.g {@link #dataWriteOperations()}.
*/ */
SchemaWriteOperations schemaWriteOperations() throws InvalidTransactionTypeKernelException; SchemaWriteOperations schemaWriteOperations() throws InvalidTransactionTypeKernelException;

/**
* @return interface exposing all DBMS operations.
*/
DbmsOperations dbmsOperations();
} }
Expand Up @@ -26,6 +26,7 @@
import org.neo4j.kernel.api.KernelTransaction; import org.neo4j.kernel.api.KernelTransaction;
import org.neo4j.kernel.api.exceptions.ProcedureException; import org.neo4j.kernel.api.exceptions.ProcedureException;
import org.neo4j.kernel.api.exceptions.Status; import org.neo4j.kernel.api.exceptions.Status;
import org.neo4j.kernel.api.security.AccessMode;


public interface CallableProcedure public interface CallableProcedure
{ {
Expand All @@ -41,6 +42,7 @@ public interface CallableProcedure
interface Context interface Context
{ {
Key<KernelTransaction> KERNEL_TRANSACTION = Key.key( "KernelTransaction", KernelTransaction.class ); Key<KernelTransaction> KERNEL_TRANSACTION = Key.key( "KernelTransaction", KernelTransaction.class );
Key<AccessMode> ACCESS_MODE = Key.key( "AccessMode", AccessMode.class );


<T> T get( Key<T> key ) throws ProcedureException; <T> T get( Key<T> key ) throws ProcedureException;
} }
Expand Down
Expand Up @@ -54,7 +54,7 @@ public AlterUserPasswordProcedure( ProcedureName name )
@Override @Override
public RawIterator<Object[],ProcedureException> apply( Context ctx, Object[] input ) throws ProcedureException public RawIterator<Object[],ProcedureException> apply( Context ctx, Object[] input ) throws ProcedureException
{ {
AccessMode accessMode = ctx.get( Context.KERNEL_TRANSACTION ).mode(); AccessMode accessMode = ctx.get( Context.ACCESS_MODE );
if ( !(accessMode instanceof AuthSubject) ) if ( !(accessMode instanceof AuthSubject) )
{ {
throw new AuthorizationViolationException( "Invalid attempt to change the password" ); throw new AuthorizationViolationException( "Invalid attempt to change the password" );
Expand All @@ -69,7 +69,7 @@ public RawIterator<Object[],ProcedureException> apply( Context ctx, Object[] inp
catch ( IOException e ) catch ( IOException e )
{ {
throw new ProcedureException( Status.Security.Forbidden, e, throw new ProcedureException( Status.Security.Forbidden, e,
"The password was not able to be changed for the provided username"); "Failed to change the password for the provided username" );
} }
} }
} }
Expand Up @@ -22,7 +22,6 @@
import org.neo4j.graphdb.NotInTransactionException; import org.neo4j.graphdb.NotInTransactionException;
import org.neo4j.graphdb.TransactionTerminatedException; import org.neo4j.graphdb.TransactionTerminatedException;
import org.neo4j.graphdb.security.AuthorizationViolationException; import org.neo4j.graphdb.security.AuthorizationViolationException;
import org.neo4j.kernel.api.DbmsOperations;
import org.neo4j.kernel.api.DataWriteOperations; import org.neo4j.kernel.api.DataWriteOperations;
import org.neo4j.kernel.api.ReadOperations; import org.neo4j.kernel.api.ReadOperations;
import org.neo4j.kernel.api.SchemaWriteOperations; import org.neo4j.kernel.api.SchemaWriteOperations;
Expand Down Expand Up @@ -117,12 +116,6 @@ public SchemaWriteOperations schemaWriteOperations()
return facade; return facade;
} }


@Override
public DbmsOperations dbmsOperations()
{
return facade;
}

@Override @Override
public TransactionState txState() public TransactionState txState()
{ {
Expand Down
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2002-2016 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.kernel.impl.api;

import org.neo4j.collection.RawIterator;
import org.neo4j.kernel.api.DbmsOperations;
import org.neo4j.kernel.api.exceptions.ProcedureException;
import org.neo4j.kernel.api.proc.CallableProcedure;
import org.neo4j.kernel.api.proc.ProcedureSignature;
import org.neo4j.kernel.api.security.AccessMode;
import org.neo4j.kernel.impl.proc.Procedures;

public class NonTransactionalDbmsOperations implements DbmsOperations
{

private final Procedures procedures;

public NonTransactionalDbmsOperations( Procedures procedures )
{
this.procedures = procedures;
}

@Override
public RawIterator<Object[],ProcedureException> procedureCallDbms( ProcedureSignature.ProcedureName name,
Object[] input, AccessMode accessMode ) throws ProcedureException
{
CallableProcedure.BasicContext ctx = new CallableProcedure.BasicContext();
ctx.put( CallableProcedure.Context.ACCESS_MODE, accessMode );
return procedures.call( ctx, name, input );
}

}
Expand Up @@ -31,7 +31,6 @@
import org.neo4j.cursor.Cursor; import org.neo4j.cursor.Cursor;
import org.neo4j.graphdb.Direction; import org.neo4j.graphdb.Direction;
import org.neo4j.kernel.api.security.AccessMode; import org.neo4j.kernel.api.security.AccessMode;
import org.neo4j.kernel.api.DbmsOperations;
import org.neo4j.kernel.api.DataWriteOperations; import org.neo4j.kernel.api.DataWriteOperations;
import org.neo4j.kernel.api.KernelTransaction; import org.neo4j.kernel.api.KernelTransaction;
import org.neo4j.kernel.api.LegacyIndexHits; import org.neo4j.kernel.api.LegacyIndexHits;
Expand Down Expand Up @@ -91,7 +90,7 @@
import org.neo4j.storageengine.api.lock.ResourceType; import org.neo4j.storageengine.api.lock.ResourceType;
import org.neo4j.storageengine.api.schema.PopulationProgress; import org.neo4j.storageengine.api.schema.PopulationProgress;


public class OperationsFacade implements ReadOperations, DataWriteOperations, SchemaWriteOperations, DbmsOperations public class OperationsFacade implements ReadOperations, DataWriteOperations, SchemaWriteOperations
{ {
private final KernelTransaction tx; private final KernelTransaction tx;
private final KernelStatement statement; private final KernelStatement statement;
Expand Down Expand Up @@ -1099,21 +1098,6 @@ public void uniqueIndexDrop( IndexDescriptor descriptor ) throws DropIndexFailur


// </SchemaWrite> // </SchemaWrite>


// <DBMS>

@Override
public RawIterator<Object[],ProcedureException> procedureCallDbms( ProcedureName name,
Object[] input ) throws ProcedureException
{
statement.assertOpen();

CallableProcedure.BasicContext ctx = new CallableProcedure.BasicContext();
ctx.put( CallableProcedure.Context.KERNEL_TRANSACTION, tx );
return procedures.call( ctx, name, input );
}

// </DBMS>

// <Locking> // <Locking>
@Override @Override
public void acquireExclusive( ResourceType type, long id ) public void acquireExclusive( ResourceType type, long id )
Expand Down
Expand Up @@ -36,13 +36,15 @@
import org.neo4j.kernel.AvailabilityGuard; import org.neo4j.kernel.AvailabilityGuard;
import org.neo4j.kernel.DatabaseAvailability; import org.neo4j.kernel.DatabaseAvailability;
import org.neo4j.kernel.NeoStoreDataSource; import org.neo4j.kernel.NeoStoreDataSource;
import org.neo4j.kernel.api.DbmsOperations;
import org.neo4j.kernel.api.KernelAPI; import org.neo4j.kernel.api.KernelAPI;
import org.neo4j.kernel.api.KernelTransaction; import org.neo4j.kernel.api.KernelTransaction;
import org.neo4j.kernel.api.Statement; import org.neo4j.kernel.api.Statement;
import org.neo4j.kernel.api.legacyindex.AutoIndexing; import org.neo4j.kernel.api.legacyindex.AutoIndexing;
import org.neo4j.kernel.builtinprocs.BuiltInProcedures; import org.neo4j.kernel.builtinprocs.BuiltInProcedures;
import org.neo4j.kernel.configuration.Config; import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.guard.Guard; import org.neo4j.kernel.guard.Guard;
import org.neo4j.kernel.impl.api.NonTransactionalDbmsOperations;
import org.neo4j.kernel.impl.api.NonTransactionalTokenNameLookup; import org.neo4j.kernel.impl.api.NonTransactionalTokenNameLookup;
import org.neo4j.kernel.impl.api.SchemaWriteGuard; import org.neo4j.kernel.impl.api.SchemaWriteGuard;
import org.neo4j.kernel.impl.api.index.IndexingService; import org.neo4j.kernel.impl.api.index.IndexingService;
Expand Down Expand Up @@ -165,6 +167,9 @@ public DataSourceModule( final GraphDatabaseFacadeFactory.Dependencies dependenc
this.queryExecutor = queryExecutor::get; this.queryExecutor = queryExecutor::get;
Procedures procedures = setupProcedures( platformModule, editionModule.coreAPIAvailabilityGuard ); Procedures procedures = setupProcedures( platformModule, editionModule.coreAPIAvailabilityGuard );


DbmsOperations dbmsOperations = new NonTransactionalDbmsOperations( procedures );
deps.satisfyDependency( dbmsOperations );

NonTransactionalTokenNameLookup tokenNameLookup = new NonTransactionalTokenNameLookup( NonTransactionalTokenNameLookup tokenNameLookup = new NonTransactionalTokenNameLookup(
editionModule.labelTokenHolder, editionModule.labelTokenHolder,
editionModule.relationshipTypeTokenHolder, editionModule.relationshipTypeTokenHolder,
Expand Down
Expand Up @@ -22,6 +22,7 @@
import org.neo4j.graphdb.Lock; import org.neo4j.graphdb.Lock;
import org.neo4j.graphdb.PropertyContainer; import org.neo4j.graphdb.PropertyContainer;
import org.neo4j.kernel.GraphDatabaseQueryService; import org.neo4j.kernel.GraphDatabaseQueryService;
import org.neo4j.kernel.api.DbmsOperations;
import org.neo4j.kernel.api.KernelTransaction; import org.neo4j.kernel.api.KernelTransaction;
import org.neo4j.kernel.api.ReadOperations; import org.neo4j.kernel.api.ReadOperations;
import org.neo4j.kernel.api.Statement; import org.neo4j.kernel.api.Statement;
Expand All @@ -38,6 +39,7 @@ public class Neo4jTransactionalContext implements TransactionalContext
private final ThreadToStatementContextBridge txBridge; private final ThreadToStatementContextBridge txBridge;
private final KernelTransaction.Type transactionType; private final KernelTransaction.Type transactionType;
private final AccessMode mode; private final AccessMode mode;
private final DbmsOperations dbmsOperations;


private InternalTransaction transaction; private InternalTransaction transaction;
private Statement statement; private Statement statement;
Expand All @@ -55,6 +57,7 @@ public Neo4jTransactionalContext( GraphDatabaseQueryService graph, InternalTrans
this.statement = initialStatement; this.statement = initialStatement;
this.locker = locker; this.locker = locker;
this.txBridge = graph.getDependencyResolver().resolveDependency( ThreadToStatementContextBridge.class ); this.txBridge = graph.getDependencyResolver().resolveDependency( ThreadToStatementContextBridge.class );
this.dbmsOperations = graph.getDependencyResolver().resolveDependency( DbmsOperations.class );
} }


@Override @Override
Expand All @@ -63,6 +66,12 @@ public ReadOperations readOperations()
return statement.readOperations(); return statement.readOperations();
} }


@Override
public DbmsOperations dbmsOperations()
{
return dbmsOperations;
}

@Override @Override
public boolean isTopLevelTx() public boolean isTopLevelTx()
{ {
Expand Down Expand Up @@ -163,8 +172,14 @@ public Lock acquireWriteLock( PropertyContainer p )
} }


@Override @Override
public KernelTransaction.Revertable restrict( AccessMode accessMode ) public KernelTransaction.Revertable restrictCurrentTransaction( AccessMode accessMode )
{ {
return transaction.restrict( accessMode ); return transaction.restrict( accessMode );
} }

@Override
public AccessMode accessMode()
{
return mode;
}
} }

0 comments on commit 4a78781

Please sign in to comment.