mirror of https://gitee.com/bigwinds/arangodb
Sort out FollowerInfo.
This commit is contained in:
parent
5375ada8a7
commit
dcf4ed8bca
|
@ -2523,72 +2523,34 @@ std::vector<ServerID> ClusterInfo::getCurrentCoordinators() {
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief get information about current followers of a shard, the first
|
/// @brief get information about current followers of a shard.
|
||||||
/// overloaded method is supposed to be very fast, whereas the second
|
|
||||||
/// needs a hash lookup, on the other hand one only needs the shardID.
|
|
||||||
/// Returns an empty shared_ptr if the follower information of the
|
|
||||||
/// shard has been dropped (see `dropFollowerInfo` below).
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ClusterInfo::FollowerInfo ClusterInfo::getFollowerInfo(TRI_collection_t& coll) {
|
std::shared_ptr<std::vector<ServerID> const> FollowerInfo::get() {
|
||||||
std::lock_guard<std::mutex> lock(_followerInfoMutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
if (coll._followerInfoIndex >= 0) {
|
return _followers;
|
||||||
return _followerInfos[static_cast<size_t>(coll._followerInfoIndex)];
|
|
||||||
}
|
|
||||||
ServerID c = coll._info.name();
|
|
||||||
auto it = _followerInfoTable.find(c);
|
|
||||||
if (it != _followerInfoTable.end()) {
|
|
||||||
coll._followerInfoIndex = it->second;
|
|
||||||
return _followerInfos[static_cast<size_t>(it->second)];
|
|
||||||
}
|
|
||||||
return newFollowerInfo(c, coll._followerInfoIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
ClusterInfo::FollowerInfo ClusterInfo::getFollowerInfo(ShardID& c) {
|
|
||||||
std::lock_guard<std::mutex> lock(_followerInfoMutex);
|
|
||||||
auto it = _followerInfoTable.find(c);
|
|
||||||
if (it != _followerInfoTable.end()) {
|
|
||||||
return _followerInfos[static_cast<size_t>(it->second)];
|
|
||||||
}
|
|
||||||
int64_t tmp = -1;
|
|
||||||
return newFollowerInfo(c, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
ClusterInfo::FollowerInfo ClusterInfo::newFollowerInfo(ShardID& c,
|
|
||||||
int64_t& index) {
|
|
||||||
// Mutex must already be locked, which is done in the getFollowerInfo methods
|
|
||||||
auto v = std::make_shared<std::vector<ServerID> const>();
|
|
||||||
_followerInfos.push_back(v);
|
|
||||||
try {
|
|
||||||
index = static_cast<int64_t>(_followerInfos.size() - 1);
|
|
||||||
_followerInfoTable.emplace(make_pair(c, index));
|
|
||||||
return v;
|
|
||||||
} catch (...) {
|
|
||||||
_followerInfos.pop_back(); // make data structure consistent again
|
|
||||||
index = -1;
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
return _followerInfos[static_cast<size_t>(index)];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief add a follower to a shard, this is only done by the server side
|
/// @brief add a follower to a shard, this is only done by the server side
|
||||||
/// of the "get-in-sync" capabilities. This reports to the agency under
|
/// of the "get-in-sync" capabilities. This reports to the agency under
|
||||||
/// `/Current` but in asynchronous "fire-and-forget" way. The method
|
/// `/Current` but in asynchronous "fire-and-forget" way.
|
||||||
/// fails silently, if the follower information has since been dropped
|
|
||||||
/// (see `dropFollowerInfo` below).
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void ClusterInfo::addFollower(ShardID& c, ServerID const& s) {
|
void FollowerInfo::add(ServerID const& s) {
|
||||||
std::lock_guard<std::mutex> lock(_followerInfoMutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
auto it = _followerInfoTable.find(c);
|
// Fully copy the vector:
|
||||||
TRI_ASSERT(it != _followerInfoTable.end());
|
auto v = std::make_shared<std::vector<ServerID>>(*_followers);
|
||||||
size_t pos = static_cast<size_t>(it->second);
|
v->push_back(s); // add a single entry
|
||||||
auto v = std::make_shared<std::vector<ServerID>>(*_followerInfos[pos]);
|
_followers = v; // will cast to std::vector<ServerID> const
|
||||||
v->push_back(s);
|
|
||||||
_followerInfos[pos] = v; // will cast to std::vector<ServerID> const
|
|
||||||
// Now tell the agency:
|
// Now tell the agency:
|
||||||
// ...
|
// Path is
|
||||||
|
// Current/Collections/<dbName>/<collectionID>/<shardID>
|
||||||
|
// do {
|
||||||
|
// Get value,
|
||||||
|
// add follower
|
||||||
|
// Casvalue
|
||||||
|
// } until geklappt
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -2599,36 +2561,23 @@ void ClusterInfo::addFollower(ShardID& c, ServerID const& s) {
|
||||||
/// since been dropped (see `dropFollowerInfo` below).
|
/// since been dropped (see `dropFollowerInfo` below).
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void ClusterInfo::removeFollower(ShardID& c, ServerID const& s) {
|
void FollowerInfo::remove(ServerID const& s) {
|
||||||
std::lock_guard<std::mutex> lock(_followerInfoMutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
auto it = _followerInfoTable.find(c);
|
|
||||||
TRI_ASSERT(it != _followerInfoTable.end());
|
|
||||||
size_t pos = static_cast<size_t>(it->second);
|
|
||||||
auto v = std::make_shared<std::vector<ServerID>>();
|
auto v = std::make_shared<std::vector<ServerID>>();
|
||||||
v->reserve(_followerInfos[pos]->size() - 1);
|
v->reserve(_followers->size() - 1);
|
||||||
for (auto const& i : *_followerInfos[pos]) {
|
for (auto const& i : *_followers) {
|
||||||
if (i != s) {
|
if (i != s) {
|
||||||
v->push_back(i);
|
v->push_back(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_followerInfos[pos] = v; // will cast to std::vector<ServerID> const
|
_followers = v; // will cast to std::vector<ServerID> const
|
||||||
// Now tell the agency:
|
// Now tell the agency:
|
||||||
// ...
|
// Path is
|
||||||
|
// Current/Collections/<dbName>/<collectionID>/<shardID>
|
||||||
|
// do {
|
||||||
|
// Get value,
|
||||||
|
// remove follower
|
||||||
|
// Casvalue
|
||||||
|
// } until geklappt
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief drop information about current followers of a shard,
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void ClusterInfo::dropFollowerInfo(ShardID& c) {
|
|
||||||
std::lock_guard<std::mutex> lock(_followerInfoMutex);
|
|
||||||
auto it = _followerInfoTable.find(c);
|
|
||||||
if (it == _followerInfoTable.end()) {
|
|
||||||
LOG_ERROR("Did not find expected followerInfo for shard %s.", c.c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_followerInfos[static_cast<size_t>(it->second)].reset();
|
|
||||||
_followerInfoTable.erase(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -527,7 +527,6 @@ class ClusterInfo {
|
||||||
DatabaseCollectionsCurrent;
|
DatabaseCollectionsCurrent;
|
||||||
typedef std::unordered_map<DatabaseID, DatabaseCollectionsCurrent>
|
typedef std::unordered_map<DatabaseID, DatabaseCollectionsCurrent>
|
||||||
AllCollectionsCurrent;
|
AllCollectionsCurrent;
|
||||||
typedef std::shared_ptr<std::vector<ServerID> const> FollowerInfo;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -851,49 +850,9 @@ class ClusterInfo {
|
||||||
double getReloadServerListTimeout() const { return 60.0; }
|
double getReloadServerListTimeout() const { return 60.0; }
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief get information about current followers of a shard, the first
|
/// @brief object for agency communication
|
||||||
/// overloaded method is supposed to be very fast, whereas the second
|
|
||||||
/// needs a hash lookup, on the other hand one only needs the shardID.
|
|
||||||
/// Returns an empty shared_ptr if the follower information of the
|
|
||||||
/// shard has been dropped (see `dropFollowerInfo` below).
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
FollowerInfo getFollowerInfo(TRI_collection_t& coll);
|
|
||||||
FollowerInfo getFollowerInfo(ShardID& c);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief add a follower to a shard, this is only done by the server side
|
|
||||||
/// of the "get-in-sync" capabilities. This reports to the agency under
|
|
||||||
/// `/Current` but in asynchronous "fire-and-forget" way. The method
|
|
||||||
/// fails silently, if the follower information has since been dropped
|
|
||||||
/// (see `dropFollowerInfo` below).
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void addFollower(ShardID& c, ServerID const& s);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief remove a follower from a shard, this is only done by the
|
|
||||||
/// server if a synchronous replication request fails. This reports to
|
|
||||||
/// the agency under `/Current` but in asynchronous "fire-and-forget"
|
|
||||||
/// way. The method fails silently, if the follower information has
|
|
||||||
/// since been dropped (see `dropFollowerInfo` below).
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void removeFollower(ShardID& c, ServerID const& s);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief drop information about current followers of a shard
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void dropFollowerInfo(ShardID& c);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief internal method to add a follower info entry
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
FollowerInfo newFollowerInfo(ShardID& c, int64_t& index);
|
|
||||||
|
|
||||||
private:
|
|
||||||
AgencyComm _agency;
|
AgencyComm _agency;
|
||||||
|
|
||||||
// Cached data from the agency, we reload whenever necessary:
|
// Cached data from the agency, we reload whenever necessary:
|
||||||
|
@ -971,13 +930,6 @@ class ClusterInfo {
|
||||||
std::unordered_map<ShardID, std::shared_ptr<std::vector<ServerID>>>
|
std::unordered_map<ShardID, std::shared_ptr<std::vector<ServerID>>>
|
||||||
_shardIds; // from Current/Collections/
|
_shardIds; // from Current/Collections/
|
||||||
|
|
||||||
// The following is a special case, it is the current information
|
|
||||||
// about synchronous followers for each shard, for which we are
|
|
||||||
// responsible as a leader.
|
|
||||||
std::vector<FollowerInfo> _followerInfos;
|
|
||||||
std::unordered_map<ShardID, int64_t> _followerInfoTable;
|
|
||||||
std::mutex _followerInfoMutex;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief uniqid sequence
|
/// @brief uniqid sequence
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1018,6 +970,48 @@ class ClusterInfo {
|
||||||
static double const reloadServerListTimeout;
|
static double const reloadServerListTimeout;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief a class to track followers that are in sync for a shard
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class FollowerInfo {
|
||||||
|
std::shared_ptr<std::vector<ServerID> const> _followers;
|
||||||
|
std::mutex _mutex;
|
||||||
|
TRI_document_collection_t* _docColl;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FollowerInfo(TRI_document_collection_t* d) : _docColl(d) {
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief get information about current followers of a shard.
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::shared_ptr<std::vector<ServerID> const> get();
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief add a follower to a shard, this is only done by the server side
|
||||||
|
/// of the "get-in-sync" capabilities. This reports to the agency under
|
||||||
|
/// `/Current` but in asynchronous "fire-and-forget" way. The method
|
||||||
|
/// fails silently, if the follower information has since been dropped
|
||||||
|
/// (see `dropFollowerInfo` below).
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void add(ServerID const& s);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief remove a follower from a shard, this is only done by the
|
||||||
|
/// server if a synchronous replication request fails. This reports to
|
||||||
|
/// the agency under `/Current` but in asynchronous "fire-and-forget"
|
||||||
|
/// way. The method fails silently, if the follower information has
|
||||||
|
/// since been dropped (see `dropFollowerInfo` below).
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void remove(ServerID const& s);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
} // end namespace arangodb
|
} // end namespace arangodb
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -300,6 +300,14 @@ static void JS_SynchronizeReplication(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool forSynchronousReplication = false;
|
||||||
|
if (object->Has(TRI_V8_ASCII_STRING("forSynchronousReplication"))) {
|
||||||
|
if (object->Get(TRI_V8_ASCII_STRING("forSynchronousReplication"))->IsBoolean()) {
|
||||||
|
forSynchronousReplication =
|
||||||
|
TRI_ObjectToBoolean(object->Get(TRI_V8_ASCII_STRING("forSynchronousReplication")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string errorMsg = "";
|
std::string errorMsg = "";
|
||||||
InitialSyncer syncer(vocbase, &config, restrictCollections, restrictType,
|
InitialSyncer syncer(vocbase, &config, restrictCollections, restrictType,
|
||||||
verbose);
|
verbose);
|
||||||
|
@ -341,6 +349,9 @@ static void JS_SynchronizeReplication(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now check forSynchronousReplication flag and tell ClusterInfo
|
||||||
|
// about a new follower.
|
||||||
|
|
||||||
TRI_V8_RETURN(result);
|
TRI_V8_RETURN(result);
|
||||||
TRI_V8_TRY_CATCH_END
|
TRI_V8_TRY_CATCH_END
|
||||||
}
|
}
|
||||||
|
|
|
@ -1891,4 +1891,3 @@ bool TRI_IsAllowedNameCollection(bool allowSystem, char const* name) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -333,10 +333,7 @@ struct TRI_collection_t {
|
||||||
TRI_vector_pointer_t _compactors; // all compactor files
|
TRI_vector_pointer_t _compactors; // all compactor files
|
||||||
TRI_vector_string_t _indexFiles; // all index filenames
|
TRI_vector_string_t _indexFiles; // all index filenames
|
||||||
|
|
||||||
int64_t _followerInfoIndex; // short-cut to find
|
TRI_collection_t() {}
|
||||||
// FollowerInfo in
|
|
||||||
// ClusterInfo quickly
|
|
||||||
TRI_collection_t() : _followerInfoIndex(-1) {}
|
|
||||||
|
|
||||||
explicit TRI_collection_t(arangodb::VocbaseCollectionInfo const& info)
|
explicit TRI_collection_t(arangodb::VocbaseCollectionInfo const& info)
|
||||||
: _info(info) {}
|
: _info(info) {}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "Basics/logging.h"
|
#include "Basics/logging.h"
|
||||||
#include "Basics/tri-strings.h"
|
#include "Basics/tri-strings.h"
|
||||||
#include "Basics/ThreadPool.h"
|
#include "Basics/ThreadPool.h"
|
||||||
|
#include "Cluster/ServerState.h"
|
||||||
#include "FulltextIndex/fulltext-index.h"
|
#include "FulltextIndex/fulltext-index.h"
|
||||||
#include "Indexes/CapConstraint.h"
|
#include "Indexes/CapConstraint.h"
|
||||||
#include "Indexes/EdgeIndex.h"
|
#include "Indexes/EdgeIndex.h"
|
||||||
|
@ -84,6 +85,9 @@ TRI_document_collection_t::TRI_document_collection_t()
|
||||||
_tickMax = 0;
|
_tickMax = 0;
|
||||||
|
|
||||||
setCompactionStatus("compaction not yet started");
|
setCompactionStatus("compaction not yet started");
|
||||||
|
if (ServerState::instance()->isDBServer()) {
|
||||||
|
_followers.reset(new FollowerInfo(this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "VocBase/update-policy.h"
|
#include "VocBase/update-policy.h"
|
||||||
#include "VocBase/voc-types.h"
|
#include "VocBase/voc-types.h"
|
||||||
#include "Wal/Marker.h"
|
#include "Wal/Marker.h"
|
||||||
|
#include "Cluster/ClusterInfo.h"
|
||||||
|
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
|
|
||||||
|
@ -256,6 +257,11 @@ struct TRI_document_collection_t : public TRI_collection_t {
|
||||||
// whether or not secondary indexes are filled
|
// whether or not secondary indexes are filled
|
||||||
bool _useSecondaryIndexes;
|
bool _useSecondaryIndexes;
|
||||||
|
|
||||||
|
// the following contains in the cluster/DBserver case the information
|
||||||
|
// which other servers are in sync with this shard. It is unset in all
|
||||||
|
// other cases.
|
||||||
|
std::unique_ptr<arangodb::FollowerInfo> _followers;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
arangodb::DatafileStatistics _datafileStatistics;
|
arangodb::DatafileStatistics _datafileStatistics;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue