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

View File

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

View File

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

View File

@ -597,11 +597,9 @@ void MMFilesCollectorThread::clearQueuedOperations() {
for (auto const& cache : operations) { for (auto const& cache : operations) {
{ {
arangodb::DatabaseGuard dbGuard(cache->databaseId); arangodb::DatabaseGuard dbGuard(cache->databaseId);
TRI_vocbase_t* vocbase = dbGuard.database(); arangodb::CollectionGuard collectionGuard(
TRI_ASSERT(vocbase != nullptr); &(dbGuard.database()), cache->collectionId, true
);
arangodb::CollectionGuard collectionGuard(vocbase, cache->collectionId,
true);
arangodb::LogicalCollection* collection = collectionGuard.collection(); arangodb::LogicalCollection* collection = collectionGuard.collection();
TRI_ASSERT(collection != nullptr); TRI_ASSERT(collection != nullptr);
@ -732,10 +730,10 @@ void MMFilesCollectorThread::processCollectionMarker(
/// @brief process all operations for a single collection /// @brief process all operations for a single collection
int MMFilesCollectorThread::processCollectionOperations(MMFilesCollectorCache* cache) { int MMFilesCollectorThread::processCollectionOperations(MMFilesCollectorCache* cache) {
arangodb::DatabaseGuard dbGuard(cache->databaseId); arangodb::DatabaseGuard dbGuard(cache->databaseId);
TRI_vocbase_t* vocbase = dbGuard.database(); auto& vocbase = dbGuard.database();
TRI_ASSERT(vocbase != nullptr); arangodb::CollectionGuard collectionGuard(
&vocbase, cache->collectionId, true
arangodb::CollectionGuard collectionGuard(vocbase, cache->collectionId, true); );
arangodb::LogicalCollection* collection = collectionGuard.collection(); arangodb::LogicalCollection* collection = collectionGuard.collection();
TRI_ASSERT(collection != nullptr); TRI_ASSERT(collection != nullptr);
@ -983,10 +981,9 @@ int MMFilesCollectorThread::transferMarkers(MMFilesWalLogfile* logfile,
// prepare database and collection // prepare database and collection
arangodb::DatabaseGuard dbGuard(databaseId); arangodb::DatabaseGuard dbGuard(databaseId);
TRI_vocbase_t* vocbase = dbGuard.database(); arangodb::CollectionGuard collectionGuard(
TRI_ASSERT(vocbase != nullptr); &(dbGuard.database()), collectionId, true
);
arangodb::CollectionGuard collectionGuard(vocbase, collectionId, true);
arangodb::LogicalCollection* collection = collectionGuard.collection(); arangodb::LogicalCollection* collection = collectionGuard.collection();
TRI_ASSERT(collection != nullptr); TRI_ASSERT(collection != nullptr);
@ -1006,6 +1003,7 @@ int MMFilesCollectorThread::transferMarkers(MMFilesWalLogfile* logfile,
int res = TRI_ERROR_INTERNAL; int res = TRI_ERROR_INTERNAL;
uint64_t numBytesTransferred = 0; uint64_t numBytesTransferred = 0;
try { try {
auto en = static_cast<MMFilesEngine*>(engine); auto en = static_cast<MMFilesEngine*>(engine);
res = en->transferMarkers(collection, cache.get(), operations, numBytesTransferred); res = en->transferMarkers(collection, cache.get(), operations, numBytesTransferred);

View File

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

View File

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

View File

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

View File

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

View File

@ -78,10 +78,10 @@ class DatabaseInitialSyncer : public InitialSyncer {
} sync_phase_e; } sync_phase_e;
public: public:
DatabaseInitialSyncer(TRI_vocbase_t*, DatabaseInitialSyncer(
ReplicationApplierConfiguration const&); TRI_vocbase_t& vocbase,
ReplicationApplierConfiguration const& configuration
public: );
/// @brief run method, performs a full synchronization /// @brief run method, performs a full synchronization
Result run(bool incremental) override { Result run(bool incremental) override {
@ -114,7 +114,7 @@ class DatabaseInitialSyncer : public InitialSyncer {
TRI_vocbase_t* vocbase() const { TRI_vocbase_t* vocbase() const {
TRI_ASSERT(vocbases().size() == 1); TRI_ASSERT(vocbases().size() == 1);
return vocbases().begin()->second.database(); return &(vocbases().begin()->second.database());
} }
/// @brief check whether the initial synchronization should be aborted /// @brief check whether the initial synchronization should be aborted

View File

@ -42,17 +42,19 @@
#include <velocypack/Slice.h> #include <velocypack/Slice.h>
#include <velocypack/velocypack-aliases.h> #include <velocypack/velocypack-aliases.h>
using namespace arangodb; namespace arangodb {
/// @brief replication applier for a single database, without configuration /// @brief replication applier for a single database, without configuration
DatabaseReplicationApplier::DatabaseReplicationApplier(TRI_vocbase_t* vocbase) DatabaseReplicationApplier::DatabaseReplicationApplier(TRI_vocbase_t& vocbase)
: DatabaseReplicationApplier(ReplicationApplierConfiguration(), vocbase) {} : DatabaseReplicationApplier(ReplicationApplierConfiguration(), vocbase) {}
/// @brief replication applier for a single database, with configuration /// @brief replication applier for a single database, with configuration
DatabaseReplicationApplier::DatabaseReplicationApplier(ReplicationApplierConfiguration const& configuration, DatabaseReplicationApplier::DatabaseReplicationApplier(
TRI_vocbase_t* vocbase) ReplicationApplierConfiguration const& configuration,
: ReplicationApplier(configuration, std::string("database '") + vocbase->name() + "'"), TRI_vocbase_t& vocbase
_vocbase(vocbase) {} ): ReplicationApplier(configuration, std::string("database '") + vocbase.name() + "'"),
_vocbase(vocbase) {
}
DatabaseReplicationApplier::~DatabaseReplicationApplier() { DatabaseReplicationApplier::~DatabaseReplicationApplier() {
try { try {
@ -62,7 +64,7 @@ DatabaseReplicationApplier::~DatabaseReplicationApplier() {
/// @brief execute the check condition /// @brief execute the check condition
bool DatabaseReplicationApplier::applies() const { bool DatabaseReplicationApplier::applies() const {
return (_vocbase->type() == TRI_VOCBASE_TYPE_NORMAL); return (_vocbase.type() == TRI_VOCBASE_TYPE_NORMAL);
} }
/// @brief configure the replication applier /// @brief configure the replication applier
@ -88,16 +90,21 @@ void DatabaseReplicationApplier::forget() {
removeState(); removeState();
StorageEngine* engine = EngineSelectorFeature::ENGINE; StorageEngine* engine = EngineSelectorFeature::ENGINE;
engine->removeReplicationApplierConfiguration(_vocbase);
engine->removeReplicationApplierConfiguration(&_vocbase);
_configuration.reset(); _configuration.reset();
} }
/// @brief factory function for creating a database-specific replication applier /// @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; std::unique_ptr<DatabaseReplicationApplier> applier;
if (vocbase->type() == TRI_VOCBASE_TYPE_NORMAL) { if (vocbase.type() == TRI_VOCBASE_TYPE_NORMAL) {
applier = std::make_unique<DatabaseReplicationApplier>(DatabaseReplicationApplier::loadConfiguration(vocbase), vocbase); applier = std::make_unique<DatabaseReplicationApplier>(
DatabaseReplicationApplier::loadConfiguration(&vocbase), vocbase
);
applier->loadState(); applier->loadState();
} else { } else {
applier = std::make_unique<DatabaseReplicationApplier>(vocbase); applier = std::make_unique<DatabaseReplicationApplier>(vocbase);
@ -131,6 +138,7 @@ void DatabaseReplicationApplier::storeConfiguration(bool doSync) {
} }
VPackBuilder builder; VPackBuilder builder;
builder.openObject(); builder.openObject();
_configuration.toVelocyPack(builder, true, true); _configuration.toVelocyPack(builder, true, true);
builder.close(); builder.close();
@ -138,7 +146,9 @@ void DatabaseReplicationApplier::storeConfiguration(bool doSync) {
LOG_TOPIC(DEBUG, Logger::REPLICATION) << "storing applier configuration " << builder.slice().toJson() << " for " << _databaseName; LOG_TOPIC(DEBUG, Logger::REPLICATION) << "storing applier configuration " << builder.slice().toJson() << " for " << _databaseName;
StorageEngine* engine = EngineSelectorFeature::ENGINE; 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) { if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res); THROW_ARANGO_EXCEPTION(res);
@ -157,5 +167,10 @@ std::unique_ptr<TailingSyncer> DatabaseReplicationApplier::buildTailingSyncer(TR
std::string DatabaseReplicationApplier::getStateFilename() const { std::string DatabaseReplicationApplier::getStateFilename() const {
StorageEngine* engine = EngineSelectorFeature::ENGINE; 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; struct TRI_vocbase_t;
namespace arangodb { namespace arangodb {
/// @brief replication applier for a single database /// @brief replication applier for a single database
class DatabaseReplicationApplier final : public ReplicationApplier { class DatabaseReplicationApplier final : public ReplicationApplier {
friend class DatabaseTailingSyncer; friend class DatabaseTailingSyncer;
friend class RestReplicationHandler; friend class RestReplicationHandler;
public: public:
explicit DatabaseReplicationApplier(TRI_vocbase_t* vocbase); explicit DatabaseReplicationApplier(TRI_vocbase_t& vocbase);
DatabaseReplicationApplier(ReplicationApplierConfiguration const& configuration, DatabaseReplicationApplier(
TRI_vocbase_t* vocbase); ReplicationApplierConfiguration const& configuration,
TRI_vocbase_t& vocbase
);
~DatabaseReplicationApplier(); ~DatabaseReplicationApplier();
@ -60,7 +63,7 @@ class DatabaseReplicationApplier final : public ReplicationApplier {
void storeConfiguration(bool doSync) override; void storeConfiguration(bool doSync) override;
/// @brief factory function for creating a database-specific replication applier /// @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 /// @brief load a persisted configuration for the applier
static ReplicationApplierConfiguration loadConfiguration(TRI_vocbase_t* vocbase); static ReplicationApplierConfiguration loadConfiguration(TRI_vocbase_t* vocbase);
@ -72,7 +75,7 @@ protected:
std::string getStateFilename() const override; std::string getStateFilename() const override;
private: private:
TRI_vocbase_t* _vocbase; TRI_vocbase_t& _vocbase;
}; };
} }

View File

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

View File

@ -33,12 +33,13 @@ class DatabaseReplicationApplier;
class DatabaseTailingSyncer : public TailingSyncer { class DatabaseTailingSyncer : public TailingSyncer {
public: public:
DatabaseTailingSyncer(TRI_vocbase_t*, DatabaseTailingSyncer(
ReplicationApplierConfiguration const&, TRI_vocbase_t& vocbase,
TRI_voc_tick_t initialTick, bool useTick, ReplicationApplierConfiguration const& configuration,
TRI_voc_tick_t barrierId); TRI_voc_tick_t initialTick,
bool useTick,
public: TRI_voc_tick_t barrierId
);
TRI_vocbase_t* resolveVocbase(velocypack::Slice const&) override { return _vocbase; } TRI_vocbase_t* resolveVocbase(velocypack::Slice const&) override { return _vocbase; }
@ -58,7 +59,7 @@ class DatabaseTailingSyncer : public TailingSyncer {
TRI_vocbase_t* vocbase() const { TRI_vocbase_t* vocbase() const {
TRI_ASSERT(vocbases().size() == 1); TRI_ASSERT(vocbases().size() == 1);
return vocbases().begin()->second.database(); return &(vocbases().begin()->second.database());
} }
private: private:

View File

@ -158,6 +158,7 @@ Result GlobalInitialSyncer::runInternal(bool incremental) {
VPackSlice const nameSlice = it.get("name"); VPackSlice const nameSlice = it.get("name");
VPackSlice const idSlice = it.get("id"); VPackSlice const idSlice = it.get("id");
VPackSlice const collections = it.get("collections"); VPackSlice const collections = it.get("collections");
if (!nameSlice.isString() || if (!nameSlice.isString() ||
!idSlice.isString() || !idSlice.isString() ||
!collections.isArray()) { !collections.isArray()) {
@ -166,6 +167,7 @@ Result GlobalInitialSyncer::runInternal(bool incremental) {
} }
TRI_vocbase_t* vocbase = resolveVocbase(nameSlice); TRI_vocbase_t* vocbase = resolveVocbase(nameSlice);
if (vocbase == nullptr) { if (vocbase == nullptr) {
return Result(TRI_ERROR_INTERNAL, "vocbase not found"); return Result(TRI_ERROR_INTERNAL, "vocbase not found");
} }
@ -174,12 +176,14 @@ Result GlobalInitialSyncer::runInternal(bool incremental) {
// change database name in place // change database name in place
auto configurationCopy = _configuration; auto configurationCopy = _configuration;
configurationCopy._database = nameSlice.copyString(); configurationCopy._database = nameSlice.copyString();
DatabaseInitialSyncer syncer(vocbase, configurationCopy); DatabaseInitialSyncer syncer(*vocbase, configurationCopy);
syncer.useAsChildSyncer(_masterInfo, _barrierId, _barrierUpdateTime, syncer.useAsChildSyncer(_masterInfo, _barrierId, _barrierUpdateTime,
_batchId, _batchUpdateTime); _batchId, _batchUpdateTime);
// run the syncer with the supplied inventory collections // run the syncer with the supplied inventory collections
Result r = syncer.runWithInventory(false, collections); Result r = syncer.runWithInventory(false, collections);
if (r.fail()) { if (r.fail()) {
@ -193,7 +197,6 @@ Result GlobalInitialSyncer::runInternal(bool incremental) {
sendExtendBatch(); sendExtendBatch();
sendExtendBarrier(); sendExtendBarrier();
} }
} catch (...) { } catch (...) {
return Result(TRI_ERROR_INTERNAL, "caught an unexpected exception"); return Result(TRI_ERROR_INTERNAL, "caught an unexpected exception");
} }

View File

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

View File

@ -356,6 +356,7 @@ TRI_vocbase_t* Syncer::resolveVocbase(VPackSlice const& slice) {
} else if (slice.isString()) { } else if (slice.isString()) {
name = slice.copyString(); name = slice.copyString();
} }
if (name.empty()) { if (name.empty()) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_REPLICATION_INVALID_RESPONSE, THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_REPLICATION_INVALID_RESPONSE,
"could not resolve vocbase id / name"); "could not resolve vocbase id / name");
@ -363,17 +364,24 @@ TRI_vocbase_t* Syncer::resolveVocbase(VPackSlice const& slice) {
// will work with either names or id's // will work with either names or id's
auto const& it = _vocbases.find(name); auto const& it = _vocbases.find(name);
if (it == _vocbases.end()) { if (it == _vocbases.end()) {
// automatically checks for id in string // automatically checks for id in string
TRI_vocbase_t* vocbase = DatabaseFeature::DATABASE->lookupDatabase(name); TRI_vocbase_t* vocbase = DatabaseFeature::DATABASE->lookupDatabase(name);
if (vocbase != nullptr) { if (vocbase != nullptr) {
_vocbases.emplace(name, DatabaseGuard(vocbase)); _vocbases.emplace(
std::piecewise_construct,
std::forward_as_tuple(name),
std::forward_as_tuple(*vocbase)
);
} else { } else {
LOG_TOPIC(DEBUG, Logger::REPLICATION) << "could not find database '" << name << "'"; LOG_TOPIC(DEBUG, Logger::REPLICATION) << "could not find database '" << name << "'";
} }
return vocbase; return vocbase;
} else { } 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 " LOG_TOPIC(TRACE, Logger::REPLICATION) << "starting replication transaction "
<< tid; << tid;
auto trx = std::make_unique<ReplicationTransaction>(vocbase); auto trx = std::make_unique<ReplicationTransaction>(*vocbase);
Result res = trx->begin(); Result res = trx->begin();
if (res.ok()) { if (res.ok()) {

View File

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

View File

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

View File

@ -102,10 +102,12 @@ uint64_t RocksDBReplicationContext::count() const {
TRI_vocbase_t* RocksDBReplicationContext::vocbase() const { TRI_vocbase_t* RocksDBReplicationContext::vocbase() const {
MUTEX_LOCKER(locker, _contextLock); MUTEX_LOCKER(locker, _contextLock);
if (!_guard) { if (!_guard) {
return nullptr; return nullptr;
} }
return _guard->database();
return &(_guard->database());
} }
// creates new transaction/snapshot // creates new transaction/snapshot
@ -116,7 +118,7 @@ void RocksDBReplicationContext::bind(TRI_vocbase_t* vocbase) {
void RocksDBReplicationContext::internalBind(TRI_vocbase_t* vocbase, void RocksDBReplicationContext::internalBind(TRI_vocbase_t* vocbase,
bool allowChange) { bool allowChange) {
if (!_trx || !_guard || (_guard->database() != vocbase)) { if (!_trx || !_guard || (&(_guard->database()) != vocbase)) {
TRI_ASSERT(allowChange); TRI_ASSERT(allowChange);
rocksdb::Snapshot const* snap = nullptr; rocksdb::Snapshot const* snap = nullptr;
if (_trx) { if (_trx) {
@ -177,7 +179,8 @@ int RocksDBReplicationContext::bindCollection(
int RocksDBReplicationContext::chooseDatabase(TRI_vocbase_t* vocbase) { int RocksDBReplicationContext::chooseDatabase(TRI_vocbase_t* vocbase) {
TRI_ASSERT(_users > 0); TRI_ASSERT(_users > 0);
MUTEX_LOCKER(locker, _contextLock); MUTEX_LOCKER(locker, _contextLock);
if (_guard->database() == vocbase) {
if (&(_guard->database()) == vocbase) {
return TRI_ERROR_NO_ERROR; // nothing to do here return TRI_ERROR_NO_ERROR; // nothing to do here
} }
@ -242,17 +245,23 @@ RocksDBReplicationResult RocksDBReplicationContext::dump(
} }
}; };
TRI_DEFER(release()); TRI_DEFER(release());
{ {
MUTEX_LOCKER(writeLocker, _contextLock); MUTEX_LOCKER(writeLocker, _contextLock);
TRI_ASSERT(vocbase != nullptr); TRI_ASSERT(vocbase != nullptr);
if (!_trx || !_guard || (_guard->database() != vocbase)) {
if (!_trx || !_guard || (&(_guard->database()) != vocbase)) {
return RocksDBReplicationResult(TRI_ERROR_BAD_PARAMETER, _lastTick); return RocksDBReplicationResult(TRI_ERROR_BAD_PARAMETER, _lastTick);
} }
TRI_voc_cid_t const id{::normalizeIdentifier(*_trx, collectionName)}; TRI_voc_cid_t const id{::normalizeIdentifier(*_trx, collectionName)};
if (0 == id) { if (0 == id) {
return RocksDBReplicationResult{TRI_ERROR_BAD_PARAMETER, _lastTick}; return RocksDBReplicationResult{TRI_ERROR_BAD_PARAMETER, _lastTick};
} }
collection = getCollectionIterator(id); collection = getCollectionIterator(id);
if (!collection) { if (!collection) {
return RocksDBReplicationResult(TRI_ERROR_BAD_PARAMETER, _lastTick); 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_vocbase_t* WalAccessContext::loadVocbase(TRI_voc_tick_t dbid) {
TRI_ASSERT(dbid != 0); TRI_ASSERT(dbid != 0);
auto const& it = _vocbases.find(dbid); auto const& it = _vocbases.find(dbid);
if (it == _vocbases.end()) { if (it == _vocbases.end()) {
TRI_vocbase_t* vocbase = DatabaseFeature::DATABASE->useDatabase(dbid); TRI_vocbase_t* vocbase = DatabaseFeature::DATABASE->useDatabase(dbid);
if (vocbase != nullptr) { if (vocbase != nullptr) {
TRI_DEFER(vocbase->release()); 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; return vocbase;
} else { } 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 /// @brief create a cursor repository
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
CursorRepository::CursorRepository(TRI_vocbase_t* vocbase) CursorRepository::CursorRepository(TRI_vocbase_t& vocbase)
: _vocbase(vocbase), _lock(), _cursors() { : _vocbase(vocbase), _lock(), _cursors() {
_cursors.reserve(64); _cursors.reserve(64);
} }

View File

@ -32,6 +32,7 @@
struct TRI_vocbase_t; struct TRI_vocbase_t;
namespace arangodb { namespace arangodb {
namespace velocypack { namespace velocypack {
class Builder; class Builder;
} }
@ -46,7 +47,7 @@ class CursorRepository {
/// @brief create a cursors repository /// @brief create a cursors repository
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
explicit CursorRepository(TRI_vocbase_t*); explicit CursorRepository(TRI_vocbase_t& vocbase);
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief destroy a cursors repository /// @brief destroy a cursors repository
@ -54,8 +55,6 @@ class CursorRepository {
~CursorRepository(); ~CursorRepository();
public:
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief stores a cursor in the registry /// @brief stores a cursor in the registry
/// the repository will take ownership of the cursor /// the repository will take ownership of the cursor
@ -121,7 +120,7 @@ class CursorRepository {
/// @brief vocbase /// @brief vocbase
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
TRI_vocbase_t* _vocbase; TRI_vocbase_t& _vocbase;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief mutex for the cursors repository /// @brief mutex for the cursors repository
@ -141,6 +140,7 @@ class CursorRepository {
static size_t const MaxCollectCount; static size_t const MaxCollectCount;
}; };
} }
#endif #endif

View File

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

View File

@ -32,17 +32,22 @@ namespace arangodb {
/// dropped while still using it. /// dropped while still using it.
class DatabaseGuard { class DatabaseGuard {
public: public:
DatabaseGuard(DatabaseGuard&&) = delete;
DatabaseGuard(DatabaseGuard const&) = delete; DatabaseGuard(DatabaseGuard const&) = delete;
DatabaseGuard& operator=(DatabaseGuard const&) = delete; DatabaseGuard& operator=(DatabaseGuard const&) = delete;
/// @brief create guard on existing db /// @brief create guard on existing db
explicit DatabaseGuard(TRI_vocbase_t* vocbase) : _vocbase(vocbase) { explicit DatabaseGuard(TRI_vocbase_t& vocbase): _vocbase(vocbase) {
TRI_ASSERT(vocbase != nullptr); if (!_vocbase.use()) {
if (!_vocbase->use()) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND); 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 /// @brief create the guard, using a database id
explicit DatabaseGuard(TRI_voc_tick_t id); explicit DatabaseGuard(TRI_voc_tick_t id);
@ -51,22 +56,18 @@ class DatabaseGuard {
/// @brief destroy the guard /// @brief destroy the guard
~DatabaseGuard() { ~DatabaseGuard() {
if (_vocbase != nullptr) { TRI_ASSERT(!_vocbase.isDangling());
TRI_ASSERT(!_vocbase->isDangling()); _vocbase.release();
_vocbase->release();
}
} }
DatabaseGuard(DatabaseGuard&&);
public:
/// @brief return the database pointer /// @brief return the database pointer
inline TRI_vocbase_t* database() const { return _vocbase; } inline TRI_vocbase_t& database() const { return _vocbase; }
private: private:
/// @brief pointer to database /// @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_vocbase_t* vocbase = GetContextVocBase(isolate);
TRI_ASSERT(vocbase != nullptr); // for clarity assert duplicated from v8-util.cpp GetContextVocBase(...)
for (std::string const& name : paramVertices) { for (std::string const& name : paramVertices) {
if (ss->isCoordinator()) { if (ss->isCoordinator()) {
try { try {
@ -1982,8 +1984,9 @@ static void JS_PregelStart(v8::FunctionCallbackInfo<v8::Value> const& args) {
} }
uint64_t en = pregel::PregelFeature::instance()->createExecutionNumber(); uint64_t en = pregel::PregelFeature::instance()->createExecutionNumber();
auto c = std::make_unique<pregel::Conductor>(en, vocbase, paramVertices, edgeColls, auto c = std::make_unique<pregel::Conductor>(
algorithm, paramBuilder.slice()); en, *vocbase, paramVertices, edgeColls, algorithm, paramBuilder.slice()
);
pregel::PregelFeature::instance()->addConductor(std::move(c), en); pregel::PregelFeature::instance()->addConductor(std::move(c), en);
TRI_ASSERT(pregel::PregelFeature::instance()->conductor(en)); TRI_ASSERT(pregel::PregelFeature::instance()->conductor(en));
pregel::PregelFeature::instance()->conductor(en)->start(); 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 { 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, 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 // get the permissions to be used by this task
bool allowContinue = true; bool allowContinue = true;
std::unique_ptr<ExecContext> execContext; std::unique_ptr<ExecContext> execContext;
if (!_user.empty()) { // not superuser if (!_user.empty()) { // not superuser
std::string const& dbname = _dbGuard->database()->name(); auto& dbname = _dbGuard->database().name();
execContext.reset(ExecContext::create(_user, dbname)); execContext.reset(ExecContext::create(_user, dbname));
allowContinue = execContext->canUseDatabase(dbname, auth::Level::RW); allowContinue = execContext->canUseDatabase(dbname, auth::Level::RW);
allowContinue = allowContinue && ServerState::writeOpsEnabled(); allowContinue = allowContinue && ServerState::writeOpsEnabled();
} }
ExecContextScope scope(_user.empty() ? ExecContextScope scope(_user.empty() ?
ExecContext::superuser() : execContext.get()); ExecContext::superuser() : execContext.get());
@ -412,12 +414,13 @@ void V8Task::toVelocyPack(VPackBuilder& builder) const {
builder.add("offset", VPackValue(_offset.count() / 1000000.0)); builder.add("offset", VPackValue(_offset.count() / 1000000.0));
builder.add("command", VPackValue(_command)); 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) { void V8Task::work(ExecContext const* exec) {
auto context = V8DealerFeature::DEALER->enterContext(_dbGuard->database(), auto context = V8DealerFeature::DEALER->enterContext(
_allowUseDatabase); &(_dbGuard->database()), _allowUseDatabase
);
// note: the context might be 0 in case of shut-down // note: the context might be 0 in case of shut-down
if (context == nullptr) { if (context == nullptr) {

View File

@ -191,7 +191,6 @@ static void SynchronizeReplication(
// treat the argument as an object from now on // treat the argument as an object from now on
v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(args[0]); v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(args[0]);
VPackBuilder builder; VPackBuilder builder;
int res = TRI_V8ToVPack(isolate, builder, args[0], false); int res = TRI_V8ToVPack(isolate, builder, args[0], false);
@ -222,10 +221,9 @@ static void SynchronizeReplication(
v8::Handle<v8::Object> result = v8::Object::New(isolate); v8::Handle<v8::Object> result = v8::Object::New(isolate);
std::unique_ptr<InitialSyncer> syncer; std::unique_ptr<InitialSyncer> syncer;
if (applierType == APPLIER_DATABASE) { if (applierType == APPLIER_DATABASE) {
// database-specific synchronization // database-specific synchronization
syncer.reset(new DatabaseInitialSyncer(vocbase, configuration)); syncer.reset(new DatabaseInitialSyncer(*vocbase, configuration));
if (object->Has(TRI_V8_ASCII_STRING(isolate, "leaderId"))) { if (object->Has(TRI_V8_ASCII_STRING(isolate, "leaderId"))) {
syncer->setLeaderId(TRI_ObjectToString(object->Get(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), _deadlockDetector(false),
_userStructures(nullptr) { _userStructures(nullptr) {
_queries.reset(new arangodb::aql::QueryList(this)); _queries.reset(new arangodb::aql::QueryList(this));
_cursorRepository.reset(new arangodb::CursorRepository(this)); _cursorRepository.reset(new arangodb::CursorRepository(*this));
_collectionKeys.reset(new arangodb::CollectionKeysRepository()); _collectionKeys.reset(new arangodb::CollectionKeysRepository());
// init collections // init collections
@ -1856,7 +1856,8 @@ bool TRI_vocbase_t::IsAllowedName(
} }
void TRI_vocbase_t::addReplicationApplier() { void TRI_vocbase_t::addReplicationApplier() {
DatabaseReplicationApplier* applier = DatabaseReplicationApplier::create(this); auto* applier = DatabaseReplicationApplier::create(*this);
_replicationApplier.reset(applier); _replicationApplier.reset(applier);
} }
@ -1866,6 +1867,7 @@ void TRI_vocbase_t::updateReplicationClient(TRI_server_id_t serverId, double ttl
if (ttl <= 0.0) { if (ttl <= 0.0) {
ttl = InitialSyncer::defaultBatchTimeout; ttl = InitialSyncer::defaultBatchTimeout;
} }
double const expires = TRI_microtime() + ttl; double const expires = TRI_microtime() + ttl;
WRITE_LOCKER(writeLocker, _replicationClientsLock); WRITE_LOCKER(writeLocker, _replicationClientsLock);