Skip to content

Commit

Permalink
Remove nodeCursorGetForLabel
Browse files Browse the repository at this point in the history
  • Loading branch information
davidegrohmann committed Jan 4, 2017
1 parent d40c13b commit 0814026
Show file tree
Hide file tree
Showing 9 changed files with 219 additions and 41 deletions.
Expand Up @@ -56,6 +56,7 @@
import org.neo4j.kernel.impl.api.operations.EntityWriteOperations;
import org.neo4j.kernel.impl.api.operations.SchemaReadOperations;
import org.neo4j.kernel.impl.api.operations.SchemaWriteOperations;
import org.neo4j.kernel.impl.api.store.EntityLoadingIterator;
import org.neo4j.kernel.impl.constraints.ConstraintSemantics;
import org.neo4j.kernel.impl.locking.LockTracer;
import org.neo4j.kernel.impl.locking.Locks;
Expand Down Expand Up @@ -437,12 +438,6 @@ public Cursor<RelationshipItem> relationshipCursorGetAll( KernelStatement statem
return entityReadOperations.relationshipCursorGetAll( statement );
}

@Override
public Cursor<NodeItem> nodeCursorGetForLabel( KernelStatement statement, int labelId )
{
return entityReadOperations.nodeCursorGetForLabel( statement, labelId );
}

