1
0
Fork 0

issue 374.3: use a reference to vocbase instead of a pointer in DatabaseGuard

This commit is contained in:
Vasiliy 2018-04-13 09:56:49 +03:00
parent d3626dd5c8
commit f392925903
30 changed files with 383 additions and 230 deletions

View File

@ -45,10 +45,14 @@
using namespace arangodb;
using namespace arangodb::aql;
QueryResultCursor::QueryResultCursor(TRI_vocbase_t* vocbase, CursorId id,
aql::QueryResult&& result,
size_t batchSize, double ttl,
bool hasCount)
QueryResultCursor::QueryResultCursor(
TRI_vocbase_t& vocbase,
CursorId id,
aql::QueryResult&& result,
size_t batchSize,
double ttl,
bool hasCount
)
: Cursor(id, batchSize, ttl, hasCount),
_guard(vocbase),
_result(std::move(result)),
@ -140,23 +144,33 @@ Result QueryResultCursor::dump(VPackBuilder& builder) {
return TRI_ERROR_NO_ERROR;
}
QueryStreamCursor::QueryStreamCursor(TRI_vocbase_t* vocbase, CursorId id,
std::string const& query,
std::shared_ptr<VPackBuilder> bindVars,
std::shared_ptr<VPackBuilder> opts,
size_t batchSize, double ttl)
QueryStreamCursor::QueryStreamCursor(
TRI_vocbase_t& vocbase,
CursorId id,
std::string const& query,
std::shared_ptr<VPackBuilder> bindVars,
std::shared_ptr<VPackBuilder> opts,
size_t batchSize,
double ttl
)
: Cursor(id, batchSize, ttl, /*hasCount*/ false),
_guard(vocbase),
_queryString(query) {
TRI_ASSERT(QueryRegistryFeature::QUERY_REGISTRY != nullptr);
auto prevLockHeaders = CollectionLockState::_noLockHeaders;
TRI_DEFER(CollectionLockState::_noLockHeaders = prevLockHeaders);
_query = std::make_unique<Query>(false, _guard.database(),
aql::QueryString(_queryString.c_str(), _queryString.length()),
std::move(bindVars), std::move(opts), arangodb::aql::PART_MAIN);
_query = std::make_unique<Query>(
false,
&(_guard.database()),
aql::QueryString(_queryString.c_str(), _queryString.length()),
std::move(bindVars),
std::move(opts),
arangodb::aql::PART_MAIN
);
_query->prepare(QueryRegistryFeature::QUERY_REGISTRY, aql::Query::DontCache);
TRI_ASSERT(_query->state() == aql::QueryExecutionState::ValueType::EXECUTION);
// If we have set _noLockHeaders, we need to unset it:
if (CollectionLockState::_noLockHeaders != nullptr &&
CollectionLockState::_noLockHeaders == _query->engine()->lockedShards()) {
@ -184,8 +198,9 @@ Result QueryStreamCursor::dump(VPackBuilder& builder) {
TRI_DEFER(CollectionLockState::_noLockHeaders = prevLockHeaders);
// we do have a query string... pass query to WorkMonitor
AqlWorkStack work(_guard.database(), _query->id(), _queryString.data(),
_queryString.size());
AqlWorkStack work(
&(_guard.database()), _query->id(), _queryString.data(), _queryString.size()
);
LOG_TOPIC(TRACE, Logger::QUERIES) << "executing query " << _id << ": '"
<< _queryString.substr(1024) << "'";

View File

@ -39,12 +39,17 @@ class Query;
/// Should be used in conjunction with the RestCursorHandler
class QueryResultCursor final : public arangodb::Cursor {
public:
QueryResultCursor(TRI_vocbase_t*, CursorId, aql::QueryResult&&, size_t,
double ttl, bool hasCount);
QueryResultCursor(
TRI_vocbase_t& vocbase,
CursorId id,
aql::QueryResult&& result,
size_t batchSize,
double ttl,
bool hasCount
);
~QueryResultCursor() = default;
public:
aql::QueryResult const* result() const { return &_result; }
CursorType type() const override final { return CURSOR_VPACK; }
@ -79,14 +84,18 @@ class QueryResultCursor final : public arangodb::Cursor {
/// cursor is deleted (or query exhausted)
class QueryStreamCursor final : public arangodb::Cursor {
public:
QueryStreamCursor(TRI_vocbase_t*, CursorId, std::string const& query,
std::shared_ptr<velocypack::Builder> bindVars,
std::shared_ptr<velocypack::Builder> opts, size_t,
double ttl);
QueryStreamCursor(
TRI_vocbase_t& vocbase,
CursorId id,
std::string const& query,
std::shared_ptr<velocypack::Builder> bindVars,
std::shared_ptr<velocypack::Builder> opts,
size_t batchSize,
double ttl
);
~QueryStreamCursor();
public:
CursorType type() const override final { return CURSOR_VPACK; }
size_t count() const override final { return 0; }
@ -104,4 +113,4 @@ class QueryStreamCursor final : public arangodb::Cursor {
} // aql
} // arangodb
#endif
#endif

View File

@ -58,10 +58,9 @@ DBServerAgencySyncResult DBServerAgencySync::execute() {
LOG_TOPIC(DEBUG, Logger::HEARTBEAT) << "DBServerAgencySync::execute starting";
DatabaseFeature* database =
ApplicationServer::getFeature<DatabaseFeature>("Database");
TRI_vocbase_t* const vocbase = database->systemDatabase();
DBServerAgencySyncResult result;
if (vocbase == nullptr) {
LOG_TOPIC(DEBUG, Logger::HEARTBEAT)
<< "DBServerAgencySync::execute no vocbase";
@ -71,9 +70,7 @@ DBServerAgencySyncResult DBServerAgencySync::execute() {
auto clusterInfo = ClusterInfo::instance();
auto plan = clusterInfo->getPlan();
auto current = clusterInfo->getCurrent();
DatabaseGuard guard(vocbase);
DatabaseGuard guard(*vocbase);
double startTime = TRI_microtime();
V8Context* context = V8DealerFeature::DEALER->enterContext(vocbase, true, V8DealerFeature::ANY_CONTEXT_OR_PRIORITY);
@ -81,16 +78,17 @@ DBServerAgencySyncResult DBServerAgencySync::execute() {
LOG_TOPIC(WARN, arangodb::Logger::HEARTBEAT) << "DBServerAgencySync::execute: no V8 context";
return result;
}
TRI_DEFER(V8DealerFeature::DEALER->exitContext(context));
double now = TRI_microtime();
if (now - startTime > 5.0) {
LOG_TOPIC(WARN, arangodb::Logger::HEARTBEAT) << "DBServerAgencySync::execute took " << Logger::FIXED(now - startTime) << " to get free V8 context, starting handlePlanChange now";
}
auto isolate = context->_isolate;
try {
v8::HandleScope scope(isolate);

View File

@ -597,11 +597,9 @@ void MMFilesCollectorThread::clearQueuedOperations() {
for (auto const& cache : operations) {
{
arangodb::DatabaseGuard dbGuard(cache->databaseId);
TRI_vocbase_t* vocbase = dbGuard.database();
TRI_ASSERT(vocbase != nullptr);
arangodb::CollectionGuard collectionGuard(vocbase, cache->collectionId,
true);
arangodb::CollectionGuard collectionGuard(
&(dbGuard.database()), cache->collectionId, true
);
arangodb::LogicalCollection* collection = collectionGuard.collection();
TRI_ASSERT(collection != nullptr);
@ -732,10 +730,10 @@ void MMFilesCollectorThread::processCollectionMarker(
/// @brief process all operations for a single collection
int MMFilesCollectorThread::processCollectionOperations(MMFilesCollectorCache* cache) {
arangodb::DatabaseGuard dbGuard(cache->databaseId);
TRI_vocbase_t* vocbase = dbGuard.database();
TRI_ASSERT(vocbase != nullptr);
arangodb::CollectionGuard collectionGuard(vocbase, cache->collectionId, true);
auto& vocbase = dbGuard.database();
arangodb::CollectionGuard collectionGuard(
&vocbase, cache->collectionId, true
);
arangodb::LogicalCollection* collection = collectionGuard.collection();
TRI_ASSERT(collection != nullptr);
@ -983,10 +981,9 @@ int MMFilesCollectorThread::transferMarkers(MMFilesWalLogfile* logfile,
// prepare database and collection
arangodb::DatabaseGuard dbGuard(databaseId);
TRI_vocbase_t* vocbase = dbGuard.database();
TRI_ASSERT(vocbase != nullptr);
arangodb::CollectionGuard collectionGuard(vocbase, collectionId, true);
arangodb::CollectionGuard collectionGuard(
&(dbGuard.database()), collectionId, true
);
arangodb::LogicalCollection* collection = collectionGuard.collection();
TRI_ASSERT(collection != nullptr);
@ -1006,13 +1003,14 @@ int MMFilesCollectorThread::transferMarkers(MMFilesWalLogfile* logfile,
int res = TRI_ERROR_INTERNAL;
uint64_t numBytesTransferred = 0;
try {
auto en = static_cast<MMFilesEngine*>(engine);
res = en->transferMarkers(collection, cache.get(), operations, numBytesTransferred);
LOG_TOPIC(TRACE, Logger::COLLECTOR) << "wal collector transferred markers for '"
<< collection->name() << ", number of bytes transferred: " << numBytesTransferred;
if (res == TRI_ERROR_NO_ERROR && !cache->operations->empty()) {
queueOperations(logfile, cache);
}

View File

@ -32,7 +32,7 @@
#include <velocypack/Options.h>
#include <velocypack/velocypack-aliases.h>
using namespace arangodb;
namespace arangodb {
MMFilesExportCursor::MMFilesExportCursor(TRI_vocbase_t* vocbase, CursorId id,
arangodb::MMFilesCollectionExport* ex, size_t batchSize,
@ -73,7 +73,7 @@ VPackSlice MMFilesExportCursor::next() {
size_t MMFilesExportCursor::count() const { return _size; }
Result MMFilesExportCursor::dump(VPackBuilder& builder) {
auto ctx = transaction::StandaloneContext::Create(_guard.database());
auto ctx = transaction::StandaloneContext::Create(&(_guard.database()));
VPackOptions const* oldOptions = builder.options;
builder.options = ctx->getVPackOptions();
@ -144,5 +144,7 @@ Result MMFilesExportCursor::dump(VPackBuilder& builder) {
}
std::shared_ptr<transaction::Context> MMFilesExportCursor::context() const {
return transaction::StandaloneContext::Create(_guard.database()); // likely not used
return transaction::StandaloneContext::Create(&(_guard.database())); // likely not used
}
} // arangodb

View File

@ -51,10 +51,14 @@ using namespace arangodb::basics;
const char* arangodb::pregel::ExecutionStateNames[6] = {
"none", "running", "done", "canceled", "in error", "recovering"};
Conductor::Conductor(uint64_t executionNumber, TRI_vocbase_t* vocbase,
std::vector<CollectionID> const& vertexCollections,
std::vector<CollectionID> const& edgeCollections,
std::string const& algoName, VPackSlice const& config)
Conductor::Conductor(
uint64_t executionNumber,
TRI_vocbase_t& vocbase,
std::vector<CollectionID> const& vertexCollections,
std::vector<CollectionID> const& edgeCollections,
std::string const& algoName,
VPackSlice const& config
)
: _vocbaseGuard(vocbase),
_executionNumber(executionNumber),
_algorithm(AlgoRegistry::createAlgorithm(algoName, config)),
@ -243,12 +247,15 @@ void Conductor::finishedWorkerStartup(VPackSlice const& data) {
}
_computationStartTimeSecs = TRI_microtime();
if (_startGlobalStep()) {
// listens for changing primary DBServers on each collection shard
RecoveryManager* mngr = PregelFeature::instance()->recoveryManager();
if (mngr) {
mngr->monitorCollections(_vocbaseGuard.database()->name(),
_vertexCollections, this);
mngr->monitorCollections(
_vocbaseGuard.database().name(), _vertexCollections, this
);
}
}
}
@ -523,7 +530,7 @@ int Conductor::_initializeWorkers(std::string const& suffix,
_callbackMutex.assertLockedByCurrentThread();
std::string const path =
Utils::baseUrl(_vocbaseGuard.database()->name(), Utils::workerPrefix) +
Utils::baseUrl(_vocbaseGuard.database().name(), Utils::workerPrefix) +
suffix;
// int64_t vertexCount = 0, edgeCount = 0;
@ -534,12 +541,22 @@ int Conductor::_initializeWorkers(std::string const& suffix,
// resolve plan id's and shards on the servers
for (CollectionID const& collectionID : _vertexCollections) {
resolveInfo(_vocbaseGuard.database(), collectionID, collectionPlanIdMap,
vertexMap, shardList); // store or
resolveInfo(
&(_vocbaseGuard.database()),
collectionID,
collectionPlanIdMap,
vertexMap,
shardList
); // store or
}
for (CollectionID const& collectionID : _edgeCollections) {
resolveInfo(_vocbaseGuard.database(), collectionID, collectionPlanIdMap,
edgeMap, shardList); // store or
resolveInfo(
&(_vocbaseGuard.database()),
collectionID,
collectionPlanIdMap,
edgeMap,
shardList
); // store or
}
_dbServers.clear();
@ -610,22 +627,23 @@ int Conductor::_initializeWorkers(std::string const& suffix,
if (ServerState::instance()->getRole() == ServerState::ROLE_SINGLE) {
TRI_ASSERT(vertexMap.size() == 1);
PregelFeature* feature = PregelFeature::instance();
std::shared_ptr<IWorker> worker = feature->worker(_executionNumber);
if (worker) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"a worker with this execution number already exists.");
}
TRI_vocbase_t* vocbase = _vocbaseGuard.database();
auto created = AlgoRegistry::createWorker(vocbase, b.slice());
auto created =
AlgoRegistry::createWorker(&(_vocbaseGuard.database()), b.slice());
TRI_ASSERT(created.get() != nullptr);
PregelFeature::instance()->addWorker(std::move(created), _executionNumber);
worker = PregelFeature::instance()->worker(_executionNumber);
TRI_ASSERT (worker);
worker->setupWorker();
return TRI_ERROR_NO_ERROR;
} else {
auto body = std::make_shared<std::string const>(b.toJson());
requests.emplace_back("server:" + server, rest::RequestType::POST, path,
@ -744,16 +762,20 @@ int Conductor::_sendToAllDBServers(std::string const& path,
if (ServerState::instance()->isRunningInCluster() == false) {
if (handle) {
VPackBuilder response;
PregelFeature::handleWorkerRequest(_vocbaseGuard.database(), path,
message.slice(), response);
PregelFeature::handleWorkerRequest(
&(_vocbaseGuard.database()), path, message.slice(), response
);
handle(response.slice());
} else {
TRI_ASSERT(SchedulerFeature::SCHEDULER != nullptr);
rest::Scheduler* scheduler = SchedulerFeature::SCHEDULER;
scheduler->post([this, path, message] {
VPackBuilder response;
PregelFeature::handleWorkerRequest(_vocbaseGuard.database(), path,
message.slice(), response);
PregelFeature::handleWorkerRequest(
&(_vocbaseGuard.database()), path, message.slice(), response
);
});
}
return TRI_ERROR_NO_ERROR;
@ -761,14 +783,17 @@ int Conductor::_sendToAllDBServers(std::string const& path,
// cluster case
std::shared_ptr<ClusterComm> cc = ClusterComm::instance();
if (_dbServers.size() == 0) {
LOG_TOPIC(WARN, Logger::PREGEL) << "No servers registered";
return TRI_ERROR_FAILED;
}
std::string base =
Utils::baseUrl(_vocbaseGuard.database()->name(), Utils::workerPrefix);
Utils::baseUrl(_vocbaseGuard.database().name(), Utils::workerPrefix);
auto body = std::make_shared<std::string const>(message.toJson());
std::vector<ClusterCommRequest> requests;
for (auto const& server : _dbServers) {
requests.emplace_back("server:" + server, rest::RequestType::POST,
base + path, body);

View File

@ -106,10 +106,14 @@ class Conductor {
void finishedRecoveryStep(VPackSlice const& data);
public:
Conductor(uint64_t executionNumber, TRI_vocbase_t* vocbase,
std::vector<CollectionID> const& vertexCollections,
std::vector<CollectionID> const& edgeCollections,
std::string const& algoName, VPackSlice const& userConfig);
Conductor(
uint64_t executionNumber,
TRI_vocbase_t& vocbase,
std::vector<CollectionID> const& vertexCollections,
std::vector<CollectionID> const& edgeCollections,
std::string const& algoName,
VPackSlice const& userConfig
);
~Conductor();

View File

@ -336,13 +336,16 @@ std::unique_ptr<transaction::Methods> GraphStore<V, E>::_createTransaction() {
transaction::Options transactionOptions;
transactionOptions.waitForSync = false;
transactionOptions.allowImplicitCollections = true;
auto ctx = transaction::StandaloneContext::Create(_vocbaseGuard.database());
auto ctx =
transaction::StandaloneContext::Create(&(_vocbaseGuard.database()));
std::unique_ptr<transaction::Methods> trx(
new transaction::UserTransaction(ctx, {}, {}, {}, transactionOptions));
Result res = trx->begin();
if (!res.ok()) {
THROW_ARANGO_EXCEPTION(res);
}
return trx;
}
@ -504,27 +507,39 @@ void GraphStore<V, E>::_storeVertices(std::vector<ShardID> const& globalShards,
if (it->shard() != currentShard) {
if (trx) {
res = trx->finish(res);
if (!res.ok()) {
THROW_ARANGO_EXCEPTION(res);
}
}
currentShard = it->shard();
ShardID const& shard = globalShards[currentShard];
transaction::Options transactionOptions;
transactionOptions.waitForSync = false;
transactionOptions.allowImplicitCollections = false;
trx.reset(new transaction::UserTransaction(
transaction::StandaloneContext::Create(_vocbaseGuard.database()), {},
{shard}, {}, transactionOptions));
transaction::StandaloneContext::Create(&(_vocbaseGuard.database())),
{},
{shard},
{},
transactionOptions
));
res = trx->begin();
if (!res.ok()) {
THROW_ARANGO_EXCEPTION(res);
}
}
transaction::BuilderLeaser b(trx.get());
b->openArray();
size_t buffer = 0;
while (it != it.end() && it->shard() == currentShard && buffer < 1000) {
// This loop will fill a buffer of vertices until we run into a new
// collection

View File

@ -62,14 +62,20 @@ using namespace arangodb::rest;
size_t const DatabaseInitialSyncer::MaxChunkSize = 10 * 1024 * 1024;
DatabaseInitialSyncer::DatabaseInitialSyncer(TRI_vocbase_t* vocbase,
ReplicationApplierConfiguration const& configuration)
: InitialSyncer(configuration),
_vocbase(vocbase),
_hasFlushed(false) {
_vocbases.emplace(vocbase->name(), DatabaseGuard(vocbase));
DatabaseInitialSyncer::DatabaseInitialSyncer(
TRI_vocbase_t& vocbase,
ReplicationApplierConfiguration const& configuration
): InitialSyncer(configuration),
_vocbase(&vocbase),
_hasFlushed(false) {
_vocbases.emplace(
std::piecewise_construct,
std::forward_as_tuple(vocbase.name()),
std::forward_as_tuple(vocbase)
);
if (configuration._database.empty()) {
_databaseName = vocbase->name();
_databaseName = vocbase.name();
}
}

View File

@ -76,23 +76,23 @@ class DatabaseInitialSyncer : public InitialSyncer {
PHASE_DROP_CREATE,
PHASE_DUMP
} sync_phase_e;
public:
DatabaseInitialSyncer(TRI_vocbase_t*,
ReplicationApplierConfiguration const&);
public:
DatabaseInitialSyncer(
TRI_vocbase_t& vocbase,
ReplicationApplierConfiguration const& configuration
);
/// @brief run method, performs a full synchronization
Result run(bool incremental) override {
return runWithInventory(incremental, velocypack::Slice::noneSlice());
}
/// @brief run method, performs a full synchronization with the
/// given list of collections.
Result runWithInventory(bool incremental,
velocypack::Slice collections);
TRI_vocbase_t* resolveVocbase(velocypack::Slice const&) override { return _vocbase; }
/// @brief translate a phase to a phase name
@ -114,12 +114,12 @@ class DatabaseInitialSyncer : public InitialSyncer {
TRI_vocbase_t* vocbase() const {
TRI_ASSERT(vocbases().size() == 1);
return vocbases().begin()->second.database();
return &(vocbases().begin()->second.database());
}
/// @brief check whether the initial synchronization should be aborted
bool isAborted() const override;
/// @brief insert the batch id and barrier ID.
/// For use in globalinitalsyncer
void useAsChildSyncer(Syncer::MasterInfo const& info,
@ -132,7 +132,7 @@ class DatabaseInitialSyncer : public InitialSyncer {
_batchId = batchId;
_batchUpdateTime = batchUpdateTime;
}
/// @brief last time the barrier was extended or created
/// The barrier prevents the deletion of WAL files for mmfiles
double barrierUpdateTime() const { return _barrierUpdateTime; }

View File

@ -42,17 +42,19 @@
#include <velocypack/Slice.h>
#include <velocypack/velocypack-aliases.h>
using namespace arangodb;
namespace arangodb {
/// @brief replication applier for a single database, without configuration
DatabaseReplicationApplier::DatabaseReplicationApplier(TRI_vocbase_t* vocbase)
DatabaseReplicationApplier::DatabaseReplicationApplier(TRI_vocbase_t& vocbase)
: DatabaseReplicationApplier(ReplicationApplierConfiguration(), vocbase) {}
/// @brief replication applier for a single database, with configuration
DatabaseReplicationApplier::DatabaseReplicationApplier(ReplicationApplierConfiguration const& configuration,
TRI_vocbase_t* vocbase)
: ReplicationApplier(configuration, std::string("database '") + vocbase->name() + "'"),
_vocbase(vocbase) {}
DatabaseReplicationApplier::DatabaseReplicationApplier(
ReplicationApplierConfiguration const& configuration,
TRI_vocbase_t& vocbase
): ReplicationApplier(configuration, std::string("database '") + vocbase.name() + "'"),
_vocbase(vocbase) {
}
DatabaseReplicationApplier::~DatabaseReplicationApplier() {
try {
@ -62,7 +64,7 @@ DatabaseReplicationApplier::~DatabaseReplicationApplier() {
/// @brief execute the check condition
bool DatabaseReplicationApplier::applies() const {
return (_vocbase->type() == TRI_VOCBASE_TYPE_NORMAL);
return (_vocbase.type() == TRI_VOCBASE_TYPE_NORMAL);
}
/// @brief configure the replication applier
@ -71,7 +73,7 @@ void DatabaseReplicationApplier::reconfigure(ReplicationApplierConfiguration con
// no database
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_REPLICATION_INVALID_APPLIER_CONFIGURATION, "no database configured");
}
ReplicationApplier::reconfigure(configuration);
}
@ -88,16 +90,21 @@ void DatabaseReplicationApplier::forget() {
removeState();
StorageEngine* engine = EngineSelectorFeature::ENGINE;
engine->removeReplicationApplierConfiguration(_vocbase);
engine->removeReplicationApplierConfiguration(&_vocbase);
_configuration.reset();
}
/// @brief factory function for creating a database-specific replication applier
DatabaseReplicationApplier* DatabaseReplicationApplier::create(TRI_vocbase_t* vocbase) {
/*static*/ DatabaseReplicationApplier* DatabaseReplicationApplier::create(
TRI_vocbase_t& vocbase
) {
std::unique_ptr<DatabaseReplicationApplier> applier;
if (vocbase->type() == TRI_VOCBASE_TYPE_NORMAL) {
applier = std::make_unique<DatabaseReplicationApplier>(DatabaseReplicationApplier::loadConfiguration(vocbase), vocbase);
if (vocbase.type() == TRI_VOCBASE_TYPE_NORMAL) {
applier = std::make_unique<DatabaseReplicationApplier>(
DatabaseReplicationApplier::loadConfiguration(&vocbase), vocbase
);
applier->loadState();
} else {
applier = std::make_unique<DatabaseReplicationApplier>(vocbase);
@ -129,8 +136,9 @@ void DatabaseReplicationApplier::storeConfiguration(bool doSync) {
if (!applies()) {
return;
}
VPackBuilder builder;
builder.openObject();
_configuration.toVelocyPack(builder, true, true);
builder.close();
@ -138,8 +146,10 @@ void DatabaseReplicationApplier::storeConfiguration(bool doSync) {
LOG_TOPIC(DEBUG, Logger::REPLICATION) << "storing applier configuration " << builder.slice().toJson() << " for " << _databaseName;
StorageEngine* engine = EngineSelectorFeature::ENGINE;
int res = engine->saveReplicationApplierConfiguration(_vocbase, builder.slice(), doSync);
int res = engine->saveReplicationApplierConfiguration(
&_vocbase, builder.slice(), doSync
);
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
}
@ -154,8 +164,13 @@ std::unique_ptr<TailingSyncer> DatabaseReplicationApplier::buildTailingSyncer(TR
return std::make_unique<arangodb::DatabaseTailingSyncer>(_vocbase, _configuration,
initialTick, useTick, barrierId);
}
std::string DatabaseReplicationApplier::getStateFilename() const {
StorageEngine* engine = EngineSelectorFeature::ENGINE;
return arangodb::basics::FileUtils::buildFilename(engine->databasePath(_vocbase), "REPLICATION-APPLIER-STATE");
return arangodb::basics::FileUtils::buildFilename(
engine->databasePath(&_vocbase), "REPLICATION-APPLIER-STATE"
);
}
} // arangodb

View File

@ -31,16 +31,19 @@
struct TRI_vocbase_t;
namespace arangodb {
/// @brief replication applier for a single database
class DatabaseReplicationApplier final : public ReplicationApplier {
friend class DatabaseTailingSyncer;
friend class RestReplicationHandler;
public:
explicit DatabaseReplicationApplier(TRI_vocbase_t* vocbase);
explicit DatabaseReplicationApplier(TRI_vocbase_t& vocbase);
DatabaseReplicationApplier(ReplicationApplierConfiguration const& configuration,
TRI_vocbase_t* vocbase);
DatabaseReplicationApplier(
ReplicationApplierConfiguration const& configuration,
TRI_vocbase_t& vocbase
);
~DatabaseReplicationApplier();
@ -55,26 +58,26 @@ class DatabaseReplicationApplier final : public ReplicationApplier {
/// @brief configure the replication applier
void reconfigure(ReplicationApplierConfiguration const& configuration) override;
/// @brief store the configuration for the applier
void storeConfiguration(bool doSync) override;
/// @brief factory function for creating a database-specific replication applier
static DatabaseReplicationApplier* create(TRI_vocbase_t* vocbase);
static DatabaseReplicationApplier* create(TRI_vocbase_t& vocbase);
/// @brief load a persisted configuration for the applier
static ReplicationApplierConfiguration loadConfiguration(TRI_vocbase_t* vocbase);
std::unique_ptr<InitialSyncer> buildInitialSyncer() const override;
std::unique_ptr<TailingSyncer> buildTailingSyncer(TRI_voc_tick_t initialTick, bool useTick, TRI_voc_tick_t barrierId) const override;
protected:
std::string getStateFilename() const override;
private:
TRI_vocbase_t* _vocbase;
TRI_vocbase_t& _vocbase;
};
}
#endif
#endif

View File

@ -56,15 +56,27 @@ using namespace arangodb::httpclient;
using namespace arangodb::rest;
DatabaseTailingSyncer::DatabaseTailingSyncer(
TRI_vocbase_t* vocbase,
TRI_vocbase_t& vocbase,
ReplicationApplierConfiguration const& configuration,
TRI_voc_tick_t initialTick, bool useTick, TRI_voc_tick_t barrierId)
: TailingSyncer(vocbase->replicationApplier(),
configuration, initialTick, useTick, barrierId),
_vocbase(vocbase) {
_vocbases.emplace(vocbase->name(), DatabaseGuard(vocbase));
TRI_voc_tick_t initialTick,
bool useTick,
TRI_voc_tick_t barrierId
): TailingSyncer(
vocbase.replicationApplier(),
configuration,
initialTick,
useTick,
barrierId
),
_vocbase(&vocbase) {
_vocbases.emplace(
std::piecewise_construct,
std::forward_as_tuple(vocbase.name()),
std::forward_as_tuple(vocbase)
);
if (configuration._database.empty()) {
_databaseName = vocbase->name();
_databaseName = vocbase.name();
}
}

View File

@ -33,40 +33,41 @@ class DatabaseReplicationApplier;
class DatabaseTailingSyncer : public TailingSyncer {
public:
DatabaseTailingSyncer(TRI_vocbase_t*,
ReplicationApplierConfiguration const&,
TRI_voc_tick_t initialTick, bool useTick,
TRI_voc_tick_t barrierId);
DatabaseTailingSyncer(
TRI_vocbase_t& vocbase,
ReplicationApplierConfiguration const& configuration,
TRI_voc_tick_t initialTick,
bool useTick,
TRI_voc_tick_t barrierId
);
public:
TRI_vocbase_t* resolveVocbase(velocypack::Slice const&) override { return _vocbase; }
/// @brief return the syncer's replication applier
DatabaseReplicationApplier* applier() const {
return static_cast<DatabaseReplicationApplier*>(_applier);
}
/// @brief finalize the synchronization of a collection by tailing the WAL
/// and filtering on the collection name until no more data is available
Result syncCollectionFinalize(std::string const& collectionName);
protected:
/// @brief save the current applier state
Result saveApplierState() override;
TRI_vocbase_t* vocbase() const {
TRI_ASSERT(vocbases().size() == 1);
return vocbases().begin()->second.database();
return &(vocbases().begin()->second.database());
}
private:
/// @brief vocbase to use for this run
TRI_vocbase_t* _vocbase;
};
}
#endif
#endif

View File

@ -158,46 +158,49 @@ Result GlobalInitialSyncer::runInternal(bool incremental) {
VPackSlice const nameSlice = it.get("name");
VPackSlice const idSlice = it.get("id");
VPackSlice const collections = it.get("collections");
if (!nameSlice.isString() ||
!idSlice.isString() ||
!collections.isArray()) {
return Result(TRI_ERROR_REPLICATION_INVALID_RESPONSE,
"database declaration is invalid in response");
}
TRI_vocbase_t* vocbase = resolveVocbase(nameSlice);
if (vocbase == nullptr) {
return Result(TRI_ERROR_INTERNAL, "vocbase not found");
}
DatabaseGuard guard(nameSlice.copyString());
// change database name in place
auto configurationCopy = _configuration;
configurationCopy._database = nameSlice.copyString();
DatabaseInitialSyncer syncer(vocbase, configurationCopy);
DatabaseInitialSyncer syncer(*vocbase, configurationCopy);
syncer.useAsChildSyncer(_masterInfo, _barrierId, _barrierUpdateTime,
_batchId, _batchUpdateTime);
// run the syncer with the supplied inventory collections
Result r = syncer.runWithInventory(false, collections);
if (r.fail()) {
return r;
}
// we need to pass on the update times to the next syncer
_barrierUpdateTime = syncer.barrierUpdateTime();
_batchUpdateTime = syncer.batchUpdateTime();
sendExtendBatch();
sendExtendBarrier();
}
} catch (...) {
return Result(TRI_ERROR_INTERNAL, "caught an unexpected exception");
}
return TRI_ERROR_NO_ERROR;
}

View File

@ -37,16 +37,13 @@ namespace arangodb {
class ReplicationTransaction : public transaction::Methods {
public:
/// @brief create the transaction
explicit ReplicationTransaction(TRI_vocbase_t* vocbase)
: transaction::Methods(transaction::StandaloneContext::Create(vocbase)),
_guard(vocbase) {
explicit ReplicationTransaction(TRI_vocbase_t& vocbase)
: transaction::Methods(transaction::StandaloneContext::Create(&vocbase)),
_guard(vocbase) {
TRI_ASSERT(_state != nullptr);
_state->setType(AccessMode::Type::EXCLUSIVE);
}
public:
/// @brief get a collection by id
/// this will automatically add the collection to the transaction
/*inline TransactionCollection* trxCollection(TRI_voc_cid_t cid, AccessMode::Type) const override {
@ -79,4 +76,4 @@ class ReplicationTransaction : public transaction::Methods {
}
#endif
#endif

View File

@ -356,24 +356,32 @@ TRI_vocbase_t* Syncer::resolveVocbase(VPackSlice const& slice) {
} else if (slice.isString()) {
name = slice.copyString();
}
if (name.empty()) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_REPLICATION_INVALID_RESPONSE,
"could not resolve vocbase id / name");
}
// will work with either names or id's
auto const& it = _vocbases.find(name);
if (it == _vocbases.end()) {
// automatically checks for id in string
TRI_vocbase_t* vocbase = DatabaseFeature::DATABASE->lookupDatabase(name);
if (vocbase != nullptr) {
_vocbases.emplace(name, DatabaseGuard(vocbase));
_vocbases.emplace(
std::piecewise_construct,
std::forward_as_tuple(name),
std::forward_as_tuple(*vocbase)
);
} else {
LOG_TOPIC(DEBUG, Logger::REPLICATION) << "could not find database '" << name << "'";
}
return vocbase;
} else {
return it->second.database();
return &(it->second.database());
}
}

View File

@ -444,7 +444,7 @@ Result TailingSyncer::startTransaction(VPackSlice const& slice) {
LOG_TOPIC(TRACE, Logger::REPLICATION) << "starting replication transaction "
<< tid;
auto trx = std::make_unique<ReplicationTransaction>(vocbase);
auto trx = std::make_unique<ReplicationTransaction>(*vocbase);
Result res = trx->begin();
if (res.ok()) {

View File

@ -1755,13 +1755,15 @@ void RestReplicationHandler::handleCommandSync() {
TRI_ASSERT(!config._skipCreateDrop);
std::unique_ptr<InitialSyncer> syncer;
if (isGlobal) {
syncer.reset(new GlobalInitialSyncer(config));
} else {
syncer.reset(new DatabaseInitialSyncer(&_vocbase, config));
syncer.reset(new DatabaseInitialSyncer(_vocbase, config));
}
Result r = syncer->run(config._incremental);
if (r.fail()) {
LOG_TOPIC(ERR, Logger::REPLICATION)
<< "failed to sync: " << r.errorMessage();

View File

@ -107,8 +107,9 @@ VPackSlice RocksDBExportCursor::next() {
size_t RocksDBExportCursor::count() const { return _size; }
Result RocksDBExportCursor::dump(VPackBuilder& builder) {
auto ctx = transaction::StandaloneContext::Create(_guard.database());
auto ctx = transaction::StandaloneContext::Create(&(_guard.database()));
VPackOptions const* oldOptions = builder.options;
builder.options = ctx->getVPackOptions();
TRI_ASSERT(_iter.get() != nullptr);

View File

@ -102,10 +102,12 @@ uint64_t RocksDBReplicationContext::count() const {
TRI_vocbase_t* RocksDBReplicationContext::vocbase() const {
MUTEX_LOCKER(locker, _contextLock);
if (!_guard) {
return nullptr;
}
return _guard->database();
return &(_guard->database());
}
// creates new transaction/snapshot
@ -116,7 +118,7 @@ void RocksDBReplicationContext::bind(TRI_vocbase_t* vocbase) {
void RocksDBReplicationContext::internalBind(TRI_vocbase_t* vocbase,
bool allowChange) {
if (!_trx || !_guard || (_guard->database() != vocbase)) {
if (!_trx || !_guard || (&(_guard->database()) != vocbase)) {
TRI_ASSERT(allowChange);
rocksdb::Snapshot const* snap = nullptr;
if (_trx) {
@ -177,7 +179,8 @@ int RocksDBReplicationContext::bindCollection(
int RocksDBReplicationContext::chooseDatabase(TRI_vocbase_t* vocbase) {
TRI_ASSERT(_users > 0);
MUTEX_LOCKER(locker, _contextLock);
if (_guard->database() == vocbase) {
if (&(_guard->database()) == vocbase) {
return TRI_ERROR_NO_ERROR; // nothing to do here
}
@ -242,17 +245,23 @@ RocksDBReplicationResult RocksDBReplicationContext::dump(
}
};
TRI_DEFER(release());
{
MUTEX_LOCKER(writeLocker, _contextLock);
TRI_ASSERT(vocbase != nullptr);
if (!_trx || !_guard || (_guard->database() != vocbase)) {
if (!_trx || !_guard || (&(_guard->database()) != vocbase)) {
return RocksDBReplicationResult(TRI_ERROR_BAD_PARAMETER, _lastTick);
}
TRI_voc_cid_t const id{::normalizeIdentifier(*_trx, collectionName)};
if (0 == id) {
return RocksDBReplicationResult{TRI_ERROR_BAD_PARAMETER, _lastTick};
}
collection = getCollectionIterator(id);
if (!collection) {
return RocksDBReplicationResult(TRI_ERROR_BAD_PARAMETER, _lastTick);
}

View File

@ -55,15 +55,22 @@ bool WalAccessContext::shouldHandleCollection(TRI_voc_tick_t dbid,
TRI_vocbase_t* WalAccessContext::loadVocbase(TRI_voc_tick_t dbid) {
TRI_ASSERT(dbid != 0);
auto const& it = _vocbases.find(dbid);
if (it == _vocbases.end()) {
TRI_vocbase_t* vocbase = DatabaseFeature::DATABASE->useDatabase(dbid);
if (vocbase != nullptr) {
TRI_DEFER(vocbase->release());
_vocbases.emplace(dbid, DatabaseGuard(vocbase));
_vocbases.emplace(
std::piecewise_construct,
std::forward_as_tuple(dbid),
std::forward_as_tuple(*vocbase)
);
}
return vocbase;
} else {
return it->second.database();
return &(it->second.database());
}
}

View File

@ -40,7 +40,7 @@ size_t const CursorRepository::MaxCollectCount = 32;
/// @brief create a cursor repository
////////////////////////////////////////////////////////////////////////////////
CursorRepository::CursorRepository(TRI_vocbase_t* vocbase)
CursorRepository::CursorRepository(TRI_vocbase_t& vocbase)
: _vocbase(vocbase), _lock(), _cursors() {
_cursors.reserve(64);
}

View File

@ -32,6 +32,7 @@
struct TRI_vocbase_t;
namespace arangodb {
namespace velocypack {
class Builder;
}
@ -46,7 +47,7 @@ class CursorRepository {
/// @brief create a cursors repository
//////////////////////////////////////////////////////////////////////////////
explicit CursorRepository(TRI_vocbase_t*);
explicit CursorRepository(TRI_vocbase_t& vocbase);
//////////////////////////////////////////////////////////////////////////////
/// @brief destroy a cursors repository
@ -54,15 +55,13 @@ class CursorRepository {
~CursorRepository();
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief stores a cursor in the registry
/// the repository will take ownership of the cursor
////////////////////////////////////////////////////////////////////////////////
Cursor* addCursor(std::unique_ptr<Cursor> cursor);
//////////////////////////////////////////////////////////////////////////////
/// @brief creates a cursor and stores it in the registry
/// the cursor will be returned with the usage flag set to true. it must be
@ -71,19 +70,19 @@ class CursorRepository {
//////////////////////////////////////////////////////////////////////////////
Cursor* createFromQueryResult(aql::QueryResult&&, size_t, double, bool);
//////////////////////////////////////////////////////////////////////////////
/// @brief creates a cursor and stores it in the registry
/// the cursor will be returned with the usage flag set to true. it must be
/// returned later using release()
/// the cursor will create a query internally and retain it until deleted
//////////////////////////////////////////////////////////////////////////////
Cursor* createQueryStream(std::string const& query,
std::shared_ptr<velocypack::Builder> const& binds,
std::shared_ptr<velocypack::Builder> const& opts,
size_t batchSize, double ttl);
//////////////////////////////////////////////////////////////////////////////
/// @brief remove a cursor by id
//////////////////////////////////////////////////////////////////////////////
@ -121,7 +120,7 @@ class CursorRepository {
/// @brief vocbase
//////////////////////////////////////////////////////////////////////////////
TRI_vocbase_t* _vocbase;
TRI_vocbase_t& _vocbase;
//////////////////////////////////////////////////////////////////////////////
/// @brief mutex for the cursors repository
@ -141,6 +140,7 @@ class CursorRepository {
static size_t const MaxCollectCount;
};
}
#endif
#endif

View File

@ -26,32 +26,48 @@
#include "Basics/Exceptions.h"
#include "RestServer/DatabaseFeature.h"
using namespace arangodb;
namespace {
/// @brief create the guard, using a database id
DatabaseGuard::DatabaseGuard(TRI_voc_tick_t id) : _vocbase(nullptr) {
DatabaseFeature* databaseFeature = DatabaseFeature::DATABASE;
_vocbase = databaseFeature->useDatabase(id);
template<typename T>
TRI_vocbase_t& vocbase(T& id) {
auto* databaseFeature = arangodb::DatabaseFeature::DATABASE;
if (_vocbase == nullptr) {
if (!databaseFeature) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
TRI_ASSERT(!_vocbase->isDangling());
auto* vocbase = databaseFeature->useDatabase(id);
if (!vocbase) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
return *vocbase;
}
template<>
TRI_vocbase_t& vocbase(TRI_vocbase_t*& vocbase) {
// check from the original constructor of DatabaseGuard
TRI_ASSERT(vocbase != nullptr);
return *vocbase;
}
} // namespace
namespace arangodb {
DatabaseGuard::DatabaseGuard(TRI_vocbase_t* ptr): DatabaseGuard(vocbase(ptr)) {
}
/// @brief create the guard, using a database id
DatabaseGuard::DatabaseGuard(TRI_voc_tick_t id): _vocbase(vocbase(id)) {
TRI_ASSERT(!_vocbase.isDangling());
}
/// @brief create the guard, using a database name
DatabaseGuard::DatabaseGuard(std::string const& name) : _vocbase(nullptr) {
DatabaseFeature* databaseFeature = DatabaseFeature::DATABASE;
_vocbase = databaseFeature->useDatabase(name);
if (_vocbase == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
TRI_ASSERT(!_vocbase->isDangling());
DatabaseGuard::DatabaseGuard(std::string const& name): _vocbase(vocbase(name)) {
TRI_ASSERT(!_vocbase.isDangling());
}
DatabaseGuard::DatabaseGuard(DatabaseGuard&& other) : _vocbase(other._vocbase) {
other._vocbase = nullptr;
}
} // arangodb

View File

@ -32,17 +32,22 @@ namespace arangodb {
/// dropped while still using it.
class DatabaseGuard {
public:
DatabaseGuard(DatabaseGuard&&) = delete;
DatabaseGuard(DatabaseGuard const&) = delete;
DatabaseGuard& operator=(DatabaseGuard const&) = delete;
/// @brief create guard on existing db
explicit DatabaseGuard(TRI_vocbase_t* vocbase) : _vocbase(vocbase) {
TRI_ASSERT(vocbase != nullptr);
if (!_vocbase->use()) {
explicit DatabaseGuard(TRI_vocbase_t& vocbase): _vocbase(vocbase) {
if (!_vocbase.use()) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
}
/// @brief create guard on existing db pointer (not nullptr)
/// @deprecated DO NOT USE for new code
/// FIXME TODO remove once V8Task and arangodb::pregel::GraphStore are fixed
explicit DatabaseGuard(TRI_vocbase_t* vocbase);
/// @brief create the guard, using a database id
explicit DatabaseGuard(TRI_voc_tick_t id);
@ -51,22 +56,18 @@ class DatabaseGuard {
/// @brief destroy the guard
~DatabaseGuard() {
if (_vocbase != nullptr) {
TRI_ASSERT(!_vocbase->isDangling());
_vocbase->release();
}
TRI_ASSERT(!_vocbase.isDangling());
_vocbase.release();
}
DatabaseGuard(DatabaseGuard&&);
public:
/// @brief return the database pointer
inline TRI_vocbase_t* database() const { return _vocbase; }
inline TRI_vocbase_t& database() const { return _vocbase; }
private:
/// @brief pointer to database
TRI_vocbase_t* _vocbase;
TRI_vocbase_t& _vocbase;
};
}
#endif
#endif

View File

@ -1913,6 +1913,8 @@ static void JS_PregelStart(v8::FunctionCallbackInfo<v8::Value> const& args) {
}
TRI_vocbase_t* vocbase = GetContextVocBase(isolate);
TRI_ASSERT(vocbase != nullptr); // for clarity assert duplicated from v8-util.cpp GetContextVocBase(...)
for (std::string const& name : paramVertices) {
if (ss->isCoordinator()) {
try {
@ -1982,8 +1984,9 @@ static void JS_PregelStart(v8::FunctionCallbackInfo<v8::Value> const& args) {
}
uint64_t en = pregel::PregelFeature::instance()->createExecutionNumber();
auto c = std::make_unique<pregel::Conductor>(en, vocbase, paramVertices, edgeColls,
algorithm, paramBuilder.slice());
auto c = std::make_unique<pregel::Conductor>(
en, *vocbase, paramVertices, edgeColls, algorithm, paramBuilder.slice()
);
pregel::PregelFeature::instance()->addConductor(std::move(c), en);
TRI_ASSERT(pregel::PregelFeature::instance()->conductor(en));
pregel::PregelFeature::instance()->conductor(en)->start();

View File

@ -232,7 +232,7 @@ void V8Task::removeTasksForDatabase(std::string const& name) {
}
bool V8Task::databaseMatches(std::string const& name) const {
return (_dbGuard->database()->name() == name);
return (_dbGuard->database().name() == name);
}
V8Task::V8Task(std::string const& id, std::string const& name,
@ -299,14 +299,16 @@ V8Task::callbackFunction() {
// get the permissions to be used by this task
bool allowContinue = true;
std::unique_ptr<ExecContext> execContext;
if (!_user.empty()) { // not superuser
std::string const& dbname = _dbGuard->database()->name();
auto& dbname = _dbGuard->database().name();
execContext.reset(ExecContext::create(_user, dbname));
allowContinue = execContext->canUseDatabase(dbname, auth::Level::RW);
allowContinue = allowContinue && ServerState::writeOpsEnabled();
}
ExecContextScope scope(_user.empty() ?
ExecContext::superuser() : execContext.get());
@ -412,12 +414,13 @@ void V8Task::toVelocyPack(VPackBuilder& builder) const {
builder.add("offset", VPackValue(_offset.count() / 1000000.0));
builder.add("command", VPackValue(_command));
builder.add("database", VPackValue(_dbGuard->database()->name()));
builder.add("database", VPackValue(_dbGuard->database().name()));
}
void V8Task::work(ExecContext const* exec) {
auto context = V8DealerFeature::DEALER->enterContext(_dbGuard->database(),
_allowUseDatabase);
auto context = V8DealerFeature::DEALER->enterContext(
&(_dbGuard->database()), _allowUseDatabase
);
// note: the context might be 0 in case of shut-down
if (context == nullptr) {

View File

@ -191,25 +191,24 @@ static void SynchronizeReplication(
// treat the argument as an object from now on
v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(args[0]);
VPackBuilder builder;
int res = TRI_V8ToVPack(isolate, builder, args[0], false);
if (res != TRI_ERROR_NO_ERROR) {
TRI_V8_THROW_EXCEPTION(res);
}
TRI_vocbase_t* vocbase = GetContextVocBase(isolate);
if (vocbase == nullptr) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
std::string databaseName;
if (applierType == APPLIER_DATABASE) {
databaseName = vocbase->name();
}
bool keepBarrier = false;
if (object->Has(TRI_V8_ASCII_STRING(isolate, "keepBarrier"))) {
keepBarrier =
@ -221,12 +220,11 @@ static void SynchronizeReplication(
v8::Handle<v8::Object> result = v8::Object::New(isolate);
std::unique_ptr<InitialSyncer> syncer;
if (applierType == APPLIER_DATABASE) {
// database-specific synchronization
syncer.reset(new DatabaseInitialSyncer(vocbase, configuration));
syncer.reset(new DatabaseInitialSyncer(*vocbase, configuration));
if (object->Has(TRI_V8_ASCII_STRING(isolate, "leaderId"))) {
syncer->setLeaderId(TRI_ObjectToString(object->Get(TRI_V8_ASCII_STRING(isolate, "leaderId"))));
}

View File

@ -1773,7 +1773,7 @@ TRI_vocbase_t::TRI_vocbase_t(TRI_vocbase_type_e type, TRI_voc_tick_t id,
_deadlockDetector(false),
_userStructures(nullptr) {
_queries.reset(new arangodb::aql::QueryList(this));
_cursorRepository.reset(new arangodb::CursorRepository(this));
_cursorRepository.reset(new arangodb::CursorRepository(*this));
_collectionKeys.reset(new arangodb::CollectionKeysRepository());
// init collections
@ -1856,7 +1856,8 @@ bool TRI_vocbase_t::IsAllowedName(
}
void TRI_vocbase_t::addReplicationApplier() {
DatabaseReplicationApplier* applier = DatabaseReplicationApplier::create(this);
auto* applier = DatabaseReplicationApplier::create(*this);
_replicationApplier.reset(applier);
}
@ -1866,6 +1867,7 @@ void TRI_vocbase_t::updateReplicationClient(TRI_server_id_t serverId, double ttl
if (ttl <= 0.0) {
ttl = InitialSyncer::defaultBatchTimeout;
}
double const expires = TRI_microtime() + ttl;
WRITE_LOCKER(writeLocker, _replicationClientsLock);