From 9befc4328f3e556babb09408c896cfb0a14de055 Mon Sep 17 00:00:00 2001 From: fickludd Date: Thu, 25 Jan 2018 15:55:07 +0100 Subject: [PATCH] Migrate Core API NodeProxy.getRelationships impl to Kernel API --- .../org/neo4j/kernel/impl/core/NodeProxy.java | 54 ++++++---------- .../impl/core/RelationshipConversion.java | 61 +++++++++++++------ .../impl/core/RelationshipConversionTest.java | 58 ++++++------------ 3 files changed, 83 insertions(+), 90 deletions(-) diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/core/NodeProxy.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/core/NodeProxy.java index e21e45346f1f2..0bb3271f1db3c 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/core/NodeProxy.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/core/NodeProxy.java @@ -42,6 +42,7 @@ import org.neo4j.internal.kernel.api.LabelSet; import org.neo4j.internal.kernel.api.NodeCursor; import org.neo4j.internal.kernel.api.PropertyCursor; +import org.neo4j.internal.kernel.api.RelationshipTraversalCursor; import org.neo4j.internal.kernel.api.TokenRead; import org.neo4j.internal.kernel.api.exceptions.InvalidTransactionTypeKernelException; import org.neo4j.internal.kernel.api.exceptions.KernelException; @@ -125,30 +126,9 @@ public ResourceIterable getRelationships() } @Override - public ResourceIterable getRelationships( final Direction dir ) + public ResourceIterable getRelationships( final Direction direction ) { - assertInUnterminatedTransaction(); - return () -> - { - Statement statement = spi.statement(); - try - { - RelationshipConversion result = new RelationshipConversion( spi ); - result.iterator = statement.readOperations().nodeGetRelationships( nodeId, dir ); - result.statement = statement; - return result; - } - catch ( EntityNotFoundException e ) - { - statement.close(); - throw new NotFoundException( format( "Node %d not found", nodeId ), e ); - } - catch ( Throwable e ) - { - statement.close(); - throw e; - } - }; + return innerGetRelationships( direction, null ); } @Override @@ -171,25 +151,31 @@ public ResourceIterable getRelationships( final Direction directio { typeIds = relTypeIds( types, statement ); } + return innerGetRelationships( direction, typeIds ); + } + + private ResourceIterable innerGetRelationships( final Direction direction, int[] typeIds ) + { + assertInUnterminatedTransaction(); return () -> { - Statement statement = spi.statement(); - try + KernelTransaction transaction = safeAcquireTransaction(); + NodeCursor node = transaction.nodeCursor(); + transaction.dataRead().singleNode( getId(), node ); + if ( !node.next() ) { - RelationshipConversion result = new RelationshipConversion( spi ); - result.iterator = statement.readOperations().nodeGetRelationships( - nodeId, direction, typeIds ); - result.statement = statement; - return result; + throw new NotFoundException( format( "Node %d not found", nodeId ) ); } - catch ( EntityNotFoundException e ) + + RelationshipTraversalCursor relationship = transaction.cursors().allocateRelationshipTraversalCursor(); + try { - statement.close(); - throw new NotFoundException( format( "Node %d not found", nodeId ), e ); + node.allRelationships( relationship ); + return new RelationshipConversion( spi, relationship, direction, typeIds ); } catch ( Throwable e ) { - statement.close(); + relationship.close(); throw e; } }; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/core/RelationshipConversion.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/core/RelationshipConversion.java index 7a5fbe3df281c..acd994f913c8b 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/core/RelationshipConversion.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/core/RelationshipConversion.java @@ -19,42 +19,68 @@ */ package org.neo4j.kernel.impl.core; +import org.apache.commons.lang3.ArrayUtils; + import java.util.NoSuchElementException; +import org.neo4j.graphdb.Direction; import org.neo4j.graphdb.Relationship; import org.neo4j.graphdb.ResourceIterator; -import org.neo4j.kernel.api.Statement; -import org.neo4j.kernel.impl.api.RelationshipVisitor; -import org.neo4j.kernel.impl.api.store.RelationshipIterator; +import org.neo4j.internal.kernel.api.RelationshipTraversalCursor; -public class RelationshipConversion implements RelationshipVisitor, ResourceIterator +public class RelationshipConversion implements ResourceIterator { private final EmbeddedProxySPI actions; - RelationshipIterator iterator; - Statement statement; + private final RelationshipTraversalCursor cursor; + private final Direction direction; + private final int[] typeIds; private Relationship next; private boolean closed; - public RelationshipConversion( EmbeddedProxySPI actions ) + public RelationshipConversion( + EmbeddedProxySPI actions, + RelationshipTraversalCursor cursor, + Direction direction, + int[] typeIds) { this.actions = actions; - } - - @Override - public void visit( long relId, int type, long startNode, long endNode ) throws RuntimeException - { - next = actions.newRelationshipProxy( relId, startNode, type, endNode ); + this.cursor = cursor; + this.direction = direction; + this.typeIds = typeIds; } @Override public boolean hasNext() { - boolean hasNext = iterator.hasNext(); - if ( !hasNext ) + if ( next == null && !closed ) { + while ( cursor.next() ) + { + if ( correctDirection() && correctType() ) + { + next = actions.newRelationshipProxy( + cursor.relationshipReference(), + cursor.sourceNodeReference(), + cursor.label(), + cursor.targetNodeReference() ); + return true; + } + } close(); } - return hasNext; + return next != null; + } + + private boolean correctDirection() + { + return direction == Direction.BOTH || + (direction == Direction.OUTGOING && cursor.originNodeReference() == cursor.sourceNodeReference()) || + (direction == Direction.INCOMING && cursor.originNodeReference() == cursor.targetNodeReference()); + } + + private boolean correctType() + { + return typeIds == null || ArrayUtils.contains( typeIds, cursor.label() ); } @Override @@ -64,7 +90,6 @@ public Relationship next() { throw new NoSuchElementException(); } - iterator.relationshipVisit( iterator.next(), this ); Relationship current = next; next = null; return current; @@ -81,7 +106,7 @@ public void close() { if ( !closed ) { - statement.close(); + cursor.close(); closed = true; } } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/core/RelationshipConversionTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/core/RelationshipConversionTest.java index 331ce023bba73..f96eb9ae17b11 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/core/RelationshipConversionTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/core/RelationshipConversionTest.java @@ -22,59 +22,66 @@ import org.junit.Before; import org.junit.Test; -import org.neo4j.kernel.api.Statement; -import org.neo4j.kernel.impl.api.RelationshipVisitor; -import org.neo4j.kernel.impl.api.store.RelationshipIterator; +import org.neo4j.graphdb.Direction; +import org.neo4j.internal.kernel.api.RelationshipTraversalCursor; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; public class RelationshipConversionTest { private EmbeddedProxySPI nodeActions = mock( EmbeddedProxySPI.class ); - private Statement statement = mock( Statement.class ); private RelationshipConversion relationshipConversion; + private RelationshipTraversalCursor cursor; @Before public void setUp() { - relationshipConversion = new RelationshipConversion( nodeActions ); - relationshipConversion.statement = statement; + when( nodeActions.newRelationshipProxy( anyLong(), anyLong(), anyInt(), anyLong() ) ) + .thenReturn( new RelationshipProxy( null, 1 ) ); + + cursor = mock( RelationshipTraversalCursor.class ); + relationshipConversion = new RelationshipConversion( nodeActions, cursor, Direction.BOTH, null ); } @Test public void closeStatementOnClose() throws Exception { + when( cursor.next() ).thenReturn( false ); + relationshipConversion.close(); - verify( statement ).close(); + verify( cursor ).close(); } @Test public void closeStatementWhenIterationIsOver() { - relationshipConversion.iterator = new ArrayRelationshipVisitor( new long[]{1L, 8L} ); + when( cursor.next() ).thenReturn( true, true, false ); assertTrue( relationshipConversion.hasNext() ); relationshipConversion.next(); - verify( statement, never() ).close(); + verify( cursor, never() ).close(); assertTrue( relationshipConversion.hasNext() ); relationshipConversion.next(); - verify( statement, never() ).close(); + verify( cursor, never() ).close(); assertFalse( relationshipConversion.hasNext() ); - verify( statement ).close(); + verify( cursor ).close(); } @Test public void closeStatementOnlyOnce() { - relationshipConversion.iterator = new ArrayRelationshipVisitor( new long[]{1L} ); + when( cursor.next() ).thenReturn( true, false ); assertTrue( relationshipConversion.hasNext() ); relationshipConversion.next(); @@ -85,31 +92,6 @@ public void closeStatementOnlyOnce() relationshipConversion.close(); relationshipConversion.close(); - verify( statement ).close(); - } - - private static class ArrayRelationshipVisitor extends RelationshipIterator.BaseIterator - { - private final long[] ids; - private int position; - - ArrayRelationshipVisitor( long[] ids ) - { - this.ids = ids; - } - - @Override - protected boolean fetchNext() - { - return ids.length > position && next( ids[position++] ); - } - - @Override - public boolean relationshipVisit( long relationshipId, - RelationshipVisitor visitor ) throws EXCEPTION - { - visitor.visit( relationshipId, 1, 1L, 1L ); - return false; - } + verify( cursor ).close(); } }