diff options
Diffstat (limited to 'src/libstore')
-rw-r--r-- | src/libstore/build.cc | 4 | ||||
-rw-r--r-- | src/libstore/gc.cc | 58 | ||||
-rw-r--r-- | src/libstore/gc.hh | 27 | ||||
-rw-r--r-- | src/libstore/store.cc | 11 | ||||
-rw-r--r-- | src/libstore/store.hh | 2 |
5 files changed, 78 insertions, 24 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc index b63488b8d..52bd08bb1 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -458,7 +458,7 @@ void DerivationGoal::haveStoreExpr() i != invalidOutputs.end(); ++i) /* Don't bother creating a substitution goal if there are no substitutes. */ - if (querySubstitutes(*i).size() > 0) + if (querySubstitutes(noTxn, *i).size() > 0) addWaitee(worker.makeSubstitutionGoal(*i)); if (waitees.empty()) /* to prevent hang (no wake-up event) */ @@ -1315,7 +1315,7 @@ void SubstitutionGoal::init() } /* Read the substitutes. */ - subs = querySubstitutes(storePath); + subs = querySubstitutes(noTxn, storePath); /* To maintain the closure invairant, we first have to realise the paths referenced by this one. */ diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 4f3306505..ba6e6bb9d 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -1,12 +1,68 @@ #include "globals.hh" #include "gc.hh" - +#include "build.hh" #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> +void collectGarbage(const PathSet & roots, GCAction action, + PathSet & result) +{ + result.clear(); + + /* !!! TODO: Acquire an exclusive lock on the gcroots directory. + This prevents the set of live paths from increasing after this + point. */ + + /* Determine the live paths which is just the closure of the + roots under the `references' relation. */ + PathSet livePaths; + for (PathSet::const_iterator i = roots.begin(); i != roots.end(); ++i) + computeFSClosure(canonPath(*i), livePaths); + + if (action == gcReturnLive) { + result = livePaths; + return; + } + + /* !!! TODO: Try to acquire (without blocking) exclusive locks on + the files in the `pending' directory. Delete all files for + which we managed to acquire such a lock (since if we could get + such a lock, that means that the process that owned the file + has died). */ + + /* !!! TODO: Acquire shared locks on all files in the pending + directories. This prevents the set of pending paths from + increasing while we are garbage-collecting. Read the set of + pending paths from those files. */ + + /* Read the Nix store directory to find all currently existing + paths. */ + Strings storeNames = readDirectory(nixStore); + + for (Strings::iterator i = storeNames.begin(); i != storeNames.end(); ++i) { + Path path = canonPath(nixStore + "/" + *i); + + if (livePaths.find(path) != livePaths.end()) { + debug(format("live path `%1%'") % path); + continue; + } + + debug(format("dead path `%1%'") % path); + result.insert(path); + + if (action == gcDeleteDead) { + printMsg(lvlInfo, format("deleting `%1%'") % path); + deleteFromStore(path); + } + + } +} + + + #if 0 void followLivePaths(Path nePath, PathSet & live) { diff --git a/src/libstore/gc.hh b/src/libstore/gc.hh index d1ca5c63e..2ea851abc 100644 --- a/src/libstore/gc.hh +++ b/src/libstore/gc.hh @@ -3,24 +3,15 @@ #include "util.hh" +/* Garbage collector operation. */ +typedef enum { gcReturnLive, gcReturnDead, gcDeleteDead } GCAction; -/* Determine the set of "live" store paths, given a set of root store - expressions. The live store paths are those that are reachable - from the roots. The roots are reachable by definition. Any path - mentioned in a reachable store expression is also reachable. If a - derivation store expression is reachable, then its successor (if it - exists) if also reachable. It is not an error for store - expressions not to exist (since this can happen on derivation store - expressions, for instance, due to the substitute mechanism), but - successor links are followed even for non-existant derivations. */ -PathSet findLivePaths(const Paths & roots); - -/* Given a set of "live" store paths, determine the set of "dead" - store paths (which are simply all store paths that are not in the - live set). The value `minAge' specifies the minimum age in seconds - for an unreachable file to be considered dead (0 meaning that any - unreachable file is dead). */ -PathSet findDeadPaths(const PathSet & live, time_t minAge); - +/* If `action' is set to `soReturnLive', return the set of paths + reachable from (i.e. in the closure of) the specified roots. If + `action' is `soReturnDead', return the set of paths not reachable + from the roots. If `action' is `soDeleteDead', actually delete the + latter set. */ +void collectGarbage(const PathSet & roots, GCAction action, + PathSet & result); #endif /* !__GC_H */ diff --git a/src/libstore/store.cc b/src/libstore/store.cc index f5e7d2aa5..30573992c 100644 --- a/src/libstore/store.cc +++ b/src/libstore/store.cc @@ -363,9 +363,9 @@ void registerSubstitute(const Transaction & txn, } -Substitutes querySubstitutes(const Path & srcPath) +Substitutes querySubstitutes(const Transaction & txn, const Path & srcPath) { - return readSubstitutes(noTxn, srcPath); + return readSubstitutes(txn, srcPath); } @@ -411,6 +411,13 @@ static void invalidatePath(const Path & path, Transaction & txn) debug(format("unregistering path `%1%'") % path); nixDB.delPair(txn, dbValidPaths, path); + + /* Clear the `references' entry for this path, as well as the + inverse `referers' entries; but only if there are no + substitutes for this path. This maintains the cleanup + invariant. */ + if (querySubstitutes(txn, path).size() == 0) + setReferences(txn, path, PathSet()); } diff --git a/src/libstore/store.hh b/src/libstore/store.hh index 968786305..dce4eb1d6 100644 --- a/src/libstore/store.hh +++ b/src/libstore/store.hh @@ -45,7 +45,7 @@ void registerSubstitute(const Transaction & txn, const Path & srcPath, const Substitute & sub); /* Return the substitutes for the given path. */ -Substitutes querySubstitutes(const Path & srcPath); +Substitutes querySubstitutes(const Transaction & txn, const Path & srcPath); /* Deregister all substitutes. */ void clearSubstitutes(); |