forked from lix-project/lix
* Refactor the upgrade / database initialisation logic a bit.
This commit is contained in:
parent
cfe742cfc5
commit
e33f67ff0b
|
@ -205,52 +205,43 @@ LocalStore::LocalStore()
|
||||||
lockFile(globalLock, ltRead, true);
|
lockFile(globalLock, ltRead, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open the Nix database. */
|
|
||||||
if (sqlite3_open_v2((nixDBPath + "/db.sqlite").c_str(), &db.db,
|
|
||||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0) != SQLITE_OK)
|
|
||||||
throw Error("cannot open SQLite database");
|
|
||||||
|
|
||||||
if (sqlite3_busy_timeout(db, 60000) != SQLITE_OK)
|
|
||||||
throw SQLiteError(db, "setting timeout");
|
|
||||||
|
|
||||||
if (sqlite3_exec(db, "pragma foreign_keys = 1;", 0, 0, 0) != SQLITE_OK)
|
|
||||||
throw SQLiteError(db, "enabling foreign keys");
|
|
||||||
|
|
||||||
/* !!! check whether sqlite has been built with foreign key
|
|
||||||
support */
|
|
||||||
|
|
||||||
/* Whether SQLite should fsync(). "Normal" synchronous mode
|
|
||||||
should be safe enough. If the user asks for it, don't sync at
|
|
||||||
all. This can cause database corruption if the system
|
|
||||||
crashes. */
|
|
||||||
string syncMode = queryBoolSetting("fsync-metadata", true) ? "normal" : "off";
|
|
||||||
if (sqlite3_exec(db, ("pragma synchronous = " + syncMode + ";").c_str(), 0, 0, 0) != SQLITE_OK)
|
|
||||||
throw SQLiteError(db, "setting synchronous mode");
|
|
||||||
|
|
||||||
/* Use `truncate' journal mode, which should be a bit faster. */
|
|
||||||
if (sqlite3_exec(db, "pragma main.journal_mode = truncate;", 0, 0, 0) != SQLITE_OK)
|
|
||||||
throw SQLiteError(db, "setting journal mode");
|
|
||||||
|
|
||||||
/* Check the current database schema and if necessary do an
|
/* Check the current database schema and if necessary do an
|
||||||
upgrade. !!! Race condition: several processes could start
|
upgrade. */
|
||||||
the upgrade at the same time. */
|
|
||||||
int curSchema = getSchema();
|
int curSchema = getSchema();
|
||||||
if (curSchema > nixSchemaVersion)
|
if (curSchema > nixSchemaVersion)
|
||||||
throw Error(format("current Nix store schema is version %1%, but I only support %2%")
|
throw Error(format("current Nix store schema is version %1%, but I only support %2%")
|
||||||
% curSchema % nixSchemaVersion);
|
% curSchema % nixSchemaVersion);
|
||||||
if (curSchema == 0) { /* new store */
|
|
||||||
|
else if (curSchema == 0) { /* new store */
|
||||||
curSchema = nixSchemaVersion;
|
curSchema = nixSchemaVersion;
|
||||||
initSchema();
|
openDB(true);
|
||||||
writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str());
|
writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str());
|
||||||
}
|
}
|
||||||
else if (curSchema == 1) throw Error("your Nix store is no longer supported");
|
|
||||||
else if (curSchema < 5)
|
else if (curSchema < nixSchemaVersion) {
|
||||||
throw Error(
|
if (curSchema < 5)
|
||||||
"Your Nix store has a database in Berkeley DB format,\n"
|
throw Error(
|
||||||
"which is no longer supported. To convert to the new format,\n"
|
"Your Nix store has a database in Berkeley DB format,\n"
|
||||||
"please upgrade Nix to version 0.12 first.");
|
"which is no longer supported. To convert to the new format,\n"
|
||||||
else if (curSchema < 6) upgradeStore6();
|
"please upgrade Nix to version 0.12 first.");
|
||||||
else prepareStatements();
|
|
||||||
|
if (!lockFile(globalLock, ltWrite, false)) {
|
||||||
|
printMsg(lvlError, "waiting for exclusive access to the Nix store...");
|
||||||
|
lockFile(globalLock, ltWrite, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the schema version again, because another process may
|
||||||
|
have performed the upgrade already. */
|
||||||
|
curSchema = getSchema();
|
||||||
|
|
||||||
|
if (curSchema < 6) upgradeStore6();
|
||||||
|
|
||||||
|
writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str());
|
||||||
|
|
||||||
|
lockFile(globalLock, ltRead, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
else openDB(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -280,19 +271,42 @@ int LocalStore::getSchema()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LocalStore::initSchema()
|
void LocalStore::openDB(bool create)
|
||||||
{
|
{
|
||||||
|
/* Open the Nix database. */
|
||||||
|
if (sqlite3_open_v2((nixDBPath + "/db.sqlite").c_str(), &db.db,
|
||||||
|
SQLITE_OPEN_READWRITE | (create ? SQLITE_OPEN_CREATE : 0), 0) != SQLITE_OK)
|
||||||
|
throw Error("cannot open SQLite database");
|
||||||
|
|
||||||
|
if (sqlite3_busy_timeout(db, 60000) != SQLITE_OK)
|
||||||
|
throw SQLiteError(db, "setting timeout");
|
||||||
|
|
||||||
|
if (sqlite3_exec(db, "pragma foreign_keys = 1;", 0, 0, 0) != SQLITE_OK)
|
||||||
|
throw SQLiteError(db, "enabling foreign keys");
|
||||||
|
|
||||||
|
/* !!! check whether sqlite has been built with foreign key
|
||||||
|
support */
|
||||||
|
|
||||||
|
/* Whether SQLite should fsync(). "Normal" synchronous mode
|
||||||
|
should be safe enough. If the user asks for it, don't sync at
|
||||||
|
all. This can cause database corruption if the system
|
||||||
|
crashes. */
|
||||||
|
string syncMode = queryBoolSetting("fsync-metadata", true) ? "normal" : "off";
|
||||||
|
if (sqlite3_exec(db, ("pragma synchronous = " + syncMode + ";").c_str(), 0, 0, 0) != SQLITE_OK)
|
||||||
|
throw SQLiteError(db, "setting synchronous mode");
|
||||||
|
|
||||||
|
/* Use `truncate' journal mode, which should be a bit faster. */
|
||||||
|
if (sqlite3_exec(db, "pragma main.journal_mode = truncate;", 0, 0, 0) != SQLITE_OK)
|
||||||
|
throw SQLiteError(db, "setting journal mode");
|
||||||
|
|
||||||
|
/* Initialise the database schema, if necessary. */
|
||||||
|
if (create) {
|
||||||
#include "schema.sql.hh"
|
#include "schema.sql.hh"
|
||||||
|
if (sqlite3_exec(db, (const char *) schema, 0, 0, 0) != SQLITE_OK)
|
||||||
|
throw SQLiteError(db, "initialising database schema");
|
||||||
|
}
|
||||||
|
|
||||||
if (sqlite3_exec(db, (const char *) schema, 0, 0, 0) != SQLITE_OK)
|
/* Prepare SQL statements. */
|
||||||
throw SQLiteError(db, "initialising database schema");
|
|
||||||
|
|
||||||
prepareStatements();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LocalStore::prepareStatements()
|
|
||||||
{
|
|
||||||
stmtRegisterValidPath.create(db,
|
stmtRegisterValidPath.create(db,
|
||||||
"insert or replace into ValidPaths (path, hash, registrationTime, deriver) values (?, ?, ?, ?);");
|
"insert or replace into ValidPaths (path, hash, registrationTime, deriver) values (?, ?, ?, ?);");
|
||||||
stmtAddReference.create(db,
|
stmtAddReference.create(db,
|
||||||
|
@ -1225,14 +1239,9 @@ ValidPathInfo LocalStore::queryPathInfoOld(const Path & path)
|
||||||
/* Upgrade from schema 5 (Nix 0.12) to schema 6 (Nix >= 0.15). */
|
/* Upgrade from schema 5 (Nix 0.12) to schema 6 (Nix >= 0.15). */
|
||||||
void LocalStore::upgradeStore6()
|
void LocalStore::upgradeStore6()
|
||||||
{
|
{
|
||||||
if (!lockFile(globalLock, ltWrite, false)) {
|
|
||||||
printMsg(lvlError, "waiting for exclusive access to the Nix store...");
|
|
||||||
lockFile(globalLock, ltWrite, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
printMsg(lvlError, "upgrading Nix store to new schema (this may take a while)...");
|
printMsg(lvlError, "upgrading Nix store to new schema (this may take a while)...");
|
||||||
|
|
||||||
initSchema();
|
openDB(true);
|
||||||
|
|
||||||
PathSet validPaths = queryValidPathsOld();
|
PathSet validPaths = queryValidPathsOld();
|
||||||
|
|
||||||
|
@ -1256,10 +1265,6 @@ void LocalStore::upgradeStore6()
|
||||||
std::cerr << "\n";
|
std::cerr << "\n";
|
||||||
|
|
||||||
txn.commit();
|
txn.commit();
|
||||||
|
|
||||||
writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str());
|
|
||||||
|
|
||||||
lockFile(globalLock, ltRead, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -209,9 +209,7 @@ private:
|
||||||
|
|
||||||
int getSchema();
|
int getSchema();
|
||||||
|
|
||||||
void initSchema();
|
void openDB(bool create);
|
||||||
|
|
||||||
void prepareStatements();
|
|
||||||
|
|
||||||
unsigned long long queryValidPathId(const Path & path);
|
unsigned long long queryValidPathId(const Path & path);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue