Skip to content

Commit

Permalink
Merge pull request #345 from thobe/sa-no-recovery
Browse files Browse the repository at this point in the history
Made it possible to start StoreAccess without performing recovery.
  • Loading branch information
tinwelint committed Mar 19, 2012
2 parents 85ecfad + 08eb29a commit d397c60
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 13 deletions.
Expand Up @@ -20,13 +20,14 @@

package org.neo4j.kernel.impl.nioneo.store;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import org.neo4j.kernel.AbstractGraphDatabase;
import org.neo4j.kernel.CommonFactories;
import org.neo4j.kernel.Config;
import org.neo4j.kernel.IdGeneratorFactory;
import org.neo4j.kernel.impl.util.StringLogger;

/**
* Not thread safe (since DiffRecordStore is not thread safe), intended for
Expand All @@ -44,6 +45,9 @@ public class StoreAccess
private final RecordStore<PropertyIndexRecord> propIndexStore;
private final RecordStore<DynamicRecord> typeNameStore;
private final RecordStore<DynamicRecord> propKeyStore;
// internal state
private boolean closeable;
private NeoStore neoStore;

public StoreAccess( AbstractGraphDatabase graphdb )
{
Expand All @@ -59,6 +63,7 @@ public StoreAccess( NeoStore store )
{
this( store.getNodeStore(), store.getRelationshipStore(), store.getPropertyStore(),
store.getRelationshipTypeStore() );
this.neoStore = store;
}

public StoreAccess( NodeStore nodeStore, RelationshipStore relStore, PropertyStore propStore,
Expand All @@ -75,6 +80,35 @@ public StoreAccess( NodeStore nodeStore, RelationshipStore relStore, PropertySto
this.propKeyStore = wrapStore( propStore.getIndexStore().getNameStore() );
}

public StoreAccess( String path )
{
this( path, defaultParams() );
}

public StoreAccess( String path, Map<String, String> params )
{
this(
new StoreFactory( requiredParams( params, path ), CommonFactories.defaultIdGeneratorFactory(),
CommonFactories.defaultFileSystemAbstraction(),
CommonFactories.defaultLastCommittedTxIdSetter(), initLogger( path ),
CommonFactories.defaultTxHook() ).attemptNewNeoStore( new File( path, "neostore" ).getAbsolutePath() ) );
this.closeable = true;
}

private static StringLogger initLogger( String path )
{
StringLogger logger = StringLogger.logger( path );
logger.logMessage( "Starting " + StoreAccess.class.getSimpleName() );
return logger;
}

private static Map<String, String> requiredParams( Map<String, String> params, String path )
{
params = new HashMap<String, String>( params );
params.put( "neo_store", new File( path, "neostore" ).getAbsolutePath() );
return params;
}

public RecordStore<NodeRecord> getNodeStore()
{
return nodeStore;
Expand Down Expand Up @@ -148,25 +182,33 @@ protected void apply( RecordStore.Processor processor, RecordStore<?> store )
processor.applyFiltered( store, RecordStore.IN_USE );
}

private static Map<Object, Object> defaultParams()
private static Map<String, String> defaultParams()
{
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" );
Map<String, String> params = new HashMap<String, String>();
params.put( Config.NODE_STORE_MMAP_SIZE, "20M" );
params.put( Config.PROPERTY_STORE_MMAP_SIZE, "90M" );
params.put( Config.PROPERTY_INDEX_STORE_MMAP_SIZE, "1M" );
params.put( Config.PROPERTY_INDEX_KEY_STORE_MMAP_SIZE, "1M" );
params.put( Config.STRING_PROPERTY_STORE_MMAP_SIZE, "130M" );
params.put( Config.ARRAY_PROPERTY_STORE_MMAP_SIZE, "130M" );
params.put( Config.RELATIONSHIP_STORE_MMAP_SIZE, "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" );
params.put( Config.USE_MEMORY_MAPPED_BUFFERS, "false" );
}
params.put( Config.REBUILD_IDGENERATORS_FAST, "true" );

params.put( IdGeneratorFactory.class, new CommonFactories.DefaultIdGeneratorFactory() );
return params;
}

public synchronized void close()
{
if ( closeable )
{
closeable = false;
neoStore.close();
}
}
}
Expand Up @@ -81,7 +81,7 @@ public NeoStore newNeoStore(String fileName)
}
}

private NeoStore attemptNewNeoStore( String fileName )
NeoStore attemptNewNeoStore( String fileName )
{
return new NeoStore( fileName, ConfigProxy.config(config, NeoStore.Configuration.class),
lastCommittedTxIdSetter, idGeneratorFactory, fileSystemAbstraction, stringLogger, txHook,
Expand Down
Expand Up @@ -19,10 +19,14 @@
*/
package org.neo4j.kernel.impl.nioneo.store;

import java.io.File;

import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction;
import org.neo4j.kernel.EmbeddedGraphDatabase;

import static org.junit.Assert.assertEquals;

public class ProduceUncleanStore
{
public static void main( String[] args )
Expand All @@ -38,4 +42,12 @@ public static void main( String[] args )
tx.finish();
System.exit( 0 );
}

public static void atPath( File path ) throws Exception
{
int ret = Runtime.getRuntime()
.exec( new String[] { "java", "-cp", System.getProperty( "java.class.path" ),
ProduceUncleanStore.class.getName(), path.getAbsolutePath() } ).waitFor();
assertEquals( "ProduceUncleanStore terminated unsuccessfully", 0, ret );
}
}
@@ -0,0 +1,90 @@
/**
* Copyright (c) 2002-2012 "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.impl.nioneo.store;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

import org.junit.Rule;
import org.junit.Test;
import org.neo4j.test.TargetDirectory;
import org.neo4j.test.TargetDirectory.TestDirectory;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class TestStoreAccess
{
public @Rule
TestDirectory testdir = TargetDirectory.testDirForTest( getClass() );

@Test
public void openingThroughStoreAccessShouldNotTriggerRecovery() throws Exception
{
ProduceUncleanStore.atPath( testdir.directory() );
assertTrue( "Store should be unclean", isUnclean( testdir.directory() ) );
File messages = new File( testdir.directory(), "messages.log" );
long eof = messages.length();
new StoreAccess( testdir.directory().getAbsolutePath() ).close();
String data = readFrom( messages, eof );
// This doesn't actually check for recovery, it checks for startup of the DB (by
// looking in the log) and we assume that recovery would happen during DB startup.
assertFalse( "should not have started GraphDatabase", data.contains( "STARTUP" ) );
System.out.println( data );
assertTrue( "Store should be unclean", isUnclean( testdir.directory() ) );
}

private boolean isUnclean( File directory ) throws IOException
{
char chr = activeLog( directory );
return chr == '1' || chr == '2';
}

private String readFrom( File file, long start ) throws IOException
{
RandomAccessFile input = new RandomAccessFile( file, "r" );
try
{
byte[] data = new byte[(int) ( input.length() - start )];
input.seek( start );
assertEquals( data.length, input.read( data ) );
return new String( data );
}
finally
{
input.close();
}
}

private char activeLog( File directory ) throws IOException
{
RandomAccessFile file = new RandomAccessFile( new File( directory, "nioneo_logical.log.active" ), "r" );
try
{
return file.readChar();
}
finally
{
file.close();
}
}
}

0 comments on commit d397c60

Please sign in to comment.