Skip to content

Commit

Permalink
Extract common functionality
Browse files Browse the repository at this point in the history
Native Number and Spatial indexes share a lot of functionality.
  • Loading branch information
OliviaYtterbrink committed Feb 14, 2018
1 parent 1bb666a commit 52c7286
Show file tree
Hide file tree
Showing 38 changed files with 372 additions and 1,727 deletions.
Expand Up @@ -28,7 +28,7 @@
/** /**
* Writes a failure message to a header in a {@link GBPTree}. * Writes a failure message to a header in a {@link GBPTree}.
*/ */
public class FailureHeaderWriter implements Consumer<PageCursor> class FailureHeaderWriter implements Consumer<PageCursor>
{ {
/** /**
* The {@code short} length field containing the length (number of bytes) of the failure message. * The {@code short} length field containing the length (number of bytes) of the failure message.
Expand All @@ -37,7 +37,7 @@ public class FailureHeaderWriter implements Consumer<PageCursor>


private final byte[] failureBytes; private final byte[] failureBytes;


public FailureHeaderWriter( byte[] failureBytes ) FailureHeaderWriter( byte[] failureBytes )
{ {
this.failureBytes = failureBytes; this.failureBytes = failureBytes;
} }
Expand Down
Expand Up @@ -51,7 +51,7 @@
* @param <KEY> type of {@link NativeSchemaKey}. * @param <KEY> type of {@link NativeSchemaKey}.
* @param <VALUE> type of {@link NativeSchemaValue}. * @param <VALUE> type of {@link NativeSchemaValue}.
*/ */
public abstract class NativeSchemaIndexPopulator<KEY extends NativeSchemaKey, VALUE extends NativeSchemaValue> abstract class NativeSchemaIndexPopulator<KEY extends NativeSchemaKey, VALUE extends NativeSchemaValue>
extends NativeSchemaIndex<KEY,VALUE> implements IndexPopulator extends NativeSchemaIndex<KEY,VALUE> implements IndexPopulator
{ {
static final byte BYTE_FAILED = 0; static final byte BYTE_FAILED = 0;
Expand Down
Expand Up @@ -26,11 +26,11 @@
/** /**
* Utilities for implementing {@link IndexSampler sampling}. * Utilities for implementing {@link IndexSampler sampling}.
*/ */
public class SamplingUtil class SamplingUtil
{ {
private static final String DELIMITER = "\u001F"; private static final String DELIMITER = "\u001F";


public static String encodedStringValuesForSampling( Object... values ) static String encodedStringValuesForSampling( Object... values )
{ {
return StringUtils.join( values, DELIMITER ); return StringUtils.join( values, DELIMITER );
} }
Expand Down
Expand Up @@ -17,41 +17,43 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.neo4j.kernel.impl.index.schema.spatial; package org.neo4j.kernel.impl.index.schema;


import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;


import org.neo4j.index.internal.gbptree.GBPTree; import org.neo4j.index.internal.gbptree.GBPTree;
import org.neo4j.index.internal.gbptree.RecoveryCleanupWorkCollector; import org.neo4j.index.internal.gbptree.RecoveryCleanupWorkCollector;
import org.neo4j.internal.kernel.api.InternalIndexState;
import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.io.pagecache.PageCache; import org.neo4j.io.pagecache.PageCache;
import org.neo4j.kernel.api.index.IndexAccessor; import org.neo4j.kernel.api.index.IndexAccessor;
import org.neo4j.kernel.api.index.IndexDirectoryStructure; import org.neo4j.kernel.api.index.IndexDirectoryStructure;
import org.neo4j.kernel.api.index.IndexPopulator; import org.neo4j.kernel.api.index.IndexPopulator;
import org.neo4j.kernel.api.index.InternalIndexState;
import org.neo4j.kernel.api.index.SchemaIndexProvider; import org.neo4j.kernel.api.index.SchemaIndexProvider;
import org.neo4j.kernel.api.schema.index.IndexDescriptor; import org.neo4j.kernel.api.schema.index.IndexDescriptor;
import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingConfig; import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingConfig;
import org.neo4j.kernel.impl.index.schema.fusion.SpatialFusionSchemaIndexProvider;
import org.neo4j.values.storable.CoordinateReferenceSystem; import org.neo4j.values.storable.CoordinateReferenceSystem;
import org.neo4j.values.storable.Value; import org.neo4j.values.storable.Value;


import static org.neo4j.kernel.impl.index.schema.spatial.SpatialSchemaIndexPopulator.BYTE_FAILED; import static org.neo4j.kernel.impl.index.schema.NativeSchemaIndexPopulator.BYTE_FAILED;
import static org.neo4j.kernel.impl.index.schema.spatial.SpatialSchemaIndexPopulator.BYTE_ONLINE; import static org.neo4j.kernel.impl.index.schema.NativeSchemaIndexPopulator.BYTE_ONLINE;
import static org.neo4j.kernel.impl.index.schema.spatial.SpatialSchemaIndexPopulator.BYTE_POPULATING; import static org.neo4j.kernel.impl.index.schema.NativeSchemaIndexPopulator.BYTE_POPULATING;


/** /**
* An instance of this class represents a dynamically created sub-index specific to a particular coordinate reference system. * An instance of this class represents a dynamically created sub-index specific to a particular coordinate reference system.
* This allows the fusion index design to be extended to an unknown number of sub-indexes, one for each CRS. * This allows the fusion index design to be extended to an unknown number of sub-indexes, one for each CRS.
*/ */
public class KnownSpatialIndex public class SpatialKnownIndex
{ {


interface Factory public interface Factory
{ {
KnownSpatialIndex selectAndCreate( Map<CoordinateReferenceSystem,KnownSpatialIndex> indexMap, long indexId, Value... values ); SpatialKnownIndex selectAndCreate( Map<CoordinateReferenceSystem,SpatialKnownIndex> indexMap, long indexId, Value... values );
KnownSpatialIndex selectAndCreate( Map<CoordinateReferenceSystem,KnownSpatialIndex> indexMap, long indexId, CoordinateReferenceSystem crs );
SpatialKnownIndex selectAndCreate( Map<CoordinateReferenceSystem,SpatialKnownIndex> indexMap, long indexId, CoordinateReferenceSystem crs );
} }


private final File indexFile; private final File indexFile;
Expand All @@ -62,12 +64,12 @@ interface Factory
private final SchemaIndexProvider.Monitor monitor; private final SchemaIndexProvider.Monitor monitor;
private final RecoveryCleanupWorkCollector recoveryCleanupWorkCollector; private final RecoveryCleanupWorkCollector recoveryCleanupWorkCollector;
private SpatialSchemaIndexAccessor indexAccessor; private SpatialSchemaIndexAccessor indexAccessor;
private SpatialSchemaIndexPopulator indexPopulator; private NativeSchemaIndexPopulator indexPopulator;


/** /**
* Create a representation of a spatial index for a specific coordinate reference system. This constructure should be used for first time creation. * Create a representation of a spatial index for a specific coordinate reference system. This constructure should be used for first time creation.
*/ */
KnownSpatialIndex( IndexDirectoryStructure directoryStructure, CoordinateReferenceSystem crs, long indexId, PageCache pageCache, public SpatialKnownIndex( IndexDirectoryStructure directoryStructure, CoordinateReferenceSystem crs, long indexId, PageCache pageCache,
FileSystemAbstraction fs, SchemaIndexProvider.Monitor monitor, RecoveryCleanupWorkCollector recoveryCleanupWorkCollector ) FileSystemAbstraction fs, SchemaIndexProvider.Monitor monitor, RecoveryCleanupWorkCollector recoveryCleanupWorkCollector )
{ {
this.crs = crs; this.crs = crs;
Expand All @@ -78,7 +80,8 @@ interface Factory
this.recoveryCleanupWorkCollector = recoveryCleanupWorkCollector; this.recoveryCleanupWorkCollector = recoveryCleanupWorkCollector;


// Depends on crs // Depends on crs
SchemaIndexProvider.Descriptor crsDescriptor = new SchemaIndexProvider.Descriptor( Integer.toString( crs.getTable().getTableId() ), Integer.toString( crs.getCode() ) ); SchemaIndexProvider.Descriptor crsDescriptor =
new SchemaIndexProvider.Descriptor( Integer.toString( crs.getTable().getTableId() ), Integer.toString( crs.getCode() ) );
IndexDirectoryStructure indexDir = IndexDirectoryStructure.directoriesBySubProvider( directoryStructure ).forProvider( crsDescriptor ); IndexDirectoryStructure indexDir = IndexDirectoryStructure.directoriesBySubProvider( directoryStructure ).forProvider( crsDescriptor );
indexFile = new File( indexDir.directoryForIndex( indexId ), indexFileName( indexId ) ); indexFile = new File( indexDir.directoryForIndex( indexId ), indexFileName( indexId ) );
} }
Expand All @@ -88,22 +91,22 @@ private static String indexFileName( long indexId )
return "index-" + indexId; return "index-" + indexId;
} }


boolean indexExists() public boolean indexExists()
{ {
return fs.fileExists( indexFile ); return fs.fileExists( indexFile );
} }


public String readPopupationFailure() throws IOException public String readPopupationFailure() throws IOException
{ {
SpatialSchemaIndexHeaderReader headerReader = new SpatialSchemaIndexHeaderReader(); NativeSchemaIndexHeaderReader headerReader = new NativeSchemaIndexHeaderReader();
GBPTree.readHeader( pageCache, indexFile, new SpatialSchemaIndexProvider.ReadOnlyMetaNumberLayout(), headerReader ); GBPTree.readHeader( pageCache, indexFile, new SpatialFusionSchemaIndexProvider.ReadOnlyMetaNumberLayout(), headerReader );
return headerReader.failureMessage; return headerReader.failureMessage;
} }


InternalIndexState readState() throws IOException public InternalIndexState readState() throws IOException
{ {
SpatialSchemaIndexHeaderReader headerReader = new SpatialSchemaIndexHeaderReader(); NativeSchemaIndexHeaderReader headerReader = new NativeSchemaIndexHeaderReader();
GBPTree.readHeader( pageCache, indexFile, new SpatialSchemaIndexProvider.ReadOnlyMetaNumberLayout(), headerReader ); GBPTree.readHeader( pageCache, indexFile, new SpatialFusionSchemaIndexProvider.ReadOnlyMetaNumberLayout(), headerReader );
switch ( headerReader.state ) switch ( headerReader.state )
{ {
case BYTE_FAILED: case BYTE_FAILED:
Expand All @@ -117,21 +120,21 @@ InternalIndexState readState() throws IOException
} }
} }


private SpatialSchemaIndexPopulator makeIndexPopulator(IndexDescriptor descriptor, IndexSamplingConfig samplingConfig) private NativeSchemaIndexPopulator makeIndexPopulator( IndexDescriptor descriptor, IndexSamplingConfig samplingConfig )
{ {
switch ( descriptor.type() ) switch ( descriptor.type() )
{ {
case GENERAL: case GENERAL:
return new SpatialNonUniqueSchemaIndexPopulator<>( pageCache, fs, indexFile, new NonUniqueSpatialLayout(), samplingConfig, monitor, descriptor, return new NativeNonUniqueSchemaIndexPopulator<>( pageCache, fs, indexFile, new SpatialLayoutNonUnique(), samplingConfig, monitor, descriptor,
indexId ); indexId );
case UNIQUE: case UNIQUE:
return new SpatialUniqueSchemaIndexPopulator<>( pageCache, fs, indexFile, new UniqueSpatialLayout(), monitor, descriptor, indexId ); return new NativeUniqueSchemaIndexPopulator<>( pageCache, fs, indexFile, new SpatialLayoutUnique(), monitor, descriptor, indexId );
default: default:
throw new UnsupportedOperationException( "Can not create index populator of type " + descriptor.type() ); throw new UnsupportedOperationException( "Can not create index populator of type " + descriptor.type() );
} }
} }


IndexPopulator getPopulator(IndexDescriptor descriptor, IndexSamplingConfig samplingConfig) public IndexPopulator getPopulator( IndexDescriptor descriptor, IndexSamplingConfig samplingConfig )
{ {
if ( indexPopulator == null ) if ( indexPopulator == null )
{ {
Expand All @@ -150,31 +153,30 @@ IndexPopulator getPopulator(IndexDescriptor descriptor, IndexSamplingConfig samp
return indexPopulator; return indexPopulator;
} }


void closePopulator( IndexDescriptor descriptor, IndexSamplingConfig samplingConfig, boolean populationCompletedSuccessfully ) throws IOException public void closePopulator( IndexDescriptor descriptor, IndexSamplingConfig samplingConfig, boolean populationCompletedSuccessfully ) throws IOException
{ {
getPopulator( descriptor, samplingConfig ).close( populationCompletedSuccessfully ); getPopulator( descriptor, samplingConfig ).close( populationCompletedSuccessfully );
this.indexPopulator = null; this.indexPopulator = null;
} }


private SpatialSchemaIndexAccessor makeOnlineAccessor(IndexDescriptor descriptor, IndexSamplingConfig samplingConfig) throws IOException private SpatialSchemaIndexAccessor makeOnlineAccessor( IndexDescriptor descriptor, IndexSamplingConfig samplingConfig ) throws IOException
{ {
SpatialLayout layout; SpatialLayout layout;
switch ( descriptor.type() ) switch ( descriptor.type() )
{ {
case GENERAL: case GENERAL:
layout = new NonUniqueSpatialLayout(); layout = new SpatialLayoutNonUnique();
break; break;
case UNIQUE: case UNIQUE:
layout = new UniqueSpatialLayout(); layout = new SpatialLayoutUnique();
break; break;
default: default:
throw new UnsupportedOperationException( "Can not create index accessor of type " + descriptor.type() ); throw new UnsupportedOperationException( "Can not create index accessor of type " + descriptor.type() );
} }
return new SpatialSchemaIndexAccessor<>( pageCache, fs, indexFile, layout, recoveryCleanupWorkCollector, monitor, descriptor, indexId, return new SpatialSchemaIndexAccessor<>( pageCache, fs, indexFile, layout, recoveryCleanupWorkCollector, monitor, descriptor, indexId, samplingConfig );
samplingConfig );
} }


IndexAccessor getOnlineAccessor( IndexDescriptor descriptor, IndexSamplingConfig samplingConfig ) throws IOException public IndexAccessor getOnlineAccessor( IndexDescriptor descriptor, IndexSamplingConfig samplingConfig ) throws IOException
{ {
if ( indexAccessor == null ) if ( indexAccessor == null )
{ {
Expand Down
Expand Up @@ -17,15 +17,15 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.neo4j.kernel.impl.index.schema.spatial; package org.neo4j.kernel.impl.index.schema;


import org.neo4j.index.internal.gbptree.Layout; import org.neo4j.index.internal.gbptree.Layout;
import org.neo4j.io.pagecache.PageCursor; import org.neo4j.io.pagecache.PageCursor;


/** /**
* {@link Layout} for numbers where numbers doesn't need to be unique. * {@link Layout} for numbers where numbers doesn't need to be unique.
*/ */
abstract class SpatialLayout extends Layout.Adapter<SpatialSchemaKey,SpatialSchemaValue> public abstract class SpatialLayout extends Layout.Adapter<SpatialSchemaKey,NativeSchemaValue>
{ {
@Override @Override
public SpatialSchemaKey newKey() public SpatialSchemaKey newKey()
Expand All @@ -39,15 +39,15 @@ public SpatialSchemaKey copyKey( SpatialSchemaKey key,
{ {
into.type = key.type; into.type = key.type;
into.rawValueBits = key.rawValueBits; into.rawValueBits = key.rawValueBits;
into.entityId = key.entityId; into.setEntityId( key.getEntityId() );
into.entityIdIsSpecialTieBreaker = key.entityIdIsSpecialTieBreaker; into.setEntityIdIsSpecialTieBreaker( key.getEntityIdIsSpecialTieBreaker() );
return into; return into;
} }


@Override @Override
public SpatialSchemaValue newValue() public NativeSchemaValue newValue()
{ {
return SpatialSchemaValue.INSTANCE; return NativeSchemaValue.INSTANCE;
} }


@Override @Override
Expand All @@ -59,19 +59,19 @@ public int keySize()
@Override @Override
public int valueSize() public int valueSize()
{ {
return SpatialSchemaValue.SIZE; return NativeSchemaValue.SIZE;
} }


@Override @Override
public void writeKey( PageCursor cursor, SpatialSchemaKey key ) public void writeKey( PageCursor cursor, SpatialSchemaKey key )
{ {
cursor.putByte( key.type ); cursor.putByte( key.type );
cursor.putLong( key.rawValueBits ); cursor.putLong( key.rawValueBits );
cursor.putLong( key.entityId ); cursor.putLong( key.getEntityId() );
} }


@Override @Override
public void writeValue( PageCursor cursor, SpatialSchemaValue value ) public void writeValue( PageCursor cursor, NativeSchemaValue value )
{ {
} }


Expand All @@ -80,11 +80,11 @@ public void readKey( PageCursor cursor, SpatialSchemaKey into )
{ {
into.type = cursor.getByte(); into.type = cursor.getByte();
into.rawValueBits = cursor.getLong(); into.rawValueBits = cursor.getLong();
into.entityId = cursor.getLong(); into.setEntityId( cursor.getLong() );
} }


@Override @Override
public void readValue( PageCursor cursor, SpatialSchemaValue into ) public void readValue( PageCursor cursor, NativeSchemaValue into )
{ {
} }
} }
Expand Up @@ -17,16 +17,16 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.neo4j.kernel.impl.index.schema.spatial; package org.neo4j.kernel.impl.index.schema;


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


public class NonUniqueSpatialLayout extends SpatialLayout public class SpatialLayoutNonUnique extends SpatialLayout
{ {
private static final String IDENTIFIER_NAME = "NUNI"; private static final String IDENTIFIER_NAME = "NUNI";
static final int MAJOR_VERSION = 0; public static final int MAJOR_VERSION = 0;
static final int MINOR_VERSION = 1; public static final int MINOR_VERSION = 1;
static long IDENTIFIER = Layout.namedIdentifier( IDENTIFIER_NAME, SpatialSchemaValue.SIZE ); public static long IDENTIFIER = Layout.namedIdentifier( IDENTIFIER_NAME, NativeSchemaValue.SIZE );


@Override @Override
public long identifier() public long identifier()
Expand All @@ -50,6 +50,6 @@ public int minorVersion()
public int compare( SpatialSchemaKey o1, SpatialSchemaKey o2 ) public int compare( SpatialSchemaKey o1, SpatialSchemaKey o2 )
{ {
int comparison = o1.compareValueTo( o2 ); int comparison = o1.compareValueTo( o2 );
return comparison != 0 ? comparison : Long.compare( o1.entityId, o2.entityId ); return comparison != 0 ? comparison : Long.compare( o1.getEntityId(), o2.getEntityId() );
} }
} }
Expand Up @@ -17,19 +17,19 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.neo4j.kernel.impl.index.schema.spatial; package org.neo4j.kernel.impl.index.schema;


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


/** /**
* {@link Layout} for numbers where numbers need to be unique. * {@link Layout} for numbers where numbers need to be unique.
*/ */
public class UniqueSpatialLayout extends SpatialLayout public class SpatialLayoutUnique extends SpatialLayout
{ {
private static final String IDENTIFIER_NAME = "UNI"; private static final String IDENTIFIER_NAME = "UNI";
static final int MAJOR_VERSION = 0; public static final int MAJOR_VERSION = 0;
static final int MINOR_VERSION = 1; public static final int MINOR_VERSION = 1;
static long IDENTIFIER = Layout.namedIdentifier( IDENTIFIER_NAME, SpatialSchemaValue.SIZE ); public static long IDENTIFIER = Layout.namedIdentifier( IDENTIFIER_NAME, NativeSchemaValue.SIZE );


@Override @Override
public long identifier() public long identifier()
Expand Down Expand Up @@ -57,9 +57,9 @@ public int compare( SpatialSchemaKey o1, SpatialSchemaKey o2 )
if ( comparison == 0 ) if ( comparison == 0 )
{ {
// This is a special case where we need also compare entityId to support inclusive/exclusive // This is a special case where we need also compare entityId to support inclusive/exclusive
if ( o1.entityIdIsSpecialTieBreaker || o2.entityIdIsSpecialTieBreaker ) if ( o1.getEntityIdIsSpecialTieBreaker() || o2.getEntityIdIsSpecialTieBreaker() )
{ {
return Long.compare( o1.entityId, o2.entityId ); return Long.compare( o1.getEntityId(), o2.getEntityId() );
} }
} }
return comparison; return comparison;
Expand Down

0 comments on commit 52c7286

Please sign in to comment.