Skip to content

Commit

Permalink
Mover store id check from EdgeServerStarupProcess to LocalDatabase
Browse files Browse the repository at this point in the history
  • Loading branch information
davidegrohmann committed Jul 4, 2016
1 parent 93e697d commit 5575f11
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 34 deletions.
Expand Up @@ -27,11 +27,12 @@
import org.neo4j.coreedge.catchup.storecopy.edge.StoreFetcher;
import org.neo4j.coreedge.server.CoreMember;
import org.neo4j.coreedge.server.StoreId;
import org.neo4j.kernel.NeoStoreDataSource;
import org.neo4j.kernel.impl.transaction.log.TransactionIdStore;
import org.neo4j.kernel.impl.transaction.state.DataSourceManager;
import org.neo4j.kernel.internal.DatabaseHealth;

import static java.lang.String.format;

public class LocalDatabase implements Supplier<StoreId>
{
private final File storeDir;
Expand All @@ -45,11 +46,8 @@ public class LocalDatabase implements Supplier<StoreId>
private volatile StoreId storeId;
private volatile DatabaseHealth databaseHealth;

public LocalDatabase(
File storeDir,
CopiedStoreRecovery copiedStoreRecovery, StoreFiles storeFiles,
DataSourceManager dataSourceManager,
Supplier<TransactionIdStore> transactionIdStoreSupplier,
public LocalDatabase( File storeDir, CopiedStoreRecovery copiedStoreRecovery, StoreFiles storeFiles,
DataSourceManager dataSourceManager, Supplier<TransactionIdStore> transactionIdStoreSupplier,
Supplier<DatabaseHealth> databaseHealthSupplier )
{
this.storeDir = storeDir;
Expand All @@ -76,8 +74,8 @@ public StoreId storeId()
if ( storeId == null )
{
org.neo4j.kernel.impl.store.StoreId kernelStoreId = dataSourceManager.getDataSource().getStoreId();
storeId = new StoreId( kernelStoreId.getCreationTime(),
kernelStoreId.getRandomId(), kernelStoreId.getUpgradeTime(), kernelStoreId.getUpgradeId() );
storeId = new StoreId( kernelStoreId.getCreationTime(), kernelStoreId.getRandomId(),
kernelStoreId.getUpgradeTime(), kernelStoreId.getUpgradeId() );
}
return storeId;
}
Expand Down Expand Up @@ -111,7 +109,6 @@ public void copyStoreFrom( CoreMember from, StoreFetcher storeFetcher ) throws S
try
{
storeFiles.delete( storeDir );

TemporaryStoreDirectory tempStore = new TemporaryStoreDirectory( storeDir );
storeFetcher.copyStore( from, tempStore.storeDir() );
copiedStoreRecovery.recoverCopiedStore( tempStore.storeDir() );
Expand Down Expand Up @@ -139,4 +136,17 @@ public StoreId get()
{
return storeId();
}

public void ensureSameStoreId( CoreMember coreMember, StoreFetcher storeFetcher )
throws StoreIdDownloadFailedException
{
StoreId localStoreId = storeId();
StoreId remoteStoreId = storeFetcher.storeId( coreMember );
if ( !localStoreId.equals( remoteStoreId ) )
{
throw new IllegalStateException( format( "This edge machine cannot join the cluster. " +
"The local database is not empty and has a mismatching storeId: expected %s actual %s.",
remoteStoreId, localStoreId ) );
}
}
}
Expand Up @@ -90,14 +90,7 @@ public void start() throws Throwable
}
else
{
StoreId localStoreId = localDatabase.storeId();
StoreId remoteStoreId = storeFetcher.storeId( coreMember );
if ( !localStoreId.equals( remoteStoreId ) )
{
throw new IllegalStateException( format( "This edge machine cannot join the cluster. " +
"The local database is not empty and has a mismatching storeId: expected %s actual %s.",
remoteStoreId, localStoreId ) );
}
localDatabase.ensureSameStoreId( coreMember, storeFetcher );
}

txPulling.start();
Expand Down
Expand Up @@ -19,6 +19,7 @@
*/
package org.neo4j.coreedge;

import org.apache.lucene.document.Field;
import org.junit.Test;

import java.util.Collections;
Expand Down Expand Up @@ -46,6 +47,7 @@
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
Expand Down Expand Up @@ -97,18 +99,17 @@ public void startShouldNotReplaceTheNonEmptyLocalStoreWithStoreFromCoreServerAnd
{
// given
StoreFetcher storeFetcher = mock( StoreFetcher.class );
when( storeFetcher.storeId( any( CoreMember.class ) ) ).thenReturn( new StoreId( 1, 2, 3, 4 ) );
CoreMember coreMember = new CoreMember( UUID.randomUUID() );
LocalDatabase localDatabase = mock( LocalDatabase.class );
when( localDatabase.storeId() ).thenReturn( new StoreId( 5, 6, 7, 8 ) );
when( localDatabase.isEmpty() ).thenReturn( false );
doThrow( IllegalStateException.class ).when( localDatabase ).ensureSameStoreId( coreMember, storeFetcher );

CoreMember coreMember = new CoreMember( UUID.randomUUID() );
TopologyService hazelcastTopology = mock( TopologyService.class );

ClusterTopology clusterTopology = mock( ClusterTopology.class );
when( hazelcastTopology.currentTopology() ).thenReturn( clusterTopology );

when( clusterTopology.coreMembers() ).thenReturn( asSet( coreMember ) );
when( localDatabase.isEmpty() ).thenReturn( false );

DataSourceManager dataSourceManager = mock( DataSourceManager.class );
Lifecycle txPulling = mock( Lifecycle.class );
Expand All @@ -122,7 +123,7 @@ txPulling, dataSourceManager, new AlwaysChooseFirstServer( hazelcastTopology ),
try
{
edgeServerStartupProcess.start();
fail( "shoud have thrown" );
fail( "should have thrown" );
}
catch ( IllegalStateException ex )
{
Expand All @@ -131,10 +132,9 @@ txPulling, dataSourceManager, new AlwaysChooseFirstServer( hazelcastTopology ),

// then
verify( dataSourceManager ).start();
verify( storeFetcher ).storeId( any() );
verify( localDatabase ).isEmpty();
verify( localDatabase ).storeId();
verifyNoMoreInteractions( localDatabase, dataSourceManager, storeFetcher );
verify( localDatabase ).ensureSameStoreId( coreMember, storeFetcher );
verifyNoMoreInteractions( localDatabase, dataSourceManager );
verifyZeroInteractions( txPulling );
}

Expand Down Expand Up @@ -170,11 +170,10 @@ txPulling, dataSourceManager, new AlwaysChooseFirstServer( hazelcastTopology ),

// then
verify( localDatabase ).isEmpty();
verify( localDatabase ).storeId();
verify( localDatabase ).ensureSameStoreId( coreMember, storeFetcher );
verify( dataSourceManager ).start();
verify( storeFetcher ).storeId( any() );
verify( txPulling ).start();
verifyNoMoreInteractions( localDatabase, dataSourceManager, txPulling, storeFetcher );
verifyNoMoreInteractions( localDatabase, dataSourceManager, txPulling );
}

@Test
Expand Down
Expand Up @@ -24,6 +24,8 @@
import java.io.File;

import org.neo4j.coreedge.catchup.storecopy.edge.CopiedStoreRecovery;
import org.neo4j.coreedge.catchup.storecopy.edge.StoreFetcher;
import org.neo4j.coreedge.server.CoreMember;
import org.neo4j.coreedge.server.StoreId;
import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.kernel.NeoStoreDataSource;
Expand All @@ -32,6 +34,9 @@
import org.neo4j.kernel.internal.DatabaseHealth;

import static junit.framework.TestCase.assertEquals;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.neo4j.function.Suppliers.singleton;
Expand All @@ -45,16 +50,61 @@ public void shouldRetrieveStoreId() throws Throwable
StoreId storeId = new StoreId( 1, 2, 3, 4 );

// when
LocalDatabase localDatabase = createLocalDatabase( new org.neo4j.kernel.impl.store.StoreId( 1, 2, 5, 3, 4 ) );

// then
assertEquals( storeId, localDatabase.storeId() );
}

