Search in sources :

Example 6 with RaftAlgorithmConfig

use of com.hazelcast.config.cp.RaftAlgorithmConfig in project hazelcast by hazelcast.

the class PersistenceTest method when_leaderIsRestarted_then_itBecomesFollowerAndRestoresItsRaftStateWithSnapshot.

@Test
public void when_leaderIsRestarted_then_itBecomesFollowerAndRestoresItsRaftStateWithSnapshot() throws ExecutionException, InterruptedException {
    final int committedEntryCountToSnapshot = 50;
    RaftAlgorithmConfig config = new RaftAlgorithmConfig().setCommitIndexAdvanceCountToSnapshot(committedEntryCountToSnapshot);
    group = new LocalRaftGroupBuilder(3, config).setAppendNopEntryOnLeaderElection(true).setRaftStateStoreFactory(RAFT_STATE_STORE_FACTORY).build();
    group.start();
    RaftNodeImpl leader = group.waitUntilLeaderElected();
    for (int i = 0; i <= committedEntryCountToSnapshot; i++) {
        leader.replicate(new ApplyRaftRunnable("val" + i)).get();
    }
    assertTrue(getSnapshotEntry(leader).index() > 0);
    RaftEndpoint terminatedEndpoint = leader.getLocalMember();
    InMemoryRaftStateStore stateStore = getRaftStateStore(leader);
    RestoredRaftState terminatedState = stateStore.toRestoredRaftState();
    group.terminateNode(terminatedEndpoint);
    final RaftNodeImpl newLeader = group.waitUntilLeaderElected();
    final RaftNodeImpl restartedNode = group.createNewRaftNode(terminatedState, stateStore);
    assertEquals(new ArrayList<>(getCommittedGroupMembers(newLeader).members()), new ArrayList<>(getCommittedGroupMembers(restartedNode).members()));
    assertEquals(new ArrayList<>(getLastGroupMembers(newLeader).members()), new ArrayList<>(getLastGroupMembers(restartedNode).members()));
    assertTrueEventually(() -> {
        assertEquals(newLeader.getLocalMember(), restartedNode.getLeader());
        assertEquals(getTerm(newLeader), getTerm(restartedNode));
        assertEquals(getCommitIndex(newLeader), getCommitIndex(restartedNode));
        assertEquals(getLastApplied(newLeader), getLastApplied(restartedNode));
        RaftDataService service = group.getService(restartedNode);
        Object[] values = service.valuesArray();
        assertThat(values, arrayWithSize(committedEntryCountToSnapshot + 1));
        for (int i = 0; i <= committedEntryCountToSnapshot; i++) {
            assertEquals("val" + i, values[i]);
        }
    });
}
Also used : RaftAlgorithmConfig(com.hazelcast.config.cp.RaftAlgorithmConfig) RestoredRaftState(com.hazelcast.cp.internal.raft.impl.persistence.RestoredRaftState) InMemoryRaftStateStore(com.hazelcast.cp.internal.raft.impl.testing.InMemoryRaftStateStore) ApplyRaftRunnable(com.hazelcast.cp.internal.raft.impl.dataservice.ApplyRaftRunnable) RaftDataService(com.hazelcast.cp.internal.raft.impl.dataservice.RaftDataService) LocalRaftGroupBuilder(com.hazelcast.cp.internal.raft.impl.testing.LocalRaftGroup.LocalRaftGroupBuilder) ParallelJVMTest(com.hazelcast.test.annotation.ParallelJVMTest) QuickTest(com.hazelcast.test.annotation.QuickTest) Test(org.junit.Test)

Example 7 with RaftAlgorithmConfig

use of com.hazelcast.config.cp.RaftAlgorithmConfig in project hazelcast by hazelcast.

the class SnapshotTest method when_followersIsFarBehind_then_itInstallsSnapshot.

