Skip to content

Commit

Permalink
Read dynamic labels through record cursor
Browse files Browse the repository at this point in the history
Record cursor for dynamic labels is now pooled together with other cursors.
This is done to reuse same page cursor when reading labels of nodes inside the
same transaction.
  • Loading branch information
lutovich committed May 12, 2016
1 parent 0c16c0f commit 33733e5
Show file tree
Hide file tree
Showing 19 changed files with 533 additions and 36 deletions.
Expand Up @@ -110,7 +110,7 @@ public static long[] getListOfLabels( NodeRecord nodeRecord, RecordStore<Dynamic
}
return LabelChainWalker.labelIds( recordList );
}
return NodeLabelsField.get( nodeRecord, null );
return InlineNodeLabels.get( nodeRecord );
}

public static Set<Long> getListOfLabels( long labelField )
Expand Down
Expand Up @@ -32,7 +32,6 @@
import org.neo4j.kernel.impl.locking.LockService;
import org.neo4j.kernel.impl.store.InvalidRecordException;
import org.neo4j.kernel.impl.store.NeoStores;
import org.neo4j.kernel.impl.store.NodeLabelsField;
import org.neo4j.kernel.impl.store.NodeStore;
import org.neo4j.kernel.impl.store.RecordCursors;
import org.neo4j.kernel.impl.store.RecordStore;
Expand Down Expand Up @@ -92,15 +91,15 @@ public StoreAbstractNodeCursor( NodeRecord nodeRecord,
@Override
protected StoreLabelCursor create()
{
return new StoreLabelCursor( this );
return new StoreLabelCursor( cursors.label(), this );
}
};
singleLabelCursor = new InstanceCache<StoreSingleLabelCursor>()
{
@Override
protected StoreSingleLabelCursor create()
{
return new StoreSingleLabelCursor( this );
return new StoreSingleLabelCursor( cursors.label(), this );
}
};
nodeRelationshipCursor = new InstanceCache<StoreNodeRelationshipCursor>()
Expand Down Expand Up @@ -147,13 +146,13 @@ public long id()
@Override
public Cursor<LabelItem> labels()
{
return labelCursor.get().init( NodeLabelsField.get( nodeRecord, nodeStore ) );
return labelCursor.get().init( nodeRecord );
}

@Override
public Cursor<LabelItem> label( int labelId )
{
return singleLabelCursor.get().init( NodeLabelsField.get( nodeRecord, nodeStore ), labelId );
return singleLabelCursor.get().init( nodeRecord, labelId );
}

/**
Expand Down
Expand Up @@ -22,6 +22,10 @@
import java.util.function.Consumer;

import org.neo4j.cursor.Cursor;
import org.neo4j.kernel.impl.store.NodeLabelsField;
import org.neo4j.kernel.impl.store.RecordCursor;
import org.neo4j.kernel.impl.store.record.DynamicRecord;
import org.neo4j.kernel.impl.store.record.NodeRecord;
import org.neo4j.storageengine.api.LabelItem;

import static org.neo4j.kernel.impl.util.IoPrimitiveUtils.safeCastLongToInt;
Expand All @@ -34,17 +38,20 @@ public class StoreLabelCursor implements Cursor<LabelItem>, LabelItem
private long[] labels;
private int index;
private int currentLabel;

private final RecordCursor<DynamicRecord> dynamicLabelRecordCursor;
private final Consumer<StoreLabelCursor> instanceCache;

public StoreLabelCursor( Consumer<StoreLabelCursor> instanceCache )
public StoreLabelCursor( RecordCursor<DynamicRecord> dynamicLabelRecordCursor,
Consumer<StoreLabelCursor> instanceCache )
{
this.dynamicLabelRecordCursor = dynamicLabelRecordCursor;
this.instanceCache = instanceCache;
}

public StoreLabelCursor init( long[] labels )
public StoreLabelCursor init( NodeRecord nodeRecord )
{
this.labels = labels;
index = 0;
this.labels = NodeLabelsField.get( nodeRecord, dynamicLabelRecordCursor );
return this;
}

Expand Down Expand Up @@ -77,6 +84,14 @@ public int getAsInt()
@Override
public void close()
{
// this cursor is pooled so it is better to clear it's state here
clearState();
instanceCache.accept( this );
}

private void clearState()
{
labels = null;
index = 0;
}
}
Expand Up @@ -21,6 +21,9 @@

import java.util.function.Consumer;

import org.neo4j.kernel.impl.store.RecordCursor;
import org.neo4j.kernel.impl.store.record.DynamicRecord;
import org.neo4j.kernel.impl.store.record.NodeRecord;
import org.neo4j.kernel.impl.util.InstanceCache;

/**
Expand All @@ -30,14 +33,15 @@ public class StoreSingleLabelCursor extends StoreLabelCursor
{
private int labelId;

public StoreSingleLabelCursor( InstanceCache<StoreSingleLabelCursor> instanceCache )
public StoreSingleLabelCursor( RecordCursor<DynamicRecord> dynamicLabelRecordCursor,
InstanceCache<StoreSingleLabelCursor> instanceCache )
{
super( (Consumer) instanceCache );
super( dynamicLabelRecordCursor, (Consumer) instanceCache );
}

public StoreSingleLabelCursor init( long[] labels, int labelId )
public StoreSingleLabelCursor init( NodeRecord nodeRecord, int labelId )
{
super.init( labels );
super.init( nodeRecord );
this.labelId = labelId;
return this;
}
Expand Down
Expand Up @@ -24,8 +24,6 @@
import java.nio.file.NoSuchFileException;
import java.nio.file.StandardOpenOption;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import org.neo4j.graphdb.config.Setting;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
Expand Down Expand Up @@ -1146,17 +1144,10 @@ public <EXCEPTION extends Exception> void scanAllRecords( Visitor<RECORD,EXCEPTI
@Override
public Collection<RECORD> getRecords( long firstId, RecordLoad mode )
{
// TODO we should instead be passed in a consumer of records, so we don't have to spend memory building up
// this list
try ( RecordCursor<RECORD> cursor = newRecordCursor( newRecord() ) )
{
List<RECORD> recordList = new LinkedList<>();
cursor.acquire( firstId, mode );
while ( cursor.next() )
{
recordList.add( (RECORD) cursor.get().clone() );
}
return recordList;
return cursor.getAll();
}
}

Expand Down
Expand Up @@ -63,6 +63,15 @@ public static long[] get( NodeRecord node, NodeStore nodeStore )
return getDynamicLabelsArray( node.getUsedDynamicLabelRecords(), nodeStore.getDynamicLabelStore() );
}

public static long[] get( NodeRecord node, RecordCursor<DynamicRecord> dynamicLabelCursor )
{
if ( node.isLight() )
{
NodeStore.ensureHeavy( node, dynamicLabelCursor );
}
return getDynamicLabelsArrayFromHeavyRecords( node.getUsedDynamicLabelRecords() );
}

@Override
public long[] getIfLoaded()
{
Expand Down
Expand Up @@ -19,6 +19,7 @@
*/
package org.neo4j.kernel.impl.store;

