* Fix and simplify the garbage collector (it's still not concurrent,
though). In particular it's now much easier to register a GC root. Just place a symlink to whatever store path it is that you want to keep in /nix/var/nix/gcroots.
This commit is contained in:
parent
59682e6188
commit
c505702265
10 changed files with 124 additions and 109 deletions
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue