use of org.neo4j.kernel.ha.com.master.HandshakeResult in project neo4j by neo4j.
the class SwitchToSlaveCopyThenBranchTest method shouldHandleBranchedStoreWhenMyStoreIdDiffersFromMasterStoreId.
@Test
@SuppressWarnings("unchecked")
public void shouldHandleBranchedStoreWhenMyStoreIdDiffersFromMasterStoreId() throws Throwable {
// Given
SwitchToSlaveCopyThenBranch switchToSlave = newSwitchToSlaveSpy();
URI me = new URI("cluster://localhost?serverId=2");
MasterClient masterClient = mock(MasterClient.class);
Response<HandshakeResult> response = mock(Response.class);
when(response.response()).thenReturn(new HandshakeResult(1, 2));
when(masterClient.handshake(anyLong(), any(StoreId.class))).thenReturn(response);
StoreId storeId = newStoreIdForCurrentVersion(1, 2, 3, 4);
TransactionIdStore transactionIdStore = mock(TransactionIdStore.class);
when(transactionIdStore.getLastCommittedTransaction()).thenReturn(new TransactionId(42, 42, 42));
when(transactionIdStore.getLastCommittedTransactionId()).thenReturn(TransactionIdStore.BASE_TX_ID);
// When
try {
switchToSlave.checkDataConsistency(masterClient, transactionIdStore, storeId, new URI("cluster://localhost?serverId=1"), me, CancellationRequest.NEVER_CANCELLED);
fail("Should have thrown " + MismatchingStoreIdException.class.getSimpleName() + " exception");
} catch (MismatchingStoreIdException e) {
// good we got the expected exception
}
// Then
verify(switchToSlave).stopServicesAndHandleBranchedStore(any(BranchedDataPolicy.class), any(URI.class), any(URI.class), any(CancellationRequest.class));
}
use of org.neo4j.kernel.ha.com.master.HandshakeResult in project neo4j by neo4j.
the class SwitchToSlaveCopyThenBranchTest method newSwitchToSlaveSpy.
@SuppressWarnings("unchecked")
private SwitchToSlaveCopyThenBranch newSwitchToSlaveSpy(PageCache pageCacheMock, StoreCopyClient storeCopyClient) throws IOException {
ClusterMembers clusterMembers = mock(ClusterMembers.class);
ClusterMember master = mock(ClusterMember.class);
when(master.getStoreId()).thenReturn(storeId);
when(master.getHARole()).thenReturn(HighAvailabilityModeSwitcher.MASTER);
when(master.hasRole(eq(HighAvailabilityModeSwitcher.MASTER))).thenReturn(true);
when(master.getInstanceId()).thenReturn(new InstanceId(1));
when(clusterMembers.getMembers()).thenReturn(asList(master));
Dependencies resolver = new Dependencies();
resolver.satisfyDependencies(requestContextFactory, clusterMembers, mock(TransactionObligationFulfiller.class), mock(OnlineBackupKernelExtension.class), mock(IndexConfigStore.class), mock(TransactionCommittingResponseUnpacker.class), mock(DataSourceManager.class), mock(StoreLockerLifecycleAdapter.class), mock(FileSystemWatcherService.class));
NeoStoreDataSource dataSource = mock(NeoStoreDataSource.class);
when(dataSource.getStoreId()).thenReturn(storeId);
TransactionStats transactionCounters = mock(TransactionStats.class);
when(transactionCounters.getNumberOfActiveTransactions()).thenReturn(0L);
Response<HandshakeResult> response = mock(Response.class);
when(response.response()).thenReturn(new HandshakeResult(42, 2));
when(masterClient.handshake(anyLong(), any(StoreId.class))).thenReturn(response);
when(masterClient.getProtocolVersion()).thenReturn(MasterClient.CURRENT);
TransactionIdStore transactionIdStoreMock = mock(TransactionIdStore.class);
// note that the checksum (the second member of the array) is the same as the one in the handshake mock above
when(transactionIdStoreMock.getLastCommittedTransaction()).thenReturn(new TransactionId(42, 42, 42));
MasterClientResolver masterClientResolver = mock(MasterClientResolver.class);
when(masterClientResolver.instantiate(anyString(), anyInt(), anyString(), any(Monitors.class), any(StoreId.class), any(LifeSupport.class))).thenReturn(masterClient);
return spy(new SwitchToSlaveCopyThenBranch(new File(""), NullLogService.getInstance(), configMock(), resolver, mock(HaIdGeneratorFactory.class), mock(DelegateInvocationHandler.class), mock(ClusterMemberAvailability.class), requestContextFactory, pullerFactory, masterClientResolver, mock(SwitchToSlave.Monitor.class), storeCopyClient, Suppliers.singleton(dataSource), Suppliers.singleton(transactionIdStoreMock), slave -> {
SlaveServer server = mock(SlaveServer.class);
InetSocketAddress inetSocketAddress = InetSocketAddress.createUnresolved("localhost", 42);
when(server.getSocketAddress()).thenReturn(inetSocketAddress);
return server;
}, updatePuller, pageCacheMock, mock(Monitors.class), transactionCounters));
}
use of org.neo4j.kernel.ha.com.master.HandshakeResult in project neo4j by neo4j.
the class HighAvailabilityMemberStateMachineTest method whenHAModeSwitcherSwitchesToSlaveTheOtherModeSwitcherDoNotGetTheOldMasterClient.
@Test
public void whenHAModeSwitcherSwitchesToSlaveTheOtherModeSwitcherDoNotGetTheOldMasterClient() throws Throwable {
InstanceId me = new InstanceId(1);
StoreId storeId = newStoreIdForCurrentVersion();
HighAvailabilityMemberContext context = mock(HighAvailabilityMemberContext.class);
when(context.getMyId()).thenReturn(me);
AvailabilityGuard guard = mock(AvailabilityGuard.class);
ObservedClusterMembers members = mock(ObservedClusterMembers.class);
ClusterMember masterMember = mock(ClusterMember.class);
when(masterMember.getHARole()).thenReturn("master");
when(masterMember.hasRole("master")).thenReturn(true);
when(masterMember.getInstanceId()).thenReturn(new InstanceId(2));
when(masterMember.getStoreId()).thenReturn(storeId);
ClusterMember self = new ClusterMember(me);
when(members.getMembers()).thenReturn(Arrays.asList(self, masterMember));
when(members.getCurrentMember()).thenReturn(self);
DependencyResolver dependencyResolver = mock(DependencyResolver.class);
FileSystemAbstraction fs = mock(FileSystemAbstraction.class);
when(fs.fileExists(any(File.class))).thenReturn(true);
when(dependencyResolver.resolveDependency(FileSystemAbstraction.class)).thenReturn(fs);
when(dependencyResolver.resolveDependency(Monitors.class)).thenReturn(new Monitors());
NeoStoreDataSource dataSource = mock(NeoStoreDataSource.class);
when(dataSource.getDependencyResolver()).thenReturn(dependencyResolver);
when(dataSource.getStoreId()).thenReturn(storeId);
when(dependencyResolver.resolveDependency(NeoStoreDataSource.class)).thenReturn(dataSource);
when(dependencyResolver.resolveDependency(TransactionIdStore.class)).thenReturn(new DeadSimpleTransactionIdStore());
when(dependencyResolver.resolveDependency(ObservedClusterMembers.class)).thenReturn(members);
UpdatePuller updatePuller = mock(UpdatePuller.class);
when(updatePuller.tryPullUpdates()).thenReturn(true);
when(dependencyResolver.resolveDependency(UpdatePuller.class)).thenReturn(updatePuller);
ClusterMemberAvailability clusterMemberAvailability = mock(ClusterMemberAvailability.class);
final TriggerableClusterMemberEvents events = new TriggerableClusterMemberEvents();
Election election = mock(Election.class);
HighAvailabilityMemberStateMachine stateMachine = new HighAvailabilityMemberStateMachine(context, guard, members, events, election, NullLogProvider.getInstance());
ClusterMembers clusterMembers = new ClusterMembers(members, stateMachine);
when(dependencyResolver.resolveDependency(ClusterMembers.class)).thenReturn(clusterMembers);
stateMachine.init();
stateMachine.start();
final DelegateInvocationHandler<Master> handler = new DelegateInvocationHandler<>(Master.class);
MasterClientResolver masterClientResolver = mock(MasterClientResolver.class);
MasterClient masterClient = mock(MasterClient.class);
when(masterClient.getProtocolVersion()).thenReturn(MasterClient214.PROTOCOL_VERSION);
when(masterClient.handshake(anyLong(), any(StoreId.class))).thenReturn(new Response<HandshakeResult>(new HandshakeResult(0, 42), storeId, mock(ResourceReleaser.class)) {
@Override
public void accept(Handler handler) throws IOException {
}
@Override
public boolean hasTransactionsToBeApplied() {
return false;
}
});
when(masterClient.toString()).thenReturn("TheExpectedMasterClient!");
when(masterClientResolver.instantiate(anyString(), anyInt(), anyString(), any(Monitors.class), any(StoreId.class), any(LifeSupport.class))).thenReturn(masterClient);
final CountDownLatch latch = new CountDownLatch(2);
final AtomicBoolean switchedSuccessfully = new AtomicBoolean();
SwitchToSlave.Monitor monitor = new SwitchToSlave.Monitor() {
@Override
public void switchToSlaveCompleted(boolean wasSuccessful) {
switchedSuccessfully.set(wasSuccessful);
latch.countDown();
}
};
Config config = Config.embeddedDefaults(Collections.singletonMap(ClusterSettings.server_id.name(), me.toString()));
TransactionStats transactionCounters = mock(TransactionStats.class);
when(transactionCounters.getNumberOfActiveTransactions()).thenReturn(0L);
PageCache pageCacheMock = mock(PageCache.class);
PagedFile pagedFileMock = mock(PagedFile.class);
when(pagedFileMock.getLastPageId()).thenReturn(1L);
when(pageCacheMock.map(any(File.class), anyInt())).thenReturn(pagedFileMock);
TransactionIdStore transactionIdStoreMock = mock(TransactionIdStore.class);
when(transactionIdStoreMock.getLastCommittedTransaction()).thenReturn(new TransactionId(0, 0, 0));
SwitchToSlaveCopyThenBranch switchToSlave = new SwitchToSlaveCopyThenBranch(new File(""), NullLogService.getInstance(), mock(FileSystemAbstraction.class), config, dependencyResolver, mock(HaIdGeneratorFactory.class), handler, mock(ClusterMemberAvailability.class), mock(RequestContextFactory.class), mock(PullerFactory.class, RETURNS_MOCKS), Iterables.empty(), masterClientResolver, monitor, new StoreCopyClient.Monitor.Adapter(), Suppliers.singleton(dataSource), Suppliers.singleton(transactionIdStoreMock), slave -> {
SlaveServer mock = mock(SlaveServer.class);
when(mock.getSocketAddress()).thenReturn(new InetSocketAddress("localhost", 123));
return mock;
}, updatePuller, pageCacheMock, mock(Monitors.class), transactionCounters);
ComponentSwitcherContainer switcherContainer = new ComponentSwitcherContainer();
HighAvailabilityModeSwitcher haModeSwitcher = new HighAvailabilityModeSwitcher(switchToSlave, mock(SwitchToMaster.class), election, clusterMemberAvailability, mock(ClusterClient.class), storeSupplierMock(), me, switcherContainer, neoStoreDataSourceSupplierMock(), NullLogService.getInstance());
haModeSwitcher.init();
haModeSwitcher.start();
haModeSwitcher.listeningAt(URI.create("http://localhost:12345"));
stateMachine.addHighAvailabilityMemberListener(haModeSwitcher);
final AtomicReference<Master> ref = new AtomicReference<>(null);
//noinspection unchecked
AbstractComponentSwitcher<Object> otherModeSwitcher = new AbstractComponentSwitcher<Object>(mock(DelegateInvocationHandler.class)) {
@Override
protected Object getSlaveImpl() {
Master master = handler.cement();
ref.set(master);
latch.countDown();
return null;
}
@Override
protected Object getMasterImpl() {
return null;
}
};
switcherContainer.add(otherModeSwitcher);
// When
events.switchToSlave(me);
// Then
latch.await();
assertTrue("mode switch failed", switchedSuccessfully.get());
Master actual = ref.get();
// let's test the toString()s since there are too many wrappers of proxies
assertEquals(masterClient.toString(), actual.toString());
stateMachine.stop();
stateMachine.shutdown();
haModeSwitcher.stop();
haModeSwitcher.shutdown();
}
use of org.neo4j.kernel.ha.com.master.HandshakeResult in project neo4j by neo4j.
the class SwitchToSlave method checkDataConsistencyWithMaster.
void checkDataConsistencyWithMaster(URI availableMasterId, Master master, StoreId storeId, TransactionIdStore transactionIdStore) {
TransactionId myLastCommittedTxData = transactionIdStore.getLastCommittedTransaction();
long myLastCommittedTx = myLastCommittedTxData.transactionId();
HandshakeResult handshake;
try (Response<HandshakeResult> response = master.handshake(myLastCommittedTx, storeId)) {
handshake = response.response();
requestContextFactory.setEpoch(handshake.epoch());
} catch (BranchedDataException e) {
// Rethrow wrapped in a branched data exception on our side, to clarify where the problem originates.
throw new BranchedDataException("The database stored on this machine has diverged from that " + "of the master. This will be automatically resolved.", e);
} catch (RuntimeException e) {
// server-side exception
if (e.getCause() instanceof MissingLogDataException) {
/*
* This means the master was unable to find a log entry for the txid we just asked. This
* probably means the thing we asked for is too old or too new. Anyway, since it doesn't
* have the tx it is better if we just throw our store away and ask for a new copy. Next
* time around it shouldn't have to even pass from here.
*/
throw new StoreOutOfDateException("The master is missing the log required to complete the " + "consistency check", e.getCause());
}
throw e;
}
long myChecksum = myLastCommittedTxData.checksum();
if (myChecksum != handshake.txChecksum()) {
String msg = "The cluster contains two logically different versions of the database.. This will be " + "automatically resolved. Details: I (server_id:" + config.get(ClusterSettings.server_id) + ") think checksum for txId (" + myLastCommittedTx + ") is " + myChecksum + ", but master (server_id:" + getServerId(availableMasterId) + ") says that it's " + handshake.txChecksum() + ", where handshake is " + handshake;
throw new BranchedDataException(msg);
}
msgLog.info("Checksum for last committed tx ok with lastTxId=" + myLastCommittedTx + " with checksum=" + myChecksum, true);
}
use of org.neo4j.kernel.ha.com.master.HandshakeResult in project neo4j by neo4j.
the class MasterEpochTest method shouldFailSubsequentRequestsAfterAllocateIdsAfterMasterSwitch.
@Test
public void shouldFailSubsequentRequestsAfterAllocateIdsAfterMasterSwitch() throws Throwable {
// GIVEN
SPI spi = MasterImplTest.mockedSpi();
IdAllocation servedIdAllocation = idAllocation(0, 999);
when(spi.allocateIds(any(IdType.class))).thenReturn(servedIdAllocation);
when(spi.getTransactionChecksum(anyLong())).thenReturn(10L);
StoreId storeId = newStoreIdForCurrentVersion();
MasterImpl master = new MasterImpl(spi, mock(ConversationManager.class), mock(MasterImpl.Monitor.class), Config.embeddedDefaults(stringMap(ClusterSettings.server_id.name(), "1")));
HandshakeResult handshake = master.handshake(1, storeId).response();
master.start();
// WHEN/THEN
IdAllocation idAllocation = master.allocateIds(context(handshake.epoch()), IdType.NODE).response();
assertEquals(servedIdAllocation.getHighestIdInUse(), idAllocation.getHighestIdInUse());
try {
master.allocateIds(context(handshake.epoch() + 1), IdType.NODE);
fail("Should fail with invalid epoch");
} catch (InvalidEpochException e) {
// Good
}
}
Aggregations