Skip to content

Commit

Permalink
Avoid loading and looking up Locks factory for each database.
Browse files Browse the repository at this point in the history
Extract factories for various locks construction from CommunityEditionModule.
Extract interface for LocksFactory into separate class.
  • Loading branch information
MishaDemianenko committed Aug 21, 2018
1 parent 2c254b7 commit 90b28be
Show file tree
Hide file tree
Showing 12 changed files with 328 additions and 60 deletions.
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2002-2018 "Neo4j,"
* Neo4j Sweden AB [http://neo4j.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.locking;

import org.neo4j.helpers.Service;

/**
* Factory for lock managers that can be loaded over service loading.
*/
public abstract class DynamicLocksFactory extends Service implements LocksFactory
{
public DynamicLocksFactory( String key, String... altKeys )
{
super( key, altKeys );
}
}
Expand Up @@ -19,11 +19,8 @@
*/ */
package org.neo4j.kernel.impl.locking; package org.neo4j.kernel.impl.locking;


import java.time.Clock;
import java.util.stream.Stream; import java.util.stream.Stream;


import org.neo4j.helpers.Service;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.storageengine.api.lock.AcquireLockTimeoutException; import org.neo4j.storageengine.api.lock.AcquireLockTimeoutException;
import org.neo4j.storageengine.api.lock.LockTracer; import org.neo4j.storageengine.api.lock.LockTracer;
import org.neo4j.storageengine.api.lock.ResourceLocker; import org.neo4j.storageengine.api.lock.ResourceLocker;
Expand Down Expand Up @@ -51,15 +48,6 @@
*/ */
public interface Locks public interface Locks
{ {
abstract class Factory extends Service
{
public Factory( String key, String... altKeys )
{
super( key, altKeys );
}

public abstract Locks newInstance( Config config, Clock clocks, ResourceType[] resourceTypes );
}


/** For introspection and debugging. */ /** For introspection and debugging. */
interface Visitor interface Visitor
Expand Down
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2002-2018 "Neo4j,"
* Neo4j Sweden AB [http://neo4j.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.locking;

import java.time.Clock;

import org.neo4j.kernel.configuration.Config;
import org.neo4j.storageengine.api.lock.ResourceType;

public interface LocksFactory
{
Locks newInstance( Config config, Clock clock, ResourceType[] resourceTypes );
}
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2002-2018 "Neo4j,"
* Neo4j Sweden AB [http://neo4j.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.locking.community;

import java.time.Clock;

import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.impl.locking.Locks;
import org.neo4j.kernel.impl.locking.LocksFactory;
import org.neo4j.storageengine.api.lock.ResourceType;

public class CommunityLocksFactory implements LocksFactory
{
@Override
public Locks newInstance( Config config, Clock clock, ResourceType[] resourceTypes )
{
return new CommunityLockManger( config, clock );
}
}
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2002-2018 "Neo4j,"
* Neo4j Sweden AB [http://neo4j.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.locking.community;

import org.junit.jupiter.api.Test;

import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.impl.locking.Locks;
import org.neo4j.kernel.impl.locking.ResourceTypes;
import org.neo4j.time.Clocks;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.jupiter.api.Assertions.assertNotSame;

class CommunityLocksFactoryTest
{

@Test
void createDifferentCommunityLockManagers()
{
CommunityLocksFactory factory = new CommunityLocksFactory();
Locks locks1 = factory.newInstance( Config.defaults(), Clocks.systemClock(), ResourceTypes.values() );
Locks locks2 = factory.newInstance( Config.defaults(), Clocks.systemClock(), ResourceTypes.values() );
assertNotSame( locks1, locks2 );
assertThat( locks1, instanceOf( CommunityLockManger.class ) );
assertThat( locks2, instanceOf( CommunityLockManger.class ) );
}
}
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2002-2018 "Neo4j,"
* Neo4j Sweden AB [http://neo4j.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.graphdb.factory;

import java.time.Clock;

import org.neo4j.graphdb.factory.module.CommunityEditionModule;
import org.neo4j.helpers.Service;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.impl.locking.DynamicLocksFactory;
import org.neo4j.kernel.impl.locking.Locks;
import org.neo4j.kernel.impl.locking.LocksFactory;
import org.neo4j.kernel.impl.locking.ResourceTypes;
import org.neo4j.kernel.impl.locking.community.CommunityLocksFactory;
import org.neo4j.kernel.impl.logging.LogService;

public final class EditionLocksFactories
{
public static Locks createLockManager( LocksFactory locksFactory, Config config, Clock clock )
{
return locksFactory.newInstance( config, clock, ResourceTypes.values() );
}

public static LocksFactory createLockFactory( Config config, LogService logging )
{
String key = config.get( GraphDatabaseSettings.lock_manager );
for ( DynamicLocksFactory candidate : Service.load( DynamicLocksFactory.class ) )
{
String candidateId = candidate.getKeys().iterator().next();
if ( key.equals( candidateId ) )
{
return candidate;
}
else if ( "".equals( key ) )
{
logging.getInternalLog( CommunityEditionModule.class )
.info( "No locking implementation specified, defaulting to '" + candidateId + "'" );
return candidate;
}
}

if ( "community".equals( key ) )
{
return new CommunityLocksFactory();
}
else if ( "".equals( key ) )
{
logging.getInternalLog( CommunityEditionModule.class )
.info( "No locking implementation specified, defaulting to 'community'" );
return new CommunityLocksFactory();
}

throw new IllegalArgumentException( "No lock manager found with the name '" + key + "'." );
}
}
Expand Up @@ -20,12 +20,10 @@
package org.neo4j.graphdb.factory.module; package org.neo4j.graphdb.factory.module;


import java.io.File; import java.io.File;
import java.time.Clock;
import java.util.function.Predicate; import java.util.function.Predicate;


import org.neo4j.function.Predicates; import org.neo4j.function.Predicates;
import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.helpers.Service;
import org.neo4j.internal.kernel.api.exceptions.KernelException; import org.neo4j.internal.kernel.api.exceptions.KernelException;
import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.io.pagecache.IOLimiter; import org.neo4j.io.pagecache.IOLimiter;
Expand All @@ -52,10 +50,9 @@
import org.neo4j.kernel.impl.factory.ReadOnly; import org.neo4j.kernel.impl.factory.ReadOnly;
import org.neo4j.kernel.impl.index.IndexConfigStore; import org.neo4j.kernel.impl.index.IndexConfigStore;
import org.neo4j.kernel.impl.locking.Locks; import org.neo4j.kernel.impl.locking.Locks;
import org.neo4j.kernel.impl.locking.ResourceTypes; import org.neo4j.kernel.impl.locking.LocksFactory;
import org.neo4j.kernel.impl.locking.SimpleStatementLocksFactory; import org.neo4j.kernel.impl.locking.SimpleStatementLocksFactory;
import org.neo4j.kernel.impl.locking.StatementLocksFactory; import org.neo4j.kernel.impl.locking.StatementLocksFactory;
import org.neo4j.kernel.impl.locking.community.CommunityLockManger;
import org.neo4j.kernel.impl.logging.LogService; import org.neo4j.kernel.impl.logging.LogService;
import org.neo4j.kernel.impl.proc.Procedures; import org.neo4j.kernel.impl.proc.Procedures;
import org.neo4j.kernel.impl.store.id.DefaultIdGeneratorFactory; import org.neo4j.kernel.impl.store.id.DefaultIdGeneratorFactory;
Expand All @@ -70,6 +67,9 @@
import org.neo4j.kernel.lifecycle.LifeSupport; import org.neo4j.kernel.lifecycle.LifeSupport;
import org.neo4j.udc.UsageData; import org.neo4j.udc.UsageData;


import static org.neo4j.graphdb.factory.EditionLocksFactories.createLockFactory;
import static org.neo4j.graphdb.factory.EditionLocksFactories.createLockManager;

/** /**
* This implementation of {@link EditionModule} creates the implementations of services * This implementation of {@link EditionModule} creates the implementations of services
* that are specific to the Community edition. * that are specific to the Community edition.
Expand Down Expand Up @@ -97,7 +97,8 @@ public CommunityEditionModule( PlatformModule platformModule )
dependencies.satisfyDependency( dependencies.satisfyDependency(
SslPolicyLoader.create( config, logging.getInternalLogProvider() ) ); // for bolt and web server SslPolicyLoader.create( config, logging.getInternalLogProvider() ) ); // for bolt and web server


locksSupplier = () -> createLockManager( config, platformModule.clock, logging ); LocksFactory lockFactory = createLockFactory( config, logging );
locksSupplier = () -> createLockManager( lockFactory, config, platformModule.clock );
statementLocksFactoryProvider = locks -> createStatementLocksFactory( locks, config, logging ); statementLocksFactoryProvider = locks -> createStatementLocksFactory( locks, config, logging );


idTypeConfigurationProvider = createIdTypeConfigurationProvider( config ); idTypeConfigurationProvider = createIdTypeConfigurationProvider( config );
Expand Down Expand Up @@ -215,38 +216,6 @@ protected IdGeneratorFactory createIdGeneratorFactory( FileSystemAbstraction fs,
return new DefaultIdGeneratorFactory( fs, idTypeConfigurationProvider ); return new DefaultIdGeneratorFactory( fs, idTypeConfigurationProvider );
} }


public static Locks createLockManager( Config config, Clock clock, LogService logging )
{
String key = config.get( GraphDatabaseSettings.lock_manager );
for ( Locks.Factory candidate : Service.load( Locks.Factory.class ) )
{
String candidateId = candidate.getKeys().iterator().next();
if ( key.equals( candidateId ) )
{
return candidate.newInstance( config, clock, ResourceTypes.values() );
}
else if ( key.equals( "" ) )
{
logging.getInternalLog( CommunityEditionModule.class )
.info( "No locking implementation specified, defaulting to '" + candidateId + "'" );
return candidate.newInstance( config, clock, ResourceTypes.values() );
}
}

if ( key.equals( "community" ) )
{
return new CommunityLockManger( config, clock );
}
else if ( key.equals( "" ) )
{
logging.getInternalLog( CommunityEditionModule.class )
.info( "No locking implementation specified, defaulting to 'community'" );
return new CommunityLockManger( config, clock );
}

throw new IllegalArgumentException( "No lock manager found with the name '" + key + "'." );
}

protected TransactionHeaderInformationFactory createHeaderInformationFactory() protected TransactionHeaderInformationFactory createHeaderInformationFactory()
{ {
return TransactionHeaderInformationFactory.DEFAULT; return TransactionHeaderInformationFactory.DEFAULT;
Expand Down

0 comments on commit 90b28be

Please sign in to comment.