Skip to content

Commit

Permalink
Happy path: add and delete nodes and labels
Browse files Browse the repository at this point in the history
  • Loading branch information
fickludd authored and pontusmelke committed Nov 25, 2017
1 parent 028098b commit c15e069
Show file tree
Hide file tree
Showing 32 changed files with 446 additions and 139 deletions.
Expand Up @@ -35,8 +35,9 @@ public interface Write
/** /**
* Delete a node. * Delete a node.
* @param node the internal id of the node to delete * @param node the internal id of the node to delete
* @return returns true if it deleted a node or false if no node was found for this id
*/ */
void nodeDelete( long node ); boolean nodeDelete( long node );


/** /**
* Create a relationship between two nodes. * Create a relationship between two nodes.
Expand Down
Expand Up @@ -27,6 +27,7 @@
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.neo4j.graphdb.Label.label; import static org.neo4j.graphdb.Label.label;


Expand Down Expand Up @@ -69,6 +70,53 @@ public void shouldRollbackOnFailure() throws Exception
} }
} }


@Test
public void shouldRemoveNode() throws Exception
{
long node;
try ( org.neo4j.graphdb.Transaction tx = graphDb.beginTx() )
{
node = graphDb.createNode().getId();
tx.success();
}

try ( Transaction tx = session.beginTransaction() )
{
tx.dataWrite().nodeDelete( node );
tx.success();
}
try ( org.neo4j.graphdb.Transaction tx = graphDb.beginTx() )
{
try
{
graphDb.getNodeById( node );
fail( "Did not remove node" );
}
catch ( NotFoundException e )
{
// expected
}
}
}

@Test
public void shouldNotRemoveNodeThatDoesNotExist() throws Exception
{
long node = 0;

try ( Transaction tx = session.beginTransaction() )
{
assertFalse( tx.dataWrite().nodeDelete( node ) );
tx.failure();
}
try ( Transaction tx = session.beginTransaction() )
{
assertFalse( tx.dataWrite().nodeDelete( node ) );
tx.success();
}
// should not crash
}

@Test @Test
public void shouldAddLabelNode() throws Exception public void shouldAddLabelNode() throws Exception
{ {
Expand All @@ -85,9 +133,7 @@ public void shouldAddLabelNode() throws Exception


try ( org.neo4j.graphdb.Transaction ctx = graphDb.beginTx() ) try ( org.neo4j.graphdb.Transaction ctx = graphDb.beginTx() )
{ {
assertThat( assertThat( graphDb.getNodeById( node ).getLabels(), equalTo( Iterables.iterable( label( labelName ) ) ) );
graphDb.getNodeById( node ).getLabels(),
equalTo( Iterables.iterable( label( labelName ) ) ) );
} }
} }


Expand All @@ -113,9 +159,9 @@ public void shouldRemoveLabel() throws Exception


try ( org.neo4j.graphdb.Transaction ctx = graphDb.beginTx() ) try ( org.neo4j.graphdb.Transaction ctx = graphDb.beginTx() )
{ {
assertThat( assertThat( graphDb.getNodeById( nodeId ).getLabels(), equalTo( Iterables.empty() ) );
graphDb.getNodeById( nodeId ).getLabels(),
equalTo( Iterables.empty() ) );
} }
} }


} }
Expand Up @@ -83,6 +83,7 @@
import org.neo4j.kernel.impl.locking.ReentrantLockService; import org.neo4j.kernel.impl.locking.ReentrantLockService;
import org.neo4j.kernel.impl.locking.StatementLocksFactory; import org.neo4j.kernel.impl.locking.StatementLocksFactory;
import org.neo4j.kernel.impl.logging.LogService; import org.neo4j.kernel.impl.logging.LogService;
import org.neo4j.kernel.impl.newapi.Cursors;
import org.neo4j.kernel.impl.proc.Procedures; import org.neo4j.kernel.impl.proc.Procedures;
import org.neo4j.kernel.impl.storageengine.impl.recordstorage.RecordStorageEngine; import org.neo4j.kernel.impl.storageengine.impl.recordstorage.RecordStorageEngine;
import org.neo4j.kernel.impl.storageengine.impl.recordstorage.id.IdController; import org.neo4j.kernel.impl.storageengine.impl.recordstorage.id.IdController;
Expand Down Expand Up @@ -688,7 +689,7 @@ private NeoStoreKernelModule buildKernel( LogFiles logFiles, TransactionAppender
constraintIndexCreator, statementOperationParts, schemaWriteGuard, transactionHeaderInformationFactory, constraintIndexCreator, statementOperationParts, schemaWriteGuard, transactionHeaderInformationFactory,
transactionCommitProcess, indexConfigStore, explicitIndexProviderLookup, hooks, transactionMonitor, transactionCommitProcess, indexConfigStore, explicitIndexProviderLookup, hooks, transactionMonitor,
availabilityGuard, tracers, storageEngine, procedures, transactionIdStore, clock, availabilityGuard, tracers, storageEngine, procedures, transactionIdStore, clock,
cpuClock, heapAllocation, accessCapability ) ); cpuClock, heapAllocation, accessCapability, new Cursors() ) );


buildTransactionMonitor( kernelTransactions, clock, config ); buildTransactionMonitor( kernelTransactions, clock, config );


Expand Down
Expand Up @@ -63,6 +63,7 @@
import org.neo4j.kernel.impl.locking.LockTracer; import org.neo4j.kernel.impl.locking.LockTracer;
import org.neo4j.kernel.impl.locking.Locks; import org.neo4j.kernel.impl.locking.Locks;
import org.neo4j.kernel.impl.locking.StatementLocks; import org.neo4j.kernel.impl.locking.StatementLocks;
import org.neo4j.kernel.impl.newapi.Cursors;
import org.neo4j.kernel.impl.newapi.Operations; import org.neo4j.kernel.impl.newapi.Operations;
import org.neo4j.kernel.impl.proc.Procedures; import org.neo4j.kernel.impl.proc.Procedures;
import org.neo4j.kernel.impl.transaction.TransactionHeaderInformationFactory; import org.neo4j.kernel.impl.transaction.TransactionHeaderInformationFactory;
Expand Down Expand Up @@ -164,7 +165,7 @@ public KernelTransactionImplementation( StatementOperationParts statementOperati
TransactionMonitor transactionMonitor, Supplier<ExplicitIndexTransactionState> explicitIndexTxStateSupplier, TransactionMonitor transactionMonitor, Supplier<ExplicitIndexTransactionState> explicitIndexTxStateSupplier,
Pool<KernelTransactionImplementation> pool, Clock clock, CpuClock cpuClock, HeapAllocation heapAllocation, Pool<KernelTransactionImplementation> pool, Clock clock, CpuClock cpuClock, HeapAllocation heapAllocation,
TransactionTracer transactionTracer, LockTracer lockTracer, PageCursorTracerSupplier cursorTracerSupplier, TransactionTracer transactionTracer, LockTracer lockTracer, PageCursorTracerSupplier cursorTracerSupplier,
StorageEngine storageEngine, AccessCapability accessCapability ) StorageEngine storageEngine, AccessCapability accessCapability, Cursors cursors )
{ {
this.statementOperations = statementOperations; this.statementOperations = statementOperations;
this.schemaWriteGuard = schemaWriteGuard; this.schemaWriteGuard = schemaWriteGuard;
Expand All @@ -185,7 +186,7 @@ public KernelTransactionImplementation( StatementOperationParts statementOperati
procedures, accessCapability, lockTracer, statementOperations ); procedures, accessCapability, lockTracer, statementOperations );
this.statistics = new Statistics( this, cpuClock, heapAllocation ); this.statistics = new Statistics( this, cpuClock, heapAllocation );
this.userMetaData = new HashMap<>(); this.userMetaData = new HashMap<>();
this.operations = new Operations( storageEngine, storageStatement, this, explicitIndexTxStateSupplier ); this.operations = new Operations( storageEngine, storageStatement, this, explicitIndexTxStateSupplier, cursors );
} }


/** /**
Expand Down Expand Up @@ -684,7 +685,7 @@ public Read dataRead()
@Override @Override
public Write dataWrite() public Write dataWrite()
{ {
throw new UnsupportedOperationException( "not implemented" ); return operations;
} }


@Override @Override
Expand Down
Expand Up @@ -42,6 +42,7 @@
import org.neo4j.kernel.impl.index.IndexConfigStore; import org.neo4j.kernel.impl.index.IndexConfigStore;
import org.neo4j.kernel.impl.locking.StatementLocks; import org.neo4j.kernel.impl.locking.StatementLocks;
import org.neo4j.kernel.impl.locking.StatementLocksFactory; import org.neo4j.kernel.impl.locking.StatementLocksFactory;
import org.neo4j.kernel.impl.newapi.Cursors;
import org.neo4j.kernel.impl.proc.Procedures; import org.neo4j.kernel.impl.proc.Procedures;
import org.neo4j.kernel.impl.store.TransactionId; import org.neo4j.kernel.impl.store.TransactionId;
import org.neo4j.kernel.impl.transaction.TransactionHeaderInformationFactory; import org.neo4j.kernel.impl.transaction.TransactionHeaderInformationFactory;
Expand Down Expand Up @@ -88,6 +89,7 @@ public class KernelTransactions extends LifecycleAdapter implements Supplier<Ker
private final SystemNanoClock clock; private final SystemNanoClock clock;
private final ReentrantReadWriteLock newTransactionsLock = new ReentrantReadWriteLock(); private final ReentrantReadWriteLock newTransactionsLock = new ReentrantReadWriteLock();
private final MonotonicCounter userTransactionIdCounter = MonotonicCounter.newAtomicMonotonicCounter(); private final MonotonicCounter userTransactionIdCounter = MonotonicCounter.newAtomicMonotonicCounter();
private final Cursors cursors;


/** /**
* Used to enumerate all transactions in the system, active and idle ones. * Used to enumerate all transactions in the system, active and idle ones.
Expand Down Expand Up @@ -124,7 +126,7 @@ public KernelTransactions( StatementLocksFactory statementLocksFactory,
ExplicitIndexProviderLookup explicitIndexProviderLookup, TransactionHooks hooks, ExplicitIndexProviderLookup explicitIndexProviderLookup, TransactionHooks hooks,
TransactionMonitor transactionMonitor, AvailabilityGuard availabilityGuard, Tracers tracers, TransactionMonitor transactionMonitor, AvailabilityGuard availabilityGuard, Tracers tracers,
StorageEngine storageEngine, Procedures procedures, TransactionIdStore transactionIdStore, SystemNanoClock clock, StorageEngine storageEngine, Procedures procedures, TransactionIdStore transactionIdStore, SystemNanoClock clock,
CpuClock cpuClock, HeapAllocation heapAllocation, AccessCapability accessCapability ) CpuClock cpuClock, HeapAllocation heapAllocation, AccessCapability accessCapability, Cursors cursors )
{ {
this.statementLocksFactory = statementLocksFactory; this.statementLocksFactory = statementLocksFactory;
this.constraintIndexCreator = constraintIndexCreator; this.constraintIndexCreator = constraintIndexCreator;
Expand All @@ -146,6 +148,7 @@ public KernelTransactions( StatementLocksFactory statementLocksFactory,
new ExplicitIndexTransactionStateImpl( indexConfigStore, explicitIndexProviderLookup ) ); new ExplicitIndexTransactionStateImpl( indexConfigStore, explicitIndexProviderLookup ) );
this.clock = clock; this.clock = clock;
blockNewTransactions(); blockNewTransactions();
this.cursors = cursors;
} }


public Supplier<ExplicitIndexTransactionState> explicitIndexTxStateSupplier() public Supplier<ExplicitIndexTransactionState> explicitIndexTxStateSupplier()
Expand Down Expand Up @@ -332,7 +335,7 @@ public KernelTransactionImplementation newInstance()
constraintIndexCreator, procedures, transactionHeaderInformationFactory, constraintIndexCreator, procedures, transactionHeaderInformationFactory,
transactionCommitProcess, transactionMonitor, explicitIndexTxStateSupplier, localTxPool, transactionCommitProcess, transactionMonitor, explicitIndexTxStateSupplier, localTxPool,
clock, cpuClock, heapAllocation, tracers.transactionTracer, tracers.lockTracer, clock, cpuClock, heapAllocation, tracers.transactionTracer, tracers.lockTracer,
tracers.pageCursorTracerSupplier, storageEngine, accessCapability ); tracers.pageCursorTracerSupplier, storageEngine, accessCapability, cursors );
this.transactions.add( tx ); this.transactions.add( tx );
return tx; return tx;
} }
Expand Down
Expand Up @@ -312,4 +312,4 @@ private void ensureIndexExists( DataWriteOperations ops ) throws ExplicitIndexNo
indexCreated = true; indexCreated = true;
} }
} }
} }
Expand Up @@ -70,8 +70,10 @@ class AllStoreHolder extends Read implements Token


AllStoreHolder( StorageEngine engine, AllStoreHolder( StorageEngine engine,
StorageStatement statement, StorageStatement statement,
Supplier<ExplicitIndexTransactionState> explicitIndexes ) Supplier<ExplicitIndexTransactionState> explicitIndexes,
Cursors cursors )
{ {
super( cursors );
this.read = engine.storeReadLayer(); this.read = engine.storeReadLayer();
this.statement = statement; // use provided statement, to assert no leakage this.statement = statement; // use provided statement, to assert no leakage
this.explicitIndexes = Suppliers.lazySingleton( explicitIndexes ); this.explicitIndexes = Suppliers.lazySingleton( explicitIndexes );
Expand Down Expand Up @@ -238,11 +240,6 @@ RecordCursor<DynamicRecord> labelCursor()
return nodes.newLabelCursor(); return nodes.newLabelCursor();
} }


private static <R extends AbstractBaseRecord> RecordCursor<R> newCursor( RecordStore<R> store )
{
return store.newRecordCursor( store.newRecord() ).acquire( store.getNumberOfReservedLowIds(), NORMAL );
}

@Override @Override
void node( NodeRecord record, long reference, PageCursor pageCursor ) void node( NodeRecord record, long reference, PageCursor pageCursor )
{ {
Expand Down Expand Up @@ -294,4 +291,9 @@ ArrayValue array( PropertyCursor cursor, long reference, PageCursor page )
buffer.flip(); buffer.flip();
return PropertyUtil.readArrayFromBuffer( buffer ); return PropertyUtil.readArrayFromBuffer( buffer );
} }

public boolean nodeExists( long id )
{
return read.nodeExists( id );
}
} }
Expand Up @@ -19,66 +19,59 @@
*/ */
package org.neo4j.kernel.impl.newapi; package org.neo4j.kernel.impl.newapi;


