1
0
Fork 0

Improve upgrade logic (#4789)

This commit is contained in:
Simon 2018-03-12 22:44:09 +01:00 committed by Jan
parent 07f7769018
commit 4b666de5c0
8 changed files with 236 additions and 161 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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