Search in sources :

Example 6 with SwitchToSlaveCopyThenBranch

use of org.neo4j.kernel.ha.cluster.SwitchToSlaveCopyThenBranch in project neo4j by neo4j.

the class HighAvailabilityModeSwitcherTest method shouldNotResetAvailableMasterURIIfElectionResultReceived.

@Test
public void shouldNotResetAvailableMasterURIIfElectionResultReceived() throws Throwable {
    /*
         * It is possible that a masterIsElected nulls out the current available master URI in the HAMS. That can
         * be a problem if handing the mIE event is concurrent with an ongoing switch which re-runs because
         * the store was incompatible or a log was missing. In such a case it will find a null master URI on
         * rerun and it will fail.
         */
    // Given
    SwitchToSlaveCopyThenBranch switchToSlave = mock(SwitchToSlaveCopyThenBranch.class);
    // The fist run through switchToSlave
    final CountDownLatch firstCallMade = new CountDownLatch(1);
    // The second run through switchToSlave
    final CountDownLatch secondCallMade = new CountDownLatch(1);
    // The latch for waiting for the masterIsElected to come through
    final CountDownLatch waitForSecondMessage = new CountDownLatch(1);
    HighAvailabilityModeSwitcher toTest = new HighAvailabilityModeSwitcher(switchToSlave, mock(SwitchToMaster.class), mock(Election.class), mock(ClusterMemberAvailability.class), mock(ClusterClient.class), storeSupplierMock(), new InstanceId(1), new ComponentSwitcherContainer(), neoStoreDataSourceSupplierMock(), NullLogService.getInstance());
    URI uri1 = URI.create("ha://server1");
    toTest.init();
    toTest.start();
    toTest.listeningAt(URI.create("ha://server3?serverId=3"));
    when(switchToSlave.switchToSlave(any(LifeSupport.class), any(URI.class), any(URI.class), any(CancellationRequest.class))).thenAnswer(invocation -> {
        firstCallMade.countDown();
        waitForSecondMessage.await();
        throw new MismatchingStoreIdException(StoreId.DEFAULT, StoreId.DEFAULT);
    }).thenAnswer(invocation -> {
        secondCallMade.countDown();
        return URI.create("ha://server3");
    });
    // When
    // The first message goes through, start the first run
    toTest.masterIsAvailable(new HighAvailabilityMemberChangeEvent(PENDING, TO_SLAVE, new InstanceId(1), uri1));
    // Wait for it to be processed but get just before the exception
    firstCallMade.await();
    // It is just about to throw the exception, i.e. rerun. Send in the event
    toTest.masterIsElected(new HighAvailabilityMemberChangeEvent(TO_SLAVE, TO_SLAVE, new InstanceId(1), null));
    // Allow to continue and do the second run
    waitForSecondMessage.countDown();
    // Wait for the call to finish
    secondCallMade.await();
    // Then
    verify(switchToSlave, times(2)).switchToSlave(any(LifeSupport.class), any(URI.class), eq(uri1), any(CancellationRequest.class));
}
Also used : InstanceId(org.neo4j.cluster.InstanceId) StoreId(org.neo4j.kernel.impl.store.StoreId) ScheduledFuture(java.util.concurrent.ScheduledFuture) NeoStoreDataSource(org.neo4j.kernel.NeoStoreDataSource) SwitchToMaster(org.neo4j.kernel.ha.cluster.SwitchToMaster) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) TO_SLAVE(org.neo4j.kernel.ha.cluster.HighAvailabilityMemberState.TO_SLAVE) Callable(java.util.concurrent.Callable) LifeSupport(org.neo4j.kernel.lifecycle.LifeSupport) NullLogProvider(org.neo4j.logging.NullLogProvider) Supplier(java.util.function.Supplier) Mockito.verifyZeroInteractions(org.mockito.Mockito.verifyZeroInteractions) Answer(org.mockito.stubbing.Answer) Mockito.doThrow(org.mockito.Mockito.doThrow) Future(java.util.concurrent.Future) PENDING(org.neo4j.kernel.ha.cluster.HighAvailabilityMemberState.PENDING) AssertableLogProvider(org.neo4j.logging.AssertableLogProvider) Matchers.eq(org.mockito.Matchers.eq) CancellationRequest(org.neo4j.helpers.CancellationRequest) Mockito.doAnswer(org.mockito.Mockito.doAnswer) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) Matchers.anyLong(org.mockito.Matchers.anyLong) URI(java.net.URI) MismatchingStoreIdException(org.neo4j.kernel.impl.store.MismatchingStoreIdException) ExecutorService(java.util.concurrent.ExecutorService) HighAvailabilityMemberState(org.neo4j.kernel.ha.cluster.HighAvailabilityMemberState) InOrder(org.mockito.InOrder) ComException(org.neo4j.com.ComException) SwitchToSlaveCopyThenBranch(org.neo4j.kernel.ha.cluster.SwitchToSlaveCopyThenBranch) Test(org.junit.Test) Mockito.times(org.mockito.Mockito.times) AssertableLogProvider.inLog(org.neo4j.logging.AssertableLogProvider.inLog) Election(org.neo4j.cluster.protocol.election.Election) Mockito.when(org.mockito.Mockito.when) DataSourceManager(org.neo4j.kernel.impl.transaction.state.DataSourceManager) Executors(java.util.concurrent.Executors) Mockito.verify(org.mockito.Mockito.verify) TimeUnit(java.util.concurrent.TimeUnit) Matchers.any(org.mockito.Matchers.any) CountDownLatch(java.util.concurrent.CountDownLatch) NullLogService(org.neo4j.kernel.impl.logging.NullLogService) ClusterMemberAvailability(org.neo4j.cluster.member.ClusterMemberAvailability) Mockito.inOrder(org.mockito.Mockito.inOrder) SimpleLogService(org.neo4j.kernel.impl.logging.SimpleLogService) ClusterClient(org.neo4j.cluster.client.ClusterClient) HighAvailabilityMemberChangeEvent(org.neo4j.kernel.ha.cluster.HighAvailabilityMemberChangeEvent) Mockito.reset(org.mockito.Mockito.reset) Mockito.mock(org.mockito.Mockito.mock) InstanceId(org.neo4j.cluster.InstanceId) ClusterMemberAvailability(org.neo4j.cluster.member.ClusterMemberAvailability) MismatchingStoreIdException(org.neo4j.kernel.impl.store.MismatchingStoreIdException) CountDownLatch(java.util.concurrent.CountDownLatch) Election(org.neo4j.cluster.protocol.election.Election) URI(java.net.URI) ClusterClient(org.neo4j.cluster.client.ClusterClient) SwitchToSlaveCopyThenBranch(org.neo4j.kernel.ha.cluster.SwitchToSlaveCopyThenBranch) HighAvailabilityMemberChangeEvent(org.neo4j.kernel.ha.cluster.HighAvailabilityMemberChangeEvent) LifeSupport(org.neo4j.kernel.lifecycle.LifeSupport) SwitchToMaster(org.neo4j.kernel.ha.cluster.SwitchToMaster) CancellationRequest(org.neo4j.helpers.CancellationRequest) Test(org.junit.Test)

