Skip to content

Commit

Permalink
Makes index value validation customizable per IndexAccessor
Browse files Browse the repository at this point in the history
Instead of having on global static tailored to lucene.
This allows native indexes to have their own validation.
  • Loading branch information
tinwelint committed Mar 28, 2018
1 parent 6e4a4c0 commit c6ed903
Show file tree
Hide file tree
Showing 53 changed files with 876 additions and 465 deletions.
Expand Up @@ -95,7 +95,7 @@ class DynamicSizeUtil
// mask for one-byte key size to map to the k's in [_,_,_,k,k,k,k,k] // mask for one-byte key size to map to the k's in [_,_,_,k,k,k,k,k]
static final int MASK_ONE_BYTE_KEY_SIZE = 0x1F; static final int MASK_ONE_BYTE_KEY_SIZE = 0x1F;
// max two-byte key size to map to the k's in [_,_,_,k,k,k,k,k][_,k,k,k,k,k,k,k] // max two-byte key size to map to the k's in [_,_,_,k,k,k,k,k][_,k,k,k,k,k,k,k]
private static final int MAX_TWO_BYTE_KEY_SIZE = 0xFFF; static final int MAX_TWO_BYTE_KEY_SIZE = 0xFFF;
// mask for one-byte value size to map to the v's in [_,v,v,v,v,v,v,v] // mask for one-byte value size to map to the v's in [_,v,v,v,v,v,v,v]
static final int MASK_ONE_BYTE_VALUE_SIZE = 0x7F; static final int MASK_ONE_BYTE_VALUE_SIZE = 0x7F;
// max two-byte value size to map to the v's in [_,v,v,v,v,v,v,v][v,v,v,v,v,v,v,v] // max two-byte value size to map to the v's in [_,v,v,v,v,v,v,v][v,v,v,v,v,v,v,v]
Expand Down
Expand Up @@ -63,6 +63,8 @@
*/ */
public class TreeNodeDynamicSize<KEY, VALUE> extends TreeNode<KEY,VALUE> public class TreeNodeDynamicSize<KEY, VALUE> extends TreeNode<KEY,VALUE>
{ {
public static final int MAX_KEY_SIZE = DynamicSizeUtil.MAX_TWO_BYTE_KEY_SIZE;

static final byte FORMAT_IDENTIFIER = 3; static final byte FORMAT_IDENTIFIER = 3;
static final byte FORMAT_VERSION = 0; static final byte FORMAT_VERSION = 0;


Expand Down
Expand Up @@ -681,7 +681,7 @@ private NeoStoreKernelModule buildKernel( LogFiles logFiles, TransactionAppender
StatementOperationParts statementOperationParts = dependencies.satisfyDependency( StatementOperationParts statementOperationParts = dependencies.satisfyDependency(
buildStatementOperations( storeLayer, autoIndexing, buildStatementOperations( storeLayer, autoIndexing,
constraintIndexCreator, databaseSchemaState, explicitIndexStore, cpuClockRef, constraintIndexCreator, databaseSchemaState, explicitIndexStore, cpuClockRef,
heapAllocationRef ) ); heapAllocationRef, indexingService ) );


TransactionHooks hooks = new TransactionHooks(); TransactionHooks hooks = new TransactionHooks();


Expand All @@ -691,7 +691,7 @@ private NeoStoreKernelModule buildKernel( LogFiles logFiles, TransactionAppender
availabilityGuard, tracers, storageEngine, procedures, transactionIdStore, clock, availabilityGuard, tracers, storageEngine, procedures, transactionIdStore, clock,
cpuClockRef, heapAllocationRef, accessCapability, DefaultCursors::new, autoIndexing, cpuClockRef, heapAllocationRef, accessCapability, DefaultCursors::new, autoIndexing,
explicitIndexStore, versionContextSupplier, collectionsFactorySupplier, constraintSemantics, explicitIndexStore, versionContextSupplier, collectionsFactorySupplier, constraintSemantics,
databaseSchemaState ) ); databaseSchemaState, indexingService ) );


