public class SingleThreadedRaftAlgorithm extends java.lang.Object implements RaftAlgorithm
RaftAlgorithm that wraps all of its calls in a queue to ensure that they
are executed single-threaded.| Modifier and Type | Field and Description |
|---|---|
static java.util.concurrent.atomic.AtomicInteger |
boundaryPoolThreadsWaiting
JUST FOR TESTS: Only used in LocalTransport
We need this in order to prevent time from slipping while boundary pool threads are created but have not yet
started.
|
RaftAlgorithm |
impl
The Raft algorithm we're actually running, wrapped in a single-threaded
environment.
|
DEFAULT_ELECTION_RANGE, summaryTiming| Constructor and Description |
|---|
SingleThreadedRaftAlgorithm(RaftAlgorithm impl,
java.util.concurrent.ExecutorService boundaryPool)
Create a single-thread driven Raft algorithm from an implementing instance.
|
| Modifier and Type | Method and Description |
|---|---|
boolean |
bootstrap(boolean force)
Mark this node for bootstrapping.
|
void |
broadcastAppendEntries(long now)
Send out an append entries RPC (i.e., a heartbeat) to all listeners on the transport.
|
java.util.List<java.lang.String> |
errors()
Get errors from this Raft algorithm
|
protected void |
finalize()
Kill this Raft on GC
|
void |
flush(java.lang.Runnable additionalCriteria)
Flush the task queue.
|
RaftTransport |
getTransport()
This gets the RaftTransport associated with this RaftAlgorithm.
|
void |
heartbeat(long now)
A method to be called on every heartbeat interval.
|
boolean |
isRunning()
Check if the algorithm has already been stopped via
RaftAlgorithm.stop(boolean). |
java.util.Optional<RaftLifecycle> |
lifecycle()
Get the RaftLifecycle object that this Algorithm is registered for.
|
RaftState |
mutableState()
DANGEROUS: USE ONLY IF YOU KNOW WHAT YOU ARE DOING
get A REFERENCE TO the current Raft state.
|
RaftStateMachine |
mutableStateMachine()
DANGEROUS: USE ONLY IF YOU KNOW WHAT YOU ARE DOING
get A REFERENCE TO the current Raft state machine.
|
int |
queuedTaskCount()
Return the number of tasks we have queued to be executed by Raft.
|
java.util.concurrent.CompletableFuture<EloquentRaftProto.RaftMessage> |
receiveAddServerRPC(EloquentRaftProto.AddServerRequest addServerRequest,
long now)
A request has been received to add a server to the cluster.
|
void |
receiveAppendEntriesReply(EloquentRaftProto.AppendEntriesReply reply,
long now)
We received an asynchronous heartbeat from a server.
|
void |
receiveAppendEntriesRPC(EloquentRaftProto.AppendEntriesRequest heartbeat,
java.util.function.Consumer<EloquentRaftProto.RaftMessage> replyLeader,
long now)
Receive a request to apply a transition or multiple transitions.
|
java.util.concurrent.CompletableFuture<EloquentRaftProto.RaftMessage> |
receiveApplyTransitionRPC(EloquentRaftProto.ApplyTransitionRequest transition,
long now)
Apply a transition to Raft.
|
void |
receiveBadRequest(EloquentRaftProto.RaftMessage message)
A bad RPC call was received.
|
void |
receiveInstallSnapshotReply(EloquentRaftProto.InstallSnapshotReply reply,
long now)
We received an asynchronous snapshot reply from a server.
|
void |
receiveInstallSnapshotRPC(EloquentRaftProto.InstallSnapshotRequest snapshot,
java.util.function.Consumer<EloquentRaftProto.RaftMessage> replyLeader,
long now)
Receive a snapshot request RPC call.
|
java.util.concurrent.CompletableFuture<EloquentRaftProto.RaftMessage> |
receiveRemoveServerRPC(EloquentRaftProto.RemoveServerRequest removeServerRequest,
long now)
A request has been received to remove a server to the cluster.
|
void |
receiveRequestVoteRPC(EloquentRaftProto.RequestVoteRequest voteRequest,
java.util.function.Consumer<EloquentRaftProto.RaftMessage> replyLeader,
long now)
Clearly an election has been initiated, and some candidate is requesting votes to become the new leader.
|
void |
receiveRequestVotesReply(EloquentRaftProto.RequestVoteReply reply,
long now)
We received votes from another server.
|
void |
sendAppendEntries(java.lang.String target,
long nextIndex)
Send an append entries request to a particular server.
|
java.lang.String |
serverName()
The name of this server.
|
RaftState |
state()
get A COPY OF the current Raft state.
|
void |
stop(boolean kill)
A method, called primarily from unit tests, to stop this algorithm and clean up the underlying transport,
if appropriate.
|
long |
term()
The term this node sees.
|
void |
triggerElection(long now)
Signal to the cluster that we are a candidate for an election, and we are soliciting votes
|
clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitelectionTimeoutMillisRange, heartbeatMillis, receiveMessage, receiveRPC, shutdownpublic final RaftAlgorithm impl
public static final java.util.concurrent.atomic.AtomicInteger boundaryPoolThreadsWaiting
public SingleThreadedRaftAlgorithm(RaftAlgorithm impl, java.util.concurrent.ExecutorService boundaryPool)
impl - The implemeting algorithm. See impl.boundaryPool - The boundary pool. See boundaryPool.public int queuedTaskCount()
public RaftState state()
state in interface RaftAlgorithmpublic RaftState mutableState()
mutableState in interface RaftAlgorithmpublic RaftStateMachine mutableStateMachine()
mutableStateMachine in interface RaftAlgorithmpublic long term()
RaftState.currentTermterm in interface RaftAlgorithmpublic java.lang.String serverName()
RaftState.serverNameserverName in interface RaftAlgorithmpublic void broadcastAppendEntries(long now)
broadcastAppendEntries in interface RaftAlgorithmnow - The current time. This is usually System.currentTimeMillis(), but can
be mocked by unit tests.public void sendAppendEntries(java.lang.String target,
long nextIndex)
sendAppendEntries in interface RaftAlgorithmtarget - The server we're sending the append entries RPC to.nextIndex - The nextIndex value on the target machine.public void receiveAppendEntriesRPC(EloquentRaftProto.AppendEntriesRequest heartbeat, java.util.function.Consumer<EloquentRaftProto.RaftMessage> replyLeader, long now)
receiveAppendEntriesRPC in interface RaftAlgorithmheartbeat - The request body, doubling both as a heartbeat and a request to mutate the
state machine.replyLeader - The method for replying to the leader with an ACK of the request.now - The timestamp of the current time. In non-mock cases, this is always System.currentTimeMillis().public void receiveAppendEntriesReply(EloquentRaftProto.AppendEntriesReply reply, long now)
receiveAppendEntriesReply in interface RaftAlgorithmreply - The heartbeat ACK from the follower node.now - The timestamp of the current time. In non-mock cases, this is always System.currentTimeMillis().public void receiveInstallSnapshotRPC(EloquentRaftProto.InstallSnapshotRequest snapshot, java.util.function.Consumer<EloquentRaftProto.RaftMessage> replyLeader, long now)
receiveInstallSnapshotRPC in interface RaftAlgorithmsnapshot - The snapshot to install.replyLeader - The method for replying to the leader with an ACK of the request.now - The timestamp of the current time. In non-mock cases, this is always System.currentTimeMillis().public void receiveInstallSnapshotReply(EloquentRaftProto.InstallSnapshotReply reply, long now)
receiveInstallSnapshotReply in interface RaftAlgorithmreply - The snapshot reply from the follower node.now - The timestamp of the current time. In non-mock cases, this is always System.currentTimeMillis().public void triggerElection(long now)
triggerElection in interface RaftAlgorithmpublic void receiveRequestVoteRPC(EloquentRaftProto.RequestVoteRequest voteRequest, java.util.function.Consumer<EloquentRaftProto.RaftMessage> replyLeader, long now)
receiveRequestVoteRPC in interface RaftAlgorithmvoteRequest - The request for votes for a particular server.replyLeader - The method for replying to the leader with an ACK of the request.now - The timestamp of the current time. In non-mock cases, this is always System.currentTimeMillis().public void receiveRequestVotesReply(EloquentRaftProto.RequestVoteReply reply, long now)
receiveRequestVotesReply in interface RaftAlgorithmreply - The vote from the server, which we should count to see if we have a
majority.now - The timestamp of the current time. In non-mock cases, this is always System.currentTimeMillis().public java.util.concurrent.CompletableFuture<EloquentRaftProto.RaftMessage> receiveAddServerRPC(EloquentRaftProto.AddServerRequest addServerRequest, long now)
A request has been received to add a server to the cluster. This is only well-defined for the leader -- if the request was not received by the leader, then it should forward to the leader.
The algorithm for this is the following:
receiveAddServerRPC in interface RaftAlgorithmaddServerRequest - The request to add the server.now - The timestamp of the current time. In non-mock cases, this is always System.currentTimeMillis().public java.util.concurrent.CompletableFuture<EloquentRaftProto.RaftMessage> receiveRemoveServerRPC(EloquentRaftProto.RemoveServerRequest removeServerRequest, long now)
receiveRemoveServerRPC in interface RaftAlgorithmremoveServerRequest - The snapshot to install.now - The timestamp of the current time. In non-mock cases, this is always System.currentTimeMillis().public java.util.concurrent.CompletableFuture<EloquentRaftProto.RaftMessage> receiveApplyTransitionRPC(EloquentRaftProto.ApplyTransitionRequest transition, long now)
receiveApplyTransitionRPC in interface RaftAlgorithmtransition - The transition to applynow - The timestamp of the current time. In non-mock cases, this is always System.currentTimeMillis().public boolean bootstrap(boolean force)
RaftState.bootstrap(boolean), with
some error checks beforehand.
If this node cannot bootstrap, we return false.bootstrap in interface RaftAlgorithmpublic void stop(boolean kill)
stop in interface RaftAlgorithmkill - If true, kill the server unceremoniously, without waiting for a handoff.public boolean isRunning()
RaftAlgorithm.stop(boolean).isRunning in interface RaftAlgorithmpublic void heartbeat(long now)
heartbeat in interface RaftAlgorithmpublic void receiveBadRequest(EloquentRaftProto.RaftMessage message)
receiveBadRequest in interface RaftAlgorithmmessage - The raw message received.public java.util.Optional<RaftLifecycle> lifecycle()
lifecycle in interface RaftAlgorithmpublic RaftTransport getTransport()
RaftAlgorithmgetTransport in interface RaftAlgorithmpublic void flush(java.lang.Runnable additionalCriteria)
additionalCriteria - A function to run once things are flushed, after
which we should flush again. That is, make sure both
the transport is flushed, and this additional criteria
is also met (i.e., has run) when the algorithm is flushed.public java.util.List<java.lang.String> errors()
protected void finalize()
throws java.lang.Throwable
finalize in class java.lang.Objectjava.lang.Throwable