about summary refs log tree commit diff
path: root/src/libstore/gc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/gc.cc')
-rw-r--r--src/libstore/gc.cc68
1 files changed, 35 insertions, 33 deletions
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index bb2e032c107e..5752e408a80d 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<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