Skip to content

Commit

Permalink
Minimum logical log threshold is now 1 Mb
Browse files Browse the repository at this point in the history
it doesn't really make sense to have threshold smaller than that.
  • Loading branch information
tinwelint committed Feb 2, 2015
1 parent 282c505 commit 9356988
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 68 deletions.
Expand Up @@ -191,7 +191,7 @@ public abstract class GraphDatabaseSettings


@Description( "Specifies at which file size the logical log will auto-rotate. " + @Description( "Specifies at which file size the logical log will auto-rotate. " +
"`0` means that no rotation will automatically occur based on file size. " ) "`0` means that no rotation will automatically occur based on file size. " )
public static final Setting<Long> logical_log_rotation_threshold = setting( "logical_log_rotation_threshold", BYTES, "250M" ); public static final Setting<Long> logical_log_rotation_threshold = setting( "logical_log_rotation_threshold", BYTES, "250M", min( 1024*1024L /*1Mb*/ ) );


@Description("Use a quick approach for rebuilding the ID generators. This give quicker recovery time, " + @Description("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.") "but will limit the ability to reuse the space of deleted entities.")
Expand Down
Expand Up @@ -19,12 +19,12 @@
*/ */
package org.neo4j.helpers; package org.neo4j.helpers;


import org.junit.Test;

import java.io.File; import java.io.File;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;


import org.junit.Test;

import org.neo4j.graphdb.config.InvalidSettingException; import org.neo4j.graphdb.config.InvalidSettingException;
import org.neo4j.graphdb.config.Setting; import org.neo4j.graphdb.config.Setting;
import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.graphdb.factory.GraphDatabaseSettings;
Expand All @@ -39,8 +39,8 @@
import static org.neo4j.helpers.Settings.DURATION; import static org.neo4j.helpers.Settings.DURATION;
import static org.neo4j.helpers.Settings.INTEGER; import static org.neo4j.helpers.Settings.INTEGER;
import static org.neo4j.helpers.Settings.MANDATORY; import static org.neo4j.helpers.Settings.MANDATORY;
import static org.neo4j.helpers.Settings.NO_DEFAULT;
import static org.neo4j.helpers.Settings.NORMALIZED_RELATIVE_URI; import static org.neo4j.helpers.Settings.NORMALIZED_RELATIVE_URI;
import static org.neo4j.helpers.Settings.NO_DEFAULT;
import static org.neo4j.helpers.Settings.PATH; import static org.neo4j.helpers.Settings.PATH;
import static org.neo4j.helpers.Settings.STRING; import static org.neo4j.helpers.Settings.STRING;
import static org.neo4j.helpers.Settings.basePath; import static org.neo4j.helpers.Settings.basePath;
Expand Down Expand Up @@ -283,13 +283,11 @@ public void testLogicalLogRotationThreshold() throws Exception
// WHEN // WHEN
Setting<Long> setting = GraphDatabaseSettings.logical_log_rotation_threshold; Setting<Long> setting = GraphDatabaseSettings.logical_log_rotation_threshold;
long defaultValue = setting.apply( map( stringMap() ) ); long defaultValue = setting.apply( map( stringMap() ) );
long kiloValue = setting.apply( map( stringMap( setting.name(), "10k" ) ) );
long megaValue = setting.apply( map( stringMap( setting.name(), "10M" ) ) ); long megaValue = setting.apply( map( stringMap( setting.name(), "10M" ) ) );
long gigaValue = setting.apply( map( stringMap( setting.name(), "10g" ) ) ); long gigaValue = setting.apply( map( stringMap( setting.name(), "10g" ) ) );


// THEN // THEN
assertThat( defaultValue, greaterThan( 0L ) ); assertThat( defaultValue, greaterThan( 0L ) );
assertEquals( 10 * 1024, kiloValue );
assertEquals( 10 * 1024 * 1024, megaValue ); assertEquals( 10 * 1024 * 1024, megaValue );
assertEquals( 10L * 1024 * 1024 * 1024, gigaValue ); assertEquals( 10L * 1024 * 1024 * 1024, gigaValue );
} }
Expand Down Expand Up @@ -335,13 +333,13 @@ public void testMemoryUsageConfigFromSystemMemory() throws Exception
// When && then // When && then
assertThat(memUse.apply( Functions.<String,String>constant( null ) ), greaterThan( 0l )); assertThat(memUse.apply( Functions.<String,String>constant( null ) ), greaterThan( 0l ));
} }