Example 7 with SwitchToSlaveCopyThenBranch

use of org.neo4j.kernel.ha.cluster.SwitchToSlaveCopyThenBranch in project neo4j by neo4j.

the class HighAvailabilityModeSwitcherTest method shouldReswitchToSlaveIfNewMasterBecameElectedAndAvailableDuringSwitch.

@Test
public void shouldReswitchToSlaveIfNewMasterBecameElectedAndAvailableDuringSwitch() throws Throwable {
    // Given
    final CountDownLatch switching = new CountDownLatch(1);
    final CountDownLatch slaveAvailable = new CountDownLatch(2);
    final AtomicBoolean firstSwitch = new AtomicBoolean(true);
    ClusterMemberAvailability availability = mock(ClusterMemberAvailability.class);
    SwitchToSlaveCopyThenBranch switchToSlave = mock(SwitchToSlaveCopyThenBranch.class);
    @SuppressWarnings("resource") SwitchToMaster switchToMaster = mock(SwitchToMaster.class);
    when(switchToSlave.switchToSlave(any(LifeSupport.class), any(URI.class), any(URI.class), any(CancellationRequest.class))).thenAnswer(invocationOnMock -> {
        switching.countDown();
        CancellationRequest cancel = (CancellationRequest) invocationOnMock.getArguments()[3];
        if (firstSwitch.get()) {
            while (!cancel.cancellationRequested()) {
                Thread.sleep(1);
            }
            firstSwitch.set(false);
        }
        slaveAvailable.countDown();
        return URI.create("ha://slave");
    });
    HighAvailabilityModeSwitcher toTest = new HighAvailabilityModeSwitcher(switchToSlave, switchToMaster, mock(Election.class), availability, mock(ClusterClient.class), storeSupplierMock(), mock(InstanceId.class), new ComponentSwitcherContainer(), neoStoreDataSourceSupplierMock(), NullLogService.getInstance());
    toTest.init();
    toTest.start();
    toTest.listeningAt(URI.create("ha://server3?serverId=3"));
    // When
    // This will start a switch to slave
    toTest.masterIsAvailable(new HighAvailabilityMemberChangeEvent(PENDING, TO_SLAVE, mock(InstanceId.class), URI.create("ha://server1")));
    // Wait until it starts and blocks on the cancellation request
    switching.await();
    // change the elected master, moving to pending, cancelling the previous change. This will block until the
    // previous switch is aborted
    toTest.masterIsElected(new HighAvailabilityMemberChangeEvent(TO_SLAVE, PENDING, new InstanceId(2), URI.create("ha://server2")));
    // Now move to the new master by switching to TO_SLAVE
    toTest.masterIsAvailable(new HighAvailabilityMemberChangeEvent(PENDING, TO_SLAVE, new InstanceId(2), URI.create("ha://server2")));
    // Then
    // The second switch must happen and this test won't block
    slaveAvailable.await();
}
Also used : InstanceId(org.neo4j.cluster.InstanceId) ClusterMemberAvailability(org.neo4j.cluster.member.ClusterMemberAvailability) CountDownLatch(java.util.concurrent.CountDownLatch) URI(java.net.URI) Election(org.neo4j.cluster.protocol.election.Election) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ClusterClient(org.neo4j.cluster.client.ClusterClient) SwitchToSlaveCopyThenBranch(org.neo4j.kernel.ha.cluster.SwitchToSlaveCopyThenBranch) HighAvailabilityMemberChangeEvent(org.neo4j.kernel.ha.cluster.HighAvailabilityMemberChangeEvent) LifeSupport(org.neo4j.kernel.lifecycle.LifeSupport) SwitchToMaster(org.neo4j.kernel.ha.cluster.SwitchToMaster) CancellationRequest(org.neo4j.helpers.CancellationRequest) Test(org.junit.Test)