@Test
public void when_followersIsFarBehind_then_itInstallsSnapshot() throws ExecutionException, InterruptedException {
    final int entryCount = 50;
    RaftAlgorithmConfig config = new RaftAlgorithmConfig().setCommitIndexAdvanceCountToSnapshot(entryCount);
    group = newGroup(3, config);
    group.start();
    RaftNodeImpl leader = group.waitUntilLeaderElected();
    leader.replicate(new ApplyRaftRunnable("val0")).get();
    RaftNodeImpl[] followers = group.getNodesExcept(leader.getLocalMember());
    RaftNodeImpl slowFollower = followers[1];
    group.dropMessagesToMember(leader.getLocalMember(), slowFollower.getLocalMember(), AppendRequest.class);
    group.dropMessagesToMember(leader.getLocalMember(), slowFollower.getLocalMember(), InstallSnapshot.class);
    for (int i = 1; i < entryCount; i++) {
        leader.replicate(new ApplyRaftRunnable("val" + i)).get();
    }
    assertTrueEventually(() -> assertEquals(entryCount, getSnapshotEntry(leader).index()));
    leader.replicate(new ApplyRaftRunnable("valFinal")).get();
    group.allowMessagesToMember(leader.getLocalMember(), slowFollower.getLocalMember(), InstallSnapshot.class);
    assertTrueEventually(() -> assertEquals(entryCount, getCommitIndex(slowFollower)));
    group.resetAllRulesFrom(leader.getLocalMember());
    assertTrueEventually(() -> {
        for (RaftNodeImpl raftNode : group.getNodes()) {
            assertEquals(entryCount + 1, getCommitIndex(raftNode));
            RaftDataService service = group.getService(raftNode);
            assertEquals(entryCount + 1, service.size());
            for (int i = 0; i < entryCount; i++) {
                assertEquals(("val" + i), service.get(i + 1));
            }
            assertEquals("valFinal", service.get(51));
        }
    });
}
Also used : RaftAlgorithmConfig(com.hazelcast.config.cp.RaftAlgorithmConfig) ApplyRaftRunnable(com.hazelcast.cp.internal.raft.impl.dataservice.ApplyRaftRunnable) RaftDataService(com.hazelcast.cp.internal.raft.impl.dataservice.RaftDataService) ParallelJVMTest(com.hazelcast.test.annotation.ParallelJVMTest) QuickTest(com.hazelcast.test.annotation.QuickTest) Test(org.junit.Test)

Example 8 with RaftAlgorithmConfig

use of com.hazelcast.config.cp.RaftAlgorithmConfig in project hazelcast by hazelcast.

the class SnapshotTest method when_followerMissesTheLastEntryThatGoesIntoTheSnapshot_then_itCatchesUpWithoutInstallingSnapshot.

@Test
public void when_followerMissesTheLastEntryThatGoesIntoTheSnapshot_then_itCatchesUpWithoutInstallingSnapshot() throws ExecutionException, InterruptedException {
    final int entryCount = 50;
    RaftAlgorithmConfig config = new RaftAlgorithmConfig().setCommitIndexAdvanceCountToSnapshot(entryCount);
    group = newGroup(3, config);
    group.start();
    RaftNodeImpl leader = group.waitUntilLeaderElected();
    RaftNodeImpl[] followers = group.getNodesExcept(leader.getLocalMember());
    RaftNodeImpl slowFollower = followers[1];
    for (int i = 0; i < entryCount - 1; i++) {
        leader.replicate(new ApplyRaftRunnable("val" + i)).get();
    }
    assertTrueEventually(() -> {
        for (RaftNodeImpl follower : group.getNodesExcept(leader.getLocalMember())) {
            assertEquals(entryCount - 1, getMatchIndex(leader, follower.getLocalMember()));
        }
    });
    group.dropMessagesToMember(leader.getLocalMember(), slowFollower.getLocalMember(), AppendRequest.class);
    group.dropMessagesToMember(leader.getLocalMember(), slowFollower.getLocalMember(), InstallSnapshot.class);
    leader.replicate(new ApplyRaftRunnable("val" + (entryCount - 1))).get();
    assertTrueEventually(() -> assertEquals(entryCount, getSnapshotEntry(leader).index()));
    leader.replicate(new ApplyRaftRunnable("valFinal")).get();
    group.allowMessagesToMember(leader.getLocalMember(), slowFollower.getLocalMember(), AppendRequest.class);
    assertTrueEventually(() -> {
        for (RaftNodeImpl raftNode : group.getNodes()) {
            assertEquals(entryCount + 1, getCommitIndex(raftNode));
            RaftDataService service = group.getService(raftNode);
            assertEquals(entryCount + 1, service.size());
            for (int i = 0; i < entryCount; i++) {
                assertEquals(("val" + i), service.get(i + 1));
            }
            assertEquals("valFinal", service.get(51));
        }
    });
}
Also used : RaftAlgorithmConfig(com.hazelcast.config.cp.RaftAlgorithmConfig) ApplyRaftRunnable(com.hazelcast.cp.internal.raft.impl.dataservice.ApplyRaftRunnable) RaftDataService(com.hazelcast.cp.internal.raft.impl.dataservice.RaftDataService) ParallelJVMTest(com.hazelcast.test.annotation.ParallelJVMTest) QuickTest(com.hazelcast.test.annotation.QuickTest) Test(org.junit.Test)

