1
0
Fork 0

some vocbase refactoring

This commit is contained in:
jsteemann 2016-07-28 11:06:21 +02:00
parent cc5eaea09c
commit b71e12f6a0
36 changed files with 223 additions and 305 deletions

View File

@ -82,13 +82,11 @@ static_assert(sizeof(StateNames) / sizeof(std::string) ==
/// @brief create a profile
Profile::Profile(Query* query)
: query(query), results(), stamp(query->startTime()), tracked(false) {
auto queryList = static_cast<QueryList*>(query->vocbase()->_queries);
auto queryList = query->vocbase()->queryList();
if (queryList != nullptr) {
try {
tracked = queryList->insert(query, stamp);
} catch (...) {
}
try {
tracked = queryList->insert(query, stamp);
} catch (...) {
}
}
@ -96,13 +94,11 @@ Profile::Profile(Query* query)
Profile::~Profile() {
// only remove from list when the query was inserted into it...
if (tracked) {
auto queryList = static_cast<QueryList*>(query->vocbase()->_queries);
auto queryList = query->vocbase()->queryList();
if (queryList != nullptr) {
try {
queryList->remove(query, stamp);
} catch (...) {
}
try {
queryList->remove(query, stamp);
} catch (...) {
}
}
}

View File

@ -106,8 +106,7 @@ DBServerAgencySyncResult DBServerAgencySync::execute() {
auto plan = clusterInfo->getPlan();
auto current = clusterInfo->getCurrent();
TRI_UseVocBase(vocbase);
TRI_DEFER(TRI_ReleaseVocBase(vocbase));
VocbaseGuard guard(vocbase);
V8Context* context = V8DealerFeature::DEALER->enterContext(vocbase, true);

View File

@ -534,7 +534,7 @@ bool HeartbeatThread::handlePlanChangeCoordinator(uint64_t currentPlanVersion) {
HasRunOnce = true;
}
} else {
TRI_ReleaseVocBase(vocbase);
vocbase->release();
}
}

View File

@ -215,7 +215,7 @@ void RestCursorHandler::processQuery(VPackSlice const& slice) {
}
// result is bigger than batchSize, and a cursor will be created
auto cursors = _vocbase->_cursorRepository;
auto cursors = _vocbase->cursorRepository();
TRI_ASSERT(cursors != nullptr);
double ttl = arangodb::basics::VelocyPackHelper::getNumericValue<double>(
@ -456,8 +456,7 @@ void RestCursorHandler::modifyCursor() {
std::string const& id = suffix[0];
auto cursors =
static_cast<arangodb::CursorRepository*>(_vocbase->_cursorRepository);
auto cursors = _vocbase->cursorRepository();
TRI_ASSERT(cursors != nullptr);
auto cursorId = static_cast<arangodb::CursorId>(
@ -526,8 +525,7 @@ void RestCursorHandler::deleteCursor() {
std::string const& id = suffix[0];
auto cursors =
static_cast<arangodb::CursorRepository*>(_vocbase->_cursorRepository);
auto cursors = _vocbase->cursorRepository();
TRI_ASSERT(cursors != nullptr);
auto cursorId = static_cast<arangodb::CursorId>(

View File

@ -274,8 +274,7 @@ void RestExportHandler::createCursor() {
// TODO: generalize to calling handler setPayload
response->setContentType(HttpResponse::ContentType::JSON);
auto cursors =
static_cast<arangodb::CursorRepository*>(_vocbase->_cursorRepository);
auto cursors = _vocbase->cursorRepository();
TRI_ASSERT(cursors != nullptr);
// create a cursor from the result
@ -318,8 +317,7 @@ void RestExportHandler::modifyCursor() {
std::string const& id = suffix[0];
auto cursors =
static_cast<arangodb::CursorRepository*>(_vocbase->_cursorRepository);
auto cursors = _vocbase->cursorRepository();
TRI_ASSERT(cursors != nullptr);
auto cursorId = static_cast<arangodb::CursorId>(
@ -383,8 +381,7 @@ void RestExportHandler::deleteCursor() {
std::string const& id = suffix[0];
auto cursors =
static_cast<arangodb::CursorRepository*>(_vocbase->_cursorRepository);
auto cursors = _vocbase->cursorRepository();
TRI_ASSERT(cursors != nullptr);
auto cursorId = static_cast<arangodb::CursorId>(

View File

@ -92,7 +92,7 @@ RestHandler::status RestQueryHandler::execute() {
bool RestQueryHandler::readQueryProperties() {
try {
auto queryList = static_cast<QueryList*>(_vocbase->_queries);
auto queryList = _vocbase->queryList();
VPackBuilder result;
result.add(VPackValue(VPackValueType::Object));
@ -124,7 +124,7 @@ bool RestQueryHandler::readQueryProperties() {
bool RestQueryHandler::readQuery(bool slow) {
try {
auto queryList = static_cast<QueryList*>(_vocbase->_queries);
auto queryList = _vocbase->queryList();
auto queries = slow ? queryList->listSlow() : queryList->listCurrent();
VPackBuilder result;
@ -192,7 +192,7 @@ bool RestQueryHandler::readQuery() {
}
bool RestQueryHandler::deleteQuerySlow() {
auto queryList = static_cast<arangodb::aql::QueryList*>(_vocbase->_queries);
auto queryList = _vocbase->queryList();
queryList->clearSlow();
VPackBuilder result;
@ -208,7 +208,7 @@ bool RestQueryHandler::deleteQuerySlow() {
bool RestQueryHandler::deleteQuery(std::string const& name) {
auto id = StringUtils::uint64(name);
auto queryList = static_cast<arangodb::aql::QueryList*>(_vocbase->_queries);
auto queryList = _vocbase->queryList();
TRI_ASSERT(queryList != nullptr);
auto res = queryList->kill(id);
@ -276,7 +276,7 @@ bool RestQueryHandler::replaceProperties() {
"expecting a JSON object as body");
};
auto queryList = static_cast<arangodb::aql::QueryList*>(_vocbase->_queries);
auto queryList = _vocbase->queryList();
try {
bool enabled = queryList->enabled();

View File

@ -2798,7 +2798,7 @@ void RestReplicationHandler::handleCommandCreateKeys() {
keys->create(tickEnd);
size_t const count = keys->count();
auto keysRepository = _vocbase->_collectionKeys;
auto keysRepository = _vocbase->collectionKeys();
try {
keysRepository->store(keys.get());
@ -2859,7 +2859,7 @@ void RestReplicationHandler::handleCommandGetKeys() {
int res = TRI_ERROR_NO_ERROR;
try {
auto keysRepository = _vocbase->_collectionKeys;
auto keysRepository = _vocbase->collectionKeys();
TRI_ASSERT(keysRepository != nullptr);
auto collectionKeysId = static_cast<arangodb::CollectionKeysId>(
@ -2973,7 +2973,7 @@ void RestReplicationHandler::handleCommandFetchKeys() {
int res = TRI_ERROR_NO_ERROR;
try {
auto keysRepository = _vocbase->_collectionKeys;
auto keysRepository = _vocbase->collectionKeys();
TRI_ASSERT(keysRepository != nullptr);
auto collectionKeysId = static_cast<arangodb::CollectionKeysId>(
@ -3046,7 +3046,7 @@ void RestReplicationHandler::handleCommandRemoveKeys() {
std::string const& id = suffix[1];
auto keys = _vocbase->_collectionKeys;
auto keys = _vocbase->collectionKeys();
TRI_ASSERT(keys != nullptr);
auto collectionKeysId = static_cast<arangodb::CollectionKeysId>(

View File

@ -174,8 +174,8 @@ void BootstrapFeature::unprepare() {
TRI_vocbase_t* vocbase = databaseFeature->useDatabase(id);
if (vocbase != nullptr) {
vocbase->_queries->killAll(true);
TRI_ReleaseVocBase(vocbase);
vocbase->queryList()->killAll(true);
vocbase->release();
}
}
} else {
@ -183,8 +183,8 @@ void BootstrapFeature::unprepare() {
TRI_vocbase_t* vocbase = databaseFeature->useDatabase(name);
if (vocbase != nullptr) {
vocbase->_queries->killAll(true);
TRI_ReleaseVocBase(vocbase);
vocbase->queryList()->killAll(true);
vocbase->release();
}
}
}

View File

@ -89,7 +89,7 @@ void DatabaseManagerThread::run() {
auto theLists = databaseFeature->_databasesLists.load();
for (TRI_vocbase_t* vocbase : theLists->_droppedDatabases) {
if (!TRI_CanRemoveVocBase(vocbase)) {
if (!vocbase->canBeDropped()) {
continue;
}
@ -205,7 +205,7 @@ void DatabaseManagerThread::run() {
for (auto& p : theLists->_coordinatorDatabases) {
TRI_vocbase_t* vocbase = p.second;
TRI_ASSERT(vocbase != nullptr);
auto cursorRepository = vocbase->_cursorRepository;
auto cursorRepository = vocbase->cursorRepository();
try {
cursorRepository->garbageCollect(false);
@ -460,7 +460,7 @@ int DatabaseFeature::createDatabaseCoordinator(TRI_voc_tick_t id, std::string co
}
// increase reference counter
TRI_UseVocBase(vocbase.get());
vocbase->use();
vocbase->_state = (sig_atomic_t)TRI_VOCBASE_STATE_NORMAL;
{
@ -569,7 +569,7 @@ int DatabaseFeature::createDatabase(TRI_voc_tick_t id, std::string const& name,
}
// increase reference counter
TRI_UseVocBase(vocbase.get());
vocbase->use();
}
{
@ -634,7 +634,7 @@ int DatabaseFeature::dropDatabaseCoordinator(TRI_voc_tick_t id, bool force) {
_databasesProtector.scan();
delete oldLists;
if (TRI_DropVocBase(vocbase)) {
if (vocbase->markAsDropped()) {
LOG(INFO) << "dropping coordinator database '" << vocbase->name() << "'";
res = TRI_ERROR_NO_ERROR;
}
@ -691,7 +691,7 @@ int DatabaseFeature::dropDatabase(std::string const& name, bool writeMarker, boo
// invalidate all entries for the database
arangodb::aql::QueryCache::instance()->invalidate(vocbase);
if (!TRI_DropVocBase(vocbase)) {
if (!vocbase->markAsDropped()) {
// deleted by someone else?
return TRI_ERROR_ARANGO_DATABASE_NOT_FOUND;
}
@ -837,7 +837,7 @@ TRI_vocbase_t* DatabaseFeature::useDatabaseCoordinator(TRI_voc_tick_t id) {
TRI_vocbase_t* vocbase = p.second;
if (vocbase->_id == id) {
bool result TRI_UNUSED = TRI_UseVocBase(vocbase);
bool result TRI_UNUSED = vocbase->use();
// if we got here, no one else can have deleted the database
TRI_ASSERT(result == true);
@ -851,30 +851,30 @@ TRI_vocbase_t* DatabaseFeature::useDatabaseCoordinator(std::string const& name)
auto unuser(_databasesProtector.use());
auto theLists = _databasesLists.load();
TRI_vocbase_t* vocbase = nullptr;
auto it = theLists->_coordinatorDatabases.find(name);
if (it != theLists->_coordinatorDatabases.end()) {
vocbase = it->second;
TRI_UseVocBase(vocbase);
TRI_vocbase_t* vocbase = it->second;
vocbase->use();
return vocbase;
}
return vocbase;
return nullptr;
}
TRI_vocbase_t* DatabaseFeature::useDatabase(std::string const& name) {
auto unuser(_databasesProtector.use());
auto theLists = _databasesLists.load();
TRI_vocbase_t* vocbase = nullptr;
auto it = theLists->_databases.find(name);
if (it != theLists->_databases.end()) {
vocbase = it->second;
TRI_UseVocBase(vocbase);
TRI_vocbase_t* vocbase = it->second;
vocbase->use();
return vocbase;
}
return vocbase;
return nullptr;
}
TRI_vocbase_t* DatabaseFeature::useDatabase(TRI_voc_tick_t id) {
@ -885,7 +885,7 @@ TRI_vocbase_t* DatabaseFeature::useDatabase(TRI_voc_tick_t id) {
TRI_vocbase_t* vocbase = p.second;
if (vocbase->_id == id) {
TRI_UseVocBase(vocbase);
vocbase->use();
return vocbase;
}
}
@ -893,12 +893,6 @@ TRI_vocbase_t* DatabaseFeature::useDatabase(TRI_voc_tick_t id) {
return nullptr;
}
/// @brief release a previously used database
/// this will decrease the reference-counter for the database
void DatabaseFeature::releaseDatabase(TRI_vocbase_t* vocbase) {
TRI_ReleaseVocBase(vocbase);
}
/// @brief lookup a database by its name, not increasing its reference count
TRI_vocbase_t* DatabaseFeature::lookupDatabase(std::string const& name) {
auto unuser(_databasesProtector.use());

View File

@ -94,7 +94,6 @@ class DatabaseFeature final : public application_features::ApplicationFeature {
TRI_vocbase_t* useDatabaseCoordinator(TRI_voc_tick_t id);
TRI_vocbase_t* useDatabase(std::string const& name);
TRI_vocbase_t* useDatabase(TRI_voc_tick_t id);
void releaseDatabase(TRI_vocbase_t* vocbase);
TRI_vocbase_t* lookupDatabase(std::string const& name);

View File

@ -51,7 +51,7 @@ VocbaseContext::VocbaseContext(GeneralRequest* request, TRI_vocbase_t* vocbase,
TRI_ASSERT(_vocbase != nullptr);
}
VocbaseContext::~VocbaseContext() { TRI_ReleaseVocBase(_vocbase); }
VocbaseContext::~VocbaseContext() { _vocbase->release(); }
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not to use special cluster authentication

View File

@ -79,7 +79,7 @@ class MMFilesEngine final : public StorageEngine {
uint64_t getMaxRevision() override;
// return the path for a database
std::string databasePath(TRI_vocbase_t* vocbase) const override { return databaseDirectory(vocbase->_id); }
std::string databasePath(TRI_vocbase_t const* vocbase) const override { return databaseDirectory(vocbase->_id); }
TRI_vocbase_t* openDatabase(arangodb::velocypack::Slice const& parameters, bool isUpgrade) override;

View File

@ -68,7 +68,7 @@ class OtherEngine final : public StorageEngine {
uint64_t getMaxRevision() override;
// return the path for a database
std::string databasePath(TRI_vocbase_t*) const override { return "none"; }
std::string databasePath(TRI_vocbase_t const*) const override { return "none"; }
TRI_vocbase_t* openDatabase(arangodb::velocypack::Slice const& parameters, bool isUpgrade) override {
return nullptr;

View File

@ -85,7 +85,7 @@ class StorageEngine : public application_features::ApplicationFeature {
virtual uint64_t getMaxRevision() = 0;
// return the path for a database
virtual std::string databasePath(TRI_vocbase_t* vocbase) const = 0;
virtual std::string databasePath(TRI_vocbase_t const* vocbase) const = 0;
virtual TRI_vocbase_t* openDatabase(arangodb::velocypack::Slice const& parameters, bool isUpgrade) = 0;

View File

@ -68,16 +68,11 @@ VelocyPackCursor::VelocyPackCursor(TRI_vocbase_t* vocbase, CursorId id,
std::shared_ptr<VPackBuilder> extra,
double ttl, bool hasCount)
: Cursor(id, batchSize, extra, ttl, hasCount),
_vocbase(vocbase),
_vocbaseGuard(vocbase),
_result(std::move(result)),
_iterator(_result.result->slice()),
_cached(_result.cached) {
TRI_ASSERT(_result.result->slice().isArray());
TRI_UseVocBase(vocbase);
}
VelocyPackCursor::~VelocyPackCursor() {
TRI_ReleaseVocBase(_vocbase);
}
////////////////////////////////////////////////////////////////////////////////
@ -200,15 +195,13 @@ ExportCursor::ExportCursor(TRI_vocbase_t* vocbase, CursorId id,
arangodb::CollectionExport* ex, size_t batchSize,
double ttl, bool hasCount)
: Cursor(id, batchSize, nullptr, ttl, hasCount),
_vocbase(vocbase),
_vocbaseGuard(vocbase),
_ex(ex),
_size(ex->_documents->size()) {
TRI_UseVocBase(vocbase);
}
ExportCursor::~ExportCursor() {
delete _ex;
TRI_ReleaseVocBase(_vocbase);
}
////////////////////////////////////////////////////////////////////////////////
@ -272,7 +265,7 @@ static bool IncludeAttribute(
////////////////////////////////////////////////////////////////////////////////
void ExportCursor::dump(arangodb::basics::StringBuffer& buffer) {
auto transactionContext = std::make_shared<StandaloneTransactionContext>(_vocbase);
auto transactionContext = std::make_shared<StandaloneTransactionContext>(_vocbaseGuard.vocbase());
VPackOptions* options = transactionContext->getVPackOptions();
TRI_ASSERT(_ex != nullptr);

View File

@ -28,11 +28,10 @@
#include "Basics/StringBuffer.h"
#include "Aql/QueryResult.h"
#include "VocBase/voc-types.h"
#include "VocBase/vocbase.h"
#include <velocypack/Iterator.h>
struct TRI_vocbase_t;
namespace arangodb {
namespace velocypack {
class Builder;
@ -116,7 +115,7 @@ class VelocyPackCursor : public Cursor {
std::shared_ptr<arangodb::velocypack::Builder>, double,
bool);
~VelocyPackCursor();
~VelocyPackCursor() = default;
public:
bool hasNext() override final;
@ -128,7 +127,7 @@ class VelocyPackCursor : public Cursor {
void dump(arangodb::basics::StringBuffer&) override final;
private:
TRI_vocbase_t* _vocbase;
VocbaseGuard _vocbaseGuard;
aql::QueryResult _result;
arangodb::velocypack::ArrayIterator _iterator;
bool _cached;
@ -151,7 +150,7 @@ class ExportCursor : public Cursor {
void dump(arangodb::basics::StringBuffer&) override final;
private:
TRI_vocbase_t* _vocbase;
VocbaseGuard _vocbaseGuard;
arangodb::CollectionExport* _ex;
size_t const _size;
};

View File

@ -21,8 +21,8 @@
/// @author Jan Steemann
////////////////////////////////////////////////////////////////////////////////
#ifndef ARANGOD_UTILS_DATABASE_GUARD_H
#define ARANGOD_UTILS_DATABASE_GUARD_H 1
#ifndef ARANGOD_UTILS_vocbase_GUARD_H
#define ARANGOD_UTILS_vocbase_GUARD_H 1
#include "ApplicationFeatures/ApplicationServer.h"
#include "Basics/Exceptions.h"
@ -42,12 +42,12 @@ class DatabaseGuard {
//////////////////////////////////////////////////////////////////////////////
explicit DatabaseGuard(TRI_voc_tick_t id)
: _database(nullptr) {
: _vocbase(nullptr) {
auto databaseFeature = application_features::ApplicationServer::getFeature<DatabaseFeature>("Database");
_database = databaseFeature->useDatabase(id);
_vocbase = databaseFeature->useDatabase(id);
if (_database == nullptr) {
if (_vocbase == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
}
@ -56,13 +56,13 @@ class DatabaseGuard {
/// @brief create the guard, using a database name
//////////////////////////////////////////////////////////////////////////////
explicit DatabaseGuard(char const* name)
: _database(nullptr) {
explicit DatabaseGuard(std::string const& name)
: _vocbase(nullptr) {
auto databaseFeature = application_features::ApplicationServer::getFeature<DatabaseFeature>("Database");
_database = databaseFeature->useDatabase(name);
_vocbase = databaseFeature->useDatabase(name);
if (_database == nullptr) {
if (_vocbase == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
}
@ -72,10 +72,8 @@ class DatabaseGuard {
//////////////////////////////////////////////////////////////////////////////
~DatabaseGuard() {
if (_database != nullptr) {
auto databaseFeature = application_features::ApplicationServer::getFeature<DatabaseFeature>("Database");
databaseFeature->releaseDatabase(_database);
}
TRI_ASSERT(_vocbase != nullptr);
_vocbase->release();
}
public:
@ -83,7 +81,7 @@ class DatabaseGuard {
/// @brief return the database pointer
//////////////////////////////////////////////////////////////////////////////
inline TRI_vocbase_t* database() const { return _database; }
inline TRI_vocbase_t* database() const { return _vocbase; }
private:
@ -91,7 +89,7 @@ class DatabaseGuard {
/// @brief pointer to database
//////////////////////////////////////////////////////////////////////////////
TRI_vocbase_t* _database;
TRI_vocbase_t* _vocbase;
};
}

View File

@ -24,8 +24,6 @@
#ifndef ARANGOD_UTILS_REPLICATION_TRANSACTION_H
#define ARANGOD_UTILS_REPLICATION_TRANSACTION_H 1
#include "ApplicationFeatures/ApplicationServer.h"
#include "RestServer/DatabaseFeature.h"
#include "Utils/StandaloneTransactionContext.h"
#include "Utils/Transaction.h"
#include "VocBase/ticks.h"
@ -37,25 +35,15 @@ namespace arangodb {
class ReplicationTransaction : public Transaction {
public:
//////////////////////////////////////////////////////////////////////////////
/// @brief create the transaction
//////////////////////////////////////////////////////////////////////////////
ReplicationTransaction(TRI_vocbase_t* vocbase)
: Transaction(StandaloneTransactionContext::Create(vocbase)) {
auto databaseFeature = application_features::ApplicationServer::getFeature<DatabaseFeature>("Database");
databaseFeature->useDatabase(vocbase->name());
_vocbase->use();
}
//////////////////////////////////////////////////////////////////////////////
/// @brief end the transaction
//////////////////////////////////////////////////////////////////////////////
~ReplicationTransaction() {
auto databaseFeature = application_features::ApplicationServer::getFeature<DatabaseFeature>("Database");
databaseFeature->releaseDatabase(vocbase());
}
~ReplicationTransaction() { _vocbase->release(); }
public:

View File

@ -95,7 +95,7 @@ bool WorkMonitor::cancelAql(WorkDescription* desc) {
LOG(WARN) << "cancel query " << id << " in " << vocbase;
auto queryList = static_cast<arangodb::aql::QueryList*>(vocbase->_queries);
auto queryList = vocbase->queryList();
auto res = queryList->kill(id);
if (res != TRI_ERROR_NO_ERROR) {

View File

@ -87,7 +87,7 @@ void V8Context::handleGlobalContextMethods() {
}
for (auto& type : copy) {
std::string func = GlobalContextMethods::code(type);
std::string const& func = GlobalContextMethods::code(type);
LOG(DEBUG) << "executing global context method '" << func
<< "' for context " << _id;

View File

@ -29,6 +29,7 @@
#include <v8.h>
#include "Basics/Mutex.h"
#include "Basics/StaticStrings.h"
namespace arangodb {
class GlobalContextMethods {
@ -81,7 +82,7 @@ class GlobalContextMethods {
}
}
static std::string const code(MethodType type) {
static std::string const& code(MethodType type) {
switch (type) {
case MethodType::RELOAD_ROUTING:
return CodeReloadRouting;
@ -95,7 +96,7 @@ class GlobalContextMethods {
return CodeWarmupExports;
case MethodType::UNKNOWN:
default:
return "";
return StaticStrings::Empty;
}
}

View File

@ -545,10 +545,14 @@ V8Context* V8DealerFeature::enterContext(TRI_vocbase_t* vocbase,
v8g->_vocbase = vocbase;
v8g->_allowUseDatabase = allowUseDatabase;
TRI_UseVocBase(vocbase);
vocbase->use();
LOG(TRACE) << "entering V8 context " << context->_id;
context->handleGlobalContextMethods();
try {
LOG(TRACE) << "entering V8 context " << context->_id;
context->handleGlobalContextMethods();
} catch (...) {
// ignore errors here
}
}
}
@ -578,7 +582,7 @@ void V8DealerFeature::exitContext(V8Context* context) {
TRI_ASSERT(vocbase != nullptr);
// release last recently used vocbase
TRI_ReleaseVocBase(vocbase);
vocbase->release();
// check for cancelation requests
canceled = v8g->_canceled;

View File

@ -34,7 +34,6 @@
#include "V8Server/V8Context.h"
#include "V8Server/V8DealerFeature.h"
#include "V8Server/V8PeriodicTask.h"
#include "VocBase/vocbase.h"
using namespace arangodb;
using namespace arangodb::basics;
@ -48,13 +47,12 @@ V8Job::V8Job(TRI_vocbase_t* vocbase, std::string const& command,
std::shared_ptr<VPackBuilder> parameters, bool allowUseDatabase,
Task* task)
: Job("V8 Job"),
_vocbase(vocbase),
_vocbaseGuard(vocbase),
_command(command),
_parameters(parameters),
_canceled(false),
_allowUseDatabase(allowUseDatabase),
_task(task) {
TRI_UseVocBase(vocbase);
}
////////////////////////////////////////////////////////////////////////////////
@ -62,8 +60,6 @@ V8Job::V8Job(TRI_vocbase_t* vocbase, std::string const& command,
////////////////////////////////////////////////////////////////////////////////
V8Job::~V8Job() {
TRI_ReleaseVocBase(_vocbase);
if (_task != nullptr) {
V8PeriodicTask::jobDone(_task);
}
@ -75,7 +71,7 @@ void V8Job::work() {
}
auto context =
V8DealerFeature::DEALER->enterContext(_vocbase, _allowUseDatabase);
V8DealerFeature::DEALER->enterContext(_vocbaseGuard.vocbase(), _allowUseDatabase);
// note: the context might be 0 in case of shut-down
if (context == nullptr) {

View File

@ -26,8 +26,7 @@
#include "Basics/Common.h"
#include "Dispatcher/Job.h"
struct TRI_vocbase_t;
#include "VocBase/vocbase.h"
namespace arangodb {
namespace rest {
@ -53,7 +52,8 @@ class V8Job : public rest::Job {
virtual std::string const& getName() const override { return _command; }
private:
TRI_vocbase_t* _vocbase;
/// @brief guard to make sure the database is not dropped while used by us
VocbaseGuard _vocbaseGuard;
std::string const _command;
std::shared_ptr<arangodb::velocypack::Builder> _parameters;
std::atomic<bool> _canceled;

View File

@ -54,20 +54,11 @@ V8PeriodicTask::V8PeriodicTask(std::string const& id, std::string const& name,
bool allowUseDatabase)
: Task(id, name),
PeriodicTask(id, offset, period),
_vocbase(vocbase),
_vocbaseGuard(vocbase),
_command(command),
_parameters(parameters),
_created(TRI_microtime()),
_allowUseDatabase(allowUseDatabase) {
TRI_ASSERT(vocbase != nullptr);
// increase reference counter for the database used
TRI_UseVocBase(_vocbase);
}
V8PeriodicTask::~V8PeriodicTask() {
// decrease reference counter for the database used
TRI_ReleaseVocBase(_vocbase);
}
// get a task specific description in JSON format
@ -77,7 +68,7 @@ void V8PeriodicTask::getDescription(VPackBuilder& builder) const {
builder.add("created", VPackValue(_created));
builder.add("command", VPackValue(_command));
builder.add("database", VPackValue(_vocbase->name()));
builder.add("database", VPackValue(_vocbaseGuard.vocbase()->name()));
}
// handles the next tick
@ -99,7 +90,7 @@ bool V8PeriodicTask::handlePeriod() {
}
std::unique_ptr<Job> job(new V8Job(
_vocbase, "(function (params) { " + _command + " } )(params);",
_vocbaseGuard.vocbase(), "(function (params) { " + _command + " } )(params);",
_parameters, _allowUseDatabase, this));
DispatcherFeature::DISPATCHER->addJob(job, false);

View File

@ -39,7 +39,7 @@ class V8PeriodicTask : public rest::PeriodicTask {
double, std::string const&,
std::shared_ptr<arangodb::velocypack::Builder>, bool);
~V8PeriodicTask();
~V8PeriodicTask() = default;
public:
static void jobDone(Task*);
@ -56,7 +56,8 @@ class V8PeriodicTask : public rest::PeriodicTask {
static std::unordered_set<Task*> RUNNING;
private:
TRI_vocbase_t* _vocbase;
/// @brief guard to make sure the database is not dropped while used by us
VocbaseGuard _vocbaseGuard;
std::string const _command;
std::shared_ptr<arangodb::velocypack::Builder> _parameters;
double _created;

View File

@ -46,20 +46,11 @@ V8TimerTask::V8TimerTask(std::string const& id, std::string const& name,
// greater than zero,
// otherwise
// the timertask will not execute the task at all
_vocbase(vocbase),
_vocbaseGuard(vocbase),
_command(command),
_parameters(parameters),
_created(TRI_microtime()),
_allowUseDatabase(allowUseDatabase) {
TRI_ASSERT(vocbase != nullptr);
// increase reference counter for the database used
TRI_UseVocBase(_vocbase);
}
V8TimerTask::~V8TimerTask() {
// decrease reference counter for the database used
TRI_ReleaseVocBase(_vocbase);
}
////////////////////////////////////////////////////////////////////////////////
@ -70,7 +61,7 @@ void V8TimerTask::getDescription(VPackBuilder& builder) const {
TimerTask::getDescription(builder);
builder.add("created", VPackValue(_created));
builder.add("command", VPackValue(_command));
builder.add("database", VPackValue(_vocbase->name()));
builder.add("database", VPackValue(_vocbaseGuard.vocbase()->name()));
}
////////////////////////////////////////////////////////////////////////////////
@ -81,7 +72,7 @@ bool V8TimerTask::handleTimeout() {
TRI_ASSERT(DispatcherFeature::DISPATCHER != nullptr);
std::unique_ptr<Job> job(
new V8Job(_vocbase, "(function (params) { " + _command + " } )(params);",
new V8Job(_vocbaseGuard.vocbase(), "(function (params) { " + _command + " } )(params);",
_parameters, _allowUseDatabase, nullptr));
if (DispatcherFeature::DISPATCHER == nullptr) {

View File

@ -44,7 +44,7 @@ class V8TimerTask : public rest::TimerTask {
std::string const&,
std::shared_ptr<arangodb::velocypack::Builder>, bool);
~V8TimerTask();
~V8TimerTask() = default;
protected:
//////////////////////////////////////////////////////////////////////////////
@ -67,11 +67,8 @@ class V8TimerTask : public rest::TimerTask {
bool handleTimeout() override;
private:
//////////////////////////////////////////////////////////////////////////////
/// @brief system vocbase
//////////////////////////////////////////////////////////////////////////////
TRI_vocbase_t* _vocbase;
/// @brief guard to make sure the database is not dropped while used by us
VocbaseGuard _vocbaseGuard;
//////////////////////////////////////////////////////////////////////////////
/// @brief command to execute

View File

@ -115,7 +115,7 @@ static void WeakCollectionCallback(const v8::WeakCallbackData<
v8g->decreaseActiveExternals();
// decrease the reference-counter for the database
TRI_ReleaseVocBase(collection->_vocbase);
collection->_vocbase->release();
// find the persistent handle
#if ARANGODB_ENABLE_MAINTAINER_MODE
@ -157,15 +157,20 @@ v8::Handle<v8::Object> WrapCollection(v8::Isolate* isolate,
if (it == v8g->JSCollections.end()) {
// increase the reference-counter for the database
TRI_UseVocBase(collection->_vocbase);
auto externalCollection = v8::External::New(isolate, nonconstCollection);
collection->_vocbase->use();
try {
auto externalCollection = v8::External::New(isolate, nonconstCollection);
result->SetInternalField(SLOT_COLLECTION, externalCollection);
result->SetInternalField(SLOT_COLLECTION, externalCollection);
v8g->JSCollections[nonconstCollection].Reset(isolate, externalCollection);
v8g->JSCollections[nonconstCollection].SetWeak(
&v8g->JSCollections[nonconstCollection], WeakCollectionCallback);
v8g->increaseActiveExternals();
v8g->JSCollections[nonconstCollection].Reset(isolate, externalCollection);
v8g->JSCollections[nonconstCollection].SetWeak(
&v8g->JSCollections[nonconstCollection], WeakCollectionCallback);
v8g->increaseActiveExternals();
} catch (...) {
collection->_vocbase->release();
throw;
}
} else {
auto myCollection = v8::Local<v8::External>::New(isolate, it->second);

View File

@ -2097,7 +2097,7 @@ static void JS_SaveVocbase(v8::FunctionCallbackInfo<v8::Value> const& args) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
if (TRI_IsDeletedVocBase(vocbase)) {
if (vocbase->isDropped()) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
@ -2688,7 +2688,7 @@ static void JS_CollectionVocbase(
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
if (TRI_IsDeletedVocBase(vocbase)) {
if (vocbase->isDropped()) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}

View File

@ -1366,7 +1366,7 @@ static void JS_QueriesPropertiesAql(
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
auto queryList = static_cast<arangodb::aql::QueryList*>(vocbase->_queries);
auto queryList = vocbase->queryList();
TRI_ASSERT(queryList != nullptr);
if (args.Length() > 1) {
@ -1442,7 +1442,7 @@ static void JS_QueriesCurrentAql(
TRI_V8_THROW_EXCEPTION_USAGE("AQL_QUERIES_CURRENT()");
}
auto queryList = static_cast<arangodb::aql::QueryList*>(vocbase->_queries);
auto queryList = vocbase->queryList();
TRI_ASSERT(queryList != nullptr);
try {
@ -1486,7 +1486,7 @@ static void JS_QueriesSlowAql(v8::FunctionCallbackInfo<v8::Value> const& args) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
auto queryList = static_cast<arangodb::aql::QueryList*>(vocbase->_queries);
auto queryList = vocbase->queryList();
TRI_ASSERT(queryList != nullptr);
if (args.Length() == 1) {
@ -1545,7 +1545,7 @@ static void JS_QueriesKillAql(v8::FunctionCallbackInfo<v8::Value> const& args) {
auto id = TRI_ObjectToUInt64(args[0], true);
auto queryList = static_cast<arangodb::aql::QueryList*>(vocbase->_queries);
auto queryList = vocbase->queryList();
TRI_ASSERT(queryList != nullptr);
auto res = queryList->kill(id);
@ -2042,7 +2042,7 @@ static void JS_UseDatabase(v8::FunctionCallbackInfo<v8::Value> const& args) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_INTERNAL);
}
if (TRI_IsDeletedVocBase(vocbase)) {
if (vocbase->isDropped()) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
@ -2068,7 +2068,7 @@ static void JS_UseDatabase(v8::FunctionCallbackInfo<v8::Value> const& args) {
v8g->_vocbase = vocbase;
TRI_ASSERT(orig != vocbase);
databaseFeature->releaseDatabase(static_cast<TRI_vocbase_t*>(orig));
static_cast<TRI_vocbase_t*>(orig)->release();
TRI_V8_RETURN(WrapVocBase(isolate, vocbase));
}
@ -2305,7 +2305,7 @@ static void CreateDatabaseCoordinator(
// and switch back
v8g->_vocbase = orig;
TRI_ReleaseVocBase(vocbase);
vocbase->release();
TRI_V8_RETURN_TRUE();
}
@ -2394,7 +2394,7 @@ static void JS_CreateDatabase(v8::FunctionCallbackInfo<v8::Value> const& args) {
v8g->_vocbase = orig;
// finally decrease the reference-counter
TRI_ReleaseVocBase(database);
database->release();
TRI_V8_RETURN_TRUE();
}
@ -2419,7 +2419,7 @@ static void DropDatabaseCoordinator(
}
TRI_voc_tick_t const id = vocbase->_id;
TRI_ReleaseVocBase(vocbase);
vocbase->release();
ClusterInfo* ci = ClusterInfo::instance();
std::string errorMsg;
@ -2441,7 +2441,7 @@ static void DropDatabaseCoordinator(
break;
}
TRI_ReleaseVocBase(vocbase);
vocbase->release();
// sleep
usleep(10000);
}

View File

@ -86,8 +86,7 @@ static void JS_CreateCursor(v8::FunctionCallbackInfo<v8::Value> const& args) {
}
// create a cursor
auto cursors =
static_cast<arangodb::CursorRepository*>(vocbase->_cursorRepository);
auto cursors = vocbase->cursorRepository();
arangodb::aql::QueryResult result(TRI_ERROR_NO_ERROR);
result.result = builder;
@ -134,8 +133,7 @@ static void JS_JsonCursor(v8::FunctionCallbackInfo<v8::Value> const& args) {
arangodb::basics::StringUtils::uint64(id));
// find the cursor
auto cursors =
static_cast<arangodb::CursorRepository*>(vocbase->_cursorRepository);
auto cursors = vocbase->cursorRepository();
TRI_ASSERT(cursors != nullptr);
bool busy;

View File

@ -140,8 +140,7 @@ void CleanupThread::run() {
/// @brief clean up cursors
void CleanupThread::cleanupCursors(bool force) {
// clean unused cursors
auto cursors =
static_cast<arangodb::CursorRepository*>(_vocbase->_cursorRepository);
auto cursors = _vocbase->cursorRepository();
TRI_ASSERT(cursors != nullptr);
try {
@ -242,7 +241,7 @@ void CleanupThread::cleanupCollection(TRI_vocbase_col_t* collection,
}
}
if (!isDeleted && TRI_IsDeletedVocBase(document->_vocbase)) {
if (!isDeleted && document->_vocbase->isDropped()) {
// the collection was not marked as deleted, but the database was
isDeleted = true;
}

View File

@ -1087,15 +1087,11 @@ void TRI_vocbase_t::shutdown() {
}
// mark all cursors as deleted so underlying collections can be freed soon
if (_cursorRepository != nullptr) {
_cursorRepository->garbageCollect(true);
}
_cursorRepository->garbageCollect(true);
// mark all collection keys as deleted so underlying collections can be freed
// soon
if (_collectionKeys != nullptr) {
_collectionKeys->garbageCollect(true);
}
_collectionKeys->garbageCollect(true);
std::vector<TRI_vocbase_col_t*> collections;
@ -1678,68 +1674,6 @@ void TRI_ReleaseCollectionVocBase(TRI_vocbase_t* vocbase,
TRI_READ_UNLOCK_STATUS_VOCBASE_COL(collection);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the vocbase has been marked as deleted
////////////////////////////////////////////////////////////////////////////////
bool TRI_IsDeletedVocBase(TRI_vocbase_t* vocbase) {
auto refCount = vocbase->_refCount.load();
// if the stored value is odd, it means the database has been marked as
// deleted
return (refCount % 2 == 1);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief increase the reference counter for a database
////////////////////////////////////////////////////////////////////////////////
bool TRI_UseVocBase(TRI_vocbase_t* vocbase) {
// increase the reference counter by 2.
// this is because we use odd values to indicate that the database has been
// marked as deleted
auto oldValue = vocbase->_refCount.fetch_add(2, std::memory_order_release);
// check if the deleted bit is set
return (oldValue % 2 != 1);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief decrease the reference counter for a database
////////////////////////////////////////////////////////////////////////////////
void TRI_ReleaseVocBase(TRI_vocbase_t* vocbase) {
// decrease the reference counter by 2.
// this is because we use odd values to indicate that the database has been
// marked as deleted
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
auto oldValue = vocbase->_refCount.fetch_sub(2, std::memory_order_release);
TRI_ASSERT(oldValue >= 2);
#else
vocbase->_refCount.fetch_sub(2, std::memory_order_release);
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// @brief marks a database as deleted
////////////////////////////////////////////////////////////////////////////////
bool TRI_DropVocBase(TRI_vocbase_t* vocbase) {
auto oldValue = vocbase->_refCount.fetch_or(1, std::memory_order_release);
// if the previously stored value is odd, it means the database has already
// been marked as deleted
return (oldValue % 2 == 0);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns whether the database can be removed
////////////////////////////////////////////////////////////////////////////////
bool TRI_CanRemoveVocBase(TRI_vocbase_t* vocbase) {
auto refCount = vocbase->_refCount.load();
// we are intentionally comparing with exactly 1 here, because a 1 means
// that noone else references the database but it has been marked as deleted
return (refCount == 1);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief gets the "throw collection not loaded error"
////////////////////////////////////////////////////////////////////////////////
@ -1768,14 +1702,11 @@ TRI_vocbase_t::TRI_vocbase_t(TRI_vocbase_type_e type, TRI_voc_tick_t id,
_refCount(0),
_deadlockDetector(false),
_userStructures(nullptr),
_queries(nullptr),
_cursorRepository(nullptr),
_collectionKeys(nullptr),
_hasCompactor(false),
_isOwnAppsDirectory(true) {
_queries = new arangodb::aql::QueryList(this);
_cursorRepository = new arangodb::CursorRepository(this);
_collectionKeys = new arangodb::CollectionKeysRepository();
_queries.reset(new arangodb::aql::QueryList(this));
_cursorRepository.reset(new arangodb::CursorRepository(this));
_collectionKeys.reset(new arangodb::CollectionKeysRepository());
// init collections
_collections.reserve(32);
@ -1801,13 +1732,9 @@ TRI_vocbase_t::~TRI_vocbase_t() {
_cleanupThread.reset();
TRI_DestroyCondition(&_compactorCondition);
delete _cursorRepository;
delete _collectionKeys;
delete _queries;
}
std::string const TRI_vocbase_t::path() {
std::string TRI_vocbase_t::path() const {
StorageEngine* engine = EngineSelectorFeature::ENGINE;
return engine->databasePath(this);
}

View File

@ -27,6 +27,7 @@
#include "Basics/Common.h"
#include "Basics/ConditionVariable.h"
#include "Basics/DeadlockDetector.h"
#include "Basics/Exceptions.h"
#include "Basics/ReadWriteLock.h"
#include "Basics/StringUtils.h"
#include "Basics/threads.h"
@ -267,10 +268,11 @@ struct TRI_vocbase_t {
// structures for user-defined volatile data
void* _userStructures;
arangodb::aql::QueryList* _queries;
arangodb::CursorRepository* _cursorRepository;
arangodb::CollectionKeysRepository* _collectionKeys;
private:
std::unique_ptr<arangodb::aql::QueryList> _queries;
std::unique_ptr<arangodb::CursorRepository> _cursorRepository;
std::unique_ptr<arangodb::CollectionKeysRepository> _collectionKeys;
public:
bool _hasCompactor;
bool _isOwnAppsDirectory;
@ -303,14 +305,68 @@ struct TRI_vocbase_t {
/// @brief checks if a database name is allowed
/// returns true if the name is allowed and false otherwise
static bool IsAllowedName(bool allowSystem, std::string const& name);
std::string const name() { return _name; }
std::string const path();
std::string const& name() const { return _name; }
std::string path() const;
void updateReplicationClient(TRI_server_id_t, TRI_voc_tick_t);
std::vector<std::tuple<TRI_server_id_t, double, TRI_voc_tick_t>>
getReplicationClients();
arangodb::aql::QueryList* queryList() const { return _queries.get(); }
arangodb::CursorRepository* cursorRepository() const { return _cursorRepository.get(); }
arangodb::CollectionKeysRepository* collectionKeys() const { return _collectionKeys.get(); }
/// @brief whether or not the vocbase has been marked as deleted
inline bool isDropped() const {
auto refCount = _refCount.load();
// if the stored value is odd, it means the database has been marked as
// deleted
return (refCount % 2 == 1);
}
/// @brief increase the reference counter for a database
bool use() {
// increase the reference counter by 2.
// this is because we use odd values to indicate that the database has been
// marked as deleted
auto oldValue = _refCount.fetch_add(2, std::memory_order_release);
// check if the deleted bit is set
return (oldValue % 2 != 1);
}
/// @brief decrease the reference counter for a database
void release() {
// decrease the reference counter by 2.
// this is because we use odd values to indicate that the database has been
// marked as deleted
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
auto oldValue = _refCount.fetch_sub(2, std::memory_order_release);
TRI_ASSERT(oldValue >= 2);
#else
_refCount.fetch_sub(2, std::memory_order_release);
#endif
}
/// @brief returns whether the database can be dropped
bool canBeDropped() const {
if (isSystem()) {
return false;
}
auto refCount = _refCount.load();
// we are intentionally comparing with exactly 1 here, because a 1 means
// that noone else references the database but it has been marked as deleted
return (refCount == 1);
}
/// @brief marks a database as deleted
bool markAsDropped() {
auto oldValue = _refCount.fetch_or(1, std::memory_order_release);
// if the previously stored value is odd, it means the database has already
// been marked as deleted
return (oldValue % 2 == 0);
}
/// @brief returns whether the database is the system database
bool isSystem() { return name() == TRI_VOC_SYSTEM_DATABASE; }
bool isSystem() const { return name() == TRI_VOC_SYSTEM_DATABASE; }
/// @brief closes a database and all collections
void shutdown();
@ -343,6 +399,27 @@ struct TRI_vocbase_t {
bool doOverride, bool writeMarker);
};
// scope guard for a database
// ensures that a database
class VocbaseGuard {
public:
VocbaseGuard() = delete;
VocbaseGuard(VocbaseGuard const&) = delete;
VocbaseGuard& operator=(VocbaseGuard const&) = delete;
explicit VocbaseGuard(TRI_vocbase_t* vocbase) : _vocbase(vocbase) {
if (!_vocbase->use()) {
// database already dropped
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
}
~VocbaseGuard() { _vocbase->release(); }
TRI_vocbase_t* vocbase() const { return _vocbase; }
private:
TRI_vocbase_t* _vocbase;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief status of a collection
///
@ -518,36 +595,6 @@ TRI_vocbase_col_t* TRI_UseCollectionByNameVocBase(TRI_vocbase_t*, char const*,
void TRI_ReleaseCollectionVocBase(TRI_vocbase_t*, TRI_vocbase_col_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the vocbase has been marked as deleted
////////////////////////////////////////////////////////////////////////////////
bool TRI_IsDeletedVocBase(TRI_vocbase_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief increase the reference counter for a database
////////////////////////////////////////////////////////////////////////////////
bool TRI_UseVocBase(TRI_vocbase_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief decrease the reference counter for a database
////////////////////////////////////////////////////////////////////////////////
void TRI_ReleaseVocBase(TRI_vocbase_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief marks a database as deleted
////////////////////////////////////////////////////////////////////////////////
bool TRI_DropVocBase(TRI_vocbase_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief returns whether the database can be removed
////////////////////////////////////////////////////////////////////////////////
bool TRI_CanRemoveVocBase(TRI_vocbase_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief gets the "throw collection not loaded error"
////////////////////////////////////////////////////////////////////////////////

View File

@ -102,7 +102,7 @@ void RecoverState::releaseResources() {
// release all databases
for (auto it = openedDatabases.begin(); it != openedDatabases.end(); ++it) {
databaseFeature->releaseDatabase((*it).second);
(*it).second->release();
}
openedDatabases.clear();
@ -159,7 +159,7 @@ TRI_vocbase_t* RecoverState::releaseDatabase(TRI_voc_tick_t databaseId) {
}
}
databaseFeature->releaseDatabase(vocbase);
vocbase->release();
openedDatabases.erase(databaseId);
return vocbase;