diff --git a/arangod/Agency/Constituent.cpp b/arangod/Agency/Constituent.cpp index afc07adbca..eb4b19052d 100644 --- a/arangod/Agency/Constituent.cpp +++ b/arangod/Agency/Constituent.cpp @@ -77,13 +77,13 @@ Constituent::Constituent() _vocbase(nullptr), _queryRegistry(nullptr), _term(0), + _cast(false), _leaderID((std::numeric_limits::max)()), _id(0), _role(FOLLOWER), _agent(nullptr), _votedFor((std::numeric_limits::max)()), - _notifier(nullptr) { - } + _notifier(nullptr) {} /// Shutdown if not already @@ -131,7 +131,8 @@ void Constituent::term(term_t 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; body.add(VPackValue(VPackValueType::Object)); @@ -180,7 +181,7 @@ void Constituent::follow(term_t t) { if (_role != FOLLOWER) { LOG_TOPIC(INFO, Logger::AGENCY) - << "Role change: Converting to follower in term " << t; + << _id << ": Converting to follower in term " << t; } _term = t; @@ -190,13 +191,19 @@ void Constituent::follow(term_t t) { /// Become leader -void Constituent::lead() { +void Constituent::lead(std::vector const& votes) { MUTEX_LOCKER(guard, _castLock); if (_role != LEADER) { - LOG_TOPIC(INFO, Logger::AGENCY) - << "Role change: Converted to leader in term " << _term; + std::stringstream ss; + 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; } @@ -213,7 +220,7 @@ void Constituent::candidate() { if (_role != CANDIDATE) LOG_TOPIC(INFO, Logger::AGENCY) - << "Role change: Converted to candidate in term " << _term; + << _id << ": Converted to candidate in term " << _term; _role = CANDIDATE; @@ -300,18 +307,23 @@ void Constituent::notifyAll() { /// @brief Vote bool Constituent::vote(term_t term, arangodb::consensus::id_t id, index_t prevLogIndex, term_t prevLogTerm) { + term_t t = 0; arangodb::consensus::id_t lid = 0; + bool cast = false; + { MUTEX_LOCKER(guard, _castLock); t = _term; lid = _leaderID; + cast = _cast; + _cast = true; } - if (term > t || (t == term && lid == id)) { + + if (term > t || (t == term && lid == id && !cast)) { this->term(term); { MUTEX_LOCKER(guard, _castLock); - _cast = true; // Note that I voted this time around. _votedFor = id; // The guy I voted for I assume leader. _leaderID = id; } @@ -323,9 +335,10 @@ bool Constituent::vote(term_t term, arangodb::consensus::id_t id, _cv.signal(); } return true; - } else { // Myself running or leading - return false; - } + } + + return false; + } /// @brief Call to election @@ -405,7 +418,7 @@ void Constituent::callElection() { // Evaluate election results if (yea > size() / 2) { - lead(); + lead(votes); } else { follow(_term); } diff --git a/arangod/Agency/Constituent.h b/arangod/Agency/Constituent.h index b24c563722..1740b0a79b 100644 --- a/arangod/Agency/Constituent.h +++ b/arangod/Agency/Constituent.h @@ -108,7 +108,7 @@ class Constituent : public arangodb::Thread { void candidate(); /// @brief Become leader - void lead(); + void lead(std::vector const&); /// @brief Call for vote (by leader or candidates after timeout) void callElection();