From 57690cb03f1c57a0adde0d059442826859b93bb6 Mon Sep 17 00:00:00 2001 From: Mikhaylo Demianenko Date: Sun, 21 Feb 2016 16:09:27 +0100 Subject: [PATCH] Add support for secondary unit in commands Add support for secondary unit during RelationshipCommand, RelationshipGroupCommand, PropertyCommands serialization, support secondary unit in PhysicalLogCommandReaderV3_0. --- .../impl/api/TransactionApplierFacade.java | 3 +- .../recordstorage/RecordStorageEngine.java | 2 +- .../impl/store/record/AbstractBaseRecord.java | 2 +- .../kernel/impl/store/record/Record.java | 7 +- .../impl/transaction/command/Command.java | 43 +++-- .../command/IndexBatchTransactionApplier.java | 12 +- .../command/PhysicalLogCommandReaderV3_0.java | 59 +++---- .../transaction/log/entry/LogEntryWriter.java | 29 ++-- .../transaction/state/OnlineIndexUpdates.java | 3 - .../IndexBatchTransactionApplierTest.java | 4 +- .../NeoStoreTransactionApplierTest.java | 2 +- .../NeoTransactionIndexApplierTest.java | 4 +- .../PhysicalLogCommandReaderV3_0Test.java | 150 ++++++++++++++++++ ... => RelationshipGroupCommandV2_2Test.java} | 2 +- .../state/SchemaRuleCommandTest.java | 47 +++--- .../state/TransactionRecordStateTest.java | 2 +- 16 files changed, 279 insertions(+), 92 deletions(-) rename community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/{RelationshipGroupCommandTest.java => RelationshipGroupCommandV2_2Test.java} (98%) diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/TransactionApplierFacade.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/TransactionApplierFacade.java index 176364f9282ee..6d2d6f58080f4 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/TransactionApplierFacade.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/TransactionApplierFacade.java @@ -28,7 +28,8 @@ /** * Wraps several {@link TransactionApplier}s. In this case, each individual visit-call will delegate to {@link - * #visit(Command)} instead, which will call each wrapped {@link TransactionApplier} in turn. In {@link #close()}, + * #visit(StorageCommand)} instead, which will call each wrapped {@link TransactionApplier} in turn. In + * {@link #close()}, * the appliers are closed in reversed order. */ public class TransactionApplierFacade extends TransactionApplier.Adapter diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/storageengine/impl/recordstorage/RecordStorageEngine.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/storageengine/impl/recordstorage/RecordStorageEngine.java index 2360820ff3b85..f6797a6524f4c 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/storageengine/impl/recordstorage/RecordStorageEngine.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/storageengine/impl/recordstorage/RecordStorageEngine.java @@ -355,7 +355,7 @@ private BatchTransactionApplierFacade applier( TransactionApplicationMode mode ) // Schema index application appliers.add( new IndexBatchTransactionApplier( indexingService, labelScanStoreSync, indexUpdatesSync, - neoStores.getNodeStore(), neoStores.getPropertyStore(), new PropertyLoader( neoStores ), + neoStores.getNodeStore(), new PropertyLoader( neoStores ), indexUpdatesConverter, mode ) ); // Legacy index application diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/record/AbstractBaseRecord.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/record/AbstractBaseRecord.java index 76d6760c73d70..64c8a45095839 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/record/AbstractBaseRecord.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/record/AbstractBaseRecord.java @@ -87,7 +87,7 @@ public void setId( long id ) } /** - * Sets a secondary record unit ID for this record. If this is set to something other than {@code -1} + * Sets a secondary record unit ID for this record. If this is set to something other than {@link #NO_ID} * then {@link #requiresSecondaryUnit()} will return {@code true}. * Setting this id is separate from setting {@link #requiresSecondaryUnit()} since this secondary unit id * may be used to just free that id at the time of updating in the store if a record goes from two to one unit. diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/record/Record.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/record/Record.java index 1aec36ccb7e02..af88238d335c1 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/record/Record.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/record/Record.java @@ -45,16 +45,19 @@ public enum Record NO_LABELS_FIELD( (byte)0, 0 ); public static final byte CREATED_IN_TX = 2; + public static final byte REQUIRE_SECONDARY_UNIT = 4; + public static final byte HAS_SECONDARY_UNIT = 8; + private byte byteValue; private int intValue; - private Record( Record from ) + Record( Record from ) { this( from.byteValue, from.intValue ); } - private Record( byte byteValue, int intValue ) + Record( byte byteValue, int intValue ) { this.byteValue = byteValue; this.intValue = intValue; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/Command.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/Command.java index 8ae12341787c1..71badbb2618b5 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/Command.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/Command.java @@ -156,7 +156,10 @@ void writeDynamicRecord( WritableChannel channel, DynamicRecord record ) throws { inUse |= Record.FIRST_IN_CHAIN.byteValue(); } - channel.putLong( record.getId() ).putInt( record.getType() ).put( inUse ).putInt( record.getLength() ) + channel.putLong( record.getId() ) + .putInt( record.getType() ) + .put( inUse ) + .putInt( record.getLength() ) .putLong( record.getNextBlock() ); byte[] data = record.getData(); assert data != null; @@ -165,7 +168,9 @@ void writeDynamicRecord( WritableChannel channel, DynamicRecord record ) throws else { byte inUse = Record.NOT_IN_USE.byteValue(); - channel.putLong( record.getId() ).putInt( record.getType() ).put( inUse ); + channel.putLong( record.getId() ) + .putInt( record.getType() ) + .put( inUse ); } } @@ -262,7 +267,9 @@ public void serialize( WritableChannel channel ) throws IOException private void writeRelationshipRecord( WritableChannel channel, RelationshipRecord record ) throws IOException { byte flags = bitFlags( bitFlag( record.inUse(), Record.IN_USE.byteValue() ), - bitFlag( record.isCreated(), Record.CREATED_IN_TX ) ); + bitFlag( record.isCreated(), Record.CREATED_IN_TX ), + bitFlag( record.requiresSecondaryUnit(), Record.REQUIRE_SECONDARY_UNIT ), + bitFlag( record.hasSecondaryUnitId(), Record.HAS_SECONDARY_UNIT )); channel.put( flags ); if ( record.inUse() ) { @@ -271,6 +278,10 @@ private void writeRelationshipRecord( WritableChannel channel, RelationshipRecor .putLong( record.getSecondPrevRel() ).putLong( record.getSecondNextRel() ) .putLong( record.getNextProp() ) .put( (byte) ((record.isFirstInFirstChain() ? 1 : 0) | (record.isFirstInSecondChain() ? 2 : 0)) ); + if ( record.hasSecondaryUnitId() ) + { + channel.putLong( record.getSecondaryUnitId() ); + } } else { @@ -304,13 +315,20 @@ public void serialize( WritableChannel channel ) throws IOException private void writeRelationshipGroupRecord( WritableChannel channel, RelationshipGroupRecord record ) throws IOException { - channel.put( (byte) (record.inUse() ? Record.IN_USE.intValue() : Record.NOT_IN_USE.intValue()) ); + byte flags = bitFlags( bitFlag( record.inUse(), Record.IN_USE.byteValue() ), + bitFlag( record.requiresSecondaryUnit(), Record.REQUIRE_SECONDARY_UNIT ), + bitFlag( record.hasSecondaryUnitId(), Record.HAS_SECONDARY_UNIT ) ); + channel.put( flags ); channel.putShort( (short) record.getType() ); channel.putLong( record.getNext() ); channel.putLong( record.getFirstOut() ); channel.putLong( record.getFirstIn() ); channel.putLong( record.getFirstLoop() ); channel.putLong( record.getOwningNode() ); + if ( record.hasSecondaryUnitId() ) + { + channel.putLong( record.getSecondaryUnitId() ); + } } } @@ -375,13 +393,12 @@ public void serialize( WritableChannel channel ) throws IOException private void writePropertyRecord( WritableChannel channel, PropertyRecord record ) throws IOException { - byte inUse = record.inUse() ? Record.IN_USE.byteValue() : Record.NOT_IN_USE.byteValue(); - if ( record.getRelId() != -1 ) - { - // Here we add 2, i.e. set the second lsb. - inUse += Record.REL_PROPERTY.byteValue(); - } - channel.put( inUse ); // 1 + byte flags = bitFlags( bitFlag( record.inUse(), Record.IN_USE.byteValue() ), + bitFlag( record.getRelId() != -1, Record.REL_PROPERTY.byteValue() ), + bitFlag( record.requiresSecondaryUnit(), Record.REQUIRE_SECONDARY_UNIT ), + bitFlag( record.hasSecondaryUnitId(), Record.HAS_SECONDARY_UNIT ) ); + + channel.put( flags ); // 1 channel.putLong( record.getNextProp() ).putLong( record.getPrevProp() ); // 8 + 8 long nodeId = record.getNodeId(); long relId = record.getRelId(); @@ -399,6 +416,10 @@ else if ( relId != -1 ) // prop chain channel.putLong( -1 ); // 8 } + if ( record.hasSecondaryUnitId() ) + { + channel.putLong( record.getSecondaryUnitId() ); + } channel.put( (byte) record.numberOfProperties() ); // 1 for ( PropertyBlock block : record ) { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/IndexBatchTransactionApplier.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/IndexBatchTransactionApplier.java index aae2502a9b9a8..a8d8e7807f6e0 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/IndexBatchTransactionApplier.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/IndexBatchTransactionApplier.java @@ -68,7 +68,7 @@ public class IndexBatchTransactionApplier extends BatchTransactionApplier.Adapte public IndexBatchTransactionApplier( IndexingService indexingService, WorkSync,LabelUpdateWork> labelScanStoreSync, WorkSync indexUpdatesSync, - NodeStore nodeStore, PropertyStore propertyStore, PropertyLoader propertyLoader, + NodeStore nodeStore, PropertyLoader propertyLoader, PropertyPhysicalToLogicalConverter indexUpdateConverter, TransactionApplicationMode mode ) { @@ -76,7 +76,7 @@ public IndexBatchTransactionApplier( IndexingService indexingService, this.labelScanStoreSync = labelScanStoreSync; this.indexUpdatesSync = indexUpdatesSync; this.indexUpdateConverter = indexUpdateConverter; - this.transactionApplier = new SingleTransactionApplier( nodeStore, propertyStore, propertyLoader, mode ); + this.transactionApplier = new SingleTransactionApplier( nodeStore, propertyLoader, mode ); } @Override @@ -117,17 +117,15 @@ public void close() throws Exception private class SingleTransactionApplier extends TransactionApplier.Adapter { private final NodeStore nodeStore; - private final PropertyStore propertyStore; private final PropertyLoader propertyLoader; private final TransactionApplicationMode mode; private final NodePropertyCommandsExtractor indexUpdatesExtractor = new NodePropertyCommandsExtractor(); private List createdIndexes; - public SingleTransactionApplier( NodeStore nodeStore, PropertyStore propertyStore, - PropertyLoader propertyLoader, TransactionApplicationMode mode ) + public SingleTransactionApplier( NodeStore nodeStore, PropertyLoader propertyLoader, + TransactionApplicationMode mode ) { this.nodeStore = nodeStore; - this.propertyStore = propertyStore; this.propertyLoader = propertyLoader; this.mode = mode; } @@ -164,7 +162,7 @@ private IndexUpdates indexUpdates() private IndexUpdates createIndexUpdates() { return mode == TransactionApplicationMode.RECOVERY ? new RecoveryIndexUpdates() : - new OnlineIndexUpdates( nodeStore, propertyStore, propertyLoader, indexUpdateConverter ); + new OnlineIndexUpdates( nodeStore, propertyLoader, indexUpdateConverter ); } @Override diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV3_0.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV3_0.java index faf5ce4819f0f..c43ae2b070818 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV3_0.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV3_0.java @@ -58,7 +58,6 @@ import static org.neo4j.kernel.impl.transaction.command.CommandReading.PROPERTY_DELETED_DYNAMIC_RECORD_ADDER; import static org.neo4j.kernel.impl.transaction.command.CommandReading.PROPERTY_INDEX_DYNAMIC_RECORD_ADDER; import static org.neo4j.kernel.impl.util.Bits.bitFlag; -import static org.neo4j.kernel.impl.util.Bits.notFlag; import static org.neo4j.kernel.impl.util.IoPrimitiveUtils.read2bLengthAndString; import static org.neo4j.kernel.impl.util.IoPrimitiveUtils.read2bMap; import static org.neo4j.kernel.impl.util.IoPrimitiveUtils.read3bLengthAndString; @@ -206,12 +205,11 @@ private Command visitRelationshipGroupCommand( ReadableChannel channel ) throws private RelationshipGroupRecord readRelationshipGroupRecord( long id, ReadableChannel channel ) throws IOException { - byte inUseByte = channel.get(); - boolean inUse = inUseByte == Record.IN_USE.byteValue(); - if ( inUseByte != Record.IN_USE.byteValue() && inUseByte != Record.NOT_IN_USE.byteValue() ) - { - throw new IOException( "Illegal in use flag: " + inUseByte ); - } + byte flags = channel.get(); + boolean inUse = bitFlag( flags, Record.IN_USE.byteValue() ); + boolean requireSecondaryUnit = bitFlag( flags, Record.REQUIRE_SECONDARY_UNIT ); + boolean hasSecondaryUnit = bitFlag( flags, Record.HAS_SECONDARY_UNIT ); + int type = channel.getShort(); RelationshipGroupRecord record = new RelationshipGroupRecord( id, type ); record.setInUse( inUse ); @@ -220,6 +218,11 @@ private RelationshipGroupRecord readRelationshipGroupRecord( long id, ReadableCh record.setFirstIn( channel.getLong() ); record.setFirstLoop( channel.getLong() ); record.setOwningNode( channel.getLong() ); + record.setRequiresSecondaryUnit( requireSecondaryUnit ); + if ( hasSecondaryUnit ) + { + record.setSecondaryUnitId( channel.getLong() ); + } return record; } @@ -430,20 +433,15 @@ record = new NodeRecord( id ); private RelationshipRecord readRelationshipRecord( long id, ReadableChannel channel ) throws IOException { byte flags = channel.get(); - boolean inUse = false; - if ( notFlag( notFlag( flags, Record.IN_USE.byteValue() ), Record.CREATED_IN_TX ) != 0 ) - { - throw new IOException( "Illegal in use flag: " + flags ); - } - if ( bitFlag( flags, Record.IN_USE.byteValue() ) ) - { - inUse = true; - } + boolean inUse = bitFlag( flags, Record.IN_USE.byteValue() ); + boolean requiresSecondaryUnit = bitFlag( flags, Record.REQUIRE_SECONDARY_UNIT ); + boolean hasSecondaryUnit = bitFlag( flags, Record.HAS_SECONDARY_UNIT ); RelationshipRecord record; if ( inUse ) { record = new RelationshipRecord( id, channel.getLong(), channel.getLong(), channel.getInt() ); record.setInUse( true ); + record.setRequiresSecondaryUnit( requiresSecondaryUnit ); record.setFirstPrevRel( channel.getLong() ); record.setFirstNextRel( channel.getLong() ); record.setSecondPrevRel( channel.getLong() ); @@ -452,6 +450,10 @@ record = new RelationshipRecord( id, channel.getLong(), channel.getLong(), chann byte extraByte = channel.get(); record.setFirstInFirstChain( (extraByte & 0x1) > 0 ); record.setFirstInSecondChain( (extraByte & 0x2) > 0 ); + if (hasSecondaryUnit) + { + record.setSecondaryUnitId( channel.getLong() ); + } } else { @@ -517,21 +519,20 @@ private PropertyRecord readPropertyRecord( long id, ReadableChannel channel ) th // in_use(byte)+type(int)+key_indexId(int)+prop_blockId(long)+ // prev_prop_id(long)+next_prop_id(long) PropertyRecord record = new PropertyRecord( id ); - byte inUseFlag = channel.get(); // 1 + byte flags = channel.get(); // 1 + + boolean inUse = bitFlag( flags, Record.IN_USE.byteValue() ); + boolean nodeProperty = !bitFlag( flags, Record.REL_PROPERTY.byteValue() ); + boolean requireSecondaryUnit = bitFlag( flags, Record.REQUIRE_SECONDARY_UNIT ); + boolean hasSecondaryUnit = bitFlag( flags, Record.HAS_SECONDARY_UNIT ); + + record.setRequiresSecondaryUnit( requireSecondaryUnit ); + long nextProp = channel.getLong(); // 8 long prevProp = channel.getLong(); // 8 record.setNextProp( nextProp ); record.setPrevProp( prevProp ); - boolean inUse = false; - if ( (inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue() ) - { - inUse = true; - } - boolean nodeProperty = true; - if ( (inUseFlag & Record.REL_PROPERTY.byteValue()) == Record.REL_PROPERTY.byteValue() ) - { - nodeProperty = false; - } + long primitiveId = channel.getLong(); // 8 if ( primitiveId != -1 && nodeProperty ) { @@ -541,6 +542,10 @@ else if ( primitiveId != -1 ) { record.setRelId( primitiveId ); } + if (hasSecondaryUnit) + { + record.setSecondaryUnitId( channel.getLong() ); + } int nrPropBlocks = channel.get(); assert nrPropBlocks >= 0; if ( nrPropBlocks > 0 ) diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryWriter.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryWriter.java index 72ad118a05ed1..15eb3e57cc202 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryWriter.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryWriter.java @@ -42,16 +42,7 @@ public class LogEntryWriter public LogEntryWriter( FlushableChannel channel ) { this.channel = channel; - this.serializer = new Visitor() - { - @Override - public boolean visit( StorageCommand command ) throws IOException - { - writeLogEntryHeader( COMMAND ); - command.serialize( channel ); - return false; - } - }; + this.serializer = new StorageCommandSerializer( channel ); } private void writeLogEntryHeader( byte type ) throws IOException @@ -92,4 +83,22 @@ public void writeCheckPointEntry( LogPosition logPosition ) throws IOException channel.putLong( logPosition.getLogVersion() ). putLong( logPosition.getByteOffset() ); } + + private class StorageCommandSerializer implements Visitor + { + private final FlushableChannel channel; + + public StorageCommandSerializer( FlushableChannel channel ) + { + this.channel = channel; + } + + @Override + public boolean visit( StorageCommand command ) throws IOException + { + writeLogEntryHeader( COMMAND ); + command.serialize( channel ); + return false; + } + } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/state/OnlineIndexUpdates.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/state/OnlineIndexUpdates.java index 23fe60abbf1c6..db7774cc7096a 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/state/OnlineIndexUpdates.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/state/OnlineIndexUpdates.java @@ -64,19 +64,16 @@ public class OnlineIndexUpdates implements IndexUpdates { private final NodeStore nodeStore; - private final PropertyStore propertyStore; private final PropertyLoader propertyLoader; private final PropertyPhysicalToLogicalConverter converter; private final Collection updates = new ArrayList<>(); private NodeRecord nodeRecord; public OnlineIndexUpdates( NodeStore nodeStore, - PropertyStore propertyStore, PropertyLoader propertyLoader, PropertyPhysicalToLogicalConverter converter ) { this.nodeStore = nodeStore; - this.propertyStore = propertyStore; this.propertyLoader = propertyLoader; this.converter = converter; } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/IndexBatchTransactionApplierTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/IndexBatchTransactionApplierTest.java index 61588593eb88e..aaff5629f30be 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/IndexBatchTransactionApplierTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/IndexBatchTransactionApplierTest.java @@ -61,8 +61,8 @@ public void shouldProvideLabelScanStoreUpdatesSortedByNodeId() throws Exception TransactionToApply tx = mock( TransactionToApply.class ); PropertyStore propertyStore = mock( PropertyStore.class ); try ( IndexBatchTransactionApplier applier = new IndexBatchTransactionApplier( indexing, labelScanSync, - indexUpdatesSync, mock( NodeStore.class ), propertyStore, - mock( PropertyLoader.class ), new PropertyPhysicalToLogicalConverter( propertyStore ), + indexUpdatesSync, mock( NodeStore.class ), mock( PropertyLoader.class ), + new PropertyPhysicalToLogicalConverter( propertyStore ), TransactionApplicationMode.INTERNAL ) ) { try ( TransactionApplier txApplier = applier.startTx( tx ) ) diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/NeoStoreTransactionApplierTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/NeoStoreTransactionApplierTest.java index 53b3eb45dc5a9..3a84991c632f9 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/NeoStoreTransactionApplierTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/NeoStoreTransactionApplierTest.java @@ -931,7 +931,7 @@ private BatchTransactionApplier newApplierFacade( BatchTransactionApplier... app private BatchTransactionApplier newIndexApplier() { return new IndexBatchTransactionApplier( indexingService, labelScanStoreSynchronizer, - indexUpdatesSync, nodeStore, propertyStore, new PropertyLoader( neoStores ), + indexUpdatesSync, nodeStore, new PropertyLoader( neoStores ), new PropertyPhysicalToLogicalConverter( propertyStore ), INTERNAL ); } } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/NeoTransactionIndexApplierTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/NeoTransactionIndexApplierTest.java index 32de876bb9348..b83b2e612b490 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/NeoTransactionIndexApplierTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/NeoTransactionIndexApplierTest.java @@ -95,8 +95,8 @@ private IndexBatchTransactionApplier newIndexTransactionApplier() { PropertyStore propertyStore = mock( PropertyStore.class ); return new IndexBatchTransactionApplier( indexingService, - labelScanStoreSynchronizer, indexUpdatesSync, mock( NodeStore.class ), propertyStore, mock( - PropertyLoader.class ), new PropertyPhysicalToLogicalConverter( propertyStore ), + labelScanStoreSynchronizer, indexUpdatesSync, mock( NodeStore.class ), + mock(PropertyLoader.class ), new PropertyPhysicalToLogicalConverter( propertyStore ), TransactionApplicationMode.INTERNAL ); } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV3_0Test.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV3_0Test.java index 2518cf4934385..dc0972c0e44a4 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV3_0Test.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV3_0Test.java @@ -21,8 +21,12 @@ import org.junit.Test; +import java.io.IOException; + import org.neo4j.kernel.impl.store.PropertyType; +import org.neo4j.kernel.impl.store.record.AbstractBaseRecord; import org.neo4j.kernel.impl.store.record.NeoStoreRecord; +import org.neo4j.kernel.impl.store.record.PropertyRecord; import org.neo4j.kernel.impl.store.record.RelationshipGroupRecord; import org.neo4j.kernel.impl.store.record.RelationshipRecord; import org.neo4j.kernel.impl.transaction.log.InMemoryClosableChannel; @@ -54,6 +58,46 @@ public void shouldReadRelationshipCommand() throws Throwable assertEquals( after, relationshipCommand.getAfter() ); } + @Test + public void readRelationshipCommandWithSecondaryUnit() throws IOException + { + InMemoryClosableChannel channel = new InMemoryClosableChannel(); + RelationshipRecord before = new RelationshipRecord( 42, true, 1, 2, 3, 4, 5, 6, 7, true, true ); + before.setRequiresSecondaryUnit( true ); + before.setSecondaryUnitId( 47 ); + RelationshipRecord after = new RelationshipRecord( 42, true, 1, 8, 3, 4, 5, 6, 7, true, true ); + new Command.RelationshipCommand( before, after ).serialize( channel ); + + PhysicalLogCommandReaderV3_0 reader = new PhysicalLogCommandReaderV3_0(); + Command command = reader.read( channel ); + assertTrue( command instanceof Command.RelationshipCommand ); + + Command.RelationshipCommand relationshipCommand = (Command.RelationshipCommand) command; + assertEquals( before, relationshipCommand.getBefore() ); + verifySecondaryUnit( before, relationshipCommand.getBefore() ); + assertEquals( after, relationshipCommand.getAfter() ); + } + + @Test + public void readRelationshipCommandWithNonRequiredSecondaryUnit() throws IOException + { + InMemoryClosableChannel channel = new InMemoryClosableChannel(); + RelationshipRecord before = new RelationshipRecord( 42, true, 1, 2, 3, 4, 5, 6, 7, true, true ); + before.setRequiresSecondaryUnit( false ); + before.setSecondaryUnitId( 52 ); + RelationshipRecord after = new RelationshipRecord( 42, true, 1, 8, 3, 4, 5, 6, 7, true, true ); + new Command.RelationshipCommand( before, after ).serialize( channel ); + + PhysicalLogCommandReaderV3_0 reader = new PhysicalLogCommandReaderV3_0(); + Command command = reader.read( channel ); + assertTrue( command instanceof Command.RelationshipCommand ); + + Command.RelationshipCommand relationshipCommand = (Command.RelationshipCommand) command; + assertEquals( before, relationshipCommand.getBefore() ); + verifySecondaryUnit( before, relationshipCommand.getBefore() ); + assertEquals( after, relationshipCommand.getAfter() ); + } + @Test public void shouldReadRelationshipGroupCommand() throws Throwable { @@ -77,6 +121,58 @@ public void shouldReadRelationshipGroupCommand() throws Throwable assertEquals( after, relationshipGroupCommand.getAfter() ); } + @Test + public void readRelationshipGroupCommandWithSecondaryUnit() throws IOException + { + // Given + InMemoryClosableChannel channel = new InMemoryClosableChannel(); + RelationshipGroupRecord before = new RelationshipGroupRecord( 42, 3 ); + RelationshipGroupRecord after = new RelationshipGroupRecord( 42, 3, 4, 5, 6, 7, 8, true ); + after.setRequiresSecondaryUnit( true ); + after.setSecondaryUnitId( 17 ); + after.setCreated(); + + new Command.RelationshipGroupCommand( before, after ).serialize( channel ); + + // When + PhysicalLogCommandReaderV3_0 reader = new PhysicalLogCommandReaderV3_0(); + Command command = reader.read( channel ); + assertTrue( command instanceof Command.RelationshipGroupCommand); + + Command.RelationshipGroupCommand relationshipGroupCommand = (Command.RelationshipGroupCommand) command; + + // Then + assertEquals( before, relationshipGroupCommand.getBefore() ); + assertEquals( after, relationshipGroupCommand.getAfter() ); + verifySecondaryUnit( after, relationshipGroupCommand.getAfter() ); + } + + @Test + public void readRelationshipGroupCommandWithNonRequiredSecondaryUnit() throws IOException + { + // Given + InMemoryClosableChannel channel = new InMemoryClosableChannel(); + RelationshipGroupRecord before = new RelationshipGroupRecord( 42, 3 ); + RelationshipGroupRecord after = new RelationshipGroupRecord( 42, 3, 4, 5, 6, 7, 8, true ); + after.setRequiresSecondaryUnit( false ); + after.setSecondaryUnitId( 17 ); + after.setCreated(); + + new Command.RelationshipGroupCommand( before, after ).serialize( channel ); + + // When + PhysicalLogCommandReaderV3_0 reader = new PhysicalLogCommandReaderV3_0(); + Command command = reader.read( channel ); + assertTrue( command instanceof Command.RelationshipGroupCommand); + + Command.RelationshipGroupCommand relationshipGroupCommand = (Command.RelationshipGroupCommand) command; + + // Then + assertEquals( before, relationshipGroupCommand.getBefore() ); + assertEquals( after, relationshipGroupCommand.getAfter() ); + verifySecondaryUnit( after, relationshipGroupCommand.getAfter() ); + } + @Test public void shouldReadNeoStoreCommand() throws Throwable { @@ -100,6 +196,52 @@ public void shouldReadNeoStoreCommand() throws Throwable assertEquals( after.getNextProp(), neoStoreCommand.getAfter().getNextProp() ); } + @Test + public void readPropertyCommandWithSecondaryUnit() throws IOException + { + InMemoryClosableChannel channel = new InMemoryClosableChannel(); + PropertyRecord before = new PropertyRecord( 1 ); + PropertyRecord after = new PropertyRecord( 2 ); + after.setRequiresSecondaryUnit( true ); + after.setSecondaryUnitId( 78 ); + + new Command.PropertyCommand( before, after ).serialize( channel ); + + PhysicalLogCommandReaderV3_0 reader = new PhysicalLogCommandReaderV3_0(); + Command command = reader.read( channel ); + assertTrue( command instanceof Command.PropertyCommand); + + Command.PropertyCommand neoStoreCommand = (Command.PropertyCommand) command; + + // Then + assertEquals( before.getNextProp(), neoStoreCommand.getBefore().getNextProp() ); + assertEquals( after.getNextProp(), neoStoreCommand.getAfter().getNextProp() ); + verifySecondaryUnit( after, neoStoreCommand.getAfter() ); + } + + @Test + public void readPropertyCommandWithNonRequiredSecondaryUnit() throws IOException + { + InMemoryClosableChannel channel = new InMemoryClosableChannel(); + PropertyRecord before = new PropertyRecord( 1 ); + PropertyRecord after = new PropertyRecord( 2 ); + after.setRequiresSecondaryUnit( false ); + after.setSecondaryUnitId( 78 ); + + new Command.PropertyCommand( before, after ).serialize( channel ); + + PhysicalLogCommandReaderV3_0 reader = new PhysicalLogCommandReaderV3_0(); + Command command = reader.read( channel ); + assertTrue( command instanceof Command.PropertyCommand); + + Command.PropertyCommand neoStoreCommand = (Command.PropertyCommand) command; + + // Then + assertEquals( before.getNextProp(), neoStoreCommand.getBefore().getNextProp() ); + assertEquals( after.getNextProp(), neoStoreCommand.getAfter().getNextProp() ); + verifySecondaryUnit( after, neoStoreCommand.getAfter() ); + } + @Test public void shouldReadSomeCommands() throws Exception { @@ -121,4 +263,12 @@ public void shouldReadSomeCommands() throws Exception assertTrue( reader.read( channel ) instanceof Command.PropertyKeyTokenCommand ); assertTrue( reader.read( channel ) instanceof Command.PropertyCommand ); } + + private void verifySecondaryUnit( T record, T commandRecord ) + { + assertEquals( "Secondary unit requirements should be the same", record.requiresSecondaryUnit(), + commandRecord.requiresSecondaryUnit() ); + assertEquals( "Secondary unit ids should be the same", record.getSecondaryUnitId(), + commandRecord.getSecondaryUnitId() ); + } } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/RelationshipGroupCommandTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/RelationshipGroupCommandV2_2Test.java similarity index 98% rename from community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/RelationshipGroupCommandTest.java rename to community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/RelationshipGroupCommandV2_2Test.java index 30ddaec3bb900..7d018453c3f77 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/RelationshipGroupCommandTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/RelationshipGroupCommandV2_2Test.java @@ -32,7 +32,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsEqual.equalTo; -public class RelationshipGroupCommandTest +public class RelationshipGroupCommandV2_2Test { @Test public void shouldSerializeAndDeserializeUnusedRecords() throws Exception diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/SchemaRuleCommandTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/SchemaRuleCommandTest.java index 7e94f8f53c45f..eae5da06e00a9 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/SchemaRuleCommandTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/SchemaRuleCommandTest.java @@ -68,6 +68,30 @@ public class SchemaRuleCommandTest { + + private final int labelId = 2; + private final int propertyKey = 8; + private final long id = 0; + private final long txId = 1337l; + private final NeoStores neoStores = mock( NeoStores.class ); + private final MetaDataStore metaDataStore = mock( MetaDataStore.class ); + private final SchemaStore schemaStore = mock( SchemaStore.class ); + private final IndexingService indexes = mock( IndexingService.class ); + @SuppressWarnings( "unchecked" ) + private final Supplier labelScanStore = mock( Supplier.class ); + private final NeoStoreBatchTransactionApplier storeApplier = new NeoStoreBatchTransactionApplier( neoStores, + mock( CacheAccessBackDoor.class ), LockService.NO_LOCK_SERVICE ); + private final WorkSync,LabelUpdateWork> labelScanStoreSynchronizer = + new WorkSync<>( labelScanStore ); + private final WorkSync indexUpdatesSync = new WorkSync<>( indexes ); + private final PropertyStore propertyStore = mock( PropertyStore.class ); + private final IndexBatchTransactionApplier indexApplier = new IndexBatchTransactionApplier( indexes, + labelScanStoreSynchronizer, indexUpdatesSync, mock( NodeStore.class ), + mock( PropertyLoader.class ), new PropertyPhysicalToLogicalConverter( propertyStore ), + TransactionApplicationMode.INTERNAL ); + private final PhysicalLogCommandReaderV2_2 reader = new PhysicalLogCommandReaderV2_2(); + private final IndexRule rule = IndexRule.indexRule( id, labelId, propertyKey, PROVIDER_DESCRIPTOR ); + @Test public void shouldWriteCreatedSchemaRuleToStore() throws Exception { @@ -195,28 +219,7 @@ public void shouldRecreateSchemaRuleWhenDeleteCommandReadFromDisk() throws Excep assertSchemaRule( (SchemaRuleCommand)readCommand ); } - private final int labelId = 2; - private final int propertyKey = 8; - private final long id = 0; - private final long txId = 1337l; - private final NeoStores neoStores = mock( NeoStores.class ); - private final MetaDataStore metaDataStore = mock( MetaDataStore.class ); - private final SchemaStore schemaStore = mock( SchemaStore.class ); - private final IndexingService indexes = mock( IndexingService.class ); - @SuppressWarnings( "unchecked" ) - private final Supplier labelScanStore = mock( Supplier.class ); - private final NeoStoreBatchTransactionApplier storeApplier = new NeoStoreBatchTransactionApplier( neoStores, - mock( CacheAccessBackDoor.class ), LockService.NO_LOCK_SERVICE ); - private final WorkSync,LabelUpdateWork> labelScanStoreSynchronizer = - new WorkSync<>( labelScanStore ); - private final WorkSync indexUpdatesSync = new WorkSync<>( indexes ); - private final PropertyStore propertyStore = mock( PropertyStore.class ); - private final IndexBatchTransactionApplier indexApplier = new IndexBatchTransactionApplier( indexes, - labelScanStoreSynchronizer, indexUpdatesSync, mock( NodeStore.class ), propertyStore, - mock( PropertyLoader.class ), new PropertyPhysicalToLogicalConverter( propertyStore ), - TransactionApplicationMode.INTERNAL ); - private final PhysicalLogCommandReaderV2_2 reader = new PhysicalLogCommandReaderV2_2(); - private final IndexRule rule = IndexRule.indexRule( id, labelId, propertyKey, PROVIDER_DESCRIPTOR ); + private SchemaRecord serialize( AbstractSchemaRule rule, long id, boolean inUse, boolean created ) { diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/TransactionRecordStateTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/TransactionRecordStateTest.java index 26620c16cb6da..6f74eb3db9380 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/TransactionRecordStateTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/TransactionRecordStateTest.java @@ -1174,7 +1174,7 @@ private Iterable indexUpdatesOf( NeoStores neoStores, Transa transaction.accept( extractor ); OnlineIndexUpdates lazyIndexUpdates = new OnlineIndexUpdates( neoStores.getNodeStore(), - neoStores.getPropertyStore(), new PropertyLoader( neoStores ), + new PropertyLoader( neoStores ), new PropertyPhysicalToLogicalConverter( neoStores.getPropertyStore() ) ); lazyIndexUpdates.feed( extractor.propertyCommandsByNodeIds(), extractor.nodeCommandsById() ); return lazyIndexUpdates;