Example 9 with RaftAlgorithmConfig

use of com.hazelcast.config.cp.RaftAlgorithmConfig in project hazelcast by hazelcast.

the class SnapshotTest method testMembershipChangeBlocksSnapshotBug.

@Test
public void testMembershipChangeBlocksSnapshotBug() throws ExecutionException, InterruptedException {
    // The comments below show how the code behaves before the mentioned bug is fixed.
    int commitIndexAdvanceCount = 50;
    int uncommittedEntryCount = 10;
    RaftAlgorithmConfig config = new RaftAlgorithmConfig().setCommitIndexAdvanceCountToSnapshot(commitIndexAdvanceCount).setUncommittedEntryCountToRejectNewAppends(uncommittedEntryCount);
    group = newGroup(3, config);
    group.start();
    RaftNodeImpl leader = group.waitUntilLeaderElected();
    RaftNodeImpl[] followers = group.getNodesExcept(leader.getLocalMember());
    group.dropMessagesToMember(leader.getLocalMember(), followers[0].getLocalMember(), AppendRequest.class);
    while (getSnapshotEntry(leader).index() == 0) {
        leader.replicate(new ApplyRaftRunnable("into_snapshot")).get();
    }
    // now, the leader has taken a snapshot.
    // It also keeps some already committed entries in the log because followers[0] hasn't appended them.
    // LOG: [ <46 - 49>, <50>], SNAPSHOT INDEX: 50, COMMIT INDEX: 50
    long leaderCommitIndex = getCommitIndex(leader);
    do {
        leader.replicate(new ApplyRaftRunnable("committed_after_snapshot")).get();
    } while (getCommitIndex(leader) < leaderCommitIndex + commitIndexAdvanceCount - 1);
    // committing new entries.
    // one more entry is needed to take the next snapshot.
    // LOG: [ <46 - 49>, <50>, <51 - 99 (committed)> ], SNAPSHOT INDEX: 50, COMMIT INDEX: 99
    group.dropMessagesToMember(leader.getLocalMember(), followers[1].getLocalMember(), AppendRequest.class);
    for (int i = 0; i < uncommittedEntryCount - 1; i++) {
        leader.replicate(new ApplyRaftRunnable("uncommitted_after_snapshot"));
    }
    // appended some more entries which will not be committed because the leader has no majority.
    // the last uncommitted index is reserved for membership changed.
    // LOG: [ <46 - 49>, <50>, <51 - 99 (committed)>, <100 - 108 (uncommitted)> ], SNAPSHOT INDEX: 50, COMMIT INDEX: 99
    // There are only 2 empty indices in the log.
    RaftNodeImpl newRaftNode = group.createNewRaftNode();
    Function<Object, Object> alterFunc = o -> {
        if (o instanceof AppendRequest) {
            AppendRequest request = (AppendRequest) o;
            LogEntry[] entries = request.entries();
            if (entries.length > 0) {
                if (entries[entries.length - 1].operation() instanceof UpdateRaftGroupMembersCmd) {
                    entries = Arrays.copyOf(entries, entries.length - 1);
                    return new AppendRequest(request.leader(), request.term(), request.prevLogTerm(), request.prevLogIndex(), request.leaderCommitIndex(), entries, request.queryRound());
                } else if (entries[0].operation() instanceof UpdateRaftGroupMembersCmd) {
                    entries = new LogEntry[0];
                    return new AppendRequest(request.leader(), request.term(), request.prevLogTerm(), request.prevLogIndex(), request.leaderCommitIndex(), entries, request.queryRound());
                }
            }
        }
        return null;
    };
    group.alterMessagesToMember(leader.getLocalMember(), followers[1].getLocalMember(), alterFunc);
    group.alterMessagesToMember(leader.getLocalMember(), newRaftNode.getLocalMember(), alterFunc);
    long lastLogIndex1 = getLastLogOrSnapshotEntry(leader).index();
    leader.replicateMembershipChange(newRaftNode.getLocalMember(), MembershipChangeMode.ADD);
    // When the membership change entry is appended, the leader's Log will be as following:
    // LOG: [ <46 - 49>, <50>, <51 - 99 (committed)>, <100 - 108 (uncommitted)>, <109 (membership change)> ], SNAPSHOT INDEX: 50, COMMIT INDEX: 99
    assertTrueEventually(() -> assertTrue(getLastLogOrSnapshotEntry(leader).index() > lastLogIndex1));
    group.allowMessagesToMember(leader.getLocalMember(), followers[1].getLocalMember(), AppendRequest.class);
    // Then, only the entries before the membership change will be committed because we alter the append request. The log will be:
    // LOG: [ <46 - 49>, <50>, <51 - 108 (committed)>, <109 (membership change)> ], SNAPSHOT INDEX: 50, COMMIT INDEX: 108
    // There is only 1 empty index in the log.
    assertTrueEventually(() -> {
        assertEquals(lastLogIndex1, getCommitIndex(leader));
        assertEquals(lastLogIndex1, getCommitIndex(followers[1]));
    });
    // assertTrueEventually(() -> {
    // assertEquals(lastLogIndex1 + 1, getCommitIndex(leader));
    // assertEquals(lastLogIndex1 + 1, getCommitIndex(followers[1]));
    // });
    long lastLogIndex2 = getLastLogOrSnapshotEntry(leader).index();
    leader.replicate(new ApplyRaftRunnable("after_membership_change_append"));
    assertTrueEventually(() -> assertTrue(getLastLogOrSnapshotEntry(leader).index() > lastLogIndex2));
    // Now the log is full. There is no empty space left.
    // LOG: [ <46 - 49>, <50>, <51 - 108 (committed)>, <109 (membership change)>, <110 (uncommitted)> ], SNAPSHOT INDEX: 50, COMMIT INDEX: 108
    long lastLogIndex3 = getLastLogOrSnapshotEntry(leader).index();
    Future f = leader.replicate(new ApplyRaftRunnable("after_membership_change_append"));
    assertTrueEventually(() -> assertTrue(getLastLogOrSnapshotEntry(leader).index() > lastLogIndex3));
    assertFalse(f.isDone());
}
Also used : ParallelJVMTest(com.hazelcast.test.annotation.ParallelJVMTest) AppendSuccessResponse(com.hazelcast.cp.internal.raft.impl.dto.AppendSuccessResponse) Arrays(java.util.Arrays) StaleAppendRequestException(com.hazelcast.cp.exception.StaleAppendRequestException) MembershipChangeMode(com.hazelcast.cp.internal.raft.MembershipChangeMode) QuickTest(com.hazelcast.test.annotation.QuickTest) RunWith(org.junit.runner.RunWith) RaftUtil.getLeaderMember(com.hazelcast.cp.internal.raft.impl.RaftUtil.getLeaderMember) InstallSnapshot(com.hazelcast.cp.internal.raft.impl.dto.InstallSnapshot) Function(java.util.function.Function) ArrayList(java.util.ArrayList) InternalCompletableFuture(com.hazelcast.spi.impl.InternalCompletableFuture) Assert.assertThat(org.junit.Assert.assertThat) AppendRequest(com.hazelcast.cp.internal.raft.impl.dto.AppendRequest) RaftUtil.getMatchIndex(com.hazelcast.cp.internal.raft.impl.RaftUtil.getMatchIndex) Future(java.util.concurrent.Future) RaftUtil.getCommitIndex(com.hazelcast.cp.internal.raft.impl.RaftUtil.getCommitIndex) AppendFailureResponse(com.hazelcast.cp.internal.raft.impl.dto.AppendFailureResponse) After(org.junit.After) RaftAlgorithmConfig(com.hazelcast.config.cp.RaftAlgorithmConfig) Assert.fail(org.junit.Assert.fail) ACTIVE(com.hazelcast.cp.internal.raft.impl.RaftNodeStatus.ACTIVE) RaftUtil.getCommittedGroupMembers(com.hazelcast.cp.internal.raft.impl.RaftUtil.getCommittedGroupMembers) Matchers.greaterThanOrEqualTo(org.hamcrest.Matchers.greaterThanOrEqualTo) Assert.assertNotNull(org.junit.Assert.assertNotNull) ApplyRaftRunnable(com.hazelcast.cp.internal.raft.impl.dataservice.ApplyRaftRunnable) HazelcastTestSupport(com.hazelcast.test.HazelcastTestSupport) RaftUtil.getStatus(com.hazelcast.cp.internal.raft.impl.RaftUtil.getStatus) Assert.assertTrue(org.junit.Assert.assertTrue) Test(org.junit.Test) LocalRaftGroup(com.hazelcast.cp.internal.raft.impl.testing.LocalRaftGroup) Category(org.junit.experimental.categories.Category) Assert.assertNotEquals(org.junit.Assert.assertNotEquals) UpdateRaftGroupMembersCmd(com.hazelcast.cp.internal.raft.impl.command.UpdateRaftGroupMembersCmd) ExecutionException(java.util.concurrent.ExecutionException) RaftUtil.getSnapshotEntry(com.hazelcast.cp.internal.raft.impl.RaftUtil.getSnapshotEntry) RaftDataService(com.hazelcast.cp.internal.raft.impl.dataservice.RaftDataService) List(java.util.List) LocalRaftGroupBuilder.newGroup(com.hazelcast.cp.internal.raft.impl.testing.LocalRaftGroup.LocalRaftGroupBuilder.newGroup) Assert.assertFalse(org.junit.Assert.assertFalse) HazelcastParallelClassRunner(com.hazelcast.test.HazelcastParallelClassRunner) LogEntry(com.hazelcast.cp.internal.raft.impl.log.LogEntry) RaftUtil.getLastLogOrSnapshotEntry(com.hazelcast.cp.internal.raft.impl.RaftUtil.getLastLogOrSnapshotEntry) Assert.assertEquals(org.junit.Assert.assertEquals) RaftAlgorithmConfig(com.hazelcast.config.cp.RaftAlgorithmConfig) UpdateRaftGroupMembersCmd(com.hazelcast.cp.internal.raft.impl.command.UpdateRaftGroupMembersCmd) ApplyRaftRunnable(com.hazelcast.cp.internal.raft.impl.dataservice.ApplyRaftRunnable) InternalCompletableFuture(com.hazelcast.spi.impl.InternalCompletableFuture) Future(java.util.concurrent.Future) AppendRequest(com.hazelcast.cp.internal.raft.impl.dto.AppendRequest) ParallelJVMTest(com.hazelcast.test.annotation.ParallelJVMTest) QuickTest(com.hazelcast.test.annotation.QuickTest) Test(org.junit.Test)