@Test @Test
public void testNormalizedRelativeURI() throws Exception public void testNormalizedRelativeURI() throws Exception
{ {
// Given // Given
Setting<URI> uri = setting( "mySetting", NORMALIZED_RELATIVE_URI, "http://localhost:7474///db///data///" ); Setting<URI> uri = setting( "mySetting", NORMALIZED_RELATIVE_URI, "http://localhost:7474///db///data///" );

// When && then // When && then
assertThat( uri.apply( Functions.<String,String>constant( null ) ).toString(), equalTo( "/db/data" ) ); assertThat( uri.apply( Functions.<String,String>constant( null ) ).toString(), equalTo( "/db/data" ) );
} }
Expand Down
Expand Up @@ -32,7 +32,6 @@
import org.neo4j.graphdb.Label; import org.neo4j.graphdb.Label;
import org.neo4j.graphdb.Transaction; import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.factory.GraphDatabaseBuilder; import org.neo4j.graphdb.factory.GraphDatabaseBuilder;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.helpers.Pair; import org.neo4j.helpers.Pair;
import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.io.pagecache.PageCache; import org.neo4j.io.pagecache.PageCache;
Expand All @@ -43,17 +42,19 @@
import org.neo4j.kernel.impl.store.counts.keys.CountsKey; import org.neo4j.kernel.impl.store.counts.keys.CountsKey;
import org.neo4j.kernel.impl.store.kvstore.KeyValueRecordVisitor; import org.neo4j.kernel.impl.store.kvstore.KeyValueRecordVisitor;
import org.neo4j.kernel.impl.store.kvstore.SortedKeyValueStore; import org.neo4j.kernel.impl.store.kvstore.SortedKeyValueStore;
import org.neo4j.kernel.impl.transaction.log.LogRotation;
import org.neo4j.register.Register.CopyableDoubleLongRegister; import org.neo4j.register.Register.CopyableDoubleLongRegister;
import org.neo4j.register.Register.DoubleLongRegister;
import org.neo4j.test.EphemeralFileSystemRule; import org.neo4j.test.EphemeralFileSystemRule;
import org.neo4j.test.PageCacheRule; import org.neo4j.test.PageCacheRule;
import org.neo4j.test.TargetDirectory; import org.neo4j.test.TargetDirectory;
import org.neo4j.test.TestGraphDatabaseFactory; import org.neo4j.test.TestGraphDatabaseFactory;


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

import static org.neo4j.kernel.impl.store.kvstore.SortedKeyValueStoreHeader.BASE_MINOR_VERSION; import static org.neo4j.kernel.impl.store.kvstore.SortedKeyValueStoreHeader.BASE_MINOR_VERSION;
import static org.neo4j.kernel.impl.transaction.log.TransactionIdStore.BASE_TX_ID; import static org.neo4j.kernel.impl.transaction.log.TransactionIdStore.BASE_TX_ID;
import static org.neo4j.register.Register.DoubleLongRegister;
import static org.neo4j.register.Registers.newDoubleLongRegister; import static org.neo4j.register.Registers.newDoubleLongRegister;