buildTransactionMonitor( kernelTransactions, clock, config ); buildTransactionMonitor( kernelTransactions, clock, config );


Expand Down Expand Up @@ -866,13 +866,14 @@ public DependencyResolver getDependencyResolver()
private StatementOperationParts buildStatementOperations( StoreReadLayer storeReadLayer, AutoIndexing autoIndexing, private StatementOperationParts buildStatementOperations( StoreReadLayer storeReadLayer, AutoIndexing autoIndexing,
ConstraintIndexCreator constraintIndexCreator, DatabaseSchemaState databaseSchemaState, ConstraintIndexCreator constraintIndexCreator, DatabaseSchemaState databaseSchemaState,
ExplicitIndexStore explicitIndexStore, AtomicReference<CpuClock> cpuClockRef, ExplicitIndexStore explicitIndexStore, AtomicReference<CpuClock> cpuClockRef,
AtomicReference<HeapAllocation> heapAllocationRef ) AtomicReference<HeapAllocation> heapAllocationRef,
IndexingService indexingService )
{ {
// The passed in StoreReadLayer is the bottom most layer: Read-access to committed data. // The passed in StoreReadLayer is the bottom most layer: Read-access to committed data.
// To it we add: // To it we add:
// + Transaction state handling // + Transaction state handling
StateHandlingStatementOperations stateHandlingContext = new StateHandlingStatementOperations( storeReadLayer, StateHandlingStatementOperations stateHandlingContext = new StateHandlingStatementOperations( storeReadLayer,
autoIndexing, constraintIndexCreator, explicitIndexStore ); autoIndexing, constraintIndexCreator, explicitIndexStore, indexingService );


QueryRegistrationOperations queryRegistrationOperations = QueryRegistrationOperations queryRegistrationOperations =
new StackingQueryRegistrationOperations( clock, cpuClockRef, heapAllocationRef ); new StackingQueryRegistrationOperations( clock, cpuClockRef, heapAllocationRef );
Expand Down
Expand Up @@ -30,7 +30,9 @@
import org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException; import org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException;
import org.neo4j.kernel.impl.api.index.IndexUpdateMode; import org.neo4j.kernel.impl.api.index.IndexUpdateMode;
import org.neo4j.kernel.impl.api.index.updater.SwallowingIndexUpdater; import org.neo4j.kernel.impl.api.index.updater.SwallowingIndexUpdater;
import org.neo4j.kernel.impl.util.Validator;
import org.neo4j.storageengine.api.schema.IndexReader; import org.neo4j.storageengine.api.schema.IndexReader;
import org.neo4j.values.storable.Value;


import static java.util.Collections.emptyIterator; import static java.util.Collections.emptyIterator;
import static org.neo4j.helpers.collection.Iterators.emptyResourceIterator; import static org.neo4j.helpers.collection.Iterators.emptyResourceIterator;
Expand All @@ -53,7 +55,7 @@ public interface IndexAccessor extends Closeable
/** /**
* Return an updater for applying a set of changes to this index. * Return an updater for applying a set of changes to this index.
* Updates must be visible in {@link #newReader() readers} created after this update. * Updates must be visible in {@link #newReader() readers} created after this update.
* * <p>
* This is called with IndexUpdateMode.RECOVERY when starting up after * This is called with IndexUpdateMode.RECOVERY when starting up after
* a crash or similar. Updates given then may have already been applied to this index, so * a crash or similar. Updates given then may have already been applied to this index, so
* additional checks must be in place so that data doesn't get duplicated, but is idempotent. * additional checks must be in place so that data doesn't get duplicated, but is idempotent.
Expand Down Expand Up @@ -120,6 +122,14 @@ public interface IndexAccessor extends Closeable
*/ */
boolean isDirty(); boolean isDirty();


/**
* @return a {@link Validator} capable of validating {@link Value values} before transaction determines that it can commit.
*/
default void validateBeforeCommit( Value[] tuple )
{
// For most types values there are no specific validations to be made.
}

class Adapter implements IndexAccessor class Adapter implements IndexAccessor
{ {
@Override @Override
Expand Down Expand Up @@ -271,5 +281,11 @@ public boolean isDirty()
{ {
return delegate.isDirty(); return delegate.isDirty();
} }

@Override
public void validateBeforeCommit( Value[] tuple )
{
delegate.validateBeforeCommit( tuple );
}
} }
} }

