Skip to content

Commit

Permalink
Support for Spatial and Temporal in IndexProvider Lucene-1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
burqen committed Mar 22, 2018
1 parent 3a9bbc9 commit c96c29f
Show file tree
Hide file tree
Showing 14 changed files with 192 additions and 87 deletions.
Expand Up @@ -333,7 +333,6 @@ public void shouldPerformNumericRangeSearch() throws Exception
read.nodeIndexSeek( index, node, IndexOrder.NONE, IndexQuery.range( prop, 5, true, 12, false ) );

// then

assertFoundNodesAndValue( node, uniqueIds, numberCapability, num5, num6 );

// when
Expand Down
Expand Up @@ -47,7 +47,7 @@ abstract class NativeSchemaIndexReader<KEY extends NativeSchemaKey, VALUE extend
final Layout<KEY,VALUE> layout;
private final IndexSamplingConfig samplingConfig;

protected final Set<RawCursor<Hit<KEY,VALUE>,IOException>> openSeekers;
final Set<RawCursor<Hit<KEY,VALUE>,IOException>> openSeekers;
protected final SchemaIndexDescriptor descriptor;

NativeSchemaIndexReader( GBPTree<KEY,VALUE> tree, Layout<KEY,VALUE> layout,
Expand Down Expand Up @@ -133,8 +133,8 @@ public PrimitiveLongResourceIterator query( IndexQuery... predicates )

private PrimitiveLongResourceIterator getHitIterator( RawCursor<Hit<KEY,VALUE>,IOException> seeker, boolean needFilter, IndexQuery[] predicates )
{
return needFilter ? new FilteringNativeHitIterator<KEY,VALUE>( seeker, openSeekers, predicates )
: new NativeHitIterator<KEY,VALUE>( seeker, openSeekers );
return needFilter ? new FilteringNativeHitIterator<>( seeker, openSeekers, predicates )
: new NativeHitIterator<>( seeker, openSeekers );
}

@Override
Expand Down
Expand Up @@ -26,8 +26,6 @@
import org.neo4j.graphdb.Resource;
import org.neo4j.internal.kernel.api.IndexOrder;
import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.internal.kernel.api.IndexQuery.ExactPredicate;
import org.neo4j.internal.kernel.api.IndexQuery.RangePredicate;
import org.neo4j.kernel.api.exceptions.index.IndexNotApplicableKernelException;
import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor;
import org.neo4j.kernel.impl.api.schema.BridgingIndexProgressor;
Expand All @@ -36,7 +34,6 @@
import org.neo4j.storageengine.api.schema.IndexReader;
import org.neo4j.storageengine.api.schema.IndexSampler;
import org.neo4j.values.storable.Value;
import org.neo4j.values.storable.ValueGroup;

import static java.lang.String.format;

Expand Down Expand Up @@ -113,24 +110,13 @@ public void query( IndexProgressor.NodeValueClient cursor, IndexOrder indexOrder
@Override
public boolean hasFullValuePrecision( IndexQuery... predicates )
{
if ( predicates.length > 1 )
{
return false;
}

IndexQuery predicate = predicates[0];
if ( predicate instanceof ExactPredicate )
{
Value value = ((ExactPredicate) predicate).value();
return selector.select( instances, value ).hasFullValuePrecision( predicates );
}

if ( predicate instanceof RangePredicate && predicate.valueGroup() == ValueGroup.NUMBER )
IndexReader instance = selector.select( instances, predicates );
if ( instance == null )
{
return instances[NUMBER].hasFullValuePrecision( predicates );
// null means ExistsPredicate and we don't care about
// full value precision for that, therefor true.
return true;
}
// TODO: support temporal range queries

return false;
return instance.hasFullValuePrecision( predicates );
}
}
Expand Up @@ -22,8 +22,11 @@
import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.storageengine.api.schema.IndexReader;
import org.neo4j.values.storable.Value;
import org.neo4j.values.storable.Values;

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;

/**
* Selector for index provider "lucene-1.x".
Expand All @@ -34,18 +37,68 @@ public class FusionSelector00 implements FusionIndexProvider.Selector
@Override
public void validateSatisfied( Object[] instances )
{
FusionIndexBase.validateSelectorInstances( instances, LUCENE );
FusionIndexBase.validateSelectorInstances( instances, LUCENE, SPATIAL, TEMPORAL );
}

@Override
public int selectSlot( Value... values )
{
if ( values.length > 1 )
{
// Multiple values must be handled by lucene
return LUCENE;
}

Value singleValue = values[0];
if ( Values.isGeometryValue( singleValue ) )
{
// It's a geometry, the spatial index can handle this
return SPATIAL;
}

if ( Values.isTemporalValue( singleValue ) )
{
return TEMPORAL;
}

return LUCENE;
}

@Override
public IndexReader select( IndexReader[] instances, IndexQuery... predicates )
{
if ( predicates.length > 1 )
{
return instances[LUCENE];
}
IndexQuery predicate = predicates[0];

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

if ( predicate instanceof IndexQuery.RangePredicate )
{
switch ( predicate.valueGroup() )
{
case GEOMETRY:
return instances[SPATIAL];
case DATE:
case LOCAL_DATE_TIME:
case ZONED_DATE_TIME:
case LOCAL_TIME:
case ZONED_TIME:
case DURATION:
return instances[TEMPORAL];
default: // fall through
}
}
if ( predicate instanceof IndexQuery.ExistsPredicate )
{
return null;
}
return instances[LUCENE];
}
}
Expand Up @@ -32,7 +32,7 @@ enum FusionVersion
@Override
int[] aliveSlots()
{
return new int[]{LUCENE};
return new int[]{LUCENE, SPATIAL, TEMPORAL};
}

@Override
Expand Down
Expand Up @@ -19,6 +19,7 @@
*/
package org.neo4j.kernel.api.impl.index.storage;

import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.IOContext;
import org.apache.lucene.store.IndexInput;
Expand Down Expand Up @@ -241,7 +242,7 @@ private List<File> listFolders( File rootFolder )
File[] files = fileSystem.listFiles( rootFolder );
return files == null ? Collections.emptyList()
: Stream.of( files )
.filter( fileSystem::isDirectory )
.filter( f -> fileSystem.isDirectory( f ) && StringUtils.isNumeric( f.getName() ) )
.sorted( FILE_COMPARATOR )
.collect( toList() );

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

import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.index.internal.gbptree.RecoveryCleanupWorkCollector;
import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.io.pagecache.PageCache;
import org.neo4j.kernel.api.impl.index.storage.DirectoryFactory;
import org.neo4j.kernel.api.index.IndexDirectoryStructure;
import org.neo4j.kernel.api.index.IndexProvider;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.impl.factory.GraphDatabaseFacadeFactory;
import org.neo4j.kernel.impl.factory.OperationalMode;
import org.neo4j.kernel.impl.index.schema.NumberIndexProvider;
import org.neo4j.kernel.impl.index.schema.TemporalIndexProvider;
import org.neo4j.kernel.impl.index.schema.fusion.SpatialFusionIndexProvider;

import static org.neo4j.kernel.api.impl.index.LuceneKernelExtensions.directoryFactory;

class IndexProviderFactoryUtil
{
static boolean isReadOnly( Config config, OperationalMode operationalMode )
{
return config.get( GraphDatabaseSettings.read_only ) && (OperationalMode.single == operationalMode);
}

static NumberIndexProvider numberProvider( PageCache pageCache, FileSystemAbstraction fs, IndexProvider.Monitor monitor,
RecoveryCleanupWorkCollector recoveryCleanupWorkCollector, IndexDirectoryStructure.Factory childDirectoryStructure, boolean readOnly )
{
return new NumberIndexProvider( pageCache, fs, childDirectoryStructure, monitor, recoveryCleanupWorkCollector, readOnly );
}

static SpatialFusionIndexProvider spatialProvider( PageCache pageCache, FileSystemAbstraction fs, IndexProvider.Monitor monitor,
RecoveryCleanupWorkCollector recoveryCleanupWorkCollector, boolean readOnly, IndexDirectoryStructure.Factory directoryStructure,
Config config )
{
return new SpatialFusionIndexProvider( pageCache, fs, directoryStructure, monitor, recoveryCleanupWorkCollector, readOnly, config );
}

static TemporalIndexProvider temporalProvider( PageCache pageCache, FileSystemAbstraction fs, IndexProvider.Monitor monitor,
RecoveryCleanupWorkCollector recoveryCleanupWorkCollector, boolean readOnly, IndexDirectoryStructure.Factory directoryStructure )
{
return new TemporalIndexProvider( pageCache, fs, directoryStructure, monitor, recoveryCleanupWorkCollector, readOnly );
}

static LuceneIndexProvider luceneProvider( FileSystemAbstraction fileSystemAbstraction,
IndexDirectoryStructure.Factory directoryStructure, IndexProvider.Monitor monitor, Config config,
OperationalMode operationalMode )
{
boolean ephemeral = config.get( GraphDatabaseFacadeFactory.Configuration.ephemeral );
DirectoryFactory directoryFactory = directoryFactory( ephemeral, fileSystemAbstraction );
return new LuceneIndexProvider( fileSystemAbstraction, directoryFactory, directoryStructure, monitor, config, operationalMode );
}
}
Expand Up @@ -22,25 +22,27 @@
import java.io.File;

import org.neo4j.helpers.Service;
import org.neo4j.index.internal.gbptree.RecoveryCleanupWorkCollector;
import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.kernel.api.impl.index.storage.DirectoryFactory;
import org.neo4j.io.pagecache.PageCache;
import org.neo4j.kernel.api.index.IndexDirectoryStructure;
import org.neo4j.kernel.api.index.IndexProvider;
import org.neo4j.kernel.api.index.LoggingMonitor;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.extension.KernelExtensionFactory;
import org.neo4j.kernel.impl.factory.GraphDatabaseFacadeFactory;
import org.neo4j.kernel.impl.factory.OperationalMode;
import org.neo4j.kernel.impl.index.schema.TemporalIndexProvider;
import org.neo4j.kernel.impl.index.schema.fusion.FusionIndexProvider;
import org.neo4j.kernel.impl.index.schema.fusion.FusionSelector00;
import org.neo4j.kernel.impl.index.schema.fusion.SpatialFusionIndexProvider;
import org.neo4j.kernel.impl.logging.LogService;
import org.neo4j.kernel.impl.spi.KernelContext;
import org.neo4j.kernel.monitoring.Monitors;
import org.neo4j.logging.Log;

import static org.neo4j.kernel.api.impl.index.LuceneKernelExtensions.directoryFactory;
import static org.neo4j.kernel.api.index.IndexDirectoryStructure.directoriesByProvider;
import static org.neo4j.kernel.api.index.IndexDirectoryStructure.directoriesByProviderKey;
import static org.neo4j.kernel.api.index.IndexDirectoryStructure.directoriesBySubProvider;
import static org.neo4j.kernel.api.index.IndexProvider.EMPTY;

@Service.Implementation( KernelExtensionFactory.class )
Expand All @@ -54,6 +56,10 @@ public class LuceneIndexProviderFactory extends

public interface Dependencies
{
PageCache pageCache();

RecoveryCleanupWorkCollector recoveryCleanupWorkCollector();

Config getConfig();

Monitors monitors();
Expand All @@ -71,39 +77,35 @@ public LuceneIndexProviderFactory()
@Override
public IndexProvider newInstance( KernelContext context, Dependencies dependencies )
{
FileSystemAbstraction fileSystemAbstraction = dependencies.fileSystem();
PageCache pageCache = dependencies.pageCache();
File storeDir = context.storeDir();
Config config = dependencies.getConfig();
Log log = dependencies.getLogService().getInternalLogProvider().getLog( LuceneIndexProvider.class );
FileSystemAbstraction fs = dependencies.fileSystem();
Monitors monitors = dependencies.monitors();
Log log = dependencies.getLogService().getInternalLogProvider().getLog( LuceneIndexProvider.class );
monitors.addMonitorListener( new LoggingMonitor( log ), KEY );
IndexProvider.Monitor monitor = monitors.newMonitor( IndexProvider.Monitor.class, KEY );
Config config = dependencies.getConfig();
OperationalMode operationalMode = context.databaseInfo().operationalMode;

LuceneIndexProvider luceneProvider = createLuceneProvider( fileSystemAbstraction, storeDir, monitor, config, operationalMode );

return new FusionIndexProvider( EMPTY, EMPTY, EMPTY, EMPTY, luceneProvider, new FusionSelector00(),
PROVIDER_DESCRIPTOR, LuceneIndexProvider.PRIORITY, directoriesByProvider( storeDir ), fileSystemAbstraction );
}

public static LuceneIndexProvider createLuceneProvider( FileSystemAbstraction fileSystemAbstraction, File storeDir,
IndexProvider.Monitor monitor, Config config, OperationalMode operationalMode )
{
return createLuceneProvider( fileSystemAbstraction, directoryStructureForLuceneProvider( storeDir ), monitor, config, operationalMode );
RecoveryCleanupWorkCollector recoveryCleanupWorkCollector = dependencies.recoveryCleanupWorkCollector();
return newInstance( pageCache, storeDir, fs, monitor, config, operationalMode, recoveryCleanupWorkCollector );
}

static LuceneIndexProvider createLuceneProvider( FileSystemAbstraction fileSystemAbstraction,
IndexDirectoryStructure.Factory directoryStructure, IndexProvider.Monitor monitor, Config config,
OperationalMode operationalMode )
public static FusionIndexProvider newInstance( PageCache pageCache, File storeDir, FileSystemAbstraction fs,
IndexProvider.Monitor monitor, Config config, OperationalMode operationalMode,
RecoveryCleanupWorkCollector recoveryCleanupWorkCollector )
{
boolean ephemeral = config.get( GraphDatabaseFacadeFactory.Configuration.ephemeral );
DirectoryFactory directoryFactory = directoryFactory( ephemeral, fileSystemAbstraction );
return new LuceneIndexProvider( fileSystemAbstraction, directoryFactory, directoryStructure, monitor, config,
operationalMode );
boolean readOnly = IndexProviderFactoryUtil.isReadOnly( config, operationalMode );
IndexDirectoryStructure.Factory baseDirStructure = directoriesByProviderKey( storeDir );
IndexDirectoryStructure.Factory childDirectoryStructure = directoriesBySubProvider( baseDirStructure.forProvider( PROVIDER_DESCRIPTOR ) );

LuceneIndexProvider lucene = IndexProviderFactoryUtil.luceneProvider( fs, baseDirStructure, monitor, config, operationalMode );
TemporalIndexProvider temporal =
IndexProviderFactoryUtil.temporalProvider( pageCache, fs, monitor, recoveryCleanupWorkCollector, readOnly, childDirectoryStructure );
SpatialFusionIndexProvider spatial =
IndexProviderFactoryUtil.spatialProvider( pageCache, fs, monitor, recoveryCleanupWorkCollector, readOnly, childDirectoryStructure, config );

return new FusionIndexProvider( EMPTY, EMPTY, spatial, temporal, lucene, new FusionSelector00(),
PROVIDER_DESCRIPTOR, LuceneIndexProvider.PRIORITY, directoriesByProvider( storeDir ), fs );
}

private static IndexDirectoryStructure.Factory directoryStructureForLuceneProvider( File storeDir )
{
return directoriesByProviderKey( storeDir );
}
}

0 comments on commit c96c29f

Please sign in to comment.