public class CountsRotationTest public class CountsRotationTest
Expand Down Expand Up @@ -121,16 +122,17 @@ public void shouldRotateCountsStoreWhenClosingTheDatabase() throws IOException
public void shouldRotateCountsStoreWhenRotatingLog() throws IOException public void shouldRotateCountsStoreWhenRotatingLog() throws IOException
{ {
// GIVEN // GIVEN
GraphDatabaseAPI db = (GraphDatabaseAPI) dbBuilder. GraphDatabaseAPI db = (GraphDatabaseAPI) dbBuilder.newGraphDatabase();
setConfig( GraphDatabaseSettings.logical_log_rotation_threshold, "1" ).newGraphDatabase();
// WHEN doing a transaction (actually two, the label-mini-tx also counts)
try ( Transaction tx = db.beginTx() ) try ( Transaction tx = db.beginTx() )
{ {
db.createNode( B ); db.createNode( B );
tx.success(); tx.success();
} }

// and rotating the log (which implies flushing)
// WHEN rotateLog( db );
// we do a log rotation _BEFORE_ this transaction // and creating another node after it
try ( Transaction tx = db.beginTx() ) try ( Transaction tx = db.beginTx() )
{ {
db.createNode( C ); db.createNode( C );
Expand All @@ -142,7 +144,7 @@ public void shouldRotateCountsStoreWhenRotatingLog() throws IOException
assertTrue( fs.fileExists( betaStoreFile() ) ); assertTrue( fs.fileExists( betaStoreFile() ) );


final PageCache pageCache = db.getDependencyResolver().resolveDependency( PageCache.class ); final PageCache pageCache = db.getDependencyResolver().resolveDependency( PageCache.class );
try ( CountsStore store = CountsStore.open( fs, pageCache, alphaStoreFile() ) ) try ( CountsStore store = CountsStore.open( fs, pageCache, betaStoreFile() ) )
{ {
// NOTE since the rotation happens before the second transaction is committed we do not see those changes // NOTE since the rotation happens before the second transaction is committed we do not see those changes
// in the stats // in the stats
Expand All @@ -165,6 +167,11 @@ public void shouldRotateCountsStoreWhenRotatingLog() throws IOException
db.shutdown(); db.shutdown();
} }


private void rotateLog( GraphDatabaseAPI db ) throws IOException
{
db.getDependencyResolver().resolveDependency( LogRotation.class ).rotateLogFile();
}

private final Label A = DynamicLabel.label( "A" ); private final Label A = DynamicLabel.label( "A" );
private final Label B = DynamicLabel.label( "B" ); private final Label B = DynamicLabel.label( "B" );
private final Label C = DynamicLabel.label( "C" ); private final Label C = DynamicLabel.label( "C" );
Expand Down
Expand Up @@ -19,14 +19,14 @@
*/ */
package org.neo4j.kernel.impl.transaction; package org.neo4j.kernel.impl.transaction;


import org.junit.Rule;
import org.junit.Test;

import java.util.Arrays; import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;


import org.junit.Rule;
import org.junit.Test;

import org.neo4j.adversaries.ClassGuardedAdversary; import org.neo4j.adversaries.ClassGuardedAdversary;
import org.neo4j.adversaries.CountingAdversary; import org.neo4j.adversaries.CountingAdversary;
import org.neo4j.adversaries.fs.AdversarialFileSystemAbstraction; import org.neo4j.adversaries.fs.AdversarialFileSystemAbstraction;
Expand All @@ -41,6 +41,7 @@
import org.neo4j.kernel.impl.api.scan.InMemoryLabelScanStoreExtension; import org.neo4j.kernel.impl.api.scan.InMemoryLabelScanStoreExtension;
import org.neo4j.kernel.impl.cache.CacheProvider; import org.neo4j.kernel.impl.cache.CacheProvider;
import org.neo4j.kernel.impl.cache.SoftCacheProvider; import org.neo4j.kernel.impl.cache.SoftCacheProvider;
import org.neo4j.kernel.impl.transaction.log.LogRotation;
import org.neo4j.test.TargetDirectory; import org.neo4j.test.TargetDirectory;


import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
Expand Down Expand Up @@ -68,10 +69,8 @@ public void concurrentlyCommittingTransactionsMustNotRotateOutLoggedCommandsOfFa
"org.neo4j.kernel.impl.nioneo.xa.Command$RelationshipCommand" ); "org.neo4j.kernel.impl.nioneo.xa.Command$RelationshipCommand" );
adversary.disable(); adversary.disable();


Map<String, String> params = stringMap(
"logical_log_rotation_threshold", "1");
String storeDir = dir.directory().getAbsolutePath(); String storeDir = dir.directory().getAbsolutePath();
final EmbeddedGraphDatabase db = new TestEmbeddedGraphDatabase( storeDir, params ) { final EmbeddedGraphDatabase db = new TestEmbeddedGraphDatabase( storeDir, stringMap() ) {
@Override @Override
protected FileSystemAbstraction createFileSystemAbstraction() protected FileSystemAbstraction createFileSystemAbstraction()
{ {
Expand Down Expand Up @@ -179,6 +178,7 @@ public void run()
x.createRelationshipTo( y, DynamicRelationshipType.withName( "r" ) ); x.createRelationshipTo( y, DynamicRelationshipType.withName( "r" ) );
tx.success(); tx.success();
latch.await(); latch.await();
db.getDependencyResolver().resolveDependency( LogRotation.class ).rotateLogFile();
tx.finish(); tx.finish();
} }
catch ( Exception ignore ) catch ( Exception ignore )
Expand Down
Expand Up @@ -19,13 +19,13 @@
*/ */
package org.neo4j.kernel.impl.transaction; package org.neo4j.kernel.impl.transaction;


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

import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;


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

import org.neo4j.graphdb.Label; import org.neo4j.graphdb.Label;
import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.PropertyContainer; import org.neo4j.graphdb.PropertyContainer;
Expand All @@ -37,7 +37,6 @@
import org.neo4j.kernel.GraphDatabaseAPI; import org.neo4j.kernel.GraphDatabaseAPI;
import org.neo4j.kernel.impl.MyRelTypes; import org.neo4j.kernel.impl.MyRelTypes;
import org.neo4j.kernel.impl.transaction.log.LogFileInformation; import org.neo4j.kernel.impl.transaction.log.LogFileInformation;
import org.neo4j.kernel.impl.transaction.log.PhysicalLogFile;
import org.neo4j.kernel.impl.transaction.log.entry.LogEntry; import org.neo4j.kernel.impl.transaction.log.entry.LogEntry;
import org.neo4j.test.DatabaseRule; import org.neo4j.test.DatabaseRule;
import org.neo4j.test.ImpermanentDatabaseRule; import org.neo4j.test.ImpermanentDatabaseRule;
Expand Down Expand Up @@ -76,7 +75,6 @@ public void shouldNotWriteAnyLogCommandInPureReadTransaction() throws Exception
protected void configure( GraphDatabaseBuilder builder ) protected void configure( GraphDatabaseBuilder builder )
{ {
builder.setConfig( GraphDatabaseSettings.cache_type, "none" ); builder.setConfig( GraphDatabaseSettings.cache_type, "none" );
builder.setConfig( GraphDatabaseSettings.logical_log_rotation_threshold, "5");
}; };
}; };


Expand All @@ -99,7 +97,6 @@ public void createDataset() throws IOException
relationship.setProperty( "long", longString( 300 ) ); relationship.setProperty( "long", longString( 300 ) );
tx.success(); tx.success();
} }
db.getDependencyResolver().resolveDependency( PhysicalLogFile.class ).rotationNeeded();
logEntriesWrittenBeforeReadOperations = countLogEntries(); logEntriesWrittenBeforeReadOperations = countLogEntries();
} }


