diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 4c1bbb708e..2f12256db0 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -3,9 +3,9 @@ #include "globals.hh" #include "archive.hh" #include "pathlocks.hh" -#include "aterm.hh" #include "derivations-ast.hh" #include "worker-protocol.hh" +#include "derivations.hh" #include #include @@ -295,6 +295,8 @@ void LocalStore::prepareStatements() "insert into FailedPaths (path, time) values (?, ?);"); stmtHasPathFailed.create(db, "select time from FailedPaths where path = ?;"); + stmtAddDerivationOutput.create(db, + "insert or replace into DerivationOutputs (drv, id, path) values (?, ?, ?);"); } @@ -397,7 +399,27 @@ unsigned long long LocalStore::addValidPath(const ValidPathInfo & info) stmtRegisterValidPath.bind(); // null if (sqlite3_step(stmtRegisterValidPath) != SQLITE_DONE) throw SQLiteError(db, format("registering valid path `%1%' in database") % info.path); - return sqlite3_last_insert_rowid(db); + unsigned long long id = sqlite3_last_insert_rowid(db); + + /* If this is a derivation, then store the derivation outputs in + the database. This is useful for the garbage collector: it can + efficiently query whether a path is an output of some + derivation. */ + if (isDerivation(info.path)) { + ATerm t = ATreadFromNamedFile(info.path.c_str()); + if (!t) throw Error(format("cannot read derivation `%1%'") % info.path); + Derivation drv = parseDerivation(t); + foreach (DerivationOutputs::iterator, i, drv.outputs) { + SQLiteStmtUse use(stmtAddDerivationOutput); + stmtAddDerivationOutput.bind(id); + stmtAddDerivationOutput.bind(i->first); + stmtAddDerivationOutput.bind(i->second.path); + if (sqlite3_step(stmtAddDerivationOutput) != SQLITE_DONE) + throw SQLiteError(db, format("adding derivation output for `%1%' in database") % info.path); + } + } + + return id; } diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index e1859e68ed..f10ba18d5a 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -198,6 +198,7 @@ private: SQLiteStmt stmtInvalidatePath; SQLiteStmt stmtRegisterFailedPath; SQLiteStmt stmtHasPathFailed; + SQLiteStmt stmtAddDerivationOutput; int getSchema(); diff --git a/src/libstore/schema.sql b/src/libstore/schema.sql index 1e707ce1f4..682ce5ed7b 100644 --- a/src/libstore/schema.sql +++ b/src/libstore/schema.sql @@ -17,6 +17,16 @@ 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 DerivationOutputs ( + drv integer not null, + id text not null, -- symbolic output id, usually "out" + path text not null, + primary key (drv, id), + foreign key (drv) references ValidPaths(id) on delete cascade +); + +create index if not exists IndexDerivationOutputs on DerivationOutputs(path); + create table if not exists FailedPaths ( path text primary key not null, time integer not null