diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/SpatialIndexReader.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/SpatialIndexReader.java index 3cf12ba1277a..732634fd367c 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/SpatialIndexReader.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/SpatialIndexReader.java @@ -19,8 +19,6 @@ */ package org.neo4j.kernel.impl.index.schema; -import java.io.IOException; - import org.neo4j.collection.primitive.PrimitiveLongResourceIterator; import org.neo4j.graphdb.Resource; import org.neo4j.helpers.collection.Iterators; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/TemporalIndexReader.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/TemporalIndexReader.java index 5b2f45b32352..252e1c61843a 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/TemporalIndexReader.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/TemporalIndexReader.java @@ -19,8 +19,6 @@ */ package org.neo4j.kernel.impl.index.schema; -import java.io.IOException; - import org.neo4j.collection.primitive.PrimitiveLongResourceIterator; import org.neo4j.graphdb.Resource; import org.neo4j.helpers.collection.Iterators; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/TemporalIndexUpdater.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/TemporalIndexUpdater.java index c9704453bfc6..059323b8ecb6 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/TemporalIndexUpdater.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/TemporalIndexUpdater.java @@ -25,9 +25,10 @@ import org.neo4j.kernel.api.index.IndexEntryUpdate; import org.neo4j.kernel.api.index.IndexUpdater; import org.neo4j.kernel.impl.api.index.IndexUpdateMode; -import org.neo4j.kernel.impl.index.schema.fusion.FusionIndexBase; import org.neo4j.values.storable.ValueGroup; +import static org.neo4j.kernel.impl.index.schema.fusion.FusionIndexBase.forAll; + public class TemporalIndexUpdater extends TemporalIndexCache> implements IndexUpdater { TemporalIndexUpdater( TemporalIndexAccessor accessor, IndexUpdateMode mode ) @@ -68,7 +69,7 @@ public void process( IndexEntryUpdate update ) throws IOException, IndexEntry @Override public void close() throws IOException { - FusionIndexBase.forAll( NativeSchemaIndexUpdater::close, this ); + forAll( NativeSchemaIndexUpdater::close, this ); } static class PartFactory implements TemporalIndexCache.Factory> diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexAccessor.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexAccessor.java index 61222aa32fd0..5168f0f27a71 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexAccessor.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexAccessor.java @@ -21,9 +21,7 @@ import java.io.File; import java.io.IOException; -import java.util.ArrayList; import java.util.Iterator; -import java.util.List; import org.neo4j.graphdb.ResourceIterator; import org.neo4j.helpers.collection.BoundedIterable; @@ -36,12 +34,12 @@ import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; import org.neo4j.kernel.impl.api.index.IndexUpdateMode; import org.neo4j.kernel.impl.index.schema.fusion.FusionIndexProvider.DropAction; -import org.neo4j.kernel.impl.index.schema.fusion.FusionIndexProvider.Selector; import org.neo4j.storageengine.api.schema.IndexReader; import org.neo4j.values.storable.Value; -import static java.util.Arrays.stream; import static org.neo4j.helpers.collection.Iterators.concatResourceIterators; +import static org.neo4j.helpers.collection.Iterators.iterator; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.INSTANCE_COUNT; class FusionIndexAccessor extends FusionIndexBase implements IndexAccessor { @@ -49,13 +47,13 @@ class FusionIndexAccessor extends FusionIndexBase implements Inde private final SchemaIndexDescriptor descriptor; private final DropAction dropAction; - FusionIndexAccessor( IndexAccessor[] accessors, - Selector selector, + FusionIndexAccessor( SlotSelector slotSelector, + Selector selector, long indexId, SchemaIndexDescriptor descriptor, DropAction dropAction ) { - super( accessors, selector ); + super( slotSelector, selector ); this.indexId = indexId; this.descriptor = descriptor; this.dropAction = dropAction; @@ -64,44 +62,46 @@ class FusionIndexAccessor extends FusionIndexBase implements Inde @Override public void drop() throws IOException { - forAll( IndexAccessor::drop, instances ); + forAll( IndexAccessor::drop, selector ); dropAction.drop( indexId ); } @Override public IndexUpdater newUpdater( IndexUpdateMode mode ) { - return new FusionIndexUpdater( instancesAs( IndexUpdater.class, accessor -> accessor.newUpdater( mode ) ), selector ); + Selector updaterSelector = new Selector<>( new IndexUpdater[INSTANCE_COUNT], slot -> selector.select( slot ).newUpdater( mode ) ); + return new FusionIndexUpdater( slotSelector, updaterSelector ); } @Override public void force( IOLimiter ioLimiter ) throws IOException { - forAll( accessor -> accessor.force( ioLimiter ), instances ); + forAll( accessor -> accessor.force( ioLimiter ), selector ); } @Override public void refresh() throws IOException { - forAll( IndexAccessor::refresh, instances ); + forAll( IndexAccessor::refresh, selector ); } @Override public void close() throws IOException { - forAll( IndexAccessor::close, instances ); + forAll( IndexAccessor::close, selector ); } @Override public IndexReader newReader() { - return new FusionIndexReader( instancesAs( IndexReader.class, IndexAccessor::newReader ), selector, descriptor ); + Selector readerSelector = new Selector<>( new IndexReader[INSTANCE_COUNT], slot -> selector.select( slot ).newReader() ); + return new FusionIndexReader( slotSelector, readerSelector, descriptor ); } @Override public BoundedIterable newAllEntriesReader() { - BoundedIterable[] entries = instancesAs( BoundedIterable.class, IndexAccessor::newAllEntriesReader ); + BoundedIterable[] entries = instancesAs( new BoundedIterable[INSTANCE_COUNT], IndexAccessor::newAllEntriesReader ); return new BoundedIterable() { @Override @@ -147,30 +147,33 @@ public Iterator iterator() @Override public ResourceIterator snapshotFiles() throws IOException { - List> snapshots = new ArrayList<>(); - forAll( accessor -> snapshots.add( accessor.snapshotFiles() ), instances ); - return concatResourceIterators( snapshots.iterator() ); + return concatResourceIterators( iterator( instancesAs( new ResourceIterator[INSTANCE_COUNT], accessor -> accessor.snapshotFiles() ) ) ); } @Override public void verifyDeferredConstraints( PropertyAccessor propertyAccessor ) throws IndexEntryConflictException, IOException { - for ( IndexAccessor accessor : instances ) + for ( int slot = 0; slot < INSTANCE_COUNT; slot++ ) { - accessor.verifyDeferredConstraints( propertyAccessor ); + selector.select( slot ).verifyDeferredConstraints( propertyAccessor ); } } @Override public boolean isDirty() { - return stream( instances ).anyMatch( IndexAccessor::isDirty ); + boolean isDirty = false; + for ( int slot = 0; slot < INSTANCE_COUNT; slot++ ) + { + isDirty |= selector.select( slot ).isDirty(); + } + return isDirty; } @Override public void validateBeforeCommit( Value[] tuple ) { - selector.select( instances, tuple ).validateBeforeCommit( tuple ); + selector.select( slotSelector.selectSlot( tuple, GROUP_OF ) ).validateBeforeCommit( tuple ); } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexBase.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexBase.java index be05d66df191..512184233e94 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexBase.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexBase.java @@ -19,14 +19,18 @@ */ package org.neo4j.kernel.impl.index.schema.fusion; -import java.lang.reflect.Array; import java.util.Arrays; +import java.util.function.Function; import org.neo4j.collection.primitive.PrimitiveIntCollections; import org.neo4j.function.ThrowingConsumer; import org.neo4j.function.ThrowingFunction; import org.neo4j.helpers.Exceptions; import org.neo4j.kernel.api.index.IndexProvider; +import org.neo4j.values.storable.Value; +import org.neo4j.values.storable.ValueGroup; + +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.INSTANCE_COUNT; /** * Acting as a simplifier for the multiplexing that is going in inside a fusion index. A fusion index consists of multiple parts, @@ -37,42 +41,80 @@ */ public abstract class FusionIndexBase { - static final int INSTANCE_COUNT = 5; - - static final int STRING = 0; - static final int NUMBER = 1; - static final int SPATIAL = 2; - static final int TEMPORAL = 3; - static final int LUCENE = 4; + static Function GROUP_OF = Value::valueGroup; - final T[] instances; - final FusionIndexProvider.Selector selector; + final SlotSelector slotSelector; + final Selector selector; - FusionIndexBase( T[] instances, FusionIndexProvider.Selector selector ) + FusionIndexBase( SlotSelector slotSelector, Selector selector ) { - assert instances.length == INSTANCE_COUNT; - this.instances = instances; + this.slotSelector = slotSelector; this.selector = selector; } - R[] instancesAs( Class cls, ThrowingFunction converter ) throws E + /** + * Short-hand for calling the static {@link #instancesAs(Selector, Object[], ThrowingFunction)}, here with the local {@link #selector}. + */ + R[] instancesAs( R[] target, ThrowingFunction converter ) throws E { - return instancesAs( instances, cls, converter ); + return instancesAs( selector, target, converter ); } - static R[] instancesAs( T[] instances, Class cls, ThrowingFunction converter ) throws E + /** + * Convenience method typically for calling a method on each of the sub-parts of a fusion entity, + * one which creates another instance. All those instances are returned as an array, or actually put into an array + * created by the caller to avoid reflection to instantiate the array. + * + * @param selector {@link Selector} to use as the source. + * @param target array to put the created instances into, also returned. + * @param converter {@link ThrowingFunction} which converts from the source to target instance. + * @param type of source instance. + * @param type of target instance. + * @param type of exception that converter may throw. + * @return the target array which was passed in, now populated. + * @throws E exception from converter. + */ + static T[] instancesAs( Selector selector, T[] target, ThrowingFunction converter ) throws E { - R[] result = (R[]) Array.newInstance( cls, instances.length ); - for ( int i = 0; i < instances.length; i++ ) + for ( int slot = 0; slot < INSTANCE_COUNT; slot++ ) { - result[i] = converter.apply( instances[i] ); + target[slot] = converter.apply( selector.select( slot ) ); + } + return target; + } + + static void forInstantiated( ThrowingConsumer consumer, Selector selector ) throws E + { + E exception = null; + for ( int slot = 0; slot < INSTANCE_COUNT; slot++ ) + { + T instance = selector.getIfInstantiated( slot ); + if ( instance != null ) + { + exception = consume( exception, consumer, instance ); + } + } + if ( exception != null ) + { + throw exception; + } + } + + public static void forAll( ThrowingConsumer consumer, Selector selector ) throws E + { + E exception = null; + for ( int slot = 0; slot < INSTANCE_COUNT; slot++ ) + { + exception = consume( exception, consumer, selector.select( slot ) ); + } + if ( exception != null ) + { + throw exception; } - return result; } /** - * NOTE: duplicate of {@link #forAll(ThrowingConsumer, Iterable)} to avoid having to wrap subjects of one form into another. - * There are some real use cases for passing in an array instead of {@link Iterable} out there... + * See {@link #forAll(ThrowingConsumer, Object[])} * * Method for calling a lambda function on many objects when it is expected that the function might * throw an exception. First exception will be thrown and subsequent will be suppressed. @@ -90,21 +132,12 @@ static R[] instancesAs( T[] instances, Class cls, T * @param the type of exception anticipated, inferred from the lambda * @throws E if consumption fails with this exception */ - @SafeVarargs - public static void forAll( ThrowingConsumer consumer, T... subjects ) throws E + public static void forAll( ThrowingConsumer consumer, Iterable subjects ) throws E { - // Duplicate this method for array to avoid creating a purely internal list to shove that in to the other method. E exception = null; - for ( T subject : subjects ) + for ( T instance : subjects ) { - try - { - consumer.accept( subject ); - } - catch ( Exception e ) - { - exception = Exceptions.chain( exception, (E) e ); - } + exception = consume( exception, consumer, instance ); } if ( exception != null ) { @@ -113,10 +146,6 @@ public static void forAll( ThrowingConsumer consum } /** - * See {@link #forAll(ThrowingConsumer, Object[])} - * NOTE: duplicate of {@link #forAll(ThrowingConsumer, Object[])} to avoid having to wrap subjects of one form into another. - * There are some real use cases for passing in an Iterable instead of array out there... - * * Method for calling a lambda function on many objects when it is expected that the function might * throw an exception. First exception will be thrown and subsequent will be suppressed. * @@ -133,24 +162,22 @@ public static void forAll( ThrowingConsumer consum * @param the type of exception anticipated, inferred from the lambda * @throws E if consumption fails with this exception */ - public static void forAll( ThrowingConsumer consumer, Iterable subjects ) throws E + public static void forAll( ThrowingConsumer consumer, T[] subjects ) throws E { - E exception = null; - for ( T subject : subjects ) + forAll( consumer, Arrays.asList( subjects ) ); + } + + private static E consume( E exception, ThrowingConsumer consumer, T instance ) + { + try { - try - { - consumer.accept( subject ); - } - catch ( Exception e ) - { - exception = Exceptions.chain( exception, (E) e ); - } + consumer.accept( instance ); } - if ( exception != null ) + catch ( Exception e ) { - throw exception; + exception = Exceptions.chain( exception, (E) e ); } + return exception; } static void validateSelectorInstances( Object[] instances, int... aliveIndex ) diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexPopulator.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexPopulator.java index da379363db93..e13fc6b7f639 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexPopulator.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexPopulator.java @@ -29,10 +29,10 @@ import org.neo4j.kernel.api.index.IndexUpdater; import org.neo4j.kernel.api.index.PropertyAccessor; import org.neo4j.kernel.impl.index.schema.fusion.FusionIndexProvider.DropAction; -import org.neo4j.kernel.impl.index.schema.fusion.FusionIndexProvider.Selector; import org.neo4j.storageengine.api.schema.IndexSample; import static org.neo4j.kernel.impl.index.schema.fusion.FusionIndexSampler.combineSamples; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.INSTANCE_COUNT; class FusionIndexPopulator extends FusionIndexBase implements IndexPopulator { @@ -40,9 +40,9 @@ class FusionIndexPopulator extends FusionIndexBase implements In private final DropAction dropAction; private final boolean archiveFailedIndex; - FusionIndexPopulator( IndexPopulator[] populators, Selector selector, long indexId, DropAction dropAction, boolean archiveFailedIndex ) + FusionIndexPopulator( SlotSelector slotSelector, Selector selector, long indexId, DropAction dropAction, boolean archiveFailedIndex ) { - super( populators, selector ); + super( slotSelector, selector ); this.indexId = indexId; this.dropAction = dropAction; this.archiveFailedIndex = archiveFailedIndex; @@ -52,37 +52,32 @@ class FusionIndexPopulator extends FusionIndexBase implements In public void create() throws IOException { dropAction.drop( indexId, archiveFailedIndex ); - forAll( IndexPopulator::create, instances ); + forAll( IndexPopulator::create, selector ); } @Override public void drop() throws IOException { - forAll( IndexPopulator::drop, instances ); + forAll( IndexPopulator::drop, selector ); dropAction.drop( indexId ); } @Override public void add( Collection> updates ) throws IndexEntryConflictException, IOException { - Collection>[] batches = new Collection[instances.length]; + Selector>> batchSelector = new Selector<>( new Collection[INSTANCE_COUNT], slot -> new ArrayList<>() ); for ( IndexEntryUpdate update : updates ) { - int slot = selector.selectSlot( update.values() ); - Collection> batch = batches[slot]; - if ( batch == null ) - { - batch = new ArrayList<>(); - batches[slot] = batch; - } - batch.add( update ); + batchSelector.select( slotSelector.selectSlot( update.values(), GROUP_OF ) ).add( update ); } - for ( int i = 0; i < instances.length; i++ ) + // Manual loop due do multiple exception types + for ( int slot = 0; slot < INSTANCE_COUNT; slot++ ) { - if ( batches[i] != null ) + Collection> batch = batchSelector.getIfInstantiated( slot ); + if ( batch != null ) { - instances[i].add( batches[i] ); + this.selector.select( slot ).add( batch ); } } } @@ -91,39 +86,42 @@ public void add( Collection> updates ) throws Inde public void verifyDeferredConstraints( PropertyAccessor propertyAccessor ) throws IndexEntryConflictException, IOException { - for ( IndexPopulator populator : instances ) + // Manual loop due do multiple exception types + for ( int slot = 0; slot < INSTANCE_COUNT; slot++ ) { - populator.verifyDeferredConstraints( propertyAccessor ); + selector.select( slot ).verifyDeferredConstraints( propertyAccessor ); } } @Override public IndexUpdater newPopulatingUpdater( PropertyAccessor accessor ) throws IOException { - return new FusionIndexUpdater( instancesAs( IndexUpdater.class, populator -> populator.newPopulatingUpdater( accessor ) ), selector ); + Selector updaterSelector = + new Selector<>( new IndexUpdater[INSTANCE_COUNT], slot -> selector.select( slot ).newPopulatingUpdater( accessor ) ); + return new FusionIndexUpdater( slotSelector, updaterSelector ); } @Override public void close( boolean populationCompletedSuccessfully ) throws IOException { - forAll( populator -> populator.close( populationCompletedSuccessfully ), instances ); + forAll( populator -> populator.close( populationCompletedSuccessfully ), selector ); } @Override public void markAsFailed( String failure ) throws IOException { - forAll( populator -> populator.markAsFailed( failure ), instances ); + forAll( populator -> populator.markAsFailed( failure ), selector ); } @Override public void includeSample( IndexEntryUpdate update ) { - selector.select( instances, update.values() ).includeSample( update ); + selector.select( slotSelector.selectSlot( update.values(), GROUP_OF ) ).includeSample( update ); } @Override public IndexSample sampleResult() { - return combineSamples( instancesAs( IndexSample.class, IndexPopulator::sampleResult ) ); + return combineSamples( instancesAs( new IndexSample[INSTANCE_COUNT], IndexPopulator::sampleResult ) ); } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexProvider.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexProvider.java index 1b630b96b5ee..8caf89013597 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexProvider.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexProvider.java @@ -26,7 +26,6 @@ import org.neo4j.graphdb.factory.GraphDatabaseSettings; 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.compress.ZipUtils; import org.neo4j.io.fs.FileSystemAbstraction; @@ -40,20 +39,18 @@ import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingConfig; 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.ValueCategory; 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; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.INSTANCE_COUNT; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.LUCENE; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.NUMBER; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.SPATIAL; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.STRING; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.TEMPORAL; /** * This {@link IndexProvider index provider} act as one logical index but is backed by four physical @@ -61,26 +58,11 @@ */ public class FusionIndexProvider extends IndexProvider { - interface Selector - { - void validateSatisfied( Object[] instances ); - - int selectSlot( Value... values ); - - default T select( T[] instances, Value... values ) - { - return instances[selectSlot( values )]; - } - - /** - * @return Appropriate IndexReader for given predicate or null if predicate needs all readers. - */ - IndexReader select( IndexReader[] instances, IndexQuery... predicates ); - } private final boolean archiveFailedIndex; private final IndexProvider[] providers = new IndexProvider[INSTANCE_COUNT]; - private final Selector selector; + private final Selector selector; + private final SlotSelector slotSelector; private final DropAction dropAction; public FusionIndexProvider( @@ -90,7 +72,7 @@ public FusionIndexProvider( IndexProvider spatialProvider, IndexProvider temporalProvider, IndexProvider luceneProvider, - Selector selector, + SlotSelector slotSelector, Descriptor descriptor, int priority, IndexDirectoryStructure.Factory directoryStructure, @@ -99,9 +81,10 @@ public FusionIndexProvider( { super( descriptor, priority, directoryStructure ); fillProvidersArray( stringProvider, numberProvider, spatialProvider, temporalProvider, luceneProvider ); - selector.validateSatisfied( providers ); + slotSelector.validateSatisfied( providers ); this.archiveFailedIndex = archiveFailedIndex; - this.selector = selector; + this.slotSelector = slotSelector; + this.selector = new Selector<>( providers ); this.dropAction = new FileSystemDropAction( fs, directoryStructure() ); } @@ -118,24 +101,25 @@ private void fillProvidersArray( IndexProvider stringProvider, IndexProvider num @Override public IndexPopulator getPopulator( long indexId, SchemaIndexDescriptor descriptor, IndexSamplingConfig samplingConfig ) { - return new FusionIndexPopulator( instancesAs( providers, IndexPopulator.class, - provider -> provider.getPopulator( indexId, descriptor, samplingConfig ) ), selector, indexId, dropAction, archiveFailedIndex ); + IndexPopulator[] populators = + instancesAs( selector, new IndexPopulator[INSTANCE_COUNT], provider -> provider.getPopulator( indexId, descriptor, samplingConfig ) ); + return new FusionIndexPopulator( slotSelector, new Selector<>( populators ), indexId, dropAction, archiveFailedIndex ); } @Override public IndexAccessor getOnlineAccessor( long indexId, SchemaIndexDescriptor descriptor, IndexSamplingConfig samplingConfig ) throws IOException { - return new FusionIndexAccessor( - instancesAs( providers, IndexAccessor.class, provider -> provider.getOnlineAccessor( indexId, descriptor, samplingConfig ) ), - selector, indexId, descriptor, dropAction ); + IndexAccessor[] accessors = + instancesAs( selector, new IndexAccessor[INSTANCE_COUNT], provider -> provider.getOnlineAccessor( indexId, descriptor, samplingConfig ) ); + return new FusionIndexAccessor( slotSelector, new Selector<>( accessors ), indexId, descriptor, dropAction ); } @Override public String getPopulationFailure( long indexId, SchemaIndexDescriptor descriptor ) throws IllegalStateException { StringBuilder builder = new StringBuilder(); - forAll( p -> writeFailure( p.getClass().getSimpleName(), builder, p, indexId, descriptor ), providers ); + forAll( p -> writeFailure( p.getClass().getSimpleName(), builder, p, indexId, descriptor ), selector ); String failure = builder.toString(); if ( !failure.isEmpty() ) { @@ -162,7 +146,7 @@ private void writeFailure( String indexName, StringBuilder builder, IndexProvide @Override public InternalIndexState getInitialState( long indexId, SchemaIndexDescriptor descriptor ) { - InternalIndexState[] states = FusionIndexBase.instancesAs( providers, InternalIndexState.class, p -> p.getInitialState( indexId, descriptor ) ); + InternalIndexState[] states = instancesAs( selector, new InternalIndexState[INSTANCE_COUNT], 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 @@ -180,11 +164,8 @@ public InternalIndexState getInitialState( long indexId, SchemaIndexDescriptor d @Override public IndexCapability getCapability( SchemaIndexDescriptor schemaIndexDescriptor ) { - IndexCapability[] capabilities = new IndexCapability[providers.length]; - for ( int i = 0; i < providers.length; i++ ) - { - capabilities[i] = providers[i].getCapability( schemaIndexDescriptor ); - } + IndexCapability[] capabilities = + instancesAs( selector, new IndexCapability[providers.length], provider -> provider.getCapability( schemaIndexDescriptor ) ); return new UnionIndexCapability( capabilities ) { @Override @@ -193,7 +174,7 @@ public IndexOrder[] orderCapability( ValueCategory... valueCategories ) // No order capability when combining results from different indexes if ( valueCategories.length == 1 && valueCategories[0] == ValueCategory.UNKNOWN ) { - return new IndexOrder[0]; + return ORDER_NONE; } // Otherwise union of capabilities return super.orderCapability( valueCategories ); diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexReader.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexReader.java index d196b7b5edfa..67ffce65aea8 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexReader.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexReader.java @@ -21,7 +21,6 @@ import java.util.Arrays; -import org.neo4j.collection.primitive.PrimitiveLongResourceCollections; import org.neo4j.collection.primitive.PrimitiveLongResourceIterator; import org.neo4j.graphdb.Resource; import org.neo4j.internal.kernel.api.IndexOrder; @@ -30,65 +29,60 @@ 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 static java.lang.String.format; +import static org.neo4j.collection.primitive.PrimitiveLongResourceCollections.concat; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.INSTANCE_COUNT; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.UNKNOWN; class FusionIndexReader extends FusionIndexBase implements IndexReader { private final SchemaIndexDescriptor descriptor; - FusionIndexReader( IndexReader[] readers, Selector selector, SchemaIndexDescriptor descriptor ) + FusionIndexReader( SlotSelector slotSelector, Selector selector, SchemaIndexDescriptor descriptor ) { - super( readers, selector ); + super( slotSelector, selector ); this.descriptor = descriptor; } @Override public void close() { - forAll( Resource::close, instances ); + forInstantiated( Resource::close, selector ); } @Override public long countIndexedNodes( long nodeId, Value... propertyValues ) { - return selector.select( instances, propertyValues ).countIndexedNodes( nodeId, propertyValues ); + return selector.select( slotSelector.selectSlot( propertyValues, GROUP_OF ) ).countIndexedNodes( nodeId, propertyValues ); } @Override public IndexSampler createSampler() { - return new FusionIndexSampler( instancesAs( IndexSampler.class, IndexReader::createSampler ) ); + return new FusionIndexSampler( instancesAs( new IndexSampler[INSTANCE_COUNT], IndexReader::createSampler ) ); } @Override public PrimitiveLongResourceIterator query( IndexQuery... predicates ) throws IndexNotApplicableKernelException { - IndexReader instance = selector.select( instances, predicates ); - if ( instance != null ) - { - return instance.query( predicates ); - } - else - { - PrimitiveLongResourceIterator[] converted = instancesAs( PrimitiveLongResourceIterator.class, reader -> reader.query( predicates ) ); - return PrimitiveLongResourceCollections.concat( converted ); - } + int slot = slotSelector.selectSlot( predicates, IndexQuery::valueGroup ); + return slot != UNKNOWN ? selector.select( slot ).query( predicates ) + : concat( instancesAs( new PrimitiveLongResourceIterator[INSTANCE_COUNT], reader -> reader.query( predicates ) ) ); } @Override public void query( IndexProgressor.NodeValueClient cursor, IndexOrder indexOrder, IndexQuery... predicates ) throws IndexNotApplicableKernelException { - IndexReader instance = selector.select( instances, predicates ); - if ( instance != null ) + int slot = slotSelector.selectSlot( predicates, IndexQuery::valueGroup ); + if ( slot != UNKNOWN ) { - instance.query( cursor, indexOrder, predicates ); + selector.select( slot ).query( cursor, indexOrder, predicates ); } else { @@ -101,18 +95,19 @@ public void query( IndexProgressor.NodeValueClient cursor, IndexOrder indexOrder BridgingIndexProgressor multiProgressor = new BridgingIndexProgressor( cursor, descriptor.schema().getPropertyIds() ); cursor.initialize( descriptor, multiProgressor, predicates ); - for ( IndexReader reader : instances ) - { - reader.query( multiProgressor, indexOrder, predicates ); - } + forAll( reader -> reader.query( multiProgressor, indexOrder, predicates ), selector ); } } @Override public boolean hasFullValuePrecision( IndexQuery... predicates ) { - IndexReader instance = selector.select( instances, predicates ); - if ( instance == null ) + int slot = slotSelector.selectSlot( predicates, IndexQuery::valueGroup ); + if ( slot != UNKNOWN ) + { + return selector.select( slot ).hasFullValuePrecision( predicates ); + } + else { if ( !(predicates.length == 1 && predicates[0] instanceof ExistsPredicate) ) { @@ -122,6 +117,5 @@ public boolean hasFullValuePrecision( IndexQuery... predicates ) // full value precision for that, therefor true. return true; } - return instance.hasFullValuePrecision( predicates ); } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexUpdater.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexUpdater.java index 3592ce5b2e76..68d7b7442d8b 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexUpdater.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexUpdater.java @@ -24,13 +24,12 @@ import org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException; import org.neo4j.kernel.api.index.IndexEntryUpdate; import org.neo4j.kernel.api.index.IndexUpdater; -import org.neo4j.kernel.impl.index.schema.fusion.FusionIndexProvider.Selector; class FusionIndexUpdater extends FusionIndexBase implements IndexUpdater { - FusionIndexUpdater( IndexUpdater[] updaters, Selector selector ) + FusionIndexUpdater( SlotSelector slotSelector, Selector selector ) { - super( updaters, selector ); + super( slotSelector, selector ); } @Override @@ -39,14 +38,14 @@ public void process( IndexEntryUpdate update ) throws IOException, IndexEntry switch ( update.updateMode() ) { case ADDED: - selector.select( instances, update.values() ).process( update ); + selector.select( slotSelector.selectSlot( update.values(), GROUP_OF ) ).process( update ); break; case CHANGED: // Hmm, here's a little conundrum. What if we change from a value that goes into native // to a value that goes into fallback, or vice versa? We also don't want to blindly pass // all CHANGED updates to both updaters since not all values will work in them. - IndexUpdater from = selector.select( instances, update.beforeValues() ); - IndexUpdater to = selector.select( instances, update.values() ); + IndexUpdater from = selector.select( slotSelector.selectSlot( update.beforeValues(), GROUP_OF ) ); + IndexUpdater to = selector.select( slotSelector.selectSlot( update.values(), GROUP_OF ) ); // There are two cases: // - both before/after go into the same updater --> pass update into that updater if ( from == to ) @@ -61,7 +60,7 @@ public void process( IndexEntryUpdate update ) throws IOException, IndexEntry } break; case REMOVED: - selector.select( instances, update.values() ).process( update ); + selector.select( slotSelector.selectSlot( update.values(), GROUP_OF ) ).process( update ); break; default: throw new IllegalArgumentException( "Unknown update mode" ); @@ -73,7 +72,7 @@ public void close() throws IOException, IndexEntryConflictException { try { - forAll( IndexUpdater::close, instances ); + forInstantiated( IndexUpdater::close, selector ); } catch ( IOException | IndexEntryConflictException | RuntimeException e ) { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionSelector00.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionSelector00.java index ecefc63ad292..e925f8b4cfed 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionSelector00.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionSelector00.java @@ -19,68 +19,42 @@ */ package org.neo4j.kernel.impl.index.schema.fusion; -import org.neo4j.internal.kernel.api.IndexQuery; -import org.neo4j.internal.kernel.api.IndexQuery.RangePredicate; -import org.neo4j.storageengine.api.schema.IndexReader; -import org.neo4j.values.storable.Value; +import java.util.function.Function; -import static org.neo4j.internal.kernel.api.IndexQuery.ExactPredicate; -import static org.neo4j.internal.kernel.api.IndexQuery.ExistsPredicate; -import static org.neo4j.kernel.impl.index.schema.fusion.FusionIndexBase.LUCENE; -import static org.neo4j.kernel.impl.index.schema.fusion.FusionIndexBase.SPATIAL; -import static org.neo4j.kernel.impl.index.schema.fusion.FusionIndexBase.TEMPORAL; +import org.neo4j.kernel.api.index.IndexProvider; +import org.neo4j.values.storable.ValueGroup; /** * Selector for index provider "lucene-1.x". * The version name "00" comes from lucene-1.x originally not being a fusion index. */ -public class FusionSelector00 implements FusionIndexProvider.Selector +public class FusionSelector00 implements SlotSelector { @Override - public void validateSatisfied( Object[] instances ) + public void validateSatisfied( IndexProvider[] instances ) { FusionIndexBase.validateSelectorInstances( instances, LUCENE, SPATIAL, TEMPORAL ); } @Override - public int selectSlot( Value... values ) + public int selectSlot( V[] values, Function groupOf ) { if ( values.length > 1 ) { return LUCENE; } - Value singleValue = values[0]; - switch ( singleValue.valueGroup().category() ) + ValueGroup singleGroup = groupOf.apply( values[0] ); + switch ( singleGroup.category() ) { case GEOMETRY: return SPATIAL; case TEMPORAL: return TEMPORAL; - default: - return LUCENE; - } - } - - @Override - public IndexReader select( IndexReader[] instances, IndexQuery... predicates ) - { - if ( predicates.length > 1 ) - { - return instances[LUCENE]; - } - - IndexQuery predicate = predicates[0]; - switch ( predicate.valueGroup().category() ) - { - case GEOMETRY: - return instances[SPATIAL]; - case TEMPORAL: - return instances[TEMPORAL]; case UNKNOWN: - return null; + return UNKNOWN; default: - return instances[LUCENE]; + return LUCENE; } } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionSelector10.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionSelector10.java index 0b0cd52df6b7..dfb9e1812639 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionSelector10.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionSelector10.java @@ -19,38 +19,33 @@ */ package org.neo4j.kernel.impl.index.schema.fusion; -import org.neo4j.internal.kernel.api.IndexQuery; -import org.neo4j.storageengine.api.schema.IndexReader; -import org.neo4j.values.storable.Value; - -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.TEMPORAL; +import java.util.function.Function; +import org.neo4j.kernel.api.index.IndexProvider; +import org.neo4j.values.storable.ValueGroup; /** * Selector for "lucene+native-1.x". * Separates numbers into native index. */ -public class FusionSelector10 implements FusionIndexProvider.Selector +public class FusionSelector10 implements SlotSelector { @Override - public void validateSatisfied( Object[] instances ) + public void validateSatisfied( IndexProvider[] instances ) { FusionIndexBase.validateSelectorInstances( instances, NUMBER, LUCENE, SPATIAL, TEMPORAL ); } @Override - public int selectSlot( Value... values ) + public int selectSlot( V[] values, Function groupOf ) { if ( values.length > 1 ) { return LUCENE; } - Value singleValue = values[0]; - switch ( singleValue.valueGroup().category() ) + ValueGroup singleGroup = groupOf.apply( values[0] ); + switch ( singleGroup.category() ) { case NUMBER: return NUMBER; @@ -58,32 +53,10 @@ public int selectSlot( Value... values ) return SPATIAL; case TEMPORAL: return TEMPORAL; - default: - return LUCENE; - } - } - - @Override - public IndexReader select( IndexReader[] instances, IndexQuery... predicates ) - { - if ( predicates.length > 1 ) - { - return instances[LUCENE]; - } - - IndexQuery predicate = predicates[0]; - switch ( predicate.valueGroup().category() ) - { - case NUMBER: - return instances[NUMBER]; - case GEOMETRY: - return instances[SPATIAL]; - case TEMPORAL: - return instances[TEMPORAL]; case UNKNOWN: - return null; + return UNKNOWN; default: - return instances[LUCENE]; + return LUCENE; } } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionSelector20.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionSelector20.java index 13f3ae373663..e825adb2685f 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionSelector20.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionSelector20.java @@ -19,38 +19,34 @@ */ package org.neo4j.kernel.impl.index.schema.fusion; -import org.neo4j.internal.kernel.api.IndexQuery; -import org.neo4j.storageengine.api.schema.IndexReader; -import org.neo4j.values.storable.Value; +import java.util.function.Function; + +import org.neo4j.kernel.api.index.IndexProvider; +import org.neo4j.values.storable.ValueGroup; -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; /** * Selector for "lucene+native-2.x". * Separates strings, numbers, temporal and spatial into native index. */ -public class FusionSelector20 implements FusionIndexProvider.Selector +public class FusionSelector20 implements SlotSelector { @Override - public void validateSatisfied( Object[] instances ) + public void validateSatisfied( IndexProvider[] instances ) { FusionIndexBase.validateSelectorInstances( instances, STRING, NUMBER, SPATIAL, TEMPORAL, LUCENE ); } @Override - public int selectSlot( Value... values ) + public int selectSlot( V[] values, Function groupOf ) { if ( values.length > 1 ) { return LUCENE; } - Value singleValue = values[0]; - switch ( singleValue.valueGroup().category() ) + ValueGroup singleGroup = groupOf.apply( values[0] ); + switch ( singleGroup.category() ) { case NUMBER: return NUMBER; @@ -60,34 +56,10 @@ public int selectSlot( Value... values ) return SPATIAL; case TEMPORAL: return TEMPORAL; - default: - return LUCENE; - } - } - - @Override - public IndexReader select( IndexReader[] instances, IndexQuery... predicates ) - { - if ( predicates.length > 1 ) - { - return instances[LUCENE]; - } - - IndexQuery predicate = predicates[0]; - switch ( predicate.valueGroup().category() ) - { - case NUMBER: - return instances[NUMBER]; - case TEXT: - return instances[STRING]; - case GEOMETRY: - return instances[SPATIAL]; - case TEMPORAL: - return instances[TEMPORAL]; case UNKNOWN: - return null; + return UNKNOWN; default: - return instances[LUCENE]; + return LUCENE; } } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/Selector.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/Selector.java new file mode 100644 index 000000000000..2c9cfcdc6bea --- /dev/null +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/Selector.java @@ -0,0 +1,73 @@ +/* + * 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 . + */ +package org.neo4j.kernel.impl.index.schema.fusion; + +/** + * Selects an instance given a certain slot. + * @param type of instance + */ +class Selector +{ + private final T[] instances; + private final ThrowingIntFunction factory; + + /** + * @param instances fully instantiated instances so that no factory is needed. + */ + Selector( T[] instances ) + { + this( instances, slot -> + { + throw new IllegalStateException( "No instantiation expected" ); + } ); + } + + /** + * @param instances uninstantiated instances, instantiated lazily by the {@code factory}. + * @param factory {@link ThrowingIntFunction} for instantiating instances for specific slots. + */ + Selector( T[] instances, ThrowingIntFunction factory ) + { + this.instances = instances; + this.factory = factory; + } + + T select( int slot ) + { + if ( instances[slot] == null ) + { + try + { + instances[slot] = factory.apply( slot ); + } + catch ( Exception e ) + { + // TODO figure out how to handle this + throw new RuntimeException( e ); + } + } + return instances[slot]; + } + + T getIfInstantiated( int slot ) + { + return instances[slot]; + } +} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/SlotSelector.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/SlotSelector.java new file mode 100644 index 000000000000..d4b54841edf7 --- /dev/null +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/SlotSelector.java @@ -0,0 +1,53 @@ +/* + * 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 . + */ +package org.neo4j.kernel.impl.index.schema.fusion; + +import java.util.function.Function; + +import org.neo4j.kernel.api.index.IndexProvider; +import org.neo4j.values.storable.ValueGroup; + +/** + * Given a set of values selects a slot to use. + */ +interface SlotSelector +{ + int INSTANCE_COUNT = 5; + + int UNKNOWN = -1; + int STRING = 0; + int NUMBER = 1; + int SPATIAL = 2; + int TEMPORAL = 3; + int LUCENE = 4; + + void validateSatisfied( IndexProvider[] instances ); + + /** + * Selects a slot to use based on the given values. The values can be anything that can yield a {@link ValueGroup value group}, + * which is what the {@code groupOf} function extracts from each value. + * + * @param values values, something which can yield a {@link ValueGroup}. + * @param groupOf {@link Function} to get {@link ValueGroup} for the given values. + * @param type of value to extract {@link ValueGroup} from. + * @return a slot number, or {@link #UNKNOWN} if no single slot could be selected. This typically means that all slots are needed. + */ + int selectSlot( V[] values, Function groupOf ); +} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/ThrowingIntFunction.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/ThrowingIntFunction.java new file mode 100644 index 000000000000..d1fea0eabb00 --- /dev/null +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/ThrowingIntFunction.java @@ -0,0 +1,33 @@ +/* + * 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 . + */ +package org.neo4j.kernel.impl.index.schema.fusion; + +import java.util.function.IntFunction; + +/** + * Like {@link IntFunction}, but one that can throw {@link Exception}. + * + * @param type of return value. + * @param type of {@link Exception}. + */ +public interface ThrowingIntFunction +{ + T apply( int value ) throws E; +} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexAccessorTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexAccessorTest.java index aa9e0ccbbe4b..26ec995f7173 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexAccessorTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexAccessorTest.java @@ -56,18 +56,18 @@ import static org.mockito.Mockito.when; import static org.mockito.internal.verification.VerificationModeFactory.times; import static org.neo4j.helpers.ArrayUtil.without; -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.FusionIndexTestHelp.verifyFusionCloseThrowIfAllThrow; import static org.neo4j.kernel.impl.index.schema.fusion.FusionIndexTestHelp.verifyFusionCloseThrowOnSingleCloseThrow; import static org.neo4j.kernel.impl.index.schema.fusion.FusionIndexTestHelp.verifyOtherIsClosedOnSingleThrow; import static org.neo4j.kernel.impl.index.schema.fusion.FusionVersion.v00; import static org.neo4j.kernel.impl.index.schema.fusion.FusionVersion.v10; import static org.neo4j.kernel.impl.index.schema.fusion.FusionVersion.v20; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.INSTANCE_COUNT; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.LUCENE; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.NUMBER; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.SPATIAL; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.STRING; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.TEMPORAL; import static org.neo4j.values.storable.Values.stringValue; @RunWith( Parameterized.class ) @@ -131,7 +131,9 @@ private void initiateMocks() throw new RuntimeException(); } } - fusionIndexAccessor = new FusionIndexAccessor( accessors, fusionVersion.selector(), indexId, mock( SchemaIndexDescriptor.class ), dropAction ); + fusionIndexAccessor = + new FusionIndexAccessor( fusionVersion.slotSelector(), new Selector<>( accessors ), indexId, mock( SchemaIndexDescriptor.class ), + dropAction ); } private void resetMocks() diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexPopulatorTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexPopulatorTest.java index 4c2c0ca80ead..9ea43c4fab64 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexPopulatorTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexPopulatorTest.java @@ -49,17 +49,17 @@ import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -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.FusionIndexTestHelp.add; import static org.neo4j.kernel.impl.index.schema.fusion.FusionIndexTestHelp.verifyCallFail; import static org.neo4j.kernel.impl.index.schema.fusion.FusionVersion.v00; import static org.neo4j.kernel.impl.index.schema.fusion.FusionVersion.v10; import static org.neo4j.kernel.impl.index.schema.fusion.FusionVersion.v20; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.INSTANCE_COUNT; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.LUCENE; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.NUMBER; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.SPATIAL; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.STRING; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.TEMPORAL; @RunWith( Parameterized.class ) public class FusionIndexPopulatorTest @@ -119,7 +119,7 @@ private void initiateMocks() throw new RuntimeException(); } } - fusionIndexPopulator = new FusionIndexPopulator( populators, fusionVersion.selector(), indexId, dropAction, false ); + fusionIndexPopulator = new FusionIndexPopulator( fusionVersion.slotSelector(), new Selector<>( populators ), indexId, dropAction, false ); } private void resetMocks() @@ -231,7 +231,7 @@ public void addMustSelectCorrectPopulator() throws Exception { for ( Value secondValue : allValues ) { - verifyAddWithCorrectPopulator( populators[FusionIndexBase.LUCENE], firstValue, secondValue ); + verifyAddWithCorrectPopulator( populators[LUCENE], firstValue, secondValue ); } } } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexProviderTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexProviderTest.java index f044aa450f35..87944cd39d3a 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexProviderTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexProviderTest.java @@ -38,7 +38,6 @@ 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.index.schema.fusion.FusionIndexProvider.Selector; import org.neo4j.storageengine.api.schema.IndexSample; import org.neo4j.test.rule.RandomRule; import org.neo4j.values.storable.Value; @@ -55,15 +54,16 @@ import static org.neo4j.helpers.ArrayUtil.array; import static org.neo4j.kernel.api.index.IndexDirectoryStructure.NONE; import static org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory.forLabel; -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.GROUP_OF; import static org.neo4j.kernel.impl.index.schema.fusion.FusionVersion.v00; import static org.neo4j.kernel.impl.index.schema.fusion.FusionVersion.v10; import static org.neo4j.kernel.impl.index.schema.fusion.FusionVersion.v20; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.INSTANCE_COUNT; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.LUCENE; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.NUMBER; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.SPATIAL; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.STRING; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.TEMPORAL; @RunWith( Parameterized.class ) public class FusionIndexProviderTest @@ -73,7 +73,8 @@ public class FusionIndexProviderTest private IndexProvider[] providers; private IndexProvider[] aliveProviders; private IndexProvider fusionIndexProvider; - private Selector selector; + private SlotSelector slotSelector; + private Selector selector; @Parameterized.Parameters( name = "{0}" ) public static FusionVersion[] versions() @@ -90,7 +91,7 @@ public static FusionVersion[] versions() @Before public void setup() { - selector = fusionVersion.selector(); + slotSelector = fusionVersion.slotSelector(); setupMocks(); } @@ -110,7 +111,7 @@ public void mustSelectCorrectTargetForAllGivenValueCombinations() for ( Value value : group ) { // when - IndexProvider selected = selector.select( providers, value ); + IndexProvider selected = selector.select( slotSelector.selectSlot( array( value ), GROUP_OF ) ); // then assertSame( orLucene( providers[i] ), selected ); @@ -123,7 +124,7 @@ public void mustSelectCorrectTargetForAllGivenValueCombinations() for ( Value secondValue : allValues ) { // when - IndexProvider selected = selector.select( providers, firstValue, secondValue ); + IndexProvider selected = selector.select( slotSelector.selectSlot( array( firstValue, secondValue ), GROUP_OF ) ); // then assertSame( providers[LUCENE], selected ); @@ -318,7 +319,8 @@ private void setupMocks() providers[SPATIAL], providers[TEMPORAL], providers[LUCENE], - fusionVersion.selector(), DESCRIPTOR, 10, NONE, mock( FileSystemAbstraction.class ), false ); + fusionVersion.slotSelector(), DESCRIPTOR, 10, NONE, mock( FileSystemAbstraction.class ), false ); + selector = new Selector<>( providers ); } private IndexProvider mockProvider( Class providerClass, String name ) diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexReaderTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexReaderTest.java index c61f0f94d186..294312fe7827 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexReaderTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexReaderTest.java @@ -53,15 +53,15 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -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.FusionVersion.v00; import static org.neo4j.kernel.impl.index.schema.fusion.FusionVersion.v10; import static org.neo4j.kernel.impl.index.schema.fusion.FusionVersion.v20; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.INSTANCE_COUNT; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.LUCENE; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.NUMBER; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.SPATIAL; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.STRING; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.TEMPORAL; @RunWith( Parameterized.class ) public class FusionIndexReaderTest @@ -121,7 +121,8 @@ private void initiateMocks() throw new RuntimeException(); } } - fusionIndexReader = new FusionIndexReader( readers, fusionVersion.selector(), SchemaIndexDescriptorFactory.forLabel( LABEL_KEY, PROP_KEY ) ); + fusionIndexReader = new FusionIndexReader( fusionVersion.slotSelector(), new Selector<>( readers ), + SchemaIndexDescriptorFactory.forLabel( LABEL_KEY, PROP_KEY ) ); } /* close */ diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexUpdaterTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexUpdaterTest.java index 1b40941050be..0367e33d63bb 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexUpdaterTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexUpdaterTest.java @@ -42,18 +42,18 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.neo4j.helpers.ArrayUtil.without; -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.FusionIndexTestHelp.add; import static org.neo4j.kernel.impl.index.schema.fusion.FusionIndexTestHelp.change; import static org.neo4j.kernel.impl.index.schema.fusion.FusionIndexTestHelp.remove; import static org.neo4j.kernel.impl.index.schema.fusion.FusionVersion.v00; import static org.neo4j.kernel.impl.index.schema.fusion.FusionVersion.v10; import static org.neo4j.kernel.impl.index.schema.fusion.FusionVersion.v20; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.INSTANCE_COUNT; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.LUCENE; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.NUMBER; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.SPATIAL; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.STRING; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.TEMPORAL; @RunWith( Parameterized.class ) public class FusionIndexUpdaterTest @@ -113,7 +113,7 @@ private void initiateMocks() throw new RuntimeException(); } } - fusionIndexUpdater = new FusionIndexUpdater( updaters, fusionVersion.selector() ); + fusionIndexUpdater = new FusionIndexUpdater( fusionVersion.slotSelector(), new Selector( updaters ) ); } private void resetMocks() diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionVersion.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionVersion.java index 6d7d7a5b2477..e15d01021723 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionVersion.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/fusion/FusionVersion.java @@ -19,11 +19,11 @@ */ package org.neo4j.kernel.impl.index.schema.fusion; -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.SlotSelector.LUCENE; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.NUMBER; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.SPATIAL; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.STRING; +import static org.neo4j.kernel.impl.index.schema.fusion.SlotSelector.TEMPORAL; enum FusionVersion { @@ -36,7 +36,7 @@ int[] aliveSlots() } @Override - FusionIndexProvider.Selector selector() + SlotSelector slotSelector() { return new FusionSelector00(); } @@ -50,7 +50,7 @@ int[] aliveSlots() } @Override - FusionIndexProvider.Selector selector() + SlotSelector slotSelector() { return new FusionSelector10(); } @@ -64,7 +64,7 @@ int[] aliveSlots() } @Override - FusionIndexProvider.Selector selector() + SlotSelector slotSelector() { return new FusionSelector20(); } @@ -72,5 +72,5 @@ FusionIndexProvider.Selector selector() abstract int[] aliveSlots(); - abstract FusionIndexProvider.Selector selector(); + abstract SlotSelector slotSelector(); }