Skip to content

Commit

Permalink
Clean some code and add some tests
Browse files Browse the repository at this point in the history
Clean up the Progressor API for the index cursors.
Add unit tests for the IndexCursorFilter. This required ability to stub the store.
  • Loading branch information
thobe authored and fickludd committed Nov 9, 2017
1 parent f7a9cdc commit 569035b
Show file tree
Hide file tree
Showing 11 changed files with 963 additions and 317 deletions.
Expand Up @@ -25,16 +25,17 @@
import org.neo4j.internal.kernel.api.IndexQuery; import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.values.storable.Value; import org.neo4j.values.storable.Value;


class IndexCursorFilter implements CursorProgressor.Cursor<IndexState.NodeValue> class IndexCursorFilter implements IndexCursorProgressor.NodeValueCursor
{ {
private static final Comparator<IndexQuery> ASCENDING_BY_KEY = Comparator.comparingInt( IndexQuery::propertyKeyId ); private static final Comparator<IndexQuery> ASCENDING_BY_KEY = Comparator.comparingInt( IndexQuery::propertyKeyId );
private final CursorProgressor.Cursor<IndexState.NodeValue> target; private final IndexCursorProgressor.NodeValueCursor target;
private final NodeCursor node; private final NodeCursor node;
private final PropertyCursor property; private final PropertyCursor property;
private final IndexQuery[] filters; private final IndexQuery[] filters;
private int[] keys;


IndexCursorFilter( IndexCursorFilter(
CursorProgressor.Cursor<IndexState.NodeValue> target, IndexCursorProgressor.NodeValueCursor target,
NodeCursor node, PropertyCursor property, IndexQuery... filters ) NodeCursor node, PropertyCursor property, IndexQuery... filters )
{ {
this.target = target; this.target = target;
Expand All @@ -45,104 +46,92 @@ class IndexCursorFilter implements CursorProgressor.Cursor<IndexState.NodeValue>
} }


@Override @Override
public void empty() public void initialize( IndexCursorProgressor progressor, int[] keys )
{ {
node.close(); this.keys = keys;
property.close(); target.initialize( progressor, keys );
target.empty();
} }


@Override @Override
public void initialize( CursorProgressor<IndexState.NodeValue> progressor ) public void done()
{ {
target.initialize( new Progressor( progressor, node, property, filters ) ); node.close();
property.close();
target.done();
} }


private static class Progressor implements CursorProgressor<IndexState.NodeValue>, IndexState.NodeValue @Override
public boolean node( long reference, Value[] values )
{ {
private final CursorProgressor<IndexState.NodeValue> progressor; if ( keys != null && values != null )
private final NodeCursor node;
private final PropertyCursor property;
private final IndexQuery[] filters;
private long reference;
private int[] keys;
private Value[] values;

Progressor(
CursorProgressor<IndexState.NodeValue> progressor,
NodeCursor node, PropertyCursor property, IndexQuery[] filters )
{ {
this.progressor = progressor; return filterByIndexValues( reference, values );
this.node = node;
this.property = property;
this.filters = filters;
} }

else
@Override
public boolean next( IndexState.NodeValue nodeValue )
{ {
if ( !progressor.next( this ) ) node.single( reference );
if ( node.next() )
{
node.properties( property );
}
else
{ {
property.clear();
return false; return false;
} }
PROPERTIES: return filterByCursors( reference, values );
while ( property.next() ) }
}

private boolean filterByIndexValues( long reference, Value[] values )
{
FILTERS:
for ( IndexQuery filter : filters )
{
for ( int i = 0; i < keys.length; i++ )
{ {
for ( IndexQuery filter : filters ) if ( keys[i] == filter.propertyKeyId() )
{ {
if ( filter.propertyKeyId() == property.propertyKey() ) if ( !filter.acceptsValue( values[i] ) )
{
if ( !filter.acceptsValueAt( property ) )
{
// this will reset the property cursor to the properties of the next node
if ( !progressor.next( this ) )
{
return false;
}
// so all we have to do is continue in order to inspect the next one
continue PROPERTIES;
}
}
else if ( property.propertyKey() < filter.propertyKeyId() )
{ {
continue PROPERTIES; return false;
} }
continue FILTERS;
} }
} }
// when we get here, we know that we are on a node where all filters are accepted assert false : "Cannot satisfy filter " + filter + " - no corresponding key!";
nodeValue.node( reference, keys, values ); return false;
return true;
}

@Override
public void close()
{
node.close();
property.close();
progressor.close();
} }
return target.node( reference, values );
}


@Override private boolean filterByCursors( long reference, Value[] values )
public void node( long reference, int[] keys, Value[] values ) {
// note that this way of checking if all filters are matched relies on the node not having duplicate properties
int accepted = 0;
PROPERTIES:
while ( property.next() )
{ {
// it's a bit iffy that we have to put these things into fields, but ok enough. for ( IndexQuery filter : filters )
this.reference = reference;
this.keys = keys;
this.values = values;
node.single( reference );
if ( node.next() )
{
node.properties( property );
}
else
{ {
property.clear(); if ( filter.propertyKeyId() == property.propertyKey() )
{
if ( !filter.acceptsValueAt( property ) )
{
return false;
}
accepted++;
}
else if ( property.propertyKey() < filter.propertyKeyId() )
{
continue PROPERTIES;
}
} }
} }

if ( accepted < filters.length )
@Override
public void done()
{ {
return false; // not all filters were matched
} }
return target.node( reference, values );
} }
} }
Expand Up @@ -19,16 +19,20 @@
*/ */
package org.neo4j.kernel.impl.newapi; package org.neo4j.kernel.impl.newapi;