Example 10 with RaftAlgorithmConfig

use of com.hazelcast.config.cp.RaftAlgorithmConfig in project hazelcast by hazelcast.

the class LinearizableQueryTest method when_multipleQueryLimitIsReachedBeforeHeartbeatAcks_then_noNewQueryIsAccepted.

@Test(timeout = 300_000)
public void when_multipleQueryLimitIsReachedBeforeHeartbeatAcks_then_noNewQueryIsAccepted() throws Exception {
    RaftAlgorithmConfig config = new RaftAlgorithmConfig().setUncommittedEntryCountToRejectNewAppends(1);
    group = new LocalRaftGroupBuilder(5, config).setAppendNopEntryOnLeaderElection(true).build();
    group.start();
    RaftNodeImpl leader = group.waitUntilLeaderElected();
    assertTrueEventually(() -> assertThat(getCommitIndex(leader), greaterThanOrEqualTo(1L)));
    RaftNodeImpl[] followers = group.getNodesExcept(leader.getLocalMember());
    group.dropMessagesToMember(leader.getLocalMember(), followers[0].getLocalMember(), AppendRequest.class);
    group.dropMessagesToMember(leader.getLocalMember(), followers[1].getLocalMember(), AppendRequest.class);
    group.dropMessagesToMember(leader.getLocalMember(), followers[2].getLocalMember(), AppendRequest.class);
    InternalCompletableFuture queryFuture1 = leader.query(new QueryRaftRunnable(), LINEARIZABLE);
    InternalCompletableFuture queryFuture2 = leader.query(new QueryRaftRunnable(), LINEARIZABLE);
    try {
        queryFuture2.joinInternal();
        fail();
    } catch (CannotReplicateException ignored) {
    }
    group.resetAllRulesFrom(leader.getLocalMember());
    queryFuture1.get();
}
Also used : RaftAlgorithmConfig(com.hazelcast.config.cp.RaftAlgorithmConfig) InternalCompletableFuture(com.hazelcast.spi.impl.InternalCompletableFuture) QueryRaftRunnable(com.hazelcast.cp.internal.raft.impl.dataservice.QueryRaftRunnable) LocalRaftGroupBuilder(com.hazelcast.cp.internal.raft.impl.testing.LocalRaftGroup.LocalRaftGroupBuilder) CannotReplicateException(com.hazelcast.cp.exception.CannotReplicateException) ParallelJVMTest(com.hazelcast.test.annotation.ParallelJVMTest) QuickTest(com.hazelcast.test.annotation.QuickTest) Test(org.junit.Test)

