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;
}
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;
}
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;
}
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();
}
}
Aggregations