Search in sources :

Example 1 with SnapshotEntry

use of com.hazelcast.cp.internal.raft.impl.log.SnapshotEntry in project hazelcast by hazelcast.

the class PersistenceTest method testSnapshotIsPersisted.

@Test
public void testSnapshotIsPersisted() throws ExecutionException, InterruptedException {
    final int committedEntryCountToSnapshot = 50;
    RaftAlgorithmConfig config = new RaftAlgorithmConfig().setCommitIndexAdvanceCountToSnapshot(committedEntryCountToSnapshot);
    group = new LocalRaftGroupBuilder(3, config).setRaftStateStoreFactory(RAFT_STATE_STORE_FACTORY).build();
    group.start();
    final RaftNodeImpl leader = group.waitUntilLeaderElected();
    for (int i = 0; i < committedEntryCountToSnapshot; i++) {
        leader.replicate(new ApplyRaftRunnable("val" + i)).get();
    }
    assertTrueEventually(() -> {
        assertEquals(committedEntryCountToSnapshot, getSnapshotEntry(leader).index());
        for (RaftNodeImpl node : group.getNodes()) {
            RestoredRaftState restoredState = getRestoredState(node);
            SnapshotEntry snapshot = restoredState.snapshot();
            assertNotNull(snapshot);
            assertEquals(committedEntryCountToSnapshot, snapshot.index());
        }
    });
}
Also used : RaftAlgorithmConfig(com.hazelcast.config.cp.RaftAlgorithmConfig) RestoredRaftState(com.hazelcast.cp.internal.raft.impl.persistence.RestoredRaftState) ApplyRaftRunnable(com.hazelcast.cp.internal.raft.impl.dataservice.ApplyRaftRunnable) LocalRaftGroupBuilder(com.hazelcast.cp.internal.raft.impl.testing.LocalRaftGroup.LocalRaftGroupBuilder) RaftUtil.getSnapshotEntry(com.hazelcast.cp.internal.raft.impl.RaftUtil.getSnapshotEntry) SnapshotEntry(com.hazelcast.cp.internal.raft.impl.log.SnapshotEntry) ParallelJVMTest(com.hazelcast.test.annotation.ParallelJVMTest) QuickTest(com.hazelcast.test.annotation.QuickTest) Test(org.junit.Test)

Example 2 with SnapshotEntry

use of com.hazelcast.cp.internal.raft.impl.log.SnapshotEntry in project hazelcast by hazelcast.

the class RaftNodeImpl method takeSnapshotIfCommitIndexAdvanced.

/**
 * Takes a snapshot if the advance in {@code commitIndex} is equal to
 * {@link RaftAlgorithmConfig#getCommitIndexAdvanceCountToSnapshot()}.
 * <p>
 * Snapshot is not created if the Raft group is being destroyed.
 */
