about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/local-store.cc26
-rw-r--r--src/libstore/local-store.hh1
-rw-r--r--src/libstore/schema.sql10
3 files changed, 35 insertions, 2 deletions
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index 4c1bbb708e78..2f12256db02e 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 <iostream>
 #include <algorithm>
@@ -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 e1859e68edf2..f10ba18d5a71 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 1e707ce1f41e..682ce5ed7b26 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