This file was deleted.

@@ -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.impl.api;

import org.neo4j.kernel.impl.util.Validator;
import org.neo4j.values.storable.TextValue;
import org.neo4j.values.storable.Value;
import org.neo4j.values.storable.Values;

/**
* Validates {@link TextValue text values} so that they are within a certain length, byte-wise.
*/
public class IndexTextValueLengthValidator implements Validator<Value>
{
private final int maxByteLength;
private final int checkThreshold;

public IndexTextValueLengthValidator( int maxByteLength )
{
this.maxByteLength = maxByteLength;

// This check threshold is for not having to check every value that comes in, only those that may have a chance to exceed the max length.
// The value 5 comes from a safer 4, which is the number of bytes that a max size UTF-8 code point needs.
this.checkThreshold = maxByteLength / 5;
}

@Override
public void validate( Value value )
{
if ( value == null || value == Values.NO_VALUE )
{
throw new IllegalArgumentException( "Null value" );
}
if ( Values.isTextValue( value ) && ((TextValue)value).length() >= checkThreshold )
{
validate( ((TextValue)value).stringValue().getBytes() );
}
}

public void validate( byte[] encodedValue )
{
if ( encodedValue == null )
{
throw new IllegalArgumentException( "Null value" );
}

int byteLength = encodedValue.length;
if ( byteLength > maxByteLength )
{
throw new IllegalArgumentException( "Property value bytes length: " + byteLength +
" is longer than " + maxByteLength + ", which is maximum supported length" +
" of indexed property value." );
}
}
}

This file was deleted.