@SuppressWarnings("checkstyle:npathcomplexity")
private void takeSnapshotIfCommitIndexAdvanced() {
    long commitIndex = state.commitIndex();
    if ((commitIndex - state.log().snapshotIndex()) < commitIndexAdvanceCountToSnapshot) {
        return;
    }
    if (isTerminatedOrSteppedDown()) {
        // If the status is TERMINATED or STEPPED_DOWN, then there will not be any new appends.
        return;
    }
    RaftLog log = state.log();
    Object snapshot = raftIntegration.takeSnapshot(commitIndex);
    if (snapshot instanceof Throwable) {
        Throwable t = (Throwable) snapshot;
        logger.severe("Could not take snapshot at commit index: " + commitIndex, t);
        return;
    }
    int snapshotTerm = log.getLogEntry(commitIndex).term();
    RaftGroupMembers members = state.committedGroupMembers();
    SnapshotEntry snapshotEntry = new SnapshotEntry(snapshotTerm, commitIndex, snapshot, members.index(), members.members());
    long highestLogIndexToTruncate = commitIndex - maxNumberOfLogsToKeepAfterSnapshot;
    LeaderState leaderState = state.leaderState();
    if (leaderState != null) {
        long[] matchIndices = leaderState.matchIndices();
        // Last slot is reserved for leader index and always zero.
        // If there is at least one follower with unknown match index,
        // its log can be close to the leader's log so we are keeping the old log entries.
        boolean allMatchIndicesKnown = Arrays.stream(matchIndices, 0, matchIndices.length - 1).noneMatch(i -> i == 0);
        if (allMatchIndicesKnown) {
            // Otherwise, we will keep the log entries until the minimum match index
            // that is bigger than (commitIndex - maxNumberOfLogsToKeepAfterSnapshot).
            // If there is no such follower (all of the minority followers are far behind),
            // then there is no need to keep the old log entries.
            highestLogIndexToTruncate = Arrays.stream(matchIndices).filter(i -> i < commitIndex).filter(i -> i > commitIndex - maxNumberOfLogsToKeepAfterSnapshot).map(i -> i - 1).sorted().findFirst().orElse(commitIndex);
        }
    }
    int truncatedEntryCount = log.setSnapshot(snapshotEntry, highestLogIndexToTruncate);
    if (logger.isFineEnabled()) {
        logger.fine(snapshotEntry + " is taken, " + truncatedEntryCount + " entries are truncated.");
    }
}
Also used : RaftStateStore(com.hazelcast.cp.internal.raft.impl.persistence.RaftStateStore) AppendSuccessResponse(com.hazelcast.cp.internal.raft.impl.dto.AppendSuccessResponse) QueryTask(com.hazelcast.cp.internal.raft.impl.task.QueryTask) Arrays(java.util.Arrays) StaleAppendRequestException(com.hazelcast.cp.exception.StaleAppendRequestException) Clock(com.hazelcast.internal.util.Clock) MembershipChangeTask(com.hazelcast.cp.internal.raft.impl.task.MembershipChangeTask) PreVoteRequest(com.hazelcast.cp.internal.raft.impl.dto.PreVoteRequest) InitLeadershipTransferTask(com.hazelcast.cp.internal.raft.impl.task.InitLeadershipTransferTask) InstallSnapshot(com.hazelcast.cp.internal.raft.impl.dto.InstallSnapshot) LeaderDemotedException(com.hazelcast.cp.exception.LeaderDemotedException) Arrays.sort(java.util.Arrays.sort) VoteResponse(com.hazelcast.cp.internal.raft.impl.dto.VoteResponse) RaftState.restoreRaftState(com.hazelcast.cp.internal.raft.impl.state.RaftState.restoreRaftState) InternalCompletableFuture(com.hazelcast.spi.impl.InternalCompletableFuture) AppendFailureResponse(com.hazelcast.cp.internal.raft.impl.dto.AppendFailureResponse) Map(java.util.Map) UPDATING_GROUP_MEMBER_LIST(com.hazelcast.cp.internal.raft.impl.RaftNodeStatus.UPDATING_GROUP_MEMBER_LIST) RaftAlgorithmConfig(com.hazelcast.config.cp.RaftAlgorithmConfig) PreVoteRequestHandlerTask(com.hazelcast.cp.internal.raft.impl.handler.PreVoteRequestHandlerTask) SnapshotEntry.isNonInitial(com.hazelcast.cp.internal.raft.impl.log.SnapshotEntry.isNonInitial) VoteRequestHandlerTask(com.hazelcast.cp.internal.raft.impl.handler.VoteRequestHandlerTask) Collection(java.util.Collection) TriggerLeaderElection(com.hazelcast.cp.internal.raft.impl.dto.TriggerLeaderElection) RandomPicker(com.hazelcast.internal.util.RandomPicker) Math.min(java.lang.Math.min) MILLISECONDS(java.util.concurrent.TimeUnit.MILLISECONDS) TERMINATING(com.hazelcast.cp.internal.raft.impl.RaftNodeStatus.TERMINATING) VoteResponseHandlerTask(com.hazelcast.cp.internal.raft.impl.handler.VoteResponseHandlerTask) NopRaftStateStore(com.hazelcast.cp.internal.raft.impl.persistence.NopRaftStateStore) QueryState(com.hazelcast.cp.internal.raft.impl.state.QueryState) CPMember(com.hazelcast.cp.CPMember) RaftGroupCmd(com.hazelcast.cp.internal.raft.command.RaftGroupCmd) Long2ObjectHashMap(com.hazelcast.internal.util.collection.Long2ObjectHashMap) Entry(java.util.Map.Entry) LogEntry(com.hazelcast.cp.internal.raft.impl.log.LogEntry) STEPPED_DOWN(com.hazelcast.cp.internal.raft.impl.RaftNodeStatus.STEPPED_DOWN) SnapshotEntry(com.hazelcast.cp.internal.raft.impl.log.SnapshotEntry) PreVoteResponseHandlerTask(com.hazelcast.cp.internal.raft.impl.handler.PreVoteResponseHandlerTask) MembershipChangeMode(com.hazelcast.cp.internal.raft.MembershipChangeMode) VoteRequest(com.hazelcast.cp.internal.raft.impl.dto.VoteRequest) InstallSnapshotHandlerTask(com.hazelcast.cp.internal.raft.impl.handler.InstallSnapshotHandlerTask) LEADER(com.hazelcast.cp.internal.raft.impl.RaftRole.LEADER) RaftState.newRaftState(com.hazelcast.cp.internal.raft.impl.state.RaftState.newRaftState) Level(java.util.logging.Level) AppendRequest(com.hazelcast.cp.internal.raft.impl.dto.AppendRequest) FollowerState(com.hazelcast.cp.internal.raft.impl.state.FollowerState) TriggerLeaderElectionHandlerTask(com.hazelcast.cp.internal.raft.impl.handler.TriggerLeaderElectionHandlerTask) RestoredRaftState(com.hazelcast.cp.internal.raft.impl.persistence.RestoredRaftState) TERMINATED(com.hazelcast.cp.internal.raft.impl.RaftNodeStatus.TERMINATED) DestroyRaftGroupCmd(com.hazelcast.cp.internal.raft.command.DestroyRaftGroupCmd) BiTuple(com.hazelcast.internal.util.BiTuple) ILogger(com.hazelcast.logging.ILogger) RaftGroupMembers(com.hazelcast.cp.internal.raft.impl.state.RaftGroupMembers) CPGroupId(com.hazelcast.cp.CPGroupId) ACTIVE(com.hazelcast.cp.internal.raft.impl.RaftNodeStatus.ACTIVE) RaftState(com.hazelcast.cp.internal.raft.impl.state.RaftState) LeaderState(com.hazelcast.cp.internal.raft.impl.state.LeaderState) Iterator(java.util.Iterator) RaftLog(com.hazelcast.cp.internal.raft.impl.log.RaftLog) AppendRequestHandlerTask(com.hazelcast.cp.internal.raft.impl.handler.AppendRequestHandlerTask) PreVoteTask(com.hazelcast.cp.internal.raft.impl.task.PreVoteTask) IOException(java.io.IOException) QueryPolicy(com.hazelcast.cp.internal.raft.QueryPolicy) AppendFailureResponseHandlerTask(com.hazelcast.cp.internal.raft.impl.handler.AppendFailureResponseHandlerTask) Preconditions.checkNotNull(com.hazelcast.internal.util.Preconditions.checkNotNull) AppendSuccessResponseHandlerTask(com.hazelcast.cp.internal.raft.impl.handler.AppendSuccessResponseHandlerTask) FOLLOWER(com.hazelcast.cp.internal.raft.impl.RaftRole.FOLLOWER) UpdateRaftGroupMembersCmd(com.hazelcast.cp.internal.raft.impl.command.UpdateRaftGroupMembersCmd) TimeUnit(java.util.concurrent.TimeUnit) PreVoteResponse(com.hazelcast.cp.internal.raft.impl.dto.PreVoteResponse) RaftNodeStatusAwareTask(com.hazelcast.cp.internal.raft.impl.task.RaftNodeStatusAwareTask) PostponedResponse(com.hazelcast.cp.internal.raft.impl.util.PostponedResponse) ReplicateTask(com.hazelcast.cp.internal.raft.impl.task.ReplicateTask) INITIAL(com.hazelcast.cp.internal.raft.impl.RaftNodeStatus.INITIAL) RaftGroupMembers(com.hazelcast.cp.internal.raft.impl.state.RaftGroupMembers) SnapshotEntry(com.hazelcast.cp.internal.raft.impl.log.SnapshotEntry) RaftLog(com.hazelcast.cp.internal.raft.impl.log.RaftLog) LeaderState(com.hazelcast.cp.internal.raft.impl.state.LeaderState)

