summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2012-03-26 20:56:30 +0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2012-03-26 20:56:30 +0200
commit480dda0e42e69be47434be5bce95be950bdb59b5 (patch)
tree2429d3ec9b8fa8b36a8b18bb337642aeab2d3fd4 /src
parent117670be570d775a18e4e35db3dae00abc24f729 (diff)
downloadguix-480dda0e42e69be47434be5bce95be950bdb59b5.tar.gz
Delete non-directory valid paths right away
It's unlikely that rename() is faster than unlink() on a regular file
or symlink, so don't bother.
Diffstat (limited to 'src')
-rw-r--r--src/libstore/gc.cc43
1 files changed, 27 insertions, 16 deletions
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index 65c8dc210b..56cb97d877 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -433,8 +433,13 @@ void LocalStore::deleteGarbage(GCState & state, const Path & path)
 bool LocalStore::tryToDelete(GCState & state, const Path & path)
 {
     checkInterrupt();
-    
-    if (!pathExists(path)) return true;
+
+    struct stat st;
+    if (lstat(path.c_str(), &st)) {
+        if (errno == ENOENT) return true;
+        throw SysError(format("getting status of %1%") % path);
+    }
+
     if (state.deleted.find(path) != state.deleted.end()) return true;
     if (state.live.find(path) != state.live.end()) return false;
 
@@ -514,21 +519,27 @@ bool LocalStore::tryToDelete(GCState & state, const Path & path)
     /* The path is garbage, so delete it. */
     if (shouldDelete(state.options.action)) {
 
+        /* If it's a valid path that's not a regular file or symlink,
+           invalidate it, rename it, and schedule it for deletion.
+           The renaming is to ensure that later (when we're not
+           holding the global GC lock) we can delete the path without
+           being afraid that the path has become alive again.
+           Otherwise delete it right away. */
         if (isValidPath(path)) {
-            /* If it's a valid path, invalidate it, rename it, and
-               schedule it for deletion.  The renaming is to ensure
-               that later (when we're not holding the global GC lock)
-               we can delete the path without being afraid that the
-               path has become alive again. */
-            printMsg(lvlInfo, format("invalidating `%1%'") % path);
-            // Estimate the amount freed using the narSize field.
-            state.bytesInvalidated += queryPathInfo(path).narSize;
-            invalidatePathChecked(path);
-            Path tmp = (format("%1%-gc-%2%") % path % getpid()).str();
-            makeMutable(path.c_str());
-            if (rename(path.c_str(), tmp.c_str()))
-                throw SysError(format("unable to rename `%1%' to `%2%'") % path % tmp);
-            state.invalidated.insert(tmp);
+            if (S_ISDIR(st.st_mode)) {
+                printMsg(lvlInfo, format("invalidating `%1%'") % path);
+                // Estimate the amount freed using the narSize field.
+                state.bytesInvalidated += queryPathInfo(path).narSize;
+                invalidatePathChecked(path);
+                makeMutable(path.c_str());
+                Path tmp = (format("%1%-gc-%2%") % path % getpid()).str();
+                if (rename(path.c_str(), tmp.c_str()))
+                    throw SysError(format("unable to rename `%1%' to `%2%'") % path % tmp);
+                state.invalidated.insert(tmp);
+            } else {
+                invalidatePathChecked(path);
+                deleteGarbage(state, path);
+            }
         } else
             deleteGarbage(state, path);