Expand Down
Expand Up @@ -19,19 +19,19 @@
*/ */
package org.neo4j.kernel.impl.transaction.log.pruning; package org.neo4j.kernel.impl.transaction.log.pruning;


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

import org.junit.After; import org.junit.After;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;


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

import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction; import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.mockfs.EphemeralFileSystemAbstraction; import org.neo4j.graphdb.mockfs.EphemeralFileSystemAbstraction;
import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.io.fs.StoreChannel; import org.neo4j.io.fs.StoreChannel;
import org.neo4j.kernel.GraphDatabaseAPI; import org.neo4j.kernel.GraphDatabaseAPI;
import org.neo4j.kernel.impl.transaction.log.LogRotation;
import org.neo4j.kernel.impl.transaction.log.LogVersionBridge; import org.neo4j.kernel.impl.transaction.log.LogVersionBridge;
import org.neo4j.kernel.impl.transaction.log.LogVersionedStoreChannel; import org.neo4j.kernel.impl.transaction.log.LogVersionedStoreChannel;
import org.neo4j.kernel.impl.transaction.log.PhysicalLogFile; import org.neo4j.kernel.impl.transaction.log.PhysicalLogFile;
Expand All @@ -47,7 +47,6 @@
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;


import static org.neo4j.graphdb.factory.GraphDatabaseSettings.keep_logical_logs; import static org.neo4j.graphdb.factory.GraphDatabaseSettings.keep_logical_logs;
import static org.neo4j.graphdb.factory.GraphDatabaseSettings.logical_log_rotation_threshold;
import static org.neo4j.helpers.collection.MapUtil.stringMap; import static org.neo4j.helpers.collection.MapUtil.stringMap;
import static org.neo4j.kernel.impl.transaction.log.entry.LogVersions.CURRENT_LOG_VERSION; import static org.neo4j.kernel.impl.transaction.log.entry.LogVersions.CURRENT_LOG_VERSION;


Expand All @@ -58,11 +57,10 @@ private interface Extractor
int extract( File from ) throws IOException; int extract( File from ) throws IOException;
} }


// From the last measurement by figureOutSampleTransactionSizeBytes
private final int transactionLogSize = 358;
private GraphDatabaseAPI db; private GraphDatabaseAPI db;
private FileSystemAbstraction fs; private FileSystemAbstraction fs;
private PhysicalLogFiles files; private PhysicalLogFiles files;
private int rotateEveryNTransactions, performedTransactions;