Example 3 with SnapshotEntry

use of com.hazelcast.cp.internal.raft.impl.log.SnapshotEntry in project hazelcast by hazelcast.

the class RaftNodeImpl method initRestoredState.

private void initRestoredState() {
    SnapshotEntry snapshot = state.log().snapshot();
    if (isNonInitial(snapshot)) {
        printMemberState();
        raftIntegration.restoreSnapshot(snapshot.operation(), snapshot.index());
        if (logger.isFineEnabled()) {
            logger.info(snapshot + " is restored.");
        } else {
            logger.info("Snapshot is restored at commitIndex=" + snapshot.index());
        }
    }
    applyRestoredRaftGroupCommands(snapshot);
}
Also used : SnapshotEntry(com.hazelcast.cp.internal.raft.impl.log.SnapshotEntry)

Example 4 with SnapshotEntry

use of com.hazelcast.cp.internal.raft.impl.log.SnapshotEntry in project hazelcast by hazelcast.

the class InstallSnapshotHandlerTask method innerRun.

@Override
protected void innerRun() {
    if (logger.isFineEnabled()) {
        logger.fine("Received " + req);
    }
    RaftState state = raftNode.state();
    SnapshotEntry snapshot = req.snapshot();
    // Reply false if term < currentTerm (§5.1)
    if (req.term() < state.term()) {
        if (logger.isFineEnabled()) {
            logger.warning("Stale snapshot: " + req + " received in current term: " + state.term());
        }
        raftNode.send(new AppendFailureResponse(localMember(), state.term(), snapshot.index() + 1), req.leader());
        return;
    }
    // Transform into follower if a newer term is seen or another node wins the election of the current term
    if (req.term() > state.term() || state.role() != FOLLOWER) {
        // If RPC request or response contains term T > currentTerm: set currentTerm = T, convert to follower (§5.1)
        logger.info("Demoting to FOLLOWER from current role: " + state.role() + ", term: " + state.term() + " to new term: " + req.term() + " and leader: " + req.leader());
        raftNode.toFollower(req.term());
    }
    if (!req.leader().equals(state.leader())) {
        logger.info("Setting leader: " + req.leader());
        raftNode.leader(req.leader());
    }
    raftNode.updateLastAppendEntriesTimestamp();
    if (raftNode.installSnapshot(snapshot)) {
        raftNode.send(new AppendSuccessResponse(localMember(), req.term(), snapshot.index(), req.queryRound()), req.leader());
    }
}
Also used : AppendSuccessResponse(com.hazelcast.cp.internal.raft.impl.dto.AppendSuccessResponse) RaftState(com.hazelcast.cp.internal.raft.impl.state.RaftState) SnapshotEntry(com.hazelcast.cp.internal.raft.impl.log.SnapshotEntry) AppendFailureResponse(com.hazelcast.cp.internal.raft.impl.dto.AppendFailureResponse)

