Search in sources :

Example 1 with QueryState

use of com.hazelcast.cp.internal.raft.impl.state.QueryState in project hazelcast by hazelcast.

the class AppendSuccessResponseHandlerTask method updateFollowerIndices.

private boolean updateFollowerIndices(RaftState state) {
    // If successful: update nextIndex and matchIndex for follower (§5.3)
    RaftEndpoint follower = resp.follower();
    LeaderState leaderState = state.leaderState();
    FollowerState followerState = leaderState.getFollowerState(follower);
    QueryState queryState = leaderState.queryState();
    if (queryState.tryAck(resp.queryRound(), follower)) {
        if (logger.isFineEnabled()) {
            logger.fine("Ack from " + follower + " for query round: " + resp.queryRound());
        }
    }
    long matchIndex = followerState.matchIndex();
    long followerLastLogIndex = resp.lastLogIndex();
    if (followerLastLogIndex > matchIndex) {
        // Received a response for the last append request. Resetting the flag...
        followerState.appendRequestAckReceived();
        long newNextIndex = followerLastLogIndex + 1;
        followerState.matchIndex(followerLastLogIndex);
        followerState.nextIndex(newNextIndex);
        if (logger.isFineEnabled()) {
            logger.fine("Updated match index: " + followerLastLogIndex + " and next index: " + newNextIndex + " for follower: " + follower);
        }
        return true;
    } else if (followerLastLogIndex == matchIndex) {
        // Received a response for the last append request. Resetting the flag...
        followerState.appendRequestAckReceived();
    } else if (logger.isFineEnabled()) {
        logger.fine("Will not update match index for follower: " + follower + ". follower last log index: " + followerLastLogIndex + ", match index: " + matchIndex);
    }
    return false;
}
Also used : RaftEndpoint(com.hazelcast.cp.internal.raft.impl.RaftEndpoint) QueryState(com.hazelcast.cp.internal.raft.impl.state.QueryState) FollowerState(com.hazelcast.cp.internal.raft.impl.state.FollowerState) LeaderState(com.hazelcast.cp.internal.raft.impl.state.LeaderState)

Example 2 with QueryState

use of com.hazelcast.cp.internal.raft.impl.state.QueryState in project hazelcast by hazelcast.

the class RaftNodeImpl method tryRunQueries.

public boolean tryRunQueries() {
    QueryState queryState = state.leaderState().queryState();
    if (queryState.queryCount() == 0) {
        return false;
    }
    long commitIndex = state.commitIndex();
    if (!queryState.isMajorityAcked(commitIndex, state.majority())) {
        return true;
    }
    Collection<BiTuple<Object, InternalCompletableFuture>> operations = queryState.operations();
    if (logger.isFineEnabled()) {
        logger.fine("Running " + operations.size() + " queries at commit index: " + commitIndex + ", query round: " + queryState.queryRound());
    }
    for (BiTuple<Object, InternalCompletableFuture> t : operations) {
        runQuery(t.element1, t.element2);
    }
    queryState.reset();
    return false;
}
Also used : InternalCompletableFuture(com.hazelcast.spi.impl.InternalCompletableFuture) QueryState(com.hazelcast.cp.internal.raft.impl.state.QueryState) BiTuple(com.hazelcast.internal.util.BiTuple)

Example 3 with QueryState

use of com.hazelcast.cp.internal.raft.impl.state.QueryState in project hazelcast by hazelcast.

the class RaftNodeImpl method canQueryLinearizable.

/**
 * Returns true if a new query is currently allowed to be executed without
 * appending to the Raft log. This method can be invoked only when
 * the local Raft node is the leader.
 * <p>
 * A new linearizable query execution is not allowed, when;
 * <ul>
 * <li>Node is terminating, terminated or stepped down.
 * See {@link RaftNodeStatus}.</li>
 * <li>If the leader has not yet marked an entry from its current term
 * committed. See Section 6.4 of Raft Dissertation.</li>
 * <li>There are already
 * {@link RaftAlgorithmConfig#getUncommittedEntryCountToRejectNewAppends()}
 * queries waiting to be executed.</li>
 * </ul>
 */
