* Some refactoring. Better output with `-v' for --use-atime.

This commit is contained in:
Eelco Dolstra 2008-09-17 12:54:07 +00:00
parent 77afd97a99
commit c987061aa4
2 changed files with 40 additions and 35 deletions

View File

@ -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<Path, Path, bool>
{
std::map<Path, time_t> 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

View File

@ -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);