class Cursors implements org.neo4j.internal.kernel.api.CursorFactory public class Cursors implements org.neo4j.internal.kernel.api.CursorFactory
{ {
private final Read read;

Cursors( Read read )
{
this.read = read;
}

@Override @Override
public NodeCursor allocateNodeCursor() public NodeCursor allocateNodeCursor()
{ {
return new NodeCursor( read ); return new NodeCursor( );
} }


@Override @Override
public RelationshipScanCursor allocateRelationshipScanCursor() public RelationshipScanCursor allocateRelationshipScanCursor()
{ {
return new RelationshipScanCursor( read ); return new RelationshipScanCursor( );
} }


@Override @Override
public RelationshipTraversalCursor allocateRelationshipTraversalCursor() public RelationshipTraversalCursor allocateRelationshipTraversalCursor()
{ {
return new RelationshipTraversalCursor( read ); return new RelationshipTraversalCursor( allocateRelationshipGroupCursor() );
} }


@Override @Override
public PropertyCursor allocatePropertyCursor() public PropertyCursor allocatePropertyCursor()
{ {
return new PropertyCursor( read ); return new PropertyCursor( );
} }


@Override @Override
public RelationshipGroupCursor allocateRelationshipGroupCursor() public RelationshipGroupCursor allocateRelationshipGroupCursor()
{ {
return new RelationshipGroupCursor( read ); return new RelationshipGroupCursor( );
} }


@Override @Override
public NodeValueIndexCursor allocateNodeValueIndexCursor() public NodeValueIndexCursor allocateNodeValueIndexCursor()
{ {
return new NodeValueIndexCursor( read ); return new NodeValueIndexCursor( );
} }


@Override @Override
public NodeLabelIndexCursor allocateNodeLabelIndexCursor() public NodeLabelIndexCursor allocateNodeLabelIndexCursor()
{ {
return new NodeLabelIndexCursor( read ); return new NodeLabelIndexCursor( );
} }


@Override @Override
public NodeExplicitIndexCursor allocateNodeManualIndexCursor() public NodeExplicitIndexCursor allocateNodeManualIndexCursor()
{ {
return new NodeExplicitIndexCursor( read ); return new NodeExplicitIndexCursor( );
} }


@Override @Override
public RelationshipExplicitIndexCursor allocateRelationshipManualIndexCursor() public RelationshipExplicitIndexCursor allocateRelationshipManualIndexCursor()
{ {
return new RelationshipExplicitIndexCursor( read ); return new RelationshipExplicitIndexCursor( );
} }
} }
Expand Up @@ -26,17 +26,17 @@


