1
0
Fork 0

fixed seldom race in election pulled back from 3.0

This commit is contained in:
Kaveh Vahedipour 2016-06-15 12:35:40 +02:00
parent 414e4ac714
commit e4556bb766
2 changed files with 28 additions and 15 deletions

View File

@ -77,13 +77,13 @@ Constituent::Constituent()
_vocbase(nullptr), _vocbase(nullptr),
_queryRegistry(nullptr), _queryRegistry(nullptr),
_term(0), _term(0),
_cast(false),
_leaderID((std::numeric_limits<arangodb::consensus::id_t>::max)()), _leaderID((std::numeric_limits<arangodb::consensus::id_t>::max)()),
_id(0), _id(0),
_role(FOLLOWER), _role(FOLLOWER),
_agent(nullptr), _agent(nullptr),
_votedFor((std::numeric_limits<arangodb::consensus::id_t>::max)()), _votedFor((std::numeric_limits<arangodb::consensus::id_t>::max)()),
_notifier(nullptr) { _notifier(nullptr) {}
}
/// Shutdown if not already /// Shutdown if not already
@ -131,7 +131,8 @@ void Constituent::term(term_t t) {
if (tmp != t) { if (tmp != t) {
LOG_TOPIC(INFO, Logger::AGENCY) << roleStr[_role] << " term " << t; LOG_TOPIC(INFO, Logger::AGENCY)
<< _id << ": " << roleStr[_role] << " term " << t;
Builder body; Builder body;
body.add(VPackValue(VPackValueType::Object)); body.add(VPackValue(VPackValueType::Object));
@ -180,7 +181,7 @@ void Constituent::follow(term_t t) {
if (_role != FOLLOWER) { if (_role != FOLLOWER) {
LOG_TOPIC(INFO, Logger::AGENCY) LOG_TOPIC(INFO, Logger::AGENCY)
<< "Role change: Converting to follower in term " << t; << _id << ": Converting to follower in term " << t;
} }
_term = t; _term = t;
@ -190,13 +191,19 @@ void Constituent::follow(term_t t) {
/// Become leader /// Become leader
void Constituent::lead() { void Constituent::lead(std::vector<bool> const& votes) {
MUTEX_LOCKER(guard, _castLock); MUTEX_LOCKER(guard, _castLock);
if (_role != LEADER) { if (_role != LEADER) {
LOG_TOPIC(INFO, Logger::AGENCY) std::stringstream ss;
<< "Role change: Converted to leader in term " << _term; ss << _id << ": Converted to leader in term " << _term << " with votes (";
for (auto const& vote : votes) {
ss << vote;
}
ss << ")";
LOG_TOPIC(INFO, Logger::AGENCY) << ss.str();
_agent->lead(); // We need to rebuild spear_head and read_db; _agent->lead(); // We need to rebuild spear_head and read_db;
} }
@ -213,7 +220,7 @@ void Constituent::candidate() {
if (_role != CANDIDATE) if (_role != CANDIDATE)
LOG_TOPIC(INFO, Logger::AGENCY) LOG_TOPIC(INFO, Logger::AGENCY)
<< "Role change: Converted to candidate in term " << _term; << _id << ": Converted to candidate in term " << _term;
_role = CANDIDATE; _role = CANDIDATE;
@ -300,18 +307,23 @@ void Constituent::notifyAll() {
/// @brief Vote /// @brief Vote
bool Constituent::vote(term_t term, arangodb::consensus::id_t id, bool Constituent::vote(term_t term, arangodb::consensus::id_t id,
index_t prevLogIndex, term_t prevLogTerm) { index_t prevLogIndex, term_t prevLogTerm) {
term_t t = 0; term_t t = 0;
arangodb::consensus::id_t lid = 0; arangodb::consensus::id_t lid = 0;
bool cast = false;
{ {
MUTEX_LOCKER(guard, _castLock); MUTEX_LOCKER(guard, _castLock);
t = _term; t = _term;
lid = _leaderID; lid = _leaderID;
cast = _cast;
_cast = true;
} }
if (term > t || (t == term && lid == id)) {
if (term > t || (t == term && lid == id && !cast)) {
this->term(term); this->term(term);
{ {
MUTEX_LOCKER(guard, _castLock); MUTEX_LOCKER(guard, _castLock);
_cast = true; // Note that I voted this time around.
_votedFor = id; // The guy I voted for I assume leader. _votedFor = id; // The guy I voted for I assume leader.
_leaderID = id; _leaderID = id;
} }
@ -323,9 +335,10 @@ bool Constituent::vote(term_t term, arangodb::consensus::id_t id,
_cv.signal(); _cv.signal();
} }
return true; return true;
} else { // Myself running or leading }
return false;
} return false;
} }
/// @brief Call to election /// @brief Call to election
@ -405,7 +418,7 @@ void Constituent::callElection() {
// Evaluate election results // Evaluate election results
if (yea > size() / 2) { if (yea > size() / 2) {
lead(); lead(votes);
} else { } else {
follow(_term); follow(_term);
} }

View File

@ -108,7 +108,7 @@ class Constituent : public arangodb::Thread {
void candidate(); void candidate();
/// @brief Become leader /// @brief Become leader
void lead(); void lead(std::vector<bool> const&);
/// @brief Call for vote (by leader or candidates after timeout) /// @brief Call for vote (by leader or candidates after timeout)
void callElection(); void callElection();