Skip to content

Commit

Permalink
TxState aware relationship traversal of non-dense node
Browse files Browse the repository at this point in the history
  • Loading branch information
fickludd committed Jan 23, 2018
1 parent 0cea7cc commit 573c5a3
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 37 deletions.
Expand Up @@ -93,4 +93,98 @@ public void shouldNotSeeSingleRelationshipWhichWasDeletedInTransaction() throws
tx.success(); tx.success();
} }
} }

@Test
public void shouldSeeRelationshipInTransaction() throws Exception
{
long n1, n2;
try ( Transaction tx = session.beginTransaction() )
{
n1 = tx.dataWrite().nodeCreate();
n2 = tx.dataWrite().nodeCreate();
tx.success();
}

try ( Transaction tx = session.beginTransaction() )
{
int label = tx.tokenWrite().relationshipTypeGetOrCreateForName( "R" );
long r = tx.dataWrite().relationshipCreate( n1, label, n2 );
try ( NodeCursor node = cursors.allocateNodeCursor();
RelationshipTraversalCursor relationship = cursors.allocateRelationshipTraversalCursor() )
{
tx.dataRead().singleNode( n1, node );
assertTrue( "should access node", node.next() );

node.allRelationships( relationship );
assertTrue( "should find relationship", relationship.next() );
assertEquals( r, relationship.relationshipReference() );

assertFalse( "should only find one relationship", relationship.next() );
}
tx.success();
}
}

@Test
public void shouldNotSeeRelationshipDeletedInTransaction() throws Exception
{
long n1, n2, r;
try ( Transaction tx = session.beginTransaction() )
{
n1 = tx.dataWrite().nodeCreate();
n2 = tx.dataWrite().nodeCreate();

int label = tx.tokenWrite().relationshipTypeGetOrCreateForName( "R" );
r = tx.dataWrite().relationshipCreate( n1, label, n2 );

tx.success();
}

try ( Transaction tx = session.beginTransaction() )
{
tx.dataWrite().relationshipDelete( r );
try ( NodeCursor node = cursors.allocateNodeCursor();
RelationshipTraversalCursor relationship = cursors.allocateRelationshipTraversalCursor() )
{
tx.dataRead().singleNode( n1, node );
assertTrue( "should access node", node.next() );

node.allRelationships( relationship );
assertFalse( "should not find relationship", relationship.next() );
}
tx.success();
}
}

@Test
public void shouldSeeRelationshipInTransactionBeforeCursorInitialization() throws Exception
{
long n1, n2;
try ( Transaction tx = session.beginTransaction() )
{
n1 = tx.dataWrite().nodeCreate();
n2 = tx.dataWrite().nodeCreate();
tx.success();
}

try ( Transaction tx = session.beginTransaction() )
{
int label = tx.tokenWrite().relationshipTypeGetOrCreateForName( "R" );
long r = tx.dataWrite().relationshipCreate( n1, label, n2 );
try ( NodeCursor node = cursors.allocateNodeCursor();
RelationshipTraversalCursor relationship = cursors.allocateRelationshipTraversalCursor() )
{
tx.dataRead().singleNode( n1, node );
assertTrue( "should access node", node.next() );

node.allRelationships( relationship );
assertTrue( "should find relationship", relationship.next() );
assertEquals( r, relationship.relationshipReference() );

tx.dataWrite().relationshipCreate( n1, label, n2 ); // should not be seen
assertFalse( "should not find relationship added after cursor init", relationship.next() );
}
tx.success();
}
}
} }
Expand Up @@ -697,7 +697,7 @@ public Cursor<RelationshipItem> augmentNodeRelationshipCursor( Cursor<Relationsh
NodeState nodeState, NodeState nodeState,
Direction direction ) Direction direction )
{ {
return nodeState.hasPropertyChanges() || nodeState.hasRelationshipChanges() return nodeState.hasRelationshipChanges()
? iteratorRelationshipCursor.get().init( cursor, nodeState.getAddedRelationships( direction ) ) ? iteratorRelationshipCursor.get().init( cursor, nodeState.getAddedRelationships( direction ) )
: cursor; : cursor;
} }
Expand All @@ -707,7 +707,7 @@ public Cursor<RelationshipItem> augmentNodeRelationshipCursor( Cursor<Relationsh
Direction direction, Direction direction,
int[] relTypes ) int[] relTypes )
{ {
return nodeState.hasPropertyChanges() || nodeState.hasRelationshipChanges() return nodeState.hasRelationshipChanges()
? iteratorRelationshipCursor.get().init( cursor, nodeState.getAddedRelationships( direction, relTypes ) ) ? iteratorRelationshipCursor.get().init( cursor, nodeState.getAddedRelationships( direction, relTypes ) )
: cursor; : cursor;
} }
Expand Down
Expand Up @@ -176,10 +176,11 @@ public boolean next()
reset(); reset();
return false; return false;
} }

// Check tx state // Check tx state
boolean hasChanges = hasChanges(); boolean hasChanges = hasChanges();

TransactionState txs = hasChanges ? read.txState() : null; TransactionState txs = hasChanges ? read.txState() : null;

