Skip to content

Commit

Permalink
Handle direct traversal of dense nodes.
Browse files Browse the repository at this point in the history
  • Loading branch information
pontusmelke authored and fickludd committed Nov 9, 2017
1 parent 9c77392 commit 8c55416
Showing 1 changed file with 93 additions and 2 deletions.
Expand Up @@ -23,17 +23,28 @@
import org.neo4j.io.pagecache.PageCursor;
import org.neo4j.kernel.impl.store.record.RelationshipRecord;

import static org.neo4j.kernel.impl.newapi.RelationshipTraversalCursor.GroupState.INCOMING;
import static org.neo4j.kernel.impl.newapi.RelationshipTraversalCursor.GroupState.LOOP;
import static org.neo4j.kernel.impl.newapi.RelationshipTraversalCursor.GroupState.NONE;
import static org.neo4j.kernel.impl.newapi.RelationshipTraversalCursor.GroupState.OUTGOING;

class RelationshipTraversalCursor extends RelationshipCursor
implements org.neo4j.internal.kernel.api.RelationshipTraversalCursor
{
enum GroupState { INCOMING, OUTGOING, LOOP, NONE };

private long originNodeReference;
private long next;
private Record buffer;
private PageCursor pageCursor;
private final RelationshipGroupCursor group;
private GroupState groupState;


RelationshipTraversalCursor( Read read )
{
super( read );
this.group = new RelationshipGroupCursor( read );
}

/*
Expand All @@ -56,16 +67,21 @@ void chain( long nodeReference, long reference )
pageCursor = read.relationshipPage( reference );
}
setId( NO_ID );
groupState = NONE;
originNodeReference = nodeReference;
next = reference;
}

/*
* Reference to a group record
*/
void groups( long nodeReference, long reference )
void groups( long nodeReference, long groupReference )
{
throw new UnsupportedOperationException( "not implemented" );
setId( NO_ID );
next = NO_ID;
groupState = INCOMING;
originNodeReference = nodeReference;
read.relationshipGroups( nodeReference, groupReference, group );
}

void filtered( long nodeReference, long reference )
Expand Down Expand Up @@ -120,6 +136,75 @@ public long originNodeReference()
@Override
public boolean next()
{
/*
Node(dense=true)
|
v
Group(:HOLDS) -incoming-> Rel(id=2) -> Rel(id=3)
-outgoing-> Rel(id=5) -> Rel(id=10) -> Rel(id=3)
-loop-> Rel(id=9)
|
v
Group(:USES) -incoming-> Rel(id=14)
-outgoing-> Rel(id=55) -> Rel(id=51) -> ...
-loop-> Rel(id=21) -> Rel(id=11)
|
v
...
*/
if ( traversingDenseNode() )
{
while ( next == NO_ID )
{
/*
Defines a small state machine, we start in state INCOMING.
1) fetch next group, if no more group stop.
2) set next to group.incomingReference, switch state to OUTGOING
3) Iterate relationship chain until we reach the end
4) set next to group.outgoingReference and state to LOOP
5) Iterate relationship chain until we reach the end
6) set next to group.loop and state back to INCOMING
7) Iterate relationship chain until we reach the end
8) GOTO 1
*/
switch ( groupState )
{
case INCOMING:
boolean hasNext = group.next();
if ( !hasNext )
{
reset();
return false;
}
next = group.incomingReference();
if ( pageCursor == null )
{
pageCursor = read.relationshipPage( Math.max( next, 0L ) );
}
groupState = OUTGOING;
break;

case OUTGOING:
next = group.outgoingReference();
groupState = LOOP;
break;

case LOOP:
next = group.loopsReference();
groupState = INCOMING;
break;

default:
throw new IllegalStateException( "We cannot get here, but checkstyle forces this!" );
}
}
}

if ( hasBufferedData() )
{ //We have buffered data, iterate the chain of buffered records
buffer = buffer.next;
Expand Down Expand Up @@ -163,6 +248,11 @@ else if ( target == originNodeReference )
return true;
}

private boolean traversingDenseNode()
{
return groupState != NONE;
}

@Override
public boolean shouldRetry()
{
Expand All @@ -183,6 +273,7 @@ public void close()
private void reset()
{
setId( next = NO_ID );
groupState = NONE;
buffer = null;
}

Expand Down

0 comments on commit 8c55416

Please sign in to comment.