From 4759b2a434db4cb0e5786c5d8e377e73a8c99fb9 Mon Sep 17 00:00:00 2001 From: Kaveh Vahedipour Date: Thu, 11 Aug 2016 12:05:53 +0200 Subject: [PATCH] Agency compiling again --- arangod/Agency/AgencyFeature.cpp | 6 +- arangod/Agency/AgencyFeature.h | 3 +- arangod/Agency/Agent.cpp | 112 +++++++++++++----- arangod/Agency/Agent.h | 22 +++- arangod/Agency/AgentConfiguration.h | 4 +- arangod/Agency/Constituent.cpp | 138 ++++++++--------------- arangod/Agency/Constituent.h | 10 +- arangod/Agency/RestAgencyHandler.cpp | 6 +- arangod/Agency/RestAgencyPrivHandler.cpp | 4 +- arangod/Agency/State.cpp | 11 +- 10 files changed, 167 insertions(+), 149 deletions(-) diff --git a/arangod/Agency/AgencyFeature.cpp b/arangod/Agency/AgencyFeature.cpp index c84caf632d..d318f832c7 100644 --- a/arangod/Agency/AgencyFeature.cpp +++ b/arangod/Agency/AgencyFeature.cpp @@ -70,7 +70,7 @@ void AgencyFeature::collectOptions(std::shared_ptr 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 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))); diff --git a/arangod/Agency/AgencyFeature.h b/arangod/Agency/AgencyFeature.h index 5138455c82..7c3d2fdcec 100644 --- a/arangod/Agency/AgencyFeature.h +++ b/arangod/Agency/AgencyFeature.h @@ -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 _agencyEndpoints; // agency adresses bool _notify; // interval between retry to slaves bool _supervision; bool _waitForSync; double _supervisionFrequency; uint64_t _compactionStepSize; + std::vector _agencyEndpoints; public: consensus::Agent* agent() const { return _agent.get(); } diff --git a/arangod/Agency/Agent.cpp b/arangod/Agency/Agent.cpp index d862eb04f2..43c70f9516 100644 --- a/arangod/Agency/Agent.cpp +++ b/arangod/Agency/Agent.cpp @@ -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(builder.toJson()), headerFields, std::make_shared(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 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(word->toString()), headerFields, std::make_shared(), 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 pool; + std::vector 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 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(); + } } diff --git a/arangod/Agency/Agent.h b/arangod/Agency/Agent.h index d8c14ba049..4e7d497944 100644 --- a/arangod/Agency/Agent.h +++ b/arangod/Agency/Agent.h @@ -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 _lastHighest; std::map _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; diff --git a/arangod/Agency/AgentConfiguration.h b/arangod/Agency/AgentConfiguration.h index d26c189370..df3b9f7441 100644 --- a/arangod/Agency/AgentConfiguration.h +++ b/arangod/Agency/AgentConfiguration.h @@ -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; + } }; diff --git a/arangod/Agency/Constituent.cpp b/arangod/Agency/Constituent.cpp index fb83650f75..a98c3f2209 100644 --- a/arangod/Agency/Constituent.cpp +++ b/arangod/Agency/Constituent.cpp @@ -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 const& votes) { +void Constituent::lead(std::map const& votes) { { MUTEX_LOCKER(guard, _castLock); @@ -207,7 +200,7 @@ void Constituent::lead(std::vector 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 const& Constituent::endpoints() const { - return config().endpoints; -} - -/// Notify peers of updated endpoints -void Constituent::notifyAll() { - - // Send request to all but myself - std::vector 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(); - 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(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 votes(size(), false); + std::map votes; + std::vector 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 operationIDs(config().endpoints.size()); + std::map 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>(); - operationIDs[i] = arangodb::ClusterComm::instance()->asyncRequest( - "1", 1, config().endpoints[i], GeneralRequest::RequestType::GET, - path.str(), std::make_shared(body), headerFields, - nullptr, 0.75*config().minPing, true, 0.5*config().minPing); + std::make_unique>(); + operationIDs[i] = ClusterComm::instance()->asyncRequest( + "1", 1, _agent->config().pool.at(i), + GeneralRequest::RequestType::GET, path.str(), + std::make_shared(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 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(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(1000000.0 * config().minPing), right = static_cast(1000000.0 * config().maxPing); + + int32_t left = static_cast(1000000.0 * _agent->config().minPing), + right = static_cast(1000000.0 * _agent->config().maxPing); long rand_wait = static_cast(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(100000.0 * config().minPing); + int32_t left = static_cast(100000.0 * _agent->config().minPing); long rand_wait = static_cast(left); { CONDITION_LOCKER(guardv, _cv); diff --git a/arangod/Agency/Constituent.h b/arangod/Agency/Constituent.h index 6e8e762583..da6c72ff5e 100644 --- a/arangod/Agency/Constituent.h +++ b/arangod/Agency/Constituent.h @@ -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 const&); + void lead(std::map 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 _notifier; - arangodb::basics::ConditionVariable _cv; // agency callbacks mutable arangodb::Mutex _castLock; }; diff --git a/arangod/Agency/RestAgencyHandler.cpp b/arangod/Agency/RestAgencyHandler.cpp index 57bf751f9a..63bc9914a3 100644 --- a/arangod/Agency/RestAgencyHandler.cpp +++ b/arangod/Agency/RestAgencyHandler.cpp @@ -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)); } diff --git a/arangod/Agency/RestAgencyPrivHandler.cpp b/arangod/Agency/RestAgencyPrivHandler.cpp index 97f623e99d..752e75dfef 100644 --- a/arangod/Agency/RestAgencyPrivHandler.cpp +++ b/arangod/Agency/RestAgencyPrivHandler.cpp @@ -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 { diff --git a/arangod/Agency/State.cpp b/arangod/Agency/State.cpp index 52472186a8..3d11d74ba2 100644 --- a/arangod/Agency/State.cpp +++ b/arangod/Agency/State.cpp @@ -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(_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; - }