/** * 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 static java.util.regex.Pattern.quote; import java.util.HashMap; import java.util.Map; import javax.transaction.TransactionManager; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.helpers.Args; import org.neo4j.kernel.impl.annotations.Documented; import org.neo4j.kernel.impl.cache.AdaptiveCacheManager; import org.neo4j.kernel.impl.core.GraphDbModule; import org.neo4j.kernel.impl.core.KernelPanicEventGenerator; import org.neo4j.kernel.impl.core.LastCommittedTxIdSetter; import org.neo4j.kernel.impl.core.LockReleaser; import org.neo4j.kernel.impl.core.RelationshipTypeCreator; import org.neo4j.kernel.impl.core.RelationshipTypeHolder; import org.neo4j.kernel.impl.core.TxEventSyncHookFactory; import org.neo4j.kernel.impl.index.IndexStore; import org.neo4j.kernel.impl.nioneo.store.FileSystemAbstraction; import org.neo4j.kernel.impl.nioneo.store.StoreId; import org.neo4j.kernel.impl.persistence.IdGenerator; import org.neo4j.kernel.impl.persistence.IdGeneratorModule; import org.neo4j.kernel.impl.persistence.PersistenceModule; import org.neo4j.kernel.impl.transaction.LockManager; import org.neo4j.kernel.impl.transaction.TxModule; import org.neo4j.kernel.impl.transaction.xaframework.TxIdGenerator; import android.content.Context; /** * A non-standard configuration object. */ public class Config { static final String NIO_NEO_DB_CLASS = "org.neo4j.kernel.impl.nioneo.xa.NeoStoreXaDataSource"; public static final String DEFAULT_DATA_SOURCE_NAME = "nioneodb"; static final String LUCENE_DS_CLASS = "org.neo4j.index.lucene.LuceneDataSource"; static final String LUCENE_FULLTEXT_DS_CLASS = "org.neo4j.index.lucene.LuceneFulltextDataSource"; /** * Tell Neo4j to use memory mapped buffers for accessing the native storage * layer */ @Documented public static final String USE_MEMORY_MAPPED_BUFFERS = "use_memory_mapped_buffers"; /** Print out the effective Neo4j configuration after startup */ @Documented public static final String DUMP_CONFIGURATION = "dump_configuration"; /** * Make Neo4j keep the logical transaction logs for being able to backup the * database */ @Documented public static final String KEEP_LOGICAL_LOGS = "keep_logical_logs"; /** Enable a remote shell server which shell clients can log in to */ @Documented public static final String ENABLE_REMOTE_SHELL = "enable_remote_shell"; /** Enable a support for running online backups */ @Documented public static final String ENABLE_ONLINE_BACKUP = "enable_online_backup"; /** Mark this database as a backup slave. */ @Documented public static final String BACKUP_SLAVE = "backup_slave"; /** Only allow read operations from this Neo4j instance. */ @Documented public static final String READ_ONLY = "read_only"; /** Relative path for where the Neo4j storage directory is located */ @Documented public static final String STORAGE_DIRECTORY = "store_dir"; /** * Use a quick approach for rebuilding the ID generators. This give quicker * recovery time, but will limit the ability to reuse the space of deleted * entities. */ @Documented public static final String REBUILD_IDGENERATORS_FAST = "rebuild_idgenerators_fast"; /** The size to allocate for memory mapping the node store */ @Documented public static final String NODE_STORE_MMAP_SIZE = "neostore.nodestore.db.mapped_memory"; /** The size to allocate for memory mapping the array property store */ @Documented public static final String ARRAY_PROPERTY_STORE_MMAP_SIZE = "neostore.propertystore.db.arrays.mapped_memory"; /** * The size to allocate for memory mapping the store for property key * strings */ @Documented public static final String PROPERTY_INDEX_KEY_STORE_MMAP_SIZE = "neostore.propertystore.db.index.keys.mapped_memory"; /** * The size to allocate for memory mapping the store for property key * indexes */ @Documented public static final String PROPERTY_INDEX_STORE_MMAP_SIZE = "neostore.propertystore.db.index.mapped_memory"; /** The size to allocate for memory mapping the property value store */ @Documented public static final String PROPERTY_STORE_MMAP_SIZE = "neostore.propertystore.db.mapped_memory"; /** The size to allocate for memory mapping the string property store */ @Documented public static final String STRING_PROPERTY_STORE_MMAP_SIZE = "neostore.propertystore.db.strings.mapped_memory"; /** The size to allocate for memory mapping the relationship store */ @Documented public static final String RELATIONSHIP_STORE_MMAP_SIZE = "neostore.relationshipstore.db.mapped_memory"; /** Relative path for where the Neo4j logical log is located */ @Documented public static final String LOGICAL_LOG = "logical_log"; /** Relative path for where the Neo4j storage information file is located */ @Documented public static final String NEO_STORE = "neo_store"; /** * The type of cache to use for nodes and relationships, one of [weak, soft, * none] */ @Documented public static final String CACHE_TYPE = "cache_type"; /** * The name of the Transaction Manager service to use as defined in the TM * service provider constructor, defaults to native. */ @Documented public static final String TXMANAGER_IMPLEMENTATION = "tx_manager_impl"; /** * Boolean (one of true,false) defining whether to allow a store upgrade * in case the current version of the database starts against an older store * version. Setting this to true does not guarantee successful upgrade, just * allows an attempt at it. */ @Documented public static final String ALLOW_STORE_UPGRADE = "allow_store_upgrade"; public static final String STRING_BLOCK_SIZE = "string_block_size"; public static final String ARRAY_BLOCK_SIZE = "array_block_size"; /** * A list of property names (comma separated) that will be indexed by * default. * This applies to Nodes only. */ @Documented public static final String NODE_KEYS_INDEXABLE = "node_keys_indexable"; /** * A list of property names (comma separated) that will be indexed by * default. * This applies to Relationships only. */ @Documented public static final String RELATIONSHIP_KEYS_INDEXABLE = "relationship_keys_indexable"; /** * A list of property names (comma separated) that will be ignored by the * auto indexer. * This applies to Nodes only. */ @Documented public static final String NODE_AUTO_INDEXING = "node_auto_indexing"; /** * Boolean value (one of true, false) that controls the auto indexing * feature for relationships. Setting to false shuts it down * unconditionally, while true * enables it for every property, subject to restrictions in the * configuration. * The default is false. */ @Documented public static final String RELATIONSHIP_AUTO_INDEXING = "relationship_auto_indexing"; static final String LOAD_EXTENSIONS = "load_kernel_extensions"; private final AdaptiveCacheManager cacheManager; private final TxModule txModule; private final LockManager lockManager; private final LockReleaser lockReleaser; private final PersistenceModule persistenceModule; private boolean create = false; private String persistenceSourceName; private final IdGeneratorModule idGeneratorModule; private final GraphDbModule graphDbModule; private final String storeDir; private final IndexStore indexStore; private final Map<Object, Object> params; private final Map inputParams; private final TxEventSyncHookFactory syncHookFactory; private final RelationshipTypeCreator relTypeCreator; private final boolean readOnly; private final boolean backupSlave; private final IdGeneratorFactory idGeneratorFactory; private final TxIdGenerator txIdGenerator; private final Context context; Config( Context context, GraphDatabaseService graphDb, String storeDir, StoreId storeId, Map<String, String> inputParams, KernelPanicEventGenerator kpe, TxModule txModule, LockManager lockManager, LockReleaser lockReleaser, IdGeneratorFactory idGeneratorFactory, TxEventSyncHookFactory txSyncHookFactory, RelationshipTypeCreator relTypeCreator, TxIdGenerator txIdGenerator, LastCommittedTxIdSetter lastCommittedTxIdSetter, FileSystemAbstraction fileSystem ) { this.context = context; this.storeDir = storeDir; this.inputParams = inputParams; // Get the default params and override with the user supplied values this.params = getDefaultParams(); this.params.putAll( inputParams ); this.idGeneratorFactory = idGeneratorFactory; this.relTypeCreator = relTypeCreator; this.txIdGenerator = txIdGenerator; this.txModule = txModule; this.lockManager = lockManager; this.lockReleaser = lockReleaser; this.idGeneratorModule = new IdGeneratorModule( new IdGenerator() ); this.readOnly = Boolean.parseBoolean( (String) params.get( READ_ONLY ) ); this.backupSlave = Boolean.parseBoolean( (String) params.get( BACKUP_SLAVE ) ); this.syncHookFactory = txSyncHookFactory; this.persistenceModule = new PersistenceModule(); this.cacheManager = new AdaptiveCacheManager(); this.params.put( FileSystemAbstraction.class, fileSystem ); graphDbModule = new GraphDbModule( graphDb, cacheManager, lockManager, txModule.getTxManager(), idGeneratorModule.getIdGenerator(), readOnly ); indexStore = new IndexStore( storeDir ); params.put( IndexStore.class, indexStore ); if ( storeId != null ) params.put( StoreId.class, storeId ); params.put( IdGeneratorFactory.class, idGeneratorFactory ); params.put( TxIdGenerator.class, txIdGenerator ); params.put( TransactionManager.class, txModule.getTxManager() ); params.put( LastCommittedTxIdSetter.class, lastCommittedTxIdSetter ); params.put( GraphDbModule.class, graphDbModule ); } public static 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 if ( osIsWindows() ) { params.put( Config.USE_MEMORY_MAPPED_BUFFERS, "false" ); } else { // If not on win, default use memory mapping params.put( Config.USE_MEMORY_MAPPED_BUFFERS, "true" ); } params.put( NODE_AUTO_INDEXING, "false" ); params.put( RELATIONSHIP_AUTO_INDEXING, "false" ); return params; } public static boolean osIsWindows() { String nameOs = System.getProperty( "os.name" ); return nameOs.startsWith( "Windows" ); } public static boolean osIsMacOS() { String nameOs = System.getProperty( "os.name" ); return nameOs.equalsIgnoreCase( "Mac OS X" ); } void setPersistenceSource( String name, boolean create ) { persistenceSourceName = name; this.create = create; } String getPersistenceSource() { return persistenceSourceName; } boolean getCreatePersistenceSource() { return create; } public TxModule getTxModule() { return txModule; } public GraphDbModule getGraphDbModule() { return graphDbModule; } public PersistenceModule getPersistenceModule() { return persistenceModule; } public IdGeneratorModule getIdGeneratorModule() { return idGeneratorModule; } public LockManager getLockManager() { return lockManager; } public IndexStore getIndexStore() { return indexStore; } public LockReleaser getLockReleaser() { return lockReleaser; } public Map<Object, Object> getParams() { return this.params; } public boolean isReadOnly() { return readOnly; } boolean isBackupSlave() { return backupSlave; } Map<Object, Object> getInputParams() { return inputParams; } TxEventSyncHookFactory getSyncHookFactory() { return syncHookFactory; } public RelationshipTypeCreator getRelationshipTypeCreator() { return relTypeCreator; } public IdGeneratorFactory getIdGeneratorFactory() { return idGeneratorFactory; } public RelationshipTypeHolder getRelationshipTypeHolder() { return graphDbModule.getNodeManager().getRelationshipTypeHolder(); } public Context getContext() { return context; } public static void dumpConfiguration( Map<?, ?> config ) { for ( Object key : config.keySet() ) { if ( key instanceof String ) { Object value = config.get( key ); if ( value instanceof String ) { System.out.println( key + "=" + value ); } } } } public static boolean configValueContainsMultipleParameters( String configValue ) { return configValue != null && configValue.contains( "=" ); } public static Args parseMapFromConfigValue( String name, String configValue ) { Map<String, String> result = new HashMap<String, String>(); for ( String part : configValue.split( quote( "," ) ) ) { String[] tokens = part.split( quote( "=" ) ); if ( tokens.length != 2 ) { throw new RuntimeException( "Invalid configuration value '" + configValue + "' for " + name + ". The format is [true/false] or [key1=value1,key2=value2...]" ); } result.put( tokens[0], tokens[1] ); } return new Args( result ); } public static Object getFromConfig( Map<?, ?> config, Object key, Object defaultValue ) { Object result = config != null ? config.get( key ) : defaultValue; return result != null ? result : defaultValue; } }