about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libmain/shared.cc1
-rw-r--r--src/libstore/Makefile.am2
-rw-r--r--src/libstore/build.cc1
-rw-r--r--src/libstore/gc.cc8
-rw-r--r--src/libstore/gc.hh42
-rw-r--r--src/libstore/local-store.cc1
-rw-r--r--src/libstore/local-store.hh3
-rw-r--r--src/libstore/remote-store.cc21
-rw-r--r--src/libstore/remote-store.hh3
-rw-r--r--src/libstore/store-api.hh48
-rw-r--r--src/libstore/worker-protocol.hh1
-rw-r--r--src/nix-env/main.cc1
-rw-r--r--src/nix-env/profiles.cc2
-rw-r--r--src/nix-instantiate/main.cc1
-rw-r--r--src/nix-store/main.cc5
-rw-r--r--src/nix-worker/main.cc22
16 files changed, 106 insertions, 56 deletions
diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc
index c1bd1b73a7fd..393f31fcda66 100644
--- a/src/libmain/shared.cc
+++ b/src/libmain/shared.cc
@@ -1,6 +1,5 @@
 #include "shared.hh"
 #include "globals.hh"
-#include "gc.hh"
 #include "store-api.hh"
 #include "util.hh"
 
diff --git a/src/libstore/Makefile.am b/src/libstore/Makefile.am
index bb217464e03f..21b1545f6c68 100644
--- a/src/libstore/Makefile.am
+++ b/src/libstore/Makefile.am
@@ -6,7 +6,7 @@ libstore_la_SOURCES = \
 
 pkginclude_HEADERS = \
  store-api.hh local-store.hh remote-store.hh derivations.hh misc.hh \
- globals.hh db.hh references.hh pathlocks.hh gc.hh  \
+ globals.hh db.hh references.hh pathlocks.hh \
  worker-protocol.hh
 
 libstore_la_LIBADD = ../libutil/libutil.la ../boost/format/libformat.la
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 8a109bcefdab..202fb0ac44e3 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -2,7 +2,6 @@
 #include "pathlocks.hh"
 #include "misc.hh"
 #include "globals.hh"
-#include "gc.hh"
 #include "local-store.hh"
 #include "db.hh"
 #include "util.hh"
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index e5217c9b8636..4d8f25e655fc 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -1,4 +1,3 @@
-#include "gc.hh"
 #include "globals.hh"
 #include "misc.hh"
 #include "pathlocks.hh"
@@ -428,7 +427,7 @@ static Paths topoSort(const PathSet & paths)
 }
 
 
