1
0
Fork 0

Agency compiling again

This commit is contained in:
Kaveh Vahedipour 2016-08-11 12:05:53 +02:00
parent 39ca341097
commit 4759b2a434
10 changed files with 167 additions and 149 deletions

View File

@ -70,7 +70,7 @@ void AgencyFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
new UInt64Parameter(&_size)); new UInt64Parameter(&_size));
options->addOption("--agency.pool-size", "number of agent pool", options->addOption("--agency.pool-size", "number of agent pool",
new UInt64Parameter(&_pool_size)); new UInt64Parameter(&_poolSize));
options->addOption( options->addOption(
"--agency.election-timeout-min", "--agency.election-timeout-min",
@ -122,7 +122,7 @@ void AgencyFeature::validateOptions(std::shared_ptr<ProgramOptions> options) {
} }
// Agency size // Agency size
if (_pool_size < _size) { if (_poolSize < _size) {
LOG_TOPIC(FATAL, Logger::AGENCY) LOG_TOPIC(FATAL, Logger::AGENCY)
<< "AGENCY: agency pool size must be larger than agency size."; << "AGENCY: agency pool size must be larger than agency size.";
FATAL_ERROR_EXIT(); FATAL_ERROR_EXIT();
@ -191,7 +191,7 @@ void AgencyFeature::start() {
_agent.reset( _agent.reset(
new consensus::Agent( new consensus::Agent(
consensus::config_t( consensus::config_t(
std::string(), _minElectionTimeout, _maxElectionTimeout, endpoint, _size, _poolSize, _minElectionTimeout, _maxElectionTimeout, endpoint,
_agencyEndpoints, _supervision, _waitForSync, _supervisionFrequency, _agencyEndpoints, _supervision, _waitForSync, _supervisionFrequency,
_compactionStepSize))); _compactionStepSize)));

View File

@ -45,15 +45,16 @@ class AgencyFeature : virtual public application_features::ApplicationFeature {
private: private:
bool _activated; bool _activated;
uint64_t _size; // agency size (default: 5) uint64_t _size; // agency size (default: 5)
uint64_t _poolSize;
std::string _agentId; std::string _agentId;
double _minElectionTimeout; // min election timeout double _minElectionTimeout; // min election timeout
double _maxElectionTimeout; // max election timeout double _maxElectionTimeout; // max election timeout
std::map<std::string, std::string> _agencyEndpoints; // agency adresses
bool _notify; // interval between retry to slaves bool _notify; // interval between retry to slaves
bool _supervision; bool _supervision;
bool _waitForSync; bool _waitForSync;
double _supervisionFrequency; double _supervisionFrequency;
uint64_t _compactionStepSize; uint64_t _compactionStepSize;
std::vector<std::string> _agencyEndpoints;
public: public:
consensus::Agent* agent() const { return _agent.get(); } consensus::Agent* agent() const { return _agent.get(); }

View File

@ -22,6 +22,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include "Agent.h" #include "Agent.h"
#include "GossipCallback.h"
#include "Basics/ConditionLocker.h" #include "Basics/ConditionLocker.h"
#include "RestServer/DatabaseFeature.h" #include "RestServer/DatabaseFeature.h"
@ -48,19 +49,31 @@ Agent::Agent(config_t const& config)
_lastCommitIndex(0), _lastCommitIndex(0),
_spearhead(this), _spearhead(this),
_readDB(this), _readDB(this),
_serveActiveAgents(false), _serveActiveAgent(false),
_nextCompationAfter(_config.compactionStepSize) { _nextCompationAfter(_config.compactionStepSize) {
_state.configure(this); _state.configure(this);
_constituent.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 /// This agent's id
arangodb::consensus::id_t Agent::id() const { 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 /// Get copy of momentary configuration
config_t const& Agent::config() const { config_t const Agent::config() const {
MUTEX_LOCKER(mutexLocker, _cfgLock);
return _config; return _config;
} }
@ -318,7 +332,7 @@ priv_rpc_ret_t Agent::sendAppendEntriesRPC(
// Send request // Send request
arangodb::ClusterComm::instance()->asyncRequest( arangodb::ClusterComm::instance()->asyncRequest(
"1", 1, _config.endpoints[follower_id], "1", 1, _config.pool[follower_id],
arangodb::GeneralRequest::RequestType::POST, path.str(), arangodb::GeneralRequest::RequestType::POST, path.str(),
std::make_shared<std::string>(builder.toJson()), headerFields, std::make_shared<std::string>(builder.toJson()), headerFields,
std::make_shared<AgentCallback>(this, follower_id, highest), std::make_shared<AgentCallback>(this, follower_id, highest),
@ -445,7 +459,7 @@ void Agent::run() {
} }
// Append entries to followers // Append entries to followers
for (arangodb::consensus::id_t i = 0; i < size(); ++i) { for (auto const& i : _config.active) {
if (i != id()) { if (i != id()) {
sendAppendEntriesRPC(i); sendAppendEntriesRPC(i);
} }
@ -580,7 +594,7 @@ void Agent::gossip() {
std::map<std::string, std::string> pool; std::map<std::string, std::string> pool;
{ {
MUTEX_LOCKER(mutexLocker, _cfgLock); MUTEX_LOCKER(mutexLocker, _cfgLock);
pool = _config.pool pool = _config.pool;
} }
if (!pool.empty()) { if (!pool.empty()) {
@ -607,7 +621,7 @@ void Agent::gossip() {
for (auto const& agent : pool) { for (auto const& agent : pool) {
arangodb::ClusterComm::instance()->asyncRequest( 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<std::string>(word->toString()), headerFields,
std::make_shared<GossipCallback>(), 1.0, true); std::make_shared<GossipCallback>(), 1.0, true);
} }
@ -621,16 +635,16 @@ void Agent::gossip() {
/// Handle incomint gossip /// Handle incomint gossip
void Agent::gossip(query_t const& word) { void Agent::gossip(query_t const& word) {
TRI_ASSERT(word->isObject()); TRI_ASSERT(word->slice().isObject());
MUTEX_LOCKER(mutexLocker, _cfgLock); MUTEX_LOCKER(mutexLocker, _cfgLock);
for (auto const& ent : VPackObjectIterator(word)) { for (auto const& ent : VPackObjectIterator(word->slice())) {
TRI_ASSERT(ent.value.isString()); 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()) { if (it != _config.pool.end()) {
TRI_ASSERT(it->second == ent.value.copyString()); TRI_ASSERT(it->second == ent.value.copyString());
} else { } 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() { bool Agent::activeAgency() {
std::map<std::string, std::string> pool; std::map<std::string, std::string> pool;
std::vector<std::string> active;
{ {
MUTEX_LOCKER(mutexLocker, _cfgLock); MUTEX_LOCKER(mutexLocker, _cfgLock);
pool = _config.pool; pool = _config.pool;
@ -655,22 +670,21 @@ bool Agent::activeAgency() {
} }
return false;
} }
inline static query_t getResponse( 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; query_t ret = nullptr;
std::unordered_map<std::string, std::string> headerFields;
auto headerFields =
std::make_unique<std::unordered_map<std::string, std::string>>();
auto res = arangodb::ClusterComm::instance()->syncRequest( auto res = arangodb::ClusterComm::instance()->syncRequest(
"1", 1, endpoint, GeneralRequest::RequestType::GET, path, std::string(), "1", 1, endpoint, GeneralRequest::RequestType::GET, path, std::string(),
headerFields, 1.0); headerFields, 1.0);
if (res.status == CL_COMM_RECEIVED) { if (res->status == CL_COMM_RECEIVED) {
ret = res.result->getBodyVelocyPack(); ret = res->result->getBodyVelocyPack();
} }
return ret; return ret;
@ -685,13 +699,33 @@ bool Agent::persistedAgents() {
active = _config.active; 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(); 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) { 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 { } else {
@ -710,27 +744,39 @@ bool Agent::persistedAgents() {
<< "Got response from a persisted agent with configuration " << "Got response from a persisted agent with configuration "
<< slice.toJson(); << slice.toJson();
MUTEX_LOCKER(mutexLocker, _cfgLock); 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; return false;
} }
} }
} }
_serveActiveAgents = false;
return false; return false;
} }
/// Do we serve agentStartupSequence
bool Agent::serveActiveAgent() {
return _serveActiveAgent;
}
/// Initial inception of the agency world /// Initial inception of the agency world
void Agent::inception() { void Agent::inception() {
auto start = std::chrono::system_clock::now(); // auto start = std::chrono::system_clock::now(); //
std::chrono::seconds timeout(300);
if (persistedAgents()) { if (persistedAgents()) {
return; return;
@ -738,7 +784,7 @@ void Agent::inception() {
CONDITION_LOCKER(guard, _configCV); CONDITION_LOCKER(guard, _configCV);
while (booting) { while (booting()) {
if (activeAgency()) { if (activeAgency()) {
return; return;
@ -746,6 +792,12 @@ void Agent::inception() {
_configCV.wait(1000); _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();
}
} }
} }

View File

@ -56,7 +56,7 @@ class Agent : public arangodb::Thread {
index_t, query_t const&); index_t, query_t const&);
/// @brief Provide configuration /// @brief Provide configuration
config_t const& config() const; config_t const config() const;
/// @brief Start thread /// @brief Start thread
bool start(); bool start();
@ -106,7 +106,7 @@ class Agent : public arangodb::Thread {
void run() override final; void run() override final;
/// @brief Are we still booting? /// @brief Are we still booting?
void booting(); bool booting();
/// @brief Gossip out /// @brief Gossip out
void gossip(); void gossip();
@ -114,6 +114,9 @@ class Agent : public arangodb::Thread {
/// @brief Gossip in /// @brief Gossip in
void gossip(query_t const& word); void gossip(query_t const& word);
/// @brief Persisted agents
bool persistedAgents();
/// @brief Gossip in /// @brief Gossip in
bool activeAgency(); bool activeAgency();
@ -147,11 +150,22 @@ class Agent : public arangodb::Thread {
/// @brief Get spearhead store /// @brief Get spearhead store
Store const& spearhead() const; Store const& spearhead() const;
bool serveActiveAgent();
/// State reads persisted state and prepares the agent
friend class State; friend class State;
private: private:
Agent& operator=(VPackSlice const&); 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 /// @brief Leader ID
void lastCommitted(arangodb::consensus::index_t); 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, index_t> _lastHighest;
std::map<std::string, TimePoint> _lastSent; std::map<std::string, TimePoint> _lastSent;
arangodb::Mutex _ioLock; /**< @brief Read/Write lock */ 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 /// @brief Server active agents rest handler
bool _serveActiveAgents; bool _serveActiveAgent;
/// @brief Next compaction after /// @brief Next compaction after
arangodb::consensus::index_t _nextCompationAfter; arangodb::consensus::index_t _nextCompationAfter;

View File

@ -211,7 +211,7 @@ struct config_t {
/// @brief merge from persisted configuration /// @brief merge from persisted configuration
void merge (VPackSlice const& conf) { bool merge (VPackSlice const& conf) {
id = conf.get(idStr).copyString(); // I get my id id = conf.get(idStr).copyString(); // I get my id
pool[id] = endpoint; // Register my endpoint with it pool[id] = endpoint; // Register my endpoint with it
@ -349,6 +349,8 @@ struct config_t {
} }
LOG_TOPIC(DEBUG, Logger::AGENCY) << ss.str(); LOG_TOPIC(DEBUG, Logger::AGENCY) << ss.str();
return true;
} }
}; };

View File

@ -43,7 +43,6 @@
#include "Utils/StandaloneTransactionContext.h" #include "Utils/StandaloneTransactionContext.h"
#include "VocBase/collection.h" #include "VocBase/collection.h"
#include "VocBase/vocbase.h" #include "VocBase/vocbase.h"
#include "Agency/NotifierThread.h"
using namespace arangodb::consensus; using namespace arangodb::consensus;
using namespace arangodb::rest; using namespace arangodb::rest;
@ -82,8 +81,8 @@ Constituent::Constituent()
_id(0), _id(0),
_role(FOLLOWER), _role(FOLLOWER),
_agent(nullptr), _agent(nullptr),
_votedFor(NO_LEADER), _votedFor(NO_LEADER)
_notifier(nullptr) {} {}
/// Shutdown if not already /// Shutdown if not already
@ -92,12 +91,6 @@ Constituent::~Constituent() {
} }
/// Configuration
config_t const& Constituent::config() const {
return _agent->config();
}
/// Wait for sync /// Wait for sync
bool Constituent::waitForSync() const { bool Constituent::waitForSync() const {
return _agent->config().waitForSync; return _agent->config().waitForSync;
@ -140,7 +133,7 @@ void Constituent::term(term_t t) {
i_str << std::setw(20) << std::setfill('0') << t; i_str << std::setw(20) << std::setfill('0') << t;
body.add("_key", Value(i_str.str())); body.add("_key", Value(i_str.str()));
body.add("term", Value(t)); body.add("term", Value(t));
body.add("voted_for", Value((uint32_t)_votedFor)); body.add("voted_for", Value(_votedFor));
body.close(); body.close();
TRI_ASSERT(_vocbase != nullptr); TRI_ASSERT(_vocbase != nullptr);
@ -191,7 +184,7 @@ void Constituent::follow(term_t t) {
/// Become leader /// 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); MUTEX_LOCKER(guard, _castLock);
@ -207,7 +200,7 @@ void Constituent::lead(std::vector<bool> const& votes) {
std::stringstream ss; std::stringstream ss;
ss << _id << ": Converted to leader in term " << _term << " with votes ("; ss << _id << ": Converted to leader in term " << _term << " with votes (";
for (auto const& vote : votes) { for (auto const& vote : votes) {
ss << vote; ss << vote.second;
} }
ss << ")"; ss << ")";
@ -260,54 +253,16 @@ arangodb::consensus::id_t Constituent::leaderID() const {
/// Agency size /// Agency size
size_t Constituent::size() const { size_t Constituent::size() const {
return config().size(); return _agent->config().size();
} }
/// Get endpoint to an id /// Get endpoint to an id
std::string const& Constituent::endpoint(arangodb::consensus::id_t id) const { 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 /// @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,
@ -351,49 +306,53 @@ bool Constituent::vote(term_t term, arangodb::consensus::id_t id,
/// @brief Call to election /// @brief Call to election
void Constituent::callElection() { 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; _cast = true;
_votedFor = _id; _votedFor = _id;
_leaderID = NO_LEADER; _leaderID = NO_LEADER;
this->term(_term + 1); // raise my term this->term(_term + 1); // raise my term
std::string body; std::string body;
std::vector<OperationID> operationIDs(config().endpoints.size()); std::map<arangodb::consensus::id_t,OperationID> operationIDs;
std::stringstream path; std::stringstream path;
path << "/_api/agency_priv/requestVote?term=" << _term path << "/_api/agency_priv/requestVote?term=" << _term
<< "&candidateId=" << _id << "&prevLogIndex=" << _agent->lastLog().index << "&candidateId=" << _id
<< "&prevLogIndex=" << _agent->lastLog().index
<< "&prevLogTerm=" << _agent->lastLog().term; << "&prevLogTerm=" << _agent->lastLog().term;
double minPing = _agent->config().minPing;
double respTimeout = 0.9*minPing;
double initTimeout = 0.5*minPing;
// Ask everyone for their vote // Ask everyone for their vote
for (arangodb::consensus::id_t i = 0; i < config().endpoints.size(); ++i) { for (auto const& i : active) {
if (i != _id && endpoint(i) != "") { if (i != _id) {
auto headerFields = auto headerFields =
std::make_unique<std::unordered_map<std::string, std::string>>(); std::make_unique<std::unordered_map<std::string, std::string>>();
operationIDs[i] = arangodb::ClusterComm::instance()->asyncRequest( operationIDs[i] = ClusterComm::instance()->asyncRequest(
"1", 1, config().endpoints[i], GeneralRequest::RequestType::GET, "1", 1, _agent->config().pool.at(i),
path.str(), std::make_shared<std::string>(body), headerFields, GeneralRequest::RequestType::GET, path.str(),
nullptr, 0.75*config().minPing, true, 0.5*config().minPing); std::make_shared<std::string>(body), headerFields,
nullptr, respTimeout, true, initTimeout);
} }
} }
// Wait randomized timeout // Wait randomized timeout
std::this_thread::sleep_for( std::this_thread::sleep_for(sleepFor(initTimeout, respTimeout));
sleepFor(.5 * config().minPing, .8 * config().minPing));
// Collect votes // Collect votes
// FIXME: This code can be improved: One can wait for an arbitrary for (const auto& i : active) {
// result by creating a coordinatorID and waiting for a pattern. if (i != _id) {
for (arangodb::consensus::id_t i = 0; i < config().endpoints.size(); ++i) {
if (i != _id && endpoint(i) != "") {
ClusterCommResult res = ClusterCommResult res =
arangodb::ClusterComm::instance()->enquire(operationIDs[i]); arangodb::ClusterComm::instance()->enquire(operationIDs[i]);
if (res.status == CL_COMM_SENT) { // Request successfully sent if (res.status == CL_COMM_SENT) { // Request successfully sent
res = arangodb::ClusterComm::instance()->wait( res = ClusterComm::instance()->wait("1", 1, operationIDs[i], "1");
"1", 1, operationIDs[i], "1");
std::shared_ptr<Builder> body = res.result->getBodyVelocyPack(); std::shared_ptr<Builder> body = res.result->getBodyVelocyPack();
if (body->isEmpty()) { // body empty if (body->isEmpty()) { // body empty
continue; continue;
@ -406,7 +365,7 @@ void Constituent::callElection() {
follow(t); follow(t);
break; break;
} }
votes[i] = slc.get("voteGranted").getBool(); // Get vote votes[i] = slc.get("voteGranted").getBool(); // Get vote
} }
} }
} }
@ -418,8 +377,8 @@ void Constituent::callElection() {
// Count votes // Count votes
size_t yea = 0; size_t yea = 0;
for (size_t i = 0; i < size(); ++i) { for (auto const& i : votes) {
if (votes[i]) { if (i.second) {
yea++; yea++;
} }
} }
@ -437,7 +396,6 @@ void Constituent::callElection() {
/// Start clean shutdown /// Start clean shutdown
void Constituent::beginShutdown() { void Constituent::beginShutdown() {
_notifier.reset();
Thread::beginShutdown(); Thread::beginShutdown();
CONDITION_LOCKER(guard, _cv); CONDITION_LOCKER(guard, _cv);
@ -482,11 +440,10 @@ void Constituent::run() {
for (auto const& i : VPackArrayIterator(result)) { for (auto const& i : VPackArrayIterator(result)) {
try { try {
_term = i.get("term").getUInt(); _term = i.get("term").getUInt();
_votedFor = _votedFor = i.get("voted_for").copyString();
static_cast<decltype(_votedFor)>(i.get("voted_for").getUInt());
} catch (std::exception const&) { } catch (std::exception const&) {
LOG_TOPIC(ERR, Logger::AGENCY) LOG_TOPIC(ERR, Logger::AGENCY)
<< "Persisted election entries corrupt! Defaulting term,vote (0,0)"; << "Persisted election entries corrupt! Defaulting term,vote (0,0)";
} }
} }
} }
@ -502,7 +459,8 @@ void Constituent::run() {
_cast = false; // New round set not cast vote _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)); long rand_wait = static_cast<long>(RandomGenerator::interval(left, right));
{ {
@ -522,7 +480,7 @@ void Constituent::run() {
} else if (_role == CANDIDATE) { } else if (_role == CANDIDATE) {
callElection(); // Run for office callElection(); // Run for office
} else { } 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); long rand_wait = static_cast<long>(left);
{ {
CONDITION_LOCKER(guardv, _cv); CONDITION_LOCKER(guardv, _cv);

View File

@ -26,7 +26,6 @@
#include "AgencyCommon.h" #include "AgencyCommon.h"
#include "AgentConfiguration.h" #include "AgentConfiguration.h"
#include "NotifierThread.h"
#include "Basics/Common.h" #include "Basics/Common.h"
#include "Basics/Thread.h" #include "Basics/Thread.h"
@ -109,7 +108,7 @@ class Constituent : public arangodb::Thread {
void candidate(); void candidate();
/// @brief Become leader /// @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) /// @brief Call for vote (by leader or candidates after timeout)
void callElection(); void callElection();
@ -120,11 +119,6 @@ class Constituent : public arangodb::Thread {
/// @brief Wait for sync /// @brief Wait for sync
bool waitForSync() const; 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 /// @brief Sleep for how long
duration_t sleepFor(double, double); duration_t sleepFor(double, double);
@ -141,8 +135,6 @@ class Constituent : public arangodb::Thread {
Agent* _agent; /**< @brief My boss */ Agent* _agent; /**< @brief My boss */
arangodb::consensus::id_t _votedFor; arangodb::consensus::id_t _votedFor;
std::unique_ptr<NotifierThread> _notifier;
arangodb::basics::ConditionVariable _cv; // agency callbacks arangodb::basics::ConditionVariable _cv; // agency callbacks
mutable arangodb::Mutex _castLock; mutable arangodb::Mutex _castLock;
}; };

View File

@ -74,7 +74,7 @@ inline RestHandler::status RestAgencyHandler::reportUnknownMethod() {
void RestAgencyHandler::redirectRequest(arangodb::consensus::id_t leaderId) { void RestAgencyHandler::redirectRequest(arangodb::consensus::id_t leaderId) {
try { try {
std::string url = std::string url =
Endpoint::uriForm(_agent->config().pool[leaderId]) + Endpoint::uriForm(_agent->config().pool.at(leaderId)) +
_request->requestPath(); _request->requestPath();
setResponseCode(GeneralResponse::ResponseCode::TEMPORARY_REDIRECT); setResponseCode(GeneralResponse::ResponseCode::TEMPORARY_REDIRECT);
_response->setHeaderNC(StaticStrings::Location, url); _response->setHeaderNC(StaticStrings::Location, url);
@ -140,7 +140,7 @@ RestHandler::status RestAgencyHandler::handleWrite() {
return status::DONE; 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)); std::this_thread::sleep_for(duration_t(100));
} }
@ -215,7 +215,7 @@ inline RestHandler::status RestAgencyHandler::handleRead() {
return status::DONE; return status::DONE;
} }
while(_agent->size() > 1 && _agent->leaderID() > 100) { while(_agent->size() > 1 && _agent->leaderID() == "") {
std::this_thread::sleep_for(duration_t(100)); std::this_thread::sleep_for(duration_t(100));
} }

View File

@ -130,11 +130,11 @@ RestHandler::status RestAgencyPrivHandler::execute() {
return reportBadQuery(); // bad query return reportBadQuery(); // bad query
} }
} else if (_request->suffix()[0] == "gossip") { } else if (_request->suffix()[0] == "gossip") {
if (_agent->activeAgentStartupSequence()) { if (_agent->serveActiveAgent()) { // only during startup (see Agent)
arangodb::velocypack::Options options; arangodb::velocypack::Options options;
query_t query = _request->toVelocyPackBuilderPtr(&options); query_t query = _request->toVelocyPackBuilderPtr(&options);
_agent->gossip(query); _agent->gossip(query);
} else { } else { // Gone!
return reportGone(); return reportGone();
} }
}else { }else {

View File

@ -505,9 +505,9 @@ bool State::loadOrPersistConfiguration() {
if (result.isArray() && result.length()) { // We already have a persisted conf if (result.isArray() && result.length()) { // We already have a persisted conf
try (config.merge(result)) { try {
0; _agent->mergeConfiguration(result);
} catch (std::exception const& e) { } catch (std::exception const& e) {
LOG_TOPIC(ERR, Logger::AGENCY) LOG_TOPIC(ERR, Logger::AGENCY)
<< "Failed to merge persisted configuration into runtime configuration:" << "Failed to merge persisted configuration into runtime configuration:"
<< e.what(); << e.what();
@ -519,7 +519,7 @@ bool State::loadOrPersistConfiguration() {
LOG_TOPIC(DEBUG, Logger::AGENCY) << "New agency!"; LOG_TOPIC(DEBUG, Logger::AGENCY) << "New agency!";
TRI_ASSERT(_agent != nullptr); TRI_ASSERT(_agent != nullptr);
_agent->config().id = to_string(boost::uuids::random_generator()()); _agent->id(to_string(boost::uuids::random_generator()()));
auto transactionContext = auto transactionContext =
std::make_shared<StandaloneTransactionContext>(_vocbase); std::make_shared<StandaloneTransactionContext>(_vocbase);
@ -535,7 +535,7 @@ bool State::loadOrPersistConfiguration() {
try { try {
result = trx.insert( result = trx.insert(
"configuration", _agent.config().toBuilder().slice(), _options); "configuration", _agent->config().toBuilder()->slice(), _options);
} catch (std::exception const& e) { } catch (std::exception const& e) {
LOG_TOPIC(ERR, Logger::AGENCY) LOG_TOPIC(ERR, Logger::AGENCY)
<< "Failed to persist configuration entry:" << e.what(); << "Failed to persist configuration entry:" << e.what();
@ -550,7 +550,6 @@ bool State::loadOrPersistConfiguration() {
return true; return true;
} }