Aggregations

RaftAlgorithmConfig (com.hazelcast.config.cp.RaftAlgorithmConfig)32 QuickTest (com.hazelcast.test.annotation.QuickTest)28 Test (org.junit.Test)28 ParallelJVMTest (com.hazelcast.test.annotation.ParallelJVMTest)27 ApplyRaftRunnable (com.hazelcast.cp.internal.raft.impl.dataservice.ApplyRaftRunnable)23 RaftDataService (com.hazelcast.cp.internal.raft.impl.dataservice.RaftDataService)14 LocalRaftGroupBuilder (com.hazelcast.cp.internal.raft.impl.testing.LocalRaftGroup.LocalRaftGroupBuilder)9 RestoredRaftState (com.hazelcast.cp.internal.raft.impl.persistence.RestoredRaftState)8 InternalCompletableFuture (com.hazelcast.spi.impl.InternalCompletableFuture)7 InMemoryRaftStateStore (com.hazelcast.cp.internal.raft.impl.testing.InMemoryRaftStateStore)6 CPSubsystemConfig (com.hazelcast.config.cp.CPSubsystemConfig)4 FencedLockConfig (com.hazelcast.config.cp.FencedLockConfig)4 SemaphoreConfig (com.hazelcast.config.cp.SemaphoreConfig)4 StaleAppendRequestException (com.hazelcast.cp.exception.StaleAppendRequestException)3 KerberosAuthenticationConfig (com.hazelcast.config.security.KerberosAuthenticationConfig)2 KerberosIdentityConfig (com.hazelcast.config.security.KerberosIdentityConfig)2 LdapAuthenticationConfig (com.hazelcast.config.security.LdapAuthenticationConfig)2 RealmConfig (com.hazelcast.config.security.RealmConfig)2 SimpleAuthenticationConfig (com.hazelcast.config.security.SimpleAuthenticationConfig)2 CannotReplicateException (com.hazelcast.cp.exception.CannotReplicateException)2