/* * Copyright (c) 2002-2009 "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 Affero 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.neo4j.kernel; import java.io.File; import java.util.HashMap; import java.util.Map; import javax.transaction.TransactionManager; import org.neo4j.graphdb.RelationshipType; import org.neo4j.kernel.impl.core.LockReleaser; import org.neo4j.kernel.impl.nioneo.xa.NioNeoDbPersistenceSource; import org.neo4j.kernel.impl.transaction.LockManager; import org.neo4j.kernel.impl.transaction.TransactionFailureException; import org.neo4j.kernel.impl.transaction.TxModule; import org.neo4j.kernel.impl.transaction.xaframework.XaDataSource; import org.neo4j.kernel.impl.util.FileUtils; class GraphDbInstance { private static final String NIO_NEO_DB_CLASS = "org.neo4j.kernel.impl.nioneo.xa.NeoStoreXaDataSource"; private static final String DEFAULT_DATA_SOURCE_NAME = "nioneodb"; private static final String LUCENE_DS_CLASS = "org.neo4j.index.lucene.LuceneDataSource"; private boolean started = false; private boolean create; private String storeDir; GraphDbInstance( String storeDir, boolean create ) { this.storeDir = storeDir; this.create = create; } private Config config = null; private NioNeoDbPersistenceSource persistenceSource = null; public Config getConfig() { return config; } public void start() { start( new HashMap<String,String>() ); } private Map<Object,Object> getDefaultParams() { Map<Object,Object> params = new HashMap<Object,Object>(); params.put( "neostore.nodestore.db.mapped_memory", "20M" ); params.put( "neostore.propertystore.db.mapped_memory", "90M" ); params.put( "neostore.propertystore.db.index.mapped_memory", "1M" ); params.put( "neostore.propertystore.db.index.keys.mapped_memory", "1M" ); params.put( "neostore.propertystore.db.strings.mapped_memory", "130M" ); params.put( "neostore.propertystore.db.arrays.mapped_memory", "130M" ); params.put( "neostore.relationshipstore.db.mapped_memory", "100M" ); // if on windows, default no memory mapping String nameOs = System.getProperty( "os.name" ); if ( nameOs.startsWith( "Windows" ) ) { params.put( "use_memory_mapped_buffers", "false" ); } return params; } /** * Starts Neo4j with default configuration * * @param storeDir * path to directory where Neo4j store is located * @param create * if true a new Neo4j store will be created if no store * exist at <CODE>storeDir</CODE> * @param configuration * parameters * @throws StartupFailedException * if unable to start */ public synchronized void start( Map<String,String> stringParams ) { if ( started ) { throw new IllegalStateException( "Neo4j instance already started" ); } Map<Object,Object> params = getDefaultParams(); for ( Map.Entry<String,String> entry : stringParams.entrySet() ) { params.put( entry.getKey(), entry.getValue() ); } config = new Config( storeDir, params ); storeDir = FileUtils.fixSeparatorsInPath( storeDir ); String separator = System.getProperty( "file.separator" ); String store = storeDir + separator + "neostore"; params.put( "store_dir", storeDir ); params.put( "neo_store", store ); params.put( "create", String.valueOf( create ) ); String logicalLog = storeDir + separator + "nioneo_logical.log"; params.put( "logical_log", logicalLog ); byte resourceId[] = "414141".getBytes(); params.put( LockManager.class, config.getLockManager() ); params.put( LockReleaser.class, config.getLockReleaser() ); config.getTxModule().registerDataSource( DEFAULT_DATA_SOURCE_NAME, NIO_NEO_DB_CLASS, resourceId, params ); // hack for lucene index recovery if in path XaDataSource lucene = null; if ( !config.isReadOnly() ) { try { Class clazz = Class.forName( LUCENE_DS_CLASS ); cleanWriteLocksInLuceneDirectory( storeDir + "/lucene" ); lucene = registerLuceneDataSource( clazz.getName(), config .getTxModule(), storeDir + "/lucene", config.getLockManager() ); } catch ( ClassNotFoundException e ) { // ok index util not on class path } } // System.setProperty( "neo.tx_log_directory", storeDir ); persistenceSource = new NioNeoDbPersistenceSource(); config.setNeoPersistenceSource( DEFAULT_DATA_SOURCE_NAME, create ); config.getIdGeneratorModule().setPersistenceSourceInstance( persistenceSource ); config.getEventModule().init(); config.getTxModule().init(); config.getPersistenceModule().init(); persistenceSource.init(); config.getIdGeneratorModule().init(); config.getNeoModule().init(); config.getEventModule().start(); config.getTxModule().start(); config.getPersistenceModule().start( config.getTxModule().getTxManager(), persistenceSource ); persistenceSource.start( config.getTxModule().getXaDataSourceManager() ); config.getIdGeneratorModule().start(); config.getNeoModule().start( config.getLockReleaser(), config.getPersistenceModule().getPersistenceManager(), params ); if ( lucene != null ) { config.getTxModule().getXaDataSourceManager().unregisterDataSource( "lucene" ); lucene = null; } started = true; } private void cleanWriteLocksInLuceneDirectory( String luceneDir ) { File dir = new File( luceneDir ); if ( !dir.isDirectory() ) { return; } for ( File file : dir.listFiles() ) { if ( file.isDirectory() ) { cleanWriteLocksInLuceneDirectory( file.getAbsolutePath() ); } else if ( file.getName().equals( "write.lock" ) ) { boolean success = file.delete(); assert success; } } } private XaDataSource registerLuceneDataSource( String className, TxModule txModule, String luceneDirectory, LockManager lockManager ) { byte resourceId[] = "162373".getBytes(); Map<Object,Object> params = new HashMap<Object,Object>(); params.put( "dir", luceneDirectory ); params.put( LockManager.class, lockManager ); return txModule.registerDataSource( "lucene", className, resourceId, params, true ); } /** * Returns true if Neo4j is started. * * @return True if Neo4j started */ public boolean started() { return started; } /** * Shut down Neo4j. */ public synchronized void shutdown() { if ( started ) { config.getNeoModule().stop(); config.getIdGeneratorModule().stop(); persistenceSource.stop(); config.getPersistenceModule().stop(); config.getTxModule().stop(); config.getEventModule().stop(); config.getNeoModule().destroy(); config.getIdGeneratorModule().destroy(); persistenceSource.destroy(); config.getPersistenceModule().destroy(); config.getTxModule().destroy(); config.getEventModule().destroy(); } started = false; } public Iterable<RelationshipType> getRelationshipTypes() { return config.getNeoModule().getRelationshipTypes(); } public boolean transactionRunning() { try { return config.getTxModule().getTxManager().getTransaction() != null; } catch ( Exception e ) { throw new TransactionFailureException( "Unable to get transaction.", e ); } } public TransactionManager getTransactionManager() { return config.getTxModule().getTxManager(); } }