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.cc138
1 files changed, 69 insertions, 69 deletions
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index 8d7da67f5204..f4cb672cdeb9 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -1,5 +1,5 @@
+#include "derivations.hh"
 #include "globals.hh"
-#include "misc.hh"
 #include "local-store.hh"
 
 #include <functional>
@@ -83,7 +83,7 @@ void LocalStore::addIndirectRoot(const Path & path)
 }
 
 
-Path addPermRoot(StoreAPI & store, const Path & _storePath,
+Path Store::addPermRoot(const Path & _storePath,
     const Path & _gcRoot, bool indirect, bool allowOutsideRootsDir)
 {
     Path storePath(canonPath(_storePath));
@@ -101,7 +101,7 @@ Path addPermRoot(StoreAPI & store, const Path & _storePath,
         if (pathExists(gcRoot) && (!isLink(gcRoot) || !isInStore(readLink(gcRoot))))
             throw Error(format("cannot create symlink ‘%1%’; already exists") % gcRoot);
         makeSymlink(gcRoot, storePath);
-        store.addIndirectRoot(gcRoot);
+        addIndirectRoot(gcRoot);
     }
 
     else {
@@ -127,7 +127,7 @@ Path addPermRoot(StoreAPI & store, const Path & _storePath,
        check if the root is in a directory in or linked from the
        gcroots directory. */
     if (settings.checkRootReachability) {
-        Roots roots = store.findRoots();
+        Roots roots = findRoots();
         if (roots.find(gcRoot) == roots.end())
             printMsg(lvlError,
                 format(
@@ -139,7 +139,7 @@ Path addPermRoot(StoreAPI & store, const Path & _storePath,
     /* Grab the global GC root, causing us to block while a GC is in
        progress.  This prevents the set of permanent roots from
        increasing while a GC is in progress. */
-    store.syncWithGC();
+    syncWithGC();
 
     return gcRoot;
 }
@@ -147,35 +147,36 @@ Path addPermRoot(StoreAPI & store, const Path & _storePath,
 
 void LocalStore::addTempRoot(const Path & path)
 {
+    auto state(_state.lock());
+
     /* Create the temporary roots file for this process. */
-    if (fdTempRoots == -1) {
+    if (state->fdTempRoots == -1) {
 
         while (1) {
             Path dir = (format("%1%/%2%") % settings.nixStateDir % tempRootsDir).str();
             createDirs(dir);
 
-            fnTempRoots = (format("%1%/%2%")
-                % dir % getpid()).str();
+            state->fnTempRoots = (format("%1%/%2%") % dir % getpid()).str();
 
             AutoCloseFD fdGCLock = openGCLock(ltRead);
 
-            if (pathExists(fnTempRoots))
+            if (pathExists(state->fnTempRoots))
                 /* It *must* be stale, since there can be no two
                    processes with the same pid. */
-                unlink(fnTempRoots.c_str());
+                unlink(state->fnTempRoots.c_str());
 
-            fdTempRoots = openLockFile(fnTempRoots, true);
+            state->fdTempRoots = openLockFile(state->fnTempRoots, true);
 
             fdGCLock.close();
 
-            debug(format("acquiring read lock on ‘%1%’") % fnTempRoots);
-            lockFile(fdTempRoots, ltRead, true);
+            debug(format("acquiring read lock on ‘%1%’") % state->fnTempRoots);
+            lockFile(state->fdTempRoots, ltRead, true);
 
             /* Check whether the garbage collector didn't get in our
                way. */
             struct stat st;
-            if (fstat(fdTempRoots, &st) == -1)
-                throw SysError(format("statting ‘%1%’") % fnTempRoots);
+            if (fstat(state->fdTempRoots, &st) == -1)
+                throw SysError(format("statting ‘%1%’") % state->fnTempRoots);
             if (st.st_size == 0) break;
 
             /* The garbage collector deleted this file before we could
@@ -187,15 +188,15 @@ void LocalStore::addTempRoot(const Path & path)
 
     /* Upgrade the lock to a write lock.  This will cause us to block
        if the garbage collector is holding our lock. */
-    debug(format("acquiring write lock on ‘%1%’") % fnTempRoots);
-    lockFile(fdTempRoots, ltWrite, true);
+    debug(format("acquiring write lock on ‘%1%’") % state->fnTempRoots);
+    lockFile(state->fdTempRoots, ltWrite, true);
 
     string s = path + '\0';
-    writeFull(fdTempRoots, s);
+    writeFull(state->fdTempRoots, s);
 
     /* Downgrade to a read lock. */
-    debug(format("downgrading to read lock on ‘%1%’") % fnTempRoots);
-    lockFile(fdTempRoots, ltRead, true);
+    debug(format("downgrading to read lock on ‘%1%’") % state->fnTempRoots);
+    lockFile(state->fdTempRoots, ltRead, true);
 }
 
 
@@ -260,19 +261,16 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds)
 }
 
 
-static void foundRoot(StoreAPI & store,
-    const Path & path, const Path & target, Roots & roots)
+void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
 {
-    Path storePath = toStorePath(target);
-    if (store.isValidPath(storePath))
-        roots[path] = storePath;
-    else
-        printMsg(lvlInfo, format("skipping invalid root from ‘%1%’ to ‘%2%’") % path % storePath);
-}
-
+    auto foundRoot = [&](const Path & path, const Path & target) {
+        Path storePath = toStorePath(target);
+        if (isStorePath(storePath) && isValidPath(storePath))
+            roots[path] = storePath;
+        else
+            printMsg(lvlInfo, format("skipping invalid root from ‘%1%’ to ‘%2%’") % path % storePath);
+    };
 
-static void findRoots(StoreAPI & store, const Path & path, unsigned char type, Roots & roots)
-{
     try {
 
         if (type == DT_UNKNOWN)
@@ -280,13 +278,13 @@ static void findRoots(StoreAPI & store, const Path & path, unsigned char type, R
 
         if (type == DT_DIR) {
             for (auto & i : readDirectory(path))
-                findRoots(store, path + "/" + i.name, i.type, roots);
+                findRoots(path + "/" + i.name, i.type, roots);
         }
 
         else if (type == DT_LNK) {
             Path target = readLink(path);
             if (isInStore(target))
-                foundRoot(store, path, target, roots);
+                foundRoot(path, target);
 
             /* Handle indirect roots. */
             else {
@@ -300,14 +298,14 @@ static void findRoots(StoreAPI & store, const Path & path, unsigned char type, R
                     struct stat st2 = lstat(target);
                     if (!S_ISLNK(st2.st_mode)) return;
                     Path target2 = readLink(target);
-                    if (isInStore(target2)) foundRoot(store, target, target2, roots);
+                    if (isInStore(target2)) foundRoot(target, target2);
                 }
             }
         }
 
         else if (type == DT_REG) {
             Path storePath = settings.nixStore + "/" + baseNameOf(path);
-            if (store.isValidPath(storePath))
+            if (isStorePath(storePath) && isValidPath(storePath))
                 roots[path] = storePath;
         }
 
@@ -328,16 +326,16 @@ Roots LocalStore::findRoots()
     Roots roots;
 
     /* Process direct roots in {gcroots,manifests,profiles}. */
-    nix::findRoots(*this, settings.nixStateDir + "/" + gcRootsDir, DT_UNKNOWN, roots);
+    findRoots(settings.nixStateDir + "/" + gcRootsDir, DT_UNKNOWN, roots);
     if (pathExists(settings.nixStateDir + "/manifests"))
-        nix::findRoots(*this, settings.nixStateDir + "/manifests", DT_UNKNOWN, roots);
-    nix::findRoots(*this, settings.nixStateDir + "/profiles", DT_UNKNOWN, roots);
+        findRoots(settings.nixStateDir + "/manifests", DT_UNKNOWN, roots);
+    findRoots(settings.nixStateDir + "/profiles", DT_UNKNOWN, roots);
 
     return roots;
 }
 
 
-static void addAdditionalRoots(StoreAPI & store, PathSet & roots)
+void LocalStore::findRuntimeRoots(PathSet & roots)
 {
     Path rootFinder = getEnv("NIX_ROOT_FINDER",
         settings.nixLibexecDir + "/nix/find-runtime-roots.pl");
@@ -350,15 +348,14 @@ static void addAdditionalRoots(StoreAPI & store, PathSet & roots)
 
     StringSet paths = tokenizeString<StringSet>(result, "\n");
 
-    foreach (StringSet::iterator, i, paths) {
-        if (isInStore(*i)) {
-            Path path = toStorePath(*i);
-            if (roots.find(path) == roots.end() && store.isValidPath(path)) {
+    for (auto & i : paths)
+        if (isInStore(i)) {
+            Path path = toStorePath(i);
+            if (roots.find(path) == roots.end() && isStorePath(path) && isValidPath(path)) {
                 debug(format("got additional root ‘%1%’") % path);
                 roots.insert(path);
             }
         }
-    }
 }
 
 
@@ -405,12 +402,12 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path)
 
     unsigned long long size = 0;
 
-    if (isValidPath(path)) {
+    if (isStorePath(path) && isValidPath(path)) {
         PathSet referrers;
         queryReferrers(path, referrers);
-        foreach (PathSet::iterator, i, referrers)
-            if (*i != path) deletePathRecursive(state, *i);
-        size = queryPathInfo(path).narSize;
+        for (auto & i : referrers)
+            if (i != path) deletePathRecursive(state, i);
+        size = queryPathInfo(path)->narSize;
         invalidatePathChecked(path);
     }
 
@@ -476,7 +473,7 @@ bool LocalStore::canReachRoot(GCState & state, PathSet & visited, const Path & p
 
     visited.insert(path);
 
-    if (!isValidPath(path)) return false;
+    if (!isStorePath(path) || !isValidPath(path)) return false;
 
     PathSet incoming;
 
@@ -487,22 +484,22 @@ bool LocalStore::canReachRoot(GCState & state, PathSet & visited, const Path & p
        don't delete the derivation if any of the outputs are alive. */
     if (state.gcKeepDerivations && isDerivation(path)) {
         PathSet outputs = queryDerivationOutputs(path);
-        foreach (PathSet::iterator, i, outputs)
-            if (isValidPath(*i) && queryDeriver(*i) == path)
-                incoming.insert(*i);
+        for (auto & i : outputs)
+            if (isValidPath(i) && queryPathInfo(i)->deriver == path)
+                incoming.insert(i);
     }
 
     /* If gc-keep-outputs is set, then don't delete this path if there
        are derivers of this path that are not garbage. */
     if (state.gcKeepOutputs) {
         PathSet derivers = queryValidDerivers(path);
-        foreach (PathSet::iterator, i, derivers)
-            incoming.insert(*i);
+        for (auto & i : derivers)
+            incoming.insert(i);
     }
 
-    foreach (PathSet::iterator, i, incoming)
-        if (*i != path)
-            if (canReachRoot(state, visited, *i)) {
+    for (auto & i : incoming)
+        if (i != path)
+            if (canReachRoot(state, visited, i)) {
                 state.alive.insert(path);
                 return true;
             }
@@ -517,9 +514,9 @@ void LocalStore::tryToDelete(GCState & state, const Path & path)
 
     if (path == linksDir || path == state.trashDir) return;
 
-    startNest(nest, lvlDebug, format("considering whether to delete ‘%1%’") % path);
+    Activity act(*logger, lvlDebug, format("considering whether to delete ‘%1%’") % path);
 
-    if (!isValidPath(path)) {
+    if (!isStorePath(path) || !isValidPath(path)) {
         /* A lock file belonging to a path that we're building right
            now isn't garbage. */
         if (isActiveTempFile(state, path, ".lock")) return;
@@ -612,6 +609,9 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
 
     state.shouldDelete = options.action == GCOptions::gcDeleteDead || options.action == GCOptions::gcDeleteSpecific;
 
+    if (state.shouldDelete)
+        deletePath(reservedPath);
+
     /* Acquire the global GC root.  This prevents
        a) New roots from being added.
        b) Processes from creating new temporary root files. */
@@ -622,14 +622,14 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
     printMsg(lvlError, format("finding garbage collector roots..."));
     Roots rootMap = options.ignoreLiveness ? Roots() : findRoots();
 
-    foreach (Roots::iterator, i, rootMap) state.roots.insert(i->second);
+    for (auto & i : rootMap) state.roots.insert(i.second);
 
     /* Add additional roots returned by the program specified by the
        NIX_ROOT_FINDER environment variable.  This is typically used
        to add running programs to the set of roots (to prevent them
        from being garbage collected). */
     if (!options.ignoreLiveness)
-        addAdditionalRoots(*this, state.roots);
+        findRuntimeRoots(state.roots);
 
     /* Read the temporary roots.  This acquires read locks on all
        per-process temporary root files.  So after this point no paths
@@ -659,11 +659,11 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
 
     if (options.action == GCOptions::gcDeleteSpecific) {
 
-        foreach (PathSet::iterator, i, options.pathsToDelete) {
-            assertStorePath(*i);
-            tryToDelete(state, *i);
-            if (state.dead.find(*i) == state.dead.end())
-                throw Error(format("cannot delete path ‘%1%’ since it is still alive") % *i);
+        for (auto & i : options.pathsToDelete) {
+            assertStorePath(i);
+            tryToDelete(state, i);
+            if (state.dead.find(i) == state.dead.end())
+                throw Error(format("cannot delete path ‘%1%’ since it is still alive") % i);
         }
 
     } else if (options.maxFreed > 0) {
@@ -691,7 +691,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
                 string name = dirent->d_name;
                 if (name == "." || name == "..") continue;
                 Path path = settings.nixStore + "/" + name;
-                if (isValidPath(path))
+                if (isStorePath(path) && isValidPath(path))
                     entries.push_back(path);
                 else
                     tryToDelete(state, path);
@@ -707,8 +707,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
             vector<Path> entries_(entries.begin(), entries.end());
             random_shuffle(entries_.begin(), entries_.end());
 
-            foreach (vector<Path>::iterator, i, entries_)
-                tryToDelete(state, *i);
+            for (auto & i : entries_)
+                tryToDelete(state, i);
 
         } catch (GCLimitReached & e) {
         }