Skip to content

Commit

Permalink
Adds secondary unit information in serialized NodeCommands
Browse files Browse the repository at this point in the history
Adds boolean flags related to secondary unit usage in the first
 byte serialized as part of NodeCommands, in a fashion similar to
 RelationshipCommand.
The NodeCommandTest is improved with additional assertions.
  • Loading branch information
digitalstain committed Apr 20, 2016
1 parent d809f63 commit 91ddb67
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 18 deletions.
Expand Up @@ -226,13 +226,19 @@ public void serialize( WritableChannel channel ) throws IOException


private boolean writeNodeRecord( WritableChannel channel, NodeRecord record ) throws IOException private boolean writeNodeRecord( WritableChannel channel, NodeRecord record ) throws IOException
{ {
byte inUse = record.inUse() ? Record.IN_USE.byteValue() : Record.NOT_IN_USE.byteValue(); byte flags = bitFlags( bitFlag( record.inUse(), Record.IN_USE.byteValue() ),
channel.put( inUse ); bitFlag( record.requiresSecondaryUnit(), Record.REQUIRE_SECONDARY_UNIT ),
bitFlag( record.hasSecondaryUnitId(), Record.HAS_SECONDARY_UNIT ) );
channel.put( flags );
if ( record.inUse() ) if ( record.inUse() )
{ {
channel.put( record.isDense() ? (byte) 1 : (byte) 0 ); channel.put( record.isDense() ? (byte) 1 : (byte) 0 );
channel.putLong( record.getNextRel() ).putLong( record.getNextProp() ); channel.putLong( record.getNextRel() ).putLong( record.getNextProp() );
channel.putLong( record.getLabelField() ); channel.putLong( record.getLabelField() );
if( record.hasSecondaryUnitId() )
{
channel.putLong( record.getSecondaryUnitId() );
}
} }
// Always write dynamic label records because we want to know which ones have been deleted // Always write dynamic label records because we want to know which ones have been deleted
// especially if the node has been deleted. // especially if the node has been deleted.
Expand Down
Expand Up @@ -155,7 +155,6 @@ private Command visitRelationshipCommand( ReadableChannel channel ) throws IOExc
{ {
long id = channel.getLong(); long id = channel.getLong();



RelationshipRecord before = readRelationshipRecord( id, channel ); RelationshipRecord before = readRelationshipRecord( id, channel );
if ( before == null ) if ( before == null )
{ {
Expand Down Expand Up @@ -400,16 +399,11 @@ private NeoStoreRecord readNeoStoreRecord( ReadableChannel channel ) throws IOEx


private NodeRecord readNodeRecord( long id, ReadableChannel channel ) throws IOException private NodeRecord readNodeRecord( long id, ReadableChannel channel ) throws IOException
{ {
byte inUseFlag = channel.get(); byte flags = channel.get();
boolean inUse = false; boolean inUse = bitFlag( flags, Record.IN_USE.byteValue() );
if ( inUseFlag == Record.IN_USE.byteValue() ) boolean requiresSecondaryUnit = bitFlag( flags, Record.REQUIRE_SECONDARY_UNIT );
{ boolean hasSecondaryUnit = bitFlag( flags, Record.HAS_SECONDARY_UNIT );
inUse = true;
}
else if ( inUseFlag != Record.NOT_IN_USE.byteValue() )
{
throw new IOException( "Illegal in use flag: " + inUseFlag );
}
NodeRecord record; NodeRecord record;
Collection<DynamicRecord> dynamicLabelRecords = new ArrayList<>(); Collection<DynamicRecord> dynamicLabelRecords = new ArrayList<>();
long labelField = Record.NO_LABELS_FIELD.intValue(); long labelField = Record.NO_LABELS_FIELD.intValue();
Expand All @@ -419,6 +413,11 @@ else if ( inUseFlag != Record.NOT_IN_USE.byteValue() )
record = new NodeRecord( id, dense, channel.getLong(), channel.getLong() ); record = new NodeRecord( id, dense, channel.getLong(), channel.getLong() );
// labels // labels
labelField = channel.getLong(); labelField = channel.getLong();
record.setRequiresSecondaryUnit( requiresSecondaryUnit );
if( hasSecondaryUnit )
{
record.setSecondaryUnitId( channel.getLong() );
}
} }
else else
{ {
Expand Down Expand Up @@ -450,7 +449,7 @@ record = new RelationshipRecord( id, channel.getLong(), channel.getLong(), chann
byte extraByte = channel.get(); byte extraByte = channel.get();
record.setFirstInFirstChain( (extraByte & 0x1) > 0 ); record.setFirstInFirstChain( (extraByte & 0x1) > 0 );
record.setFirstInSecondChain( (extraByte & 0x2) > 0 ); record.setFirstInSecondChain( (extraByte & 0x2) > 0 );
if (hasSecondaryUnit) if ( hasSecondaryUnit )
{ {
record.setSecondaryUnitId( channel.getLong() ); record.setSecondaryUnitId( channel.getLong() );
} }
Expand Down
Expand Up @@ -41,7 +41,7 @@
import org.neo4j.kernel.impl.store.record.DynamicRecord; import org.neo4j.kernel.impl.store.record.DynamicRecord;
import org.neo4j.kernel.impl.store.record.NodeRecord; import org.neo4j.kernel.impl.store.record.NodeRecord;
import org.neo4j.kernel.impl.transaction.command.Command; import org.neo4j.kernel.impl.transaction.command.Command;
import org.neo4j.kernel.impl.transaction.command.PhysicalLogCommandReaderV2_2; import org.neo4j.kernel.impl.transaction.command.PhysicalLogCommandReaderV3_0;
import org.neo4j.kernel.impl.transaction.log.InMemoryClosableChannel; import org.neo4j.kernel.impl.transaction.log.InMemoryClosableChannel;
import org.neo4j.logging.NullLogProvider; import org.neo4j.logging.NullLogProvider;
import org.neo4j.storageengine.api.CommandReader; import org.neo4j.storageengine.api.CommandReader;
Expand All @@ -54,6 +54,7 @@
import static org.neo4j.kernel.impl.store.DynamicNodeLabels.dynamicPointer; import static org.neo4j.kernel.impl.store.DynamicNodeLabels.dynamicPointer;
import static org.neo4j.kernel.impl.store.NodeLabelsField.parseLabelsField; import static org.neo4j.kernel.impl.store.NodeLabelsField.parseLabelsField;
import static org.neo4j.kernel.impl.store.ShortArray.LONG; import static org.neo4j.kernel.impl.store.ShortArray.LONG;
import static org.neo4j.kernel.impl.store.record.AbstractBaseRecord.NO_ID;
import static org.neo4j.kernel.impl.store.record.DynamicRecord.dynamicRecord; import static org.neo4j.kernel.impl.store.record.DynamicRecord.dynamicRecord;
import static org.neo4j.kernel.impl.util.IoPrimitiveUtils.safeCastLongToInt; import static org.neo4j.kernel.impl.util.IoPrimitiveUtils.safeCastLongToInt;


Expand All @@ -63,7 +64,7 @@ public class NodeCommandTest
public static PageCacheRule pageCacheRule = new PageCacheRule(); public static PageCacheRule pageCacheRule = new PageCacheRule();
private NodeStore nodeStore; private NodeStore nodeStore;
InMemoryClosableChannel channel = new InMemoryClosableChannel(); InMemoryClosableChannel channel = new InMemoryClosableChannel();
private final CommandReader commandReader = new PhysicalLogCommandReaderV2_2(); private final CommandReader commandReader = new PhysicalLogCommandReaderV3_0();
@Rule @Rule
public EphemeralFileSystemRule fs = new EphemeralFileSystemRule(); public EphemeralFileSystemRule fs = new EphemeralFileSystemRule();
private NeoStores neoStores; private NeoStores neoStores;
Expand All @@ -90,6 +91,18 @@ public void shouldSerializeCreatedRecord() throws Exception
assertSerializationWorksFor( new Command.NodeCommand( before, after ) ); assertSerializationWorksFor( new Command.NodeCommand( before, after ) );
} }


@Test
public void shouldSerializeDenseRecord() throws Exception
{
// Given
NodeRecord before = new NodeRecord( 12, false, 1, 2 );
before.setInUse( true );
NodeRecord after = new NodeRecord( 12, true, 2, 1 );
after.setInUse( true );
// When
assertSerializationWorksFor( new Command.NodeCommand( before, after ) );
}

@Test @Test
public void shouldSerializeUpdatedRecord() throws Exception public void shouldSerializeUpdatedRecord() throws Exception
{ {
Expand All @@ -116,6 +129,26 @@ public void shouldSerializeInlineLabels() throws Exception
assertSerializationWorksFor( new Command.NodeCommand( before, after ) ); assertSerializationWorksFor( new Command.NodeCommand( before, after ) );
} }


@Test
public void shouldSerializeSecondaryUnitUsage() throws Exception
{
// Given
// a record that is changed to include a secondary unit
NodeRecord before = new NodeRecord( 13, false, 1, 2 );
before.setInUse( true );
before.setRequiresSecondaryUnit( false );
before.setSecondaryUnitId( NO_ID ); // this and the previous line set the defaults, they are here for clarity
NodeRecord after = new NodeRecord( 13, false, 1, 2 );
after.setInUse( true );
after.setRequiresSecondaryUnit( true );
after.setSecondaryUnitId( 14L );

Command.NodeCommand command = new Command.NodeCommand( before, after );

// Then
assertSerializationWorksFor( command );
}

@Test @Test
public void shouldSerializeDynamicRecordLabels() throws Exception public void shouldSerializeDynamicRecordLabels() throws Exception
{ {
Expand Down Expand Up @@ -173,12 +206,26 @@ private void assertSerializationWorksFor( org.neo4j.kernel.impl.transaction.comm
assertThat( result.getMode(), equalTo( cmd.getMode() ) ); assertThat( result.getMode(), equalTo( cmd.getMode() ) );
assertThat( result.getBefore(), equalTo( cmd.getBefore() ) ); assertThat( result.getBefore(), equalTo( cmd.getBefore() ) );
assertThat( result.getAfter(), equalTo( cmd.getAfter() ) ); assertThat( result.getAfter(), equalTo( cmd.getAfter() ) );
// And created and dense flags should be the same
assertThat( result.getBefore().isCreated(), equalTo( cmd.getBefore().isCreated() ) );
assertThat( result.getAfter().isCreated(), equalTo( cmd.getAfter().isCreated() ) );
assertThat( result.getBefore().isDense(), equalTo( cmd.getBefore().isDense() ) );
assertThat( result.getAfter().isDense(), equalTo( cmd.getAfter().isDense()) );
// And labels should be the same // And labels should be the same
assertThat( labels( result.getBefore() ), equalTo( labels( cmd.getBefore() ) ) ); assertThat( labels( result.getBefore() ), equalTo( labels( cmd.getBefore() ) ) );
assertThat( labels( result.getAfter() ), equalTo( labels( cmd.getAfter() ) ) ); assertThat( labels( result.getAfter() ), equalTo( labels( cmd.getAfter() ) ) );
// And dynamic records should be the same // And dynamic records should be the same
assertThat( result.getBefore().getDynamicLabelRecords(), equalTo( result.getBefore().getDynamicLabelRecords() ) ); assertThat( result.getBefore().getDynamicLabelRecords(), equalTo( cmd.getBefore().getDynamicLabelRecords() ) );
assertThat( result.getAfter().getDynamicLabelRecords(), equalTo( result.getAfter().getDynamicLabelRecords() ) ); assertThat( result.getAfter().getDynamicLabelRecords(), equalTo( cmd.getAfter().getDynamicLabelRecords() ) );
// And the secondary unit information should be the same
// Before
assertThat( result.getBefore().requiresSecondaryUnit(), equalTo( cmd.getBefore().requiresSecondaryUnit() ) );
assertThat( result.getBefore().hasSecondaryUnitId(), equalTo( cmd.getBefore().hasSecondaryUnitId() ) );
assertThat( result.getBefore().getSecondaryUnitId(), equalTo( cmd.getBefore().getSecondaryUnitId() ) );
// and after
assertThat( result.getAfter().requiresSecondaryUnit(), equalTo( cmd.getAfter().requiresSecondaryUnit() ) );
assertThat( result.getAfter().hasSecondaryUnitId(), equalTo( cmd.getAfter().hasSecondaryUnitId() ) );
assertThat( result.getAfter().getSecondaryUnitId(), equalTo( cmd.getAfter().getSecondaryUnitId() ) );
} }


private Set<Integer> labels( NodeRecord record ) private Set<Integer> labels( NodeRecord record )
Expand Down

0 comments on commit 91ddb67

Please sign in to comment.