mirror of https://gitee.com/bigwinds/arangodb
added database.init-database
This commit is contained in:
parent
967d709f28
commit
a92d566234
|
@ -242,6 +242,7 @@ add_executable(${BIN_ARANGOD}
|
||||||
RestServer/EndpointFeature.cpp
|
RestServer/EndpointFeature.cpp
|
||||||
RestServer/FileDescriptorsFeature.cpp
|
RestServer/FileDescriptorsFeature.cpp
|
||||||
RestServer/FrontendFeature.cpp
|
RestServer/FrontendFeature.cpp
|
||||||
|
RestServer/InitDatabaseFeature.cpp
|
||||||
RestServer/QueryRegistryFeature.cpp
|
RestServer/QueryRegistryFeature.cpp
|
||||||
RestServer/RestServerFeature.cpp
|
RestServer/RestServerFeature.cpp
|
||||||
RestServer/ScriptFeature.cpp
|
RestServer/ScriptFeature.cpp
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
#include "ProgramOptions/Section.h"
|
#include "ProgramOptions/Section.h"
|
||||||
#include "Rest/Version.h"
|
#include "Rest/Version.h"
|
||||||
#include "RestServer/DatabaseServerFeature.h"
|
#include "RestServer/DatabaseServerFeature.h"
|
||||||
#include "RestServer/RestServerFeature.h"
|
|
||||||
#include "RestServer/QueryRegistryFeature.h"
|
#include "RestServer/QueryRegistryFeature.h"
|
||||||
|
#include "RestServer/RestServerFeature.h"
|
||||||
#include "V8Server/V8DealerFeature.h"
|
#include "V8Server/V8DealerFeature.h"
|
||||||
#include "V8Server/v8-query.h"
|
#include "V8Server/v8-query.h"
|
||||||
#include "V8Server/v8-vocbase.h"
|
#include "V8Server/v8-vocbase.h"
|
||||||
|
@ -65,12 +65,14 @@ DatabaseFeature::DatabaseFeature(ApplicationServer* server)
|
||||||
requiresElevatedPrivileges(false);
|
requiresElevatedPrivileges(false);
|
||||||
startsAfter("DatabaseServer");
|
startsAfter("DatabaseServer");
|
||||||
startsAfter("LogfileManager");
|
startsAfter("LogfileManager");
|
||||||
|
startsAfter("InitDatabase");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
|
void DatabaseFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
|
||||||
options->addSection("database", "Configure the database");
|
options->addSection("database", "Configure the database");
|
||||||
|
|
||||||
options->addOldOption("server.disable-replication-applier", "database.replication-applier");
|
options->addOldOption("server.disable-replication-applier",
|
||||||
|
"database.replication-applier");
|
||||||
|
|
||||||
options->addOption("--database.directory", "path to the database directory",
|
options->addOption("--database.directory", "path to the database directory",
|
||||||
new StringParameter(&_directory));
|
new StringParameter(&_directory));
|
||||||
|
@ -197,9 +199,9 @@ void DatabaseFeature::updateContexts() {
|
||||||
|
|
||||||
auto vocbase = _vocbase;
|
auto vocbase = _vocbase;
|
||||||
|
|
||||||
V8DealerFeature* dealer =
|
V8DealerFeature* dealer =
|
||||||
ApplicationServer::getFeature<V8DealerFeature>("V8Dealer");
|
ApplicationServer::getFeature<V8DealerFeature>("V8Dealer");
|
||||||
|
|
||||||
dealer->defineContextUpdate(
|
dealer->defineContextUpdate(
|
||||||
[queryRegistry, server, vocbase](
|
[queryRegistry, server, vocbase](
|
||||||
v8::Isolate* isolate, v8::Handle<v8::Context> context, size_t i) {
|
v8::Isolate* isolate, v8::Handle<v8::Context> context, size_t i) {
|
||||||
|
@ -243,16 +245,15 @@ void DatabaseFeature::openDatabases() {
|
||||||
defaults.forceSyncProperties = _forceSyncProperties;
|
defaults.forceSyncProperties = _forceSyncProperties;
|
||||||
|
|
||||||
// get authentication (if available)
|
// get authentication (if available)
|
||||||
RestServerFeature* rest =
|
RestServerFeature* rest =
|
||||||
ApplicationServer::getFeature<RestServerFeature>("RestServer");
|
ApplicationServer::getFeature<RestServerFeature>("RestServer");
|
||||||
|
|
||||||
defaults.requireAuthentication = rest->authentication();
|
defaults.requireAuthentication = rest->authentication();
|
||||||
defaults.requireAuthenticationUnixSockets =
|
defaults.requireAuthenticationUnixSockets = rest->authenticationUnixSockets();
|
||||||
rest->authenticationUnixSockets();
|
|
||||||
defaults.authenticateSystemOnly = rest->authenticationSystemOnly();
|
defaults.authenticateSystemOnly = rest->authenticationSystemOnly();
|
||||||
|
|
||||||
bool const iterateMarkersOnOpen =
|
bool const iterateMarkersOnOpen =
|
||||||
!wal::LogfileManager::instance()->hasFoundLastTick();
|
!wal::LogfileManager::instance()->hasFoundLastTick();
|
||||||
|
|
||||||
int res = TRI_InitServer(
|
int res = TRI_InitServer(
|
||||||
DatabaseServerFeature::SERVER, DatabaseServerFeature::INDEX_POOL,
|
DatabaseServerFeature::SERVER, DatabaseServerFeature::INDEX_POOL,
|
||||||
|
@ -267,15 +268,20 @@ void DatabaseFeature::openDatabases() {
|
||||||
res = TRI_StartServer(DatabaseServerFeature::SERVER, _checkVersion, _upgrade);
|
res = TRI_StartServer(DatabaseServerFeature::SERVER, _checkVersion, _upgrade);
|
||||||
|
|
||||||
if (res != TRI_ERROR_NO_ERROR) {
|
if (res != TRI_ERROR_NO_ERROR) {
|
||||||
if (_checkVersion && res == TRI_ERROR_ARANGO_EMPTY_DATADIR) {
|
if (res == TRI_ERROR_ARANGO_EMPTY_DATADIR) {
|
||||||
|
LOG_TOPIC(TRACE, Logger::STARTUP) << "database is empty";
|
||||||
_isInitiallyEmpty = true;
|
_isInitiallyEmpty = true;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (! _checkVersion || ! _isInitiallyEmpty) {
|
||||||
LOG(FATAL) << "cannot start server: " << TRI_errno_string(res);
|
LOG(FATAL) << "cannot start server: " << TRI_errno_string(res);
|
||||||
FATAL_ERROR_EXIT();
|
FATAL_ERROR_EXIT();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_TOPIC(TRACE, Logger::STARTUP) << "found system database";
|
if (!_isInitiallyEmpty) {
|
||||||
|
LOG_TOPIC(TRACE, Logger::STARTUP) << "found system database";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseFeature::closeDatabases() {
|
void DatabaseFeature::closeDatabases() {
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// DISCLAIMER
|
||||||
|
///
|
||||||
|
/// Copyright 2016 ArangoDB GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
/// you may not use this file except in compliance with the License.
|
||||||
|
/// You may obtain a copy of the License at
|
||||||
|
///
|
||||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
///
|
||||||
|
/// Unless required by applicable law or agreed to in writing, software
|
||||||
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
/// See the License for the specific language governing permissions and
|
||||||
|
/// limitations under the License.
|
||||||
|
///
|
||||||
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// @author Dr. Frank Celler
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "InitDatabaseFeature.h"
|
||||||
|
|
||||||
|
#include "Basics/FileUtils.h"
|
||||||
|
#include "Logger/LoggerFeature.h"
|
||||||
|
#include "Logger/LoggerFeature.h"
|
||||||
|
#include "ProgramOptions/ProgramOptions.h"
|
||||||
|
#include "ProgramOptions/Section.h"
|
||||||
|
#include "RestServer/DatabaseFeature.h"
|
||||||
|
|
||||||
|
using namespace arangodb;
|
||||||
|
using namespace arangodb::application_features;
|
||||||
|
using namespace arangodb::basics;
|
||||||
|
using namespace arangodb::options;
|
||||||
|
|
||||||
|
InitDatabaseFeature::InitDatabaseFeature(ApplicationServer* server)
|
||||||
|
: ApplicationFeature(server, "InitDatabase") {
|
||||||
|
setOptional(false);
|
||||||
|
requiresElevatedPrivileges(false);
|
||||||
|
startsAfter("Logger");
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitDatabaseFeature::collectOptions(
|
||||||
|
std::shared_ptr<ProgramOptions> options) {
|
||||||
|
options->addSection("database", "Configure the database");
|
||||||
|
|
||||||
|
options->addHiddenOption("--database.init-database",
|
||||||
|
"initializes an empty database",
|
||||||
|
new BooleanParameter(&_initDatabase));
|
||||||
|
|
||||||
|
options->addHiddenOption("--database.password",
|
||||||
|
"initial password of root user",
|
||||||
|
new StringParameter(&_password));
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitDatabaseFeature::validateOptions(
|
||||||
|
std::shared_ptr<ProgramOptions> options) {
|
||||||
|
ProgramOptions::ProcessingResult const& result = options->processingResult();
|
||||||
|
_seenPassword = result.touched("database.password");
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitDatabaseFeature::prepare() {
|
||||||
|
if (!_seenPassword) {
|
||||||
|
std::string env = "ARANGODB_DEFAULT_ROOT_PASSWORD";
|
||||||
|
char const* passworde = getenv(env.c_str());
|
||||||
|
|
||||||
|
if (passworde != nullptr && *passworde != '\0') {
|
||||||
|
env += "=";
|
||||||
|
putenv(const_cast<char*>(env.c_str()));
|
||||||
|
_password = passworde;
|
||||||
|
_seenPassword = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_initDatabase) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkEmptyDatabase();
|
||||||
|
|
||||||
|
if (!_seenPassword) {
|
||||||
|
while (true) {
|
||||||
|
std::string password1 =
|
||||||
|
readPassword("Please enter password for root user");
|
||||||
|
|
||||||
|
if (!password1.empty()) {
|
||||||
|
std::string password2 = readPassword("Repeat password");
|
||||||
|
|
||||||
|
if (password1 == password2) {
|
||||||
|
_password = password1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(ERR) << "passwords do not match, please repeat";
|
||||||
|
} else {
|
||||||
|
LOG(FATAL) << "initialization aborted by user";
|
||||||
|
FATAL_ERROR_EXIT();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitDatabaseFeature::start() {
|
||||||
|
if (!_initDatabase) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string InitDatabaseFeature::readPassword(std::string const& message) {
|
||||||
|
std::string password;
|
||||||
|
|
||||||
|
arangodb::Logger::flush();
|
||||||
|
std::cout << message << ": " << std::flush;
|
||||||
|
|
||||||
|
#ifdef TRI_HAVE_TERMIOS_H
|
||||||
|
TRI_SetStdinVisibility(false);
|
||||||
|
std::getline(std::cin, password);
|
||||||
|
|
||||||
|
TRI_SetStdinVisibility(true);
|
||||||
|
#else
|
||||||
|
std::getline(std::cin, password);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitDatabaseFeature::checkEmptyDatabase() {
|
||||||
|
auto database = ApplicationServer::getFeature<DatabaseFeature>("Database");
|
||||||
|
std::string path = database->directory();
|
||||||
|
std::string journals = FileUtils::buildFilename(path, "journals");
|
||||||
|
|
||||||
|
bool empty = false;
|
||||||
|
std::string message;
|
||||||
|
int code = 2;
|
||||||
|
|
||||||
|
if (FileUtils::exists(path)) {
|
||||||
|
if (!FileUtils::isDirectory(path)) {
|
||||||
|
message = "database path '" + path + "' is not a directory";
|
||||||
|
code = EXIT_FAILURE;
|
||||||
|
goto doexit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FileUtils::exists(journals)) {
|
||||||
|
if (!FileUtils::isDirectory(journals)) {
|
||||||
|
message =
|
||||||
|
"database journals path '" + journals + "' is not a directory";
|
||||||
|
code = EXIT_FAILURE;
|
||||||
|
goto doexit;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
empty = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
empty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty) {
|
||||||
|
message = "database already initialized, refusing to change root user";
|
||||||
|
goto doexit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
doexit:
|
||||||
|
LOG(FATAL) << message;
|
||||||
|
|
||||||
|
auto logger = ApplicationServer::getFeature<LoggerFeature>("Logger");
|
||||||
|
logger->unprepare();
|
||||||
|
|
||||||
|
TRI_EXIT_FUNCTION(code, nullptr);
|
||||||
|
exit(code);
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// DISCLAIMER
|
||||||
|
///
|
||||||
|
/// Copyright 2016 ArangoDB GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
/// you may not use this file except in compliance with the License.
|
||||||
|
/// You may obtain a copy of the License at
|
||||||
|
///
|
||||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
///
|
||||||
|
/// Unless required by applicable law or agreed to in writing, software
|
||||||
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
/// See the License for the specific language governing permissions and
|
||||||
|
/// limitations under the License.
|
||||||
|
///
|
||||||
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// @author Dr. Frank Celler
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef APPLICATION_FEATURES_INIT_DATABASE_FEATURE_H
|
||||||
|
#define APPLICATION_FEATURES_INIT_DATABASE_FEATURE_H 1
|
||||||
|
|
||||||
|
#include "ApplicationFeatures/ApplicationFeature.h"
|
||||||
|
|
||||||
|
namespace arangodb {
|
||||||
|
class InitDatabaseFeature final
|
||||||
|
: public application_features::ApplicationFeature {
|
||||||
|
public:
|
||||||
|
explicit InitDatabaseFeature(application_features::ApplicationServer* server);
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::string const& defaultPassword() const { return _password; }
|
||||||
|
bool isInitDatabase() const { return _initDatabase; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _initDatabase = false;
|
||||||
|
std::string _password;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void collectOptions(std::shared_ptr<options::ProgramOptions>) override final;
|
||||||
|
void validateOptions(std::shared_ptr<options::ProgramOptions>) override final;
|
||||||
|
void start() override final;
|
||||||
|
void prepare() override final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void checkEmptyDatabase();
|
||||||
|
std::string readPassword(std::string const&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _seenPassword = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -27,6 +27,7 @@
|
||||||
#include "ProgramOptions/Section.h"
|
#include "ProgramOptions/Section.h"
|
||||||
#include "RestServer/DatabaseFeature.h"
|
#include "RestServer/DatabaseFeature.h"
|
||||||
#include "RestServer/DatabaseServerFeature.h"
|
#include "RestServer/DatabaseServerFeature.h"
|
||||||
|
#include "RestServer/InitDatabaseFeature.h"
|
||||||
#include "V8/v8-globals.h"
|
#include "V8/v8-globals.h"
|
||||||
#include "V8Server/V8Context.h"
|
#include "V8Server/V8Context.h"
|
||||||
#include "V8Server/V8DealerFeature.h"
|
#include "V8Server/V8DealerFeature.h"
|
||||||
|
@ -58,7 +59,7 @@ UpgradeFeature::UpgradeFeature(
|
||||||
|
|
||||||
void UpgradeFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
|
void UpgradeFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
|
||||||
options->addSection("database", "Configure the database");
|
options->addSection("database", "Configure the database");
|
||||||
|
|
||||||
options->addOldOption("upgrade", "--database.auto-upgrade");
|
options->addOldOption("upgrade", "--database.auto-upgrade");
|
||||||
|
|
||||||
options->addOption("--database.auto-upgrade",
|
options->addOption("--database.auto-upgrade",
|
||||||
|
@ -86,12 +87,12 @@ void UpgradeFeature::validateOptions(std::shared_ptr<ProgramOptions> options) {
|
||||||
|
|
||||||
ApplicationServer::forceDisableFeatures(_nonServerFeatures);
|
ApplicationServer::forceDisableFeatures(_nonServerFeatures);
|
||||||
|
|
||||||
DatabaseFeature* database =
|
DatabaseFeature* database =
|
||||||
ApplicationServer::getFeature<DatabaseFeature>("Database");
|
ApplicationServer::getFeature<DatabaseFeature>("Database");
|
||||||
database->disableReplicationApplier();
|
database->disableReplicationApplier();
|
||||||
database->enableUpgrade();
|
database->enableUpgrade();
|
||||||
|
|
||||||
ClusterFeature* cluster =
|
ClusterFeature* cluster =
|
||||||
ApplicationServer::getFeature<ClusterFeature>("Cluster");
|
ApplicationServer::getFeature<ClusterFeature>("Cluster");
|
||||||
cluster->forceDisable();
|
cluster->forceDisable();
|
||||||
}
|
}
|
||||||
|
@ -103,7 +104,9 @@ void UpgradeFeature::start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// and force shutdown
|
// and force shutdown
|
||||||
if (_upgrade) {
|
auto init = ApplicationServer::getFeature<InitDatabaseFeature>("InitDatabase");
|
||||||
|
|
||||||
|
if (_upgrade || init->isInitDatabase()) {
|
||||||
server()->beginShutdown();
|
server()->beginShutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,27 +150,38 @@ void UpgradeFeature::upgradeDatabase() {
|
||||||
v8::HandleScope scope(context->_isolate);
|
v8::HandleScope scope(context->_isolate);
|
||||||
|
|
||||||
v8::Handle<v8::Object> args = v8::Object::New(context->_isolate);
|
v8::Handle<v8::Object> args = v8::Object::New(context->_isolate);
|
||||||
|
|
||||||
args->Set(TRI_V8_ASCII_STRING2(context->_isolate, "upgrade"),
|
args->Set(TRI_V8_ASCII_STRING2(context->_isolate, "upgrade"),
|
||||||
v8::Boolean::New(context->_isolate, _upgrade));
|
v8::Boolean::New(context->_isolate, _upgrade));
|
||||||
|
|
||||||
|
auto init = ApplicationServer::getFeature<InitDatabaseFeature>(
|
||||||
|
"InitDatabase");
|
||||||
|
|
||||||
|
if (init != nullptr) {
|
||||||
|
args->Set(
|
||||||
|
TRI_V8_ASCII_STRING2(context->_isolate, "password"),
|
||||||
|
TRI_V8_STD_STRING2(context->_isolate, init->defaultPassword()));
|
||||||
|
}
|
||||||
|
|
||||||
localContext->Global()->Set(
|
localContext->Global()->Set(
|
||||||
TRI_V8_ASCII_STRING2(context->_isolate, "UPGRADE_ARGS"), args);
|
TRI_V8_ASCII_STRING2(context->_isolate, "UPGRADE_ARGS"), args);
|
||||||
|
|
||||||
bool ok = TRI_UpgradeDatabase(vocbase, localContext);
|
bool ok = TRI_UpgradeDatabase(vocbase, localContext);
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
if (localContext->Global()->Has(
|
if (localContext->Global()->Has(TRI_V8_ASCII_STRING2(
|
||||||
TRI_V8_ASCII_STRING2(context->_isolate, "UPGRADE_STARTED"))) {
|
context->_isolate, "UPGRADE_STARTED"))) {
|
||||||
localContext->Exit();
|
localContext->Exit();
|
||||||
if (_upgrade) {
|
if (_upgrade) {
|
||||||
LOG(FATAL) << "Database '" << vocbase->_name
|
LOG(FATAL) << "Database '" << vocbase->_name
|
||||||
<< "' upgrade failed. Please inspect the logs from "
|
<< "' upgrade failed. Please inspect the logs from "
|
||||||
"the upgrade procedure";
|
"the upgrade procedure";
|
||||||
FATAL_ERROR_EXIT();
|
FATAL_ERROR_EXIT();
|
||||||
} else {
|
} else {
|
||||||
LOG(FATAL) << "Database '" << vocbase->_name
|
LOG(FATAL)
|
||||||
<< "' needs upgrade. Please start the server with the "
|
<< "Database '" << vocbase->_name
|
||||||
"--database.auto-upgrade option";
|
<< "' needs upgrade. Please start the server with the "
|
||||||
|
"--database.auto-upgrade option";
|
||||||
FATAL_ERROR_EXIT();
|
FATAL_ERROR_EXIT();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -175,12 +189,14 @@ void UpgradeFeature::upgradeDatabase() {
|
||||||
FATAL_ERROR_EXIT();
|
FATAL_ERROR_EXIT();
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(DEBUG) << "database '" << vocbase->_name << "' init/upgrade done";
|
LOG(DEBUG) << "database '" << vocbase->_name
|
||||||
|
<< "' init/upgrade done";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// finally leave the context. otherwise v8 will crash with assertion failure
|
// finally leave the context. otherwise v8 will crash with assertion
|
||||||
|
// failure
|
||||||
// when we delete
|
// when we delete
|
||||||
// the context locker below
|
// the context locker below
|
||||||
localContext->Exit();
|
localContext->Exit();
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
#include "RestServer/EndpointFeature.h"
|
#include "RestServer/EndpointFeature.h"
|
||||||
#include "RestServer/FileDescriptorsFeature.h"
|
#include "RestServer/FileDescriptorsFeature.h"
|
||||||
#include "RestServer/FrontendFeature.h"
|
#include "RestServer/FrontendFeature.h"
|
||||||
|
#include "RestServer/InitDatabaseFeature.h"
|
||||||
#include "RestServer/QueryRegistryFeature.h"
|
#include "RestServer/QueryRegistryFeature.h"
|
||||||
#include "RestServer/RestServerFeature.h"
|
#include "RestServer/RestServerFeature.h"
|
||||||
#include "RestServer/ScriptFeature.h"
|
#include "RestServer/ScriptFeature.h"
|
||||||
|
@ -119,6 +120,7 @@ static int runServer(int argc, char** argv) {
|
||||||
server.addFeature(new FileDescriptorsFeature(&server));
|
server.addFeature(new FileDescriptorsFeature(&server));
|
||||||
server.addFeature(new FoxxQueuesFeature(&server));
|
server.addFeature(new FoxxQueuesFeature(&server));
|
||||||
server.addFeature(new FrontendFeature(&server));
|
server.addFeature(new FrontendFeature(&server));
|
||||||
|
server.addFeature(new InitDatabaseFeature(&server));
|
||||||
server.addFeature(new LanguageFeature(&server));
|
server.addFeature(new LanguageFeature(&server));
|
||||||
server.addFeature(new LogfileManager(&server));
|
server.addFeature(new LogfileManager(&server));
|
||||||
server.addFeature(new LoggerBufferFeature(&server));
|
server.addFeature(new LoggerBufferFeature(&server));
|
||||||
|
|
|
@ -3050,8 +3050,10 @@ bool TRI_UpgradeDatabase(TRI_vocbase_t* vocbase,
|
||||||
v8g->_vocbase = vocbase;
|
v8g->_vocbase = vocbase;
|
||||||
|
|
||||||
auto startupLoader = V8DealerFeature::DEALER->startupLoader();
|
auto startupLoader = V8DealerFeature::DEALER->startupLoader();
|
||||||
|
|
||||||
v8::Handle<v8::Value> result = startupLoader->executeGlobalScript(
|
v8::Handle<v8::Value> result = startupLoader->executeGlobalScript(
|
||||||
isolate, isolate->GetCurrentContext(), "server/upgrade-database.js");
|
isolate, isolate->GetCurrentContext(), "server/upgrade-database.js");
|
||||||
|
|
||||||
bool ok = TRI_ObjectToBoolean(result);
|
bool ok = TRI_ObjectToBoolean(result);
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
|
|
|
@ -31,7 +31,10 @@
|
||||||
/// @author Copyright 2014, triAGENS GmbH, Cologne, Germany
|
/// @author Copyright 2014, triAGENS GmbH, Cologne, Germany
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
(function(args) {
|
(function() {
|
||||||
|
var args = global.UPGRADE_ARGS;
|
||||||
|
delete global.UPGRADE_ARGS;
|
||||||
|
|
||||||
const internal = require("internal");
|
const internal = require("internal");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const console = require("console");
|
const console = require("console");
|
||||||
|
@ -40,7 +43,7 @@
|
||||||
const db = internal.db;
|
const db = internal.db;
|
||||||
const shallowCopy = require("@arangodb/util").shallowCopy;
|
const shallowCopy = require("@arangodb/util").shallowCopy;
|
||||||
|
|
||||||
const defaultRootPW = require("process").env.ARANGODB_DEFAULT_ROOT_PASSWORD || "";
|
const defaultRootPW = args.password || "";
|
||||||
|
|
||||||
function upgrade() {
|
function upgrade() {
|
||||||
|
|
||||||
|
@ -776,8 +779,6 @@
|
||||||
// set this global variable to inform the server we actually got until here...
|
// set this global variable to inform the server we actually got until here...
|
||||||
global.UPGRADE_STARTED = true;
|
global.UPGRADE_STARTED = true;
|
||||||
|
|
||||||
delete global.UPGRADE_ARGS;
|
|
||||||
|
|
||||||
// and run the upgrade
|
// and run the upgrade
|
||||||
return upgrade();
|
return upgrade();
|
||||||
}(global.UPGRADE_ARGS));
|
}());
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
#include "ApplicationFeatures/ApplicationFeature.h"
|
#include "ApplicationFeatures/ApplicationFeature.h"
|
||||||
#include "ApplicationFeatures/PrivilegeFeature.h"
|
#include "ApplicationFeatures/PrivilegeFeature.h"
|
||||||
#include "Basics/StringUtils.h"
|
#include "Basics/StringUtils.h"
|
||||||
#include "ProgramOptions/ArgumentParser.h"
|
|
||||||
#include "Logger/Logger.h"
|
#include "Logger/Logger.h"
|
||||||
|
#include "ProgramOptions/ArgumentParser.h"
|
||||||
|
|
||||||
using namespace arangodb::application_features;
|
using namespace arangodb::application_features;
|
||||||
using namespace arangodb::basics;
|
using namespace arangodb::basics;
|
||||||
|
@ -194,7 +194,6 @@ void ApplicationServer::run(int argc, char* argv[]) {
|
||||||
reportServerProgress(_state);
|
reportServerProgress(_state);
|
||||||
start();
|
start();
|
||||||
|
|
||||||
|
|
||||||
// wait until we get signaled the shutdown request
|
// wait until we get signaled the shutdown request
|
||||||
_state = ServerState::IN_WAIT;
|
_state = ServerState::IN_WAIT;
|
||||||
reportServerProgress(_state);
|
reportServerProgress(_state);
|
||||||
|
@ -268,11 +267,13 @@ void ApplicationServer::collectOptions() {
|
||||||
_options->addHiddenOption("--dump-dependencies", "dump dependency graph",
|
_options->addHiddenOption("--dump-dependencies", "dump dependency graph",
|
||||||
new BooleanParameter(&_dumpDependencies));
|
new BooleanParameter(&_dumpDependencies));
|
||||||
|
|
||||||
apply([this](ApplicationFeature* feature) {
|
apply(
|
||||||
LOG_TOPIC(TRACE, Logger::STARTUP) << feature->name() << "::loadOptions";
|
[this](ApplicationFeature* feature) {
|
||||||
feature->collectOptions(_options);
|
LOG_TOPIC(TRACE, Logger::STARTUP) << feature->name() << "::loadOptions";
|
||||||
reportFeatureProgress(_state, feature->name());
|
feature->collectOptions(_options);
|
||||||
}, true);
|
reportFeatureProgress(_state, feature->name());
|
||||||
|
},
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplicationServer::parseOptions(int argc, char* argv[]) {
|
void ApplicationServer::parseOptions(int argc, char* argv[]) {
|
||||||
|
@ -366,18 +367,21 @@ void ApplicationServer::setupDependencies(bool failOnMissing) {
|
||||||
|
|
||||||
// first check if a feature references an unknown other feature
|
// first check if a feature references an unknown other feature
|
||||||
if (failOnMissing) {
|
if (failOnMissing) {
|
||||||
apply([this](ApplicationFeature* feature) {
|
apply(
|
||||||
for (auto& other : feature->requires()) {
|
[this](ApplicationFeature* feature) {
|
||||||
if (!this->exists(other)) {
|
for (auto& other : feature->requires()) {
|
||||||
fail("feature '" + feature->name() +
|
if (!this->exists(other)) {
|
||||||
"' depends on unknown feature '" + other + "'");
|
fail("feature '" + feature->name() +
|
||||||
}
|
"' depends on unknown feature '" + other + "'");
|
||||||
if (!this->feature(other)->isEnabled()) {
|
}
|
||||||
fail("enabled feature '" + feature->name() +
|
if (!this->feature(other)->isEnabled()) {
|
||||||
"' depends on other feature '" + other + "', which is disabled");
|
fail("enabled feature '" + feature->name() +
|
||||||
}
|
"' depends on other feature '" + other +
|
||||||
}
|
"', which is disabled");
|
||||||
}, true);
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// first insert all features, even the inactive ones
|
// first insert all features, even the inactive ones
|
||||||
|
@ -478,14 +482,16 @@ void ApplicationServer::prepare() {
|
||||||
feature->prepare();
|
feature->prepare();
|
||||||
feature->state(FeatureState::PREPARED);
|
feature->state(FeatureState::PREPARED);
|
||||||
} catch (std::exception const& ex) {
|
} catch (std::exception const& ex) {
|
||||||
LOG(ERR) << "caught exception during prepare of feature " << feature->name() << ": " << ex.what();
|
LOG(ERR) << "caught exception during prepare of feature "
|
||||||
|
<< feature->name() << ": " << ex.what();
|
||||||
// restore original privileges
|
// restore original privileges
|
||||||
if (!privilegesElevated) {
|
if (!privilegesElevated) {
|
||||||
raisePrivilegesTemporarily();
|
raisePrivilegesTemporarily();
|
||||||
}
|
}
|
||||||
throw;
|
throw;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
LOG(ERR) << "caught unknown exception during prepare of feature " << feature->name();
|
LOG(ERR) << "caught unknown exception during prepare of feature "
|
||||||
|
<< feature->name();
|
||||||
// restore original privileges
|
// restore original privileges
|
||||||
if (!privilegesElevated) {
|
if (!privilegesElevated) {
|
||||||
raisePrivilegesTemporarily();
|
raisePrivilegesTemporarily();
|
||||||
|
@ -511,16 +517,19 @@ void ApplicationServer::start() {
|
||||||
feature->state(FeatureState::STARTED);
|
feature->state(FeatureState::STARTED);
|
||||||
reportFeatureProgress(_state, feature->name());
|
reportFeatureProgress(_state, feature->name());
|
||||||
} catch (std::exception const& ex) {
|
} catch (std::exception const& ex) {
|
||||||
LOG(ERR) << "caught exception during start of feature " << feature->name() << ": " << ex.what() << ". shutting down";
|
LOG(ERR) << "caught exception during start of feature " << feature->name()
|
||||||
|
<< ": " << ex.what() << ". shutting down";
|
||||||
abortStartup = true;
|
abortStartup = true;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
LOG(ERR) << "caught unknown exception during start of feature " << feature->name() << ". shutting down";
|
LOG(ERR) << "caught unknown exception during start of feature "
|
||||||
|
<< feature->name() << ". shutting down";
|
||||||
abortStartup = true;
|
abortStartup = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (abortStartup) {
|
if (abortStartup) {
|
||||||
// try to stop all feature that we just started
|
// try to stop all feature that we just started
|
||||||
for (auto it = _orderedFeatures.rbegin(); it != _orderedFeatures.rend(); ++it) {
|
for (auto it = _orderedFeatures.rbegin(); it != _orderedFeatures.rend();
|
||||||
|
++it) {
|
||||||
auto feature = *it;
|
auto feature = *it;
|
||||||
if (feature->state() == FeatureState::STARTED) {
|
if (feature->state() == FeatureState::STARTED) {
|
||||||
LOG(TRACE) << "forcefully stopping feature " << feature->name();
|
LOG(TRACE) << "forcefully stopping feature " << feature->name();
|
||||||
|
@ -541,7 +550,8 @@ void ApplicationServer::start() {
|
||||||
void ApplicationServer::stop() {
|
void ApplicationServer::stop() {
|
||||||
LOG_TOPIC(TRACE, Logger::STARTUP) << "ApplicationServer::stop";
|
LOG_TOPIC(TRACE, Logger::STARTUP) << "ApplicationServer::stop";
|
||||||
|
|
||||||
for (auto it = _orderedFeatures.rbegin(); it != _orderedFeatures.rend(); ++it) {
|
for (auto it = _orderedFeatures.rbegin(); it != _orderedFeatures.rend();
|
||||||
|
++it) {
|
||||||
auto feature = *it;
|
auto feature = *it;
|
||||||
|
|
||||||
LOG_TOPIC(TRACE, Logger::STARTUP) << feature->name() << "::stop";
|
LOG_TOPIC(TRACE, Logger::STARTUP) << feature->name() << "::stop";
|
||||||
|
@ -554,7 +564,8 @@ void ApplicationServer::stop() {
|
||||||
void ApplicationServer::unprepare() {
|
void ApplicationServer::unprepare() {
|
||||||
LOG_TOPIC(TRACE, Logger::STARTUP) << "ApplicationServer::unprepare";
|
LOG_TOPIC(TRACE, Logger::STARTUP) << "ApplicationServer::unprepare";
|
||||||
|
|
||||||
for (auto it = _orderedFeatures.rbegin(); it != _orderedFeatures.rend(); ++it) {
|
for (auto it = _orderedFeatures.rbegin(); it != _orderedFeatures.rend();
|
||||||
|
++it) {
|
||||||
auto feature = *it;
|
auto feature = *it;
|
||||||
|
|
||||||
LOG_TOPIC(TRACE, Logger::STARTUP) << feature->name() << "::unprepare";
|
LOG_TOPIC(TRACE, Logger::STARTUP) << feature->name() << "::unprepare";
|
||||||
|
|
|
@ -30,7 +30,8 @@ using namespace arangodb;
|
||||||
using namespace arangodb::options;
|
using namespace arangodb::options;
|
||||||
|
|
||||||
ShutdownFeature::ShutdownFeature(
|
ShutdownFeature::ShutdownFeature(
|
||||||
application_features::ApplicationServer* server, std::vector<std::string> const& features)
|
application_features::ApplicationServer* server,
|
||||||
|
std::vector<std::string> const& features)
|
||||||
: ApplicationFeature(server, "Shutdown") {
|
: ApplicationFeature(server, "Shutdown") {
|
||||||
setOptional(true);
|
setOptional(true);
|
||||||
requiresElevatedPrivileges(false);
|
requiresElevatedPrivileges(false);
|
||||||
|
@ -43,6 +44,4 @@ ShutdownFeature::ShutdownFeature(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShutdownFeature::start() {
|
void ShutdownFeature::start() { server()->beginShutdown(); }
|
||||||
server()->beginShutdown();
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue