mirror of https://gitee.com/bigwinds/arangodb
Improve upgrade logic (#4789)
This commit is contained in:
parent
07f7769018
commit
4b666de5c0
|
@ -49,9 +49,8 @@ UpgradeFeature::UpgradeFeature(
|
|||
setOptional(false);
|
||||
requiresElevatedPrivileges(false);
|
||||
startsAfter("CheckVersion");
|
||||
startsAfter("Cluster");
|
||||
startsAfter("Database");
|
||||
startsAfter("V8Dealer");
|
||||
startsAfter("Cluster");
|
||||
startsAfter("Aql");
|
||||
}
|
||||
|
||||
|
@ -181,27 +180,19 @@ void UpgradeFeature::upgradeDatabase() {
|
|||
methods::UpgradeResult res = methods::Upgrade::startup(vocbase, _upgrade);
|
||||
if (res.fail()) {
|
||||
char const* typeName = "initialization";
|
||||
switch (res.type) {
|
||||
case methods::VersionResult::VERSION_MATCH:
|
||||
case methods::VersionResult::DOWNGRADE_NEEDED:
|
||||
case methods::VersionResult::NO_VERSION_FILE:
|
||||
// initialization
|
||||
break;
|
||||
case methods::VersionResult::UPGRADE_NEEDED:
|
||||
typeName = "upgrade";
|
||||
if (!_upgrade) {
|
||||
LOG_TOPIC(FATAL, arangodb::Logger::FIXME)
|
||||
<< "Database '" << vocbase->name()
|
||||
<< "' needs upgrade. Please start the server with the "
|
||||
"--database.auto-upgrade option";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (res.type == methods::VersionResult::UPGRADE_NEEDED) {
|
||||
typeName = "upgrade"; // an upgrade failed or is required
|
||||
if (!_upgrade) {
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME)
|
||||
<< "Database '" << vocbase->name() << "' needs upgrade. "
|
||||
<< "Please start the server with --database.auto-upgrade";
|
||||
}
|
||||
}
|
||||
LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "Database '" << vocbase->name()
|
||||
<< "' " << typeName << " failed (" << res.errorMessage() << "). "
|
||||
"Please inspect the logs from the " << typeName << " procedure";
|
||||
<< "Please inspect the logs from the " << typeName << " procedure"
|
||||
<< " and try starting the server again.";
|
||||
|
||||
FATAL_ERROR_EXIT();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ UpgradeResult Upgrade::clusterBootstrap(TRI_vocbase_t* system) {
|
|||
clusterFlag = Flags::CLUSTER_DB_SERVER_LOCAL;
|
||||
}
|
||||
TRI_ASSERT(ServerState::instance()->isRunningInCluster());
|
||||
|
||||
|
||||
VPackSlice params = VPackSlice::emptyObjectSlice();
|
||||
return runTasks(system, vinfo, params, clusterFlag,
|
||||
Upgrade::Flags::DATABASE_INIT);
|
||||
|
@ -60,7 +60,7 @@ UpgradeResult Upgrade::clusterBootstrap(TRI_vocbase_t* system) {
|
|||
|
||||
/// corresponding to local-database.js
|
||||
UpgradeResult Upgrade::createDB(TRI_vocbase_t* vocbase,
|
||||
VPackSlice const& users) {
|
||||
VPackSlice const& users) {
|
||||
TRI_ASSERT(users.isArray());
|
||||
|
||||
uint32_t clusterFlag = 0;
|
||||
|
@ -85,74 +85,85 @@ UpgradeResult Upgrade::createDB(TRI_vocbase_t* vocbase,
|
|||
params.add("users", users);
|
||||
params.close();
|
||||
|
||||
// will write version file with this number
|
||||
// will write a version file with this number
|
||||
uint64_t cc = Version::current();
|
||||
// to create a DB we use an empty version result because we want
|
||||
// to execute all tasks not needed for an upgrade
|
||||
VersionResult vinfo = {VersionResult::VERSION_MATCH, cc, cc, {}};
|
||||
return runTasks(vocbase, vinfo, params.slice(), clusterFlag,
|
||||
Upgrade::Flags::DATABASE_INIT);
|
||||
}
|
||||
|
||||
UpgradeResult Upgrade::startup(TRI_vocbase_t* vocbase, bool upgrade) {
|
||||
UpgradeResult Upgrade::startup(TRI_vocbase_t* vocbase, bool isUpgrade) {
|
||||
|
||||
uint32_t clusterFlag = Flags::CLUSTER_LOCAL;
|
||||
if (ServerState::instance()->isSingleServer()) {
|
||||
clusterFlag = Flags::CLUSTER_NONE;
|
||||
}
|
||||
uint32_t dbflag = upgrade ? Flags::DATABASE_UPGRADE : Flags::DATABASE_INIT;
|
||||
uint32_t dbflag = Flags::DATABASE_EXISTING;
|
||||
|
||||
VersionResult vinfo = Version::check(vocbase);
|
||||
if (vinfo.status == VersionResult::DOWNGRADE_NEEDED) {
|
||||
LOG_TOPIC(ERR, Logger::STARTUP)
|
||||
<< "Database directory version (" << vinfo.databaseVersion
|
||||
<< ") is higher than current version (" << vinfo.serverVersion << ").";
|
||||
switch (vinfo.status) {
|
||||
case VersionResult::INVALID:
|
||||
TRI_ASSERT(false); // never returned by Version::check
|
||||
case VersionResult::VERSION_MATCH:
|
||||
break; // just run tasks that weren't run yet
|
||||
case VersionResult::UPGRADE_NEEDED: {
|
||||
if (!isUpgrade) {
|
||||
// we do not perform upgrades without beeing told so during startup
|
||||
LOG_TOPIC(ERR, Logger::STARTUP)
|
||||
<< "Database directory version (" << vinfo.databaseVersion
|
||||
<< ") is lower than current version (" << vinfo.serverVersion
|
||||
<< ").";
|
||||
|
||||
LOG_TOPIC(ERR, Logger::STARTUP)
|
||||
<< "It seems like you are running ArangoDB on a database directory"
|
||||
<< " that was created with a newer version of ArangoDB. Maybe this"
|
||||
<< " is what you wanted but it is not supported by ArangoDB.";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP)
|
||||
<< "----------------------------------------------------------------------";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP)
|
||||
<< "It seems like you have upgraded the ArangoDB binary.";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP)
|
||||
<< "If this is what you wanted to do, please restart with the'";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP) << " --database.auto-upgrade true'";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP)
|
||||
<< "option to upgrade the data in the database directory.'";
|
||||
|
||||
return UpgradeResult(TRI_ERROR_BAD_PARAMETER, vinfo.status);
|
||||
} else if (vinfo.status == VersionResult::UPGRADE_NEEDED && !upgrade) {
|
||||
LOG_TOPIC(ERR, Logger::STARTUP)
|
||||
<< "Database directory version (" << vinfo.databaseVersion
|
||||
<< ") is lower than current version (" << vinfo.serverVersion << ").";
|
||||
|
||||
LOG_TOPIC(ERR, Logger::STARTUP) << "---------------------------------------"
|
||||
"-------------------------------";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP)
|
||||
<< "It seems like you have upgraded the ArangoDB binary.";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP)
|
||||
<< "If this is what you wanted to do, please restart with the'";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP) << " --database.auto-upgrade true'";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP)
|
||||
<< "option to upgrade the data in the database directory.'";
|
||||
|
||||
LOG_TOPIC(ERR, Logger::STARTUP)
|
||||
<< "Normally you can use the control script to upgrade your database'";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP) << " /etc/init.d/arangodb stop'";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP) << " /etc/init.d/arangodb upgrade'";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP) << " /etc/init.d/arangodb start'";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP) << "---------------------------------------"
|
||||
"-------------------------------'";
|
||||
return UpgradeResult(TRI_ERROR_BAD_PARAMETER, vinfo.status);
|
||||
} else {
|
||||
switch (vinfo.status) {
|
||||
case VersionResult::CANNOT_PARSE_VERSION_FILE:
|
||||
case VersionResult::CANNOT_READ_VERSION_FILE:
|
||||
case VersionResult::NO_SERVER_VERSION: {
|
||||
std::string msg =
|
||||
std::string("error during ") + (upgrade ? "upgrade" : "startup");
|
||||
return UpgradeResult(TRI_ERROR_INTERNAL, msg, vinfo.status);
|
||||
LOG_TOPIC(ERR, Logger::STARTUP) << "Normally you can use the control "
|
||||
"script to upgrade your database'";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP) << " /etc/init.d/arangodb stop'";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP) << " /etc/init.d/arangodb upgrade'";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP) << " /etc/init.d/arangodb start'";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP)
|
||||
<< "----------------------------------------------------------------------'";
|
||||
return UpgradeResult(TRI_ERROR_BAD_PARAMETER, vinfo.status);
|
||||
}
|
||||
case VersionResult::NO_VERSION_FILE:
|
||||
LOG_TOPIC(DEBUG, Logger::STARTUP) << "No VERSION file found";
|
||||
if (upgrade) {
|
||||
// VERSION file does not exist, we are running on a new database
|
||||
dbflag = DATABASE_INIT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
// do perform the upgrade
|
||||
dbflag = Flags::DATABASE_UPGRADE;
|
||||
break;
|
||||
}
|
||||
case VersionResult::DOWNGRADE_NEEDED: {
|
||||
// we do not support downgrades, just error out
|
||||
LOG_TOPIC(ERR, Logger::STARTUP)
|
||||
<< "Database directory version (" << vinfo.databaseVersion
|
||||
<< ") is higher than current version (" << vinfo.serverVersion
|
||||
<< ").";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP)
|
||||
<< "It seems like you are running ArangoDB on a database directory"
|
||||
<< " that was created with a newer version of ArangoDB. Maybe this"
|
||||
<< " is what you wanted but it is not supported by ArangoDB.";
|
||||
return UpgradeResult(TRI_ERROR_NO_ERROR, vinfo.status);
|
||||
}
|
||||
case VersionResult::CANNOT_PARSE_VERSION_FILE:
|
||||
case VersionResult::CANNOT_READ_VERSION_FILE:
|
||||
case VersionResult::NO_SERVER_VERSION: {
|
||||
LOG_TOPIC(DEBUG, Logger::STARTUP) << "Error reading version file";
|
||||
std::string msg =
|
||||
std::string("error during ") + (isUpgrade ? "upgrade" : "startup");
|
||||
return UpgradeResult(TRI_ERROR_INTERNAL, msg, vinfo.status);
|
||||
}
|
||||
case VersionResult::NO_VERSION_FILE:
|
||||
LOG_TOPIC(DEBUG, Logger::STARTUP) << "No VERSION file found";
|
||||
// VERSION file does not exist, we are running on a new database
|
||||
dbflag = DATABASE_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
// should not do anything on VERSION_MATCH, and init the database
|
||||
|
@ -181,10 +192,10 @@ void methods::Upgrade::registerTasks() {
|
|||
/*cluster*/ Flags::CLUSTER_NONE | Flags::CLUSTER_COORDINATOR_GLOBAL,
|
||||
/*database*/ DATABASE_INIT | DATABASE_UPGRADE,
|
||||
&UpgradeTasks::createUsersIndex);
|
||||
addTask("addDefaultUsers", "add default users for a new database",
|
||||
addTask("addDefaultUserOther", "add default users for a new database",
|
||||
/*system*/ Flags::DATABASE_EXCEPT_SYSTEM,
|
||||
/*cluster*/ Flags::CLUSTER_NONE | Flags::CLUSTER_COORDINATOR_GLOBAL,
|
||||
/*database*/ DATABASE_INIT, &UpgradeTasks::addDefaultUsers);
|
||||
/*database*/ DATABASE_INIT, &UpgradeTasks::addDefaultUserOther);
|
||||
addTask("updateUserModels",
|
||||
"convert documents in _users collection to new format",
|
||||
/*system*/ Flags::DATABASE_SYSTEM,
|
||||
|
@ -196,6 +207,12 @@ void methods::Upgrade::registerTasks() {
|
|||
/*cluster*/ Flags::CLUSTER_NONE | Flags::CLUSTER_COORDINATOR_GLOBAL,
|
||||
/*database*/ DATABASE_INIT | DATABASE_UPGRADE | DATABASE_EXISTING,
|
||||
&UpgradeTasks::createModules);
|
||||
// FIXME simon: Determine whether this is still necessary
|
||||
addTask("setupAnalyzers", "setup _iresearch_analyzers collection",
|
||||
/*system*/ Flags::DATABASE_SYSTEM,
|
||||
/*cluster*/ Flags::CLUSTER_NONE | Flags::CLUSTER_COORDINATOR_GLOBAL,
|
||||
/*database*/ DATABASE_INIT | DATABASE_UPGRADE | DATABASE_EXISTING,
|
||||
&UpgradeTasks::setupAnalyzers);
|
||||
addTask("createRouting", "setup _routing collection",
|
||||
/*system*/ Flags::DATABASE_ALL,
|
||||
/*cluster*/ Flags::CLUSTER_NONE | Flags::CLUSTER_COORDINATOR_GLOBAL,
|
||||
|
@ -255,27 +272,40 @@ UpgradeResult methods::Upgrade::runTasks(TRI_vocbase_t* vocbase,
|
|||
uint32_t dbFlag) {
|
||||
TRI_ASSERT(vocbase != nullptr);
|
||||
TRI_ASSERT(clusterFlag != 0 && dbFlag != 0);
|
||||
TRI_ASSERT(!_tasks.empty()); // forgot to call registerTask!!
|
||||
TRI_ASSERT(!_tasks.empty()); // forgot to call registerTask!!
|
||||
// needs to run in superuser scope, otherwise we get errors
|
||||
ExecContextScope scope(ExecContext::superuser());
|
||||
// only local should actually write a VERSION file
|
||||
bool isLocal = clusterFlag == CLUSTER_NONE || clusterFlag == CLUSTER_LOCAL;
|
||||
|
||||
bool ranOnce = false;
|
||||
// execute all tasks
|
||||
for (Task const& t : _tasks) {
|
||||
// check for system database
|
||||
if (t.systemFlag == DATABASE_SYSTEM && !vocbase->isSystem()) {
|
||||
LOG_TOPIC(DEBUG, Logger::STARTUP) << "Upgrade: Skipping " << t.name;
|
||||
continue;
|
||||
}
|
||||
if (t.systemFlag == DATABASE_EXCEPT_SYSTEM && vocbase->isSystem()) {
|
||||
LOG_TOPIC(DEBUG, Logger::STARTUP) << "Upgrade: Skipping " << t.name;
|
||||
continue;
|
||||
}
|
||||
|
||||
// check that the cluster occurs in the cluster list
|
||||
if (!(t.clusterFlags & clusterFlag)) {
|
||||
LOG_TOPIC(DEBUG, Logger::STARTUP) << "Upgrade: Skipping " << t.name;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto const& it = vinfo.tasks.find(t.name);
|
||||
if (it != vinfo.tasks.end()) {
|
||||
if (it->second) {
|
||||
LOG_TOPIC(DEBUG, Logger::STARTUP) << "Upgrade: Skipping " << t.name;
|
||||
continue;
|
||||
}
|
||||
vinfo.tasks.erase(it); // in case we encounter false
|
||||
}
|
||||
|
||||
// check that the database occurs in the database list
|
||||
if (!(t.databaseFlags & dbFlag)) {
|
||||
// special optimisation: for local server and new database,
|
||||
|
@ -284,26 +314,45 @@ UpgradeResult methods::Upgrade::runTasks(TRI_vocbase_t* vocbase,
|
|||
t.databaseFlags == DATABASE_UPGRADE) {
|
||||
vinfo.tasks.emplace(t.name, true);
|
||||
}
|
||||
LOG_TOPIC(DEBUG, Logger::STARTUP) << "Upgrade: Skipping " << t.name;
|
||||
continue;
|
||||
}
|
||||
|
||||
// we need to execute this task
|
||||
LOG_TOPIC(DEBUG, Logger::STARTUP) << "Upgrade: Executing " << t.name;
|
||||
try {
|
||||
t.action(vocbase, params);
|
||||
vinfo.tasks.emplace(t.name, true);
|
||||
if (isLocal) { // save after every task for resilience
|
||||
methods::Version::write(vocbase, vinfo.tasks);
|
||||
bool ranTask = t.action(vocbase, params);
|
||||
if (!ranTask) {
|
||||
std::string msg =
|
||||
"Executing " + t.name + " (" + t.description + ") failed.";
|
||||
LOG_TOPIC(ERR, Logger::STARTUP) << msg << " Aborting procedure.";
|
||||
return UpgradeResult(TRI_ERROR_INTERNAL, msg, vinfo.status);
|
||||
}
|
||||
} catch (basics::Exception const& e) {
|
||||
LOG_TOPIC(ERR, Logger::STARTUP) << "Executing " << t.name << " ("
|
||||
<< t.description << ") failed with "
|
||||
<< e.message();
|
||||
<< e.message() << ". Aborting procedure.";
|
||||
return UpgradeResult(e.code(), e.what(), vinfo.status);
|
||||
}
|
||||
|
||||
// remember we already executed this one
|
||||
vinfo.tasks.emplace(t.name, true);
|
||||
if (isLocal) { // save after every task for resilience
|
||||
Result res = methods::Version::write(vocbase, vinfo.tasks, /*sync*/false);
|
||||
if (res.fail()) {
|
||||
return UpgradeResult(res.errorNumber(), res.errorMessage(),
|
||||
vinfo.status);
|
||||
}
|
||||
ranOnce = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isLocal) { // no need to write this for cluster bootstrap
|
||||
methods::Version::write(vocbase, vinfo.tasks);
|
||||
// save even if no tasks were executed
|
||||
LOG_TOPIC(DEBUG, Logger::STARTUP) << "Upgrade: Writing VERSION file";
|
||||
Result res = methods::Version::write(vocbase, vinfo.tasks, /*sync*/ranOnce);
|
||||
if (res.fail()) {
|
||||
return UpgradeResult(res.errorNumber(), res.errorMessage(), vinfo.status);
|
||||
}
|
||||
}
|
||||
return UpgradeResult(TRI_ERROR_NO_ERROR, vinfo.status);
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ struct Upgrade {
|
|||
CLUSTER_DB_SERVER_LOCAL = (1u << 9)
|
||||
};
|
||||
|
||||
typedef std::function<void(TRI_vocbase_t*, velocypack::Slice const&)>
|
||||
typedef std::function<bool(TRI_vocbase_t*, velocypack::Slice const&)>
|
||||
TaskFunction;
|
||||
struct Task {
|
||||
std::string name;
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "UpgradeTasks.h"
|
||||
#include "Basics/Common.h"
|
||||
#include "Agency/AgencyComm.h"
|
||||
#include "Basics/Common.h"
|
||||
#include "Basics/StringUtils.h"
|
||||
#include "Basics/VelocyPackHelper.h"
|
||||
#include "Cluster/ClusterComm.h"
|
||||
|
@ -49,33 +49,40 @@ using basics::VelocyPackHelper;
|
|||
|
||||
// Note: this entire file should run with superuser rights
|
||||
|
||||
static void createSystemCollection(TRI_vocbase_t* vocbase,
|
||||
/// create a collection if it does not exists.
|
||||
static bool createSystemCollection(TRI_vocbase_t* vocbase,
|
||||
std::string const& name) {
|
||||
Result res = methods::Collections::lookup(vocbase, name,
|
||||
[](LogicalCollection* coll) {});
|
||||
if (res.is(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND)) {
|
||||
auto cl = ApplicationServer::getFeature<ClusterFeature>("Cluster");
|
||||
uint32_t defaultReplFactor = 1;
|
||||
ClusterFeature* cl = ApplicationServer::getFeature<ClusterFeature>("Cluster");
|
||||
if (cl != nullptr) {
|
||||
defaultReplFactor = cl->systemReplicationFactor();
|
||||
}
|
||||
VPackBuilder bb;
|
||||
bb.openObject();
|
||||
bb.add("isSystem", VPackSlice::trueSlice());
|
||||
bb.add("waitForSync", VPackSlice::falseSlice());
|
||||
bb.add("journalSize", VPackValue(1024 * 1024));
|
||||
bb.add("replicationFactor", VPackValue(cl->systemReplicationFactor()));
|
||||
bb.add("replicationFactor", VPackValue(defaultReplFactor));
|
||||
if (name != "_graphs") {
|
||||
bb.add("distributeShardsLike", VPackValue("_graphs"));
|
||||
}
|
||||
bb.close();
|
||||
res = Collections::create(vocbase, name, TRI_COL_TYPE_DOCUMENT, bb.slice(),
|
||||
/*waitsForSyncReplication*/ true,
|
||||
/*enforceReplicationFactor*/ true,
|
||||
[](LogicalCollection* coll) { TRI_ASSERT(coll); });
|
||||
/*waitsForSyncReplication*/ true,
|
||||
/*enforceReplicationFactor*/ true,
|
||||
[](LogicalCollection* coll) { TRI_ASSERT(coll); });
|
||||
}
|
||||
if (res.fail()) {
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void createIndex(TRI_vocbase_t* vocbase, std::string const& name,
|
||||
/// create an index if it does not exist
|
||||
static bool createIndex(TRI_vocbase_t* vocbase, std::string const& name,
|
||||
Index::IndexType type,
|
||||
std::vector<std::string> const& fields, bool unique,
|
||||
bool sparse) {
|
||||
|
@ -89,25 +96,30 @@ static void createIndex(TRI_vocbase_t* vocbase, std::string const& name,
|
|||
if (res1.fail() || res2.fail()) {
|
||||
THROW_ARANGO_EXCEPTION(res1.fail() ? res1 : res2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void UpgradeTasks::setupGraphs(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
createSystemCollection(vocbase, "_graphs");
|
||||
bool UpgradeTasks::setupGraphs(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
return createSystemCollection(vocbase, "_graphs");
|
||||
}
|
||||
void UpgradeTasks::setupUsers(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
createSystemCollection(vocbase, "_users");
|
||||
bool UpgradeTasks::setupUsers(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
return createSystemCollection(vocbase, "_users");
|
||||
}
|
||||
void UpgradeTasks::createUsersIndex(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
bool UpgradeTasks::createUsersIndex(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
TRI_ASSERT(vocbase->isSystem());
|
||||
createIndex(vocbase, "_users", Index::TRI_IDX_TYPE_HASH_INDEX, {"user"},
|
||||
/*unique*/ true, /*sparse*/ true);
|
||||
return createIndex(vocbase, "_users", Index::TRI_IDX_TYPE_HASH_INDEX,
|
||||
{"user"},
|
||||
/*unique*/ true, /*sparse*/ true);
|
||||
}
|
||||
void UpgradeTasks::addDefaultUsers(TRI_vocbase_t* vocbase,
|
||||
VPackSlice const& params) {
|
||||
bool UpgradeTasks::addDefaultUserOther(TRI_vocbase_t* vocbase,
|
||||
VPackSlice const& params) {
|
||||
TRI_ASSERT(!vocbase->isSystem());
|
||||
TRI_ASSERT(params.isObject());
|
||||
VPackSlice users = params.get("users");
|
||||
if (!users.isArray()) {
|
||||
return;
|
||||
if (users.isNone()) {
|
||||
return true; // exit, no users were specified
|
||||
} else if (!users.isArray()) {
|
||||
LOG_TOPIC(ERR, Logger::STARTUP) << "addDefaultUserOther: users is invalid";
|
||||
return false;
|
||||
}
|
||||
auth::UserManager* um = AuthenticationFeature::instance()->userManager();
|
||||
TRI_ASSERT(um != nullptr);
|
||||
|
@ -120,7 +132,8 @@ void UpgradeTasks::addDefaultUsers(TRI_vocbase_t* vocbase,
|
|||
std::string passwd = VelocyPackHelper::getStringValue(slice, "passwd", "");
|
||||
bool active = VelocyPackHelper::getBooleanValue(slice, "active", true);
|
||||
VPackSlice extra = slice.get("extra");
|
||||
Result res = um->storeUser(false, user, passwd, active, VPackSlice::noneSlice());
|
||||
Result res =
|
||||
um->storeUser(false, user, passwd, active, VPackSlice::noneSlice());
|
||||
if (res.fail() && !res.is(TRI_ERROR_USER_DUPLICATE)) {
|
||||
LOG_TOPIC(WARN, Logger::STARTUP) << "could not add database user "
|
||||
<< user;
|
||||
|
@ -131,24 +144,30 @@ void UpgradeTasks::addDefaultUsers(TRI_vocbase_t* vocbase,
|
|||
});
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void UpgradeTasks::updateUserModels(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
bool UpgradeTasks::updateUserModels(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
TRI_ASSERT(vocbase->isSystem());
|
||||
// TODO isn't this done on the fly ?
|
||||
return true;
|
||||
}
|
||||
void UpgradeTasks::createModules(TRI_vocbase_t* vocbase, VPackSlice const& s) {
|
||||
createSystemCollection(vocbase, "_modules");
|
||||
bool UpgradeTasks::createModules(TRI_vocbase_t* vocbase, VPackSlice const& s) {
|
||||
return createSystemCollection(vocbase, "_modules");
|
||||
}
|
||||
void UpgradeTasks::createRouting(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
createSystemCollection(vocbase, "_routing");
|
||||
bool UpgradeTasks::setupAnalyzers(TRI_vocbase_t* vocbase, VPackSlice const& s) {
|
||||
return createSystemCollection(vocbase, "_iresearch_analyzers");
|
||||
}
|
||||
void UpgradeTasks::insertRedirections(TRI_vocbase_t* vocbase,
|
||||
bool UpgradeTasks::createRouting(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
return createSystemCollection(vocbase, "_routing");
|
||||
}
|
||||
bool UpgradeTasks::insertRedirections(TRI_vocbase_t* vocbase,
|
||||
VPackSlice const&) {
|
||||
std::vector<std::string> toRemove; // remove in a different trx
|
||||
auto cb = [&toRemove] (VPackSlice const& doc) {
|
||||
std::vector<std::string> toRemove; // remove in a different trx
|
||||
auto cb = [&toRemove](VPackSlice const& doc) {
|
||||
TRI_ASSERT(doc.isObject());
|
||||
VPackSlice url = doc.get("url"), action = doc.get("action");
|
||||
if (url.isObject() && action.isObject() && action.get("options").isObject()) {
|
||||
if (url.isObject() && action.isObject() &&
|
||||
action.get("options").isObject()) {
|
||||
VPackSlice v = action.get("options").get("destination");
|
||||
if (v.isString()) {
|
||||
std::string path = v.copyString();
|
||||
|
@ -163,7 +182,7 @@ void UpgradeTasks::insertRedirections(TRI_vocbase_t* vocbase,
|
|||
if (res.fail()) {
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
|
||||
|
||||
auto ctx = transaction::StandaloneContext::Create(vocbase);
|
||||
SingleCollectionTransaction trx(ctx, "_routing", AccessMode::Type::WRITE);
|
||||
res = trx.begin();
|
||||
|
@ -174,12 +193,12 @@ void UpgradeTasks::insertRedirections(TRI_vocbase_t* vocbase,
|
|||
opts.waitForSync = true;
|
||||
for (std::string const& key : toRemove) {
|
||||
VPackBuilder b;
|
||||
b(VPackValue(VPackValueType::Object))(StaticStrings::KeyString, VPackValue(key))();
|
||||
trx.remove("_routing", b.slice(), opts); // check results
|
||||
b(VPackValue(VPackValueType::Object))(StaticStrings::KeyString,
|
||||
VPackValue(key))();
|
||||
trx.remove("_routing", b.slice(), opts); // check results
|
||||
}
|
||||
|
||||
std::vector<std::string> paths = {"/", "/_admin/html",
|
||||
"/_admin/html/index.html"};
|
||||
std::vector<std::string> paths = {"/", "/_admin/html", "/_admin/html/index.html"};
|
||||
std::string dest = "/_db/" + vocbase->name() + "/_admin/aardvark/index.html";
|
||||
OperationResult opres;
|
||||
for (std::string const& path : paths) {
|
||||
|
@ -204,21 +223,27 @@ void UpgradeTasks::insertRedirections(TRI_vocbase_t* vocbase,
|
|||
if (!res.ok()) {
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void UpgradeTasks::setupAqlFunctions(TRI_vocbase_t* vocbase,
|
||||
|
||||
bool UpgradeTasks::setupAqlFunctions(TRI_vocbase_t* vocbase,
|
||||
VPackSlice const&) {
|
||||
createSystemCollection(vocbase, "_aqlfunctions");
|
||||
return createSystemCollection(vocbase, "_aqlfunctions");
|
||||
}
|
||||
void UpgradeTasks::createFrontend(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
createSystemCollection(vocbase, "_frontend");
|
||||
|
||||
bool UpgradeTasks::createFrontend(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
return createSystemCollection(vocbase, "_frontend");
|
||||
}
|
||||
void UpgradeTasks::setupQueues(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
createSystemCollection(vocbase, "_queues");
|
||||
|
||||
bool UpgradeTasks::setupQueues(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
return createSystemCollection(vocbase, "_queues");
|
||||
}
|
||||
void UpgradeTasks::setupJobs(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
createSystemCollection(vocbase, "_jobs");
|
||||
|
||||
bool UpgradeTasks::setupJobs(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
return createSystemCollection(vocbase, "_jobs");
|
||||
}
|
||||
void UpgradeTasks::createJobsIndex(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
|
||||
bool UpgradeTasks::createJobsIndex(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
createSystemCollection(vocbase, "_jobs");
|
||||
createIndex(vocbase, "_jobs", Index::TRI_IDX_TYPE_SKIPLIST_INDEX,
|
||||
{"queue", "status", "delayUntil"},
|
||||
|
@ -226,14 +251,18 @@ void UpgradeTasks::createJobsIndex(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
|||
createIndex(vocbase, "_jobs", Index::TRI_IDX_TYPE_SKIPLIST_INDEX,
|
||||
{"status", "queue", "delayUntil"},
|
||||
/*unique*/ true, /*sparse*/ true);
|
||||
return true;
|
||||
}
|
||||
void UpgradeTasks::setupApps(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
createSystemCollection(vocbase, "_apps");
|
||||
|
||||
bool UpgradeTasks::setupApps(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
return createSystemCollection(vocbase, "_apps");
|
||||
}
|
||||
void UpgradeTasks::createAppsIndex(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
createIndex(vocbase, "_apps", Index::TRI_IDX_TYPE_HASH_INDEX, {"mount"},
|
||||
/*unique*/ true, /*sparse*/ true);
|
||||
|
||||
bool UpgradeTasks::createAppsIndex(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
return createIndex(vocbase, "_apps", Index::TRI_IDX_TYPE_HASH_INDEX,
|
||||
{"mount"}, /*unique*/ true, /*sparse*/ true);
|
||||
}
|
||||
void UpgradeTasks::setupAppBundles(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
createSystemCollection(vocbase, "_appbundles");
|
||||
|
||||
bool UpgradeTasks::setupAppBundles(TRI_vocbase_t* vocbase, VPackSlice const&) {
|
||||
return createSystemCollection(vocbase, "_appbundles");
|
||||
}
|
||||
|
|
|
@ -33,22 +33,23 @@ namespace methods {
|
|||
/// Code to create and initialize databases
|
||||
/// Replaces ugrade-database.js for good
|
||||
struct UpgradeTasks {
|
||||
static void setupGraphs(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static void setupUsers(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static void createUsersIndex(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static void addDefaultUsers(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static void updateUserModels(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static void createModules(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static void createRouting(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static void insertRedirections(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static void setupAqlFunctions(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static void createFrontend(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static void setupQueues(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static void setupJobs(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static void createJobsIndex(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static void setupApps(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static void createAppsIndex(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static void setupAppBundles(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static bool setupGraphs(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static bool setupUsers(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static bool createUsersIndex(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static bool addDefaultUserOther(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static bool updateUserModels(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static bool createModules(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static bool setupAnalyzers(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static bool createRouting(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static bool insertRedirections(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static bool setupAqlFunctions(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static bool createFrontend(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static bool setupQueues(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static bool setupJobs(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static bool createJobsIndex(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static bool setupApps(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static bool createAppsIndex(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
static bool setupAppBundles(TRI_vocbase_t*, velocypack::Slice const&);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -144,14 +144,15 @@ VersionResult Version::check(TRI_vocbase_t* vocbase) {
|
|||
return res;
|
||||
}
|
||||
|
||||
void Version::write(TRI_vocbase_t* vocbase,
|
||||
std::map<std::string, bool> tasks) {
|
||||
Result Version::write(TRI_vocbase_t* vocbase,
|
||||
std::map<std::string, bool> tasks,
|
||||
bool sync) {
|
||||
StorageEngine* engine = EngineSelectorFeature::ENGINE;
|
||||
TRI_ASSERT(engine != nullptr);
|
||||
|
||||
std::string versionFile = engine->versionFilename(vocbase->id());
|
||||
TRI_ASSERT(!versionFile.empty());
|
||||
|
||||
|
||||
VPackOptions opts;
|
||||
opts.buildUnindexedObjects = true;
|
||||
VPackBuilder builder(&opts);
|
||||
|
@ -163,6 +164,10 @@ void Version::write(TRI_vocbase_t* vocbase,
|
|||
}
|
||||
builder.close();
|
||||
builder.close();
|
||||
|
||||
basics::VelocyPackHelper::velocyPackToFile(versionFile, builder.slice(), true);
|
||||
|
||||
if (!basics::VelocyPackHelper::velocyPackToFile(versionFile, builder.slice(), sync)) {
|
||||
LOG_TOPIC(ERR, Logger::STARTUP) << "Writing the version file failed: " << TRI_last_error();
|
||||
return Result(TRI_errno(), TRI_last_error());
|
||||
}
|
||||
return Result();
|
||||
}
|
||||
|
|
|
@ -20,13 +20,14 @@
|
|||
/// @author Simon Grätzer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGOD_VOC_BASE_API_VERSION_H
|
||||
#define ARANGOD_VOC_BASE_API_VERSION_H 1
|
||||
#ifndef ARANGOD_VOC_BASE_METHODS_VERSION_H
|
||||
#define ARANGOD_VOC_BASE_METHODS_VERSION_H 1
|
||||
|
||||
#include "Basics/Result.h"
|
||||
|
||||
#include <velocypack/Builder.h>
|
||||
#include <velocypack/Slice.h>
|
||||
#include <cstdint>
|
||||
#include "Basics/Result.h"
|
||||
|
||||
struct TRI_vocbase_t;
|
||||
|
||||
|
@ -66,7 +67,7 @@ struct Version {
|
|||
/// @brief read the VERSION file for a database
|
||||
static VersionResult check(TRI_vocbase_t*);
|
||||
/// @brief write a VERSION file including all tasks
|
||||
static void write(TRI_vocbase_t*, std::map<std::string, bool> tasks);
|
||||
static Result write(TRI_vocbase_t*, std::map<std::string, bool> tasks, bool sync);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -187,7 +187,6 @@ void slurp(std::string const& filename, StringBuffer& result) {
|
|||
|
||||
static void throwFileWriteError(std::string const& filename) {
|
||||
TRI_set_errno(TRI_ERROR_SYS_ERROR);
|
||||
/*int res = */ TRI_errno();
|
||||
|
||||
std::string message("write failed for file '" + filename + "': " + TRI_last_error());
|
||||
LOG_TOPIC(TRACE, arangodb::Logger::FIXME) << "" << message;
|
||||
|
|
Loading…
Reference in New Issue