Aggregations

Test (org.junit.Test)7 InstanceId (org.neo4j.cluster.InstanceId)7 ClusterClient (org.neo4j.cluster.client.ClusterClient)7 ClusterMemberAvailability (org.neo4j.cluster.member.ClusterMemberAvailability)7 Election (org.neo4j.cluster.protocol.election.Election)7 HighAvailabilityMemberChangeEvent (org.neo4j.kernel.ha.cluster.HighAvailabilityMemberChangeEvent)7 SwitchToMaster (org.neo4j.kernel.ha.cluster.SwitchToMaster)7 SwitchToSlaveCopyThenBranch (org.neo4j.kernel.ha.cluster.SwitchToSlaveCopyThenBranch)7 URI (java.net.URI)6 LifeSupport (org.neo4j.kernel.lifecycle.LifeSupport)5 CountDownLatch (java.util.concurrent.CountDownLatch)4 CancellationRequest (org.neo4j.helpers.CancellationRequest)4 ScheduledExecutorService (java.util.concurrent.ScheduledExecutorService)3 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)3 InOrder (org.mockito.InOrder)3 Callable (java.util.concurrent.Callable)2 ExecutorService (java.util.concurrent.ExecutorService)2 Executors (java.util.concurrent.Executors)2 Future (java.util.concurrent.Future)2 ScheduledFuture (java.util.concurrent.ScheduledFuture)2