class KernelToken implements Token class KernelToken implements Token
{ {
private final StoreReadLayer read; private final StoreReadLayer store;


KernelToken( StorageEngine engine ) KernelToken( StorageEngine engine )
{ {
read = engine.storeReadLayer(); store = engine.storeReadLayer();
} }


@Override @Override
public int labelGetOrCreateForName( String labelName ) throws KernelException public int labelGetOrCreateForName( String labelName ) throws KernelException
{ {
throw new UnsupportedOperationException( "not implemented" ); return store.labelGetOrCreateForName( labelName );
} }


@Override @Override
Expand Down Expand Up @@ -72,18 +72,18 @@ public void relationshipTypeCreateForName( String relationshipTypeName, int id )
@Override @Override
public int nodeLabel( String name ) public int nodeLabel( String name )
{ {
return read.labelGetForName( name ); return store.labelGetForName( name );
} }


@Override @Override
public int relationshipType( String name ) public int relationshipType( String name )
{ {
return read.relationshipTypeGetForName( name ); return store.relationshipTypeGetForName( name );
} }


@Override @Override
public int propertyKey( String name ) public int propertyKey( String name )
{ {
return read.propertyKeyGetForName( name ); return store.propertyKeyGetForName( name );
} }
} }
Expand Up @@ -51,6 +51,11 @@ public NewKernel( StorageEngine engine, Supplier<ExplicitIndexTransactionState>
this.explicitIndexes = explicitIndexes; this.explicitIndexes = explicitIndexes;
this.kernel = kernel; this.kernel = kernel;
this.isRunning = false; this.isRunning = false;
this.cursors = new Cursors( );
// This extra statement will be remove once we start adding tx-state. That is because
// by then we cannot use a global Read in the CursorFactory, but need to use transaction
// specific Read instances which are given to the Cursors on initialization.
this.read = new AllStoreHolder( engine, engine.storeReadLayer().newStatement(), explicitIndexes, cursors );
} }


@Override @Override
Expand All @@ -69,14 +74,9 @@ public KernelSession beginSession( SecurityContext securityContext )


public void start() public void start()
{ {
// This extra statement will be remove once we start adding tx-state. That is because
// by then we cannot use a global Read in the CursorFactory, but need to use transaction
// specific Read instances which are given to the Cursors on initialization.
statement = engine.storeReadLayer().newStatement(); statement = engine.storeReadLayer().newStatement();
this.read = new AllStoreHolder( engine, statement, explicitIndexes ); this.cursors = new Cursors();
this.cursors = new Cursors( read );
isRunning = true; isRunning = true;

} }


public void stop() public void stop()
Expand Down

0 comments on commit c15e069

Please sign in to comment.