Fix infinite wait in leader election.
Reviewers: msantl Reviewed By: msantl Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1763
This commit is contained in:
parent
f501980973
commit
8e796e9fd1
@ -30,7 +30,7 @@ RaftServer::RaftServer(uint16_t server_id, const std::string &durability_dir,
|
|||||||
reset_callback_(reset_callback) {
|
reset_callback_(reset_callback) {
|
||||||
// Persistent storage initialization/recovery.
|
// Persistent storage initialization/recovery.
|
||||||
if (Log().empty()) {
|
if (Log().empty()) {
|
||||||
disk_storage_.Put(kCurrentTermKey, "0");
|
UpdateTerm(0);
|
||||||
} else {
|
} else {
|
||||||
Recover();
|
Recover();
|
||||||
}
|
}
|
||||||
@ -59,6 +59,15 @@ RaftServer::RaftServer(uint16_t server_id, const std::string &durability_dir,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [Raft paper figure 2]
|
||||||
|
// If RPC request or response contains term T > currentTerm,
|
||||||
|
// set currentTerm = T and convert to follower.
|
||||||
|
if (req.term > current_term) {
|
||||||
|
UpdateTerm(req.term);
|
||||||
|
if (mode_ != Mode::FOLLOWER)
|
||||||
|
Transition(Mode::FOLLOWER);
|
||||||
|
}
|
||||||
|
|
||||||
// [Raft paper 5.2, 5.4]
|
// [Raft paper 5.2, 5.4]
|
||||||
// "Each server will vote for at most one candidate in a given
|
// "Each server will vote for at most one candidate in a given
|
||||||
// term, on a first-come-first-serve basis with an additional
|
// term, on a first-come-first-serve basis with an additional
|
||||||
@ -91,6 +100,15 @@ RaftServer::RaftServer(uint16_t server_id, const std::string &durability_dir,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [Raft paper figure 2]
|
||||||
|
// If RPC request or response contains term T > currentTerm,
|
||||||
|
// set currentTerm = T and convert to follower.
|
||||||
|
if (req.term > current_term) {
|
||||||
|
UpdateTerm(req.term);
|
||||||
|
if (mode_ != Mode::FOLLOWER)
|
||||||
|
Transition(Mode::FOLLOWER);
|
||||||
|
}
|
||||||
|
|
||||||
// respond positively to a heartbeat.
|
// respond positively to a heartbeat.
|
||||||
// TODO(ipaljak) review this when implementing log replication.
|
// TODO(ipaljak) review this when implementing log replication.
|
||||||
if (req.entries.empty()) {
|
if (req.entries.empty()) {
|
||||||
@ -98,9 +116,9 @@ RaftServer::RaftServer(uint16_t server_id, const std::string &durability_dir,
|
|||||||
Save(res, res_builder);
|
Save(res, res_builder);
|
||||||
if (mode_ != Mode::FOLLOWER) {
|
if (mode_ != Mode::FOLLOWER) {
|
||||||
Transition(Mode::FOLLOWER);
|
Transition(Mode::FOLLOWER);
|
||||||
state_changed_.notify_all();
|
|
||||||
} else {
|
} else {
|
||||||
SetNextElectionTimePoint();
|
SetNextElectionTimePoint();
|
||||||
|
election_change_.notify_all();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -252,9 +270,10 @@ void RaftServer::Transition(const Mode &new_mode) {
|
|||||||
reset_callback_();
|
reset_callback_();
|
||||||
}
|
}
|
||||||
LOG(INFO) << "Server " << server_id_ << ": Transition to FOLLOWER";
|
LOG(INFO) << "Server " << server_id_ << ": Transition to FOLLOWER";
|
||||||
SetNextElectionTimePoint();
|
|
||||||
mode_ = Mode::FOLLOWER;
|
mode_ = Mode::FOLLOWER;
|
||||||
// log_entry_buffer_.Disable();
|
// log_entry_buffer_.Disable();
|
||||||
|
SetNextElectionTimePoint();
|
||||||
|
election_change_.notify_all();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,6 +333,11 @@ void RaftServer::Transition(const Mode &new_mode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RaftServer::UpdateTerm(uint64_t new_term) {
|
||||||
|
disk_storage_.Put(kCurrentTermKey, std::to_string(new_term));
|
||||||
|
disk_storage_.Delete(kVotedForKey);
|
||||||
|
}
|
||||||
|
|
||||||
void RaftServer::Recover() {
|
void RaftServer::Recover() {
|
||||||
throw utils::NotYetImplemented("RaftServer recover");
|
throw utils::NotYetImplemented("RaftServer recover");
|
||||||
}
|
}
|
||||||
|
@ -201,6 +201,9 @@ class RaftServer final : public RaftInterface {
|
|||||||
/// `raft::Mode`s.
|
/// `raft::Mode`s.
|
||||||
void Transition(const raft::Mode &new_mode);
|
void Transition(const raft::Mode &new_mode);
|
||||||
|
|
||||||
|
/// Updates the current term.
|
||||||
|
void UpdateTerm(uint64_t new_term);
|
||||||
|
|
||||||
/// Recovers from persistent storage. This function should be called from
|
/// Recovers from persistent storage. This function should be called from
|
||||||
/// the constructor before the server starts with normal operation.
|
/// the constructor before the server starts with normal operation.
|
||||||
void Recover();
|
void Recover();
|
||||||
|
Loading…
Reference in New Issue
Block a user