aboutsummaryrefslogtreecommitdiff
path: root/src/libstore
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2010-10-14 15:55:51 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2010-10-14 15:55:51 +0000
commit64fd29855a8ae49cacdaff424679821b4fd3bf57 (patch)
treebf99b1034e1bfe9a4c152bf8b361cb7e5c2ccd35 /src/libstore
parentbfa6ee7d919b84a105f6376116e82240e44b990d (diff)
* Wrap deleteFromStore() in a transaction. Otherwise there might be a
race with other processes that add new referrers to a path, resulting in the garbage collector crashing with "foreign key constraint failed". (Nix/4) * Make --gc --print-dead etc. interruptible.
Diffstat (limited to 'src/libstore')
-rw-r--r--src/libstore/gc.cc8
-rw-r--r--src/libstore/local-store.cc13
2 files changed, 13 insertions, 8 deletions
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index 7d58cd50a..b8395bfc4 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -421,7 +421,7 @@ struct LocalStore::GCState
};
-static bool doDelete(GCOptions::GCAction action)
+static bool shouldDelete(GCOptions::GCAction action)
{
return action == GCOptions::gcDeleteDead
|| action == GCOptions::gcDeleteSpecific;
@@ -438,6 +438,8 @@ bool LocalStore::isActiveTempFile(const GCState & state,
bool LocalStore::tryToDelete(GCState & state, const Path & path)
{
+ checkInterrupt();
+
if (!pathExists(path)) return true;
if (state.deleted.find(path) != state.deleted.end()) return true;
if (state.live.find(path) != state.live.end()) return false;
@@ -516,7 +518,7 @@ bool LocalStore::tryToDelete(GCState & state, const Path & path)
}
/* The path is garbage, so delete it. */
- if (doDelete(state.options.action)) {
+ if (shouldDelete(state.options.action)) {
printMsg(lvlInfo, format("deleting `%1%'") % path);
unsigned long long bytesFreed, blocksFreed;
@@ -625,7 +627,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
vector<Path> entries_(entries.begin(), entries.end());
random_shuffle(entries_.begin(), entries_.end());
- if (doDelete(state.options.action))
+ if (shouldDelete(state.options.action))
printMsg(lvlError, format("deleting garbage..."));
else
printMsg(lvlError, format("determining live/dead paths..."));
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index c0c1461b4..c0c75e34d 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -298,11 +298,10 @@ void LocalStore::openDB(bool create)
if (sqlite3_exec(db, ("pragma synchronous = " + syncMode + ";").c_str(), 0, 0, 0) != SQLITE_OK)
throw SQLiteError(db, "setting synchronous mode");
- /* Set the SQLite journal mode. The default is write-ahead
- logging since it's the fastest and supports more concurrency.
- The downside is that it doesn't work over NFS, so allow
- truncate mode alternatively. */
- string mode = queryBoolSetting("use-sqlite-wal", true) ? "wal" : "truncate";
+ /* Set the SQLite journal mode. WAL mode is fastest, but doesn't
+ seem entirely stable at the moment (Oct. 2010). Thus, use
+ truncate mode by default. */
+ string mode = queryBoolSetting("use-sqlite-wal", false) ? "wal" : "truncate";
string prevMode;
{
SQLiteStmt stmt;
@@ -1220,6 +1219,8 @@ void LocalStore::deleteFromStore(const Path & path, unsigned long long & bytesFr
assertStorePath(path);
+ SQLiteTxn txn(db);
+
if (isValidPath(path)) {
PathSet referrers; queryReferrers(path, referrers);
referrers.erase(path); /* ignore self-references */
@@ -1230,6 +1231,8 @@ void LocalStore::deleteFromStore(const Path & path, unsigned long long & bytesFr
}
deletePathWrapped(path, bytesFreed, blocksFreed);
+
+ txn.commit();
}