
org.neo4j.kernel.InternalAbstractGraphDatabase Maven / Gradle / Ivy
/**
* Copyright (c) 2002-2013 "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 .
*/
package org.neo4j.kernel;
import static java.lang.String.format;
import static org.slf4j.impl.StaticLoggerBinder.getSingleton;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import javax.transaction.SystemException;
import javax.transaction.TransactionManager;
import ch.qos.logback.classic.LoggerContext;
import org.neo4j.graphdb.DependencyResolver;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.NotFoundException;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.TransactionFailureException;
import org.neo4j.graphdb.config.Setting;
import org.neo4j.graphdb.event.KernelEventHandler;
import org.neo4j.graphdb.event.TransactionEventHandler;
import org.neo4j.graphdb.factory.GraphDatabaseSetting;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.graphdb.index.IndexManager;
import org.neo4j.graphdb.index.IndexProvider;
import org.neo4j.graphdb.index.IndexProviderKernelExtensionFactory;
import org.neo4j.graphdb.index.IndexProviders;
import org.neo4j.helpers.DaemonThreadFactory;
import org.neo4j.helpers.Function;
import org.neo4j.helpers.Service;
import org.neo4j.helpers.Settings;
import org.neo4j.helpers.collection.Iterables;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.configuration.ConfigurationChange;
import org.neo4j.kernel.configuration.ConfigurationChangeListener;
import org.neo4j.kernel.extension.KernelExtensionFactory;
import org.neo4j.kernel.extension.KernelExtensions;
import org.neo4j.kernel.guard.Guard;
import org.neo4j.kernel.impl.cache.Cache;
import org.neo4j.kernel.impl.cache.CacheProvider;
import org.neo4j.kernel.impl.cache.MonitorGc;
import org.neo4j.kernel.impl.core.Caches;
import org.neo4j.kernel.impl.core.DefaultCaches;
import org.neo4j.kernel.impl.core.DefaultRelationshipTypeCreator;
import org.neo4j.kernel.impl.core.KernelPanicEventGenerator;
import org.neo4j.kernel.impl.core.NodeImpl;
import org.neo4j.kernel.impl.core.NodeManager;
import org.neo4j.kernel.impl.core.NodeProxy;
import org.neo4j.kernel.impl.core.PropertyIndexManager;
import org.neo4j.kernel.impl.core.ReadOnlyNodeManager;
import org.neo4j.kernel.impl.core.RelationshipImpl;
import org.neo4j.kernel.impl.core.RelationshipProxy;
import org.neo4j.kernel.impl.core.RelationshipTypeCreator;
import org.neo4j.kernel.impl.core.RelationshipTypeHolder;
import org.neo4j.kernel.impl.core.TransactionEventsSyncHook;
import org.neo4j.kernel.impl.core.TxEventSyncHookFactory;
import org.neo4j.kernel.impl.index.IndexStore;
import org.neo4j.kernel.impl.nioneo.store.DefaultWindowPoolFactory;
import org.neo4j.kernel.impl.nioneo.store.FileSystemAbstraction;
import org.neo4j.kernel.impl.nioneo.store.StoreFactory;
import org.neo4j.kernel.impl.nioneo.store.StoreId;
import org.neo4j.kernel.impl.nioneo.xa.NeoStoreXaDataSource;
import org.neo4j.kernel.impl.nioneo.xa.NioNeoDbPersistenceSource;
import org.neo4j.kernel.impl.persistence.PersistenceManager;
import org.neo4j.kernel.impl.persistence.PersistenceSource;
import org.neo4j.kernel.impl.transaction.AbstractTransactionManager;
import org.neo4j.kernel.impl.transaction.LockManager;
import org.neo4j.kernel.impl.transaction.LockManagerImpl;
import org.neo4j.kernel.impl.transaction.LockType;
import org.neo4j.kernel.impl.transaction.RagManager;
import org.neo4j.kernel.impl.transaction.ReadOnlyTxManager;
import org.neo4j.kernel.impl.transaction.TransactionManagerProvider;
import org.neo4j.kernel.impl.transaction.TransactionStateFactory;
import org.neo4j.kernel.impl.transaction.TxHook;
import org.neo4j.kernel.impl.transaction.TxManager;
import org.neo4j.kernel.impl.transaction.XaDataSourceManager;
import org.neo4j.kernel.impl.transaction.xaframework.DefaultLogBufferFactory;
import org.neo4j.kernel.impl.transaction.xaframework.ForceMode;
import org.neo4j.kernel.impl.transaction.xaframework.LogBufferFactory;
import org.neo4j.kernel.impl.transaction.xaframework.LogPruneStrategies;
import org.neo4j.kernel.impl.transaction.xaframework.RecoveryVerifier;
import org.neo4j.kernel.impl.transaction.xaframework.TransactionInterceptorProvider;
import org.neo4j.kernel.impl.transaction.xaframework.TxIdGenerator;
import org.neo4j.kernel.impl.transaction.xaframework.XaFactory;
import org.neo4j.kernel.impl.util.StringLogger;
import org.neo4j.kernel.info.DiagnosticsManager;
import org.neo4j.kernel.info.JvmChecker;
import org.neo4j.kernel.info.JvmMetadataRepository;
import org.neo4j.kernel.lifecycle.LifeSupport;
import org.neo4j.kernel.lifecycle.Lifecycle;
import org.neo4j.kernel.lifecycle.LifecycleAdapter;
import org.neo4j.kernel.lifecycle.LifecycleException;
import org.neo4j.kernel.lifecycle.LifecycleListener;
import org.neo4j.kernel.lifecycle.LifecycleStatus;
import org.neo4j.kernel.logging.ClassicLoggingService;
import org.neo4j.kernel.logging.LogbackService;
import org.neo4j.kernel.logging.Logging;
import org.neo4j.tooling.GlobalGraphOperations;
/**
* Base implementation of GraphDatabaseService. Responsible for creating services, handling dependencies between them,
* and lifecycle management of these.
*/
public abstract class InternalAbstractGraphDatabase
extends AbstractGraphDatabase implements GraphDatabaseService, GraphDatabaseAPI
{
public static class Configuration
{
public static final Setting read_only = GraphDatabaseSettings.read_only;
public static final Setting use_memory_mapped_buffers =
GraphDatabaseSettings.use_memory_mapped_buffers;
public static final Setting execution_guard_enabled = GraphDatabaseSettings.execution_guard_enabled;
public static final GraphDatabaseSettings.CacheTypeSetting cache_type = GraphDatabaseSettings.cache_type;
public static final Setting load_kernel_extensions = GraphDatabaseSettings.load_kernel_extensions;
public static final Setting ephemeral = new GraphDatabaseSetting.BooleanSetting(
Settings.setting("ephemeral", Settings.BOOLEAN, Settings.FALSE ) );
public static final Setting store_dir = GraphDatabaseSettings.store_dir;
public static final Setting neo_store = GraphDatabaseSettings.neo_store;
public static final Setting logical_log = GraphDatabaseSettings.logical_log;
}
private static final long MAX_NODE_ID = IdType.NODE.getMaxValue();
private static final long MAX_RELATIONSHIP_ID = IdType.RELATIONSHIP.getMaxValue();
protected File storeDir;
protected Map params;
private TransactionInterceptorProviders transactionInterceptorProviders;
private final KernelExtensions kernelExtensions;
protected StoreId storeId;
private final TransactionBuilder defaultTxBuilder = new TransactionBuilderImpl( this, ForceMode.forced );
protected Config config;
protected DependencyResolver dependencyResolver;
protected Logging logging;
protected StringLogger msgLog;
protected StoreLockerLifecycleAdapter storeLocker;
protected KernelEventHandlers kernelEventHandlers;
protected TransactionEventHandlers transactionEventHandlers;
protected RelationshipTypeHolder relationshipTypeHolder;
protected NodeManager nodeManager;
protected IndexManagerImpl indexManager;
protected KernelPanicEventGenerator kernelPanicEventGenerator;
protected TxHook txHook;
protected FileSystemAbstraction fileSystem;
protected XaDataSourceManager xaDataSourceManager;
protected LockManager lockManager;
protected IdGeneratorFactory idGeneratorFactory;
protected RelationshipTypeCreator relationshipTypeCreator;
protected NioNeoDbPersistenceSource persistenceSource;
protected TxEventSyncHookFactory syncHook;
protected PersistenceManager persistenceManager;
protected PropertyIndexManager propertyIndexManager;
protected IndexStore indexStore;
protected LogBufferFactory logBufferFactory;
protected AbstractTransactionManager txManager;
protected TxIdGenerator txIdGenerator;
protected StoreFactory storeFactory;
protected XaFactory xaFactory;
protected DiagnosticsManager diagnosticsManager;
protected NeoStoreXaDataSource neoDataSource;
protected RecoveryVerifier recoveryVerifier;
protected Guard guard;
protected NodeAutoIndexerImpl nodeAutoIndexer;
protected RelationshipAutoIndexerImpl relAutoIndexer;
protected KernelData extensions;
protected Caches caches;
protected final LifeSupport life = new LifeSupport();
private final Map cacheProviders;
protected TransactionStateFactory stateFactory;
protected InternalAbstractGraphDatabase( String storeDir, Map params,
Iterable> settingsClasses,
Iterable indexProviders,
Iterable> kernelExtensions,
Iterable cacheProviders,
Iterable transactionInterceptorProviders )
{
this.params = params;
dependencyResolver = new DependencyResolverImpl();
// Setup configuration
params.put( Configuration.store_dir.name(), storeDir );
// SPI - provided services
this.cacheProviders = mapCacheProviders( cacheProviders );
config = new Config( params, getSettingsClasses( settingsClasses, kernelExtensions, cacheProviders ) );
// Convert IndexProviders into KernelExtensionFactories
// Remove this when the deprecated IndexProvider is removed
Iterable> indexProviderKernelExtensions = Iterables.map( new Function>()
{
@Override
public KernelExtensionFactory> apply( IndexProvider from )
{
return new IndexProviderKernelExtensionFactory( from );
}
}, indexProviders );
kernelExtensions = Iterables.concat( kernelExtensions, indexProviderKernelExtensions );
this.kernelExtensions = new KernelExtensions( kernelExtensions, config, dependencyResolver );
this.transactionInterceptorProviders = new TransactionInterceptorProviders( transactionInterceptorProviders,
dependencyResolver );
this.storeDir = config.get( Configuration.store_dir );
}
private Map mapCacheProviders( Iterable cacheProviders )
{
Map map = new HashMap();
for ( CacheProvider provider : cacheProviders )
{
map.put( provider.getName(), provider );
}
return map;
}
protected void run()
{
create();
try
{
registerRecovery();
life.start();
if ( txManager.getRecoveryError() != null )
{
throw txManager.getRecoveryError();
}
}
catch ( final Throwable throwable )
{
StringBuilder msg = new StringBuilder( );
msg.append( "Startup failed" );
Throwable temporaryThrowable = throwable;
while (temporaryThrowable != null)
{
msg.append( ": " ).append( temporaryThrowable.getMessage() );
temporaryThrowable = temporaryThrowable.getCause();
}
msgLog.logMessage( msg.toString() );
shutdown();
throw new RuntimeException( throwable );
}
}
protected void registerRecovery()
{
life.addLifecycleListener( new LifecycleListener()
{
@Override
public void notifyStatusChanged( Object instance, LifecycleStatus from, LifecycleStatus to )
{
// TODO do not explicitly depend on order of start() calls in txManager and XaDatasourceManager
// use two booleans instead
if ( instance instanceof KernelExtensions && to.equals( LifecycleStatus.STARTED ) && txManager
instanceof TxManager )
{
InternalAbstractGraphDatabase.this.doAfterRecoveryAndStartup();
}
}
} );
}
protected void doAfterRecoveryAndStartup()
{
NeoStoreXaDataSource neoStoreDataSource = xaDataSourceManager.getNeoStoreDataSource();
storeId = neoStoreDataSource.getStoreId();
KernelDiagnostics.register( diagnosticsManager, InternalAbstractGraphDatabase.this,
neoStoreDataSource );
}
protected void create()
{
fileSystem = createFileSystemAbstraction();
// Create logger
this.logging = createLogging();
// Apply autoconfiguration for memory settings
AutoConfigurator autoConfigurator = new AutoConfigurator( fileSystem,
config.get( NeoStoreXaDataSource.Configuration.store_dir ),
GraphDatabaseSettings.UseMemoryMappedBuffers.shouldMemoryMap(
config.get( Configuration.use_memory_mapped_buffers ) ) );
if (config.get( GraphDatabaseSettings.dump_configuration ))
{
System.out.println( autoConfigurator.getNiceMemoryInformation() );
}
Map configParams = config.getParams();
Map autoConfiguration = autoConfigurator.configure();
for ( Map.Entry autoConfig : autoConfiguration.entrySet() )
{
// Don't override explicit settings
String key = autoConfig.getKey();
if ( !params.containsKey( key ) )
{
configParams.put( key, autoConfig.getValue() );
}
}
config.applyChanges( configParams );
this.msgLog = logging.getMessagesLog( getClass() );
config.setLogger( msgLog );
this.storeLocker = life.add(new StoreLockerLifecycleAdapter(
new StoreLocker( config, fileSystem ), storeDir ));
new JvmChecker(msgLog, new JvmMetadataRepository() ).checkJvmCompatibilityAndIssueWarning();
// Instantiate all services - some are overridable by subclasses
boolean readOnly = config.get( Configuration.read_only );
String cacheTypeName = config.get( Configuration.cache_type );
CacheProvider cacheProvider = cacheProviders.get( cacheTypeName );
if ( cacheProvider == null )
{
throw new IllegalArgumentException( "No cache type '" + cacheTypeName + "'" );
}
kernelEventHandlers = new KernelEventHandlers();
caches = createCaches();
diagnosticsManager = life.add( new DiagnosticsManager( logging.getMessagesLog( DiagnosticsManager.class ) ) );
kernelPanicEventGenerator = new KernelPanicEventGenerator( kernelEventHandlers );
xaDataSourceManager = life.add( createXaDataSourceManager() );
txHook = createTxHook();
guard = config.get( Configuration.execution_guard_enabled ) ? new Guard( msgLog ) : null;
stateFactory = createTransactionStateFactory();
if ( readOnly )
{
txManager = new ReadOnlyTxManager( xaDataSourceManager, logging.getMessagesLog( ReadOnlyTxManager.class ) );
}
else
{
String serviceName = config.get( GraphDatabaseSettings.tx_manager_impl );
if ( GraphDatabaseSettings.tx_manager_impl.getDefaultValue().equals( serviceName ) )
{
txManager = new TxManager( this.storeDir, xaDataSourceManager, kernelPanicEventGenerator,
logging.getMessagesLog( TxManager.class ), fileSystem, stateFactory );
}
else
{
TransactionManagerProvider provider;
provider = Service.load( TransactionManagerProvider.class, serviceName );
if ( provider == null )
{
throw new IllegalStateException( "Unknown transaction manager implementation: "
+ serviceName );
}
txManager = provider.loadTransactionManager( this.storeDir.getPath(), xaDataSourceManager,
kernelPanicEventGenerator, txHook, logging.getMessagesLog( AbstractTransactionManager.class ),
fileSystem, stateFactory );
}
}
life.add( txManager );
transactionEventHandlers = new TransactionEventHandlers( txManager );
txIdGenerator = life.add( createTxIdGenerator() );
lockManager = createLockManager();
idGeneratorFactory = createIdGeneratorFactory();
relationshipTypeCreator = createRelationshipTypeCreator();
persistenceSource = life.add( new NioNeoDbPersistenceSource( xaDataSourceManager ) );
syncHook = new DefaultTxEventSyncHookFactory();
persistenceManager = new PersistenceManager( logging.getMessagesLog( PersistenceManager.class ), txManager,
persistenceSource, syncHook );
propertyIndexManager = life.add( new PropertyIndexManager( persistenceManager, persistenceSource ) );
relationshipTypeHolder = life.add( new RelationshipTypeHolder( txManager,
persistenceManager, persistenceSource, relationshipTypeCreator ) );
caches.configure( cacheProvider, config );
Cache nodeCache = diagnosticsManager.tryAppendProvider( caches.node() );
Cache relCache = diagnosticsManager.tryAppendProvider( caches.relationship() );
nodeManager = guard != null ?
createGuardedNodeManager( readOnly, cacheProvider, nodeCache, relCache ) :
createNodeManager( readOnly, cacheProvider, nodeCache, relCache );
stateFactory.setDependencies( lockManager, propertyIndexManager, nodeManager, txHook, txIdGenerator );
indexStore = life.add( new IndexStore( this.storeDir, fileSystem ) );
diagnosticsManager.prependProvider( config );
// Config can auto-configure memory mapping settings and what not, so reassign params
// after we've instantiated Config.
params = config.getParams();
/*
* LogBufferFactory needs access to the parameters so it has to be added after the default and
* user supplied configurations are consolidated
*/
logBufferFactory = new DefaultLogBufferFactory();
extensions = life.add( createKernelData() );
if ( config.get( Configuration.load_kernel_extensions ) )
{
// kernelExtensionLoader = new DefaultKernelExtensionLoader( extensions );
life.add( kernelExtensions );
}
indexManager = new IndexManagerImpl( config, indexStore, xaDataSourceManager, txManager, this );
nodeAutoIndexer = life.add( new NodeAutoIndexerImpl( config, indexManager, nodeManager ) );
relAutoIndexer = life.add( new RelationshipAutoIndexerImpl( config, indexManager, nodeManager ) );
// TODO This cyclic dependency should be resolved
indexManager.setNodeAutoIndexer( nodeAutoIndexer );
indexManager.setRelAutoIndexer( relAutoIndexer );
recoveryVerifier = createRecoveryVerifier();
// Factories for things that needs to be created later
storeFactory = createStoreFactory();
String keepLogicalLogsConfig = config.get( GraphDatabaseSettings.keep_logical_logs );
xaFactory = new XaFactory( config, txIdGenerator, txManager, logBufferFactory, fileSystem,
logging, recoveryVerifier, LogPruneStrategies.fromConfigValue(
fileSystem, keepLogicalLogsConfig ) );
createNeoDataSource();
life.add( new MonitorGc( config, msgLog ) );
// This is how we lock the entire database to avoid threads using it during lifecycle events
life.add( new DatabaseAvailability() );
// Kernel event handlers should be the very last, i.e. very first to receive shutdown events
life.add( kernelEventHandlers );
life.add( nodeManager );
// TODO This is probably too coarse-grained and we should have some strategy per user of config instead
life.add( new ConfigurationChangedRestarter() );
}
protected TransactionStateFactory createTransactionStateFactory()
{
return new TransactionStateFactory( logging );
}
protected XaDataSourceManager createXaDataSourceManager()
{
return new XaDataSourceManager( logging.getMessagesLog( XaDataSourceManager.class ) );
}
@Override
public DependencyResolver getDependencyResolver()
{
return dependencyResolver;
}
protected RelationshipTypeCreator createRelationshipTypeCreator()
{
return new DefaultRelationshipTypeCreator();
}
private NodeManager createNodeManager( final boolean readOnly, final CacheProvider cacheType,
Cache nodeCache, Cache relCache )
{
if ( readOnly )
{
return new ReadOnlyNodeManager( config, logging.getMessagesLog( NodeManager.class ), this, txManager, persistenceManager,
persistenceSource, relationshipTypeHolder, cacheType, propertyIndexManager, createNodeLookup(),
createRelationshipLookups(), nodeCache, relCache, xaDataSourceManager );
}
return new NodeManager( config, logging.getMessagesLog( NodeManager.class ), this, txManager, persistenceManager,
persistenceSource, relationshipTypeHolder, cacheType, propertyIndexManager, createNodeLookup(),
createRelationshipLookups(), nodeCache, relCache, xaDataSourceManager );
}
private NodeManager createGuardedNodeManager( final boolean readOnly, final CacheProvider cacheType,
Cache nodeCache, Cache relCache )
{
if ( readOnly )
{
return new ReadOnlyNodeManager( config, logging.getMessagesLog( NodeManager.class ), this, txManager, persistenceManager,
persistenceSource, relationshipTypeHolder, cacheType, propertyIndexManager, createNodeLookup(),
createRelationshipLookups(), nodeCache, relCache, xaDataSourceManager )
{
@Override
protected Node getNodeByIdOrNull( final long nodeId )
{
guard.check();
return super.getNodeByIdOrNull( nodeId );
}
@Override
public NodeImpl getNodeForProxy( final long nodeId, final LockType lock )
{
guard.check();
return super.getNodeForProxy( nodeId, lock );
}
@Override
public RelationshipImpl getRelationshipForProxy( final long relId, final LockType lock )
{
guard.check();
return super.getRelationshipForProxy( relId, lock );
}
@Override
protected Relationship getRelationshipByIdOrNull( final long relId )
{
guard.check();
return super.getRelationshipByIdOrNull( relId );
}
@Override
public Node createNode()
{
guard.check();
return super.createNode();
}
@Override
public Relationship createRelationship( final Node startNodeProxy, final NodeImpl startNode,
final Node endNode, final RelationshipType type )
{
guard.check();
return super.createRelationship( startNodeProxy, startNode, endNode, type );
}
};
}
return new NodeManager( config, logging.getMessagesLog( NodeManager.class ), this, txManager, persistenceManager,
persistenceSource, relationshipTypeHolder, cacheType, propertyIndexManager, createNodeLookup(),
createRelationshipLookups(), nodeCache, relCache, xaDataSourceManager )
{
@Override
protected Node getNodeByIdOrNull( final long nodeId )
{
guard.check();
return super.getNodeByIdOrNull( nodeId );
}
@Override
public NodeImpl getNodeForProxy( final long nodeId, final LockType lock )
{
guard.check();
return super.getNodeForProxy( nodeId, lock );
}
@Override
public RelationshipImpl getRelationshipForProxy( final long relId, final LockType lock )
{
guard.check();
return super.getRelationshipForProxy( relId, lock );
}
@Override
protected Relationship getRelationshipByIdOrNull( final long relId )
{
guard.check();
return super.getRelationshipByIdOrNull( relId );
}
@Override
public Node createNode()
{
guard.check();
return super.createNode();
}
@Override
public Relationship createRelationship( final Node startNodeProxy, final NodeImpl startNode,
final Node endNode, final RelationshipType type )
{
guard.check();
return super.createRelationship( startNodeProxy, startNode, endNode, type );
}
};
}
@Override
public void shutdown()
{
try
{
life.shutdown();
}
catch ( LifecycleException throwable )
{
msgLog.logMessage( "Shutdown failed", throwable );
}
}
protected StoreFactory createStoreFactory()
{
return new StoreFactory( config, idGeneratorFactory, new DefaultWindowPoolFactory(), fileSystem,
logging.getMessagesLog( StoreFactory.class ), txHook );
}
protected RecoveryVerifier createRecoveryVerifier()
{
return RecoveryVerifier.ALWAYS_VALID;
}
protected KernelData createKernelData()
{
return new DefaultKernelData( config, this );
}
protected TxIdGenerator createTxIdGenerator()
{
return TxIdGenerator.DEFAULT;
}
protected Caches createCaches()
{
return new DefaultCaches( msgLog );
}
protected RelationshipProxy.RelationshipLookups createRelationshipLookups()
{
return new RelationshipProxy.RelationshipLookups()
{
@Override
public Node lookupNode( long nodeId )
{
// TODO: add CAS check here for requests not in tx to guard against shutdown
return nodeManager.getNodeById( nodeId );
}
@Override
public RelationshipImpl lookupRelationship( long relationshipId )
{
// TODO: add CAS check here for requests not in tx to guard against shutdown
return nodeManager.getRelationshipForProxy( relationshipId, null );
}
@Override
public RelationshipImpl lookupRelationship( long relationshipId, LockType lock )
{
return nodeManager.getRelationshipForProxy( relationshipId, lock );
}
@Override
public GraphDatabaseService getGraphDatabaseService()
{
return InternalAbstractGraphDatabase.this;
}
@Override
public NodeManager getNodeManager()
{
return nodeManager;
}
@Override
public Node newNodeProxy( long nodeId )
{
// only used by relationship already checked as valid in cache
return nodeManager.newNodeProxyById( nodeId );
}
};
}
protected NodeProxy.NodeLookup createNodeLookup()
{
return new NodeProxy.NodeLookup()
{
@Override
public NodeImpl lookup( long nodeId )
{
// TODO: add CAS check here for requests not in tx to guard against shutdown
return nodeManager.getNodeForProxy( nodeId, null );
}
@Override
public NodeImpl lookup( long nodeId, LockType lock )
{
return nodeManager.getNodeForProxy( nodeId, lock );
}
@Override
public GraphDatabaseService getGraphDatabase()
{
// TODO This should be wrapped as well
return InternalAbstractGraphDatabase.this;
}
@Override
public NodeManager getNodeManager()
{
return nodeManager;
}
};
}
protected TxHook createTxHook()
{
return new DefaultTxHook();
}
protected FileSystemAbstraction createFileSystemAbstraction()
{
return new DefaultFileSystemAbstraction();
}
protected IdGeneratorFactory createIdGeneratorFactory()
{
return new DefaultIdGeneratorFactory();
}
protected LockManager createLockManager()
{
return new LockManagerImpl( new RagManager( txManager ) );
}
protected Logging createLogging()
{
Logging logging;
try
{
getClass().getClassLoader().loadClass( "ch.qos.logback.classic.LoggerContext" );
logging = new LogbackService( config, (LoggerContext) getSingleton().getLoggerFactory() );
}
catch ( Exception e )
{
logging = new ClassicLoggingService( config );
}
return life.add( logging );
}
protected void createNeoDataSource()
{
// Create DataSource
try
{
// TODO IO stuff should be done in lifecycle. Refactor!
neoDataSource = new NeoStoreXaDataSource( config,
storeFactory, lockManager, logging.getMessagesLog( NeoStoreXaDataSource.class ),
xaFactory, stateFactory, transactionInterceptorProviders, dependencyResolver );
xaDataSourceManager.registerDataSource( neoDataSource );
}
catch ( IOException e )
{
throw new IllegalStateException( "Could not create Neo XA datasource", e );
}
}
@Override
public final String getStoreDir()
{
return storeDir.getPath();
}
@Override
public StoreId getStoreId()
{
return storeId;
}
@Override
public Transaction beginTx()
{
return tx().begin();
}
protected Transaction beginTx( ForceMode forceMode )
{
if ( transactionRunning() )
{
return new PlaceboTransaction( txManager, lockManager, txManager.getTransactionState() );
}
Transaction result = null;
try
{
txManager.begin( forceMode );
result = new TopLevelTransaction( txManager, lockManager, txManager.getTransactionState() );
}
catch ( Exception e )
{
throw new TransactionFailureException(
"Unable to begin transaction", e );
}
return result;
}
@Override
public boolean transactionRunning()
{
try
{
return txManager.getTransaction() != null;
}
catch ( SystemException e )
{
throw new TransactionFailureException(
"Unable to get transaction.", e );
}
}
protected boolean isEphemeral()
{
return false;
}
@Override
public String toString()
{
return getClass().getSimpleName() + " [" + getStoreDir() + "]";
}
@Override
public Iterable getAllNodes()
{
return GlobalGraphOperations.at( this ).getAllNodes();
}
@Override
public Iterable getRelationshipTypes()
{
return GlobalGraphOperations.at( this ).getAllRelationshipTypes();
}
@Override
public KernelEventHandler registerKernelEventHandler(
KernelEventHandler handler )
{
return kernelEventHandlers.registerKernelEventHandler( handler );
}
@Override
public TransactionEventHandler registerTransactionEventHandler(
TransactionEventHandler handler )
{
return transactionEventHandlers.registerTransactionEventHandler( handler );
}
@Override
public KernelEventHandler unregisterKernelEventHandler(
KernelEventHandler handler )
{
return kernelEventHandlers.unregisterKernelEventHandler( handler );
}
@Override
public TransactionEventHandler unregisterTransactionEventHandler(
TransactionEventHandler handler )
{
return transactionEventHandlers.unregisterTransactionEventHandler( handler );
}
@Override
public Node createNode()
{
return nodeManager.createNode();
}
@Override
public Node getNodeById( long id )
{
if ( id < 0 || id > MAX_NODE_ID )
{
throw new NotFoundException( format( "Node %d not found", id ) );
}
return nodeManager.getNodeById( id );
}
@Override
public Relationship getRelationshipById( long id )
{
if ( id < 0 || id > MAX_RELATIONSHIP_ID )
{
throw new NotFoundException( format("Relationship %d not found", id));
}
return nodeManager.getRelationshipById( id );
}
@Override
public Node getReferenceNode()
{
return nodeManager.getReferenceNode();
}
@Override
public TransactionBuilder tx()
{
return defaultTxBuilder;
}
@Override
public Guard getGuard()
{
return guard;
}
@Override
public KernelData getKernelData()
{
return extensions;
}
@Override
public IndexManager index()
{
return indexManager;
}
// GraphDatabaseSPI implementation - THESE SHOULD EVENTUALLY BE REMOVED! DON'T ADD dependencies on these!
public Config getConfig()
{
return config;
}
@Override
public NodeManager getNodeManager()
{
return nodeManager;
}
@Override
public LockManager getLockManager()
{
return lockManager;
}
@Override
public XaDataSourceManager getXaDataSourceManager()
{
return xaDataSourceManager;
}
@Override
public TransactionManager getTxManager()
{
return txManager;
}
@Override
public RelationshipTypeHolder getRelationshipTypeHolder()
{
return relationshipTypeHolder;
}
@Override
public IdGeneratorFactory getIdGeneratorFactory()
{
return idGeneratorFactory;
}
@Override
public DiagnosticsManager getDiagnosticsManager()
{
return diagnosticsManager;
}
@Override
public PersistenceSource getPersistenceSource()
{
return persistenceSource;
}
@Override
public final StringLogger getMessageLog()
{
return msgLog;
}
@Override
public TxIdGenerator getTxIdGenerator()
{
return txIdGenerator;
}
@Override
public KernelPanicEventGenerator getKernelPanicGenerator()
{
return kernelPanicEventGenerator;
}
private Iterable> getSettingsClasses( Iterable> settingsClasses,
Iterable> kernelExtensions, Iterable
cacheProviders )
{
List> totalSettingsClasses = new ArrayList>();
// Add given settings classes
Iterables.addAll( totalSettingsClasses, settingsClasses );
// Get the list of settings classes for extensions
for ( KernelExtensionFactory> kernelExtension : kernelExtensions )
{
if ( kernelExtension.getSettingsClass() != null )
{
totalSettingsClasses.add( kernelExtension.getSettingsClass() );
}
}
for ( CacheProvider cacheProvider : cacheProviders )
{
if ( cacheProvider.getSettingsClass() != null )
{
totalSettingsClasses.add( cacheProvider.getSettingsClass() );
}
}
return totalSettingsClasses;
}
@Override
public boolean equals( Object o )
{
if ( this == o )
{
return true;
}
if ( o == null || !(o instanceof InternalAbstractGraphDatabase) )
{
return false;
}
InternalAbstractGraphDatabase that = (InternalAbstractGraphDatabase) o;
if ( getStoreId() != null ? !getStoreId().equals( that.getStoreId() ) : that.getStoreId() != null )
{
return false;
}
if ( !storeDir.equals( that.storeDir ) )
{
return false;
}
return true;
}
@Override
public int hashCode()
{
return storeDir.hashCode();
}
protected class DefaultKernelData extends KernelData implements Lifecycle
{
private final GraphDatabaseAPI graphDb;
public DefaultKernelData( Config config, GraphDatabaseAPI graphDb )
{
super( config );
this.graphDb = graphDb;
}
@Override
public Version version()
{
return Version.getKernel();
}
@Override
public GraphDatabaseAPI graphDatabase()
{
return graphDb;
}
@Override
public void init()
throws Throwable
{
}
@Override
public void start()
throws Throwable
{
}
@Override
public void stop()
throws Throwable
{
}
@Override
public void shutdown()
{
super.shutdown();
}
}
/*
public class DefaultKernelExtensionLoader implements Lifecycle
{
private final KernelData extensions;
private Collection> loaded;
public DefaultKernelExtensionLoader( KernelData extensions )
{
this.extensions = extensions;
}
@Override
public void init()
throws Throwable
{
loaded = extensions.loadExtensionConfigurations( logging.getLogger( Loggers.EXTENSION ), kernelExtensions );
loadIndexImplementations( indexManager, logging.getLogger( Loggers.INDEX ) );
}
@Override
public void start()
throws Throwable
{
extensions.loadExtensions( loaded, logging.getLogger( Loggers.EXTENSION ) );
}
@Override
public void stop()
throws Throwable
{
extensions.
}
@Override
public void shutdown()
throws Throwable
{
}
void loadIndexImplementations( IndexManagerImpl indexes, StringLogger msgLog )
{
for ( IndexProvider index : indexProviders )
{
try
{
indexes.addProvider( index.identifier(), index.load( dependencyResolver ) );
}
catch ( Throwable cause )
{
msgLog.logMessage( "Failed to load index provider " + index.identifier(), cause );
if ( isAnUpgradeProblem( cause ) )
{
throw launderedException( cause );
}
else
{
cause.printStackTrace();
}
}
}
}
private boolean isAnUpgradeProblem( Throwable cause )
{
while ( cause != null )
{
if ( cause instanceof Throwable )
{
return true;
}
cause = cause.getCause();
}
return false;
}
}
*/
private class DefaultTxEventSyncHookFactory implements TxEventSyncHookFactory
{
@Override
public TransactionEventsSyncHook create()
{
return transactionEventHandlers.hasHandlers() ?
new TransactionEventsSyncHook( transactionEventHandlers, txManager) : null;
}
}
/**
* FIXME: This is supposed to be handled by a Dependency Injection framework...
*
* @author ceefour
*/
class DependencyResolverImpl extends DependencyResolver.Adapter
{
private T resolveKnownSingleDependency( Class type )
{
if ( type.equals( Map.class ) )
{
return (T) getConfig().getParams();
}
else if ( type.equals( Config.class ) )
{
return (T) getConfig();
}
else if ( GraphDatabaseService.class.isAssignableFrom( type ) )
{
return (T) InternalAbstractGraphDatabase.this;
}
else if ( TransactionManager.class.isAssignableFrom( type ) )
{
return (T) txManager;
}
else if ( LockManager.class.isAssignableFrom( type ) )
{
return (T) lockManager;
}
else if( StoreFactory.class.isAssignableFrom( type ) )
{
return (T) storeFactory;
}
else if ( StringLogger.class.isAssignableFrom( type ) )
{
return (T) msgLog;
}
else if ( Logging.class.isAssignableFrom( type ) )
{
return (T) logging;
}
else if ( IndexStore.class.isAssignableFrom( type ) )
{
return (T) indexStore;
}
else if ( XaFactory.class.isAssignableFrom( type ) )
{
return (T) xaFactory;
}
else if ( XaDataSourceManager.class.isAssignableFrom( type ) )
{
return (T) xaDataSourceManager;
}
else if ( FileSystemAbstraction.class.isAssignableFrom( type ) )
{
return (T) fileSystem;
}
else if ( Guard.class.isAssignableFrom( type ) )
{
return (T) guard;
}
else if ( IndexProviders.class.isAssignableFrom( type ) )
{
return (T) indexManager;
}
else if ( KernelData.class.isAssignableFrom( type ) )
{
return (T) extensions;
}
else if ( Logging.class.isAssignableFrom( type ) )
{
return (T) logging;
}
else if ( TransactionInterceptorProviders.class.isAssignableFrom( type ) )
{
return (T) transactionInterceptorProviders;
}
else if ( KernelExtensions.class.isAssignableFrom( type ) )
{
return (T) kernelExtensions;
}
else if ( NodeManager.class.isAssignableFrom( type ) )
{
return (T) nodeManager;
}
else if ( TransactionStateFactory.class.isAssignableFrom( type ) )
{
return (T) stateFactory;
}
else if ( TxIdGenerator.class.isAssignableFrom( type ) )
{
return (T) txIdGenerator;
}
else if ( DiagnosticsManager.class.isAssignableFrom( type ) )
{
return (T) diagnosticsManager;
}
else if ( StoreLockerLifecycleAdapter.class.isAssignableFrom( type ) )
{
return (T) storeLocker;
}
else if ( DependencyResolver.class.isAssignableFrom( type ) )
{
return (T) DependencyResolverImpl.this;
}
return null;
}
@Override
public T resolveDependency( Class type, SelectionStrategy selector )
{
// Try known single dependencies
T result = resolveKnownSingleDependency( type );
if ( result != null )
return selector.select( type, Iterables.option( result ) );
// Try with kernel extensions
return kernelExtensions.resolveDependency( type, selector );
}
}
class DatabaseStartup
implements Lifecycle
{
@Override
public void init()
throws Throwable
{
}
@Override
public void start()
throws Throwable
{
}
@Override
public void stop()
throws Throwable
{
}
@Override
public void shutdown()
throws Throwable
{
}
}
/**
* This class handles whether the database as a whole is available to use at all.
* As it runs as the last service in the lifecycle list, the stop() is called first
* on stop, shutdown or restart, and thus blocks access to everything else for outsiders.
*/
class DatabaseAvailability
implements Lifecycle
{
@Override
public void init()
throws Throwable
{
// TODO: Starting database. Make sure none can access it through lock or CAS
}
@Override
public void start()
throws Throwable
{
// TODO: Starting database. Make sure none can access it through lock or CAS
msgLog.logMessage( "Started - database is now available" );
}
@Override
public void stop()
throws Throwable
{
// TODO: Starting database. Make sure none can access it through lock or CAS
msgLog.logMessage( "Stopping - database is now unavailable" );
}
@Override
public void shutdown()
throws Throwable
{
// TODO: Starting database. Make sure none can access it through lock or CAS
}
}
private class ConfigurationChangedRestarter
extends LifecycleAdapter
{
private final ConfigurationChangeListener listener = new ConfigurationChangeListener()
{
Executor executor = Executors.newSingleThreadExecutor( new DaemonThreadFactory( "Database configuration " +
"restart" ) );
@Override
public void notifyConfigurationChanges( final Iterable change )
{
executor.execute( new Runnable()
{
@Override
public void run()
{
// Restart
try
{
life.stop();
life.start();
msgLog.logMessage( "Database restarted with the following configuration changes:" +
change );
}
catch ( LifecycleException e )
{
msgLog.logMessage( "Could not restart database", e );
}
}
} );
}
};
@Override
public void start()
throws Throwable
{
config.addConfigurationChangeListener( listener );
}
@Override
public void stop()
throws Throwable
{
config.removeConfigurationChangeListener( listener );
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy