about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/misc.cc75
1 files changed, 48 insertions, 27 deletions
diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc
index 4bb043aaf17e..2e0774f7e99c 100644
--- a/src/libstore/misc.cc
+++ b/src/libstore/misc.cc
@@ -2,6 +2,7 @@
 #include "globals.hh"
 #include "local-store.hh"
 #include "store-api.hh"
+#include "thread-pool.hh"
 
 
 namespace nix {
@@ -10,43 +11,63 @@ namespace nix {
 void Store::computeFSClosure(const Path & path,
     PathSet & paths, bool flipDirection, bool includeOutputs, bool includeDerivers)
 {
-    if (paths.find(path) != paths.end()) return;
-    paths.insert(path);
+    ThreadPool pool;
 
-    PathSet edges;
+    Sync<bool> state_;
 
-    if (flipDirection) {
-        queryReferrers(path, edges);
+    std::function<void(Path)> doPath;
 
-        if (includeOutputs) {
-            PathSet derivers = queryValidDerivers(path);
-            for (auto & i : derivers)
-                edges.insert(i);
+    doPath = [&](const Path & path) {
+        {
+            auto state(state_.lock());
+            if (paths.count(path)) return;
+            paths.insert(path);
         }
 
-        if (includeDerivers && isDerivation(path)) {
-            PathSet outputs = queryDerivationOutputs(path);
-            for (auto & i : outputs)
-                if (isValidPath(i) && queryPathInfo(i)->deriver == path)
-                    edges.insert(i);
-        }
-
-    } else {
         auto info = queryPathInfo(path);
-        edges = info->references;
 
-        if (includeOutputs && isDerivation(path)) {
-            PathSet outputs = queryDerivationOutputs(path);
-            for (auto & i : outputs)
-                if (isValidPath(i)) edges.insert(i);
+        if (flipDirection) {
+
+            PathSet referrers;
+            queryReferrers(path, referrers);
+            for (auto & ref : referrers)
+                if (ref != path)
+                    pool.enqueue(std::bind(doPath, ref));
+
+            if (includeOutputs) {
+                PathSet derivers = queryValidDerivers(path);
+                for (auto & i : derivers)
+                    pool.enqueue(std::bind(doPath, i));
+            }
+
+            if (includeDerivers && isDerivation(path)) {
+                PathSet outputs = queryDerivationOutputs(path);
+                for (auto & i : outputs)
+                    if (isValidPath(i) && queryPathInfo(i)->deriver == path)
+                        pool.enqueue(std::bind(doPath, i));
+            }
+
+        } else {
+
+            for (auto & ref : info->references)
+                if (ref != path)
+                    pool.enqueue(std::bind(doPath, ref));
+
+            if (includeOutputs && isDerivation(path)) {
+                PathSet outputs = queryDerivationOutputs(path);
+                for (auto & i : outputs)
+                    if (isValidPath(i)) pool.enqueue(std::bind(doPath, i));
+            }
+
+            if (includeDerivers && isValidPath(info->deriver))
+                pool.enqueue(std::bind(doPath, info->deriver));
+
         }
+    };
 
-        if (includeDerivers && isValidPath(info->deriver))
-            edges.insert(info->deriver);
-    }
+    pool.enqueue(std::bind(doPath, path));
 
-    for (auto & i : edges)
-        computeFSClosure(i, paths, flipDirection, includeOutputs, includeDerivers);
+    pool.process();
 }