From 480dda0e42e69be47434be5bce95be950bdb59b5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 26 Mar 2012 20:56:30 +0200 Subject: [PATCH] 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. --- src/libstore/gc.cc | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 65c8dc210..56cb97d87 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);