diff --git a/arangod/Agency/Agent.cpp b/arangod/Agency/Agent.cpp index c32da529ce..3feef20487 100644 --- a/arangod/Agency/Agent.cpp +++ b/arangod/Agency/Agent.cpp @@ -1672,14 +1672,11 @@ query_t Agent::gossip(query_t const& in, bool isCallback, size_t version) { LOG_TOPIC(TRACE, Logger::AGENCY) << "Received gossip " << slice.toJson(); - - std::unordered_map incoming; for (auto const& pair : VPackObjectIterator(pslice)) { if (!pair.value.isString()) { THROW_ARANGO_EXCEPTION_MESSAGE( 20004, "Gossip message pool must contain string parameters"); } - incoming[pair.key.copyString()] = pair.value.copyString(); } query_t out = std::make_shared(); @@ -1697,14 +1694,10 @@ query_t Agent::gossip(query_t const& in, bool isCallback, size_t version) { } } - for (auto const& i : incoming) { - - /// disagreement over pool membership: fatal! - if (!_config.addToPool(i)) { - LOG_TOPIC(FATAL, Logger::AGENCY) << "Discrepancy in agent pool!"; - FATAL_ERROR_EXIT(); - } - + /// disagreement over pool membership: fatal! + if (!_config.upsertPool(pslice, id)) { + LOG_TOPIC(FATAL, Logger::AGENCY) << "Discrepancy in agent pool!"; + FATAL_ERROR_EXIT(); } if (!isCallback) { // no gain in callback to a callback. diff --git a/arangod/Agency/AgentConfiguration.cpp b/arangod/Agency/AgentConfiguration.cpp index dd9fb186d5..c8d151a7e0 100644 --- a/arangod/Agency/AgentConfiguration.cpp +++ b/arangod/Agency/AgentConfiguration.cpp @@ -265,16 +265,25 @@ void config_t::eraseFromGossipPeers(std::string const& endpoint) { } } -bool config_t::addToPool(std::pair const& i) { +bool config_t::upsertPool( + VPackSlice const& otherPool, std::string const& otherId) { WRITE_LOCKER(readLocker, _lock); - if (_pool.find(i.first) == _pool.end()) { - LOG_TOPIC(INFO, Logger::AGENCY) - << "Adding " << i.first << "(" << i.second << ") to agent pool"; - _pool[i.first] = i.second; - ++_version; - } else { - if (_pool.at(i.first) != i.second) { /// discrepancy! - return false; + for (auto const& entry : VPackObjectIterator(otherPool)) { + auto const id = entry.key.copyString(); + auto const endpoint = entry.value.copyString(); + if (_pool.find(id) == _pool.end()) { + LOG_TOPIC(INFO, Logger::AGENCY) + << "Adding " << id << "(" << endpoint << ") to agent pool"; + _pool[id] = endpoint; + ++_version; + } else { + if (_pool.at(id) != endpoint) { + if (id != otherId) { /// discrepancy! + return false; + } else { /// we trust the other guy on his own endpoint + _pool.at(id) = endpoint; + } + } } } return true; diff --git a/arangod/Agency/AgentConfiguration.h b/arangod/Agency/AgentConfiguration.h index 510605d1de..63e9683ee2 100644 --- a/arangod/Agency/AgentConfiguration.h +++ b/arangod/Agency/AgentConfiguration.h @@ -127,8 +127,20 @@ struct config_t { /// @brief wait for sync requested bool waitForSync() const; - /// @brief add pool member - bool addToPool(std::pair const& i); + /** + * @brief Verify other agent's pool against our own: + * - We only get here, if our pool is not complete yet or the + * id is member of this agency + * - We match their pool to ours and allow only for an update + * of it's own endpoint + * + * @param otherPool Other agent's pool + * @param otherId Other agent's id + * + * @return Success + */ + bool upsertPool( + VPackSlice const& otherPool, std::string const& otherId); /// @brief active agency size void activate();