From 33c94e5041390c3fb05de272e7cfee9f38e101dc Mon Sep 17 00:00:00 2001 From: jsteemann Date: Mon, 25 Jul 2016 14:56:39 +0200 Subject: [PATCH] moved database lookup functions into DatabaseFeature --- arangod/Cluster/HeartbeatThread.cpp | 10 +- .../GeneralServer/GeneralServerFeature.cpp | 26 +-- arangod/GeneralServer/RestHandlerFactory.h | 4 +- arangod/RestServer/BootstrapFeature.cpp | 24 +- arangod/RestServer/DatabaseFeature.cpp | 170 +++++++++++++- arangod/RestServer/DatabaseFeature.h | 15 +- arangod/Utils/DatabaseGuard.h | 14 +- arangod/Utils/ReplicationTransaction.h | 8 +- arangod/V8Server/v8-vocbase.cpp | 43 ++-- arangod/VocBase/server.cpp | 209 ------------------ arangod/VocBase/server.h | 62 ------ arangod/Wal/LogfileManager.cpp | 2 +- arangod/Wal/RecoverState.cpp | 38 ++-- arangod/Wal/RecoverState.h | 6 +- 14 files changed, 262 insertions(+), 369 deletions(-) diff --git a/arangod/Cluster/HeartbeatThread.cpp b/arangod/Cluster/HeartbeatThread.cpp index 1fa4386589..0598eb30a8 100644 --- a/arangod/Cluster/HeartbeatThread.cpp +++ b/arangod/Cluster/HeartbeatThread.cpp @@ -470,6 +470,8 @@ void HeartbeatThread::removeDispatchedJob(DBServerAgencySyncResult result) { static std::string const prefixPlanChangeCoordinator = "Plan/Databases"; bool HeartbeatThread::handlePlanChangeCoordinator(uint64_t currentPlanVersion) { + DatabaseFeature* databaseFeature = application_features::ApplicationServer::getFeature("Database"); + LOG_TOPIC(TRACE, Logger::HEARTBEAT) << "found a plan update"; AgencyCommResult result = _agency.getValues(prefixPlanChangeCoordinator); @@ -516,8 +518,7 @@ bool HeartbeatThread::handlePlanChangeCoordinator(uint64_t currentPlanVersion) { ids.push_back(id); } - TRI_vocbase_t* vocbase = - TRI_UseCoordinatorDatabaseServer(_server, name.c_str()); + TRI_vocbase_t* vocbase = databaseFeature->useDatabaseCoordinator(name); if (vocbase == nullptr) { // database does not yet exist, create it now @@ -528,7 +529,6 @@ bool HeartbeatThread::handlePlanChangeCoordinator(uint64_t currentPlanVersion) { } // create a local database object... - DatabaseFeature* databaseFeature = application_features::ApplicationServer::getFeature("Database"); int res = databaseFeature->createDatabaseCoordinator(id, name, vocbase); if (res != TRI_ERROR_NO_ERROR) { @@ -542,15 +542,13 @@ bool HeartbeatThread::handlePlanChangeCoordinator(uint64_t currentPlanVersion) { } // get the list of databases that we know about locally - std::vector localIds = - TRI_GetIdsCoordinatorDatabaseServer(_server); + std::vector localIds = databaseFeature->getDatabaseIdsCoordinator(false); for (auto id : localIds) { auto r = std::find(ids.begin(), ids.end(), id); if (r == ids.end()) { // local database not found in the plan... - DatabaseFeature* databaseFeature = application_features::ApplicationServer::getFeature("Database"); databaseFeature->dropDatabaseCoordinator(id, false); } } diff --git a/arangod/GeneralServer/GeneralServerFeature.cpp b/arangod/GeneralServer/GeneralServerFeature.cpp index 9558b1190a..482d8f05aa 100644 --- a/arangod/GeneralServer/GeneralServerFeature.cpp +++ b/arangod/GeneralServer/GeneralServerFeature.cpp @@ -216,31 +216,30 @@ void GeneralServerFeature::validateOptions(std::shared_ptr) { } } -static TRI_vocbase_t* LookupDatabaseFromRequest(GeneralRequest* request, - TRI_server_t* server) { +static TRI_vocbase_t* LookupDatabaseFromRequest(GeneralRequest* request) { + auto databaseFeature = application_features::ApplicationServer::getFeature("Database"); + // get database name from request std::string const& dbName = request->databaseName(); - char const* p; if (dbName.empty()) { // if no databases was specified in the request, use system database name // as a fallback request->setDatabaseName(StaticStrings::SystemDatabase); - p = StaticStrings::SystemDatabase.c_str(); - } else { - p = dbName.c_str(); + if (ServerState::instance()->isCoordinator()) { + return databaseFeature->useDatabaseCoordinator(StaticStrings::SystemDatabase); + } + return databaseFeature->useDatabase(StaticStrings::SystemDatabase); } - + if (ServerState::instance()->isCoordinator()) { - return TRI_UseCoordinatorDatabaseServer(server, p); + return databaseFeature->useDatabaseCoordinator(dbName); } - - return TRI_UseDatabaseServer(server, p); + return databaseFeature->useDatabase(dbName); } static bool SetRequestContext(GeneralRequest* request, void* data) { - TRI_server_t* server = static_cast(data); - TRI_vocbase_t* vocbase = LookupDatabaseFromRequest(request, server); + TRI_vocbase_t* vocbase = LookupDatabaseFromRequest(request); // invalid database name specified, database not found etc. if (vocbase == nullptr) { @@ -284,8 +283,7 @@ void GeneralServerFeature::start() { JOB_MANAGER = _jobManager.get(); - _handlerFactory.reset(new RestHandlerFactory(&SetRequestContext, - DatabaseFeature::SERVER)); + _handlerFactory.reset(new RestHandlerFactory(&SetRequestContext, nullptr)); HANDLER_FACTORY = _handlerFactory.get(); diff --git a/arangod/GeneralServer/RestHandlerFactory.h b/arangod/GeneralServer/RestHandlerFactory.h index 7a80906bf0..8e538797d0 100644 --- a/arangod/GeneralServer/RestHandlerFactory.h +++ b/arangod/GeneralServer/RestHandlerFactory.h @@ -68,10 +68,10 @@ class RestHandlerFactory { RestHandler* createHandler(GeneralRequest*, GeneralResponse*); // adds a path and constructor to the factory - void addHandler(std::string const& path, create_fptr, void* data = 0); + void addHandler(std::string const& path, create_fptr, void* data = nullptr); // adds a prefix path and constructor to the factory - void addPrefixHandler(std::string const& path, create_fptr, void* data = 0); + void addPrefixHandler(std::string const& path, create_fptr, void* data = nullptr); // adds a path and constructor to the factory void addNotFoundHandler(create_fptr); diff --git a/arangod/RestServer/BootstrapFeature.cpp b/arangod/RestServer/BootstrapFeature.cpp index 4ba7f7c902..0cdd6e8d0c 100644 --- a/arangod/RestServer/BootstrapFeature.cpp +++ b/arangod/RestServer/BootstrapFeature.cpp @@ -168,12 +168,11 @@ void BootstrapFeature::start() { void BootstrapFeature::unprepare() { // notify all currently running queries about the shutdown - TRI_server_t* s = DatabaseFeature::SERVER; + auto databaseFeature = application_features::ApplicationServer::getFeature("Database"); + if (ServerState::instance()->isCoordinator()) { - std::vector ids = - TRI_GetIdsCoordinatorDatabaseServer(s, true); - for (auto& id : ids) { - TRI_vocbase_t* vocbase = TRI_UseByIdCoordinatorDatabaseServer(s, id); + for (auto& id : databaseFeature->getDatabaseIdsCoordinator(true)) { + TRI_vocbase_t* vocbase = databaseFeature->useDatabase(id); if (vocbase != nullptr) { vocbase->_queries->killAll(true); @@ -181,16 +180,13 @@ void BootstrapFeature::unprepare() { } } } else { - std::vector names; - int res = TRI_GetDatabaseNamesServer(s, names); - if (res == TRI_ERROR_NO_ERROR) { - for (auto& name : names) { - TRI_vocbase_t* vocbase = TRI_UseDatabaseServer(s, name.c_str()); + std::vector names = databaseFeature->getDatabaseNames(); + for (auto& name : databaseFeature->getDatabaseNames()) { + TRI_vocbase_t* vocbase = databaseFeature->useDatabase(name); - if (vocbase != nullptr) { - vocbase->_queries->killAll(true); - TRI_ReleaseVocBase(vocbase); - } + if (vocbase != nullptr) { + vocbase->_queries->killAll(true); + TRI_ReleaseVocBase(vocbase); } } } diff --git a/arangod/RestServer/DatabaseFeature.cpp b/arangod/RestServer/DatabaseFeature.cpp index 782c872dee..0c96929da9 100644 --- a/arangod/RestServer/DatabaseFeature.cpp +++ b/arangod/RestServer/DatabaseFeature.cpp @@ -44,6 +44,7 @@ #include "V8Server/V8DealerFeature.h" #include "V8Server/v8-query.h" #include "V8Server/v8-vocbase.h" +#include "VocBase/AuthInfo.h" #include "VocBase/KeyGenerator.h" #include "VocBase/replication-applier.h" #include "VocBase/server.h" @@ -710,16 +711,145 @@ int DatabaseFeature::dropDatabase(TRI_voc_tick_t id, bool writeMarker, bool wait // and call the regular drop function return dropDatabase(name, writeMarker, waitForDeletion, removeAppsDirectory); } + +std::vector DatabaseFeature::getDatabaseIdsCoordinator(bool includeSystem) { + std::vector ids; + { + auto unuser(_databasesProtector.use()); + auto theLists = _databasesLists.load(); + + for (auto& p : theLists->_coordinatorDatabases) { + TRI_vocbase_t* vocbase = p.second; + TRI_ASSERT(vocbase != nullptr); + + if (includeSystem || std::string(vocbase->_name) != TRI_VOC_SYSTEM_DATABASE) { + ids.emplace_back(vocbase->_id); + } + } + } + + return ids; +} + +std::vector DatabaseFeature::getDatabaseIds(bool includeSystem) { + std::vector ids; + + { + auto unuser(_databasesProtector.use()); + auto theLists = _databasesLists.load(); + + for (auto& p : theLists->_databases) { + TRI_vocbase_t* vocbase = p.second; + TRI_ASSERT(vocbase != nullptr); + if (includeSystem || std::string(vocbase->_name) != TRI_VOC_SYSTEM_DATABASE) { + ids.emplace_back(vocbase->_id); + } + } + } + + return ids; +} + +/// @brief return the list of all database names +std::vector DatabaseFeature::getDatabaseNames() { + std::vector names; + + { + auto unuser(_databasesProtector.use()); + auto theLists = _databasesLists.load(); + + for (auto& p : theLists->_databases) { + TRI_vocbase_t* vocbase = p.second; + TRI_ASSERT(vocbase != nullptr); + TRI_ASSERT(vocbase->_name != nullptr); + + names.emplace_back(vocbase->_name); + } + } + + std::sort( + names.begin(), names.end(), + [](std::string const& l, std::string const& r) -> bool { return l < r; }); + + return names; +} + +/// @brief return the list of all database names for a user +std::vector DatabaseFeature::getDatabaseNamesForUser(std::string const& username) { + std::vector names; + + { + auto unuser(_databasesProtector.use()); + auto theLists = _databasesLists.load(); + + for (auto& p : theLists->_databases) { + TRI_vocbase_t* vocbase = p.second; + TRI_ASSERT(vocbase != nullptr); + TRI_ASSERT(vocbase->_name != nullptr); + + auto level = + GeneralServerFeature::AUTH_INFO.canUseDatabase(username, vocbase->_name); + + if (level == AuthLevel::NONE) { + continue; + } + + names.emplace_back(vocbase->_name); + } + } + + std::sort( + names.begin(), names.end(), + [](std::string const& l, std::string const& r) -> bool { return l < r; }); + + return names; +} void DatabaseFeature::useSystemDatabase() { useDatabase(TRI_VOC_SYSTEM_DATABASE); } +/// @brief get a coordinator database by its id +/// this will increase the reference-counter for the database +TRI_vocbase_t* DatabaseFeature::useDatabaseCoordinator(TRI_voc_tick_t id) { + auto unuser(_databasesProtector.use()); + auto theLists = _databasesLists.load(); + + for (auto& p : theLists->_coordinatorDatabases) { + TRI_vocbase_t* vocbase = p.second; + + if (vocbase->_id == id) { + bool result TRI_UNUSED = TRI_UseVocBase(vocbase); + + // if we got here, no one else can have deleted the database + TRI_ASSERT(result == true); + return vocbase; + } + } + return nullptr; +} + +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); + } + + return vocbase; +} + TRI_vocbase_t* DatabaseFeature::useDatabase(std::string const& name) { auto unuser(_databasesProtector.use()); auto theLists = _databasesLists.load(); - auto it = theLists->_databases.find(name); + TRI_vocbase_t* vocbase = nullptr; + auto it = theLists->_databases.find(name); if (it != theLists->_databases.end()) { vocbase = it->second; @@ -729,6 +859,44 @@ TRI_vocbase_t* DatabaseFeature::useDatabase(std::string const& name) { return vocbase; } +TRI_vocbase_t* DatabaseFeature::useDatabase(TRI_voc_tick_t id) { + auto unuser(_databasesProtector.use()); + auto theLists = _databasesLists.load(); + + for (auto& p : theLists->_databases) { + TRI_vocbase_t* vocbase = p.second; + + if (vocbase->_id == id) { + TRI_UseVocBase(vocbase); + return vocbase; + } + } + + 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 +TRI_vocbase_t* DatabaseFeature::lookupDatabase(std::string const& name) { + auto unuser(_databasesProtector.use()); + auto theLists = _databasesLists.load(); + + for (auto& p : theLists->_databases) { + TRI_vocbase_t* vocbase = p.second; + + if (name == vocbase->_name) { + return vocbase; + } + } + + return nullptr; +} + void DatabaseFeature::updateContexts() { TRI_ASSERT(_vocbase != nullptr); diff --git a/arangod/RestServer/DatabaseFeature.h b/arangod/RestServer/DatabaseFeature.h index e6e5d78f88..5443cfd21a 100644 --- a/arangod/RestServer/DatabaseFeature.h +++ b/arangod/RestServer/DatabaseFeature.h @@ -77,14 +77,27 @@ class DatabaseFeature final : public application_features::ApplicationFeature { void unprepare() override final; public: + /// @brief get the ids of all local coordinator databases + std::vector getDatabaseIdsCoordinator(bool includeSystem); + std::vector getDatabaseIds(bool includeSystem); + std::vector getDatabaseNames(); + std::vector getDatabaseNamesForUser(std::string const& user); + int createDatabaseCoordinator(TRI_voc_tick_t id, std::string const& name, TRI_vocbase_t*& result); int createDatabase(TRI_voc_tick_t id, std::string const& name, bool writeMarker, TRI_vocbase_t*& result); int dropDatabaseCoordinator(TRI_voc_tick_t id, bool force); int dropDatabase(std::string const& name, bool writeMarker, bool waitForDeletion, bool removeAppsDirectory); int dropDatabase(TRI_voc_tick_t id, bool writeMarker, bool waitForDeletion, bool removeAppsDirectory); - void useSystemDatabase(); + TRI_vocbase_t* useDatabaseCoordinator(std::string const& name); + 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); + + void useSystemDatabase(); TRI_vocbase_t* systemDatabase() const { return _vocbase; } bool ignoreDatafileErrors() const { return _ignoreDatafileErrors; } bool isInitiallyEmpty() const { return _isInitiallyEmpty; } diff --git a/arangod/Utils/DatabaseGuard.h b/arangod/Utils/DatabaseGuard.h index 39a9c5e5a6..e51e158614 100644 --- a/arangod/Utils/DatabaseGuard.h +++ b/arangod/Utils/DatabaseGuard.h @@ -24,8 +24,9 @@ #ifndef ARANGOD_UTILS_DATABASE_GUARD_H #define ARANGOD_UTILS_DATABASE_GUARD_H 1 -#include "Basics/Common.h" +#include "ApplicationFeatures/ApplicationServer.h" #include "Basics/Exceptions.h" +#include "RestServer/DatabaseFeature.h" #include "VocBase/server.h" struct TRI_vocbase_t; @@ -43,7 +44,9 @@ class DatabaseGuard { DatabaseGuard(TRI_server_t* server, TRI_voc_tick_t id) : _server(server), _database(nullptr) { - _database = TRI_UseDatabaseByIdServer(server, id); + + auto databaseFeature = application_features::ApplicationServer::getFeature("Database"); + _database = databaseFeature->useDatabase(id); if (_database == nullptr) { THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND); @@ -56,7 +59,9 @@ class DatabaseGuard { DatabaseGuard(TRI_server_t* server, char const* name) : _server(server), _database(nullptr) { - _database = TRI_UseDatabaseServer(server, name); + + auto databaseFeature = application_features::ApplicationServer::getFeature("Database"); + _database = databaseFeature->useDatabase(name); if (_database == nullptr) { THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND); @@ -69,7 +74,8 @@ class DatabaseGuard { ~DatabaseGuard() { if (_database != nullptr) { - TRI_ReleaseDatabaseServer(_server, _database); + auto databaseFeature = application_features::ApplicationServer::getFeature("Database"); + databaseFeature->releaseDatabase(_database); } } diff --git a/arangod/Utils/ReplicationTransaction.h b/arangod/Utils/ReplicationTransaction.h index f1506c222a..2c746852d5 100644 --- a/arangod/Utils/ReplicationTransaction.h +++ b/arangod/Utils/ReplicationTransaction.h @@ -24,7 +24,7 @@ #ifndef ARANGOD_UTILS_REPLICATION_TRANSACTION_H #define ARANGOD_UTILS_REPLICATION_TRANSACTION_H 1 -#include "Basics/Common.h" +#include "ApplicationFeatures/ApplicationServer.h" #include "RestServer/DatabaseFeature.h" #include "Utils/StandaloneTransactionContext.h" #include "Utils/Transaction.h" @@ -44,7 +44,8 @@ class ReplicationTransaction : public Transaction { ReplicationTransaction(TRI_vocbase_t* vocbase) : Transaction(StandaloneTransactionContext::Create(vocbase)) { - TRI_UseDatabaseServer(DatabaseFeature::SERVER, vocbase->_name); + auto databaseFeature = application_features::ApplicationServer::getFeature("Database"); + databaseFeature->useDatabase(vocbase->_name); } ////////////////////////////////////////////////////////////////////////////// @@ -52,7 +53,8 @@ class ReplicationTransaction : public Transaction { ////////////////////////////////////////////////////////////////////////////// ~ReplicationTransaction() { - TRI_ReleaseDatabaseServer(DatabaseFeature::SERVER, vocbase()); + auto databaseFeature = application_features::ApplicationServer::getFeature("Database"); + databaseFeature->releaseDatabase(vocbase()); } public: diff --git a/arangod/V8Server/v8-vocbase.cpp b/arangod/V8Server/v8-vocbase.cpp index 120c3a7d92..3ffe14f81e 100644 --- a/arangod/V8Server/v8-vocbase.cpp +++ b/arangod/V8Server/v8-vocbase.cpp @@ -2031,7 +2031,8 @@ static void JS_UseDatabase(v8::FunctionCallbackInfo const& args) { TRI_V8_THROW_EXCEPTION(TRI_ERROR_FORBIDDEN); } - std::string name = TRI_ObjectToString(args[0]); + auto databaseFeature = application_features::ApplicationServer::getFeature("Database"); + std::string const name = TRI_ObjectToString(args[0]); TRI_vocbase_t* vocbase = GetContextVocBase(isolate); @@ -2049,12 +2050,10 @@ static void JS_UseDatabase(v8::FunctionCallbackInfo const& args) { } if (ServerState::instance()->isCoordinator()) { - vocbase = TRI_UseCoordinatorDatabaseServer( - static_cast(v8g->_server), name.c_str()); + vocbase = databaseFeature->useDatabaseCoordinator(name); } else { // check if the other database exists, and increase its refcount - vocbase = TRI_UseDatabaseServer(static_cast(v8g->_server), - name.c_str()); + vocbase = databaseFeature->useDatabase(name); } if (vocbase == nullptr) { @@ -2067,8 +2066,7 @@ static void JS_UseDatabase(v8::FunctionCallbackInfo const& args) { v8g->_vocbase = vocbase; TRI_ASSERT(orig != vocbase); - TRI_ReleaseDatabaseServer(static_cast(v8g->_server), - static_cast(orig)); + databaseFeature->releaseDatabase(static_cast(orig)); TRI_V8_RETURN(WrapVocBase(isolate, vocbase)); } @@ -2171,26 +2169,15 @@ static void JS_Databases(v8::FunctionCallbackInfo const& args) { return; } - TRI_GET_GLOBALS(); - + auto databaseFeature = application_features::ApplicationServer::getFeature("Database"); std::vector names; - int res; - if (argc == 0) { // return all databases - res = TRI_GetDatabaseNamesServer(static_cast(v8g->_server), - names); + names = databaseFeature->getDatabaseNames(); } else { // return all databases for a specific user - std::string&& username = TRI_ObjectToString(args[0]); - - res = TRI_GetUserDatabasesServer(static_cast(v8g->_server), - username.c_str(), names); - } - - if (res != TRI_ERROR_NO_ERROR) { - TRI_V8_THROW_EXCEPTION(res); + names = databaseFeature->getDatabaseNamesForUser(TRI_ObjectToString(args[0])); } v8::Handle result = v8::Array::New(isolate, (int)names.size()); @@ -2267,10 +2254,11 @@ static void CreateDatabaseCoordinator( // now wait for heartbeat thread to create the database object TRI_vocbase_t* vocbase = nullptr; int tries = 0; + + auto databaseFeature = application_features::ApplicationServer::getFeature("Database"); while (++tries <= 6000) { - vocbase = TRI_UseByIdCoordinatorDatabaseServer( - static_cast(v8g->_server), id); + vocbase = databaseFeature->useDatabaseCoordinator(id); if (vocbase != nullptr) { break; @@ -2418,12 +2406,10 @@ static void DropDatabaseCoordinator( v8::Isolate* isolate = args.GetIsolate(); v8::HandleScope scope(isolate); - TRI_GET_GLOBALS(); - // Arguments are already checked, there is exactly one argument + auto databaseFeature = application_features::ApplicationServer::getFeature("Database"); std::string const name = TRI_ObjectToString(args[0]); - TRI_vocbase_t* vocbase = TRI_UseCoordinatorDatabaseServer( - static_cast(v8g->_server), name.c_str()); + TRI_vocbase_t* vocbase = databaseFeature->useDatabaseCoordinator(name); if (vocbase == nullptr) { // no such database @@ -2446,8 +2432,7 @@ static void DropDatabaseCoordinator( int tries = 0; while (++tries <= 6000) { - TRI_vocbase_t* vocbase = TRI_UseByIdCoordinatorDatabaseServer( - static_cast(v8g->_server), id); + TRI_vocbase_t* vocbase = databaseFeature->useDatabaseCoordinator(id); if (vocbase == nullptr) { // object has vanished diff --git a/arangod/VocBase/server.cpp b/arangod/VocBase/server.cpp index 8f5d7320b6..2c501b975d 100644 --- a/arangod/VocBase/server.cpp +++ b/arangod/VocBase/server.cpp @@ -173,215 +173,6 @@ int TRI_InitDatabasesServer(TRI_server_t* server) { return TRI_ERROR_NO_ERROR; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief get the ids of all local coordinator databases -/// the caller is responsible for freeing the result -//////////////////////////////////////////////////////////////////////////////// - -std::vector TRI_GetIdsCoordinatorDatabaseServer( - TRI_server_t* server, bool includeSystem) { - std::vector v; - { - auto unuser(server->_databasesProtector.use()); - auto theLists = server->_databasesLists.load(); - - for (auto& p : theLists->_coordinatorDatabases) { - TRI_vocbase_t* vocbase = p.second; - TRI_ASSERT(vocbase != nullptr); - - if (includeSystem || - !TRI_EqualString(vocbase->_name, TRI_VOC_SYSTEM_DATABASE)) { - v.emplace_back(vocbase->_id); - } - } - } - return v; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief get a coordinator database by its id -/// this will increase the reference-counter for the database -//////////////////////////////////////////////////////////////////////////////// - -TRI_vocbase_t* TRI_UseByIdCoordinatorDatabaseServer(TRI_server_t* server, - TRI_voc_tick_t id) { - auto unuser(server->_databasesProtector.use()); - auto theLists = server->_databasesLists.load(); - - for (auto& p : theLists->_coordinatorDatabases) { - TRI_vocbase_t* vocbase = p.second; - - if (vocbase->_id == id) { - bool result TRI_UNUSED = TRI_UseVocBase(vocbase); - - // if we got here, no one else can have deleted the database - TRI_ASSERT(result == true); - return vocbase; - } - } - return nullptr; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief get a coordinator database by its name -/// this will increase the reference-counter for the database -//////////////////////////////////////////////////////////////////////////////// - -TRI_vocbase_t* TRI_UseCoordinatorDatabaseServer(TRI_server_t* server, - char const* name) { - auto unuser(server->_databasesProtector.use()); - auto theLists = server->_databasesLists.load(); - auto it = theLists->_coordinatorDatabases.find(std::string(name)); - TRI_vocbase_t* vocbase = nullptr; - - if (it != theLists->_coordinatorDatabases.end()) { - vocbase = it->second; - TRI_UseVocBase(vocbase); - } - - return vocbase; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief get a database by its name -/// this will increase the reference-counter for the database -//////////////////////////////////////////////////////////////////////////////// - -TRI_vocbase_t* TRI_UseDatabaseServer(TRI_server_t* server, char const* name) { - auto unuser(server->_databasesProtector.use()); - auto theLists = server->_databasesLists.load(); - auto it = theLists->_databases.find(std::string(name)); - TRI_vocbase_t* vocbase = nullptr; - - if (it != theLists->_databases.end()) { - vocbase = it->second; - TRI_UseVocBase(vocbase); - } - - return vocbase; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief lookup a database by its name -//////////////////////////////////////////////////////////////////////////////// - -TRI_vocbase_t* TRI_LookupDatabaseByNameServer(TRI_server_t* server, - char const* name) { - auto unuser(server->_databasesProtector.use()); - auto theLists = server->_databasesLists.load(); - - for (auto& p : theLists->_databases) { - TRI_vocbase_t* vocbase = p.second; - - if (TRI_EqualString(vocbase->_name, name)) { - return vocbase; - } - } - - return nullptr; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief get a database by its id -/// this will increase the reference-counter for the database -//////////////////////////////////////////////////////////////////////////////// - -TRI_vocbase_t* TRI_UseDatabaseByIdServer(TRI_server_t* server, - TRI_voc_tick_t id) { - auto unuser(server->_databasesProtector.use()); - auto theLists = server->_databasesLists.load(); - - for (auto& p : theLists->_databases) { - TRI_vocbase_t* vocbase = p.second; - - if (vocbase->_id == id) { - TRI_UseVocBase(vocbase); - return vocbase; - } - } - - return nullptr; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief release a previously used database -/// this will decrease the reference-counter for the database -//////////////////////////////////////////////////////////////////////////////// - -void TRI_ReleaseDatabaseServer(TRI_server_t* server, TRI_vocbase_t* vocbase) { - TRI_ReleaseVocBase(vocbase); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the list of all databases a user can see -//////////////////////////////////////////////////////////////////////////////// - -int TRI_GetUserDatabasesServer(TRI_server_t* server, char const* username, - std::vector& names) { - int res = TRI_ERROR_NO_ERROR; - - { - auto unuser(server->_databasesProtector.use()); - auto theLists = server->_databasesLists.load(); - - for (auto& p : theLists->_databases) { - char const* dbName = p.second->_name; - TRI_ASSERT(dbName != nullptr); - - auto level = - GeneralServerFeature::AUTH_INFO.canUseDatabase(username, dbName); - - if (level == AuthLevel::NONE) { - continue; - } - - try { - names.emplace_back(dbName); - } catch (...) { - return TRI_ERROR_OUT_OF_MEMORY; - } - } - } - - std::sort( - names.begin(), names.end(), - [](std::string const& l, std::string const& r) -> bool { return l < r; }); - - return res; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the list of all database names -//////////////////////////////////////////////////////////////////////////////// - -int TRI_GetDatabaseNamesServer(TRI_server_t* server, - std::vector& names) { - int res = TRI_ERROR_NO_ERROR; - - { - auto unuser(server->_databasesProtector.use()); - auto theLists = server->_databasesLists.load(); - - for (auto& p : theLists->_databases) { - TRI_vocbase_t* vocbase = p.second; - TRI_ASSERT(vocbase != nullptr); - TRI_ASSERT(vocbase->_name != nullptr); - - try { - names.emplace_back(vocbase->_name); - } catch (...) { - return TRI_ERROR_OUT_OF_MEMORY; - } - } - } - - std::sort( - names.begin(), names.end(), - [](std::string const& l, std::string const& r) -> bool { return l < r; }); - - return res; -} - //////////////////////////////////////////////////////////////////////////////// /// @brief sets the current operation mode of the server //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/VocBase/server.h b/arangod/VocBase/server.h index 2ae2bdf8a5..cc397f02f2 100644 --- a/arangod/VocBase/server.h +++ b/arangod/VocBase/server.h @@ -69,68 +69,6 @@ struct TRI_server_t { int TRI_InitDatabasesServer(TRI_server_t*); -//////////////////////////////////////////////////////////////////////////////// -/// @brief get the ids of all local coordinator databases -//////////////////////////////////////////////////////////////////////////////// - -std::vector TRI_GetIdsCoordinatorDatabaseServer(TRI_server_t*, - bool includeSystem = false); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief get a coordinator database by its id -/// this will increase the reference-counter for the database -//////////////////////////////////////////////////////////////////////////////// - -TRI_vocbase_t* TRI_UseByIdCoordinatorDatabaseServer(TRI_server_t*, - TRI_voc_tick_t); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief use a coordinator database by its name -/// this will increase the reference-counter for the database -//////////////////////////////////////////////////////////////////////////////// - -TRI_vocbase_t* TRI_UseCoordinatorDatabaseServer(TRI_server_t*, char const*); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief use a database by its name -/// this will increase the reference-counter for the database -//////////////////////////////////////////////////////////////////////////////// - -TRI_vocbase_t* TRI_UseDatabaseServer(TRI_server_t*, char const*); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief lookup a database by its name -//////////////////////////////////////////////////////////////////////////////// - -TRI_vocbase_t* TRI_LookupDatabaseByNameServer(TRI_server_t*, char const*); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief use a database by its id -/// this will increase the reference-counter for the database -//////////////////////////////////////////////////////////////////////////////// - -TRI_vocbase_t* TRI_UseDatabaseByIdServer(TRI_server_t*, TRI_voc_tick_t); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief release a previously used database -/// this will decrease the reference-counter for the database -//////////////////////////////////////////////////////////////////////////////// - -void TRI_ReleaseDatabaseServer(TRI_server_t*, TRI_vocbase_t*); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the list of all databases a user can see -//////////////////////////////////////////////////////////////////////////////// - -int TRI_GetUserDatabasesServer(TRI_server_t*, char const*, - std::vector&); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the list of all database names -//////////////////////////////////////////////////////////////////////////////// - -int TRI_GetDatabaseNamesServer(TRI_server_t*, std::vector&); - //////////////////////////////////////////////////////////////////////////////// /// @brief sets the current operation mode of the server //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Wal/LogfileManager.cpp b/arangod/Wal/LogfileManager.cpp index 8437fc4721..3e86fde860 100644 --- a/arangod/Wal/LogfileManager.cpp +++ b/arangod/Wal/LogfileManager.cpp @@ -303,7 +303,7 @@ void LogfileManager::start() { // initialize some objects _slots = new Slots(this, _numberOfSlots, 0); - _recoverState = new RecoverState(_server, _ignoreRecoveryErrors); + _recoverState = new RecoverState(_ignoreRecoveryErrors); TRI_ASSERT(!_allowWrites); diff --git a/arangod/Wal/RecoverState.cpp b/arangod/Wal/RecoverState.cpp index 8a901505f1..b8fed40490 100644 --- a/arangod/Wal/RecoverState.cpp +++ b/arangod/Wal/RecoverState.cpp @@ -69,8 +69,8 @@ static inline T NumericValue(VPackSlice const& slice, char const* attribute) { } /// @brief creates the recover state -RecoverState::RecoverState(TRI_server_t* server, bool ignoreRecoveryErrors) - : server(server), +RecoverState::RecoverState(bool ignoreRecoveryErrors) + : databaseFeature(nullptr), failedTransactions(), lastTick(0), logfilesToProcess(), @@ -80,7 +80,10 @@ RecoverState::RecoverState(TRI_server_t* server, bool ignoreRecoveryErrors) ignoreRecoveryErrors(ignoreRecoveryErrors), errorCount(0), lastDatabaseId(0), - lastCollectionId(0) {} + lastCollectionId(0) { + + databaseFeature = application_features::ApplicationServer::getFeature("Database"); +} /// @brief destroys the recover state RecoverState::~RecoverState() { releaseResources(); } @@ -99,8 +102,7 @@ void RecoverState::releaseResources() { // release all databases for (auto it = openedDatabases.begin(); it != openedDatabases.end(); ++it) { - TRI_vocbase_t* vocbase = (*it).second; - TRI_ReleaseDatabaseServer(server, vocbase); + databaseFeature->releaseDatabase((*it).second); } openedDatabases.clear(); @@ -114,7 +116,7 @@ TRI_vocbase_t* RecoverState::useDatabase(TRI_voc_tick_t databaseId) { return (*it).second; } - TRI_vocbase_t* vocbase = TRI_UseDatabaseByIdServer(server, databaseId); + TRI_vocbase_t* vocbase = databaseFeature->useDatabase(databaseId); if (vocbase == nullptr) { return nullptr; @@ -157,7 +159,7 @@ TRI_vocbase_t* RecoverState::releaseDatabase(TRI_voc_tick_t databaseId) { } } - TRI_ReleaseDatabaseServer(server, vocbase); + databaseFeature->releaseDatabase(vocbase); openedDatabases.erase(databaseId); return vocbase; @@ -818,11 +820,10 @@ bool RecoverState::ReplayMarker(TRI_df_marker_t const* marker, void* data, if (state->willBeDropped(collectionId)) { // in case we detect that this collection is going to be deleted anyway, // set the sync properties to false temporarily - auto database = application_features::ApplicationServer::getFeature("Database"); - bool oldSync = database->forceSyncProperties(); - database->forceSyncProperties(false); + bool oldSync = state->databaseFeature->forceSyncProperties(); + state->databaseFeature->forceSyncProperties(false); collection = TRI_CreateCollectionVocBase(vocbase, info, collectionId, false); - database->forceSyncProperties(oldSync); + state->databaseFeature->forceSyncProperties(oldSync); } else { // collection will be kept collection = @@ -855,9 +856,8 @@ bool RecoverState::ReplayMarker(TRI_df_marker_t const* marker, void* data, if (vocbase != nullptr) { // remove already existing database - DatabaseFeature* databaseFeature = application_features::ApplicationServer::getFeature("Database"); // TODO: how to signal a dropDatabase failure here? - databaseFeature->dropDatabase(databaseId, false, true, false); + state->databaseFeature->dropDatabase(databaseId, false, true, false); } VPackSlice const nameSlice = payloadSlice.get("name"); @@ -871,16 +871,14 @@ bool RecoverState::ReplayMarker(TRI_df_marker_t const* marker, void* data, std::string nameString = nameSlice.copyString(); // remove already existing database with same name - vocbase = - TRI_LookupDatabaseByNameServer(state->server, nameString.c_str()); + vocbase = state->databaseFeature->lookupDatabase(nameString); if (vocbase != nullptr) { TRI_voc_tick_t otherId = vocbase->_id; state->releaseDatabase(otherId); - DatabaseFeature* databaseFeature = application_features::ApplicationServer::getFeature("Database"); // TODO: how to signal a dropDatabase failure here? - databaseFeature->dropDatabase(nameString, false, true, false); + state->databaseFeature->dropDatabase(nameString, false, true, false); } vocbase = nullptr; @@ -888,8 +886,7 @@ bool RecoverState::ReplayMarker(TRI_df_marker_t const* marker, void* data, WaitForDeletion(state->server, databaseId, TRI_ERROR_ARANGO_DATABASE_NOT_FOUND); */ - DatabaseFeature* databaseFeature = application_features::ApplicationServer::getFeature("Database"); - int res = databaseFeature->createDatabase(databaseId, nameString, false, vocbase); + int res = state->databaseFeature->createDatabase(databaseId, nameString, false, vocbase); if (res != TRI_ERROR_NO_ERROR) { LOG(WARN) << "cannot create database " << databaseId << ": " << TRI_errno_string(res); @@ -1005,8 +1002,7 @@ bool RecoverState::ReplayMarker(TRI_df_marker_t const* marker, void* data, if (vocbase != nullptr) { // ignore any potential error returned by this call - DatabaseFeature* databaseFeature = application_features::ApplicationServer::getFeature("Database"); - databaseFeature->dropDatabase(databaseId, false, true, false); + state->databaseFeature->dropDatabase(databaseId, false, true, false); } #ifdef ARANGODB_ENABLE_ROCKSDB diff --git a/arangod/Wal/RecoverState.h b/arangod/Wal/RecoverState.h index 2e8d3bd381..5e5907ed31 100644 --- a/arangod/Wal/RecoverState.h +++ b/arangod/Wal/RecoverState.h @@ -35,6 +35,8 @@ #include "Wal/Marker.h" namespace arangodb { +class DatabaseFeature; + namespace wal { /// @brief state that is built up when scanning a WAL logfile during recovery @@ -43,7 +45,7 @@ struct RecoverState { RecoverState& operator=(RecoverState const&) = delete; /// @brief creates the recover state - RecoverState(TRI_server_t*, bool); + explicit RecoverState(bool); /// @brief destroys the recover state ~RecoverState(); @@ -152,7 +154,7 @@ struct RecoverState { /// @brief fill the secondary indexes of all collections used in recovery int fillIndexes(); - TRI_server_t* server; + DatabaseFeature* databaseFeature; std::unordered_map> failedTransactions; std::unordered_set droppedCollections;