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/FileDescriptorsFeature.cpp
|
||||
RestServer/FrontendFeature.cpp
|
||||
RestServer/InitDatabaseFeature.cpp
|
||||
RestServer/QueryRegistryFeature.cpp
|
||||
RestServer/RestServerFeature.cpp
|
||||
RestServer/ScriptFeature.cpp
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
#include "ProgramOptions/Section.h"
|
||||
#include "Rest/Version.h"
|
||||
#include "RestServer/DatabaseServerFeature.h"
|
||||
#include "RestServer/RestServerFeature.h"
|
||||
#include "RestServer/QueryRegistryFeature.h"
|
||||
#include "RestServer/RestServerFeature.h"
|
||||
#include "V8Server/V8DealerFeature.h"
|
||||
#include "V8Server/v8-query.h"
|
||||
#include "V8Server/v8-vocbase.h"
|
||||
|
@ -65,12 +65,14 @@ DatabaseFeature::DatabaseFeature(ApplicationServer* server)
|
|||
requiresElevatedPrivileges(false);
|
||||
startsAfter("DatabaseServer");
|
||||
startsAfter("LogfileManager");
|
||||
startsAfter("InitDatabase");
|
||||
}
|
||||
|
||||
void DatabaseFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
|
||||
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",
|
||||
new StringParameter(&_directory));
|
||||
|
@ -197,9 +199,9 @@ void DatabaseFeature::updateContexts() {
|
|||
|
||||
auto vocbase = _vocbase;
|
||||
|
||||
V8DealerFeature* dealer =
|
||||
V8DealerFeature* dealer =
|
||||
ApplicationServer::getFeature<V8DealerFeature>("V8Dealer");
|
||||
|
||||
|
||||
dealer->defineContextUpdate(
|
||||
[queryRegistry, server, vocbase](
|
||||
v8::Isolate* isolate, v8::Handle<v8::Context> context, size_t i) {
|
||||
|
@ -243,16 +245,15 @@ void DatabaseFeature::openDatabases() {
|
|||
defaults.forceSyncProperties = _forceSyncProperties;
|
||||
|
||||
// get authentication (if available)
|
||||
RestServerFeature* rest =
|
||||
RestServerFeature* rest =
|
||||
ApplicationServer::getFeature<RestServerFeature>("RestServer");
|
||||
|
||||
defaults.requireAuthentication = rest->authentication();
|
||||
defaults.requireAuthenticationUnixSockets =
|
||||
rest->authenticationUnixSockets();
|
||||
defaults.requireAuthenticationUnixSockets = rest->authenticationUnixSockets();
|
||||
defaults.authenticateSystemOnly = rest->authenticationSystemOnly();
|
||||
|
||||
|
||||
bool const iterateMarkersOnOpen =
|
||||
!wal::LogfileManager::instance()->hasFoundLastTick();
|
||||
!wal::LogfileManager::instance()->hasFoundLastTick();
|
||||
|
||||
int res = TRI_InitServer(
|
||||
DatabaseServerFeature::SERVER, DatabaseServerFeature::INDEX_POOL,
|
||||
|
@ -267,15 +268,20 @@ void DatabaseFeature::openDatabases() {
|
|||
res = TRI_StartServer(DatabaseServerFeature::SERVER, _checkVersion, _upgrade);
|
||||
|
||||
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;
|
||||
} else {
|
||||
}
|
||||
|
||||
if (! _checkVersion || ! _isInitiallyEmpty) {
|
||||
LOG(FATAL) << "cannot start server: " << TRI_errno_string(res);
|
||||
FATAL_ERROR_EXIT();
|
||||
}
|
||||
}
|
||||
|
||||
LOG_TOPIC(TRACE, Logger::STARTUP) << "found system database";
|
||||
if (!_isInitiallyEmpty) {
|
||||
LOG_TOPIC(TRACE, Logger::STARTUP) << "found system database";
|
||||
}
|
||||
}
|
||||
|
||||
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 "RestServer/DatabaseFeature.h"
|
||||
#include "RestServer/DatabaseServerFeature.h"
|
||||
#include "RestServer/InitDatabaseFeature.h"
|
||||
#include "V8/v8-globals.h"
|
||||
#include "V8Server/V8Context.h"
|
||||
#include "V8Server/V8DealerFeature.h"
|
||||
|
@ -58,7 +59,7 @@ UpgradeFeature::UpgradeFeature(
|
|||
|
||||
void UpgradeFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
|
||||
options->addSection("database", "Configure the database");
|
||||
|
||||
|
||||
options->addOldOption("upgrade", "--database.auto-upgrade");
|
||||
|
||||
options->addOption("--database.auto-upgrade",
|
||||
|
@ -86,12 +87,12 @@ void UpgradeFeature::validateOptions(std::shared_ptr<ProgramOptions> options) {
|
|||
|
||||
ApplicationServer::forceDisableFeatures(_nonServerFeatures);
|
||||
|
||||
DatabaseFeature* database =
|
||||
DatabaseFeature* database =
|
||||
ApplicationServer::getFeature<DatabaseFeature>("Database");
|
||||
database->disableReplicationApplier();
|
||||
database->enableUpgrade();
|
||||
|
||||
ClusterFeature* cluster =
|
||||
ClusterFeature* cluster =
|
||||
ApplicationServer::getFeature<ClusterFeature>("Cluster");
|
||||
cluster->forceDisable();
|
||||
}
|
||||
|
@ -103,7 +104,9 @@ void UpgradeFeature::start() {
|
|||
}
|
||||
|
||||
// and force shutdown
|
||||
if (_upgrade) {
|
||||
auto init = ApplicationServer::getFeature<InitDatabaseFeature>("InitDatabase");
|
||||
|
||||
if (_upgrade || init->isInitDatabase()) {
|
||||
server()->beginShutdown();
|
||||
}
|
||||
}
|
||||
|
@ -147,27 +150,38 @@ void UpgradeFeature::upgradeDatabase() {
|
|||
v8::HandleScope scope(context->_isolate);
|
||||
|
||||
v8::Handle<v8::Object> args = v8::Object::New(context->_isolate);
|
||||
|
||||
args->Set(TRI_V8_ASCII_STRING2(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(
|
||||
TRI_V8_ASCII_STRING2(context->_isolate, "UPGRADE_ARGS"), args);
|
||||
|
||||
bool ok = TRI_UpgradeDatabase(vocbase, localContext);
|
||||
|
||||
if (!ok) {
|
||||
if (localContext->Global()->Has(
|
||||
TRI_V8_ASCII_STRING2(context->_isolate, "UPGRADE_STARTED"))) {
|
||||
if (localContext->Global()->Has(TRI_V8_ASCII_STRING2(
|
||||
context->_isolate, "UPGRADE_STARTED"))) {
|
||||
localContext->Exit();
|
||||
if (_upgrade) {
|
||||
LOG(FATAL) << "Database '" << vocbase->_name
|
||||
<< "' upgrade failed. Please inspect the logs from "
|
||||
<< "' upgrade failed. Please inspect the logs from "
|
||||
"the upgrade procedure";
|
||||
FATAL_ERROR_EXIT();
|
||||
} else {
|
||||
LOG(FATAL) << "Database '" << vocbase->_name
|
||||
<< "' needs upgrade. Please start the server with the "
|
||||
"--database.auto-upgrade option";
|
||||
LOG(FATAL)
|
||||
<< "Database '" << vocbase->_name
|
||||
<< "' needs upgrade. Please start the server with the "
|
||||
"--database.auto-upgrade option";
|
||||
FATAL_ERROR_EXIT();
|
||||
}
|
||||
} else {
|
||||
|
@ -175,12 +189,14 @@ void UpgradeFeature::upgradeDatabase() {
|
|||
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
|
||||
// the context locker below
|
||||
localContext->Exit();
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "RestServer/EndpointFeature.h"
|
||||
#include "RestServer/FileDescriptorsFeature.h"
|
||||
#include "RestServer/FrontendFeature.h"
|
||||
#include "RestServer/InitDatabaseFeature.h"
|
||||
#include "RestServer/QueryRegistryFeature.h"
|
||||
#include "RestServer/RestServerFeature.h"
|
||||
#include "RestServer/ScriptFeature.h"
|
||||
|
@ -119,6 +120,7 @@ static int runServer(int argc, char** argv) {
|
|||
server.addFeature(new FileDescriptorsFeature(&server));
|
||||
server.addFeature(new FoxxQueuesFeature(&server));
|
||||
server.addFeature(new FrontendFeature(&server));
|
||||
server.addFeature(new InitDatabaseFeature(&server));
|
||||
server.addFeature(new LanguageFeature(&server));
|
||||
server.addFeature(new LogfileManager(&server));
|
||||
server.addFeature(new LoggerBufferFeature(&server));
|
||||
|
|
|
@ -3050,8 +3050,10 @@ bool TRI_UpgradeDatabase(TRI_vocbase_t* vocbase,
|
|||
v8g->_vocbase = vocbase;
|
||||
|
||||
auto startupLoader = V8DealerFeature::DEALER->startupLoader();
|
||||
|
||||
v8::Handle<v8::Value> result = startupLoader->executeGlobalScript(
|
||||
isolate, isolate->GetCurrentContext(), "server/upgrade-database.js");
|
||||
|
||||
bool ok = TRI_ObjectToBoolean(result);
|
||||
|
||||
if (!ok) {
|
||||
|
|
|
@ -31,7 +31,10 @@
|
|||
/// @author Copyright 2014, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
(function(args) {
|
||||
(function() {
|
||||
var args = global.UPGRADE_ARGS;
|
||||
delete global.UPGRADE_ARGS;
|
||||
|
||||
const internal = require("internal");
|
||||
const fs = require("fs");
|
||||
const console = require("console");
|
||||
|
@ -40,7 +43,7 @@
|
|||
const db = internal.db;
|
||||
const shallowCopy = require("@arangodb/util").shallowCopy;
|
||||
|
||||
const defaultRootPW = require("process").env.ARANGODB_DEFAULT_ROOT_PASSWORD || "";
|
||||
const defaultRootPW = args.password || "";
|
||||
|
||||
function upgrade() {
|
||||
|
||||
|
@ -776,8 +779,6 @@
|
|||
// set this global variable to inform the server we actually got until here...
|
||||
global.UPGRADE_STARTED = true;
|
||||
|
||||
delete global.UPGRADE_ARGS;
|
||||
|
||||
// and run the upgrade
|
||||
return upgrade();
|
||||
}(global.UPGRADE_ARGS));
|
||||
}());
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
#include "ApplicationFeatures/ApplicationFeature.h"
|
||||
#include "ApplicationFeatures/PrivilegeFeature.h"
|
||||
#include "Basics/StringUtils.h"
|
||||
#include "ProgramOptions/ArgumentParser.h"
|
||||
#include "Logger/Logger.h"
|
||||
#include "ProgramOptions/ArgumentParser.h"
|
||||
|
||||
using namespace arangodb::application_features;
|
||||
using namespace arangodb::basics;
|
||||
|
@ -194,7 +194,6 @@ void ApplicationServer::run(int argc, char* argv[]) {
|
|||
reportServerProgress(_state);
|
||||
start();
|
||||
|
||||
|
||||
// wait until we get signaled the shutdown request
|
||||
_state = ServerState::IN_WAIT;
|
||||
reportServerProgress(_state);
|
||||
|
@ -268,11 +267,13 @@ void ApplicationServer::collectOptions() {
|
|||
_options->addHiddenOption("--dump-dependencies", "dump dependency graph",
|
||||
new BooleanParameter(&_dumpDependencies));
|
||||
|
||||
apply([this](ApplicationFeature* feature) {
|
||||
LOG_TOPIC(TRACE, Logger::STARTUP) << feature->name() << "::loadOptions";
|
||||
feature->collectOptions(_options);
|
||||
reportFeatureProgress(_state, feature->name());
|
||||
}, true);
|
||||
apply(
|
||||
[this](ApplicationFeature* feature) {
|
||||
LOG_TOPIC(TRACE, Logger::STARTUP) << feature->name() << "::loadOptions";
|
||||
feature->collectOptions(_options);
|
||||
reportFeatureProgress(_state, feature->name());
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
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
|
||||
if (failOnMissing) {
|
||||
apply([this](ApplicationFeature* feature) {
|
||||
for (auto& other : feature->requires()) {
|
||||
if (!this->exists(other)) {
|
||||
fail("feature '" + feature->name() +
|
||||
"' depends on unknown feature '" + other + "'");
|
||||
}
|
||||
if (!this->feature(other)->isEnabled()) {
|
||||
fail("enabled feature '" + feature->name() +
|
||||
"' depends on other feature '" + other + "', which is disabled");
|
||||
}
|
||||
}
|
||||
}, true);
|
||||
apply(
|
||||
[this](ApplicationFeature* feature) {
|
||||
for (auto& other : feature->requires()) {
|
||||
if (!this->exists(other)) {
|
||||
fail("feature '" + feature->name() +
|
||||
"' depends on unknown feature '" + other + "'");
|
||||
}
|
||||
if (!this->feature(other)->isEnabled()) {
|
||||
fail("enabled feature '" + feature->name() +
|
||||
"' depends on other feature '" + other +
|
||||
"', which is disabled");
|
||||
}
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
// first insert all features, even the inactive ones
|
||||
|
@ -478,14 +482,16 @@ void ApplicationServer::prepare() {
|
|||
feature->prepare();
|
||||
feature->state(FeatureState::PREPARED);
|
||||
} 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
|
||||
if (!privilegesElevated) {
|
||||
raisePrivilegesTemporarily();
|
||||
}
|
||||
throw;
|
||||
} 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
|
||||
if (!privilegesElevated) {
|
||||
raisePrivilegesTemporarily();
|
||||
|
@ -511,16 +517,19 @@ void ApplicationServer::start() {
|
|||
feature->state(FeatureState::STARTED);
|
||||
reportFeatureProgress(_state, feature->name());
|
||||
} 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;
|
||||
} 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;
|
||||
}
|
||||
|
||||
if (abortStartup) {
|
||||
// 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;
|
||||
if (feature->state() == FeatureState::STARTED) {
|
||||
LOG(TRACE) << "forcefully stopping feature " << feature->name();
|
||||
|
@ -541,7 +550,8 @@ void ApplicationServer::start() {
|
|||
void 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;
|
||||
|
||||
LOG_TOPIC(TRACE, Logger::STARTUP) << feature->name() << "::stop";
|
||||
|
@ -554,7 +564,8 @@ void ApplicationServer::stop() {
|
|||
void 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;
|
||||
|
||||
LOG_TOPIC(TRACE, Logger::STARTUP) << feature->name() << "::unprepare";
|
||||
|
|
|
@ -30,7 +30,8 @@ using namespace arangodb;
|
|||
using namespace arangodb::options;
|
||||
|
||||
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") {
|
||||
setOptional(true);
|
||||
requiresElevatedPrivileges(false);
|
||||
|
@ -43,6 +44,4 @@ ShutdownFeature::ShutdownFeature(
|
|||
}
|
||||
}
|
||||
|
||||
void ShutdownFeature::start() {
|
||||
server()->beginShutdown();
|
||||
}
|
||||
void ShutdownFeature::start() { server()->beginShutdown(); }
|
||||
|
|
Loading…
Reference in New Issue