public boolean canQueryLinearizable() {
    if (isTerminatedOrSteppedDown()) {
        return false;
    }
    long commitIndex = state.commitIndex();
    RaftLog log = state.log();
    // If the leader has not yet marked an entry from its current term committed, it waits until it has done so. (§6.4)
    // last committed entry is either in the last snapshot or still in the log
    LogEntry lastCommittedEntry = commitIndex == log.snapshotIndex() ? log.snapshot() : log.getLogEntry(commitIndex);
    assert lastCommittedEntry != null;
    if (lastCommittedEntry.term() != state.term()) {
        return false;
    }
    // We can execute multiple queries at one-shot without appending to the Raft log,
    // and we use the maxUncommittedEntryCount configuration parameter to upper-bound
    // the number of queries that are collected until the heartbeat round is done.
    QueryState queryState = state.leaderState().queryState();
    return queryState.queryCount() < maxUncommittedEntryCount;
}
Also used : QueryState(com.hazelcast.cp.internal.raft.impl.state.QueryState) LogEntry(com.hazelcast.cp.internal.raft.impl.log.LogEntry) RaftLog(com.hazelcast.cp.internal.raft.impl.log.RaftLog)

Example 4 with QueryState

use of com.hazelcast.cp.internal.raft.impl.state.QueryState in project hazelcast by hazelcast.

the class QueryTask method handleLinearizableRead.

private void handleLinearizableRead() {
    if (!raftNode.isLinearizableReadOptimizationEnabled()) {
        new ReplicateTask(raftNode, operation, resultFuture).run();
        return;
    }
    RaftState state = raftNode.state();
    if (state.role() != LEADER) {
        resultFuture.completeExceptionally(new NotLeaderException(raftNode.getGroupId(), raftNode.getLocalMember(), state.leader()));
        return;
    }
    if (!raftNode.canQueryLinearizable()) {
        resultFuture.completeExceptionally(new CannotReplicateException(state.leader()));
        return;
    }
    long commitIndex = state.commitIndex();
    QueryState queryState = state.leaderState().queryState();
    if (logger.isFineEnabled()) {
        logger.fine("Adding query at commit index: " + commitIndex + ", query round: " + queryState.queryRound());
    }
    if (queryState.addQuery(commitIndex, operation, resultFuture) == 1) {
        raftNode.broadcastAppendRequest();
    }
}
Also used : NotLeaderException(com.hazelcast.cp.exception.NotLeaderException) RaftState(com.hazelcast.cp.internal.raft.impl.state.RaftState) CannotReplicateException(com.hazelcast.cp.exception.CannotReplicateException) QueryState(com.hazelcast.cp.internal.raft.impl.state.QueryState)

Aggregations

QueryState (com.hazelcast.cp.internal.raft.impl.state.QueryState)4 CannotReplicateException (com.hazelcast.cp.exception.CannotReplicateException)1 NotLeaderException (com.hazelcast.cp.exception.NotLeaderException)1 RaftEndpoint (com.hazelcast.cp.internal.raft.impl.RaftEndpoint)1 LogEntry (com.hazelcast.cp.internal.raft.impl.log.LogEntry)1 RaftLog (com.hazelcast.cp.internal.raft.impl.log.RaftLog)1 FollowerState (com.hazelcast.cp.internal.raft.impl.state.FollowerState)1 LeaderState (com.hazelcast.cp.internal.raft.impl.state.LeaderState)1 RaftState (com.hazelcast.cp.internal.raft.impl.state.RaftState)1 BiTuple (com.hazelcast.internal.util.BiTuple)1 InternalCompletableFuture (com.hazelcast.spi.impl.InternalCompletableFuture)1