mirror of https://gitee.com/bigwinds/arangodb
Agency compiling again
This commit is contained in:
parent
39ca341097
commit
4759b2a434
|
@ -70,7 +70,7 @@ void AgencyFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
|
|||
new UInt64Parameter(&_size));
|
||||
|
||||
options->addOption("--agency.pool-size", "number of agent pool",
|
||||
new UInt64Parameter(&_pool_size));
|
||||
new UInt64Parameter(&_poolSize));
|
||||
|
||||
options->addOption(
|
||||
"--agency.election-timeout-min",
|
||||
|
@ -122,7 +122,7 @@ void AgencyFeature::validateOptions(std::shared_ptr<ProgramOptions> options) {
|
|||
}
|
||||
|
||||
// Agency size
|
||||
if (_pool_size < _size) {
|
||||
if (_poolSize < _size) {
|
||||
LOG_TOPIC(FATAL, Logger::AGENCY)
|
||||
<< "AGENCY: agency pool size must be larger than agency size.";
|
||||
FATAL_ERROR_EXIT();
|
||||
|
@ -191,7 +191,7 @@ void AgencyFeature::start() {
|
|||
_agent.reset(
|
||||
new consensus::Agent(
|
||||
consensus::config_t(
|
||||
std::string(), _minElectionTimeout, _maxElectionTimeout, endpoint,
|
||||
_size, _poolSize, _minElectionTimeout, _maxElectionTimeout, endpoint,
|
||||
_agencyEndpoints, _supervision, _waitForSync, _supervisionFrequency,
|
||||
_compactionStepSize)));
|
||||
|
||||
|
|
|
@ -45,15 +45,16 @@ class AgencyFeature : virtual public application_features::ApplicationFeature {
|
|||
private:
|
||||
bool _activated;
|
||||
uint64_t _size; // agency size (default: 5)
|
||||
uint64_t _poolSize;
|
||||
std::string _agentId;
|
||||
double _minElectionTimeout; // min election timeout
|
||||
double _maxElectionTimeout; // max election timeout
|
||||
std::map<std::string, std::string> _agencyEndpoints; // agency adresses
|
||||
bool _notify; // interval between retry to slaves
|
||||
bool _supervision;
|
||||
bool _waitForSync;
|
||||
double _supervisionFrequency;
|
||||
uint64_t _compactionStepSize;
|
||||
std::vector<std::string> _agencyEndpoints;
|
||||
|
||||
public:
|
||||
consensus::Agent* agent() const { return _agent.get(); }
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Agent.h"
|
||||
#include "GossipCallback.h"
|
||||
|
||||
#include "Basics/ConditionLocker.h"
|
||||
#include "RestServer/DatabaseFeature.h"
|
||||
|
@ -48,19 +49,31 @@ Agent::Agent(config_t const& config)
|
|||
_lastCommitIndex(0),
|
||||
_spearhead(this),
|
||||
_readDB(this),
|
||||
_serveActiveAgents(false),
|
||||
_serveActiveAgent(false),
|
||||
_nextCompationAfter(_config.compactionStepSize) {
|
||||
_state.configure(this);
|
||||
_constituent.configure(this);
|
||||
// _confirmed.resize(size(), 0); // agency's size and reset to 0
|
||||
//_lastHighest.resize(size(), 0);
|
||||
//_lastSent.resize(size());
|
||||
}
|
||||
|
||||
|
||||
/// This agent's id
|
||||
arangodb::consensus::id_t Agent::id() const {
|
||||
return _config.id;
|
||||
return config().id;
|
||||
}
|
||||
|
||||
|
||||
/// Agent's id is set once from state machine
|
||||
bool Agent::id(arangodb::consensus::id_t const& id) {
|
||||
MUTEX_LOCKER(mutexLocker, _cfgLock);
|
||||
_config.id = id;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// Merge command line and persisted comfigurations
|
||||
bool Agent::mergeConfiguration(VPackSlice const& persisted) {
|
||||
MUTEX_LOCKER(mutexLocker, _cfgLock);
|
||||
return _config.merge(persisted);
|
||||
}
|
||||
|
||||
|
||||
|
@ -111,8 +124,9 @@ priv_rpc_ret_t Agent::requestVote(
|
|||
}
|
||||
|
||||
|
||||
/// Get configuration
|
||||
config_t const& Agent::config() const {
|
||||
/// Get copy of momentary configuration
|
||||
config_t const Agent::config() const {
|
||||
MUTEX_LOCKER(mutexLocker, _cfgLock);
|
||||
return _config;
|
||||
}
|
||||
|
||||
|
@ -318,7 +332,7 @@ priv_rpc_ret_t Agent::sendAppendEntriesRPC(
|
|||
|
||||
// Send request
|
||||
arangodb::ClusterComm::instance()->asyncRequest(
|
||||
"1", 1, _config.endpoints[follower_id],
|
||||
"1", 1, _config.pool[follower_id],
|
||||
arangodb::GeneralRequest::RequestType::POST, path.str(),
|
||||
std::make_shared<std::string>(builder.toJson()), headerFields,
|
||||
std::make_shared<AgentCallback>(this, follower_id, highest),
|
||||
|
@ -445,7 +459,7 @@ void Agent::run() {
|
|||
}
|
||||
|
||||
// Append entries to followers
|
||||
for (arangodb::consensus::id_t i = 0; i < size(); ++i) {
|
||||
for (auto const& i : _config.active) {
|
||||
if (i != id()) {
|
||||
sendAppendEntriesRPC(i);
|
||||
}
|
||||
|
@ -580,7 +594,7 @@ void Agent::gossip() {
|
|||
std::map<std::string, std::string> pool;
|
||||
{
|
||||
MUTEX_LOCKER(mutexLocker, _cfgLock);
|
||||
pool = _config.pool
|
||||
pool = _config.pool;
|
||||
}
|
||||
|
||||
if (!pool.empty()) {
|
||||
|
@ -607,7 +621,7 @@ void Agent::gossip() {
|
|||
|
||||
for (auto const& agent : pool) {
|
||||
arangodb::ClusterComm::instance()->asyncRequest(
|
||||
"1", 1, pool.second, GeneralRequest::RequestType::POST, path,
|
||||
"1", 1, agent.second, GeneralRequest::RequestType::POST, path,
|
||||
std::make_shared<std::string>(word->toString()), headerFields,
|
||||
std::make_shared<GossipCallback>(), 1.0, true);
|
||||
}
|
||||
|
@ -621,16 +635,16 @@ void Agent::gossip() {
|
|||
/// Handle incomint gossip
|
||||
void Agent::gossip(query_t const& word) {
|
||||
|
||||
TRI_ASSERT(word->isObject());
|
||||
TRI_ASSERT(word->slice().isObject());
|
||||
|
||||
MUTEX_LOCKER(mutexLocker, _cfgLock);
|
||||
for (auto const& ent : VPackObjectIterator(word)) {
|
||||
for (auto const& ent : VPackObjectIterator(word->slice())) {
|
||||
TRI_ASSERT(ent.value.isString());
|
||||
auto it = _config.pool.find(ent.key);
|
||||
auto it = _config.pool.find(ent.key.copyString());
|
||||
if (it != _config.pool.end()) {
|
||||
TRI_ASSERT(it->second == ent.value.copyString());
|
||||
} else {
|
||||
_config.pool[ent.key] = ent.value;
|
||||
_config.pool[ent.key.copyString()] = ent.value.copyString();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -645,6 +659,7 @@ void Agent::gossip(query_t const& word) {
|
|||
bool Agent::activeAgency() {
|
||||
|
||||
std::map<std::string, std::string> pool;
|
||||
std::vector<std::string> active;
|
||||
{
|
||||
MUTEX_LOCKER(mutexLocker, _cfgLock);
|
||||
pool = _config.pool;
|
||||
|
@ -655,22 +670,21 @@ bool Agent::activeAgency() {
|
|||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
inline static query_t getResponse(
|
||||
std::string const& endpoint, std::sting const& path, double timeout = 1.0) {
|
||||
std::string const& endpoint, std::string const& path, double timeout = 1.0) {
|
||||
|
||||
query_t ret = nullptr;
|
||||
|
||||
auto headerFields =
|
||||
std::make_unique<std::unordered_map<std::string, std::string>>();
|
||||
|
||||
std::unordered_map<std::string, std::string> headerFields;
|
||||
auto res = arangodb::ClusterComm::instance()->syncRequest(
|
||||
"1", 1, endpoint, GeneralRequest::RequestType::GET, path, std::string(),
|
||||
headerFields, 1.0);
|
||||
|
||||
if (res.status == CL_COMM_RECEIVED) {
|
||||
ret = res.result->getBodyVelocyPack();
|
||||
if (res->status == CL_COMM_RECEIVED) {
|
||||
ret = res->result->getBodyVelocyPack();
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -685,13 +699,33 @@ bool Agent::persistedAgents() {
|
|||
active = _config.active;
|
||||
}
|
||||
|
||||
auto const& it = active.find(config.id);
|
||||
// 1 min timeout
|
||||
std::chrono::seconds timeout(60);
|
||||
|
||||
auto const& it = find(active.begin(), active.end(), _config.id);
|
||||
auto start = std::chrono::system_clock::now();
|
||||
|
||||
if (it != active.end()) { // Serve /_api/agency/activeAgents
|
||||
if (it != active.end()) {
|
||||
|
||||
{
|
||||
MUTEX_LOCKER(mutexLocker, _cfgLock);
|
||||
_serveActiveAgent = true; // Serve /_api/agency/activeAgents
|
||||
}
|
||||
|
||||
_serveActiveAgents = true;
|
||||
while (true) {
|
||||
|
||||
if (std::chrono::system_clock::now() - start > timeout) {
|
||||
{
|
||||
MUTEX_LOCKER(mutexLocker, _cfgLock);
|
||||
_config.active.clear();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
MUTEX_LOCKER(mutexLocker, _cfgLock);
|
||||
_serveActiveAgent = false; // Unserve /_api/agency/activeAgents
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -710,27 +744,39 @@ bool Agent::persistedAgents() {
|
|||
<< "Got response from a persisted agent with configuration "
|
||||
<< slice.toJson();
|
||||
MUTEX_LOCKER(mutexLocker, _cfgLock);
|
||||
_config.override(res);
|
||||
_config.override(slice);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (60.0e9 > std::chrono::system_clock::now() - start) { // 1 min timeout
|
||||
|
||||
if (std::chrono::system_clock::now() - start > timeout) {
|
||||
{
|
||||
MUTEX_LOCKER(mutexLocker, _cfgLock);
|
||||
_config.active.clear();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
_serveActiveAgents = false;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Do we serve agentStartupSequence
|
||||
bool Agent::serveActiveAgent() {
|
||||
return _serveActiveAgent;
|
||||
}
|
||||
|
||||
|
||||
/// Initial inception of the agency world
|
||||
void Agent::inception() {
|
||||
|
||||
auto start = std::chrono::system_clock::now(); //
|
||||
std::chrono::seconds timeout(300);
|
||||
|
||||
if (persistedAgents()) {
|
||||
return;
|
||||
|
@ -738,13 +784,19 @@ void Agent::inception() {
|
|||
|
||||
CONDITION_LOCKER(guard, _configCV);
|
||||
|
||||
while (booting) {
|
||||
while (booting()) {
|
||||
|
||||
if (activeAgency()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_configCV.wait(1000);
|
||||
|
||||
if (std::chrono::system_clock::now() - start > timeout) {
|
||||
LOG_TOPIC(ERR, Logger::AGENCY) <<
|
||||
"Failed to find complete pool of agents.";
|
||||
FATAL_ERROR_EXIT();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ class Agent : public arangodb::Thread {
|
|||
index_t, query_t const&);
|
||||
|
||||
/// @brief Provide configuration
|
||||
config_t const& config() const;
|
||||
config_t const config() const;
|
||||
|
||||
/// @brief Start thread
|
||||
bool start();
|
||||
|
@ -106,13 +106,16 @@ class Agent : public arangodb::Thread {
|
|||
void run() override final;
|
||||
|
||||
/// @brief Are we still booting?
|
||||
void booting();
|
||||
bool booting();
|
||||
|
||||
/// @brief Gossip out
|
||||
void gossip();
|
||||
|
||||
/// @brief Gossip in
|
||||
void gossip(query_t const& word);
|
||||
|
||||
/// @brief Persisted agents
|
||||
bool persistedAgents();
|
||||
|
||||
/// @brief Gossip in
|
||||
bool activeAgency();
|
||||
|
@ -147,11 +150,22 @@ class Agent : public arangodb::Thread {
|
|||
/// @brief Get spearhead store
|
||||
Store const& spearhead() const;
|
||||
|
||||
bool serveActiveAgent();
|
||||
|
||||
/// State reads persisted state and prepares the agent
|
||||
friend class State;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
Agent& operator=(VPackSlice const&);
|
||||
|
||||
/// @brief Get current term
|
||||
bool id(arangodb::consensus::id_t const&);
|
||||
|
||||
/// @brief Get current term
|
||||
bool mergeConfiguration(VPackSlice const&);
|
||||
|
||||
/// @brief Leader ID
|
||||
void lastCommitted(arangodb::consensus::index_t);
|
||||
|
||||
|
@ -200,10 +214,10 @@ class Agent : public arangodb::Thread {
|
|||
std::map<std::string, index_t> _lastHighest;
|
||||
std::map<std::string, TimePoint> _lastSent;
|
||||
arangodb::Mutex _ioLock; /**< @brief Read/Write lock */
|
||||
arangodb::Mutex _cfgLock; /**< @brief configuration gossip lock */
|
||||
mutable arangodb::Mutex _cfgLock; /**< @brief configuration gossip lock */
|
||||
|
||||
/// @brief Server active agents rest handler
|
||||
bool _serveActiveAgents;
|
||||
bool _serveActiveAgent;
|
||||
|
||||
/// @brief Next compaction after
|
||||
arangodb::consensus::index_t _nextCompationAfter;
|
||||
|
|
|
@ -211,7 +211,7 @@ struct config_t {
|
|||
|
||||
|
||||
/// @brief merge from persisted configuration
|
||||
void merge (VPackSlice const& conf) {
|
||||
bool merge (VPackSlice const& conf) {
|
||||
|
||||
id = conf.get(idStr).copyString(); // I get my id
|
||||
pool[id] = endpoint; // Register my endpoint with it
|
||||
|
@ -349,6 +349,8 @@ struct config_t {
|
|||
}
|
||||
LOG_TOPIC(DEBUG, Logger::AGENCY) << ss.str();
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#include "Utils/StandaloneTransactionContext.h"
|
||||
#include "VocBase/collection.h"
|
||||
#include "VocBase/vocbase.h"
|
||||
#include "Agency/NotifierThread.h"
|
||||
|
||||
using namespace arangodb::consensus;
|
||||
using namespace arangodb::rest;
|
||||
|
@ -82,8 +81,8 @@ Constituent::Constituent()
|
|||
_id(0),
|
||||
_role(FOLLOWER),
|
||||
_agent(nullptr),
|
||||
_votedFor(NO_LEADER),
|
||||
_notifier(nullptr) {}
|
||||
_votedFor(NO_LEADER)
|
||||
{}
|
||||
|
||||
|
||||
/// Shutdown if not already
|
||||
|
@ -92,12 +91,6 @@ Constituent::~Constituent() {
|
|||
}
|
||||
|
||||
|
||||
/// Configuration
|
||||
config_t const& Constituent::config() const {
|
||||
return _agent->config();
|
||||
}
|
||||
|
||||
|
||||
/// Wait for sync
|
||||
bool Constituent::waitForSync() const {
|
||||
return _agent->config().waitForSync;
|
||||
|
@ -140,7 +133,7 @@ void Constituent::term(term_t t) {
|
|||
i_str << std::setw(20) << std::setfill('0') << t;
|
||||
body.add("_key", Value(i_str.str()));
|
||||
body.add("term", Value(t));
|
||||
body.add("voted_for", Value((uint32_t)_votedFor));
|
||||
body.add("voted_for", Value(_votedFor));
|
||||
body.close();
|
||||
|
||||
TRI_ASSERT(_vocbase != nullptr);
|
||||
|
@ -191,7 +184,7 @@ void Constituent::follow(term_t t) {
|
|||
|
||||
|
||||
/// Become leader
|
||||
void Constituent::lead(std::vector<bool> const& votes) {
|
||||
void Constituent::lead(std::map<arangodb::consensus::id_t, bool> const& votes) {
|
||||
|
||||
{
|
||||
MUTEX_LOCKER(guard, _castLock);
|
||||
|
@ -207,7 +200,7 @@ void Constituent::lead(std::vector<bool> const& votes) {
|
|||
std::stringstream ss;
|
||||
ss << _id << ": Converted to leader in term " << _term << " with votes (";
|
||||
for (auto const& vote : votes) {
|
||||
ss << vote;
|
||||
ss << vote.second;
|
||||
}
|
||||
ss << ")";
|
||||
|
||||
|
@ -260,54 +253,16 @@ arangodb::consensus::id_t Constituent::leaderID() const {
|
|||
|
||||
/// Agency size
|
||||
size_t Constituent::size() const {
|
||||
return config().size();
|
||||
return _agent->config().size();
|
||||
}
|
||||
|
||||
|
||||
/// Get endpoint to an id
|
||||
std::string const& Constituent::endpoint(arangodb::consensus::id_t id) const {
|
||||
return config().endpoints[id];
|
||||
return _agent->config().pool.at(id);
|
||||
}
|
||||
|
||||
|
||||
/// Get all endpoints
|
||||
std::vector<std::string> const& Constituent::endpoints() const {
|
||||
return config().endpoints;
|
||||
}
|
||||
|
||||
/// Notify peers of updated endpoints
|
||||
void Constituent::notifyAll() {
|
||||
|
||||
// Send request to all but myself
|
||||
std::vector<std::string> toNotify;
|
||||
for (arangodb::consensus::id_t i = 0; i < size(); ++i) {
|
||||
if (i != _id) {
|
||||
toNotify.push_back(endpoint(i));
|
||||
}
|
||||
}
|
||||
|
||||
// Body contains endpoints list
|
||||
auto body = std::make_shared<VPackBuilder>();
|
||||
body->openObject();
|
||||
body->add("endpoints", VPackValue(VPackValueType::Array));
|
||||
|
||||
for (auto const& i : endpoints()) {
|
||||
body->add(Value(i));
|
||||
}
|
||||
|
||||
body->close();
|
||||
body->close();
|
||||
|
||||
// Last process notifies everyone
|
||||
std::stringstream path;
|
||||
|
||||
path << "/_api/agency_priv/notifyAll?term=" << _term << "&agencyId=" << _id;
|
||||
|
||||
_notifier = std::make_unique<NotifierThread>(path.str(), body, toNotify);
|
||||
_notifier->start();
|
||||
|
||||
}
|
||||
|
||||
/// @brief Vote
|
||||
bool Constituent::vote(term_t term, arangodb::consensus::id_t id,
|
||||
index_t prevLogIndex, term_t prevLogTerm,
|
||||
|
@ -351,49 +306,53 @@ bool Constituent::vote(term_t term, arangodb::consensus::id_t id,
|
|||
|
||||
/// @brief Call to election
|
||||
void Constituent::callElection() {
|
||||
std::vector<bool> votes(size(), false);
|
||||
std::map<arangodb::consensus::id_t,bool> votes;
|
||||
std::vector<std::string> active = _agent->config().active; // Get copy of active
|
||||
|
||||
votes.at(_id) = true; // vote for myself
|
||||
votes[_id] = true; // vote for myself
|
||||
_cast = true;
|
||||
_votedFor = _id;
|
||||
_leaderID = NO_LEADER;
|
||||
this->term(_term + 1); // raise my term
|
||||
|
||||
std::string body;
|
||||
std::vector<OperationID> operationIDs(config().endpoints.size());
|
||||
std::map<arangodb::consensus::id_t,OperationID> operationIDs;
|
||||
std::stringstream path;
|
||||
|
||||
path << "/_api/agency_priv/requestVote?term=" << _term
|
||||
<< "&candidateId=" << _id << "&prevLogIndex=" << _agent->lastLog().index
|
||||
<< "&candidateId=" << _id
|
||||
<< "&prevLogIndex=" << _agent->lastLog().index
|
||||
<< "&prevLogTerm=" << _agent->lastLog().term;
|
||||
|
||||
double minPing = _agent->config().minPing;
|
||||
|
||||
double respTimeout = 0.9*minPing;
|
||||
double initTimeout = 0.5*minPing;
|
||||
|
||||
// Ask everyone for their vote
|
||||
for (arangodb::consensus::id_t i = 0; i < config().endpoints.size(); ++i) {
|
||||
if (i != _id && endpoint(i) != "") {
|
||||
for (auto const& i : active) {
|
||||
if (i != _id) {
|
||||
auto headerFields =
|
||||
std::make_unique<std::unordered_map<std::string, std::string>>();
|
||||
operationIDs[i] = arangodb::ClusterComm::instance()->asyncRequest(
|
||||
"1", 1, config().endpoints[i], GeneralRequest::RequestType::GET,
|
||||
path.str(), std::make_shared<std::string>(body), headerFields,
|
||||
nullptr, 0.75*config().minPing, true, 0.5*config().minPing);
|
||||
std::make_unique<std::unordered_map<std::string, std::string>>();
|
||||
operationIDs[i] = ClusterComm::instance()->asyncRequest(
|
||||
"1", 1, _agent->config().pool.at(i),
|
||||
GeneralRequest::RequestType::GET, path.str(),
|
||||
std::make_shared<std::string>(body), headerFields,
|
||||
nullptr, respTimeout, true, initTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Wait randomized timeout
|
||||
std::this_thread::sleep_for(
|
||||
sleepFor(.5 * config().minPing, .8 * config().minPing));
|
||||
|
||||
std::this_thread::sleep_for(sleepFor(initTimeout, respTimeout));
|
||||
|
||||
// Collect votes
|
||||
// FIXME: This code can be improved: One can wait for an arbitrary
|
||||
// result by creating a coordinatorID and waiting for a pattern.
|
||||
for (arangodb::consensus::id_t i = 0; i < config().endpoints.size(); ++i) {
|
||||
if (i != _id && endpoint(i) != "") {
|
||||
for (const auto& i : active) {
|
||||
if (i != _id) {
|
||||
ClusterCommResult res =
|
||||
arangodb::ClusterComm::instance()->enquire(operationIDs[i]);
|
||||
|
||||
arangodb::ClusterComm::instance()->enquire(operationIDs[i]);
|
||||
|
||||
if (res.status == CL_COMM_SENT) { // Request successfully sent
|
||||
res = arangodb::ClusterComm::instance()->wait(
|
||||
"1", 1, operationIDs[i], "1");
|
||||
res = ClusterComm::instance()->wait("1", 1, operationIDs[i], "1");
|
||||
std::shared_ptr<Builder> body = res.result->getBodyVelocyPack();
|
||||
if (body->isEmpty()) { // body empty
|
||||
continue;
|
||||
|
@ -406,7 +365,7 @@ void Constituent::callElection() {
|
|||
follow(t);
|
||||
break;
|
||||
}
|
||||
votes[i] = slc.get("voteGranted").getBool(); // Get vote
|
||||
votes[i] = slc.get("voteGranted").getBool(); // Get vote
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -415,11 +374,11 @@ void Constituent::callElection() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Count votes
|
||||
size_t yea = 0;
|
||||
for (size_t i = 0; i < size(); ++i) {
|
||||
if (votes[i]) {
|
||||
for (auto const& i : votes) {
|
||||
if (i.second) {
|
||||
yea++;
|
||||
}
|
||||
}
|
||||
|
@ -437,12 +396,11 @@ void Constituent::callElection() {
|
|||
/// Start clean shutdown
|
||||
void Constituent::beginShutdown() {
|
||||
|
||||
_notifier.reset();
|
||||
Thread::beginShutdown();
|
||||
|
||||
|
||||
CONDITION_LOCKER(guard, _cv);
|
||||
guard.broadcast();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -482,11 +440,10 @@ void Constituent::run() {
|
|||
for (auto const& i : VPackArrayIterator(result)) {
|
||||
try {
|
||||
_term = i.get("term").getUInt();
|
||||
_votedFor =
|
||||
static_cast<decltype(_votedFor)>(i.get("voted_for").getUInt());
|
||||
_votedFor = i.get("voted_for").copyString();
|
||||
} catch (std::exception const&) {
|
||||
LOG_TOPIC(ERR, Logger::AGENCY)
|
||||
<< "Persisted election entries corrupt! Defaulting term,vote (0,0)";
|
||||
<< "Persisted election entries corrupt! Defaulting term,vote (0,0)";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -496,15 +453,16 @@ void Constituent::run() {
|
|||
|
||||
if (_role == FOLLOWER) {
|
||||
bool cast = false;
|
||||
|
||||
|
||||
{
|
||||
MUTEX_LOCKER(guard, _castLock);
|
||||
_cast = false; // New round set not cast vote
|
||||
}
|
||||
|
||||
int32_t left = static_cast<int32_t>(1000000.0 * config().minPing), right = static_cast<int32_t>(1000000.0 * config().maxPing);
|
||||
|
||||
int32_t left = static_cast<int32_t>(1000000.0 * _agent->config().minPing),
|
||||
right = static_cast<int32_t>(1000000.0 * _agent->config().maxPing);
|
||||
long rand_wait = static_cast<long>(RandomGenerator::interval(left, right));
|
||||
|
||||
|
||||
{
|
||||
CONDITION_LOCKER(guardv, _cv);
|
||||
_cv.wait(rand_wait);
|
||||
|
@ -522,7 +480,7 @@ void Constituent::run() {
|
|||
} else if (_role == CANDIDATE) {
|
||||
callElection(); // Run for office
|
||||
} else {
|
||||
int32_t left = static_cast<int32_t>(100000.0 * config().minPing);
|
||||
int32_t left = static_cast<int32_t>(100000.0 * _agent->config().minPing);
|
||||
long rand_wait = static_cast<long>(left);
|
||||
{
|
||||
CONDITION_LOCKER(guardv, _cv);
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
#include "AgencyCommon.h"
|
||||
#include "AgentConfiguration.h"
|
||||
#include "NotifierThread.h"
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Basics/Thread.h"
|
||||
|
@ -109,7 +108,7 @@ class Constituent : public arangodb::Thread {
|
|||
void candidate();
|
||||
|
||||
/// @brief Become leader
|
||||
void lead(std::vector<bool> const&);
|
||||
void lead(std::map<arangodb::consensus::id_t,bool> const&);
|
||||
|
||||
/// @brief Call for vote (by leader or candidates after timeout)
|
||||
void callElection();
|
||||
|
@ -120,11 +119,6 @@ class Constituent : public arangodb::Thread {
|
|||
/// @brief Wait for sync
|
||||
bool waitForSync() const;
|
||||
|
||||
/// @brief Notify everyone, that we are good to go.
|
||||
/// This is the task of the last process starting up.
|
||||
/// Will be taken care of by gossip
|
||||
void notifyAll();
|
||||
|
||||
/// @brief Sleep for how long
|
||||
duration_t sleepFor(double, double);
|
||||
|
||||
|
@ -141,8 +135,6 @@ class Constituent : public arangodb::Thread {
|
|||
Agent* _agent; /**< @brief My boss */
|
||||
arangodb::consensus::id_t _votedFor;
|
||||
|
||||
std::unique_ptr<NotifierThread> _notifier;
|
||||
|
||||
arangodb::basics::ConditionVariable _cv; // agency callbacks
|
||||
mutable arangodb::Mutex _castLock;
|
||||
};
|
||||
|
|
|
@ -74,7 +74,7 @@ inline RestHandler::status RestAgencyHandler::reportUnknownMethod() {
|
|||
void RestAgencyHandler::redirectRequest(arangodb::consensus::id_t leaderId) {
|
||||
try {
|
||||
std::string url =
|
||||
Endpoint::uriForm(_agent->config().pool[leaderId]) +
|
||||
Endpoint::uriForm(_agent->config().pool.at(leaderId)) +
|
||||
_request->requestPath();
|
||||
setResponseCode(GeneralResponse::ResponseCode::TEMPORARY_REDIRECT);
|
||||
_response->setHeaderNC(StaticStrings::Location, url);
|
||||
|
@ -140,7 +140,7 @@ RestHandler::status RestAgencyHandler::handleWrite() {
|
|||
return status::DONE;
|
||||
}
|
||||
|
||||
while(_agent->size() > 1 && _agent->leaderID() = NO_LEADER) {
|
||||
while(_agent->size() > 1 && _agent->leaderID() == "") {
|
||||
std::this_thread::sleep_for(duration_t(100));
|
||||
}
|
||||
|
||||
|
@ -215,7 +215,7 @@ inline RestHandler::status RestAgencyHandler::handleRead() {
|
|||
return status::DONE;
|
||||
}
|
||||
|
||||
while(_agent->size() > 1 && _agent->leaderID() > 100) {
|
||||
while(_agent->size() > 1 && _agent->leaderID() == "") {
|
||||
std::this_thread::sleep_for(duration_t(100));
|
||||
}
|
||||
|
||||
|
|
|
@ -130,11 +130,11 @@ RestHandler::status RestAgencyPrivHandler::execute() {
|
|||
return reportBadQuery(); // bad query
|
||||
}
|
||||
} else if (_request->suffix()[0] == "gossip") {
|
||||
if (_agent->activeAgentStartupSequence()) {
|
||||
if (_agent->serveActiveAgent()) { // only during startup (see Agent)
|
||||
arangodb::velocypack::Options options;
|
||||
query_t query = _request->toVelocyPackBuilderPtr(&options);
|
||||
_agent->gossip(query);
|
||||
} else {
|
||||
} else { // Gone!
|
||||
return reportGone();
|
||||
}
|
||||
}else {
|
||||
|
|
|
@ -505,9 +505,9 @@ bool State::loadOrPersistConfiguration() {
|
|||
|
||||
if (result.isArray() && result.length()) { // We already have a persisted conf
|
||||
|
||||
try (config.merge(result)) {
|
||||
0;
|
||||
} catch (std::exception const& e) {
|
||||
try {
|
||||
_agent->mergeConfiguration(result);
|
||||
} catch (std::exception const& e) {
|
||||
LOG_TOPIC(ERR, Logger::AGENCY)
|
||||
<< "Failed to merge persisted configuration into runtime configuration:"
|
||||
<< e.what();
|
||||
|
@ -519,7 +519,7 @@ bool State::loadOrPersistConfiguration() {
|
|||
LOG_TOPIC(DEBUG, Logger::AGENCY) << "New agency!";
|
||||
|
||||
TRI_ASSERT(_agent != nullptr);
|
||||
_agent->config().id = to_string(boost::uuids::random_generator()());
|
||||
_agent->id(to_string(boost::uuids::random_generator()()));
|
||||
|
||||
auto transactionContext =
|
||||
std::make_shared<StandaloneTransactionContext>(_vocbase);
|
||||
|
@ -535,7 +535,7 @@ bool State::loadOrPersistConfiguration() {
|
|||
|
||||
try {
|
||||
result = trx.insert(
|
||||
"configuration", _agent.config().toBuilder().slice(), _options);
|
||||
"configuration", _agent->config().toBuilder()->slice(), _options);
|
||||
} catch (std::exception const& e) {
|
||||
LOG_TOPIC(ERR, Logger::AGENCY)
|
||||
<< "Failed to persist configuration entry:" << e.what();
|
||||
|
@ -549,7 +549,6 @@ bool State::loadOrPersistConfiguration() {
|
|||
}
|
||||
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue