From c987061aa401eaad984aaa3058aa0506df4f46da Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 17 Sep 2008 12:54:07 +0000 Subject: [PATCH] * Some refactoring. Better output with `-v' for --use-atime. --- src/libstore/gc.cc | 68 +++++++++++++++++++------------------ src/libstore/local-store.hh | 7 ++-- 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index bb2e032c10..5752e408a8 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -444,6 +444,8 @@ Paths topoSortPaths(const PathSet & paths) static time_t lastFileAccessTime(const Path & path) { + checkInterrupt(); + struct stat st; if (lstat(path.c_str(), &st) == -1) throw SysError(format("statting `%1%'") % path); @@ -467,39 +469,13 @@ static time_t lastFileAccessTime(const Path & path) struct GCLimitReached { }; -void LocalStore::tryToDelete(const GCOptions & options, GCResults & results, - PathSet & done, const Path & path) +void LocalStore::gcPath(const GCOptions & options, GCResults & results, + const Path & path) { - if (done.find(path) != done.end()) return; - done.insert(path); - - startNest(nest, lvlDebug, format("looking at `%1%'") % path); - - /* Delete all the referrers first. They must be garbage too, - since if they were in the closure of some live path, then this - path would also be in the closure. Note that - deleteFromStore() below still makes sure that the referrer set - has become empty, just in case. */ - PathSet referrers; - if (isValidPath(path)) - queryReferrers(path, referrers); - foreach (PathSet::iterator, i, referrers) - if (*i != path) tryToDelete(options, results, done, *i); - results.paths.insert(path); if (!pathExists(path)) return; - /* If just returning the set of dead paths, we also return the - space that would be freed if we deleted them. */ - if (options.action == GCOptions::gcReturnDead) { - unsigned long long bytesFreed, blocksFreed; - computePathSize(path, bytesFreed, blocksFreed); - results.bytesFreed += bytesFreed; - results.blocksFreed += blocksFreed; - return; - } - #ifndef __CYGWIN__ AutoCloseFD fdLock; @@ -517,8 +493,6 @@ void LocalStore::tryToDelete(const GCOptions & options, GCResults & results, } #endif - printMsg(lvlInfo, format("deleting `%1%'") % path); - /* Okay, it's safe to delete. */ unsigned long long bytesFreed, blocksFreed; deleteFromStore(path, bytesFreed, blocksFreed); @@ -548,6 +522,31 @@ void LocalStore::tryToDelete(const GCOptions & options, GCResults & results, } +void LocalStore::gcPathRecursive(const GCOptions & options, + GCResults & results, PathSet & done, const Path & path) +{ + if (done.find(path) != done.end()) return; + done.insert(path); + + startNest(nest, lvlDebug, format("looking at `%1%'") % path); + + /* Delete all the referrers first. They must be garbage too, + since if they were in the closure of some live path, then this + path would also be in the closure. Note that + deleteFromStore() below still makes sure that the referrer set + has become empty, just in case. */ + PathSet referrers; + if (isValidPath(path)) + queryReferrers(path, referrers); + foreach (PathSet::iterator, i, referrers) + if (*i != path) gcPathRecursive(options, results, done, *i); + + printMsg(lvlInfo, format("deleting `%1%'") % path); + + gcPath(options, results, path); +} + + struct CachingAtimeComparator : public std::binary_function { std::map cache; @@ -724,7 +723,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) determined by the references graph. */ printMsg(lvlError, format("deleting garbage...")); foreach (PathSet::iterator, i, storePaths) - tryToDelete(options, results, done, *i); + gcPathRecursive(options, results, done, *i); } else { @@ -750,6 +749,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) referrers into the priority queue. */ printMsg(lvlError, format("finding deletable paths...")); foreach (PathSet::iterator, i, storePaths) { + checkInterrupt(); /* We can safely delete a path if it's invalid or it has no referrers. Note that all the invalid paths will be deleted in the first round. */ @@ -762,14 +762,16 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) /* Now delete everything in the order of the priority queue until nothing is left. */ + printMsg(lvlError, format("deleting garbage...")); while (!prioQueue.empty()) { + checkInterrupt(); Path path = prioQueue.top(); prioQueue.pop(); - printMsg(lvlTalkative, format("atime %1%: %2%") % showTime("%F %H:%M:%S", atimeComp.cache[path]) % path); + printMsg(lvlInfo, format("deleting `%1%' (last accesses %2%)") % path % showTime("%F %H:%M:%S", atimeComp.cache[path])); PathSet references; if (isValidPath(path)) references = queryReferencesNoSelf(path); - tryToDelete(options, results, done, path); + gcPath(options, results, path); /* For each reference of the current path, see if the reference has now become deletable (i.e. is in the diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index 6ad5032f6e..37ed543fc3 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -167,8 +167,11 @@ private: void upgradeStore12(); - void tryToDelete(const GCOptions & options, GCResults & results, - PathSet & done, const Path & path); + void gcPath(const GCOptions & options, GCResults & results, + const Path & path); + + void gcPathRecursive(const GCOptions & options, + GCResults & results, PathSet & done, const Path & path); void startSubstituter(const Path & substituter, RunningSubstituter & runningSubstituter);