@Test
public void shouldNotThrowWhenSameStoreIds() throws Throwable
{
// given
StoreId storeId = new StoreId( 1, 2, 3, 4 );
CoreMember coreMember = mock( CoreMember.class );
StoreFetcher storeFetcher = mock( StoreFetcher.class );
when( storeFetcher.storeId( coreMember ) ).thenReturn( storeId );

// when
LocalDatabase localDatabase = createLocalDatabase( new org.neo4j.kernel.impl.store.StoreId( 1, 2, 5, 3, 4 ) );

localDatabase.ensureSameStoreId( coreMember, storeFetcher );

// no exception is thrown
}

@Test
public void shouldThrowWhenDifferentStoreIds() throws Throwable
{
// given
StoreId storeId = new StoreId( 6, 7, 8, 9 );
CoreMember coreMember = mock( CoreMember.class );
StoreFetcher storeFetcher = mock( StoreFetcher.class );
when( storeFetcher.storeId( coreMember ) ).thenReturn( storeId );

// when
LocalDatabase localDatabase = createLocalDatabase( new org.neo4j.kernel.impl.store.StoreId( 1, 2, 5, 3, 4 ) );

try
{
localDatabase.ensureSameStoreId( coreMember, storeFetcher );
fail( "should have thrown ");
}
catch ( IllegalStateException ex )
{
assertThat( ex.getMessage(), containsString( "This edge machine cannot join the cluster. " +
"The local database is not empty and has a mismatching storeId:" ) );
}
}

private LocalDatabase createLocalDatabase( org.neo4j.kernel.impl.store.StoreId storeId )
{
DataSourceManager dataSourceManager = mock( DataSourceManager.class );
NeoStoreDataSource neoStoreDataSource = mock( NeoStoreDataSource.class );
when( dataSourceManager.getDataSource() ).thenReturn( neoStoreDataSource );
when( neoStoreDataSource.getStoreId() ).thenReturn( new org.neo4j.kernel.impl.store.StoreId( 1, 2, 5, 3, 4 ) );

LocalDatabase localDatabase = new LocalDatabase( new File( "directory" ), mock( CopiedStoreRecovery.class ),
when( neoStoreDataSource.getStoreId() ).thenReturn( storeId );
return new LocalDatabase( new File( "directory" ), mock( CopiedStoreRecovery.class ),
new StoreFiles( mock( FileSystemAbstraction.class ) ), dataSourceManager,
singleton( mock( TransactionIdStore.class ) ), () -> mock( DatabaseHealth.class ) );

// then
assertEquals( storeId, localDatabase.storeId() );
}
}

0 comments on commit 5575f11

Please sign in to comment.