do do
{ {
if ( hasChanges && containsNode( txs ) ) if ( hasChanges && containsNode( txs ) )
Expand Down
Expand Up @@ -252,7 +252,7 @@ else if ( hasDirectFlag( reference ) ) // the relationships for this node are no
public final void relationships( public final void relationships(
long nodeReference, long reference, org.neo4j.internal.kernel.api.RelationshipTraversalCursor cursor ) long nodeReference, long reference, org.neo4j.internal.kernel.api.RelationshipTraversalCursor cursor )
{ {
/* TODO: There are actually five (5!) different ways a relationship traversal cursor can be initialized: /* There are 5 different ways a relationship traversal cursor can be initialized:
* *
* 1. From a batched group in a detached way. This happens when the user manually retrieves the relationships * 1. From a batched group in a detached way. This happens when the user manually retrieves the relationships
* references from the group cursor and passes it to this method and if the group cursor was based on having * references from the group cursor and passes it to this method and if the group cursor was based on having
Expand Down Expand Up @@ -282,7 +282,8 @@ public final void relationships(
ktx.assertOpen(); ktx.assertOpen();
if ( reference == NO_ID ) // there are no relationships for this node if ( reference == NO_ID ) // there are no relationships for this node
{ {
cursor.close(); // still initiate cursor in case there are tx-state additions
((RelationshipTraversalCursor) cursor).chain( nodeReference, reference, this );
} }
else if ( hasGroupFlag( reference ) ) // this reference is actually to a group record else if ( hasGroupFlag( reference ) ) // this reference is actually to a group record
{ {
Expand Down
Expand Up @@ -19,19 +19,14 @@
*/ */
package org.neo4j.kernel.impl.newapi; package org.neo4j.kernel.impl.newapi;


import java.util.Set;

import org.neo4j.internal.kernel.api.RelationshipDataAccessor; import org.neo4j.internal.kernel.api.RelationshipDataAccessor;
import org.neo4j.kernel.impl.api.RelationshipVisitor; import org.neo4j.kernel.impl.api.RelationshipVisitor;
import org.neo4j.kernel.impl.store.record.RelationshipRecord; import org.neo4j.kernel.impl.store.record.RelationshipRecord;


import static java.util.Collections.emptySet;

abstract class RelationshipCursor extends RelationshipRecord implements RelationshipDataAccessor, RelationshipVisitor<RuntimeException> abstract class RelationshipCursor extends RelationshipRecord implements RelationshipDataAccessor, RelationshipVisitor<RuntimeException>
{ {
Read read; Read read;
private HasChanges hasChanges = HasChanges.MAYBE; private HasChanges hasChanges = HasChanges.MAYBE;
Set<Long> addedRelationships;


RelationshipCursor() RelationshipCursor()
{ {
Expand All @@ -42,7 +37,6 @@ protected void init( Read read )
{ {
this.read = read; this.read = read;
this.hasChanges = HasChanges.MAYBE; this.hasChanges = HasChanges.MAYBE;
this.addedRelationships = emptySet();
} }


@Override @Override
Expand Down Expand Up @@ -99,7 +93,7 @@ public long propertiesReference()
return getNextProp(); return getNextProp();
} }


protected abstract boolean shouldGetAddedTxStateSnapshot(); protected abstract void collectAddedTxStateSnapshot();


/** /**
* RelationshipCursor should only see changes that are there from the beginning * RelationshipCursor should only see changes that are there from the beginning
Expand All @@ -113,10 +107,7 @@ protected boolean hasChanges()
boolean changes = read.hasTxStateWithChanges(); boolean changes = read.hasTxStateWithChanges();
if ( changes ) if ( changes )
{ {
if ( shouldGetAddedTxStateSnapshot() ) collectAddedTxStateSnapshot();
{
addedRelationships = read.txState().addedAndRemovedRelationships().getAddedSnapshot();
}
hasChanges = HasChanges.YES; hasChanges = HasChanges.YES;
} }
else else
Expand Down
Expand Up @@ -19,15 +19,20 @@
*/ */
package org.neo4j.kernel.impl.newapi; package org.neo4j.kernel.impl.newapi;


import java.util.Set;

import org.neo4j.io.pagecache.PageCursor; import org.neo4j.io.pagecache.PageCursor;
import org.neo4j.kernel.api.txstate.TransactionState; import org.neo4j.kernel.api.txstate.TransactionState;


import static java.util.Collections.emptySet;

class RelationshipScanCursor extends RelationshipCursor implements org.neo4j.internal.kernel.api.RelationshipScanCursor class RelationshipScanCursor extends RelationshipCursor implements org.neo4j.internal.kernel.api.RelationshipScanCursor
{ {
private int label; private int label;
private long next; private long next;
private long highMark; private long highMark;
private PageCursor pageCursor; private PageCursor pageCursor;
Set<Long> addedRelationships;


void scan( int label, Read read ) void scan( int label, Read read )
{ {
Expand All @@ -43,6 +48,7 @@ void scan( int label, Read read )
this.label = label; this.label = label;
highMark = read.relationshipHighMark(); highMark = read.relationshipHighMark();
init( read ); init( read );
this.addedRelationships = emptySet();
} }


void single( long reference, Read read ) void single( long reference, Read read )
Expand All @@ -59,6 +65,7 @@ void single( long reference, Read read )
label = -1; label = -1;
highMark = NO_ID; highMark = NO_ID;
init( read ); init( read );
this.addedRelationships = emptySet();
} }


@Override @Override
Expand Down Expand Up @@ -172,8 +179,11 @@ private boolean isSingle()
return highMark == NO_ID; return highMark == NO_ID;
} }


protected boolean shouldGetAddedTxStateSnapshot() protected void collectAddedTxStateSnapshot()
{ {
return !isSingle(); if ( !isSingle() )
{
addedRelationships = read.txState().addedAndRemovedRelationships().getAddedSnapshot();
}
} }
} }

0 comments on commit 573c5a3

Please sign in to comment.