* Some refactoring. Better output with `-v' for --use-atime.
This commit is contained in:
parent
77afd97a99
commit
c987061aa4
2 changed files with 40 additions and 35 deletions
|
@ -444,6 +444,8 @@ Paths topoSortPaths(const PathSet & paths)
|
||||||
|
|
||||||
static time_t lastFileAccessTime(const Path & path)
|
static time_t lastFileAccessTime(const Path & path)
|
||||||
{
|
{
|
||||||
|
checkInterrupt();
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (lstat(path.c_str(), &st) == -1)
|
if (lstat(path.c_str(), &st) == -1)
|
||||||
throw SysError(format("statting `%1%'") % path);
|
throw SysError(format("statting `%1%'") % path);
|
||||||
|
@ -467,39 +469,13 @@ static time_t lastFileAccessTime(const Path & path)
|
||||||
struct GCLimitReached { };
|
struct GCLimitReached { };
|
||||||
|
|
||||||
|
|
||||||
void LocalStore::tryToDelete(const GCOptions & options, GCResults & results,
|
void LocalStore::gcPath(const GCOptions & options, GCResults & results,
|
||||||
PathSet & done, const Path & path)
|
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);
|
results.paths.insert(path);
|
||||||
|
|
||||||
if (!pathExists(path)) return;
|
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__
|
#ifndef __CYGWIN__
|
||||||
AutoCloseFD fdLock;
|
AutoCloseFD fdLock;
|
||||||
|
|
||||||
|
@ -517,8 +493,6 @@ void LocalStore::tryToDelete(const GCOptions & options, GCResults & results,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
printMsg(lvlInfo, format("deleting `%1%'") % path);
|
|
||||||
|
|
||||||
/* Okay, it's safe to delete. */
|
/* Okay, it's safe to delete. */
|
||||||
unsigned long long bytesFreed, blocksFreed;
|
unsigned long long bytesFreed, blocksFreed;
|
||||||
deleteFromStore(path, 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>
|
struct CachingAtimeComparator : public std::binary_function<Path, Path, bool>
|
||||||
{
|
{
|
||||||
std::map<Path, time_t> cache;
|
std::map<Path, time_t> cache;
|
||||||
|
@ -724,7 +723,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
|
||||||
determined by the references graph. */
|
determined by the references graph. */
|
||||||
printMsg(lvlError, format("deleting garbage..."));
|
printMsg(lvlError, format("deleting garbage..."));
|
||||||
foreach (PathSet::iterator, i, storePaths)
|
foreach (PathSet::iterator, i, storePaths)
|
||||||
tryToDelete(options, results, done, *i);
|
gcPathRecursive(options, results, done, *i);
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
|
@ -750,6 +749,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
|
||||||
referrers into the priority queue. */
|
referrers into the priority queue. */
|
||||||
printMsg(lvlError, format("finding deletable paths..."));
|
printMsg(lvlError, format("finding deletable paths..."));
|
||||||
foreach (PathSet::iterator, i, storePaths) {
|
foreach (PathSet::iterator, i, storePaths) {
|
||||||
|
checkInterrupt();
|
||||||
/* We can safely delete a path if it's invalid or
|
/* We can safely delete a path if it's invalid or
|
||||||
it has no referrers. Note that all the invalid
|
it has no referrers. Note that all the invalid
|
||||||
paths will be deleted in the first round. */
|
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
|
/* Now delete everything in the order of the priority
|
||||||
queue until nothing is left. */
|
queue until nothing is left. */
|
||||||
|
printMsg(lvlError, format("deleting garbage..."));
|
||||||
while (!prioQueue.empty()) {
|
while (!prioQueue.empty()) {
|
||||||
|
checkInterrupt();
|
||||||
Path path = prioQueue.top(); prioQueue.pop();
|
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;
|
PathSet references;
|
||||||
if (isValidPath(path)) references = queryReferencesNoSelf(path);
|
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
|
/* For each reference of the current path, see if the
|
||||||
reference has now become deletable (i.e. is in the
|
reference has now become deletable (i.e. is in the
|
||||||
|
|
|
@ -167,8 +167,11 @@ private:
|
||||||
|
|
||||||
void upgradeStore12();
|
void upgradeStore12();
|
||||||
|
|
||||||
void tryToDelete(const GCOptions & options, GCResults & results,
|
void gcPath(const GCOptions & options, GCResults & results,
|
||||||
PathSet & done, const Path & path);
|
const Path & path);
|
||||||
|
|
||||||
|
void gcPathRecursive(const GCOptions & options,
|
||||||
|
GCResults & results, PathSet & done, const Path & path);
|
||||||
|
|
||||||
void startSubstituter(const Path & substituter,
|
void startSubstituter(const Path & substituter,
|
||||||
RunningSubstituter & runningSubstituter);
|
RunningSubstituter & runningSubstituter);
|
||||||
|
|
Loading…
Reference in a new issue