Expand Up @@ -68,6 +68,7 @@
import org.neo4j.kernel.api.txstate.ExplicitIndexTransactionState; import org.neo4j.kernel.api.txstate.ExplicitIndexTransactionState;
import org.neo4j.kernel.api.txstate.TransactionState; import org.neo4j.kernel.api.txstate.TransactionState;
import org.neo4j.kernel.api.txstate.TxStateHolder; import org.neo4j.kernel.api.txstate.TxStateHolder;
import org.neo4j.kernel.impl.api.index.IndexingService;
import org.neo4j.kernel.impl.api.state.ConstraintIndexCreator; import org.neo4j.kernel.impl.api.state.ConstraintIndexCreator;
import org.neo4j.kernel.impl.api.state.TxState; import org.neo4j.kernel.impl.api.state.TxState;
import org.neo4j.kernel.impl.constraints.ConstraintSemantics; import org.neo4j.kernel.impl.constraints.ConstraintSemantics;
Expand Down Expand Up @@ -193,7 +194,7 @@ public KernelTransactionImplementation( StatementOperationParts statementOperati
StorageEngine storageEngine, AccessCapability accessCapability, DefaultCursors cursors, AutoIndexing autoIndexing, StorageEngine storageEngine, AccessCapability accessCapability, DefaultCursors cursors, AutoIndexing autoIndexing,
ExplicitIndexStore explicitIndexStore, VersionContextSupplier versionContextSupplier, ExplicitIndexStore explicitIndexStore, VersionContextSupplier versionContextSupplier,
CollectionsFactorySupplier collectionsFactorySupplier, ConstraintSemantics constraintSemantics, CollectionsFactorySupplier collectionsFactorySupplier, ConstraintSemantics constraintSemantics,
SchemaState schemaState ) SchemaState schemaState, IndexingService indexingService )
{ {
this.statementOperations = statementOperations; this.statementOperations = statementOperations;
this.schemaWriteGuard = schemaWriteGuard; this.schemaWriteGuard = schemaWriteGuard;
Expand Down Expand Up @@ -223,7 +224,7 @@ public KernelTransactionImplementation( StatementOperationParts statementOperati
this.operations = this.operations =
new Operations( new Operations(
allStoreHolder, allStoreHolder,
new IndexTxStateUpdater( storageEngine.storeReadLayer(), allStoreHolder ), new IndexTxStateUpdater( storageEngine.storeReadLayer(), allStoreHolder, indexingService ),
storageStatement, storageStatement,
this, new KernelToken( storeLayer, this ), cursors, autoIndexing, constraintIndexCreator, this, new KernelToken( storeLayer, this ), cursors, autoIndexing, constraintIndexCreator,
constraintSemantics ); constraintSemantics );
Expand Down
Expand Up @@ -40,6 +40,7 @@
import org.neo4j.kernel.api.exceptions.Status; import org.neo4j.kernel.api.exceptions.Status;
import org.neo4j.kernel.api.explicitindex.AutoIndexing; import org.neo4j.kernel.api.explicitindex.AutoIndexing;
import org.neo4j.kernel.api.txstate.ExplicitIndexTransactionState; import org.neo4j.kernel.api.txstate.ExplicitIndexTransactionState;
import org.neo4j.kernel.impl.api.index.IndexingService;
import org.neo4j.kernel.impl.api.state.ConstraintIndexCreator; import org.neo4j.kernel.impl.api.state.ConstraintIndexCreator;
import org.neo4j.kernel.impl.api.state.ExplicitIndexTransactionStateImpl; import org.neo4j.kernel.impl.api.state.ExplicitIndexTransactionStateImpl;
import org.neo4j.kernel.impl.constraints.ConstraintSemantics; import org.neo4j.kernel.impl.constraints.ConstraintSemantics;
Expand Down Expand Up @@ -100,6 +101,7 @@ public class KernelTransactions extends LifecycleAdapter implements Supplier<Ker
private final Supplier<DefaultCursors> cursorsSupplier; private final Supplier<DefaultCursors> cursorsSupplier;
private final AutoIndexing autoIndexing; private final AutoIndexing autoIndexing;
private final ExplicitIndexStore explicitIndexStore; private final ExplicitIndexStore explicitIndexStore;
private final IndexingService indexingService;
private final CollectionsFactorySupplier collectionsFactorySupplier; private final CollectionsFactorySupplier collectionsFactorySupplier;
private final SchemaState schemaState; private final SchemaState schemaState;


Expand Down Expand Up @@ -147,7 +149,8 @@ public KernelTransactions( StatementLocksFactory statementLocksFactory,
VersionContextSupplier versionContextSupplier, VersionContextSupplier versionContextSupplier,
CollectionsFactorySupplier collectionsFactorySupplier, CollectionsFactorySupplier collectionsFactorySupplier,
ConstraintSemantics constraintSemantics, ConstraintSemantics constraintSemantics,
SchemaState schemaState ) SchemaState schemaState,
IndexingService indexingService )
{ {
this.statementLocksFactory = statementLocksFactory; this.statementLocksFactory = statementLocksFactory;
this.constraintIndexCreator = constraintIndexCreator; this.constraintIndexCreator = constraintIndexCreator;
Expand All @@ -167,6 +170,7 @@ public KernelTransactions( StatementLocksFactory statementLocksFactory,
this.accessCapability = accessCapability; this.accessCapability = accessCapability;
this.autoIndexing = autoIndexing; this.autoIndexing = autoIndexing;
this.explicitIndexStore = explicitIndexStore; this.explicitIndexStore = explicitIndexStore;
this.indexingService = indexingService;
this.explicitIndexTxStateSupplier = () -> this.explicitIndexTxStateSupplier = () ->
new CachingExplicitIndexTransactionState( new CachingExplicitIndexTransactionState(
new ExplicitIndexTransactionStateImpl( indexConfigStore, explicitIndexProviderLookup ) ); new ExplicitIndexTransactionStateImpl( indexConfigStore, explicitIndexProviderLookup ) );
Expand Down Expand Up @@ -370,7 +374,7 @@ public KernelTransactionImplementation newInstance()
tracers.pageCursorTracerSupplier, storageEngine, accessCapability, tracers.pageCursorTracerSupplier, storageEngine, accessCapability,
cursorsSupplier.get(), autoIndexing, cursorsSupplier.get(), autoIndexing,
explicitIndexStore, versionContextSupplier, collectionsFactorySupplier, constraintSemantics, explicitIndexStore, versionContextSupplier, collectionsFactorySupplier, constraintSemantics,
schemaState ); schemaState, indexingService );
this.transactions.add( tx ); this.transactions.add( tx );
return tx; return tx;
} }
Expand Down
Expand Up @@ -70,6 +70,7 @@
import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory; import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory;
import org.neo4j.kernel.api.txstate.TransactionCountingStateVisitor; import org.neo4j.kernel.api.txstate.TransactionCountingStateVisitor;
import org.neo4j.kernel.api.txstate.TransactionState; import org.neo4j.kernel.api.txstate.TransactionState;
import org.neo4j.kernel.impl.api.index.IndexingService;
import org.neo4j.kernel.impl.api.operations.CountsOperations; import org.neo4j.kernel.impl.api.operations.CountsOperations;
import org.neo4j.kernel.impl.api.operations.EntityOperations; import org.neo4j.kernel.impl.api.operations.EntityOperations;
import org.neo4j.kernel.impl.api.operations.ExplicitIndexReadOperations; import org.neo4j.kernel.impl.api.operations.ExplicitIndexReadOperations;
Expand Down Expand Up @@ -136,13 +137,14 @@ public class StateHandlingStatementOperations implements
public StateHandlingStatementOperations( public StateHandlingStatementOperations(
StoreReadLayer storeLayer, AutoIndexing propertyTrackers, StoreReadLayer storeLayer, AutoIndexing propertyTrackers,
ConstraintIndexCreator constraintIndexCreator, ConstraintIndexCreator constraintIndexCreator,
ExplicitIndexStore explicitIndexStore ) ExplicitIndexStore explicitIndexStore,
IndexingService indexingService )
{ {
this.storeLayer = storeLayer; this.storeLayer = storeLayer;
this.autoIndexing = propertyTrackers; this.autoIndexing = propertyTrackers;
this.constraintIndexCreator = constraintIndexCreator; this.constraintIndexCreator = constraintIndexCreator;
this.explicitIndexStore = explicitIndexStore; this.explicitIndexStore = explicitIndexStore;
this.indexTxStateUpdater = new IndexTxStateUpdater( storeLayer, this ); this.indexTxStateUpdater = new IndexTxStateUpdater( storeLayer, this, indexingService );
} }


// <Cursors> // <Cursors>
Expand Down
Expand Up @@ -38,6 +38,7 @@
import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor;
import org.neo4j.storageengine.api.schema.IndexReader; import org.neo4j.storageengine.api.schema.IndexReader;
import org.neo4j.storageengine.api.schema.PopulationProgress; import org.neo4j.storageengine.api.schema.PopulationProgress;
import org.neo4j.values.storable.Value;


public abstract class AbstractDelegatingIndexProxy implements IndexProxy public abstract class AbstractDelegatingIndexProxy implements IndexProxy
{ {
Expand Down Expand Up @@ -133,6 +134,12 @@ public void validate() throws IndexPopulationFailedKernelException, UniqueProper
getDelegate().validate(); getDelegate().validate();
} }


@Override
public void validateBeforeCommit( Value[] tuple )
{
getDelegate().validateBeforeCommit( tuple );
}

@Override @Override
public IndexPopulationFailure getPopulationFailure() throws IllegalStateException public IndexPopulationFailure getPopulationFailure() throws IllegalStateException
{ {
Expand Down

0 comments on commit c6ed903

Please sign in to comment.