Skip to content

Commit

Permalink
Merge pull request #11168 from OliviaYtterbrink/3.4-temporal-layouts
Browse files Browse the repository at this point in the history
Temporal indexing 3 - all the parts
  • Loading branch information
fickludd committed Mar 9, 2018
2 parents c9fdfa3 + 91479c8 commit be9b5d8
Show file tree
Hide file tree
Showing 38 changed files with 1,617 additions and 272 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import org.neo4j.bolt.v1.messaging.Neo4jPack;
import org.neo4j.bolt.v1.packstream.PackedInputArray;
import org.neo4j.bolt.v1.packstream.PackedOutputArray;
import org.neo4j.kernel.impl.store.TimeZoneMapping;
import org.neo4j.kernel.impl.store.TimeZones;
import org.neo4j.values.AnyValue;
import org.neo4j.values.storable.CoordinateReferenceSystem;
import org.neo4j.values.storable.DateTimeValue;
Expand Down Expand Up @@ -74,7 +74,9 @@
public class Neo4jPackV2Test
{
private static final String[] TIME_ZONE_NAMES =
TimeZoneMapping.supportedTimeZones().stream().filter( s -> ZoneId.getAvailableZoneIds().contains( s ) ).toArray( length -> new String[length] );
TimeZones.supportedTimeZones().stream()
.filter( s -> ZoneId.getAvailableZoneIds().contains( s ) )
.toArray( length -> new String[length] );

private static final int RANDOM_VALUES_TO_TEST = 1_000;
private static final int RANDOM_LISTS_TO_TEST = 1_000;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2002-2018 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.kernel.impl.index.schema;

import org.neo4j.index.internal.gbptree.Layout;

/**
* Simple GBPTree Layout with no values.
*
* @param <KEY> the key type
*/
abstract class BaseLayout<KEY extends ComparableNativeSchemaKey<KEY>> extends SchemaLayout<KEY>
{
BaseLayout( String layoutName, int majorVersion, int minorVersion )
{
super( Layout.namedIdentifier( layoutName, NativeSchemaValue.SIZE ), majorVersion, minorVersion );
}

@Override
int compareValue( KEY o1, KEY o2 )
{
return o1.compareValueTo( o2 );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2002-2018 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.kernel.impl.index.schema;

import java.util.Comparator;

/**
* Adds comparability to NativeSchemaKey. Note that comparability of keys is required for the GBPTree, so
* this has to be implemented even if the values in the key are not comparable.
*
* @param <SELF> the type of the concrete implementing subclass
*/
abstract class ComparableNativeSchemaKey<SELF extends ComparableNativeSchemaKey> extends NativeSchemaKey
{

/**
* 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 key to compare to.
* @return comparison against the {@code other} key.
*/
abstract int compareValueTo( SELF other );

static <T extends ComparableNativeSchemaKey<T>> Comparator<T> UNIQUE()
{
return ( o1, o2 ) -> {
int comparison = o1.compareValueTo( o2 );
if ( comparison == 0 )
{
// This is a special case where we need also compare entityId to support inclusive/exclusive
if ( o1.getCompareId() || o2.getCompareId() )
{
return Long.compare( o1.getEntityId(), o2.getEntityId() );
}
}
return comparison;
};
}

static <T extends ComparableNativeSchemaKey<T>> Comparator<T> NON_UNIQUE()
{
return ( o1, o2 ) -> {
int comparison = o1.compareValueTo( o2 );
return comparison != 0 ? comparison : Long.compare( o1.getEntityId(), o2.getEntityId() );
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,22 @@
import org.neo4j.io.pagecache.PageCursor;
import org.neo4j.kernel.api.schema.index.IndexDescriptor;

class DateLayout extends SchemaLayout<DateSchemaKey>
/**
* {@link Layout} for dates.
*/
class DateLayout extends BaseLayout<DateSchemaKey>
{
public static Layout<DateSchemaKey,NativeSchemaValue> of( IndexDescriptor descriptor )
{
return descriptor.type() == IndexDescriptor.Type.UNIQUE ? DateLayout.UNIQUE : DateLayout.NON_UNIQUE;
}

private static final long UNIQUE_LAYOUT_IDENTIFIER = Layout.namedIdentifier( "UTda", NativeSchemaValue.SIZE );
public static DateLayout UNIQUE = new DateLayout( UNIQUE_LAYOUT_IDENTIFIER, 0, 1 );

private static final long NON_UNIQUE_LAYOUT_IDENTIFIER = Layout.namedIdentifier( "NTda", NativeSchemaValue.SIZE );
public static DateLayout NON_UNIQUE = new DateLayout( NON_UNIQUE_LAYOUT_IDENTIFIER, 0, 1 );
private static DateLayout UNIQUE = new DateLayout( "UTda", 0, 1 );
private static DateLayout NON_UNIQUE = new DateLayout( "NTda", 0, 1 );

DateLayout( long identifier, int majorVersion, int minorVersion )
private DateLayout( String layoutName, int majorVersion, int minorVersion )
{
super( identifier, majorVersion, minorVersion );
super( layoutName, majorVersion, minorVersion );
}

@Override
Expand Down Expand Up @@ -75,10 +75,4 @@ public void readKey( PageCursor cursor, DateSchemaKey into, int keySize )
into.epochDay = cursor.getLong();
into.setEntityId( cursor.getLong() );
}

@Override
int compareValue( DateSchemaKey o1, DateSchemaKey o2 )
{
return o1.compareValueTo( o2 );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,48 +19,22 @@
*/
package org.neo4j.kernel.impl.index.schema;

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

import static java.lang.String.format;

/**
* Includes value and entity id (to be able to handle non-unique values). A value can be any {@link String},
* or rather any string that {@link GBPTree} can handle.
* Includes value and entity id (to be able to handle non-unique values). A value can be any {@link DateValue}.
*/
class DateSchemaKey extends NativeSchemaKey
class DateSchemaKey extends ComparableNativeSchemaKey<DateSchemaKey>
{
static final int SIZE =
Long.BYTES + /* raw value bits */
Long.BYTES + /* epochDay */
Long.BYTES; /* entityId */

long epochDay;

@Override
void from( Value... values )
{
assertValidValue( values ).writeTo( this );
}

private DateValue assertValidValue( Value... values )
{
if ( values.length > 1 )
{
throw new IllegalArgumentException( "Tried to create composite key with non-composite schema key layout" );
}
if ( values.length < 1 )
{
throw new IllegalArgumentException( "Tried to create key without value" );
}
if ( !(values[0] instanceof DateValue) )
{
throw new IllegalArgumentException(
"Key layout does only support DateValue, tried to create key from " + values[0] );
}
return (DateValue) values[0];
}

@Override
public Value asValue()
{
Expand All @@ -79,27 +53,32 @@ void initValueAsHighest()
epochDay = Long.MAX_VALUE;
}

/**
* 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 DateSchemaKey} to compare to.
* @return comparison against the {@code other} {@link DateSchemaKey}.
*/
int compareValueTo( DateSchemaKey other )
@Override
public int compareValueTo( DateSchemaKey other )
{
return Long.compare( epochDay, other.epochDay );
}

@Override
public String toString()
{
return format( "value=%s,entityId=%d,epochDay=%s", asValue(), getEntityId(), epochDay );
return format( "value=%s,entityId=%d,epochDay=%d", asValue(), getEntityId(), epochDay );
}

@Override
public void writeDate( long epochDay )
{
this.epochDay = epochDay;
}

@Override
protected Value assertCorrectType( Value value )
{
if ( !(value instanceof DateValue) )
{
throw new IllegalArgumentException(
"Key layout does only support DateValue, tried to create key from " + value );
}
return value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2002-2018 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.kernel.impl.index.schema;

import org.neo4j.index.internal.gbptree.Layout;
import org.neo4j.io.pagecache.PageCursor;
import org.neo4j.kernel.api.schema.index.IndexDescriptor;

/**
* {@link Layout} for durations.
*/
class DurationLayout extends BaseLayout<DurationSchemaKey>
{
public static Layout<DurationSchemaKey,NativeSchemaValue> of( IndexDescriptor descriptor )
{
return descriptor.type() == IndexDescriptor.Type.UNIQUE ? DurationLayout.UNIQUE : DurationLayout.NON_UNIQUE;
}

private static DurationLayout UNIQUE = new DurationLayout( "UTdu", 0, 1 );
private static DurationLayout NON_UNIQUE = new DurationLayout( "NTdu", 0, 1 );

private DurationLayout( String layoutName, int majorVersion, int minorVersion )
{
super( layoutName, majorVersion, minorVersion );
}

@Override
public DurationSchemaKey newKey()
{
return new DurationSchemaKey();
}

@Override
public DurationSchemaKey copyKey( DurationSchemaKey key, DurationSchemaKey into )
{
into.totalAvgSeconds = key.totalAvgSeconds;
into.nanosOfSecond = key.nanosOfSecond;
into.months = key.months;
into.days = key.days;
into.setEntityId( key.getEntityId() );
into.setCompareId( key.getCompareId() );
return into;
}

@Override
public int keySize( DurationSchemaKey key )
{
return DurationSchemaKey.SIZE;
}

@Override
public void writeKey( PageCursor cursor, DurationSchemaKey key )
{
cursor.putLong( key.totalAvgSeconds );
cursor.putInt( key.nanosOfSecond );
cursor.putLong( key.months );
cursor.putLong( key.days );
cursor.putLong( key.getEntityId() );
}

@Override
public void readKey( PageCursor cursor, DurationSchemaKey into, int keySize )
{
into.totalAvgSeconds = cursor.getLong();
into.nanosOfSecond = cursor.getInt();
into.months = cursor.getLong();
into.days = cursor.getLong();
into.setEntityId( cursor.getLong() );
}
}

0 comments on commit be9b5d8

Please sign in to comment.