From a9c4f66cfb1618833cc70ceaf13733730b634193 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 5 Dec 2006 02:18:46 +0000 Subject: * Allow unprivileged users to run the garbage collector and to do `nix-store --delete'. But unprivileged users are not allowed to ignore liveness. * `nix-store --delete --ignore-liveness': ignore the runtime roots as well. --- src/libstore/Makefile.am | 2 +- src/libstore/build.cc | 1 - src/libstore/gc.cc | 8 +++---- src/libstore/gc.hh | 42 ------------------------------------ src/libstore/local-store.cc | 1 - src/libstore/local-store.hh | 3 +++ src/libstore/remote-store.cc | 21 ++++++++++++++++++ src/libstore/remote-store.hh | 3 +++ src/libstore/store-api.hh | 48 +++++++++++++++++++++++++++++++++++++++++ src/libstore/worker-protocol.hh | 1 + 10 files changed, 81 insertions(+), 49 deletions(-) delete mode 100644 src/libstore/gc.hh (limited to 'src/libstore') 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 Substitutes; typedef std::map 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 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 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; -- cgit 1.4.1