Skip to content

Commit

Permalink
Restore Fusion index to that of 3.3
Browse files Browse the repository at this point in the history
Disable
- Native string index
- Native Temporal index
- Native Spatial index

Also make Fusion index multiversionable for future adaptation.
  • Loading branch information
burqen committed Mar 22, 2018
1 parent 41fb5e7 commit a8c8acc
Show file tree
Hide file tree
Showing 20 changed files with 950 additions and 416 deletions.
Expand Up @@ -118,6 +118,8 @@ public interface IndexAccessor extends Closeable
*/
boolean isDirty();

IndexAccessor EMPTY = new Adapter();

class Adapter implements IndexAccessor
{
@Override
Expand Down
Expand Up @@ -142,6 +142,8 @@ void add( Collection<? extends IndexEntryUpdate<?>> updates )
*/
IndexSample sampleResult();

IndexPopulator EMPTY = new Adapter();

class Adapter implements IndexPopulator
{
@Override
Expand Down
Expand Up @@ -114,11 +114,11 @@ public void recoveryCompleted( long indexId, SchemaIndexDescriptor schemaIndexDe
void recoveryCompleted( long indexId, SchemaIndexDescriptor schemaIndexDescriptor, Map<String,Object> data );
}

public static final IndexProvider NO_INDEX_PROVIDER =
public static final IndexProvider EMPTY =
new IndexProvider( new Descriptor( "no-index-provider", "1.0" ), -1, IndexDirectoryStructure.NONE )
{
private final IndexAccessor singleWriter = new IndexAccessor.Adapter();
private final IndexPopulator singlePopulator = new IndexPopulator.Adapter();
private final IndexAccessor singleWriter = IndexAccessor.EMPTY;
private final IndexPopulator singlePopulator = IndexPopulator.EMPTY;

@Override
public IndexAccessor getOnlineAccessor( long indexId, SchemaIndexDescriptor descriptor,
Expand All @@ -137,7 +137,7 @@ public IndexPopulator getPopulator( long indexId, SchemaIndexDescriptor descript
@Override
public InternalIndexState getInitialState( long indexId, SchemaIndexDescriptor descriptor )
{
return InternalIndexState.POPULATING;
return InternalIndexState.ONLINE;
}

@Override
Expand Down
Expand Up @@ -147,10 +147,7 @@ public Iterator<Long> iterator()
public ResourceIterator<File> snapshotFiles() throws IOException
{
List<ResourceIterator<File>> snapshots = new ArrayList<>();
for ( IndexAccessor accessor : instances )
{
snapshots.add( accessor.snapshotFiles() );
}
forAll( accessor -> snapshots.add( accessor.snapshotFiles() ), instances );
return concatResourceIterators( snapshots.iterator() );
}

Expand Down
Expand Up @@ -20,9 +20,12 @@
package org.neo4j.kernel.impl.index.schema.fusion;

import java.lang.reflect.Array;
import java.util.Arrays;

import org.neo4j.collection.primitive.PrimitiveIntCollections;
import org.neo4j.function.ThrowingConsumer;
import org.neo4j.function.ThrowingFunction;
import org.neo4j.kernel.api.index.IndexProvider;

/**
* Acting as a simplifier for the multiplexing that is going in inside a fusion index. A fusion index consists of multiple parts,
Expand All @@ -33,7 +36,7 @@
*/
public abstract class FusionIndexBase<T>
{
private static final int INSTANCE_COUNT = 5;
static final int INSTANCE_COUNT = 5;

static final int STRING = 0;
static final int NUMBER = 1;
Expand Down Expand Up @@ -163,4 +166,19 @@ public static <T, E extends Exception> void forAll( ThrowingConsumer<T,E> consum
throw exception;
}
}

static void validateSelectorInstances( Object[] instances, int... notNullIndex )
{
for ( int i = 0; i < instances.length; i++ )
{
boolean expected = PrimitiveIntCollections.contains( notNullIndex, i );
boolean actual = instances[i] != IndexProvider.EMPTY;
if ( expected != actual )
{
throw new IllegalArgumentException(
String.format( "Only indexes expected to be separated from IndexProvider.EMPTY are %s but was %s",
Arrays.toString( notNullIndex ), Arrays.toString( instances ) ) );
}
}
}
}
Expand Up @@ -24,6 +24,7 @@

import org.neo4j.internal.kernel.api.IndexCapability;
import org.neo4j.internal.kernel.api.IndexOrder;
import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.internal.kernel.api.InternalIndexState;
import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.io.pagecache.PageCache;
Expand All @@ -33,18 +34,21 @@
import org.neo4j.kernel.api.index.IndexProvider;
import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor;
import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingConfig;
import org.neo4j.kernel.impl.index.schema.NumberIndexProvider;
import org.neo4j.kernel.impl.index.schema.SpatialIndexProvider;
import org.neo4j.kernel.impl.index.schema.StringIndexProvider;
import org.neo4j.kernel.impl.index.schema.TemporalIndexProvider;
import org.neo4j.kernel.impl.newapi.UnionIndexCapability;
import org.neo4j.kernel.impl.storemigration.StoreMigrationParticipant;
import org.neo4j.storageengine.api.schema.IndexReader;
import org.neo4j.values.storable.Value;
import org.neo4j.values.storable.ValueGroup;

import static org.neo4j.helpers.collection.Iterators.array;
import static org.neo4j.internal.kernel.api.InternalIndexState.FAILED;
import static org.neo4j.internal.kernel.api.InternalIndexState.POPULATING;
import static org.neo4j.kernel.impl.index.schema.fusion.FusionIndexBase.INSTANCE_COUNT;
import static org.neo4j.kernel.impl.index.schema.fusion.FusionIndexBase.LUCENE;
import static org.neo4j.kernel.impl.index.schema.fusion.FusionIndexBase.NUMBER;
import static org.neo4j.kernel.impl.index.schema.fusion.FusionIndexBase.SPATIAL;
import static org.neo4j.kernel.impl.index.schema.fusion.FusionIndexBase.STRING;
import static org.neo4j.kernel.impl.index.schema.fusion.FusionIndexBase.TEMPORAL;
import static org.neo4j.kernel.impl.index.schema.fusion.FusionIndexBase.forAll;
import static org.neo4j.kernel.impl.index.schema.fusion.FusionIndexBase.instancesAs;

/**
Expand All @@ -55,24 +59,28 @@ public class FusionIndexProvider extends IndexProvider
{
interface Selector
{
void validateSatisfied( Object[] instances );

int selectSlot( Value... values );

default <T> T select( T[] instances, Value... values )
{
return instances[selectSlot( values )];
}

IndexReader select( IndexReader[] instances, IndexQuery... predicates );
}

private final IndexProvider[] providers;
private final IndexProvider[] providers = new IndexProvider[INSTANCE_COUNT];
private final Selector selector;
private final DropAction dropAction;

public FusionIndexProvider(
// good to be strict with specific providers here since this is dev facing
StringIndexProvider stringProvider,
NumberIndexProvider numberProvider,
SpatialIndexProvider spatialProvider,
TemporalIndexProvider temporalProvider,
IndexProvider stringProvider,
IndexProvider numberProvider,
IndexProvider spatialProvider,
IndexProvider temporalProvider,
IndexProvider luceneProvider,
Selector selector,
Descriptor descriptor,
Expand All @@ -81,11 +89,22 @@ public FusionIndexProvider(
FileSystemAbstraction fs )
{
super( descriptor, priority, directoryStructure );
this.providers = array( stringProvider, numberProvider, spatialProvider, temporalProvider, luceneProvider );
fillProvidersArray( stringProvider, numberProvider, spatialProvider, temporalProvider, luceneProvider );
selector.validateSatisfied( providers );
this.selector = selector;
this.dropAction = new FileSystemDropAction( fs, directoryStructure() );
}

private void fillProvidersArray( IndexProvider stringProvider, IndexProvider numberProvider, IndexProvider spatialProvider, IndexProvider temporalProvider,
IndexProvider luceneProvider )
{
providers[STRING] = stringProvider;
providers[NUMBER] = numberProvider;
providers[SPATIAL] = spatialProvider;
providers[TEMPORAL] = temporalProvider;
providers[LUCENE] = luceneProvider;
}

@Override
public IndexPopulator getPopulator( long indexId, SchemaIndexDescriptor descriptor, IndexSamplingConfig samplingConfig )
{
Expand All @@ -106,10 +125,7 @@ public IndexAccessor getOnlineAccessor( long indexId, SchemaIndexDescriptor desc
public String getPopulationFailure( long indexId, SchemaIndexDescriptor descriptor ) throws IllegalStateException
{
StringBuilder builder = new StringBuilder();
for ( int i = 0; i < providers.length; i++ )
{
writeFailure( nameOf( i ), builder, providers[i], indexId, descriptor );
}
forAll( p -> writeFailure( p.getClass().getSimpleName(), builder, p, indexId, descriptor ), providers );
String failure = builder.toString();
if ( !failure.isEmpty() )
{
Expand All @@ -118,15 +134,6 @@ public String getPopulationFailure( long indexId, SchemaIndexDescriptor descript
throw new IllegalStateException( "None of the indexes were in a failed state" );
}

/**
* @param subProviderIndex the index into the providers array to get the name of.
* @return some name distinguishing the provider of this subProviderIndex from other providers.
*/
private String nameOf( int subProviderIndex )
{
return providers[subProviderIndex].getClass().getSimpleName();
}

private void writeFailure( String indexName, StringBuilder builder, IndexProvider provider, long indexId, SchemaIndexDescriptor descriptor )
{
try
Expand All @@ -145,8 +152,7 @@ private void writeFailure( String indexName, StringBuilder builder, IndexProvide
@Override
public InternalIndexState getInitialState( long indexId, SchemaIndexDescriptor descriptor )
{
InternalIndexState[] states =
Arrays.stream( providers ).map( provider -> provider.getInitialState( indexId, descriptor ) ).toArray( InternalIndexState[]::new );
InternalIndexState[] states = FusionIndexBase.instancesAs( providers, InternalIndexState.class, p -> p.getInitialState( indexId, descriptor ) );
if ( Arrays.stream( states ).anyMatch( state -> state == FAILED ) )
{
// One of the state is FAILED, the whole state must be considered FAILED
Expand Down
Expand Up @@ -27,23 +27,18 @@
import org.neo4j.internal.kernel.api.IndexOrder;
import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.internal.kernel.api.IndexQuery.ExactPredicate;
import org.neo4j.internal.kernel.api.IndexQuery.ExistsPredicate;
import org.neo4j.internal.kernel.api.IndexQuery.RangePredicate;
import org.neo4j.kernel.api.exceptions.index.IndexNotApplicableKernelException;
import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor;
import org.neo4j.kernel.impl.api.schema.BridgingIndexProgressor;
import org.neo4j.kernel.impl.index.schema.fusion.FusionIndexProvider.Selector;

import org.neo4j.storageengine.api.schema.IndexProgressor;
import org.neo4j.storageengine.api.schema.IndexReader;
import org.neo4j.storageengine.api.schema.IndexSampler;
import org.neo4j.values.storable.Value;
import org.neo4j.values.storable.ValueGroup;

import static java.lang.String.format;
import static org.neo4j.internal.kernel.api.IndexQuery.StringContainsPredicate;
import static org.neo4j.internal.kernel.api.IndexQuery.StringPrefixPredicate;
import static org.neo4j.internal.kernel.api.IndexQuery.StringSuffixPredicate;

class FusionIndexReader extends FusionIndexBase<IndexReader> implements IndexReader
{
Expand Down Expand Up @@ -76,109 +71,28 @@ public IndexSampler createSampler()
@Override
public PrimitiveLongResourceIterator query( IndexQuery... predicates ) throws IndexNotApplicableKernelException
{
if ( predicates.length > 1 )
IndexReader instance = selector.select( instances, predicates );
if ( instance != null )
{
return instances[LUCENE].query( predicates );
return instance.query( predicates );
}
IndexQuery predicate = predicates[0];

if ( predicate instanceof ExactPredicate )
{
ExactPredicate exactPredicate = (ExactPredicate) predicate;
return selector.select( instances, exactPredicate.value() ).query( predicates );
}

if ( predicate instanceof StringPrefixPredicate ||
predicate instanceof StringSuffixPredicate ||
predicate instanceof StringContainsPredicate )
{
return instances[STRING].query( predicate );
}

if ( predicate instanceof RangePredicate )
{
switch ( predicate.valueGroup() )
{
case NUMBER:
return instances[NUMBER].query( predicates );
case GEOMETRY:
return instances[SPATIAL].query( predicates );
case TEXT:
return instances[STRING].query( predicates );
case DATE:
case LOCAL_DATE_TIME:
case ZONED_DATE_TIME:
case LOCAL_TIME:
case ZONED_TIME:
case DURATION:
return instances[TEMPORAL].query( predicates );
default: // fall through
}
}

// todo: There will be no ordering of the node ids here. Is this a problem?
if ( predicate instanceof ExistsPredicate )
else
{
PrimitiveLongResourceIterator[] converted = instancesAs( PrimitiveLongResourceIterator.class, reader -> reader.query( predicates ) );
return PrimitiveLongResourceCollections.concat( converted );
}

return instances[LUCENE].query( predicates );
}

@Override
public void query( IndexProgressor.NodeValueClient cursor, IndexOrder indexOrder, IndexQuery... predicates )
throws IndexNotApplicableKernelException
{
if ( predicates.length > 1 )
{
instances[LUCENE].query( cursor, indexOrder, predicates );
return;
}
IndexQuery predicate = predicates[0];

if ( predicate instanceof ExactPredicate )
{
ExactPredicate exactPredicate = (ExactPredicate) predicate;
selector.select( instances, exactPredicate.value() ).query( cursor, indexOrder, predicate );
return;
}

if ( predicate instanceof StringPrefixPredicate ||
predicate instanceof StringSuffixPredicate ||
predicate instanceof StringContainsPredicate )
{
instances[STRING].query( cursor, indexOrder, predicate );
return;
}

if ( predicate instanceof RangePredicate )
IndexReader instance = selector.select( instances, predicates );
if ( instance != null )
{
switch ( predicate.valueGroup() )
{
case NUMBER:
instances[NUMBER].query( cursor, indexOrder, predicates );
return;
case GEOMETRY:
instances[SPATIAL].query( cursor, indexOrder, predicates );
return;
case TEXT:
instances[STRING].query( cursor, indexOrder, predicates );
return;
case DATE:
case LOCAL_DATE_TIME:
case ZONED_DATE_TIME:
case LOCAL_TIME:
case ZONED_TIME:
case DURATION:
instances[TEMPORAL].query( cursor, indexOrder, predicates );
return;
default: // fall through
}
instance.query( cursor, indexOrder, predicates );
}

// todo: There will be no ordering of the node ids here. Is this a problem?
if ( predicate instanceof ExistsPredicate )
else
{
if ( indexOrder != IndexOrder.NONE )
{
Expand All @@ -191,12 +105,9 @@ public void query( IndexProgressor.NodeValueClient cursor, IndexOrder indexOrder
cursor.initialize( descriptor, multiProgressor, predicates );
for ( IndexReader reader : instances )
{
reader.query( multiProgressor, indexOrder, predicate );
reader.query( multiProgressor, indexOrder, predicates );
}
return;
}

instances[LUCENE].query( cursor, indexOrder, predicates );
}

@Override
Expand Down

0 comments on commit a8c8acc

Please sign in to comment.