Skip to content

Commit

Permalink
Change NativeSchemaKey to an interface
Browse files Browse the repository at this point in the history
  • Loading branch information
OliviaYtterbrink authored and burqen committed Jan 11, 2018
1 parent 90757bb commit 1a5add2
Show file tree
Hide file tree
Showing 12 changed files with 110 additions and 82 deletions.
Expand Up @@ -39,11 +39,11 @@ public class ConflictDetectingValueMerger<KEY extends NativeSchemaKey, VALUE ext
@Override
public VALUE merge( KEY existingKey, KEY newKey, VALUE existingValue, VALUE newValue )
{
if ( existingKey.entityId != newKey.entityId )
if ( existingKey.getEntityId() != newKey.getEntityId() )
{
conflict = true;
existingNodeId = existingKey.entityId;
addedNodeId = newKey.entityId;
existingNodeId = existingKey.getEntityId();
addedNodeId = newKey.getEntityId();
}
return null;
}
Expand Down
Expand Up @@ -60,7 +60,7 @@ protected Long fetchNextOrNull()
{
try
{
return seeker.next() ? seeker.get().key().entityId : null;
return seeker.next() ? seeker.get().key().getEntityId() : null;
}
catch ( IOException e )
{
Expand Down
Expand Up @@ -50,7 +50,7 @@ public boolean next()
while ( seeker.next() )
{
KEY key = seeker.get().key();
if ( client.acceptNode( key.entityId, key.asValue() ) )
if ( client.acceptNode( key.getEntityId(), key.asValue() ) )
{
return true;
}
Expand Down
Expand Up @@ -94,7 +94,7 @@ public long countIndexedNodes( long nodeId, Value... propertyValues )
long count = 0;
while ( seeker.next() )
{
if ( seeker.get().key().entityId == nodeId )
if ( seeker.get().key().getEntityId() == nodeId )
{
count++;
}
Expand Down
Expand Up @@ -20,81 +20,41 @@
package org.neo4j.kernel.impl.index.schema;

import org.neo4j.index.internal.gbptree.GBPTree;
import org.neo4j.values.storable.NumberValue;
import org.neo4j.values.storable.Value;
import org.neo4j.values.storable.ValueWriter;

/**
* Includes value and entity id (to be able to handle non-unique values).
* A value can be any {@link Number} and is represented as a {@code long} to store the raw bits and a type
* to say if it's a long, double or float.
*
* Distinction between double and float exists because coersions between each other and long may differ.
* TODO this should be figured out and potentially reduced to long, double types only.
*/
public abstract class NativeSchemaKey extends ValueWriter.Adapter<RuntimeException>
public interface NativeSchemaKey
{
// public static final int SIZE =
// Byte.BYTES + /* type of value */
// Long.BYTES + /* raw value bits */
//
// // TODO this could use 6 bytes instead and have the highest 2 bits stored in the type byte
// Long.BYTES; /* entityId */

public byte type;
public long rawValueBits;
public long entityId;

/**
* Marks that comparisons with this key requires also comparing entityId, this allows functionality
* of inclusive/exclusive bounds of range queries.
* This is because {@link GBPTree} only support from inclusive and to exclusive.
* <p>
* Note that {@code entityIdIsSpecialTieBreaker} is only an in memory state.
*/
public boolean entityIdIsSpecialTieBreaker;
void setEntityIdIsSpecialTieBreaker( boolean entityIdIsSpecialTieBreaker );

public void from( long entityId, Value... values )
{
extractRawBitsAndType( assertValidValue( values ) );
this.entityId = entityId;
entityIdIsSpecialTieBreaker = false;
}
boolean getEntityIdIsSpecialTieBreaker();

public abstract Value assertValidValue( Value... values );
long getEntityId();

public String propertiesAsString()
{
return asValue().toString();
}
void setEntityId( long entityId );

public abstract NumberValue asValue();
void from( long entityId, Value... values );

public abstract void initAsLowest();
String propertiesAsString();

public abstract void initAsHighest();
/**
* Compares the value of this key to that of another key.
* This method is expected to be called in scenarios where inconsistent reads may happen (and later retried).
*
* @param other the {@link NativeSchemaKey} to compare to.
* @return comparison against the {@code other} {@link NativeSchemaKey}.
*/
public int compareValueTo( NativeSchemaKey other )
{
return RawBits.compare( rawValueBits, type, other.rawValueBits, other.type );
}
Value asValue();

/**
* Extracts raw bits and type from a {@link Value} and store as state of this {@link NativeSchemaKey} instance.
*
* @param value actual {@link Value} value.
*/
private void extractRawBitsAndType( Value value )
{
value.writeTo( this );
}
void initAsLowest();

void initAsHighest();

@Override
public abstract String toString();
String toString();

}
Expand Up @@ -34,13 +34,12 @@ public NumberSchemaKey newKey()
}

@Override
public NumberSchemaKey copyKey( NumberSchemaKey key,
NumberSchemaKey into )
public NumberSchemaKey copyKey( NumberSchemaKey key, NumberSchemaKey into )
{
into.type = key.type;
into.rawValueBits = key.rawValueBits;
into.entityId = key.entityId;
into.entityIdIsSpecialTieBreaker = key.entityIdIsSpecialTieBreaker;
into.setEntityId( key.getEntityId() );
into.setEntityIdIsSpecialTieBreaker( key.getEntityIdIsSpecialTieBreaker() );
return into;
}

Expand All @@ -67,7 +66,7 @@ public void writeKey( PageCursor cursor, NumberSchemaKey key )
{
cursor.putByte( key.type );
cursor.putLong( key.rawValueBits );
cursor.putLong( key.entityId );
cursor.putLong( key.getEntityId() );
}

@Override
Expand All @@ -80,7 +79,7 @@ public void readKey( PageCursor cursor, NumberSchemaKey into )
{
into.type = cursor.getByte();
into.rawValueBits = cursor.getLong();
into.entityId = cursor.getLong();
into.setEntityId( cursor.getLong() );
}

@Override
Expand Down
Expand Up @@ -50,6 +50,6 @@ public int minorVersion()
public int compare( NumberSchemaKey o1, NumberSchemaKey o2 )
{
int comparison = o1.compareValueTo( o2 );
return comparison != 0 ? comparison : Long.compare( o1.entityId, o2.entityId );
return comparison != 0 ? comparison : Long.compare( o1.getEntityId(), o2.getEntityId() );
}
}
Expand Up @@ -57,9 +57,9 @@ public int compare( NumberSchemaKey o1, NumberSchemaKey o2 )
if ( comparison == 0 )
{
// This is a special case where we need also compare entityId to support inclusive/exclusive
if ( o1.entityIdIsSpecialTieBreaker || o2.entityIdIsSpecialTieBreaker )
if ( o1.getEntityIdIsSpecialTieBreaker() || o2.getEntityIdIsSpecialTieBreaker() )
{
return Long.compare( o1.entityId, o2.entityId );
return Long.compare( o1.getEntityId(), o2.getEntityId() );
}
}
return comparison;
Expand Down
Expand Up @@ -110,7 +110,7 @@ private void initToForRange( NumberRangePredicate rangePredicate, KEY treeKeyTo
else
{
treeKeyTo.from( rangePredicate.toInclusive() ? Long.MAX_VALUE : Long.MIN_VALUE, toValue );
treeKeyTo.entityIdIsSpecialTieBreaker = true;
treeKeyTo.setEntityIdIsSpecialTieBreaker( true );
}
}

Expand All @@ -124,7 +124,7 @@ private void initFromForRange( NumberRangePredicate rangePredicate, KEY treeKeyF
else
{
treeKeyFrom.from( rangePredicate.fromInclusive() ? Long.MIN_VALUE : Long.MAX_VALUE, fromValue );
treeKeyFrom.entityIdIsSpecialTieBreaker = true;
treeKeyFrom.setEntityIdIsSpecialTieBreaker( true );
}
}

Expand Down
Expand Up @@ -21,6 +21,7 @@

import org.neo4j.values.storable.NumberValue;
import org.neo4j.values.storable.Value;
import org.neo4j.values.storable.ValueWriter;
import org.neo4j.values.storable.Values;

import static java.lang.String.format;
Expand All @@ -33,7 +34,7 @@
* Distinction between double and float exists because coersions between each other and long may differ.
* TODO this should be figured out and potentially reduced to long, double types only.
*/
class NumberSchemaKey extends NativeSchemaKey
class NumberSchemaKey extends ValueWriter.Adapter<RuntimeException> implements NativeSchemaKey
{
static final int SIZE =
Byte.BYTES + /* type of value */
Expand All @@ -42,8 +43,45 @@ class NumberSchemaKey extends NativeSchemaKey
// TODO this could use 6 bytes instead and have the highest 2 bits stored in the type byte
Long.BYTES; /* entityId */

private long entityId;
private boolean entityIdIsSpecialTieBreaker;

byte type;
long rawValueBits;

@Override
public void setEntityIdIsSpecialTieBreaker( boolean entityIdIsSpecialTieBreaker )
{
this.entityIdIsSpecialTieBreaker = entityIdIsSpecialTieBreaker;
}

@Override
public boolean getEntityIdIsSpecialTieBreaker()
{
return entityIdIsSpecialTieBreaker;
}

@Override
public long getEntityId()
{
return entityId;
}

@Override
public NumberValue assertValidValue( Value... values )
public void setEntityId( long entityId )
{
this.entityId = entityId;
}

@Override
public void from( long entityId, Value... values )
{
extractRawBitsAndType( assertValidValue( values ) );
this.entityId = entityId;
entityIdIsSpecialTieBreaker = false;
}

private NumberValue assertValidValue( Value... values )
{
// TODO: support multiple values, right?
if ( values.length > 1 )
Expand All @@ -62,6 +100,12 @@ public NumberValue assertValidValue( Value... values )
return (NumberValue) values[0];
}

@Override
public String propertiesAsString()
{
return asValue().toString();
}

@Override
public NumberValue asValue()
{
Expand All @@ -84,6 +128,28 @@ public void initAsHighest()
entityIdIsSpecialTieBreaker = true;
}

/**
* Compares the value of this key to that of another key.
* This method is expected to be called in scenarios where inconsistent reads may happen (and later retried).
*
* @param other the {@link NativeSchemaKey} to compare to.
* @return comparison against the {@code other} {@link NativeSchemaKey}.
*/
int compareValueTo( NumberSchemaKey other )
{
return RawBits.compare( rawValueBits, type, other.rawValueBits, other.type );
}

/**
* Extracts raw bits and type from a {@link Value} and store as state of this {@link NativeSchemaKey} instance.
*
* @param value actual {@link Value} value.
*/
private void extractRawBitsAndType( Value value )
{
value.writeTo( this );
}

@Override
public String toString()
{
Expand Down
Expand Up @@ -57,6 +57,8 @@ abstract class LayoutTestUtil<KEY extends NativeSchemaKey, VALUE extends NativeS

abstract Value asValue( Number value );

abstract int compareIndexedPropertyValue( KEY key1, KEY key2 );

IndexDescriptor indexDescriptor()
{
return indexDescriptor;
Expand All @@ -66,16 +68,6 @@ void copyValue( VALUE value, VALUE intoValue )
{
}

int compareIndexedPropertyValue( NativeSchemaKey key1, NativeSchemaKey key2 )
{
int typeCompare = Byte.compare( key1.type, key2.type );
if ( typeCompare == 0 )
{
return Long.compare( key1.rawValueBits, key2.rawValueBits );
}
return typeCompare;
}

Iterator<IndexEntryUpdate<IndexDescriptor>> randomUpdateGenerator( RandomRule random )
{
double fractionDuplicates = fractionDuplicates();
Expand Down
Expand Up @@ -42,4 +42,15 @@ Value asValue( Number value )
{
return Values.of( value );
}

@Override
int compareIndexedPropertyValue( NumberSchemaKey key1, NumberSchemaKey key2 )
{
int typeCompare = Byte.compare( key1.type, key2.type );
if ( typeCompare == 0 )
{
return Long.compare( key1.rawValueBits, key2.rawValueBits );
}
return typeCompare;
}
}

0 comments on commit 1a5add2

Please sign in to comment.