about summary refs log tree commit diff
path: root/src/libstore/store-api.cc
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2016-10-07T17·43+0200
committerEelco Dolstra <edolstra@gmail.com>2016-10-07T17·43+0200
commit844219f36450e94268da3f60e93efdf67055355c (patch)
tree7ea4421730697cf9118c7525c62498b0080e316e /src/libstore/store-api.cc
parentc663b84573edee2c5ece78f4ee269be73ac3ca35 (diff)
Store::queryValidPaths(): Use async queryPathInfo()
This allows the binary cache substituter to pipeline requests.
Diffstat (limited to 'src/libstore/store-api.cc')
-rw-r--r--src/libstore/store-api.cc43
1 files changed, 39 insertions, 4 deletions
diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc
index a830ae5bbd..b6ac1c3b98 100644
--- a/src/libstore/store-api.cc
+++ b/src/libstore/store-api.cc
@@ -363,12 +363,47 @@ void Store::queryPathInfo(const Path & storePath,
 
 PathSet Store::queryValidPaths(const PathSet & paths)
 {
-    PathSet valid;
+    struct State
+    {
+        size_t left;
+        PathSet valid;
+        std::exception_ptr exc;
+    };
 
-    for (auto & path : paths)
-        if (isValidPath(path)) valid.insert(path);
+    Sync<State> state_(State{paths.size(), PathSet()});
 
-    return valid;
+    std::condition_variable wakeup;
+
+    for (auto & path : paths)
+        queryPathInfo(path,
+            [path, &state_, &wakeup](ref<ValidPathInfo> info) {
+                auto state(state_.lock());
+                state->valid.insert(path);
+                assert(state->left);
+                if (!--state->left)
+                    wakeup.notify_one();
+            },
+            [path, &state_, &wakeup](std::exception_ptr exc) {
+                auto state(state_.lock());
+                try {
+                    std::rethrow_exception(exc);
+                } catch (InvalidPath &) {
+                } catch (...) {
+                    state->exc = exc;
+                }
+                assert(state->left);
+                if (!--state->left)
+                    wakeup.notify_one();
+            });
+
+    while (true) {
+        auto state(state_.lock());
+        if (!state->left) {
+            if (state->exc) std::rethrow_exception(state->exc);
+            return state->valid;
+        }
+        state.wait(wakeup);
+    }
 }