Skip to content

Commit

Permalink
Introduce constants for various bit masks, small refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
MishaDemianenko committed Aug 2, 2016
1 parent ec6a672 commit 5a6e977
Show file tree
Hide file tree
Showing 4 changed files with 270 additions and 201 deletions.
Expand Up @@ -48,6 +48,13 @@ class NodeRecordFormat extends BaseHighLimitRecordFormat<NodeRecord>
private static final int HAS_PROPERTY_BIT = 0b0010_0000;
private static final int HAS_LABELS_BIT = 0b0100_0000;

private static final long RELATIONSHIP_HIGHER_BITS_MASK = 0x1_0000_0000L;
private static final long PROPERTY_HIGHER_BITS_MASK = 0x3_0000_0000L;
private static final long RELATIONSHIP_LOWER_BITS_MASK = RELATIONSHIP_HIGHER_BITS_MASK >> 32;
private static final long PROPERTY_LOWER_BITS_MASK = PROPERTY_HIGHER_BITS_MASK >> 31;
private static final long ONE_BIT_OVERFLOW_BIT_MASK = 0xFFFF_FFFE_0000_0000L;
private static final long THREE_BITS_OVERFLOW_BIT_MASK = 0xFFFF_FFFC_0000_0000L;

public NodeRecordFormat()
{
this( RECORD_SIZE );
Expand All @@ -72,20 +79,7 @@ protected void doReadInternal( NodeRecord record, PageCursor cursor, int recordS
boolean dense = has( headerByte, DENSE_NODE_BIT );
if ( record.isUseFixedReferences() )
{
byte modifiers = cursor.getByte();
long relModifier = (modifiers & 0b0000_0001L) << 32;
long propModifier = (modifiers & 0b0000_0110L) << 31;

long nextRel = cursor.getInt() & 0xFFFFFFFFL;
long nextProp = cursor.getInt() & 0xFFFFFFFFL;

long lsbLabels = cursor.getInt() & 0xFFFFFFFFL;
long hsbLabels = cursor.getByte() & 0xFF; // so that a negative byte won't fill the "extended" bits with ones.
long labels = lsbLabels | (hsbLabels << 32);

record.initialize( inUse,
BaseRecordFormat.longFromIntAndMod( nextProp, propModifier ), dense,
BaseRecordFormat.longFromIntAndMod( nextRel, relModifier ), labels );
readFixedReferencesRecord( record, cursor, inUse, dense );
}
else
{
Expand Down Expand Up @@ -120,8 +114,8 @@ protected byte headerBits( NodeRecord record )
@Override
protected boolean canUseFixedReferences( NodeRecord record )
{
return (((record.getNextProp() == NULL) || ((record.getNextProp() & 0xFFFF_FFFC_0000_0000L) == 0)) &&
((record.getNextRel() == NULL) || ((record.getNextRel() & 0xFFFF_FFFE_0000_0000L) == 0)));
return (((record.getNextProp() == NULL) || ((record.getNextProp() & THREE_BITS_OVERFLOW_BIT_MASK) == 0)) &&
((record.getNextRel() == NULL) || ((record.getNextRel() & ONE_BIT_OVERFLOW_BIT_MASK) == 0)));
}

@Override
Expand All @@ -130,25 +124,7 @@ protected void doWriteInternal( NodeRecord record, PageCursor cursor )
{
if ( record.isUseFixedReferences() )
{
long nextRel = record.getNextRel();
long nextProp = record.getNextProp();

short relModifier = nextRel == Record.NO_NEXT_RELATIONSHIP.intValue() ? 0 : (short)((nextRel & 0x1_0000_0000L) >> 32);
short propModifier = nextProp == Record.NO_NEXT_PROPERTY.intValue() ? 0 : (short) ((nextProp & 0x3_0000_0000L) >> 31);

// [ ,xxxx] higher bits for rel id
// [xxxx, ] higher bits for prop id
short modifiers = (short) ( relModifier | propModifier );

cursor.putByte( (byte) modifiers );
cursor.putInt( (int) nextRel );
cursor.putInt( (int) nextProp );

// lsb of labels
long labelField = record.getLabelField();
cursor.putInt( (int) labelField );
// msb of labels
cursor.putByte( (byte) ((labelField & 0xFF_0000_0000L) >> 32) );
writeFixedReferencesRecord( record, cursor );
}
else
{
Expand All @@ -157,4 +133,45 @@ protected void doWriteInternal( NodeRecord record, PageCursor cursor )
encode( cursor, record.getLabelField(), NULL_LABELS );
}
}

private void readFixedReferencesRecord( NodeRecord record, PageCursor cursor, boolean inUse, boolean dense )
{
byte modifiers = cursor.getByte();
long relModifier = (modifiers & RELATIONSHIP_LOWER_BITS_MASK) << 32;
long propModifier = (modifiers & PROPERTY_LOWER_BITS_MASK) << 31;

long nextRel = cursor.getInt() & 0xFFFFFFFFL;
long nextProp = cursor.getInt() & 0xFFFFFFFFL;

long lsbLabels = cursor.getInt() & 0xFFFFFFFFL;
long hsbLabels = cursor.getByte() & 0xFF; // so that a negative byte won't fill the "extended" bits with ones.
long labels = lsbLabels | (hsbLabels << 32);

record.initialize( inUse,
BaseRecordFormat.longFromIntAndMod( nextProp, propModifier ), dense,
BaseRecordFormat.longFromIntAndMod( nextRel, relModifier ), labels );
}

private void writeFixedReferencesRecord( NodeRecord record, PageCursor cursor )
{
long nextRel = record.getNextRel();
long nextProp = record.getNextProp();

short relModifier = nextRel == Record.NO_NEXT_RELATIONSHIP.intValue() ? 0 : (short)((nextRel & RELATIONSHIP_HIGHER_BITS_MASK) >> 32);
short propModifier = nextProp == Record.NO_NEXT_PROPERTY.intValue() ? 0 : (short) ((nextProp & PROPERTY_HIGHER_BITS_MASK) >> 31);

// [ , x] higher bits for rel id
// [ , xx ] higher bits for prop id
short modifiers = (short) ( relModifier | propModifier );

cursor.putByte( (byte) modifiers );
cursor.putInt( (int) nextRel );
cursor.putInt( (int) nextProp );

// lsb of labels
long labelField = record.getLabelField();
cursor.putInt( (int) labelField );
// msb of labels
cursor.putByte( (byte) ((labelField & 0xFF_0000_0000L) >> 32) );
}
}
Expand Up @@ -52,6 +52,10 @@
class PropertyRecordFormat extends BaseOneByteHeaderRecordFormat<PropertyRecord>
{
private static final int RECORD_SIZE = 48;
private static final int FIXED_REFERENCES_BIT = 0b0000_0100;
private static final long UNSIGNED_SHORT_MASK = 0xFFFF_0000_0000L;
private static final long ONE_BIT_OVERFLOW_BIT_MASK = 0xFFFF_FFFE_0000_0000L;
private static final long THREE_BITS_OVERFLOW_BIT_MASK = 0xFFFF_FFFC_0000_0000L;

protected PropertyRecordFormat()
{
Expand All @@ -71,24 +75,15 @@ public void read( PropertyRecord record, PageCursor cursor, RecordLoad mode, int
int offset = cursor.getOffset();
byte headerByte = cursor.getByte();
boolean inUse = isInUse( headerByte );
record.setUseFixedReferences( has( headerByte, 0b0000_0100 ));
record.setUseFixedReferences( has( headerByte, FIXED_REFERENCES_BIT ));
if ( mode.shouldLoad( inUse ) )
{
int blockCount = headerByte >>> 4;
long recordId = record.getId();

if (record.isUseFixedReferences())
{
// since fixed reference limits property reference to 34 bits, 6 bytes is ample.
long prevMod = (cursor.getShort() & 0xFFFFL);
long prevProp = cursor.getInt() & 0xFFFFFFFFL;
long nextMod = (cursor.getShort() & 0xFFFFL);
long nextProp = cursor.getInt() & 0xFFFFFFFFL;
record.initialize( true,
BaseRecordFormat.longFromIntAndMod( prevProp, prevMod << 32 ),
BaseRecordFormat.longFromIntAndMod( nextProp, nextMod << 32 ) );
//skip 3 bytes before start reading property blocks
cursor.setOffset(cursor.getOffset() + 3);
readFixedReferencesRecord( record, cursor );
}
else
{
Expand Down Expand Up @@ -117,22 +112,14 @@ public void write( PropertyRecord record, PageCursor cursor, int recordSize )
byte headerByte = (byte) ((record.inUse() ? IN_USE_BIT : 0) | numberOfBlocks( record ) << 4);
boolean canUseFixedReferences = canUseFixedReferences( record );
record.setUseFixedReferences( canUseFixedReferences );
headerByte = set( headerByte, 0b0000_0100, canUseFixedReferences );
headerByte = set( headerByte, FIXED_REFERENCES_BIT, canUseFixedReferences );
cursor.putByte( headerByte );

long recordId = record.getId();

if ( canUseFixedReferences )
{
// Set up the record header
short prevModifier = record.getPrevProp() == Record.NO_NEXT_PROPERTY.intValue() ? 0 : (short) ((record.getPrevProp() & 0xFFFF_0000_0000L) >> 32);
short nextModifier = record.getNextProp() == Record.NO_NEXT_PROPERTY.intValue() ? 0 : (short) ((record.getNextProp() & 0xFFFF_0000_0000L) >> 32);
cursor.putShort( prevModifier );
cursor.putInt( (int) record.getPrevProp() );
cursor.putShort( nextModifier );
cursor.putInt( (int) record.getNextProp() );
//just stuff 3 bytes
cursor.putBytes(new byte[]{0,0,0});
writeFixedReferencesRecord( record, cursor );
}
else
{
Expand Down Expand Up @@ -171,7 +158,35 @@ public long getNextRecordReference( PropertyRecord record )

private boolean canUseFixedReferences( PropertyRecord record )
{
return (((record.getNextProp() == NULL_REFERENCE.intValue()) || ((record.getNextProp() & 0xFFFF_FFFC_0000_0000L) == 0)) &&
((record.getPrevProp() == NULL_REFERENCE.intValue()) || ((record.getPrevProp() & 0xFFFF_FFFE_0000_0000L) == 0)));
//TODO: wrong masks? should be unsigned short that potentially should be allowed?
return (((record.getNextProp() == NULL_REFERENCE.intValue()) || ((record.getNextProp() & THREE_BITS_OVERFLOW_BIT_MASK) == 0)) &&
((record.getPrevProp() == NULL_REFERENCE.intValue()) || ((record.getPrevProp() & ONE_BIT_OVERFLOW_BIT_MASK) == 0)));
}

private void readFixedReferencesRecord( PropertyRecord record, PageCursor cursor )
{
// since fixed reference limits property reference to 34 bits, 6 bytes is ample.
long prevMod = cursor.getShort() & 0xFFFFL;
long prevProp = cursor.getInt() & 0xFFFFFFFFL;
long nextMod = cursor.getShort() & 0xFFFFL;
long nextProp = cursor.getInt() & 0xFFFFFFFFL;
record.initialize( true,
BaseRecordFormat.longFromIntAndMod( prevProp, prevMod << 32 ),
BaseRecordFormat.longFromIntAndMod( nextProp, nextMod << 32 ) );
//skip 3 bytes before start reading property blocks
cursor.setOffset(cursor.getOffset() + 3);
}

private void writeFixedReferencesRecord( PropertyRecord record, PageCursor cursor )
{
// Set up the record header
short prevModifier = record.getPrevProp() == Record.NO_NEXT_PROPERTY.intValue() ? 0 : (short) ((record.getPrevProp() & UNSIGNED_SHORT_MASK) >> 32);
short nextModifier = record.getNextProp() == Record.NO_NEXT_PROPERTY.intValue() ? 0 : (short) ((record.getNextProp() & UNSIGNED_SHORT_MASK) >> 32);
cursor.putShort( prevModifier );
cursor.putInt( (int) record.getPrevProp() );
cursor.putShort( nextModifier );
cursor.putInt( (int) record.getNextProp() );
//just stuff 3 bytes
cursor.putBytes( new byte[]{0, 0, 0} );
}
}
Expand Up @@ -50,6 +50,14 @@ class RelationshipGroupRecordFormat extends BaseHighLimitRecordFormat<Relationsh
private static final int HAS_LOOP_BIT = 0b0010_0000;
private static final int HAS_NEXT_BIT = 0b0100_0000;

private static final long ONE_BIT_OVERFLOW_BIT_MASK = 0xFFFF_FFFE_0000_0000L;
private static final long FIXED_REFERENCE_BIT_MASK = 0x100000000L;
private static final int NEXT_RECORD_BIT_MASK = 0b0000_0001;
private static final int FIRST_OUT_BIT_MASK = 0b0000_0010;
private static final int FIRST_IN_BIT_MASK = 0b0000_0100;
private static final int FIRST_LOOP_BIT_MASK = 0b0000_1000;
private static final int OWNING_NODE_BIT_MASK = 0b0001_0000;

public RelationshipGroupRecordFormat()
{
this( RECORD_SIZE );
Expand All @@ -72,34 +80,7 @@ protected void doReadInternal( RelationshipGroupRecord record, PageCursor cursor
{
if ( record.isUseFixedReferences() )
{

// [ , x] high next bits
// [ , x ] high firstOut bits
// [ , x ] high firstIn bits
// [ ,x ] high firstLoop bits
// [ x, ] high owner bits
long modifiers = cursor.getByte();

int type = cursor.getShort() & 0xFFFF;

long nextLowBits = cursor.getInt() & 0xFFFFFFFFL;
long nextOutLowBits = cursor.getInt() & 0xFFFFFFFFL;
long nextInLowBits = cursor.getInt() & 0xFFFFFFFFL;
long nextLoopLowBits = cursor.getInt() & 0xFFFFFFFFL;
long owningNode = cursor.getInt() & 0xFFFFFFFFL;

long nextMod = (modifiers & 0b0000_0001) << 32;
long nextOutMod = (modifiers & 0b0000_0010) << 31;
long nextInMod = (modifiers & 0b0000_0100) << 30;
long nextLoopMod = (modifiers & 0b0000_1000) << 29;
long owningNodeMod = (modifiers & 0b0001_0000) << 28;

record.initialize( inUse, type,
BaseRecordFormat.longFromIntAndMod( nextOutLowBits, nextOutMod ),
BaseRecordFormat.longFromIntAndMod( nextInLowBits, nextInMod ),
BaseRecordFormat.longFromIntAndMod( nextLoopLowBits, nextLoopMod ),
BaseRecordFormat.longFromIntAndMod( owningNode, owningNodeMod ),
BaseRecordFormat.longFromIntAndMod( nextLowBits, nextMod ) );
readFixedReferencesMethod( record, cursor, inUse );
}
else
{
Expand Down Expand Up @@ -141,25 +122,7 @@ protected void doWriteInternal( RelationshipGroupRecord record, PageCursor curso
{
if ( record.isUseFixedReferences() )
{
long nextMod = record.getNext() == Record.NO_NEXT_RELATIONSHIP.intValue() ? 0 : (record.getNext() & 0x100000000L) >> 32;
long nextOutMod = record.getFirstOut() == Record.NO_NEXT_RELATIONSHIP.intValue() ? 0 : (record.getFirstOut() & 0x100000000L) >> 31;
long nextInMod = record.getFirstIn() == Record.NO_NEXT_RELATIONSHIP.intValue() ? 0 : (record.getFirstIn() & 0x100000000L) >> 30;
long nextLoopMod = record.getFirstLoop() == Record.NO_NEXT_RELATIONSHIP.intValue() ? 0 : (record.getFirstLoop() & 0x100000000L) >> 29;
long ownerMod = record.getOwningNode() == Record.NO_NEXT_RELATIONSHIP.intValue() ? 0 : (record.getOwningNode() & 0x100000000L) >> 28;

// [ , x] high next bits
// [ , x ] high firstOut bits
// [ , x ] high firstIn bits
// [ ,x ] high firstLoop bits
// [ x, ] high owner bits
cursor.putByte( (byte) (nextMod | nextOutMod | nextInMod | nextLoopMod | ownerMod) );

cursor.putShort( (short) record.getType() );
cursor.putInt( (int) record.getNext() );
cursor.putInt( (int) record.getFirstOut() );
cursor.putInt( (int) record.getFirstIn() );
cursor.putInt( (int) record.getFirstLoop() );
cursor.putInt( (int) record.getOwningNode() );
writeFixedReferencesRecord( record, cursor );
}
else
{
Expand All @@ -175,10 +138,64 @@ protected void doWriteInternal( RelationshipGroupRecord record, PageCursor curso
@Override
protected boolean canUseFixedReferences( RelationshipGroupRecord record )
{
return !((record.getNext() != NULL) && ((record.getNext() & 0xFFFF_FFFE_0000_0000L) != 0) ||
(record.getFirstOut() != NULL) && ((record.getFirstOut() & 0xFFFF_FFFE_0000_0000L) != 0) ||
(record.getFirstIn() != NULL) && ((record.getFirstIn() & 0xFFFF_FFFE_0000_0000L) != 0) ||
(record.getFirstLoop() != NULL) && ((record.getFirstLoop() & 0xFFFF_FFFE_0000_0000L) != 0) ||
(record.getOwningNode() != NULL) && ((record.getOwningNode() & 0xFFFF_FFFE_0000_0000L) != 0));
return !((record.getNext() != NULL) && ((record.getNext() & ONE_BIT_OVERFLOW_BIT_MASK) != 0) ||
(record.getFirstOut() != NULL) && ((record.getFirstOut() & ONE_BIT_OVERFLOW_BIT_MASK) != 0) ||
(record.getFirstIn() != NULL) && ((record.getFirstIn() & ONE_BIT_OVERFLOW_BIT_MASK) != 0) ||
(record.getFirstLoop() != NULL) && ((record.getFirstLoop() & ONE_BIT_OVERFLOW_BIT_MASK) != 0) ||
(record.getOwningNode() != NULL) && ((record.getOwningNode() & ONE_BIT_OVERFLOW_BIT_MASK) != 0));
}

private void readFixedReferencesMethod( RelationshipGroupRecord record, PageCursor cursor, boolean inUse )
{
// [ , x] high next bits
// [ , x ] high firstOut bits
// [ , x ] high firstIn bits
// [ ,x ] high firstLoop bits
// [ x, ] high owner bits
long modifiers = cursor.getByte();

int type = cursor.getShort() & 0xFFFF;

long nextLowBits = cursor.getInt() & 0xFFFFFFFFL;
long firstOutLowBits = cursor.getInt() & 0xFFFFFFFFL;
long firstInLowBits = cursor.getInt() & 0xFFFFFFFFL;
long firstLoopLowBits = cursor.getInt() & 0xFFFFFFFFL;
long owningNodeLowBits = cursor.getInt() & 0xFFFFFFFFL;

long nextMod = (modifiers & NEXT_RECORD_BIT_MASK) << 32;
long firstOutMod = (modifiers & FIRST_OUT_BIT_MASK) << 31;
long firstInMod = (modifiers & FIRST_IN_BIT_MASK) << 30;
long firstLoopMod = (modifiers & FIRST_LOOP_BIT_MASK) << 29;
long owningNodeMod = (modifiers & OWNING_NODE_BIT_MASK) << 28;

record.initialize( inUse, type,
BaseRecordFormat.longFromIntAndMod( firstOutLowBits, firstOutMod ),
BaseRecordFormat.longFromIntAndMod( firstInLowBits, firstInMod ),
BaseRecordFormat.longFromIntAndMod( firstLoopLowBits, firstLoopMod ),
BaseRecordFormat.longFromIntAndMod( owningNodeLowBits, owningNodeMod ),
BaseRecordFormat.longFromIntAndMod( nextLowBits, nextMod ) );
}

private void writeFixedReferencesRecord( RelationshipGroupRecord record, PageCursor cursor )
{
long nextMod = record.getNext() == Record.NO_NEXT_RELATIONSHIP.intValue() ? 0 : (record.getNext() & FIXED_REFERENCE_BIT_MASK) >> 32;
long firstOutMod = record.getFirstOut() == Record.NO_NEXT_RELATIONSHIP.intValue() ? 0 : (record.getFirstOut() & FIXED_REFERENCE_BIT_MASK) >> 31;
long firstInMod = record.getFirstIn() == Record.NO_NEXT_RELATIONSHIP.intValue() ? 0 : (record.getFirstIn() & FIXED_REFERENCE_BIT_MASK) >> 30;
long firstLoopMod = record.getFirstLoop() == Record.NO_NEXT_RELATIONSHIP.intValue() ? 0 : (record.getFirstLoop() & FIXED_REFERENCE_BIT_MASK) >> 29;
long owningNodeMod = record.getOwningNode() == Record.NO_NEXT_RELATIONSHIP.intValue() ? 0 : (record.getOwningNode() & FIXED_REFERENCE_BIT_MASK) >> 28;

// [ , x] high next bits
// [ , x ] high firstOut bits
// [ , x ] high firstIn bits
// [ ,x ] high firstLoop bits
// [ x, ] high owner bits
cursor.putByte( (byte) (nextMod | firstOutMod | firstInMod | firstLoopMod | owningNodeMod) );

cursor.putShort( (short) record.getType() );
cursor.putInt( (int) record.getNext() );
cursor.putInt( (int) record.getFirstOut() );
cursor.putInt( (int) record.getFirstIn() );
cursor.putInt( (int) record.getFirstLoop() );
cursor.putInt( (int) record.getOwningNode() );
}
}

0 comments on commit 5a6e977

Please sign in to comment.