/**
* 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 <http://www.gnu.org/licenses/>.
*/
package org.neo4j.kernel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.index.IndexProvider;
import org.neo4j.helpers.Service;
import org.neo4j.kernel.impl.util.StringLogger;
public abstract class KernelData
{
private static final Map<String, KernelData> instances = new HashMap<String, KernelData>();
private static int ID_COUNTER = 0;
private static synchronized String newInstance( KernelData instance )
{
final String instanceId = Integer.toString( ID_COUNTER++ );
instances.put( instanceId, instance );
return instanceId;
}
private static synchronized Collection<KernelData> kernels()
{
return new LinkedList<KernelData>( instances.values() );
}
private static synchronized void removeInstance( String instanceId )
{
instances.remove( instanceId );
}
static void visitAll( KernelExtension<?> extension, Object param )
{
for ( KernelData kernel : kernels() )
{
try
{
kernel.accept( extension, param );
}
catch ( Throwable cause )
{
System.err.println( "Agent visit failure: " + cause );
}
}
}
@SuppressWarnings( "unchecked" )
<S> void accept( KernelExtension<S> extension, Object param )
{
@SuppressWarnings( "hiding" ) Object state = this.state.get( extension );
if ( state != null )
{
extension.agentVisit( this, (S) state, param );
}
else
{
state = extension.agentLoad( this, param );
if ( state != null )
{
setState( extension, state );
}
}
}
private final String instanceId;
KernelData()
{
instanceId = newInstance( this );
}
public final String instanceId()
{
return instanceId;
}
@Override
public final int hashCode()
{
return instanceId.hashCode();
}
@Override
public final boolean equals( Object obj )
{
return obj instanceof KernelData && instanceId.equals( ( (KernelData) obj ).instanceId );
}
public abstract Version version();
public abstract Config getConfig();
public abstract GraphDatabaseService graphDatabase();
public abstract Map<Object, Object> getConfigParams();
private final Map<KernelExtension<?>, Object> state = new HashMap<KernelExtension<?>, Object>();
Collection<KernelExtension<?>> loadExtensionConfigurations( StringLogger msgLog )
{
Collection<KernelExtension<?>> loadedExtensions = new ArrayList<KernelExtension<?>>();
for ( KernelExtension<?> extension : Service.load( KernelExtension.class ) )
{
try
{
extension.loadConfiguration( this );
loadedExtensions.add( extension );
}
catch ( Throwable t )
{
msgLog.logMessage( "Failed to init extension " + extension, t, true );
}
}
return loadedExtensions;
}
void loadIndexImplementations( IndexManagerImpl indexes, StringLogger msgLog )
{
for ( IndexProvider index : Service.load( IndexProvider.class ) )
{
try
{
indexes.addProvider( index.identifier(), index.load( this ) );
}
catch ( Throwable cause )
{
msgLog.logMessage( "Failed to load index provider " + index.identifier(), cause );
}
}
}
void loadExtensions( Collection<KernelExtension<?>> loadedExtensions, StringLogger msgLog )
{
for ( KernelExtension<?> extension : loadedExtensions )
{
try
{
@SuppressWarnings( "hiding" ) Object state = extension.load( this );
if ( state != null )
{
setState( extension, state );
}
msgLog.logMessage( "Extension " + extension + " loaded ok", true );
}
catch ( Throwable cause )
{
msgLog.logMessage( "Failed to load extension " + extension, cause, true );
}
}
}
synchronized void shutdown( StringLogger msgLog )
{
try
{
for ( Map.Entry<KernelExtension<?>, Object> loaded : state.entrySet() )
{
try
{
unload( loaded.getKey(), loaded.getValue() );
}
catch ( Throwable cause )
{
msgLog.logMessage( "Error unloading " + loaded, cause, true );
}
}
}
finally
{
state.clear();
removeInstance( instanceId );
}
}
@SuppressWarnings( "unchecked" )
private <S> void unload( KernelExtension<S> extension, @SuppressWarnings( "hiding" ) Object state )
{
extension.unload( (S) state );
}
@SuppressWarnings( "unchecked" )
final <S> S getState( KernelExtension<S> extension )
{
return (S) state.get( extension );
}
private Object setState( KernelExtension<?> extension, Object value )
{
if ( value == null )
{
return state.remove( extension );
}
else
{
return state.put( extension, value );
}
}
public final Object getParam( String key )
{
return getConfigParams().get( key );
}
}