Aggregations

SnapshotEntry (com.hazelcast.cp.internal.raft.impl.log.SnapshotEntry)4 RaftAlgorithmConfig (com.hazelcast.config.cp.RaftAlgorithmConfig)2 AppendFailureResponse (com.hazelcast.cp.internal.raft.impl.dto.AppendFailureResponse)2 AppendSuccessResponse (com.hazelcast.cp.internal.raft.impl.dto.AppendSuccessResponse)2 RaftState (com.hazelcast.cp.internal.raft.impl.state.RaftState)2 CPGroupId (com.hazelcast.cp.CPGroupId)1 CPMember (com.hazelcast.cp.CPMember)1 LeaderDemotedException (com.hazelcast.cp.exception.LeaderDemotedException)1 StaleAppendRequestException (com.hazelcast.cp.exception.StaleAppendRequestException)1 MembershipChangeMode (com.hazelcast.cp.internal.raft.MembershipChangeMode)1 QueryPolicy (com.hazelcast.cp.internal.raft.QueryPolicy)1 DestroyRaftGroupCmd (com.hazelcast.cp.internal.raft.command.DestroyRaftGroupCmd)1 RaftGroupCmd (com.hazelcast.cp.internal.raft.command.RaftGroupCmd)1 ACTIVE (com.hazelcast.cp.internal.raft.impl.RaftNodeStatus.ACTIVE)1 INITIAL (com.hazelcast.cp.internal.raft.impl.RaftNodeStatus.INITIAL)1 STEPPED_DOWN (com.hazelcast.cp.internal.raft.impl.RaftNodeStatus.STEPPED_DOWN)1 TERMINATED (com.hazelcast.cp.internal.raft.impl.RaftNodeStatus.TERMINATED)1 TERMINATING (com.hazelcast.cp.internal.raft.impl.RaftNodeStatus.TERMINATING)1 UPDATING_GROUP_MEMBER_LIST (com.hazelcast.cp.internal.raft.impl.RaftNodeStatus.UPDATING_GROUP_MEMBER_LIST)1 FOLLOWER (com.hazelcast.cp.internal.raft.impl.RaftRole.FOLLOWER)1