diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index cd25ded72b..4c1bbb708e 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -209,6 +209,9 @@ LocalStore::LocalStore() 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 */ @@ -288,6 +291,10 @@ void LocalStore::prepareStatements() "select path from Refs join ValidPaths on referrer = id where reference = (select id from ValidPaths where path = ?);"); stmtInvalidatePath.create(db, "delete from ValidPaths where path = ?;"); + stmtRegisterFailedPath.create(db, + "insert into FailedPaths (path, time) values (?, ?);"); + stmtHasPathFailed.create(db, + "select time from FailedPaths where path = ?;"); } @@ -425,13 +432,23 @@ void LocalStore::registerValidPath(const ValidPathInfo & info) void LocalStore::registerFailedPath(const Path & path) { - throw Error("not implemented"); + if (hasPathFailed(path)) return; + SQLiteStmtUse use(stmtRegisterFailedPath); + stmtRegisterFailedPath.bind(path); + stmtRegisterFailedPath.bind(time(0)); + if (sqlite3_step(stmtRegisterFailedPath) != SQLITE_DONE) + throw SQLiteError(db, format("registering failed path `%1%'") % path); } bool LocalStore::hasPathFailed(const Path & path) { - throw Error("not implemented"); + SQLiteStmtUse use(stmtHasPathFailed); + stmtHasPathFailed.bind(path); + int res = sqlite3_step(stmtHasPathFailed); + if (res != SQLITE_DONE && res != SQLITE_ROW) + throw SQLiteError(db, "querying whether path failed"); + return res == SQLITE_ROW; } diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index 34aa55fc8f..e1859e68ed 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -196,6 +196,8 @@ private: SQLiteStmt stmtQueryReferences; SQLiteStmt stmtQueryReferrers; SQLiteStmt stmtInvalidatePath; + SQLiteStmt stmtRegisterFailedPath; + SQLiteStmt stmtHasPathFailed; int getSchema(); diff --git a/src/libstore/schema.sql b/src/libstore/schema.sql index dc53f452c2..1e707ce1f4 100644 --- a/src/libstore/schema.sql +++ b/src/libstore/schema.sql @@ -1,5 +1,3 @@ -pragma foreign_keys = on; - create table if not exists ValidPaths ( id integer primary key autoincrement not null, path text unique not null, @@ -19,7 +17,7 @@ create table if not exists Refs ( create index if not exists IndexReferrer on Refs(referrer); create index if not exists IndexReference on Refs(reference); -create table if not exists FailedDerivations ( +create table if not exists FailedPaths ( path text primary key not null, time integer not null ); diff --git a/tests/referrers.sh b/tests/referrers.sh index e3f8e07bc1..752f05c3d5 100644 --- a/tests/referrers.sh +++ b/tests/referrers.sh @@ -3,6 +3,8 @@ source common.sh # This takes way to long on Cygwin (because process creation is so slow...). if test "$system" = i686-cygwin; then exit 0; fi +clearStore + max=2500 reference=$NIX_STORE_DIR/abcdef @@ -25,34 +27,11 @@ echo "registering..." time $nixstore --register-validity < $TEST_ROOT/reg_info -oldTime=$(cat test-tmp/db/info/1 | grep Registered-At) - -echo "sleeping..." - -sleep 2 - -echo "reregistering..." - -time $nixstore --register-validity --reregister < $TEST_ROOT/reg_info - -newTime=$(cat test-tmp/db/info/1 | grep Registered-At) - -if test "$newTime" != "$oldTime"; then - echo "reregistration changed original registration time" - exit 1 -fi - -if test "$(cat test-tmp/db/referrer/1 | wc -w)" -ne 1; then - echo "reregistration duplicated referrers" - exit 1 -fi - echo "collecting garbage..." ln -sfn $reference "$NIX_STATE_DIR"/gcroots/ref time $nixstore --gc -if test "$(cat test-tmp/db/referrer/abcdef | wc -w)" -ne 0; then +if test "$(sqlite3 ./test-tmp/db/db.sqlite 'select count(*) from Refs')" -ne 0; then echo "referrers not cleaned up" exit 1 fi -