Skip to content

Commit

Permalink
Allow id type to be configurable, edition based configuration of id t…
Browse files Browse the repository at this point in the history
…ype.

Allow id type reusability to be configurable during database edition configuration.
Introduce enterprise edition specific configurator and settings to be able to disticnt specific settings
and perform custom configuration.
Allow relationship ids to be reusable in ha and enterprise editions.
  • Loading branch information
MishaDemianenko committed Jul 4, 2016
1 parent 7039ee3 commit e8f870f
Show file tree
Hide file tree
Showing 18 changed files with 325 additions and 69 deletions.
Expand Up @@ -34,7 +34,6 @@
import org.neo4j.legacy.consistency.report.ConsistencyReport.NodeConsistencyReport; import org.neo4j.legacy.consistency.report.ConsistencyReport.NodeConsistencyReport;


import static java.lang.String.format; import static java.lang.String.format;

import static org.neo4j.legacy.consistency.checking.DynamicStore.ARRAY; import static org.neo4j.legacy.consistency.checking.DynamicStore.ARRAY;
import static org.neo4j.legacy.consistency.checking.DynamicStore.NODE_LABEL; import static org.neo4j.legacy.consistency.checking.DynamicStore.NODE_LABEL;
import static org.neo4j.legacy.consistency.checking.DynamicStore.SCHEMA; import static org.neo4j.legacy.consistency.checking.DynamicStore.SCHEMA;
Expand Down Expand Up @@ -144,25 +143,28 @@ public final void processString( RecordStore<DynamicRecord> store, DynamicRecord
{ {
RecordType type; RecordType type;
DynamicStore dereference; DynamicStore dereference;
switch ( idType ) if ( IdType.STRING_BLOCK.equals( idType ) )
{ {
case STRING_BLOCK:
type = RecordType.STRING_PROPERTY; type = RecordType.STRING_PROPERTY;
dereference = DynamicStore.STRING; dereference = DynamicStore.STRING;
break; }
case RELATIONSHIP_TYPE_TOKEN_NAME: else if ( IdType.RELATIONSHIP_TYPE_TOKEN_NAME.equals( idType ) )
{
type = RecordType.RELATIONSHIP_TYPE_NAME; type = RecordType.RELATIONSHIP_TYPE_NAME;
dereference = DynamicStore.RELATIONSHIP_TYPE; dereference = DynamicStore.RELATIONSHIP_TYPE;
break; }
case PROPERTY_KEY_TOKEN_NAME: else if ( IdType.PROPERTY_KEY_TOKEN_NAME.equals( idType ) )
{
type = RecordType.PROPERTY_KEY_NAME; type = RecordType.PROPERTY_KEY_NAME;
dereference = DynamicStore.PROPERTY_KEY; dereference = DynamicStore.PROPERTY_KEY;
break; }
case LABEL_TOKEN_NAME: else if ( IdType.LABEL_TOKEN_NAME.equals( idType ) )
{
type = RecordType.LABEL_NAME; type = RecordType.LABEL_NAME;
dereference = DynamicStore.LABEL; dereference = DynamicStore.LABEL;
break; }
default: else
{
throw new IllegalArgumentException( format( "The id type [%s] is not valid for String records.", idType ) ); throw new IllegalArgumentException( format( "The id type [%s] is not valid for String records.", idType ) );
} }
checkDynamic( type, store, string, new DynamicRecordCheck( store, dereference ) ); checkDynamic( type, store, string, new DynamicRecordCheck( store, dereference ) );
Expand Down
Expand Up @@ -34,7 +34,6 @@
import org.neo4j.kernel.impl.store.record.RelationshipTypeTokenRecord; import org.neo4j.kernel.impl.store.record.RelationshipTypeTokenRecord;


import static java.lang.String.format; import static java.lang.String.format;

import static org.neo4j.consistency.checking.DynamicStore.ARRAY; import static org.neo4j.consistency.checking.DynamicStore.ARRAY;
import static org.neo4j.consistency.checking.DynamicStore.NODE_LABEL; import static org.neo4j.consistency.checking.DynamicStore.NODE_LABEL;
import static org.neo4j.consistency.checking.DynamicStore.SCHEMA; import static org.neo4j.consistency.checking.DynamicStore.SCHEMA;
Expand Down Expand Up @@ -161,27 +160,31 @@ public final void processString( RecordStore<DynamicRecord> store, DynamicRecord
{ {
RecordType type; RecordType type;
DynamicStore dereference; DynamicStore dereference;
switch ( idType ) if ( IdType.STRING_BLOCK.equals( idType ) )
{ {
case STRING_BLOCK:
type = RecordType.STRING_PROPERTY; type = RecordType.STRING_PROPERTY;
dereference = DynamicStore.STRING; dereference = DynamicStore.STRING;
break; }
case RELATIONSHIP_TYPE_TOKEN_NAME: else if ( IdType.RELATIONSHIP_TYPE_TOKEN_NAME.equals( idType ) )
{
type = RecordType.RELATIONSHIP_TYPE_NAME; type = RecordType.RELATIONSHIP_TYPE_NAME;
dereference = DynamicStore.RELATIONSHIP_TYPE; dereference = DynamicStore.RELATIONSHIP_TYPE;
break; }
case PROPERTY_KEY_TOKEN_NAME: else if ( IdType.PROPERTY_KEY_TOKEN_NAME.equals( idType ) )
{
type = RecordType.PROPERTY_KEY_NAME; type = RecordType.PROPERTY_KEY_NAME;
dereference = DynamicStore.PROPERTY_KEY; dereference = DynamicStore.PROPERTY_KEY;
break; }
case LABEL_TOKEN_NAME: else if ( IdType.LABEL_TOKEN_NAME.equals( idType ) )
{
type = RecordType.LABEL_NAME; type = RecordType.LABEL_NAME;
dereference = DynamicStore.LABEL; dereference = DynamicStore.LABEL;
break; }
default: else
{
throw new IllegalArgumentException( format( "The id type [%s] is not valid for String records.", idType ) ); throw new IllegalArgumentException( format( "The id type [%s] is not valid for String records.", idType ) );
} }

checkDynamic( type, store, string, new DynamicRecordCheck( store, dereference ) ); checkDynamic( type, store, string, new DynamicRecordCheck( store, dereference ) );
} }


Expand Down
112 changes: 90 additions & 22 deletions community/kernel/src/main/java/org/neo4j/kernel/IdType.java
Expand Up @@ -19,49 +19,83 @@
*/ */
package org.neo4j.kernel; package org.neo4j.kernel;


import org.neo4j.unsafe.impl.internal.dragons.FeatureToggles; import java.util.Arrays;
import java.util.List;


/** /**
* @deprecated This will be moved to internal packages in the next major release. * @deprecated This will be moved to internal packages in the next major release.
*/ */
@Deprecated @Deprecated
public enum IdType public class IdType
{ {
NODE( 35, false ), public static final IdType NODE = new IdType( 35, Name.NODE, false );
RELATIONSHIP( 35, FeatureToggles.flag( "unsupported.dbms.relationships.ids.reuse", false ) ), public static final IdType RELATIONSHIP = new IdType( 35, Name.RELATIONSHIP, false );
PROPERTY( 36, true ), public static final IdType PROPERTY = new IdType( 36, Name.PROPERTY, true );
STRING_BLOCK( 36, true ), public static final IdType STRING_BLOCK = new IdType( 36, Name.STRING_BLOCK, true );
ARRAY_BLOCK( 36, true ), public static final IdType ARRAY_BLOCK = new IdType( 36, Name.ARRAY_BLOCK, true );
PROPERTY_KEY_TOKEN( false ), public static final IdType PROPERTY_KEY_TOKEN = new IdType( Name.PROPERTY_KEY_TOKEN, false );
PROPERTY_KEY_TOKEN_NAME( false ), public static final IdType PROPERTY_KEY_TOKEN_NAME = new IdType( Name.PROPERTY_KEY_TOKEN_NAME, false );
RELATIONSHIP_TYPE_TOKEN( 16, false ), public static final IdType RELATIONSHIP_TYPE_TOKEN = new IdType( 16, Name.RELATIONSHIP_TYPE_TOKEN, false );
RELATIONSHIP_TYPE_TOKEN_NAME( false ), public static final IdType RELATIONSHIP_TYPE_TOKEN_NAME = new IdType( Name.RELATIONSHIP_TYPE_TOKEN_NAME, false );
LABEL_TOKEN( false ), public static final IdType LABEL_TOKEN = new IdType( Name.LABEL_TOKEN, false );
LABEL_TOKEN_NAME( false ), public static final IdType LABEL_TOKEN_NAME = new IdType( Name.LABEL_TOKEN_NAME, false );
NEOSTORE_BLOCK( false ), public static final IdType NEOSTORE_BLOCK = new IdType( Name.NEOSTORE_BLOCK, false );
SCHEMA( 35, false ), public static final IdType SCHEMA = new IdType( 35, Name.SCHEMA, false );
NODE_LABELS( 35, true ), public static final IdType NODE_LABELS = new IdType( 35, Name.NODE_LABELS, true );
RELATIONSHIP_GROUP( 35, false ); public static final IdType RELATIONSHIP_GROUP = new IdType( 35, Name.RELATIONSHIP_GROUP, false );

private static final List<IdType> ALL_ID_TYPES = Arrays.asList( NODE, RELATIONSHIP, PROPERTY, STRING_BLOCK,
ARRAY_BLOCK, PROPERTY_KEY_TOKEN, PROPERTY_KEY_TOKEN_NAME, RELATIONSHIP_TYPE_TOKEN,
RELATIONSHIP_TYPE_TOKEN_NAME, LABEL_TOKEN, LABEL_TOKEN_NAME, NEOSTORE_BLOCK,
SCHEMA, NODE_LABELS, RELATIONSHIP_GROUP );

/**
* Get all defined id types.
* @return list of all id types.
*/
public static List<IdType> getAllIdTypes()
{
return ALL_ID_TYPES;
}

public static IdType forName(IdType.Name typeName)
{
for ( IdType idType : ALL_ID_TYPES )
{
if ( idType.getName().equals( typeName ) )
{
return idType;
}
}
throw new IllegalArgumentException( "IdType with requested name: " + typeName + " does not exist." );
}


private final long max; private final long max;
private final boolean allowAggressiveReuse; private boolean allowAggressiveReuse;
private Name name;


IdType( boolean allowAggressiveReuse ) private IdType( Name name, boolean allowAggressiveReuse )
{ {
this( 32, allowAggressiveReuse ); this( 32, name, allowAggressiveReuse );
} }


IdType( int bits, boolean allowAggressiveReuse ) private IdType( int bits, Name name, boolean allowAggressiveReuse )
{ {
this.allowAggressiveReuse = allowAggressiveReuse; this.allowAggressiveReuse = allowAggressiveReuse;
this.max = (long)Math.pow( 2, bits )-1; this.name = name;
this.max = (long) Math.pow( 2, bits ) - 1;
} }


public long getMaxValue() public long getMaxValue()
{ {
return this.max; return this.max;
} }


public void setAllowAggressiveReuse( boolean allowAggressiveReuse )
{
this.allowAggressiveReuse = allowAggressiveReuse;
}

public boolean allowAggressiveReuse() public boolean allowAggressiveReuse()
{ {
return allowAggressiveReuse; return allowAggressiveReuse;
Expand All @@ -71,4 +105,38 @@ public int getGrabSize()
{ {
return allowAggressiveReuse ? 50000 : 1024; return allowAggressiveReuse ? 50000 : 1024;
} }

public Name getName()
{
return name;
}

@Override
public String toString()
{
return "IdType{" +
"max=" + max +
", allowAggressiveReuse=" + allowAggressiveReuse +
", name=" + name +
'}';
}

public enum Name
{
NODE,
RELATIONSHIP,
PROPERTY,
STRING_BLOCK,
ARRAY_BLOCK,
PROPERTY_KEY_TOKEN,
PROPERTY_KEY_TOKEN_NAME,
RELATIONSHIP_TYPE_TOKEN,
RELATIONSHIP_TYPE_TOKEN_NAME,
LABEL_TOKEN,
LABEL_TOKEN_NAME,
NEOSTORE_BLOCK,
SCHEMA,
NODE_LABELS,
RELATIONSHIP_GROUP
}
} }
Expand Up @@ -82,8 +82,9 @@ public CommunityEditionModule( PlatformModule platformModule )
LifeSupport life = platformModule.life; LifeSupport life = platformModule.life;
GraphDatabaseFacade graphDatabaseFacade = platformModule.graphDatabaseFacade; GraphDatabaseFacade graphDatabaseFacade = platformModule.graphDatabaseFacade;


lockManager = dependencies.satisfyDependency( createLockManager( config, logging ) ); preConfigureEdition(config);


lockManager = dependencies.satisfyDependency( createLockManager( config, logging ) );
idGeneratorFactory = dependencies.satisfyDependency( createIdGeneratorFactory( fileSystem ) ); idGeneratorFactory = dependencies.satisfyDependency( createIdGeneratorFactory( fileSystem ) );


propertyKeyTokenHolder = life.add( dependencies.satisfyDependency( new DelegatingPropertyKeyTokenHolder( propertyKeyTokenHolder = life.add( dependencies.satisfyDependency( new DelegatingPropertyKeyTokenHolder(
Expand Down Expand Up @@ -115,6 +116,11 @@ public CommunityEditionModule( PlatformModule platformModule )
publishEditionInfo( dependencies.resolveDependency( UsageData.class ) ); publishEditionInfo( dependencies.resolveDependency( UsageData.class ) );
} }


protected void preConfigureEdition( Config config )
{
// empty
}

protected ConstraintSemantics createSchemaRuleVerifier() protected ConstraintSemantics createSchemaRuleVerifier()
{ {
return new StandardConstraintSemantics(); return new StandardConstraintSemantics();
Expand Down
Expand Up @@ -20,6 +20,8 @@
package org.neo4j.kernel.impl.store.id; package org.neo4j.kernel.impl.store.id;


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


import org.neo4j.function.Predicate; import org.neo4j.function.Predicate;
import org.neo4j.function.Supplier; import org.neo4j.function.Supplier;
Expand All @@ -34,8 +36,7 @@
*/ */
public class BufferingIdGeneratorFactory extends IdGeneratorFactory.Delegate public class BufferingIdGeneratorFactory extends IdGeneratorFactory.Delegate
{ {
private final BufferingIdGenerator[/*IdType#ordinal as key*/] overriddenIdGenerators = private final Map<IdType, BufferingIdGenerator> overriddenIdGenerators = new HashMap<>();
new BufferingIdGenerator[IdType.values().length];
private Supplier<KernelTransactionsSnapshot> boundaries; private Supplier<KernelTransactionsSnapshot> boundaries;
private Predicate<KernelTransactionsSnapshot> safeThreshold; private Predicate<KernelTransactionsSnapshot> safeThreshold;


Expand All @@ -55,7 +56,7 @@ public boolean test( KernelTransactionsSnapshot snapshot )
return snapshot.allClosed() && eligibleForReuse.isEligible( snapshot ); return snapshot.allClosed() && eligibleForReuse.isEligible( snapshot );
} }
}; };
for ( BufferingIdGenerator generator : overriddenIdGenerators ) for ( BufferingIdGenerator generator : overriddenIdGenerators.values() )
{ {
if ( generator != null ) if ( generator != null )
{ {
Expand Down Expand Up @@ -92,7 +93,7 @@ public IdGenerator open( File filename, int grabSize, IdType idType, long highId
{ {
bufferingGenerator.initialize( boundaries, safeThreshold ); bufferingGenerator.initialize( boundaries, safeThreshold );
} }
overriddenIdGenerators[idType.ordinal()] = bufferingGenerator; overriddenIdGenerators.put( idType, bufferingGenerator );
generator = bufferingGenerator; generator = bufferingGenerator;
} }
return generator; return generator;
Expand All @@ -101,13 +102,13 @@ public IdGenerator open( File filename, int grabSize, IdType idType, long highId
@Override @Override
public IdGenerator get( IdType idType ) public IdGenerator get( IdType idType )
{ {
IdGenerator generator = overriddenIdGenerators[idType.ordinal()]; IdGenerator generator = overriddenIdGenerators.get( idType );
return generator != null ? generator : super.get( idType ); return generator != null ? generator : super.get( idType );
} }


public void maintenance() public void maintenance()
{ {
for ( BufferingIdGenerator generator : overriddenIdGenerators ) for ( BufferingIdGenerator generator : overriddenIdGenerators.values() )
{ {
if ( generator != null ) if ( generator != null )
{ {
Expand All @@ -118,7 +119,7 @@ public void maintenance()


public void clear() public void clear()
{ {
for ( BufferingIdGenerator generator : overriddenIdGenerators ) for ( BufferingIdGenerator generator : overriddenIdGenerators.values() )
{ {
if ( generator != null ) if ( generator != null )
{ {
Expand Down
Expand Up @@ -20,7 +20,7 @@
package org.neo4j.unsafe.impl.batchimport.store; package org.neo4j.unsafe.impl.batchimport.store;


import java.io.File; import java.io.File;
import java.util.EnumMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;


import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.fs.FileSystemAbstraction;
Expand All @@ -37,7 +37,7 @@
*/ */
public class BatchingIdGeneratorFactory implements IdGeneratorFactory public class BatchingIdGeneratorFactory implements IdGeneratorFactory
{ {
private final Map<IdType, IdGenerator> idGenerators = new EnumMap<>( IdType.class ); private final Map<IdType, IdGenerator> idGenerators = new HashMap<>();
private final FileSystemAbstraction fs; private final FileSystemAbstraction fs;


public BatchingIdGeneratorFactory( FileSystemAbstraction fs ) public BatchingIdGeneratorFactory( FileSystemAbstraction fs )
Expand Down
Expand Up @@ -20,7 +20,7 @@
package org.neo4j.kernel.impl.core; package org.neo4j.kernel.impl.core;


import java.io.File; import java.io.File;
import java.util.EnumMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;


Expand All @@ -33,7 +33,7 @@


public class JumpingIdGeneratorFactory implements IdGeneratorFactory public class JumpingIdGeneratorFactory implements IdGeneratorFactory
{ {
private final Map<IdType, IdGenerator> generators = new EnumMap<>( IdType.class ); private final Map<IdType,IdGenerator> generators = new HashMap<>();
private final IdGenerator forTheRest = new EphemeralIdGenerator( null ); private final IdGenerator forTheRest = new EphemeralIdGenerator( null );


private final int sizePerJump; private final int sizePerJump;
Expand Down
Expand Up @@ -56,7 +56,6 @@
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;

import static org.neo4j.graphdb.DynamicRelationshipType.withName; import static org.neo4j.graphdb.DynamicRelationshipType.withName;
import static org.neo4j.helpers.collection.IteratorUtil.lastOrNull; import static org.neo4j.helpers.collection.IteratorUtil.lastOrNull;
import static org.neo4j.io.fs.FileUtils.deleteRecursively; import static org.neo4j.io.fs.FileUtils.deleteRecursively;
Expand Down Expand Up @@ -542,7 +541,7 @@ public void testUnsignedId()
@Test @Test
public void makeSureIdCapacityCannotBeExceeded() throws Exception public void makeSureIdCapacityCannotBeExceeded() throws Exception
{ {
for ( IdType type : IdType.values() ) for ( IdType type : IdType.getAllIdTypes() )
{ {
makeSureIdCapacityCannotBeExceeded( type ); makeSureIdCapacityCannotBeExceeded( type );
} }
Expand Down

0 comments on commit e8f870f

Please sign in to comment.