From 85cd23243df3b03bd22db5f4f7fb746076f5d605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Finn=C3=A9?= Date: Tue, 30 Jan 2018 17:00:44 +0100 Subject: [PATCH] Implemented StringSchemaIndexProvider Broke out commonlatities from NumberSchemaIndexProvider into NativeSchemaIndexProvider --- .../schema/NativeSchemaIndexProvider.java | 182 ++++++++ .../schema/NumberSchemaIndexProvider.java | 138 +----- .../schema/StringSchemaIndexProvider.java | 120 +++++ ... => ConflictDetectingValueMergerTest.java} | 6 +- .../schema/NativeSchemaIndexAccessorTest.java | 1 - .../schema/NativeSchemaIndexProviderTest.java | 422 ++++++++++++++++++ .../schema/NumberSchemaIndexProviderTest.java | 392 +--------------- .../schema/StringSchemaIndexProviderTest.java | 52 +++ 8 files changed, 805 insertions(+), 508 deletions(-) create mode 100644 community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/NativeSchemaIndexProvider.java create mode 100644 community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/StringSchemaIndexProvider.java rename community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/{NumberConflictDetectingValueMergerTest.java => ConflictDetectingValueMergerTest.java} (95%) create mode 100644 community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/NativeSchemaIndexProviderTest.java create mode 100644 community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/StringSchemaIndexProviderTest.java diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/NativeSchemaIndexProvider.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/NativeSchemaIndexProvider.java new file mode 100644 index 0000000000000..df72ff335428e --- /dev/null +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/NativeSchemaIndexProvider.java @@ -0,0 +1,182 @@ +/* + * 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; + +import org.neo4j.kernel.api.index.IndexDirectoryStructure.Factory; +import org.neo4j.kernel.api.schema.index.IndexDescriptor; +import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingConfig; +import org.neo4j.kernel.impl.storemigration.StoreMigrationParticipant; + +import static org.neo4j.kernel.impl.index.schema.NativeSchemaIndexPopulator.BYTE_FAILED; +import static org.neo4j.kernel.impl.index.schema.NativeSchemaIndexPopulator.BYTE_ONLINE; +import static org.neo4j.kernel.impl.index.schema.NativeSchemaIndexPopulator.BYTE_POPULATING; + +import java.io.File; +import java.io.IOException; + +import org.neo4j.index.internal.gbptree.GBPTree; +import org.neo4j.index.internal.gbptree.Layout; +import org.neo4j.index.internal.gbptree.RecoveryCleanupWorkCollector; +import org.neo4j.internal.kernel.api.InternalIndexState; +import org.neo4j.io.fs.FileSystemAbstraction; +import org.neo4j.io.pagecache.PageCache; +import org.neo4j.kernel.api.index.IndexAccessor; +import org.neo4j.kernel.api.index.IndexPopulator; +import org.neo4j.kernel.api.index.SchemaIndexProvider; + +abstract class NativeSchemaIndexProvider extends SchemaIndexProvider +{ + protected final PageCache pageCache; + protected final FileSystemAbstraction fs; + protected final Monitor monitor; + protected final RecoveryCleanupWorkCollector recoveryCleanupWorkCollector; + protected final boolean readOnly; + + protected NativeSchemaIndexProvider( Descriptor descriptor, int priority, Factory directoryStructureFactory, PageCache pageCache, + FileSystemAbstraction fs, Monitor monitor, RecoveryCleanupWorkCollector recoveryCleanupWorkCollector, boolean readOnly ) + { + super( descriptor, priority, directoryStructureFactory ); + this.pageCache = pageCache; + this.fs = fs; + this.monitor = monitor; + this.recoveryCleanupWorkCollector = recoveryCleanupWorkCollector; + this.readOnly = readOnly; + } + + @Override + public IndexPopulator getPopulator( long indexId, IndexDescriptor descriptor, IndexSamplingConfig samplingConfig ) + { + if ( readOnly ) + { + throw new UnsupportedOperationException( "Can't create populator for read only index" ); + } + + File storeFile = nativeIndexFileFromIndexId( indexId ); + switch ( descriptor.type() ) + { + case GENERAL: + return new NativeNonUniqueSchemaIndexPopulator<>( pageCache, fs, storeFile, layoutNonUnique(), samplingConfig, + monitor, descriptor, indexId ); + case UNIQUE: + return new NativeUniqueSchemaIndexPopulator<>( pageCache, fs, storeFile, layoutUnique(), monitor, descriptor, + indexId ); + default: + throw new UnsupportedOperationException( "Can not create index populator of type " + descriptor.type() ); + } + } + + @Override + public IndexAccessor getOnlineAccessor( + long indexId, IndexDescriptor descriptor, IndexSamplingConfig samplingConfig ) throws IOException + { + File storeFile = nativeIndexFileFromIndexId( indexId ); + Layout layout = layout( descriptor ); + return newIndexAccessor( storeFile, layout, descriptor, indexId, samplingConfig ); + } + + protected abstract IndexAccessor newIndexAccessor( File storeFile, Layout layout, IndexDescriptor descriptor, + long indexId, IndexSamplingConfig samplingConfig ) throws IOException; + + @Override + public String getPopulationFailure( long indexId, IndexDescriptor descriptor ) throws IllegalStateException + { + try + { + String failureMessage = readPopulationFailure( indexId, descriptor ); + if ( failureMessage == null ) + { + throw new IllegalStateException( "Index " + indexId + " isn't failed" ); + } + return failureMessage; + } + catch ( IOException e ) + { + throw new RuntimeException( e ); + } + } + + @Override + public InternalIndexState getInitialState( long indexId, IndexDescriptor descriptor ) + { + try + { + NativeSchemaIndexHeaderReader headerReader = new NativeSchemaIndexHeaderReader(); + GBPTree.readHeader( pageCache, nativeIndexFileFromIndexId( indexId ), layout( descriptor ), headerReader ); + switch ( headerReader.state ) + { + case BYTE_FAILED: + return InternalIndexState.FAILED; + case BYTE_ONLINE: + return InternalIndexState.ONLINE; + case BYTE_POPULATING: + return InternalIndexState.POPULATING; + default: + throw new IllegalStateException( "Unexpected initial state byte value " + headerReader.state ); + } + } + catch ( IOException e ) + { + monitor.failedToOpenIndex( indexId, descriptor, "Requesting re-population.", e ); + return InternalIndexState.POPULATING; + } + } + + @Override + public StoreMigrationParticipant storeMigrationParticipant( FileSystemAbstraction fs, PageCache pageCache ) + { + // Since this native provider is a new one, there's no need for migration on this level. + // Migration should happen in the combined layer for the time being. + return StoreMigrationParticipant.NOT_PARTICIPATING; + } + + private String readPopulationFailure( long indexId, IndexDescriptor descriptor ) throws IOException + { + NativeSchemaIndexHeaderReader headerReader = new NativeSchemaIndexHeaderReader(); + GBPTree.readHeader( pageCache, nativeIndexFileFromIndexId( indexId ), layout( descriptor ), headerReader ); + return headerReader.failureMessage; + } + + private Layout layout( IndexDescriptor descriptor ) + { + switch ( descriptor.type() ) + { + case GENERAL: + return layoutNonUnique(); + case UNIQUE: + return layoutUnique(); + default: + throw new UnsupportedOperationException( "Can not create index accessor of type " + descriptor.type() ); + } + } + + protected abstract Layout layoutUnique(); + + protected abstract Layout layoutNonUnique(); + + private File nativeIndexFileFromIndexId( long indexId ) + { + return new File( directoryStructure().directoryForIndex( indexId ), indexFileName( indexId ) ); + } + + private static String indexFileName( long indexId ) + { + return "index-" + indexId; + } +} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/NumberSchemaIndexProvider.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/NumberSchemaIndexProvider.java index 2e70123bce151..1a15741c8d8f3 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/NumberSchemaIndexProvider.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/NumberSchemaIndexProvider.java @@ -23,151 +23,53 @@ import java.io.IOException; import org.neo4j.index.internal.gbptree.GBPTree; +import org.neo4j.index.internal.gbptree.Layout; import org.neo4j.index.internal.gbptree.RecoveryCleanupWorkCollector; import org.neo4j.internal.kernel.api.IndexCapability; import org.neo4j.internal.kernel.api.IndexOrder; import org.neo4j.internal.kernel.api.IndexValueCapability; -import org.neo4j.internal.kernel.api.InternalIndexState; import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.pagecache.PageCache; import org.neo4j.kernel.api.index.IndexAccessor; import org.neo4j.kernel.api.index.IndexDirectoryStructure; -import org.neo4j.kernel.api.index.IndexPopulator; -import org.neo4j.kernel.api.index.SchemaIndexProvider; import org.neo4j.kernel.api.schema.index.IndexDescriptor; import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingConfig; -import org.neo4j.kernel.impl.storemigration.StoreMigrationParticipant; import org.neo4j.values.storable.ValueGroup; -import static org.neo4j.kernel.impl.index.schema.NativeSchemaIndexPopulator.BYTE_FAILED; -import static org.neo4j.kernel.impl.index.schema.NativeSchemaIndexPopulator.BYTE_ONLINE; -import static org.neo4j.kernel.impl.index.schema.NativeSchemaIndexPopulator.BYTE_POPULATING; - /** * Schema index provider for native indexes backed by e.g. {@link GBPTree}. */ -public class NumberSchemaIndexProvider extends SchemaIndexProvider +public class NumberSchemaIndexProvider extends NativeSchemaIndexProvider { public static final String KEY = "native"; public static final Descriptor NATIVE_PROVIDER_DESCRIPTOR = new Descriptor( KEY, "1.0" ); static final IndexCapability CAPABILITY = new NativeIndexCapability(); - private final PageCache pageCache; - private final FileSystemAbstraction fs; - private final Monitor monitor; - private final RecoveryCleanupWorkCollector recoveryCleanupWorkCollector; - private final boolean readOnly; - public NumberSchemaIndexProvider( PageCache pageCache, FileSystemAbstraction fs, IndexDirectoryStructure.Factory directoryStructure, Monitor monitor, RecoveryCleanupWorkCollector recoveryCleanupWorkCollector, boolean readOnly ) { - super( NATIVE_PROVIDER_DESCRIPTOR, 0, directoryStructure ); - this.pageCache = pageCache; - this.fs = fs; - this.monitor = monitor; - this.recoveryCleanupWorkCollector = recoveryCleanupWorkCollector; - this.readOnly = readOnly; + super( NATIVE_PROVIDER_DESCRIPTOR, 0, directoryStructure, pageCache, fs, monitor, recoveryCleanupWorkCollector, readOnly ); } @Override - public IndexPopulator getPopulator( long indexId, IndexDescriptor descriptor, IndexSamplingConfig samplingConfig ) + protected NumberLayoutUnique layoutUnique() { - if ( readOnly ) - { - throw new UnsupportedOperationException( "Can't create populator for read only index" ); - } - - File storeFile = nativeIndexFileFromIndexId( indexId ); - switch ( descriptor.type() ) - { - case GENERAL: - return new NativeNonUniqueSchemaIndexPopulator<>( pageCache, fs, storeFile, new NumberLayoutNonUnique(), samplingConfig, - monitor, descriptor, indexId ); - case UNIQUE: - return new NativeUniqueSchemaIndexPopulator<>( pageCache, fs, storeFile, new NumberLayoutUnique(), monitor, descriptor, - indexId ); - default: - throw new UnsupportedOperationException( "Can not create index populator of type " + descriptor.type() ); - } + return new NumberLayoutUnique(); } @Override - public IndexAccessor getOnlineAccessor( - long indexId, IndexDescriptor descriptor, IndexSamplingConfig samplingConfig ) throws IOException + protected NumberLayoutNonUnique layoutNonUnique() { - File storeFile = nativeIndexFileFromIndexId( indexId ); - NumberLayout layout = layout( descriptor ); - return new NumberSchemaIndexAccessor<>( pageCache, fs, storeFile, layout, recoveryCleanupWorkCollector, monitor, - descriptor, indexId, samplingConfig ); - } - - private NumberLayout layout( IndexDescriptor descriptor ) - { - NumberLayout layout; - switch ( descriptor.type() ) - { - case GENERAL: - layout = new NumberLayoutNonUnique(); - break; - case UNIQUE: - layout = new NumberLayoutUnique(); - break; - default: - throw new UnsupportedOperationException( "Can not create index accessor of type " + descriptor.type() ); - } - return layout; + return new NumberLayoutNonUnique(); } @Override - public String getPopulationFailure( long indexId, IndexDescriptor descriptor ) throws IllegalStateException - { - try - { - String failureMessage = readPopulationFailure( indexId, descriptor ); - if ( failureMessage == null ) - { - throw new IllegalStateException( "Index " + indexId + " isn't failed" ); - } - return failureMessage; - } - catch ( IOException e ) - { - throw new RuntimeException( e ); - } - } - - private String readPopulationFailure( long indexId, IndexDescriptor descriptor ) throws IOException + protected IndexAccessor newIndexAccessor( File storeFile, Layout layout, IndexDescriptor descriptor, + long indexId, IndexSamplingConfig samplingConfig ) throws IOException { - NativeSchemaIndexHeaderReader headerReader = new NativeSchemaIndexHeaderReader(); - GBPTree.readHeader( pageCache, nativeIndexFileFromIndexId( indexId ), layout( descriptor ), headerReader ); - return headerReader.failureMessage; - } - - @Override - public InternalIndexState getInitialState( long indexId, IndexDescriptor descriptor ) - { - try - { - NativeSchemaIndexHeaderReader headerReader = new NativeSchemaIndexHeaderReader(); - GBPTree.readHeader( pageCache, nativeIndexFileFromIndexId( indexId ), layout( descriptor ), headerReader ); - switch ( headerReader.state ) - { - case BYTE_FAILED: - return InternalIndexState.FAILED; - case BYTE_ONLINE: - return InternalIndexState.ONLINE; - case BYTE_POPULATING: - return InternalIndexState.POPULATING; - default: - throw new IllegalStateException( "Unexpected initial state byte value " + headerReader.state ); - } - } - catch ( IOException e ) - { - monitor.failedToOpenIndex( indexId, descriptor, "Requesting re-population.", e ); - return InternalIndexState.POPULATING; - } + return new NumberSchemaIndexAccessor<>( pageCache, fs, storeFile, layout, recoveryCleanupWorkCollector, monitor, descriptor, + indexId, samplingConfig ); } @Override @@ -176,24 +78,6 @@ public IndexCapability getCapability( IndexDescriptor indexDescriptor ) return CAPABILITY; } - @Override - public StoreMigrationParticipant storeMigrationParticipant( FileSystemAbstraction fs, PageCache pageCache ) - { - // Since this native provider is a new one, there's no need for migration on this level. - // Migration should happen in the combined layer for the time being. - return StoreMigrationParticipant.NOT_PARTICIPATING; - } - - private File nativeIndexFileFromIndexId( long indexId ) - { - return new File( directoryStructure().directoryForIndex( indexId ), indexFileName( indexId ) ); - } - - private static String indexFileName( long indexId ) - { - return "index-" + indexId; - } - private static class NativeIndexCapability implements IndexCapability { private static final IndexOrder[] SUPPORTED_ORDER = {IndexOrder.ASCENDING}; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/StringSchemaIndexProvider.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/StringSchemaIndexProvider.java new file mode 100644 index 0000000000000..8e3285dce8004 --- /dev/null +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/StringSchemaIndexProvider.java @@ -0,0 +1,120 @@ +/* + * 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; + +import java.io.File; +import java.io.IOException; + +import org.neo4j.index.internal.gbptree.GBPTree; +import org.neo4j.index.internal.gbptree.Layout; +import org.neo4j.index.internal.gbptree.RecoveryCleanupWorkCollector; +import org.neo4j.internal.kernel.api.IndexCapability; +import org.neo4j.internal.kernel.api.IndexOrder; +import org.neo4j.internal.kernel.api.IndexValueCapability; +import org.neo4j.io.fs.FileSystemAbstraction; +import org.neo4j.io.pagecache.PageCache; +import org.neo4j.kernel.api.index.IndexAccessor; +import org.neo4j.kernel.api.index.IndexDirectoryStructure; +import org.neo4j.kernel.api.schema.index.IndexDescriptor; +import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingConfig; +import org.neo4j.values.storable.ValueGroup; + +/** + * Schema index provider for native indexes backed by e.g. {@link GBPTree}. + */ +public class StringSchemaIndexProvider extends NativeSchemaIndexProvider +{ + public static final String KEY = "string"; + public static final Descriptor STRING_PROVIDER_DESCRIPTOR = new Descriptor( KEY, "1.0" ); + static final IndexCapability CAPABILITY = new StringIndexCapability(); + + public StringSchemaIndexProvider( PageCache pageCache, FileSystemAbstraction fs, + IndexDirectoryStructure.Factory directoryStructure, Monitor monitor, RecoveryCleanupWorkCollector recoveryCleanupWorkCollector, + boolean readOnly ) + { + super( STRING_PROVIDER_DESCRIPTOR, 0, directoryStructure, pageCache, fs, monitor, recoveryCleanupWorkCollector, readOnly ); + } + + @Override + protected StringLayoutUnique layoutUnique() + { + return new StringLayoutUnique(); + } + + @Override + protected StringLayoutNonUnique layoutNonUnique() + { + return new StringLayoutNonUnique(); + } + + @Override + protected IndexAccessor newIndexAccessor( File storeFile, Layout layout, IndexDescriptor descriptor, + long indexId, IndexSamplingConfig samplingConfig ) throws IOException + { + return new StringSchemaIndexAccessor<>( pageCache, fs, storeFile, layout, recoveryCleanupWorkCollector, monitor, descriptor, + indexId, samplingConfig ); + } + + @Override + public IndexCapability getCapability( IndexDescriptor indexDescriptor ) + { + return CAPABILITY; + } + + private static class StringIndexCapability implements IndexCapability + { + private static final IndexOrder[] SUPPORTED_ORDER = {IndexOrder.ASCENDING}; + private static final IndexOrder[] EMPTY_ORDER = new IndexOrder[0]; + + @Override + public IndexOrder[] orderCapability( ValueGroup... valueGroups ) + { + if ( support( valueGroups ) ) + { + return SUPPORTED_ORDER; + } + return EMPTY_ORDER; + } + + @Override + public IndexValueCapability valueCapability( ValueGroup... valueGroups ) + { + if ( support( valueGroups ) ) + { + return IndexValueCapability.YES; + } + if ( singleWildcard( valueGroups ) ) + { + return IndexValueCapability.PARTIAL; + } + return IndexValueCapability.NO; + } + + private boolean singleWildcard( ValueGroup[] valueGroups ) + { + return valueGroups.length == 1 && valueGroups[0] == ValueGroup.UNKNOWN; + } + + private boolean support( ValueGroup[] valueGroups ) + { + return valueGroups.length == 1 && valueGroups[0] == ValueGroup.TEXT; + } + } +} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/NumberConflictDetectingValueMergerTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/ConflictDetectingValueMergerTest.java similarity index 95% rename from community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/NumberConflictDetectingValueMergerTest.java rename to community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/ConflictDetectingValueMergerTest.java index 86be5e6330929..fc9680c489938 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/NumberConflictDetectingValueMergerTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/ConflictDetectingValueMergerTest.java @@ -29,7 +29,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -public class NumberConflictDetectingValueMergerTest +public class ConflictDetectingValueMergerTest { private final ConflictDetectingValueMerger detector = new ConflictDetectingValueMerger<>(); @@ -37,7 +37,7 @@ public class NumberConflictDetectingValueMergerTest public void shouldReportConflictOnSameValueAndDifferentEntityIds() { // given - Value value = Values.of( 123); + Value value = Values.of( 123 ); long entityId1 = 10; long entityId2 = 20; @@ -59,7 +59,7 @@ public void shouldReportConflictOnSameValueAndDifferentEntityIds() public void shouldNotReportConflictOnSameValueSameEntityId() { // given - Value value = Values.of( 123); + Value value = Values.of( 123 ); long entityId = 10; // when diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/NativeSchemaIndexAccessorTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/NativeSchemaIndexAccessorTest.java index b0581cbaac53e..c0156dab3507b 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/NativeSchemaIndexAccessorTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/NativeSchemaIndexAccessorTest.java @@ -192,7 +192,6 @@ public void shouldIndexRemove() throws Exception } } - @SuppressWarnings( "unchecked" ) @Test public void shouldHandleRandomUpdates() throws Exception { diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/NativeSchemaIndexProviderTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/NativeSchemaIndexProviderTest.java new file mode 100644 index 0000000000000..8203531c62868 --- /dev/null +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/NativeSchemaIndexProviderTest.java @@ -0,0 +1,422 @@ +/* + * 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; + +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; + +import org.neo4j.index.internal.gbptree.RecoveryCleanupWorkCollector; +import org.neo4j.internal.kernel.api.InternalIndexState; +import org.neo4j.io.fs.FileSystemAbstraction; +import org.neo4j.io.pagecache.PageCache; +import org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException; +import org.neo4j.kernel.api.index.IndexAccessor; +import org.neo4j.kernel.api.index.IndexDirectoryStructure; +import org.neo4j.kernel.api.index.IndexEntryUpdate; +import org.neo4j.kernel.api.index.IndexPopulator; +import org.neo4j.kernel.api.index.IndexUpdater; +import org.neo4j.kernel.api.index.LoggingMonitor; +import org.neo4j.kernel.api.index.SchemaIndexProvider; +import org.neo4j.kernel.api.schema.index.IndexDescriptor; +import org.neo4j.kernel.api.schema.index.IndexDescriptorFactory; +import org.neo4j.kernel.configuration.Config; +import org.neo4j.kernel.impl.api.index.IndexUpdateMode; +import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingConfig; +import org.neo4j.logging.AssertableLogProvider; +import org.neo4j.test.rule.PageCacheAndDependenciesRule; +import org.neo4j.values.storable.Value; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.neo4j.index.internal.gbptree.RecoveryCleanupWorkCollector.IMMEDIATE; +import static org.neo4j.kernel.api.index.IndexDirectoryStructure.directoriesByProvider; + +public abstract class NativeSchemaIndexProviderTest +{ + @Rule + public PageCacheAndDependenciesRule rules = new PageCacheAndDependenciesRule(); + + private static final int indexId = 1; + private static final int labelId = 1; + private static final int propId = 1; + private SchemaIndexProvider provider; + private final AssertableLogProvider logging = new AssertableLogProvider(); + private final SchemaIndexProvider.Monitor monitor = new LoggingMonitor( logging.getLog( "test" ) ); + + @Before + public void setup() throws IOException + { + File nativeSchemaIndexStoreDirectory = newProvider().directoryStructure().rootDirectory(); + rules.fileSystem().mkdirs( nativeSchemaIndexStoreDirectory ); + } + + /* getPopulator */ + + @Test + public void getPopulatorMustThrowIfInReadOnlyMode() + { + // given + provider = newReadOnlyProvider(); + + try + { + // when + provider.getPopulator( indexId, descriptor(), samplingConfig() ); + fail( "Should have failed" ); + } + catch ( UnsupportedOperationException e ) + { + // then + // good + } + } + + @Test + public void getPopulatorMustCreateUniquePopulatorForTypeUnique() + { + // given + provider = newProvider(); + + // when + IndexPopulator populator = provider.getPopulator( indexId, descriptorUnique(), samplingConfig() ); + + // then + assertTrue( "Expected populator to be unique populator", populator instanceof NativeUniqueSchemaIndexPopulator ); + } + + @Test + public void getPopulatorMustCreateNonUniquePopulatorForTypeGeneral() + { + // given + provider = newProvider(); + + // when + IndexPopulator populator = provider.getPopulator( indexId, descriptor(), samplingConfig() ); + + // then + assertTrue( "Expected populator to be non-unique populator", populator instanceof NativeNonUniqueSchemaIndexPopulator ); + } + + /* getOnlineAccessor */ + + @Test + public void getOnlineAccessorMustCreateUniqueAccessorForTypeUnique() throws IOException, IndexEntryConflictException + { + // given + provider = newProvider(); + + // when + IndexDescriptor descriptor = descriptorUnique(); + try ( IndexAccessor accessor = provider.getOnlineAccessor( indexId, descriptor, samplingConfig() ); + IndexUpdater indexUpdater = accessor.newUpdater( IndexUpdateMode.ONLINE ) ) + { + Value value = someValue(); + indexUpdater.process( IndexEntryUpdate.add( 1, descriptor.schema(), value ) ); + + // then + try + { + indexUpdater.process( IndexEntryUpdate.add( 2, descriptor.schema(), value ) ); + fail( "Should have failed" ); + } + catch ( IndexEntryConflictException e ) + { + // good + } + } + } + + protected abstract Value someValue(); + + @Test + public void getOnlineAccessorMustCreateNonUniqueAccessorForTypeGeneral() throws IOException, IndexEntryConflictException + { + // given + provider = newProvider(); + + // when + IndexDescriptor descriptor = descriptor(); + try ( IndexAccessor accessor = provider.getOnlineAccessor( indexId, descriptor, samplingConfig() ); + IndexUpdater indexUpdater = accessor.newUpdater( IndexUpdateMode.ONLINE ) ) + { + Value value = someValue(); + indexUpdater.process( IndexEntryUpdate.add( 1, descriptor.schema(), value ) ); + + // then + // ... expect no failure on duplicate value + indexUpdater.process( IndexEntryUpdate.add( 2, descriptor.schema(), value ) ); + } + } + + /* getPopulationFailure */ + + @Test + public void getPopulationFailureMustThrowIfNoFailure() throws IOException + { + // given + provider = newProvider(); + IndexPopulator populator = provider.getPopulator( indexId, descriptor(), samplingConfig() ); + populator.create(); + populator.close( true ); + + // when + // ... no failure on populator + + // then + try + { + provider.getPopulationFailure( indexId, descriptor() ); + fail( "Should have failed" ); + } + catch ( IllegalStateException e ) + { + // good + assertThat( e.getMessage(), Matchers.containsString( Long.toString( indexId ) ) ); + } + } + + @Test + public void getPopulationFailureMustThrowEvenIfFailureOnOtherIndex() throws IOException + { + // given + provider = newProvider(); + + int nonFailedIndexId = NativeSchemaIndexProviderTest.indexId; + IndexPopulator nonFailedPopulator = provider.getPopulator( nonFailedIndexId, descriptor(), samplingConfig() ); + nonFailedPopulator.create(); + nonFailedPopulator.close( true ); + + int failedIndexId = 2; + IndexPopulator failedPopulator = provider.getPopulator( failedIndexId, descriptor(), samplingConfig() ); + failedPopulator.create(); + + // when + failedPopulator.markAsFailed( "failure" ); + failedPopulator.close( false ); + + // then + try + { + provider.getPopulationFailure( nonFailedIndexId, descriptor() ); + fail( "Should have failed" ); + } + catch ( IllegalStateException e ) + { + // good + assertThat( e.getMessage(), Matchers.containsString( Long.toString( nonFailedIndexId ) ) ); + } + } + + @Test + public void getPopulationFailureMustReturnReportedFailure() throws IOException + { + // given + provider = newProvider(); + IndexPopulator populator = provider.getPopulator( indexId, descriptor(), samplingConfig() ); + populator.create(); + + // when + String failureMessage = "fail"; + populator.markAsFailed( failureMessage ); + populator.close( false ); + + // then + String populationFailure = provider.getPopulationFailure( indexId, descriptor() ); + assertThat( populationFailure, is( failureMessage ) ); + } + + @Test + public void getPopulationFailureMustReturnReportedFailuresForDifferentIndexIds() throws IOException + { + // given + provider = newProvider(); + int first = 1; + int second = 2; + int third = 3; + IndexPopulator firstPopulator = provider.getPopulator( first, descriptor(), samplingConfig() ); + firstPopulator.create(); + IndexPopulator secondPopulator = provider.getPopulator( second, descriptor(), samplingConfig() ); + secondPopulator.create(); + IndexPopulator thirdPopulator = provider.getPopulator( third, descriptor(), samplingConfig() ); + thirdPopulator.create(); + + // when + String firstFailure = "first failure"; + firstPopulator.markAsFailed( firstFailure ); + firstPopulator.close( false ); + secondPopulator.close( true ); + String thirdFailure = "third failure"; + thirdPopulator.markAsFailed( thirdFailure ); + thirdPopulator.close( false ); + + // then + assertThat( provider.getPopulationFailure( first, descriptor() ), is( firstFailure ) ); + assertThat( provider.getPopulationFailure( third, descriptor() ), is( thirdFailure ) ); + try + { + provider.getPopulationFailure( second, descriptor() ); + fail( "Should have failed" ); + } + catch ( IllegalStateException e ) + { + // good + } + } + + @Test + public void getPopulationFailureMustPersistReportedFailure() throws IOException + { + // given + provider = newProvider(); + IndexPopulator populator = provider.getPopulator( indexId, descriptor(), samplingConfig() ); + populator.create(); + + // when + String failureMessage = "fail"; + populator.markAsFailed( failureMessage ); + populator.close( false ); + + // then + provider = newProvider(); + String populationFailure = provider.getPopulationFailure( indexId, descriptor() ); + assertThat( populationFailure, is( failureMessage ) ); + } + + /* getInitialState */ + // pattern: open populator, markAsFailed, close populator, getInitialState, getPopulationFailure + + @Test + public void shouldReportInitialStateAsPopulatingIfIndexDoesntExist() + { + // given + provider = newProvider(); + + // when + InternalIndexState state = provider.getInitialState( indexId, descriptor() ); + + // then + assertEquals( InternalIndexState.POPULATING, state ); + logging.assertContainsLogCallContaining( "Failed to open index" ); + } + + @Test + public void shouldReportInitialStateAsPopulatingIfPopulationStartedButIncomplete() throws IOException + { + // given + provider = newProvider(); + IndexPopulator populator = provider.getPopulator( indexId, descriptor(), samplingConfig() ); + populator.create(); + + // when + InternalIndexState state = provider.getInitialState( indexId, descriptor() ); + + // then + assertEquals( InternalIndexState.POPULATING, state ); + populator.close( true ); + } + + @Test + public void shouldReportInitialStateAsFailedIfMarkedAsFailed() throws IOException + { + // given + provider = newProvider(); + IndexPopulator populator = provider.getPopulator( indexId, descriptor(), samplingConfig() ); + populator.create(); + populator.markAsFailed( "Just some failure" ); + populator.close( false ); + + // when + InternalIndexState state = provider.getInitialState( indexId, descriptor() ); + + // then + assertEquals( InternalIndexState.FAILED, state ); + } + + @Test + public void shouldReportInitialStateAsOnlineIfPopulationCompletedSuccessfully() throws IOException + { + // given + provider = newProvider(); + IndexPopulator populator = provider.getPopulator( indexId, descriptor(), samplingConfig() ); + populator.create(); + populator.close( true ); + + // when + InternalIndexState state = provider.getInitialState( indexId, descriptor() ); + + // then + assertEquals( InternalIndexState.ONLINE, state ); + } + + /* storeMigrationParticipant */ + + abstract SchemaIndexProvider newProvider( PageCache pageCache, FileSystemAbstraction fs, IndexDirectoryStructure.Factory dir, + SchemaIndexProvider.Monitor monitor, RecoveryCleanupWorkCollector collector ); + + abstract SchemaIndexProvider newReadOnlyProvider( PageCache pageCache, FileSystemAbstraction fs, IndexDirectoryStructure.Factory dir, + SchemaIndexProvider.Monitor monitor, RecoveryCleanupWorkCollector collector ); + + private SchemaIndexProvider newProvider() + { + return newProvider( pageCache(), fs(), directoriesByProvider( baseDir() ), monitor, IMMEDIATE ); + } + + private SchemaIndexProvider newReadOnlyProvider() + { + return newReadOnlyProvider( pageCache(), fs(), directoriesByProvider( baseDir() ), monitor, IMMEDIATE ); + } + + private IndexSamplingConfig samplingConfig() + { + return new IndexSamplingConfig( Config.defaults() ); + } + + private IndexDescriptor descriptor() + { + return IndexDescriptorFactory.forLabel( labelId, propId ); + } + + private IndexDescriptor descriptorUnique() + { + return IndexDescriptorFactory.uniqueForLabel( labelId, propId ); + } + + private PageCache pageCache() + { + return rules.pageCache(); + } + + private FileSystemAbstraction fs() + { + return rules.fileSystem(); + } + + private File baseDir() + { + return rules.directory().absolutePath(); + } +} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/NumberSchemaIndexProviderTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/NumberSchemaIndexProviderTest.java index bd626cfede168..2434694665d8f 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/NumberSchemaIndexProviderTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/NumberSchemaIndexProviderTest.java @@ -19,396 +19,34 @@ */ package org.neo4j.kernel.impl.index.schema; -import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.File; -import java.io.IOException; - -import org.neo4j.internal.kernel.api.InternalIndexState; +import org.neo4j.index.internal.gbptree.RecoveryCleanupWorkCollector; import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.pagecache.PageCache; -import org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException; -import org.neo4j.kernel.api.index.IndexAccessor; -import org.neo4j.kernel.api.index.IndexEntryUpdate; -import org.neo4j.kernel.api.index.IndexPopulator; -import org.neo4j.kernel.api.index.IndexUpdater; -import org.neo4j.kernel.api.index.LoggingMonitor; +import org.neo4j.kernel.api.index.IndexDirectoryStructure; import org.neo4j.kernel.api.index.SchemaIndexProvider; -import org.neo4j.kernel.api.schema.index.IndexDescriptor; -import org.neo4j.kernel.api.schema.index.IndexDescriptorFactory; -import org.neo4j.kernel.configuration.Config; -import org.neo4j.kernel.impl.api.index.IndexUpdateMode; -import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingConfig; -import org.neo4j.logging.AssertableLogProvider; -import org.neo4j.test.rule.PageCacheAndDependenciesRule; +import org.neo4j.kernel.api.index.SchemaIndexProvider.Monitor; import org.neo4j.values.storable.Value; import org.neo4j.values.storable.Values; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.neo4j.index.internal.gbptree.RecoveryCleanupWorkCollector.IMMEDIATE; -import static org.neo4j.kernel.api.index.IndexDirectoryStructure.directoriesByProvider; - -public class NumberSchemaIndexProviderTest +public class NumberSchemaIndexProviderTest extends NativeSchemaIndexProviderTest { - @Rule - public PageCacheAndDependenciesRule rules = new PageCacheAndDependenciesRule(); - - private static final int indexId = 1; - private static final int labelId = 1; - private static final int propId = 1; - private NumberSchemaIndexProvider provider; - private final AssertableLogProvider logging = new AssertableLogProvider(); - private final SchemaIndexProvider.Monitor monitor = new LoggingMonitor( logging.getLog( "test" ) ); - - @Before - public void setup() throws IOException - { - File nativeSchemaIndexStoreDirectory = newProvider().directoryStructure().rootDirectory(); - rules.fileSystem().mkdirs( nativeSchemaIndexStoreDirectory ); - } - - /* getPopulator */ - - @Test - public void getPopulatorMustThrowIfInReadOnlyMode() - { - // given - provider = newReadOnlyProvider(); - - try - { - // when - provider.getPopulator( indexId, descriptor(), samplingConfig() ); - fail( "Should have failed" ); - } - catch ( UnsupportedOperationException e ) - { - // then - // good - } - } - - @Test - public void getPopulatorMustCreateUniquePopulatorForTypeUnique() - { - // given - provider = newProvider(); - - // when - IndexPopulator populator = provider.getPopulator( indexId, descriptorUnique(), samplingConfig() ); - - // then - assertTrue( "Expected populator to be unique populator", populator instanceof NativeUniqueSchemaIndexPopulator ); - } - - @Test - public void getPopulatorMustCreateNonUniquePopulatorForTypeGeneral() - { - // given - provider = newProvider(); - - // when - IndexPopulator populator = provider.getPopulator( indexId, descriptor(), samplingConfig() ); - - // then - assertTrue( "Expected populator to be non-unique populator", populator instanceof NativeNonUniqueSchemaIndexPopulator ); - } - - /* getOnlineAccessor */ - - @Test - public void getOnlineAccessorMustCreateUniqueAccessorForTypeUnique() throws Exception - { - // given - provider = newProvider(); - - // when - IndexDescriptor descriptor = descriptorUnique(); - try ( IndexAccessor accessor = provider.getOnlineAccessor( indexId, descriptor, samplingConfig() ); - IndexUpdater indexUpdater = accessor.newUpdater( IndexUpdateMode.ONLINE ) ) - { - Value value = Values.intValue( 1 ); - indexUpdater.process( IndexEntryUpdate.add( 1, descriptor.schema(), value ) ); - - // then - try - { - indexUpdater.process( IndexEntryUpdate.add( 2, descriptor.schema(), value ) ); - fail( "Should have failed" ); - } - catch ( IndexEntryConflictException e ) - { - // good - } - } - } - - @Test - public void getOnlineAccessorMustCreateNonUniqueAccessorForTypeGeneral() throws Exception - { - // given - provider = newProvider(); - - // when - IndexDescriptor descriptor = descriptor(); - try ( IndexAccessor accessor = provider.getOnlineAccessor( indexId, descriptor, samplingConfig() ); - IndexUpdater indexUpdater = accessor.newUpdater( IndexUpdateMode.ONLINE ) ) - { - Value value = Values.intValue( 1 ); - indexUpdater.process( IndexEntryUpdate.add( 1, descriptor.schema(), value ) ); - - // then - // ... expect no failure on duplicate value - indexUpdater.process( IndexEntryUpdate.add( 2, descriptor.schema(), value ) ); - } - } - - /* getPopulationFailure */ - - @Test - public void getPopulationFailureMustThrowIfNoFailure() throws Exception - { - // given - provider = newProvider(); - IndexPopulator populator = provider.getPopulator( indexId, descriptor(), samplingConfig() ); - populator.create(); - populator.close( true ); - - // when - // ... no failure on populator - - // then - try - { - provider.getPopulationFailure( indexId, descriptor() ); - fail( "Should have failed" ); - } - catch ( IllegalStateException e ) - { - // good - assertThat( e.getMessage(), Matchers.containsString( Long.toString( indexId ) ) ); - } - } - - @Test - public void getPopulationFailureMustThrowEvenIfFailureOnOtherIndex() throws Exception - { - // given - provider = newProvider(); - - int nonFailedIndexId = NumberSchemaIndexProviderTest.indexId; - IndexPopulator nonFailedPopulator = provider.getPopulator( nonFailedIndexId, descriptor(), samplingConfig() ); - nonFailedPopulator.create(); - nonFailedPopulator.close( true ); - - int failedIndexId = 2; - IndexPopulator failedPopulator = provider.getPopulator( failedIndexId, descriptor(), samplingConfig() ); - failedPopulator.create(); - - // when - failedPopulator.markAsFailed( "failure" ); - failedPopulator.close( false ); - - // then - try - { - provider.getPopulationFailure( nonFailedIndexId, descriptor() ); - fail( "Should have failed" ); - } - catch ( IllegalStateException e ) - { - // good - assertThat( e.getMessage(), Matchers.containsString( Long.toString( nonFailedIndexId ) ) ); - } - } - - @Test - public void getPopulationFailureMustReturnReportedFailure() throws Exception - { - // given - provider = newProvider(); - IndexPopulator populator = provider.getPopulator( indexId, descriptor(), samplingConfig() ); - populator.create(); - - // when - String failureMessage = "fail"; - populator.markAsFailed( failureMessage ); - populator.close( false ); - - // then - String populationFailure = provider.getPopulationFailure( indexId, descriptor() ); - assertThat( populationFailure, is( failureMessage ) ); - } - - @Test - public void getPopulationFailureMustReturnReportedFailuresForDifferentIndexIds() throws Exception - { - // given - provider = newProvider(); - int first = 1; - int second = 2; - int third = 3; - IndexPopulator firstPopulator = provider.getPopulator( first, descriptor(), samplingConfig() ); - firstPopulator.create(); - IndexPopulator secondPopulator = provider.getPopulator( second, descriptor(), samplingConfig() ); - secondPopulator.create(); - IndexPopulator thirdPopulator = provider.getPopulator( third, descriptor(), samplingConfig() ); - thirdPopulator.create(); - - // when - String firstFailure = "first failure"; - firstPopulator.markAsFailed( firstFailure ); - firstPopulator.close( false ); - secondPopulator.close( true ); - String thirdFailure = "third failure"; - thirdPopulator.markAsFailed( thirdFailure ); - thirdPopulator.close( false ); - - // then - assertThat( provider.getPopulationFailure( first, descriptor() ), is( firstFailure ) ); - assertThat( provider.getPopulationFailure( third, descriptor() ), is( thirdFailure ) ); - try - { - provider.getPopulationFailure( second, descriptor() ); - fail( "Should have failed" ); - } - catch ( IllegalStateException e ) - { - // good - } - } - - @Test - public void getPopulationFailureMustPersistReportedFailure() throws Exception - { - // given - provider = newProvider(); - IndexPopulator populator = provider.getPopulator( indexId, descriptor(), samplingConfig() ); - populator.create(); - - // when - String failureMessage = "fail"; - populator.markAsFailed( failureMessage ); - populator.close( false ); - - // then - provider = newProvider(); - String populationFailure = provider.getPopulationFailure( indexId, descriptor() ); - assertThat( populationFailure, is( failureMessage ) ); - } - - /* getInitialState */ - // pattern: open populator, markAsFailed, close populator, getInitialState, getPopulationFailure - - @Test - public void shouldReportInitialStateAsPopulatingIfIndexDoesntExist() - { - // given - provider = newProvider(); - - // when - InternalIndexState state = provider.getInitialState( indexId, descriptor() ); - - // then - assertEquals( InternalIndexState.POPULATING, state ); - logging.assertContainsLogCallContaining( "Failed to open index" ); - } - - @Test - public void shouldReportInitialStateAsPopulatingIfPopulationStartedButIncomplete() throws Exception - { - // given - provider = newProvider(); - IndexPopulator populator = provider.getPopulator( indexId, descriptor(), samplingConfig() ); - populator.create(); - - // when - InternalIndexState state = provider.getInitialState( indexId, descriptor() ); - - // then - assertEquals( InternalIndexState.POPULATING, state ); - populator.close( true ); - } - - @Test - public void shouldReportInitialStateAsFailedIfMarkedAsFailed() throws Exception - { - // given - provider = newProvider(); - IndexPopulator populator = provider.getPopulator( indexId, descriptor(), samplingConfig() ); - populator.create(); - populator.markAsFailed( "Just some failure" ); - populator.close( false ); - - // when - InternalIndexState state = provider.getInitialState( indexId, descriptor() ); - - // then - assertEquals( InternalIndexState.FAILED, state ); - } - - @Test - public void shouldReportInitialStateAsOnlineIfPopulationCompletedSuccessfully() throws Exception - { - // given - provider = newProvider(); - IndexPopulator populator = provider.getPopulator( indexId, descriptor(), samplingConfig() ); - populator.create(); - populator.close( true ); - - // when - InternalIndexState state = provider.getInitialState( indexId, descriptor() ); - - // then - assertEquals( InternalIndexState.ONLINE, state ); - } - - /* storeMigrationParticipant */ - - private IndexSamplingConfig samplingConfig() - { - return new IndexSamplingConfig( Config.defaults() ); - } - - private IndexDescriptor descriptor() - { - return IndexDescriptorFactory.forLabel( labelId, propId ); - } - - private IndexDescriptor descriptorUnique() - { - return IndexDescriptorFactory.uniqueForLabel( labelId, propId ); - } - - private NumberSchemaIndexProvider newProvider() - { - return new NumberSchemaIndexProvider( pageCache(), fs(), directoriesByProvider( baseDir() ), monitor, IMMEDIATE, false ); - } - - private NumberSchemaIndexProvider newReadOnlyProvider() - { - return new NumberSchemaIndexProvider( pageCache(), fs(), directoriesByProvider( baseDir() ), monitor, IMMEDIATE, true ); - } - - private PageCache pageCache() + @Override + SchemaIndexProvider newProvider( PageCache pageCache, FileSystemAbstraction fs, IndexDirectoryStructure.Factory dir, + Monitor monitor, RecoveryCleanupWorkCollector collector ) { - return rules.pageCache(); + return new NumberSchemaIndexProvider( pageCache, fs, dir, monitor, collector, false ); } - private FileSystemAbstraction fs() + @Override + SchemaIndexProvider newReadOnlyProvider( PageCache pageCache, FileSystemAbstraction fs, IndexDirectoryStructure.Factory dir, + Monitor monitor, RecoveryCleanupWorkCollector collector ) { - return rules.fileSystem(); + return new NumberSchemaIndexProvider( pageCache, fs, dir, monitor, collector, true ); } - private File baseDir() + @Override + protected Value someValue() { - return rules.directory().absolutePath(); + return Values.intValue( 1 ); } } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/StringSchemaIndexProviderTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/StringSchemaIndexProviderTest.java new file mode 100644 index 0000000000000..03c689174c7f9 --- /dev/null +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/index/schema/StringSchemaIndexProviderTest.java @@ -0,0 +1,52 @@ +/* + * 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; + +import org.neo4j.index.internal.gbptree.RecoveryCleanupWorkCollector; +import org.neo4j.io.fs.FileSystemAbstraction; +import org.neo4j.io.pagecache.PageCache; +import org.neo4j.kernel.api.index.IndexDirectoryStructure; +import org.neo4j.kernel.api.index.SchemaIndexProvider; +import org.neo4j.kernel.api.index.SchemaIndexProvider.Monitor; +import org.neo4j.values.storable.Value; +import org.neo4j.values.storable.Values; + +public class StringSchemaIndexProviderTest extends NativeSchemaIndexProviderTest +{ + @Override + SchemaIndexProvider newProvider( PageCache pageCache, FileSystemAbstraction fs, IndexDirectoryStructure.Factory dir, + Monitor monitor, RecoveryCleanupWorkCollector collector ) + { + return new StringSchemaIndexProvider( pageCache, fs, dir, monitor, collector, false ); + } + + @Override + SchemaIndexProvider newReadOnlyProvider( PageCache pageCache, FileSystemAbstraction fs, IndexDirectoryStructure.Factory dir, + Monitor monitor, RecoveryCleanupWorkCollector collector ) + { + return new StringSchemaIndexProvider( pageCache, fs, dir, monitor, collector, true ); + } + + @Override + protected Value someValue() + { + return Values.stringValue( "abc" ); + } +}