diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/AllStoreHolder.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/AllStoreHolder.java index 2d36e5f89c3fc..9f15a11cff133 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/AllStoreHolder.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/AllStoreHolder.java @@ -247,25 +247,25 @@ public String propertyKeyGetName( int propertyKeyId ) throws PropertyKeyIdNotFou @Override PageCursor nodePage( long reference ) { - return nodes.openPageCursor( reference ); + return nodes.openPageCursorForReading( reference ); } @Override PageCursor relationshipPage( long reference ) { - return relationships.openPageCursor( reference ); + return relationships.openPageCursorForReading( reference ); } @Override PageCursor groupPage( long reference ) { - return groups.openPageCursor( reference ); + return groups.openPageCursorForReading( reference ); } @Override PageCursor propertyPage( long reference ) { - return properties.openPageCursor( reference ); + return properties.openPageCursorForReading( reference ); } @Override @@ -289,13 +289,13 @@ RecordCursor labelCursor() @Override void node( NodeRecord record, long reference, PageCursor pageCursor ) { - nodes.loadRecordByCursor( reference, record, RecordLoad.CHECK, pageCursor ); + nodes.getRecordByCursor( reference, record, RecordLoad.CHECK, pageCursor ); } @Override void relationship( RelationshipRecord record, long reference, PageCursor pageCursor ) { - relationships.loadRecordByCursor( reference, record, RecordLoad.CHECK, pageCursor ); + relationships.getRecordByCursor( reference, record, RecordLoad.CHECK, pageCursor ); } @Override @@ -303,13 +303,13 @@ void property( PropertyRecord record, long reference, PageCursor pageCursor ) { //We need to load forcefully here since otherwise we can have inconsistent reads //for properties across blocks, see org.neo4j.graphdb.ConsistentPropertyReadsIT - properties.loadRecordByCursor( reference, record, RecordLoad.FORCE, pageCursor ); + properties.getRecordByCursor( reference, record, RecordLoad.FORCE, pageCursor ); } @Override void group( RelationshipGroupRecord record, long reference, PageCursor page ) { - groups.loadRecordByCursor( reference, record, RecordLoad.NORMAL, page ); + groups.getRecordByCursor( reference, record, RecordLoad.NORMAL, page ); } @Override diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/storageengine/impl/recordstorage/StoreStatement.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/storageengine/impl/recordstorage/StoreStatement.java index cde006c315577..24fd5008fd2c4 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/storageengine/impl/recordstorage/StoreStatement.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/storageengine/impl/recordstorage/StoreStatement.java @@ -19,13 +19,10 @@ */ package org.neo4j.kernel.impl.storageengine.impl.recordstorage; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; import java.util.function.IntPredicate; import java.util.function.Supplier; import org.neo4j.cursor.Cursor; -import org.neo4j.io.pagecache.PageCursor; import org.neo4j.kernel.api.AssertOpen; import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; import org.neo4j.kernel.api.schema.index.IndexDescriptor; @@ -39,26 +36,13 @@ import org.neo4j.kernel.impl.api.store.StoreSingleRelationshipCursor; import org.neo4j.kernel.impl.locking.Lock; import org.neo4j.kernel.impl.locking.LockService; -import org.neo4j.kernel.impl.store.AbstractDynamicStore; -import org.neo4j.kernel.impl.store.DynamicArrayStore; -import org.neo4j.kernel.impl.store.DynamicStringStore; -import org.neo4j.kernel.impl.store.InvalidRecordException; import org.neo4j.kernel.impl.store.NeoStores; import org.neo4j.kernel.impl.store.NodeStore; import org.neo4j.kernel.impl.store.PropertyStore; -import org.neo4j.kernel.impl.store.RecordCursor; import org.neo4j.kernel.impl.store.RecordCursors; -import org.neo4j.kernel.impl.store.RecordStore; import org.neo4j.kernel.impl.store.RelationshipGroupStore; import org.neo4j.kernel.impl.store.RelationshipStore; import org.neo4j.kernel.impl.store.StoreType; -import org.neo4j.kernel.impl.store.record.AbstractBaseRecord; -import org.neo4j.kernel.impl.store.record.DynamicRecord; -import org.neo4j.kernel.impl.store.record.NodeRecord; -import org.neo4j.kernel.impl.store.record.PropertyRecord; -import org.neo4j.kernel.impl.store.record.RecordLoad; -import org.neo4j.kernel.impl.store.record.RelationshipGroupRecord; -import org.neo4j.kernel.impl.store.record.RelationshipRecord; import org.neo4j.kernel.impl.util.InstanceCache; import org.neo4j.storageengine.api.Direction; import org.neo4j.storageengine.api.NodeItem; @@ -68,9 +52,6 @@ import org.neo4j.storageengine.api.schema.IndexReader; import org.neo4j.storageengine.api.schema.LabelScanReader; -import static org.neo4j.kernel.impl.store.record.AbstractBaseRecord.NO_ID; -import static org.neo4j.kernel.impl.store.record.RecordLoad.NORMAL; - /** * Statement for store layer. This allows for acquisition of cursors on the store data. *

@@ -97,8 +78,6 @@ public class StoreStatement implements StorageStatement private final RecordCursors recordCursors; private final Supplier labelScanStore; private final RecordStorageCommandCreationContext commandCreationContext; - private final DynamicArrayStore propertyArrayStore; - private final DynamicStringStore propertyStringStore; private IndexReaderFactory indexReaderFactory; private LabelScanReader labelScanReader; @@ -106,11 +85,6 @@ public class StoreStatement implements StorageStatement private boolean acquired; private boolean closed; - private final Nodes nodes; - private final Relationships relationships; - private final Groups groups; - private final Properties properties; - public StoreStatement( NeoStores neoStores, Supplier indexReaderFactory, Supplier labelScanReaderSupplier, LockService lockService, RecordStorageCommandCreationContext commandCreationContext ) @@ -124,8 +98,6 @@ public StoreStatement( NeoStores neoStores, Supplier indexRe this.relationshipStore = neoStores.getRelationshipStore(); this.relationshipGroupStore = neoStores.getRelationshipGroupStore(); this.propertyStore = neoStores.getPropertyStore(); - this.propertyArrayStore = propertyStore.getArrayStore(); - this.propertyStringStore = propertyStore.getStringStore(); this.recordCursors = new RecordCursors( neoStores ); singleNodeCursor = new InstanceCache() @@ -180,11 +152,6 @@ protected StorePropertyCursor create() return new StorePropertyCursor( recordCursors, this ); } }; - - nodes = new Nodes(); - relationships = new Relationships(); - groups = new Groups(); - properties = new Properties(); } @Override @@ -321,188 +288,24 @@ public long reserveRelationship() @Override public Nodes nodes() { - return nodes; + return nodeStore; } @Override public Relationships relationships() { - return relationships; + return relationshipStore; } @Override public Groups groups() { - return groups; + return relationshipGroupStore; } @Override public Properties properties() { - return properties; - } - - class Nodes implements StorageStatement.Nodes - { - @Override - public PageCursor openPageCursor( long reference ) - { - return nodeStore.openPageCursorForReading( reference ); - } - - @Override - public void loadRecordByCursor( long reference, NodeRecord nodeRecord, RecordLoad mode, PageCursor cursor ) - throws InvalidRecordException - { - nodeStore.getRecordByCursor( reference, nodeRecord, mode, cursor ); - } - - @Override - public long getHighestPossibleIdInUse() - { - return nodeStore.getHighestPossibleIdInUse(); - } - - @Override - public RecordCursor newLabelCursor() - { - return newCursor( nodeStore.getDynamicLabelStore() ); - } - } - - class Relationships implements StorageStatement.Relationships - { - @Override - public PageCursor openPageCursor( long reference ) - { - return relationshipStore.openPageCursorForReading( reference ); - } - - @Override - public void loadRecordByCursor( long reference, RelationshipRecord relationshipRecord, RecordLoad mode, - PageCursor cursor ) throws InvalidRecordException - { - relationshipStore.getRecordByCursor( reference, relationshipRecord, mode, cursor ); - } - - @Override - public long getHighestPossibleIdInUse() - { - return relationshipStore.getHighestPossibleIdInUse(); - } - } - - class Groups implements StorageStatement.Groups - { - @Override - public PageCursor openPageCursor( long reference ) - { - return relationshipGroupStore.openPageCursorForReading( reference ); - } - - @Override - public void loadRecordByCursor( long reference, RelationshipGroupRecord relationshipGroupRecord, - RecordLoad mode, PageCursor cursor ) throws InvalidRecordException - { - relationshipGroupStore.getRecordByCursor( reference, relationshipGroupRecord, mode, cursor ); - } - - @Override - public long getHighestPossibleIdInUse() - { - return relationshipGroupStore.getHighestPossibleIdInUse(); - } - } - - class Properties implements StorageStatement.Properties - { - @Override - public PageCursor openPageCursor( long reference ) - { - return propertyStore.openPageCursorForReading( reference ); - } - - @Override - public void loadRecordByCursor( long reference, PropertyRecord propertyBlocks, RecordLoad mode, - PageCursor cursor ) throws InvalidRecordException - { - propertyStore.getRecordByCursor( reference, propertyBlocks, mode, cursor ); - } - - @Override - public long getHighestPossibleIdInUse() - { - return propertyStore.getHighestPossibleIdInUse(); - } - - @Override - public PageCursor openStringPageCursor( long reference ) - { - return propertyStringStore.openPageCursorForReading( reference ); - } - - @Override - public PageCursor openArrayPageCursor( long reference ) - { - return propertyArrayStore.openPageCursorForReading( reference ); - } - - @Override - public ByteBuffer loadString( long reference, ByteBuffer buffer, PageCursor page ) - { - return readDynamic( propertyStore.getStringStore(), reference, buffer, page ); - } - - @Override - public ByteBuffer loadArray( long reference, ByteBuffer buffer, PageCursor page ) - { - return readDynamic( propertyStore.getArrayStore(), reference, buffer, page ); - } - } - - private static ByteBuffer readDynamic( AbstractDynamicStore store, long reference, ByteBuffer buffer, - PageCursor page ) - { - if ( buffer == null ) - { - buffer = ByteBuffer.allocate( 512 ); - } - else - { - buffer.clear(); - } - DynamicRecord record = store.newRecord(); - do - { - //We need to load forcefully here since otherwise we can have inconsistent reads - //for properties across blocks, see org.neo4j.graphdb.ConsistentPropertyReadsIT - store.getRecordByCursor( reference, record, RecordLoad.FORCE, page ); - reference = record.getNextBlock(); - byte[] data = record.getData(); - if ( buffer.remaining() < data.length ) - { - buffer = grow( buffer, data.length ); - } - buffer.put( data, 0, data.length ); - } - while ( reference != NO_ID ); - return buffer; - } - - private static ByteBuffer grow( ByteBuffer buffer, int required ) - { - buffer.flip(); - int capacity = buffer.capacity(); - do - { - capacity *= 2; - } - while ( capacity - buffer.limit() < required ); - return ByteBuffer.allocate( capacity ).order( ByteOrder.LITTLE_ENDIAN ).put( buffer ); - } - - private static RecordCursor newCursor( RecordStore store ) - { - return store.newRecordCursor( store.newRecord() ).acquire( store.getNumberOfReservedLowIds(), NORMAL ); + return propertyStore; } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/NodeStore.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/NodeStore.java index 7a5329613f1d7..79f4f3b382e2d 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/NodeStore.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/NodeStore.java @@ -26,6 +26,7 @@ import org.neo4j.io.pagecache.PageCache; import org.neo4j.kernel.configuration.Config; +import org.neo4j.kernel.impl.storageengine.impl.recordstorage.StoreStatement; import org.neo4j.kernel.impl.store.format.RecordFormats; import org.neo4j.kernel.impl.store.id.IdGeneratorFactory; import org.neo4j.kernel.impl.store.id.IdType; @@ -40,7 +41,7 @@ /** * Implementation of the node store. */ -public class NodeStore extends CommonAbstractStore +public class NodeStore extends CommonAbstractStore implements StoreStatement.Nodes { public static Long readOwnerFromDynamicLabelsRecord( DynamicRecord record ) { @@ -57,6 +58,13 @@ public static Long readOwnerFromDynamicLabelsRecord( DynamicRecord record ) return bits.getLong( requiredBits ); } + @Override + public RecordCursor newLabelCursor() + { + return dynamicLabelStore.newRecordCursor( dynamicLabelStore.newRecord() ).acquire( getNumberOfReservedLowIds(), + RecordLoad.NORMAL ); + } + public abstract static class Configuration extends CommonAbstractStore.Configuration { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/PropertyStore.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/PropertyStore.java index 5061c7e7a3dd7..d4802ac26b8b2 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/PropertyStore.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/PropertyStore.java @@ -20,6 +20,8 @@ package org.neo4j.kernel.impl.store; import java.io.File; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.nio.file.OpenOption; import java.util.ArrayList; import java.util.Collection; @@ -32,6 +34,7 @@ import org.neo4j.helpers.collection.Iterables; import org.neo4j.helpers.collection.Pair; import org.neo4j.io.pagecache.PageCache; +import org.neo4j.io.pagecache.PageCursor; import org.neo4j.kernel.configuration.Config; import org.neo4j.kernel.impl.store.format.Capability; import org.neo4j.kernel.impl.store.format.RecordFormats; @@ -45,6 +48,7 @@ import org.neo4j.kernel.impl.store.record.Record; import org.neo4j.kernel.impl.store.record.RecordLoad; import org.neo4j.logging.LogProvider; +import org.neo4j.storageengine.api.StorageStatement; import org.neo4j.string.UTF8; import org.neo4j.values.storable.ArrayValue; import org.neo4j.values.storable.CoordinateReferenceSystem; @@ -53,6 +57,7 @@ import static org.neo4j.kernel.impl.store.DynamicArrayStore.getRightArray; import static org.neo4j.kernel.impl.store.NoStoreHeaderFormat.NO_STORE_HEADER_FORMAT; +import static org.neo4j.kernel.impl.store.record.AbstractBaseRecord.NO_ID; import static org.neo4j.kernel.impl.store.record.RecordLoad.NORMAL; /** @@ -121,7 +126,7 @@ * values in next dimension long blocks * */ -public class PropertyStore extends CommonAbstractStore +public class PropertyStore extends CommonAbstractStore implements StorageStatement.Properties { public static final String TYPE_DESCRIPTOR = "PropertyStore"; @@ -318,6 +323,71 @@ public static void encodeValue( PropertyBlock block, int keyId, Value value, Dyn } } + @Override + public PageCursor openStringPageCursor( long reference ) + { + return stringStore.openPageCursorForReading( reference ); + } + + @Override + public PageCursor openArrayPageCursor( long reference ) + { + return arrayStore.openPageCursorForReading( reference ); + } + + @Override + public ByteBuffer loadString( long reference, ByteBuffer buffer, PageCursor page ) + { + return readDynamic( stringStore, reference, buffer, page ); + } + + @Override + public ByteBuffer loadArray( long reference, ByteBuffer buffer, PageCursor page ) + { + return readDynamic( arrayStore, reference, buffer, page ); + } + + private static ByteBuffer readDynamic( AbstractDynamicStore store, long reference, ByteBuffer buffer, + PageCursor page ) + { + if ( buffer == null ) + { + buffer = ByteBuffer.allocate( 512 ); + } + else + { + buffer.clear(); + } + DynamicRecord record = store.newRecord(); + do + { + //We need to load forcefully here since otherwise we can have inconsistent reads + //for properties across blocks, see org.neo4j.graphdb.ConsistentPropertyReadsIT + store.getRecordByCursor( reference, record, RecordLoad.FORCE, page ); + reference = record.getNextBlock(); + byte[] data = record.getData(); + if ( buffer.remaining() < data.length ) + { + buffer = grow( buffer, data.length ); + } + buffer.put( data, 0, data.length ); + } + while ( reference != NO_ID ); + return buffer; + } + + private static ByteBuffer grow( ByteBuffer buffer, int required ) + { + buffer.flip(); + int capacity = buffer.capacity(); + do + { + capacity *= 2; + } + while ( capacity - buffer.limit() < required ); + return ByteBuffer.allocate( capacity ).order( ByteOrder.LITTLE_ENDIAN ).put( buffer ); + } + private static class PropertyBlockValueWriter implements ValueWriter { private final PropertyBlock block; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/RelationshipGroupStore.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/RelationshipGroupStore.java index b289da1d034df..f796cbc5affa9 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/RelationshipGroupStore.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/RelationshipGroupStore.java @@ -30,8 +30,10 @@ import org.neo4j.kernel.impl.store.id.IdType; import org.neo4j.kernel.impl.store.record.RelationshipGroupRecord; import org.neo4j.logging.LogProvider; +import org.neo4j.storageengine.api.StorageStatement; -public class RelationshipGroupStore extends CommonAbstractStore +public class RelationshipGroupStore extends CommonAbstractStore implements + StorageStatement.Groups { public static final String TYPE_DESCRIPTOR = "RelationshipGroupStore"; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/RelationshipStore.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/RelationshipStore.java index 16cd16ce37703..bace49c8b3c60 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/RelationshipStore.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/RelationshipStore.java @@ -29,13 +29,14 @@ import org.neo4j.kernel.impl.store.id.IdType; import org.neo4j.kernel.impl.store.record.RelationshipRecord; import org.neo4j.logging.LogProvider; +import org.neo4j.storageengine.api.StorageStatement; import static org.neo4j.kernel.impl.store.NoStoreHeaderFormat.NO_STORE_HEADER_FORMAT; /** * Implementation of the relationship store. */ -public class RelationshipStore extends CommonAbstractStore +public class RelationshipStore extends CommonAbstractStore implements StorageStatement.Relationships { public static final String TYPE_DESCRIPTOR = "RelationshipStore"; diff --git a/community/kernel/src/main/java/org/neo4j/storageengine/api/StorageStatement.java b/community/kernel/src/main/java/org/neo4j/storageengine/api/StorageStatement.java index f8ee24a246a70..e1fcef0366997 100644 --- a/community/kernel/src/main/java/org/neo4j/storageengine/api/StorageStatement.java +++ b/community/kernel/src/main/java/org/neo4j/storageengine/api/StorageStatement.java @@ -116,13 +116,13 @@ Cursor acquireNodeRelationshipCursor( boolean isDense, long n Direction direction, IntPredicate relTypeFilter ); /** - - * Acquires {@link Cursor} capable of {@link Cursor#get() serving} {@link RelationshipItem} for selected - - * relationships. No relationship is selected when this method returns, a call to {@link Cursor#next()} - - * will have to be made to place the cursor over the first item and then more calls to move the cursor - - * through the selection. - - * - - * @return a {@link Cursor} over all stored relationships. - - */ + * Acquires {@link Cursor} capable of {@link Cursor#get() serving} {@link RelationshipItem} for selected + * relationships. No relationship is selected when this method returns, a call to {@link Cursor#next()} + * will have to be made to place the cursor over the first item and then more calls to move the cursor + * through the selection. + * + * @return a {@link Cursor} over all stored relationships. + */ Cursor relationshipsGetAllCursor(); Cursor acquirePropertyCursor( long propertyId, Lock shortLivedReadLock, AssertOpen assertOpen ); @@ -206,7 +206,7 @@ interface RecordReads * @param reference the initial node reference to access. * @return the opened PageCursor */ - PageCursor openPageCursor( long reference ); + PageCursor openPageCursorForReading( long reference ); /** * Load a node {@code record} with the node corresponding to the given node {@code reference}. @@ -220,7 +220,7 @@ interface RecordReads * @param cursor the PageCursor to use for record loading. * @throws InvalidRecordException if record not in use and the {@code mode} allows for throwing. */ - void loadRecordByCursor( long reference, RECORD record, RecordLoad mode, PageCursor cursor ) + void getRecordByCursor( long reference, RECORD record, RecordLoad mode, PageCursor cursor ) throws InvalidRecordException; long getHighestPossibleIdInUse();