@Override
public IndexDescriptor indexCreate( KernelStatement state, int labelId, int propertyKeyId )
throws AlreadyIndexedException, AlreadyConstrainedException
Expand Down Expand Up @@ -473,10 +468,9 @@ public UniquenessConstraint uniquePropertyConstraintCreate( KernelStatement stat
public NodePropertyExistenceConstraint nodePropertyExistenceConstraintCreate( KernelStatement state, int labelId,
int propertyKeyId ) throws AlreadyConstrainedException, CreateConstraintFailureException
{
try ( Cursor<NodeItem> cursor = nodeCursorGetForLabel( state, labelId ) )
{
constraintSemantics.validateNodePropertyExistenceConstraint( cursor, labelId, propertyKeyId );
}
Iterator<Cursor<NodeItem>> nodes = new EntityLoadingIterator<>( nodesGetForLabel( state, labelId ),
( id ) -> nodeCursorById( state, id ) );
constraintSemantics.validateNodePropertyExistenceConstraint( nodes, labelId, propertyKeyId );
return schemaWriteOperations.nodePropertyExistenceConstraintCreate( state, labelId, propertyKeyId );
}

Expand Down
Expand Up @@ -316,13 +316,6 @@ public Cursor<RelationshipItem> relationshipCursorGetAll( KernelStatement statem
return entityReadDelegate.relationshipCursorGetAll( statement );
}

@Override
public Cursor<NodeItem> nodeCursorGetForLabel( KernelStatement statement, int labelId )
{
guard.check( statement );
return entityReadDelegate.nodeCursorGetForLabel( statement, labelId );
}

@Override
public long nodesGetCount( KernelStatement statement )
{
Expand Down
Expand Up @@ -167,8 +167,8 @@ public Cursor<RelationshipItem> relationshipCursorById( KernelStatement statemen

private Cursor<RelationshipItem> relationshipCursor( KernelStatement statement, long relationshipId )
{
Cursor<RelationshipItem> cursor = statement.getStoreStatement().acquireSingleRelationshipCursor(
relationshipId );
Cursor<RelationshipItem> cursor =
statement.getStoreStatement().acquireSingleRelationshipCursor( relationshipId );
if ( statement.hasTxStateWithChanges() )
{
return statement.txState().augmentSingleRelationshipCursor( cursor, relationshipId );
Expand All @@ -187,15 +187,6 @@ public Cursor<RelationshipItem> relationshipCursorGetAll( KernelStatement statem
return cursor;
}

@Override
public Cursor<NodeItem> nodeCursorGetForLabel( KernelStatement statement, int labelId )
{
// TODO Filter this properly
StorageStatement storeStatement = statement.getStoreStatement();
return storeStatement.acquireIteratorNodeCursor(
storeLayer.nodesGetForLabel( storeStatement, labelId ) );
}

// </Cursors>

@Override
Expand Down
Expand Up @@ -142,8 +142,6 @@ Cursor<RelationshipItem> relationshipCursorById( KernelStatement statement, long

Cursor<RelationshipItem> relationshipCursorGetAll( KernelStatement statement );

Cursor<NodeItem> nodeCursorGetForLabel( KernelStatement statement, int labelId );

long nodesGetCount( KernelStatement statement );

long relationshipsGetCount( KernelStatement statement );
Expand Down
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2002-2017 "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.store;

import org.neo4j.collection.primitive.PrimitiveLongIterator;
import org.neo4j.cursor.Cursor;
import org.neo4j.function.ThrowingLongFunction;
import org.neo4j.helpers.collection.PrefetchingIterator;
import org.neo4j.kernel.api.exceptions.EntityNotFoundException;
import org.neo4j.storageengine.api.EntityItem;

public class EntityLoadingIterator<T extends EntityItem> extends PrefetchingIterator<Cursor<T>>
{
private final PrimitiveLongIterator ids;
private final ThrowingLongFunction<Cursor<T>,EntityNotFoundException> loader;

public EntityLoadingIterator( PrimitiveLongIterator ids,
ThrowingLongFunction<Cursor<T>,EntityNotFoundException> loader )
{
this.ids = ids;
this.loader = loader;
}

@Override
protected Cursor<T> fetchNextOrNull()
{
while ( ids.hasNext() )
{
try
{
return loader.apply( ids.next() );
}
catch ( EntityNotFoundException e )
{
// skip this id
}
}

return null;
}
}
Expand Up @@ -19,6 +19,8 @@
*/
package org.neo4j.kernel.impl.constraints;

import java.util.Iterator;

import org.neo4j.cursor.Cursor;
import org.neo4j.kernel.api.constraints.PropertyConstraint;
import org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException;
Expand All @@ -34,7 +36,7 @@
*/
public interface ConstraintSemantics
{
void validateNodePropertyExistenceConstraint( Cursor<NodeItem> allNodes, int label, int propertyKey )
void validateNodePropertyExistenceConstraint( Iterator<Cursor<NodeItem>> allNodes, int label, int propertyKey )
throws CreateConstraintFailureException;

void validateRelationshipPropertyExistenceConstraint( Cursor<RelationshipItem> allRels, int type, int propertyKey )
Expand Down
Expand Up @@ -19,6 +19,8 @@
*/
package org.neo4j.kernel.impl.constraints;

import java.util.Iterator;

import org.neo4j.cursor.Cursor;
import org.neo4j.kernel.api.constraints.NodePropertyExistenceConstraint;
import org.neo4j.kernel.api.constraints.PropertyConstraint;
Expand All @@ -37,8 +39,8 @@ public class StandardConstraintSemantics implements ConstraintSemantics
public static final String ERROR_MESSAGE = "Property existence constraint requires Neo4j Enterprise Edition";

@Override
public void validateNodePropertyExistenceConstraint( Cursor<NodeItem> allNodes, int label, int propertyKey )
throws CreateConstraintFailureException
public void validateNodePropertyExistenceConstraint( Iterator<Cursor<NodeItem>> allNodes, int label,
int propertyKey ) throws CreateConstraintFailureException
{
throw propertyExistenceConstraintsNotAllowed( new NodePropertyExistenceConstraint( label, propertyKey ) );
}
Expand Down
@@ -0,0 +1,138 @@
/*
* Copyright (c) 2002-2017 "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.store;

import org.junit.Test;

import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;

import org.neo4j.collection.primitive.PrimitiveLongCollections;
import org.neo4j.collection.primitive.PrimitiveLongIterator;
import org.neo4j.cursor.Cursor;
import org.neo4j.function.ThrowingLongFunction;
import org.neo4j.kernel.api.exceptions.EntityNotFoundException;
import org.neo4j.storageengine.api.EntityItem;
import org.neo4j.storageengine.api.EntityType;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.neo4j.collection.primitive.PrimitiveLongCollections.emptyIterator;

public class EntityLoadingIteratorTest
{
@Test
public void shouldHandleAnEmptyIterator() throws Exception
{
// given
EntityLoadingIterator<EntityItem> iterator = new EntityLoadingIterator<>( emptyIterator(), ( id ) ->
{
throw new IllegalStateException( "" );
} );

// when - then
assertNoMoreElements( iterator );
}

@Test
public void shouldHandleANonEmptyIterator() throws Exception
{
// given
Map<Long,Cursor<EntityItem>> map = new HashMap<>( 3 );
map.put( 1L, mockCursor() );
map.put( 2L, mockCursor() );
map.put( 3L, mockCursor() );
PrimitiveLongIterator inner = PrimitiveLongCollections.iterator( 1, 2, 3 );
EntityLoadingIterator<EntityItem> iterator = new EntityLoadingIterator<>( inner, createMapping( map ) );

// when - then
for ( long i = 1; i <= 3; i++)
{
assertTrue( iterator.hasNext() );
assertEquals( map.get( i ), iterator.next() );
}

assertNoMoreElements( iterator );
}

@Test
public void shouldHandleANonEmptyIteratorWithNotFoundEntities() throws Exception
{
// given
Map<Long,Cursor<EntityItem>> map = new HashMap<>( 3 );
map.put( 1L, mockCursor() );
map.put( 2L, null );
map.put( 3L, mockCursor() );
PrimitiveLongIterator inner = PrimitiveLongCollections.iterator( 1, 2, 3 );
EntityLoadingIterator<EntityItem> iterator = new EntityLoadingIterator<>( inner, createMapping( map ) );

// when - then
for ( long i = 1; i <= 2; i++)
{
assertTrue( iterator.hasNext() );

assertEquals( map.get( i + (i - 1) /* 1 -> 1, 2 -> 3 */ ), iterator.next() );
}

assertNoMoreElements( iterator );
}

private void assertNoMoreElements( EntityLoadingIterator<EntityItem> iterator )
{
assertFalse( iterator.hasNext() );
try
{
iterator.next();
fail( "should have thrown ");
}
catch ( NoSuchElementException e )
{
// good
}
}

private ThrowingLongFunction<Cursor<EntityItem>,EntityNotFoundException> createMapping(
Map<Long,Cursor<EntityItem>> map )
{
return ( id ) ->
{
if ( !map.containsKey( id ) )
{
throw new IllegalStateException( "wat!?" );
}
Cursor<EntityItem> cursor = map.get( id );
if ( cursor == null )
{
throw new EntityNotFoundException( EntityType.NODE, id );
}
return cursor;
};
}

@SuppressWarnings( "unchecked" )
private Cursor<EntityItem> mockCursor()
{
return (Cursor<EntityItem>) mock( Cursor.class );
}
}
Expand Up @@ -71,17 +71,19 @@ public PropertyConstraintRule writeRelationshipPropertyExistenceConstraint( long
}

@Override
public void validateNodePropertyExistenceConstraint( Cursor<NodeItem> allNodes, int label, int propertyKey )
throws CreateConstraintFailureException
public void validateNodePropertyExistenceConstraint( Iterator<Cursor<NodeItem>> allNodes, int label,
int propertyKey ) throws CreateConstraintFailureException
{
while ( allNodes.next() )
while ( allNodes.hasNext() )
{
NodeItem node = allNodes.get();
if ( !node.hasProperty( propertyKey ) )
try ( Cursor<NodeItem> cursor = allNodes.next() )
{
throw createConstraintFailure(
new NodePropertyExistenceConstraintVerificationFailedKernelException(
new NodePropertyExistenceConstraint( label,propertyKey ), node.id() ) );
NodeItem node = cursor.get();
if ( !node.hasProperty( propertyKey ) )
{
throw createConstraintFailure( new NodePropertyExistenceConstraintVerificationFailedKernelException(
new NodePropertyExistenceConstraint( label, propertyKey ), node.id() ) );
}
}
}
}
Expand Down

0 comments on commit 0814026

Please sign in to comment.