-void collectGarbage(GCAction action, const PathSet & pathsToDelete,
+void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
     bool ignoreLiveness, PathSet & result, unsigned long long & bytesFreed)
 {
     result.clear();
@@ -446,7 +445,7 @@ void collectGarbage(GCAction action, const PathSet & pathsToDelete,
 
     /* Find the roots.  Since we've grabbed the GC lock, the set of
        permanent roots cannot increase now. */
-    Roots rootMap = ignoreLiveness ? Roots() : findRoots(true);
+    Roots rootMap = ignoreLiveness ? Roots() : nix::findRoots(true);
 
     PathSet roots;
     for (Roots::iterator i = rootMap.begin(); i != rootMap.end(); ++i)
@@ -456,7 +455,8 @@ void collectGarbage(GCAction action, const PathSet & pathsToDelete,
        NIX_ROOT_FINDER environment variable.  This is typically used
        to add running programs to the set of roots (to prevent them
        from being garbage collected). */
-    addAdditionalRoots(roots);
+    if (!ignoreLiveness)
+        addAdditionalRoots(roots);
 
     if (action == gcReturnRoots) {
         result = roots;
diff --git a/src/libstore/gc.hh b/src/libstore/gc.hh
deleted file mode 100644
index d4f40afa2ac1..000000000000
--- a/src/libstore/gc.hh
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef __GC_H
-#define __GC_H
-
-#include "types.hh"
-
-
-namespace nix {
-
-
-/* Garbage collector operation. */
-typedef enum {
-    gcReturnRoots,
-    gcReturnLive,
-    gcReturnDead,
-    gcDeleteDead,
-    gcDeleteSpecific,
-} GCAction;
-
-/* If `action' is set to `gcReturnRoots', find and return the set of
-   roots for the garbage collector.  These are the store paths
-   symlinked to in the `gcroots' directory.  If `action' is
-   `gcReturnLive', return the set of paths reachable from (i.e. in the
-   closure of) the roots.  If `action' is `gcReturnDead', return the
-   set of paths not reachable from the roots.  If `action' is
-   `gcDeleteDead', actually delete the latter set. */
-void collectGarbage(GCAction action, const PathSet & pathsToDelete,
-    bool ignoreLiveness, PathSet & result, unsigned long long & bytesFreed);
-
-/* Remove the temporary roots file for this process.  Any temporary
-   root becomes garbage after this point unless it has been registered
-   as a (permanent) root. */
-void removeTempRoots();
-
-/* Register a permanent GC root. */
-Path addPermRoot(const Path & storePath, const Path & gcRoot,
-    bool indirect, bool allowOutsideRootsDir = false);
-
-
-}
-
-
-#endif /* !__GC_H */
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index 2f3f3a7da882..c1fcb035bc82 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -4,7 +4,6 @@
 #include "db.hh"
 #include "archive.hh"
 #include "pathlocks.hh"
-#include "gc.hh"
 #include "aterm.hh"
 #include "derivations-ast.hh"
     
diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh
index a7b3926cc7af..58bb70d0e4d5 100644
--- a/src/libstore/local-store.hh
+++ b/src/libstore/local-store.hh
@@ -66,6 +66,9 @@ public:
     void syncWithGC();
 
     Roots findRoots();
+
+    void collectGarbage(GCAction action, const PathSet & pathsToDelete,
+        bool ignoreLiveness, PathSet & result, unsigned long long & bytesFreed);
 };
 
 
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index 6ddbb3e2a260..504eb52329a6 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -302,6 +302,27 @@ Roots RemoteStore::findRoots()
 }
 
 
+void RemoteStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
+    bool ignoreLiveness, PathSet & result, unsigned long long & bytesFreed)
+{
+    result.clear();
+    bytesFreed = 0;
+    writeInt(wopCollectGarbage, to);
+    writeInt(action, to);
+    writeStringSet(pathsToDelete, to);
+    writeInt(ignoreLiveness, to);
+    
+    processStderr();
+    
+    result = readStringSet(from);
+
+    /* Ugh - NAR integers are 64 bits, but read/writeInt() aren't. */
+    unsigned int lo = readInt(from);
+    unsigned int hi = readInt(from);
+    bytesFreed = (((unsigned long long) hi) << 32) | lo;
+}
+
+
 void RemoteStore::processStderr()
 {
     unsigned int msg;
diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh
index 11e7e328bef3..82cfb08e952c 100644
--- a/src/libstore/remote-store.hh
+++ b/src/libstore/remote-store.hh
@@ -54,6 +54,9 @@ public:
     void syncWithGC();
     
     Roots findRoots();
+
+    void collectGarbage(GCAction action, const PathSet & pathsToDelete,
+        bool ignoreLiveness, PathSet & result, unsigned long long & bytesFreed);
     
 private:
     AutoCloseFD fdSocket;
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index bda232d3d232..19c5d81cf267 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -37,6 +37,16 @@ typedef list<Substitute> Substitutes;
 typedef std::map<Path, Path> Roots;
 
 
+/* Garbage collector operation. */
+typedef enum {
+    gcReturnRoots,
+    gcReturnLive,
+    gcReturnDead,
+    gcDeleteDead,
+    gcDeleteSpecific,
+} GCAction;
+
+
 class StoreAPI 
 {
 public:
@@ -127,6 +137,33 @@ public:
        outside of the Nix store that point to `storePath'.  */
     virtual Roots findRoots() = 0;
 
+    /* Depending on `action', this function does the following:
+
+       - `gcReturnRoots': find and return the set of roots for the
+         garbage collector.  These are the store paths symlinked to in
+         the `gcroots' directory.
+
+       - `gcReturnLive': return the set of paths reachable from
+         (i.e. in the closure of) the roots.
+
+       - `gcReturnDead': return the set of paths not reachable from
+         the roots.
+
+       - `gcDeleteDead': actually delete the latter set.
+
+       - `gcDeleteSpecific': delete the paths listed in
+         `pathsToDelete', insofar as they are not reachable.
+
+       If `ignoreLiveness' is set, then reachability from the roots is
+       ignored (dangerous!).  However, the paths must still be
+       unreferenced *within* the store (i.e., there can be no other
+       store paths that depend on them).
+
+       For `gcReturnDead', `gcDeleteDead' and `gcDeleteSpecific', the
+       number of bytes that would be or was freed is returned in
+       `bytesFreed'. */
+    virtual void collectGarbage(GCAction action, const PathSet & pathsToDelete,
+        bool ignoreLiveness, PathSet & result, unsigned long long & bytesFreed) = 0;
 };
 
 
@@ -177,6 +214,17 @@ std::pair<Path, Hash> computeStorePathForPath(const Path & srcPath,
 Path computeStorePathForText(const string & suffix, const string & s);
 
 
+/* Remove the temporary roots file for this process.  Any temporary
+   root becomes garbage after this point unless it has been registered
+   as a (permanent) root. */
+void removeTempRoots();
+
+
+/* Register a permanent GC root. */
+Path addPermRoot(const Path & storePath, const Path & gcRoot,
+    bool indirect, bool allowOutsideRootsDir = false);
+
+
 /* For now, there is a single global store API object, but we'll
    purify that in the future. */
 extern boost::shared_ptr<StoreAPI> store;
diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh
index bb5d9d7b3481..b3339101103b 100644
--- a/src/libstore/worker-protocol.hh
+++ b/src/libstore/worker-protocol.hh
@@ -25,6 +25,7 @@ typedef enum {
     wopAddIndirectRoot,
     wopSyncWithGC,
     wopFindRoots,
+    wopCollectGarbage,
 } WorkerOp;
 
 
diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc
index f2988485cdfd..90d799224efd 100644
--- a/src/nix-env/main.cc
+++ b/src/nix-env/main.cc
@@ -2,7 +2,6 @@
 #include "names.hh"
 #include "globals.hh"
 #include "misc.hh"
-#include "gc.hh"
 #include "shared.hh"
 #include "parser.hh"
 #include "eval.hh"
diff --git a/src/nix-env/profiles.cc b/src/nix-env/profiles.cc
index 0014161842e5..75585b1b2907 100644
--- a/src/nix-env/profiles.cc
+++ b/src/nix-env/profiles.cc
@@ -1,6 +1,6 @@
 #include "profiles.hh"
+#include "store-api.hh"
 #include "util.hh"
-#include "gc.hh"
 
 #include <sys/types.h>
 #include <sys/stat.h>
diff --git a/src/nix-instantiate/main.cc b/src/nix-instantiate/main.cc
index 71f0a44e2791..ffd8a2e71f40 100644
--- a/src/nix-instantiate/main.cc
+++ b/src/nix-instantiate/main.cc
@@ -2,7 +2,6 @@
 #include <iostream>
 
 #include "globals.hh"
-#include "gc.hh"
 #include "shared.hh"
 #include "eval.hh"
 #include "parser.hh"
diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc
index eb037bda1913..701e8397427b 100644
--- a/src/nix-store/main.cc
+++ b/src/nix-store/main.cc
@@ -3,7 +3,6 @@
 
 #include "globals.hh"
 #include "misc.hh"
-#include "gc.hh"
 #include "archive.hh"
 #include "shared.hh"
 #include "dotgraph.hh"
@@ -573,7 +572,7 @@ static void opGC(Strings opFlags, Strings opArgs)
     PathSet result;
     PrintFreed freed(action == gcDeleteDead || action == gcReturnDead,
         action == gcReturnDead);
-    collectGarbage(action, PathSet(), false, result, freed.bytesFreed);
+    store->collectGarbage(action, PathSet(), false, result, freed.bytesFreed);
 
     if (action != gcDeleteDead) {
         for (PathSet::iterator i = result.begin(); i != result.end(); ++i)
@@ -601,7 +600,7 @@ static void opDelete(Strings opFlags, Strings opArgs)
     
     PathSet dummy;
     PrintFreed freed(true, false);
-    collectGarbage(gcDeleteSpecific, pathsToDelete, ignoreLiveness,
+    store->collectGarbage(gcDeleteSpecific, pathsToDelete, ignoreLiveness,
         dummy, freed.bytesFreed);
 }
 
diff --git a/src/nix-worker/main.cc b/src/nix-worker/main.cc
index e772421f39bc..4fa43f643cc9 100644
--- a/src/nix-worker/main.cc
+++ b/src/nix-worker/main.cc
@@ -281,6 +281,28 @@ static void performOp(Source & from, Sink & to, unsigned int op)
         break;
     }
 
+    case wopCollectGarbage: {
+        GCAction action = (GCAction) readInt(from);
+        PathSet pathsToDelete = readStorePaths(from);
+        bool ignoreLiveness = readInt(from);
+
+        PathSet result;
+        unsigned long long bytesFreed;
+        
+        startWork();
+        if (ignoreLiveness)
+            throw Error("you are not allowed to ignore liveness");
+        store->collectGarbage(action, pathsToDelete, ignoreLiveness,
+            result, bytesFreed);
+        stopWork();
+        
+        writeStringSet(result, to);
+        writeInt(bytesFreed & 0xffffffff, to);
+        writeInt(bytesFreed >> 32, to);
+        
+        break;
+    }
+            
     default:
         throw Error(format("invalid operation %1%") % op);
     }