1
0
Fork 0

moved database lookup functions into DatabaseFeature

This commit is contained in:
jsteemann 2016-07-25 14:56:39 +02:00
parent b288d3e4dd
commit 33c94e5041
14 changed files with 262 additions and 369 deletions

View File

@ -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<DatabaseFeature>("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<DatabaseFeature>("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<TRI_voc_tick_t> localIds =
TRI_GetIdsCoordinatorDatabaseServer(_server);
std::vector<TRI_voc_tick_t> 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<DatabaseFeature>("Database");
databaseFeature->dropDatabaseCoordinator(id, false);
}
}

View File

@ -216,31 +216,30 @@ void GeneralServerFeature::validateOptions(std::shared_ptr<ProgramOptions>) {
}
}
static TRI_vocbase_t* LookupDatabaseFromRequest(GeneralRequest* request,
TRI_server_t* server) {
static TRI_vocbase_t* LookupDatabaseFromRequest(GeneralRequest* request) {
auto databaseFeature = application_features::ApplicationServer::getFeature<DatabaseFeature>("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<TRI_server_t*>(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();

View File

@ -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);

View File

@ -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<DatabaseFeature>("Database");
if (ServerState::instance()->isCoordinator()) {
std::vector<TRI_voc_tick_t> 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<std::string> 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<std::string> 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);
}
}
}

View File

@ -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<TRI_voc_tick_t> DatabaseFeature::getDatabaseIdsCoordinator(bool includeSystem) {
std::vector<TRI_voc_tick_t> 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<TRI_voc_tick_t> DatabaseFeature::getDatabaseIds(bool includeSystem) {
std::vector<TRI_voc_tick_t> 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<std::string> DatabaseFeature::getDatabaseNames() {
std::vector<std::string> 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<std::string> DatabaseFeature::getDatabaseNamesForUser(std::string const& username) {
std::vector<std::string> 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);

View File

@ -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<TRI_voc_tick_t> getDatabaseIdsCoordinator(bool includeSystem);
std::vector<TRI_voc_tick_t> getDatabaseIds(bool includeSystem);
std::vector<std::string> getDatabaseNames();
std::vector<std::string> 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; }

View File

@ -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<DatabaseFeature>("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<DatabaseFeature>("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<DatabaseFeature>("Database");
databaseFeature->releaseDatabase(_database);
}
}

View File

@ -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<DatabaseFeature>("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<DatabaseFeature>("Database");
databaseFeature->releaseDatabase(vocbase());
}
public:

View File

@ -2031,7 +2031,8 @@ static void JS_UseDatabase(v8::FunctionCallbackInfo<v8::Value> const& args) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_FORBIDDEN);
}
std::string name = TRI_ObjectToString(args[0]);
auto databaseFeature = application_features::ApplicationServer::getFeature<DatabaseFeature>("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<v8::Value> const& args) {
}
if (ServerState::instance()->isCoordinator()) {
vocbase = TRI_UseCoordinatorDatabaseServer(
static_cast<TRI_server_t*>(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<TRI_server_t*>(v8g->_server),
name.c_str());
vocbase = databaseFeature->useDatabase(name);
}
if (vocbase == nullptr) {
@ -2067,8 +2066,7 @@ static void JS_UseDatabase(v8::FunctionCallbackInfo<v8::Value> const& args) {
v8g->_vocbase = vocbase;
TRI_ASSERT(orig != vocbase);
TRI_ReleaseDatabaseServer(static_cast<TRI_server_t*>(v8g->_server),
static_cast<TRI_vocbase_t*>(orig));
databaseFeature->releaseDatabase(static_cast<TRI_vocbase_t*>(orig));
TRI_V8_RETURN(WrapVocBase(isolate, vocbase));
}
@ -2171,26 +2169,15 @@ static void JS_Databases(v8::FunctionCallbackInfo<v8::Value> const& args) {
return;
}
TRI_GET_GLOBALS();
auto databaseFeature = application_features::ApplicationServer::getFeature<DatabaseFeature>("Database");
std::vector<std::string> names;
int res;
if (argc == 0) {
// return all databases
res = TRI_GetDatabaseNamesServer(static_cast<TRI_server_t*>(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<TRI_server_t*>(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<v8::Array> 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<DatabaseFeature>("Database");
while (++tries <= 6000) {
vocbase = TRI_UseByIdCoordinatorDatabaseServer(
static_cast<TRI_server_t*>(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<DatabaseFeature>("Database");
std::string const name = TRI_ObjectToString(args[0]);
TRI_vocbase_t* vocbase = TRI_UseCoordinatorDatabaseServer(
static_cast<TRI_server_t*>(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<TRI_server_t*>(v8g->_server), id);
TRI_vocbase_t* vocbase = databaseFeature->useDatabaseCoordinator(id);
if (vocbase == nullptr) {
// object has vanished

View File

@ -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_voc_tick_t> TRI_GetIdsCoordinatorDatabaseServer(
TRI_server_t* server, bool includeSystem) {
std::vector<TRI_voc_tick_t> 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<std::string>& 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<std::string>& 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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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_voc_tick_t> 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<std::string>&);
////////////////////////////////////////////////////////////////////////////////
/// @brief return the list of all database names
////////////////////////////////////////////////////////////////////////////////
int TRI_GetDatabaseNamesServer(TRI_server_t*, std::vector<std::string>&);
////////////////////////////////////////////////////////////////////////////////
/// @brief sets the current operation mode of the server
////////////////////////////////////////////////////////////////////////////////

View File

@ -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);

View File

@ -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<DatabaseFeature>("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<DatabaseFeature>("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<DatabaseFeature>("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<DatabaseFeature>("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<DatabaseFeature>("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<DatabaseFeature>("Database");
databaseFeature->dropDatabase(databaseId, false, true, false);
state->databaseFeature->dropDatabase(databaseId, false, true, false);
}
#ifdef ARANGODB_ENABLE_ROCKSDB

View File

@ -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<TRI_voc_tid_t, std::pair<TRI_voc_tick_t, bool>>
failedTransactions;
std::unordered_set<TRI_voc_cid_t> droppedCollections;