@After @After
public void after() throws Exception public void after() throws Exception
Expand All @@ -76,7 +74,7 @@ public void after() throws Exception
@Test @Test
public void noPruning() throws Exception public void noPruning() throws Exception
{ {
newDb( "true", transactionLogSize * 2 ); newDb( "true", 2 );


for ( int i = 0; i < 100; i++ ) for ( int i = 0; i < 100; i++ )
{ {
Expand All @@ -95,25 +93,27 @@ public void noPruning() throws Exception
public void pruneByFileSize() throws Exception public void pruneByFileSize() throws Exception
{ {
// Given // Given
int size = 1050; int transactionByteSize = figureOutSampleTransactionSizeBytes();
int logThreshold = transactionLogSize * 3; int transactionsPerFile = 3;
newDb( size + " size", logThreshold ); int logThreshold = transactionByteSize * transactionsPerFile;
newDb( logThreshold + " size", 1 );


// When // When
for ( int i = 0; i < 100; i++ ) for ( int i = 0; i < 100; i++ )
{ {
doTransaction(); doTransaction();
} }


int logFileSize = logFileSize(); int totalLogFileSize = logFileSize();
assertTrue( logFileSize >= size - logThreshold && logFileSize <= size + logThreshold ); double totalTransactions = (double) totalLogFileSize / transactionByteSize;
assertTrue( totalTransactions >= 3 && totalTransactions < 4 );
} }


@Test @Test
public void pruneByFileCount() throws Exception public void pruneByFileCount() throws Exception
{ {
int logsToKeep = 5; int logsToKeep = 5;
newDb( logsToKeep + " files", transactionLogSize * 3 ); newDb( logsToKeep + " files", 3 );


for ( int i = 0; i < 100; i++ ) for ( int i = 0; i < 100; i++ )
{ {
Expand All @@ -128,9 +128,8 @@ public void pruneByFileCount() throws Exception
public void pruneByTransactionCount() throws Exception public void pruneByTransactionCount() throws Exception
{ {
int transactionsToKeep = 100; int transactionsToKeep = 100;

int transactionsPerLog = 3; int transactionsPerLog = 3;
newDb( transactionsToKeep + " txs", transactionsToKeep * transactionsPerLog ); newDb( transactionsToKeep + " txs", 3 );


for ( int i = 0; i < 100; i++ ) for ( int i = 0; i < 100; i++ )
{ {
Expand All @@ -145,12 +144,12 @@ public void pruneByTransactionCount() throws Exception
transactionCount <= (transactionsToKeep + transactionsPerLog) ); transactionCount <= (transactionsToKeep + transactionsPerLog) );
} }


private GraphDatabaseAPI newDb( String logPruning, int rotateThreshold ) private GraphDatabaseAPI newDb( String logPruning, int rotateEveryNTransactions )
{ {
this.rotateEveryNTransactions = rotateEveryNTransactions;
fs = new EphemeralFileSystemAbstraction(); fs = new EphemeralFileSystemAbstraction();
GraphDatabaseAPI db = new ImpermanentGraphDatabase( stringMap( GraphDatabaseAPI db = new ImpermanentGraphDatabase( stringMap(
keep_logical_logs.name(), logPruning, keep_logical_logs.name(), logPruning
logical_log_rotation_threshold.name(), "" + rotateThreshold
) ) ) )
{ {
@Override @Override
Expand All @@ -164,8 +163,14 @@ protected FileSystemAbstraction createFileSystemAbstraction()
return db; return db;
} }


private void doTransaction() private void doTransaction() throws IOException
{ {
if ( ++performedTransactions >= rotateEveryNTransactions )
{
db.getDependencyResolver().resolveDependency( LogRotation.class ).rotateLogFile();
performedTransactions = 0;
}

try ( Transaction tx = db.beginTx() ) try ( Transaction tx = db.beginTx() )
{ {
Node node = db.createNode(); Node node = db.createNode();
Expand All @@ -174,14 +179,12 @@ private void doTransaction()
} }
} }


@Test private int figureOutSampleTransactionSizeBytes() throws IOException
@Ignore( "Here as a helper to figure out the transaction size of the sample transaction on disk" )
public void figureOutSampleTransactionSizeBytes()
{ {
db = newDb( "true", transactionLogSize * 2 ); db = newDb( "true", 5 );
doTransaction(); doTransaction();
db.shutdown(); db.shutdown();
System.out.println( fs.getFileSize( files.getLogFileForVersion( 0 ) ) ); return (int) fs.getFileSize( files.getLogFileForVersion( 0 ) );
} }


private int aggregateLogData( Extractor extractor ) throws IOException private int aggregateLogData( Extractor extractor ) throws IOException
Expand Down

0 comments on commit 9356988

Please sign in to comment.