import org.neo4j.kernel.impl.store.record.DynamicRecord;
import org.neo4j.kernel.impl.store.record.NodeRecord;

/**
Expand Down Expand Up @@ -54,6 +55,13 @@ public static long[] get( NodeRecord node, NodeStore nodeStore )
: InlineNodeLabels.get( node );
}

public static long[] get( NodeRecord node, RecordCursor<DynamicRecord> dynamicLabelCursor )
{
return fieldPointsToDynamicRecordOfLabels( node.getLabelField() )
? DynamicNodeLabels.get( node, dynamicLabelCursor )
: InlineNodeLabels.get( node );
}

public static boolean fieldPointsToDynamicRecordOfLabels( long labelField )
{
return (labelField & 0x8000000000L) != 0;
Expand Down
Expand Up @@ -21,6 +21,7 @@

import java.io.File;
import java.util.Arrays;
import java.util.List;

import org.neo4j.io.pagecache.PageCache;
import org.neo4j.kernel.configuration.Config;
Expand Down Expand Up @@ -104,6 +105,14 @@ public void ensureHeavy( NodeRecord node, long firstDynamicLabelRecord )
node.setLabelField( node.getLabelField(), dynamicLabelStore.getRecords( firstDynamicLabelRecord, RecordLoad.NORMAL ) );
}

public static void ensureHeavy( NodeRecord node, RecordCursor<DynamicRecord> dynamicLabelCursor )
{
long firstDynamicLabelId = NodeLabelsField.firstDynamicLabelRecordId( node.getLabelField() );
dynamicLabelCursor.placeAt( firstDynamicLabelId, RecordLoad.NORMAL );
List<DynamicRecord> dynamicLabelRecords = dynamicLabelCursor.getAll();
node.setLabelField( node.getLabelField(), dynamicLabelRecords );
}

@Override
public void updateRecord( NodeRecord record )
{
Expand Down
Expand Up @@ -19,6 +19,9 @@
*/
package org.neo4j.kernel.impl.store;

import java.util.ArrayList;
import java.util.List;

import org.neo4j.cursor.Cursor;
import org.neo4j.io.pagecache.PageCursor;
import org.neo4j.kernel.impl.store.record.AbstractBaseRecord;
Expand Down Expand Up @@ -88,6 +91,17 @@ public interface RecordCursor<R extends AbstractBaseRecord> extends Cursor<R>
*/
boolean next( long id, R record, RecordLoad mode );

@SuppressWarnings( "unchecked" )
default List<R> getAll()
{
List<R> recordList = new ArrayList<>();
while ( next() )
{
recordList.add( (R) get().clone() );
}
return recordList;
}

class Delegator<R extends AbstractBaseRecord> implements RecordCursor<R>
{
private final RecordCursor<R> actual;
Expand Down
Expand Up @@ -38,6 +38,7 @@ public class RecordCursors implements AutoCloseable
private final RecordCursor<PropertyRecord> property;
private final RecordCursor<DynamicRecord> propertyString;
private final RecordCursor<DynamicRecord> propertyArray;
private final RecordCursor<DynamicRecord> label;

public RecordCursors( NeoStores neoStores )
{
Expand All @@ -52,6 +53,7 @@ public RecordCursors( NeoStores neoStores, RecordLoad mode )
property = newCursor( neoStores.getPropertyStore(), mode );
propertyString = newCursor( neoStores.getPropertyStore().getStringStore(), mode );
propertyArray = newCursor( neoStores.getPropertyStore().getArrayStore(), mode );
label = newCursor( neoStores.getNodeStore().getDynamicLabelStore(), mode );
}

private static <R extends AbstractBaseRecord> RecordCursor<R> newCursor( RecordStore<R> store, RecordLoad mode )
Expand All @@ -63,7 +65,7 @@ private static <R extends AbstractBaseRecord> RecordCursor<R> newCursor( RecordS
public void close()
{
IOUtils.closeAll( RuntimeException.class,
node, relationship, relationshipGroup, property, propertyArray, propertyString );
node, relationship, relationshipGroup, property, propertyArray, propertyString, label );
}

public RecordCursor<NodeRecord> node()
Expand Down Expand Up @@ -95,4 +97,9 @@ public RecordCursor<DynamicRecord> propertyString()
{
return propertyString;
}

public RecordCursor<DynamicRecord> label()
{
return label;
}
}

0 comments on commit 33733e5

Please sign in to comment.