public interface CursorProgressor<Sink> import org.neo4j.values.storable.Value;

public interface IndexCursorProgressor
{ {
boolean next( Sink sink ); boolean next();


void close(); void close();


interface Cursor<Sink> interface NodeValueCursor
{ {
void empty(); void initialize( IndexCursorProgressor progressor, int[] keys );

void done();


void initialize( CursorProgressor<Sink> progressor ); boolean node( long reference, Value[] values );
} }
} }
Expand Up @@ -29,4 +29,9 @@ interface NodeValue extends IndexState
{ {
void node( long reference, int[] keys, Value[] values ); void node( long reference, int[] keys, Value[] values );
} }

interface NodeLabel extends IndexState
{

}
} }
Expand Up @@ -25,29 +25,32 @@
import static org.neo4j.kernel.impl.store.record.AbstractBaseRecord.NO_ID; import static org.neo4j.kernel.impl.store.record.AbstractBaseRecord.NO_ID;


class NodeValueIndexCursor implements org.neo4j.internal.kernel.api.NodeValueIndexCursor, class NodeValueIndexCursor implements org.neo4j.internal.kernel.api.NodeValueIndexCursor,
CursorProgressor.Cursor<IndexState.NodeValue>, IndexState.NodeValue IndexCursorProgressor.NodeValueCursor
{ {
private final Read read; private final Read read;
private long node; private long node;
private int[] keys; private int[] keys;
private Value[] values; private Value[] values;
private CursorProgressor<IndexState.NodeValue> progressor; private IndexCursorProgressor progressor;


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


@Override @Override
public void empty() public void initialize( IndexCursorProgressor progressor, int[] keys )
{ {
close(); this.progressor = progressor;
this.keys = keys;
} }


@Override @Override
public void initialize( CursorProgressor<IndexState.NodeValue> progressor ) public boolean node( long reference, Value[] values )
{ {
this.progressor = progressor; this.node = reference;
this.values = values;
return true;
} }


@Override @Override
Expand All @@ -56,14 +59,6 @@ public void done()
close(); close();
} }


@Override
public void node( long reference, int[] keys, Value[] values )
{
this.node = reference;
this.keys = keys;
this.values = values;
}

@Override @Override
public void node( NodeCursor cursor ) public void node( NodeCursor cursor )
{ {
Expand Down Expand Up @@ -97,7 +92,7 @@ public Value propertyValue( int offset )
@Override @Override
public boolean next() public boolean next()
{ {
return progressor != null && progressor.next( this ); return progressor != null && progressor.next();
} }


@Override @Override
Expand Down

0 comments on commit 569035b

Please sign in to comment.