libstore: asyncify Store::queryPathInfo{,Uncached}

Change-Id: I182c396ec0bfdfc8febd6752774e668b3d97dcc1
This commit is contained in:
eldritch horrors
2025-03-05 18:49:45 +01:00
parent 09727e15c5
commit 81d5528646
34 changed files with 290 additions and 217 deletions
+2 -1
View File
@@ -1,5 +1,6 @@
#include "dotgraph.hh" #include "dotgraph.hh"
#include "lix/libstore/store-api.hh" #include "lix/libstore/store-api.hh"
#include "lix/libutil/async.hh"
#include "lix/libutil/result.hh" #include "lix/libutil/result.hh"
#include <iostream> #include <iostream>
@@ -56,7 +57,7 @@ try {
cout << makeNode(std::string(path.to_string()), path.name(), "#ff0000"); cout << makeNode(std::string(path.to_string()), path.name(), "#ff0000");
for (auto & p : store->queryPathInfo(path)->references) { for (auto & p : TRY_AWAIT(store->queryPathInfo(path))->references) {
if (p != path) { if (p != path) {
workList.insert(p); workList.insert(p);
cout << makeEdge(std::string(p.to_string()), std::string(path.to_string())); cout << makeEdge(std::string(p.to_string()), std::string(path.to_string()));
+2 -1
View File
@@ -1,6 +1,7 @@
#include "graphml.hh" #include "graphml.hh"
#include "lix/libstore/store-api.hh" #include "lix/libstore/store-api.hh"
#include "lix/libstore/derivations.hh" #include "lix/libstore/derivations.hh"
#include "lix/libutil/async.hh"
#include "lix/libutil/result.hh" #include "lix/libutil/result.hh"
#include <iostream> #include <iostream>
@@ -68,7 +69,7 @@ try {
ret = doneSet.insert(path); ret = doneSet.insert(path);
if (ret.second == false) continue; if (ret.second == false) continue;
auto info = store->queryPathInfo(path); auto info = TRY_AWAIT(store->queryPathInfo(path));
cout << makeNode(*info); cout << makeNode(*info);
for (auto & p : info->references) { for (auto & p : info->references) {
+14 -12
View File
@@ -51,13 +51,15 @@ ref<LocalStore> ensureLocalStore()
} }
static StorePath useDeriver(const StorePath & path) static kj::Promise<Result<StorePath>> useDeriver(const StorePath & path)
{ try {
if (path.isDerivation()) return path; if (path.isDerivation()) co_return path;
auto info = store->queryPathInfo(path); auto info = TRY_AWAIT(store->queryPathInfo(path));
if (!info->deriver) if (!info->deriver)
throw Error("deriver of path '%s' is not known", store->printStorePath(path)); throw Error("deriver of path '%s' is not known", store->printStorePath(path));
return *info->deriver; co_return *info->deriver;
} catch (...) {
co_return result::current_exception();
} }
@@ -278,7 +280,7 @@ static void printTree(AsyncIoRoot & aio, const StorePath & path,
cout << fmt("%s%s\n", firstPad, store->printStorePath(path)); cout << fmt("%s%s\n", firstPad, store->printStorePath(path));
auto info = store->queryPathInfo(path); auto info = aio.blockOn(store->queryPathInfo(path));
/* Topologically sort under the relation A < B iff A \in /* Topologically sort under the relation A < B iff A \in
closure(B). That is, if derivation A is an (possibly indirect) closure(B). That is, if derivation A is an (possibly indirect)
@@ -368,7 +370,7 @@ static void opQuery(AsyncIoRoot & aio, Strings opFlags, Strings opArgs)
aio.blockOn(store->computeFSClosure(j, paths, false, includeOutputs)); aio.blockOn(store->computeFSClosure(j, paths, false, includeOutputs));
} }
else if (query == qReferences) { else if (query == qReferences) {
for (auto & p : store->queryPathInfo(j)->references) for (auto & p : aio.blockOn(store->queryPathInfo(j))->references)
paths.insert(p); paths.insert(p);
} }
else if (query == qReferrers) { else if (query == qReferrers) {
@@ -390,7 +392,7 @@ static void opQuery(AsyncIoRoot & aio, Strings opFlags, Strings opArgs)
case qDeriver: case qDeriver:
for (auto & i : opArgs) { for (auto & i : opArgs) {
auto info = store->queryPathInfo(store->followLinksToStorePath(i)); auto info = aio.blockOn(store->queryPathInfo(store->followLinksToStorePath(i)));
cout << fmt("%s\n", info->deriver ? store->printStorePath(*info->deriver) : "unknown-deriver"); cout << fmt("%s\n", info->deriver ? store->printStorePath(*info->deriver) : "unknown-deriver");
} }
break; break;
@@ -413,7 +415,7 @@ static void opQuery(AsyncIoRoot & aio, Strings opFlags, Strings opArgs)
case qBinding: case qBinding:
for (auto & i : opArgs) { for (auto & i : opArgs) {
auto path = useDeriver(store->followLinksToStorePath(i)); auto path = aio.blockOn(useDeriver(store->followLinksToStorePath(i)));
Derivation drv = aio.blockOn(store->derivationFromPath(path)); Derivation drv = aio.blockOn(store->derivationFromPath(path));
StringPairs::iterator j = drv.env.find(bindingName); StringPairs::iterator j = drv.env.find(bindingName);
if (j == drv.env.end()) if (j == drv.env.end())
@@ -427,7 +429,7 @@ static void opQuery(AsyncIoRoot & aio, Strings opFlags, Strings opArgs)
case qSize: case qSize:
for (auto & i : opArgs) { for (auto & i : opArgs) {
for (auto & j : aio.blockOn(maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise))) { for (auto & j : aio.blockOn(maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise))) {
auto info = store->queryPathInfo(j); auto info = aio.blockOn(store->queryPathInfo(j));
if (query == qHash) { if (query == qHash) {
assert(info->narHash.type == HashType::SHA256); assert(info->narHash.type == HashType::SHA256);
cout << fmt("%s\n", info->narHash.to_string(Base::Base32, true)); cout << fmt("%s\n", info->narHash.to_string(Base::Base32, true));
@@ -789,7 +791,7 @@ static void opVerifyPath(AsyncIoRoot & aio, Strings opFlags, Strings opArgs)
for (auto & i : opArgs) { for (auto & i : opArgs) {
auto path = store->followLinksToStorePath(i); auto path = store->followLinksToStorePath(i);
printMsg(lvlTalkative, "checking path '%s'...", store->printStorePath(path)); printMsg(lvlTalkative, "checking path '%s'...", store->printStorePath(path));
auto info = store->queryPathInfo(path); auto info = aio.blockOn(store->queryPathInfo(path));
HashSink sink(info->narHash.type); HashSink sink(info->narHash.type);
aio.blockOn(store->narFromPath(path))->drainInto(sink); aio.blockOn(store->narFromPath(path))->drainInto(sink);
auto current = sink.finish(); auto current = sink.finish();
@@ -917,7 +919,7 @@ static void opServe(AsyncIoRoot & aio, Strings opFlags, Strings opArgs)
// !!! Maybe we want a queryPathInfos? // !!! Maybe we want a queryPathInfos?
for (auto & i : paths) { for (auto & i : paths) {
try { try {
auto info = store->queryPathInfo(i); auto info = aio.blockOn(store->queryPathInfo(i));
out << store->printStorePath(info->path); out << store->printStorePath(info->path);
out << ServeProto::write(*store, wconn, static_cast<const UnkeyedValidPathInfo &>(*info)); out << ServeProto::write(*store, wconn, static_cast<const UnkeyedValidPathInfo &>(*info));
} catch (InvalidPath &) { } catch (InvalidPath &) {
+6 -2
View File
@@ -1284,7 +1284,11 @@ static void prim_readFile(EvalState & state, const PosIdx pos, Value * * args, V
StorePathSet refs; StorePathSet refs;
if (state.ctx.store->isInStore(path.canonical().abs())) { if (state.ctx.store->isInStore(path.canonical().abs())) {
try { try {
refs = state.ctx.store->queryPathInfo(state.ctx.store->toStorePath(path.canonical().abs()).first)->references; refs = state.aio
.blockOn(state.ctx.store->queryPathInfo(
state.ctx.store->toStorePath(path.canonical().abs()).first
))
->references;
} catch (Error &) { // FIXME: should be InvalidPathError } catch (Error &) { // FIXME: should be InvalidPathError
} }
// Re-scan references to filter down to just the ones that actually occur in the file. // Re-scan references to filter down to just the ones that actually occur in the file.
@@ -1530,7 +1534,7 @@ static void addPath(
try { try {
auto [storePath, subPath] = state.ctx.store->toStorePath(path); auto [storePath, subPath] = state.ctx.store->toStorePath(path);
// FIXME: we should scanForReferences on the path before adding it // FIXME: we should scanForReferences on the path before adding it
refs = state.ctx.store->queryPathInfo(storePath)->references; refs = state.aio.blockOn(state.ctx.store->queryPathInfo(storePath))->references;
realPath = state.ctx.store->toRealPath(path); realPath = state.ctx.store->toRealPath(path);
} catch (Error &) { // FIXME: should be InvalidPathError } catch (Error &) { // FIXME: should be InvalidPathError
} }
+3 -3
View File
@@ -46,7 +46,7 @@ static void runFetchClosureWithRewrite(EvalState & state, const PosIdx pos, Stor
// check and return // check and return
auto resultInfo = state.ctx.store->queryPathInfo(toPath); auto resultInfo = state.aio.blockOn(state.ctx.store->queryPathInfo(toPath));
if (!resultInfo->isContentAddressed(*state.ctx.store)) { if (!resultInfo->isContentAddressed(*state.ctx.store)) {
// We don't perform the rewriting when outPath already exists, as an optimisation. // We don't perform the rewriting when outPath already exists, as an optimisation.
@@ -71,7 +71,7 @@ static void runFetchClosureWithContentAddressedPath(EvalState & state, const Pos
if (!state.aio.blockOn(state.ctx.store->isValidPath(fromPath))) if (!state.aio.blockOn(state.ctx.store->isValidPath(fromPath)))
state.aio.blockOn(copyClosure(fromStore, *state.ctx.store, RealisedPath::Set { fromPath })); state.aio.blockOn(copyClosure(fromStore, *state.ctx.store, RealisedPath::Set { fromPath }));
auto info = state.ctx.store->queryPathInfo(fromPath); auto info = state.aio.blockOn(state.ctx.store->queryPathInfo(fromPath));
if (!info->isContentAddressed(*state.ctx.store)) { if (!info->isContentAddressed(*state.ctx.store)) {
throw Error({ throw Error({
@@ -97,7 +97,7 @@ static void runFetchClosureWithInputAddressedPath(EvalState & state, const PosId
if (!state.aio.blockOn(state.ctx.store->isValidPath(fromPath))) if (!state.aio.blockOn(state.ctx.store->isValidPath(fromPath)))
state.aio.blockOn(copyClosure(fromStore, *state.ctx.store, RealisedPath::Set { fromPath })); state.aio.blockOn(copyClosure(fromStore, *state.ctx.store, RealisedPath::Set { fromPath }));
auto info = state.ctx.store->queryPathInfo(fromPath); auto info = state.aio.blockOn(state.ctx.store->queryPathInfo(fromPath));
if (info->isContentAddressed(*state.ctx.store)) { if (info->isContentAddressed(*state.ctx.store)) {
throw Error({ throw Error({
+1 -1
View File
@@ -280,7 +280,7 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
if (expectedHash) { if (expectedHash) {
auto hash = unpack auto hash = unpack
? state.ctx.store->queryPathInfo(storePath)->narHash ? state.aio.blockOn(state.ctx.store->queryPathInfo(storePath))->narHash
: hashFile(HashType::SHA256, state.ctx.store->toRealPath(storePath)); : hashFile(HashType::SHA256, state.ctx.store->toRealPath(storePath));
if (hash != *expectedHash) { if (hash != *expectedHash) {
state.ctx.errors.make<EvalError>( state.ctx.errors.make<EvalError>(
+1 -1
View File
@@ -176,7 +176,7 @@ try {
.storePath = storePath, .storePath = storePath,
}; };
auto narHash = store->queryPathInfo(tree.storePath)->narHash; auto narHash = TRY_AWAIT(store->queryPathInfo(tree.storePath))->narHash;
input.attrs.insert_or_assign("narHash", narHash.to_string(Base::SRI, true)); input.attrs.insert_or_assign("narHash", narHash.to_string(Base::SRI, true));
if (auto prevNarHash = getNarHash()) { if (auto prevNarHash = getNarHash()) {
+12 -8
View File
@@ -166,7 +166,7 @@ try {
for (auto & ref : info.references) for (auto & ref : info.references)
try { try {
if (ref != info.path) if (ref != info.path)
queryPathInfo(ref); TRY_AWAIT(queryPathInfo(ref));
} catch (InvalidPath &) { } catch (InvalidPath &) {
throw Error("cannot add '%s' to the binary cache because the reference '%s' does not exist", throw Error("cannot add '%s' to the binary cache because the reference '%s' does not exist",
printStorePath(info.path), printStorePath(ref)); printStorePath(info.path), printStorePath(ref));
@@ -343,7 +343,7 @@ BinaryCacheStore::queryPathFromHashPart(const std::string & hashPart)
try { try {
auto pseudoPath = StorePath(hashPart + "-" + MissingName); auto pseudoPath = StorePath(hashPart + "-" + MissingName);
try { try {
auto info = queryPathInfo(pseudoPath); auto info = TRY_AWAIT(queryPathInfo(pseudoPath));
co_return info->path; co_return info->path;
} catch (InvalidPath &) { } catch (InvalidPath &) {
co_return std::nullopt; co_return std::nullopt;
@@ -354,7 +354,7 @@ try {
kj::Promise<Result<box_ptr<Source>>> BinaryCacheStore::narFromPath(const StorePath & storePath) kj::Promise<Result<box_ptr<Source>>> BinaryCacheStore::narFromPath(const StorePath & storePath)
try { try {
auto info = queryPathInfo(storePath).cast<const NarInfo>(); auto info = TRY_AWAIT(queryPathInfo(storePath)).cast<const NarInfo>();
try { try {
auto file = getFile(info->url); auto file = getFile(info->url);
@@ -385,8 +385,9 @@ try {
co_return result::current_exception(); co_return result::current_exception();
} }
std::shared_ptr<const ValidPathInfo> BinaryCacheStore::queryPathInfoUncached(const StorePath & storePath) kj::Promise<Result<std::shared_ptr<const ValidPathInfo>>>
{ BinaryCacheStore::queryPathInfoUncached(const StorePath & storePath)
try {
auto uri = getUri(); auto uri = getUri();
auto storePathS = printStorePath(storePath); auto storePathS = printStorePath(storePath);
auto act = std::make_shared<Activity>(*logger, lvlTalkative, actQueryPathInfo, auto act = std::make_shared<Activity>(*logger, lvlTalkative, actQueryPathInfo,
@@ -397,11 +398,13 @@ std::shared_ptr<const ValidPathInfo> BinaryCacheStore::queryPathInfoUncached(con
auto data = getFileContents(narInfoFile); auto data = getFileContents(narInfoFile);
if (!data) return nullptr; if (!data) co_return result::success(nullptr);
stats.narInfoRead++; stats.narInfoRead++;
return std::make_shared<NarInfo>(*this, *data, narInfoFile); co_return std::make_shared<NarInfo>(*this, *data, narInfoFile);
} catch (...) {
co_return result::current_exception();
} }
static ValidPathInfo makeAddToStoreInfo( static ValidPathInfo makeAddToStoreInfo(
@@ -542,7 +545,8 @@ try {
S3 might return an outdated cached version. */ S3 might return an outdated cached version. */
// downcast: BinaryCacheStore always returns NarInfo from queryPathInfoUncached, making it sound // downcast: BinaryCacheStore always returns NarInfo from queryPathInfoUncached, making it sound
auto narInfo = make_ref<NarInfo>(dynamic_cast<NarInfo const &>(*queryPathInfo(storePath))); auto narInfo =
make_ref<NarInfo>(dynamic_cast<NarInfo const &>(*TRY_AWAIT(queryPathInfo(storePath))));
narInfo->sigs.insert(sigs.begin(), sigs.end()); narInfo->sigs.insert(sigs.begin(), sigs.end());
+2 -1
View File
@@ -111,7 +111,8 @@ public:
kj::Promise<Result<bool>> isValidPathUncached(const StorePath & path) override; kj::Promise<Result<bool>> isValidPathUncached(const StorePath & path) override;
std::shared_ptr<const ValidPathInfo> queryPathInfoUncached(const StorePath & path) override; kj::Promise<Result<std::shared_ptr<const ValidPathInfo>>>
queryPathInfoUncached(const StorePath & path) override;
kj::Promise<Result<std::optional<StorePath>>> kj::Promise<Result<std::optional<StorePath>>>
queryPathFromHashPart(const std::string & hashPart) override; queryPathFromHashPart(const std::string & hashPart) override;
+1 -1
View File
@@ -145,7 +145,7 @@ try {
if (result.exitCode != Goal::ecSuccess) { if (result.exitCode != Goal::ecSuccess) {
/* Since substituting the path didn't work, if we have a valid /* Since substituting the path didn't work, if we have a valid
deriver, then rebuild the deriver. */ deriver, then rebuild the deriver. */
auto info = queryPathInfo(path); auto info = TRY_AWAIT(queryPathInfo(path));
if (info->deriver && TRY_AWAIT(isValidPath(*info->deriver))) { if (info->deriver && TRY_AWAIT(isValidPath(*info->deriver))) {
TRY_AWAIT(processGoals(*this, *this, [&](GoalFactory & gf) { TRY_AWAIT(processGoals(*this, *this, [&](GoalFactory & gf) {
Worker::Targets goals; Worker::Targets goals;
+127 -107
View File
@@ -1050,23 +1050,26 @@ struct RestrictedStore : public virtual IndirectRootStore, public virtual GcStor
co_return result::current_exception(); co_return result::current_exception();
} }
std::shared_ptr<const ValidPathInfo> queryPathInfoUncached(const StorePath & path) override kj::Promise<Result<std::shared_ptr<const ValidPathInfo>>>
{ queryPathInfoUncached(const StorePath & path) override
try {
if (goal.isAllowed(path)) { if (goal.isAllowed(path)) {
try { try {
/* Censor impure information. */ /* Censor impure information. */
auto info = std::make_shared<ValidPathInfo>(*next->queryPathInfo(path)); auto info = std::make_shared<ValidPathInfo>(*TRY_AWAIT(next->queryPathInfo(path)));
info->deriver.reset(); info->deriver.reset();
info->registrationTime = 0; info->registrationTime = 0;
info->ultimate = false; info->ultimate = false;
info->sigs.clear(); info->sigs.clear();
return info; co_return info;
} catch (InvalidPath &) { } catch (InvalidPath &) {
return nullptr; co_return result::success(nullptr);
} }
} else } else
return nullptr; co_return result::success(nullptr);
}; } catch (...) {
co_return result::current_exception();
}
kj::Promise<Result<void>> kj::Promise<Result<void>>
queryReferrers(const StorePath & path, StorePathSet & referrers) override queryReferrers(const StorePath & path, StorePathSet & referrers) override
@@ -2403,7 +2406,7 @@ try {
if (buildMode == bmCheck) { if (buildMode == bmCheck) {
if (!TRY_AWAIT(worker.store.isValidPath(newInfo.path))) continue; if (!TRY_AWAIT(worker.store.isValidPath(newInfo.path))) continue;
ValidPathInfo oldInfo(*worker.store.queryPathInfo(newInfo.path)); ValidPathInfo oldInfo(*TRY_AWAIT(worker.store.queryPathInfo(newInfo.path)));
if (newInfo.narHash != oldInfo.narHash) { if (newInfo.narHash != oldInfo.narHash) {
anyCheckMismatchSeen = true; anyCheckMismatchSeen = true;
if (settings.runDiffHook || settings.keepFailed) { if (settings.runDiffHook || settings.keepFailed) {
@@ -2558,115 +2561,132 @@ try {
/* Compute the closure and closure size of some output. This /* Compute the closure and closure size of some output. This
is slightly tricky because some of its references (namely is slightly tricky because some of its references (namely
other outputs) may not be valid yet. */ other outputs) may not be valid yet. */
auto getClosure = [&](const StorePath & path) // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines)
{ auto getClosure = [&](const StorePath & path
uint64_t closureSize = 0; ) -> kj::Promise<Result<std::pair<StorePathSet, uint64_t>>> {
StorePathSet pathsDone; try {
std::queue<StorePath> pathsLeft; uint64_t closureSize = 0;
pathsLeft.push(path); StorePathSet pathsDone;
std::queue<StorePath> pathsLeft;
pathsLeft.push(path);
while (!pathsLeft.empty()) { while (!pathsLeft.empty()) {
auto path = pathsLeft.front(); auto path = pathsLeft.front();
pathsLeft.pop(); pathsLeft.pop();
if (!pathsDone.insert(path).second) continue; if (!pathsDone.insert(path).second) continue;
auto i = outputsByPath.find(worker.store.printStorePath(path)); auto i = outputsByPath.find(worker.store.printStorePath(path));
if (i != outputsByPath.end()) { if (i != outputsByPath.end()) {
closureSize += i->second.narSize; closureSize += i->second.narSize;
for (auto & ref : i->second.references) for (auto & ref : i->second.references)
pathsLeft.push(ref); pathsLeft.push(ref);
} else { } else {
auto info = worker.store.queryPathInfo(path); auto info = TRY_AWAIT(worker.store.queryPathInfo(path));
closureSize += info->narSize; closureSize += info->narSize;
for (auto & ref : info->references) for (auto & ref : info->references)
pathsLeft.push(ref); pathsLeft.push(ref);
}
} }
}
return std::make_pair(std::move(pathsDone), closureSize); co_return std::make_pair(std::move(pathsDone), closureSize);
} catch (...) {
co_return result::current_exception();
}
}; };
auto applyChecks = [&](const Checks & checks) // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines)
{ auto applyChecks = [&](const Checks & checks) -> kj::Promise<Result<void>> {
if (checks.maxSize && info.narSize > *checks.maxSize) try {
throw BuildError("path '%s' is too large at %d bytes; limit is %d bytes", if (checks.maxSize && info.narSize > *checks.maxSize)
worker.store.printStorePath(info.path), info.narSize, *checks.maxSize); throw BuildError("path '%s' is too large at %d bytes; limit is %d bytes",
worker.store.printStorePath(info.path), info.narSize, *checks.maxSize);
if (checks.maxClosureSize) { if (checks.maxClosureSize) {
uint64_t closureSize = getClosure(info.path).second; uint64_t closureSize = TRY_AWAIT(getClosure(info.path)).second;
if (closureSize > *checks.maxClosureSize) if (closureSize > *checks.maxClosureSize)
throw BuildError("closure of path '%s' is too large at %d bytes; limit is %d bytes", throw BuildError("closure of path '%s' is too large at %d bytes; limit is %d bytes",
worker.store.printStorePath(info.path), closureSize, *checks.maxClosureSize); worker.store.printStorePath(info.path), closureSize, *checks.maxClosureSize);
} }
auto checkRefs = [&](const std::optional<Strings> & value, bool allowed, bool recursive) // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines)
{ auto checkRefs = [&](const std::optional<Strings> & value,
if (!value) return; bool allowed,
bool recursive) -> kj::Promise<Result<void>> {
try {
if (!value) co_return result::success();
/* Parse a list of reference specifiers. Each element must /* Parse a list of reference specifiers. Each element must
either be a store path, or the symbolic name of the output either be a store path, or the symbolic name of the output
of the derivation (such as `out'). */ of the derivation (such as `out'). */
StorePathSet spec; StorePathSet spec;
for (auto & i : *value) { for (auto & i : *value) {
if (worker.store.isStorePath(i)) if (worker.store.isStorePath(i))
spec.insert(worker.store.parseStorePath(i)); spec.insert(worker.store.parseStorePath(i));
else if (auto output = get(newlyBuiltOutputs, i)) else if (auto output = get(newlyBuiltOutputs, i))
spec.insert(output->path); spec.insert(output->path);
else if (auto storePath = get(alreadyRegisteredOutputs, i)) else if (auto storePath = get(alreadyRegisteredOutputs, i))
spec.insert(*storePath); spec.insert(*storePath);
else { else {
std::string outputsListing = concatMapStringsSep( std::string outputsListing = concatMapStringsSep(
", ", ", ",
newlyBuiltOutputs, newlyBuiltOutputs,
[](auto & o) { return o.first; } [](auto & o) { return o.first; }
); );
if (!alreadyRegisteredOutputs.empty()) { if (!alreadyRegisteredOutputs.empty()) {
outputsListing.append(outputsListing.empty() ? "" : ", "); outputsListing.append(outputsListing.empty() ? "" : ", ");
outputsListing.append(concatMapStringsSep( outputsListing.append(concatMapStringsSep(
", ", ", ",
alreadyRegisteredOutputs, alreadyRegisteredOutputs,
[](auto & o) { return o.first; }) [](auto & o) { return o.first; })
); );
}
throw BuildError("derivation '%s' output check for '%s' contains an illegal reference specifier '%s',"
" expected store path or output name (one of [%s])",
worker.store.printStorePath(drvPath), outputName, i, outputsListing);
}
} }
throw BuildError("derivation '%s' output check for '%s' contains an illegal reference specifier '%s',"
" expected store path or output name (one of [%s])", auto used = recursive
worker.store.printStorePath(drvPath), outputName, i, outputsListing); ? TRY_AWAIT(getClosure(info.path)).first
: info.references;
if (recursive && checks.ignoreSelfRefs)
used.erase(info.path);
StorePathSet badPaths;
for (auto & i : used)
if (allowed) {
if (!spec.count(i))
badPaths.insert(i);
} else {
if (spec.count(i))
badPaths.insert(i);
}
if (!badPaths.empty()) {
std::string badPathsStr;
for (auto & i : badPaths) {
badPathsStr += "\n ";
badPathsStr += worker.store.printStorePath(i);
}
throw BuildError("output '%s' is not allowed to refer to the following paths:%s",
worker.store.printStorePath(info.path), badPathsStr);
}
co_return result::success();
} catch (...) {
co_return result::current_exception();
} }
} };
auto used = recursive TRY_AWAIT(checkRefs(checks.allowedReferences, true, false));
? getClosure(info.path).first TRY_AWAIT(checkRefs(checks.allowedRequisites, true, true));
: info.references; TRY_AWAIT(checkRefs(checks.disallowedReferences, false, false));
TRY_AWAIT(checkRefs(checks.disallowedRequisites, false, true));
if (recursive && checks.ignoreSelfRefs) co_return result::success();
used.erase(info.path); } catch (...) {
co_return result::current_exception();
StorePathSet badPaths; }
for (auto & i : used)
if (allowed) {
if (!spec.count(i))
badPaths.insert(i);
} else {
if (spec.count(i))
badPaths.insert(i);
}
if (!badPaths.empty()) {
std::string badPathsStr;
for (auto & i : badPaths) {
badPathsStr += "\n ";
badPathsStr += worker.store.printStorePath(i);
}
throw BuildError("output '%s' is not allowed to refer to the following paths:%s",
worker.store.printStorePath(info.path), badPathsStr);
}
};
checkRefs(checks.allowedReferences, true, false);
checkRefs(checks.allowedRequisites, true, true);
checkRefs(checks.disallowedReferences, false, false);
checkRefs(checks.disallowedRequisites, false, true);
}; };
if (auto structuredAttrs = parsedDrv->getStructuredAttrs()) { if (auto structuredAttrs = parsedDrv->getStructuredAttrs()) {
@@ -2717,7 +2737,7 @@ try {
checks.disallowedReferences = get_("disallowedReferences"); checks.disallowedReferences = get_("disallowedReferences");
checks.disallowedRequisites = get_("disallowedRequisites"); checks.disallowedRequisites = get_("disallowedRequisites");
applyChecks(checks); TRY_AWAIT(applyChecks(checks));
} }
} }
} else { } else {
@@ -2728,7 +2748,7 @@ try {
checks.allowedRequisites = parsedDrv->getStringsAttr("allowedRequisites"); checks.allowedRequisites = parsedDrv->getStringsAttr("allowedRequisites");
checks.disallowedReferences = parsedDrv->getStringsAttr("disallowedReferences"); checks.disallowedReferences = parsedDrv->getStringsAttr("disallowedReferences");
checks.disallowedRequisites = parsedDrv->getStringsAttr("disallowedRequisites"); checks.disallowedRequisites = parsedDrv->getStringsAttr("disallowedRequisites");
applyChecks(checks); TRY_AWAIT(applyChecks(checks));
} }
} }
+1 -2
View File
@@ -109,8 +109,7 @@ try {
do { do {
try { try {
// FIXME: make async info = TRY_AWAIT(sub->queryPathInfo(subPath ? *subPath : storePath));
info = sub->queryPathInfo(subPath ? *subPath : storePath);
break; break;
} catch (InvalidPath &) { } catch (InvalidPath &) {
} catch (SubstituterDisabled &) { } catch (SubstituterDisabled &) {
+2 -1
View File
@@ -1,5 +1,6 @@
#include "build/derivation-goal.hh" #include "build/derivation-goal.hh"
#include "lix/libutil/async-collect.hh" #include "lix/libutil/async-collect.hh"
#include "lix/libutil/async.hh"
#include "lix/libutil/charptr-cast.hh" #include "lix/libutil/charptr-cast.hh"
#include "lix/libstore/build/worker.hh" #include "lix/libstore/build/worker.hh"
#include "lix/libutil/finally.hh" #include "lix/libutil/finally.hh"
@@ -326,7 +327,7 @@ try {
auto i = pathContentsGoodCache.find(path); auto i = pathContentsGoodCache.find(path);
if (i != pathContentsGoodCache.end()) co_return i->second; if (i != pathContentsGoodCache.end()) co_return i->second;
printInfo("checking path '%s'...", store.printStorePath(path)); printInfo("checking path '%s'...", store.printStorePath(path));
auto info = store.queryPathInfo(path); auto info = TRY_AWAIT(store.queryPathInfo(path));
bool res; bool res;
if (!pathExists(store.printStorePath(path))) if (!pathExists(store.printStorePath(path)))
res = false; res = false;
+3 -3
View File
@@ -426,14 +426,14 @@ static void performOp(AsyncIoRoot & aio, TunnelLogger * logger, ref<Store> store
// We could stream this by changing Store // We could stream this by changing Store
std::string contents = source.drain(); std::string contents = source.drain();
auto path = aio.blockOn(store->addTextToStore(name, contents, refs, repair)); auto path = aio.blockOn(store->addTextToStore(name, contents, refs, repair));
return store->queryPathInfo(path); return aio.blockOn(store->queryPathInfo(path));
}, },
[&](const FileIngestionMethod & fim) { [&](const FileIngestionMethod & fim) {
AsyncSourceInputStream stream{source}; AsyncSourceInputStream stream{source};
auto path = aio.blockOn( auto path = aio.blockOn(
store->addToStoreFromDump(stream, name, fim, hashType, repair, refs) store->addToStoreFromDump(stream, name, fim, hashType, repair, refs)
); );
return store->queryPathInfo(path); return aio.blockOn(store->queryPathInfo(path));
}, },
}, contentAddressMethod.raw); }, contentAddressMethod.raw);
}(); }();
@@ -837,7 +837,7 @@ static void performOp(AsyncIoRoot & aio, TunnelLogger * logger, ref<Store> store
std::shared_ptr<const ValidPathInfo> info; std::shared_ptr<const ValidPathInfo> info;
logger->startWork(); logger->startWork();
try { try {
info = store->queryPathInfo(path); info = aio.blockOn(store->queryPathInfo(path));
} catch (InvalidPath &) { } catch (InvalidPath &) {
// The path being invalid isn't fatal here since it will just be // The path being invalid isn't fatal here since it will just be
// sent as not present. // sent as not present.
+3 -2
View File
@@ -34,9 +34,10 @@ struct DummyStore final : public Store
return *uriSchemes().begin(); return *uriSchemes().begin();
} }
std::shared_ptr<const ValidPathInfo> queryPathInfoUncached(const StorePath & path) override kj::Promise<Result<std::shared_ptr<const ValidPathInfo>>>
queryPathInfoUncached(const StorePath & path) override
{ {
return nullptr; return {result::success(nullptr)};
} }
/** /**
+1 -1
View File
@@ -27,7 +27,7 @@ try {
kj::Promise<Result<void>> Store::exportPath(const StorePath & path, Sink & sink) kj::Promise<Result<void>> Store::exportPath(const StorePath & path, Sink & sink)
try { try {
auto info = queryPathInfo(path); auto info = TRY_AWAIT(queryPathInfo(path));
HashSink hashSink(HashType::SHA256); HashSink hashSink(HashType::SHA256);
TeeSink teeSink(sink, hashSink); TeeSink teeSink(sink, hashSink);
+1 -1
View File
@@ -780,7 +780,7 @@ try {
{ {
if (maybeOutPath && if (maybeOutPath &&
TRY_AWAIT(isValidPath(*maybeOutPath)) && TRY_AWAIT(isValidPath(*maybeOutPath)) &&
queryPathInfo(*maybeOutPath)->deriver == *path) TRY_AWAIT(queryPathInfo(*maybeOutPath))->deriver == *path)
enqueue(*maybeOutPath); enqueue(*maybeOutPath);
} }
} }
+7 -4
View File
@@ -160,8 +160,9 @@ struct LegacySSHStore final : public Store
return *uriSchemes().begin() + "://" + host; return *uriSchemes().begin() + "://" + host;
} }
std::shared_ptr<const ValidPathInfo> queryPathInfoUncached(const StorePath & path) override kj::Promise<Result<std::shared_ptr<const ValidPathInfo>>>
{ queryPathInfoUncached(const StorePath & path) override
try {
auto conn(connections->get()); auto conn(connections->get());
/* No longer support missing NAR hash */ /* No longer support missing NAR hash */
@@ -173,7 +174,7 @@ struct LegacySSHStore final : public Store
conn->to.flush(); conn->to.flush();
auto p = readString(conn->from); auto p = readString(conn->from);
if (p.empty()) return nullptr; if (p.empty()) co_return result::success(nullptr);
auto path2 = parseStorePath(p); auto path2 = parseStorePath(p);
assert(path == path2); assert(path == path2);
auto info = std::make_shared<ValidPathInfo>( auto info = std::make_shared<ValidPathInfo>(
@@ -186,7 +187,9 @@ struct LegacySSHStore final : public Store
auto s = readString(conn->from); auto s = readString(conn->from);
assert(s == ""); assert(s == "");
return info; co_return info;
} catch (...) {
co_return result::current_exception();
} }
kj::Promise<Result<void>> addToStore(const ValidPathInfo & info, AsyncInputStream & source, kj::Promise<Result<void>> addToStore(const ValidPathInfo & info, AsyncInputStream & source,
+19 -7
View File
@@ -916,12 +916,22 @@ try {
} }
std::shared_ptr<const ValidPathInfo> LocalStore::queryPathInfoUncached(const StorePath & path) kj::Promise<Result<std::shared_ptr<const ValidPathInfo>>>
{ LocalStore::queryPathInfoUncached(const StorePath & path)
return retrySQLite([&]() { try {
auto state = dbPool.get(); co_return TRY_AWAIT(
return queryPathInfoInternal(*state, path); // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines)
}, always_progresses); retrySQLite([&]() -> kj::Promise<Result<std::shared_ptr<const ValidPathInfo>>> {
try {
auto state = dbPool.get();
co_return queryPathInfoInternal(*state, path);
} catch (...) {
co_return result::current_exception();
}
})
);
} catch (...) {
co_return result::current_exception();
} }
@@ -1734,7 +1744,9 @@ try {
for (auto & i : validPaths) { for (auto & i : validPaths) {
std::optional<Error> caught; std::optional<Error> caught;
try { try {
auto info = std::const_pointer_cast<ValidPathInfo>(std::shared_ptr<const ValidPathInfo>(queryPathInfo(i))); auto info = std::const_pointer_cast<ValidPathInfo>(
std::shared_ptr<const ValidPathInfo>(TRY_AWAIT(queryPathInfo(i)))
);
/* Check the content hash (optionally - slow). */ /* Check the content hash (optionally - slow). */
printMsg(lvlTalkative, "checking contents of '%s'", printStorePath(i)); printMsg(lvlTalkative, "checking contents of '%s'", printStorePath(i));
+2 -1
View File
@@ -196,7 +196,8 @@ public:
kj::Promise<Result<StorePathSet>> queryAllValidPaths() override; kj::Promise<Result<StorePathSet>> queryAllValidPaths() override;
std::shared_ptr<const ValidPathInfo> queryPathInfoUncached(const StorePath & path) override; kj::Promise<Result<std::shared_ptr<const ValidPathInfo>>>
queryPathInfoUncached(const StorePath & path) override;
kj::Promise<Result<void>> kj::Promise<Result<void>>
queryReferrers(const StorePath & path, StorePathSet & referrers) override; queryReferrers(const StorePath & path, StorePathSet & referrers) override;
+1 -1
View File
@@ -22,7 +22,7 @@ try {
for (auto & path : paths) { for (auto & path : paths) {
auto pathS = srcStore.printStorePath(path); auto pathS = srcStore.printStorePath(path);
auto oldInfo = srcStore.queryPathInfo(path); auto oldInfo = TRY_AWAIT(srcStore.queryPathInfo(path));
std::string oldHashPart(path.hashPart()); std::string oldHashPart(path.hashPart());
StringSink sink; StringSink sink;
+17 -8
View File
@@ -9,6 +9,7 @@
#include "lix/libutil/closure.hh" #include "lix/libutil/closure.hh"
#include "lix/libstore/filetransfer.hh" #include "lix/libstore/filetransfer.hh"
#include "lix/libutil/strings.hh" #include "lix/libutil/strings.hh"
#include <kj/async.h>
#include <kj/common.h> #include <kj/common.h>
namespace nix { namespace nix {
@@ -70,8 +71,13 @@ try {
paths_.merge(TRY_AWAIT(computeClosureAsync<StorePath>( paths_.merge(TRY_AWAIT(computeClosureAsync<StorePath>(
startPaths, startPaths,
[&](const StorePath& path) -> kj::Promise<Result<std::set<StorePath>>> { // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines)
return queryDeps(path, queryPathInfo(path)); [&](const StorePath& path) -> kj::Promise<Result<StorePathSet>> {
try {
co_return TRY_AWAIT(queryDeps(path, TRY_AWAIT(queryPathInfo(path))));
} catch (...) {
co_return result::current_exception();
}
}))); })));
co_return result::success(); co_return result::success();
} catch (...) { } catch (...) {
@@ -369,12 +375,15 @@ try {
kj::Promise<Result<StorePaths>> Store::topoSortPaths(const StorePathSet & paths) kj::Promise<Result<StorePaths>> Store::topoSortPaths(const StorePathSet & paths)
try { try {
co_return topoSort(paths, co_return TRY_AWAIT(topoSortAsync(paths,
{[&](const StorePath & path) { // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines)
{[&](const StorePath & path) -> kj::Promise<Result<StorePathSet>> {
try { try {
return queryPathInfo(path)->references; co_return TRY_AWAIT(queryPathInfo(path))->references;
} catch (InvalidPath &) { } catch (InvalidPath &) {
return StorePathSet(); co_return StorePathSet();
} catch (...) {
co_return result::current_exception();
} }
}}, }},
{[&](const StorePath & path, const StorePath & parent) { {[&](const StorePath & path, const StorePath & parent) {
@@ -382,7 +391,7 @@ try {
"cycle detected in the references of '%s' from '%s'", "cycle detected in the references of '%s' from '%s'",
printStorePath(path), printStorePath(path),
printStorePath(parent)); printStorePath(parent));
}}); }}));
} catch (...) { } catch (...) {
co_return result::current_exception(); co_return result::current_exception();
} }
@@ -461,7 +470,7 @@ try {
for (const auto & [inputDrv, inputNode] : drv.inputDrvs.map) for (const auto & [inputDrv, inputNode] : drv.inputDrvs.map)
TRY_AWAIT(accumRealisations(inputDrv, inputNode)); TRY_AWAIT(accumRealisations(inputDrv, inputNode));
auto info = store.queryPathInfo(outputPath); auto info = TRY_AWAIT(store.queryPathInfo(outputPath));
co_return TRY_AWAIT(drvOutputReferences( co_return TRY_AWAIT(drvOutputReferences(
TRY_AWAIT(Realisation::closure(store, inputRealisations)), info->references TRY_AWAIT(Realisation::closure(store, inputRealisations)), info->references
+9 -6
View File
@@ -286,8 +286,9 @@ try {
} }
std::shared_ptr<const ValidPathInfo> RemoteStore::queryPathInfoUncached(const StorePath & path) kj::Promise<Result<std::shared_ptr<const ValidPathInfo>>>
{ RemoteStore::queryPathInfoUncached(const StorePath & path)
try {
auto conn(getConnection()); auto conn(getConnection());
conn->to << WorkerProto::Op::QueryPathInfo << printStorePath(path); conn->to << WorkerProto::Op::QueryPathInfo << printStorePath(path);
try { try {
@@ -295,16 +296,18 @@ std::shared_ptr<const ValidPathInfo> RemoteStore::queryPathInfoUncached(const St
} catch (Error & e) { } catch (Error & e) {
// Ugly backwards compatibility hack. TODO(fj#325): remove. // Ugly backwards compatibility hack. TODO(fj#325): remove.
if (e.msg().find("is not valid") != std::string::npos) if (e.msg().find("is not valid") != std::string::npos)
return nullptr; co_return result::success(nullptr);
throw; throw;
} }
bool valid; conn->from >> valid; bool valid; conn->from >> valid;
if (!valid) return nullptr; if (!valid) co_return result::success(nullptr);
return std::make_shared<ValidPathInfo>( co_return std::make_shared<ValidPathInfo>(
StorePath{path}, StorePath{path},
WorkerProto::Serialise<UnkeyedValidPathInfo>::read(*this, *conn)); WorkerProto::Serialise<UnkeyedValidPathInfo>::read(*this, *conn));
} catch (...) {
co_return result::current_exception();
} }
@@ -497,7 +500,7 @@ try {
auto path = parseStorePath(readString(conn->from)); auto path = parseStorePath(readString(conn->from));
// Release our connection to prevent a deadlock in queryPathInfo(). // Release our connection to prevent a deadlock in queryPathInfo().
conn_.reset(); conn_.reset();
co_return queryPathInfo(path); co_return TRY_AWAIT(queryPathInfo(path));
} }
} catch (...) { } catch (...) {
co_return result::current_exception(); co_return result::current_exception();
+2 -1
View File
@@ -57,7 +57,8 @@ public:
kj::Promise<Result<StorePathSet>> queryAllValidPaths() override; kj::Promise<Result<StorePathSet>> queryAllValidPaths() override;
std::shared_ptr<const ValidPathInfo> queryPathInfoUncached(const StorePath & path) override; kj::Promise<Result<std::shared_ptr<const ValidPathInfo>>>
queryPathInfoUncached(const StorePath & path) override;
kj::Promise<Result<void>> kj::Promise<Result<void>>
queryReferrers(const StorePath & path, StorePathSet & referrers) override; queryReferrers(const StorePath & path, StorePathSet & referrers) override;
+1 -1
View File
@@ -315,7 +315,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
a GET is unlikely to be slower than HEAD. */ a GET is unlikely to be slower than HEAD. */
kj::Promise<Result<bool>> isValidPathUncached(const StorePath & storePath) override kj::Promise<Result<bool>> isValidPathUncached(const StorePath & storePath) override
try { try {
queryPathInfo(storePath); TRY_AWAIT(queryPathInfo(storePath));
co_return true; co_return true;
} catch (InvalidPath & e) { } catch (InvalidPath & e) {
co_return false; co_return false;
+20 -17
View File
@@ -21,6 +21,7 @@
#include "lix/libstore/worker-protocol.hh" #include "lix/libstore/worker-protocol.hh"
#include "lix/libutil/users.hh" #include "lix/libutil/users.hh"
#include <functional>
#include <kj/async.h> #include <kj/async.h>
#include <mutex> #include <mutex>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
@@ -600,7 +601,7 @@ try {
debug("checking substituter '%s' for path '%s'", sub->getUri(), sub->printStorePath(subPath)); debug("checking substituter '%s' for path '%s'", sub->getUri(), sub->printStorePath(subPath));
try { try {
auto info = sub->queryPathInfo(subPath); auto info = TRY_AWAIT(sub->queryPathInfo(subPath));
if (sub->config().storeDir != config().storeDir if (sub->config().storeDir != config().storeDir
&& !(info->isContentAddressed(*sub) && info->references.empty())) && !(info->isContentAddressed(*sub) && info->references.empty()))
@@ -671,7 +672,7 @@ try {
queryPathInfoUncached(). */ queryPathInfoUncached(). */
kj::Promise<Result<bool>> Store::isValidPathUncached(const StorePath & path) kj::Promise<Result<bool>> Store::isValidPathUncached(const StorePath & path)
try { try {
queryPathInfo(path); TRY_AWAIT(queryPathInfo(path));
co_return true; co_return true;
} catch (InvalidPath &) { } catch (InvalidPath &) {
co_return false; co_return false;
@@ -696,8 +697,8 @@ static void ensureGoodStorePath(Store * store, const StorePath & expected, const
} }
ref<const ValidPathInfo> Store::queryPathInfo(const StorePath & storePath) kj::Promise<Result<ref<const ValidPathInfo>>> Store::queryPathInfo(const StorePath & storePath)
{ try {
auto hashPart = std::string(storePath.hashPart()); auto hashPart = std::string(storePath.hashPart());
{ {
@@ -706,7 +707,7 @@ ref<const ValidPathInfo> Store::queryPathInfo(const StorePath & storePath)
stats.narInfoReadAverted++; stats.narInfoReadAverted++;
if (!res->didExist()) if (!res->didExist())
throw InvalidPath("path '%s' does not exist in the store", printStorePath(storePath)); throw InvalidPath("path '%s' does not exist in the store", printStorePath(storePath));
return ref<const ValidPathInfo>(res->value); co_return ref<const ValidPathInfo>(res->value);
} }
} }
@@ -721,11 +722,11 @@ ref<const ValidPathInfo> Store::queryPathInfo(const StorePath & storePath)
if (res.first == NarInfoDiskCache::oInvalid) if (res.first == NarInfoDiskCache::oInvalid)
throw InvalidPath("path '%s' does not exist in the store", printStorePath(storePath)); throw InvalidPath("path '%s' does not exist in the store", printStorePath(storePath));
} }
return ref<const ValidPathInfo>(res.second); co_return ref<const ValidPathInfo>(res.second);
} }
} }
auto info = queryPathInfoUncached(storePath); auto info = TRY_AWAIT(queryPathInfoUncached(storePath));
if (info) { if (info) {
// first, before we cache anything, check that the store gave us valid data. // first, before we cache anything, check that the store gave us valid data.
ensureGoodStorePath(this, storePath, info->path); ensureGoodStorePath(this, storePath, info->path);
@@ -745,7 +746,9 @@ ref<const ValidPathInfo> Store::queryPathInfo(const StorePath & storePath)
throw InvalidPath("path '%s' does not exist in the store", printStorePath(storePath)); throw InvalidPath("path '%s' does not exist in the store", printStorePath(storePath));
} }
return ref<const ValidPathInfo>(info); co_return ref<const ValidPathInfo>(info);
} catch (...) {
co_return result::current_exception();
} }
kj::Promise<Result<std::shared_ptr<const Realisation>>> Store::queryRealisation(const DrvOutput & id) kj::Promise<Result<std::shared_ptr<const Realisation>>> Store::queryRealisation(const DrvOutput & id)
@@ -823,14 +826,14 @@ try {
std::condition_variable wakeup; std::condition_variable wakeup;
ThreadPool pool{"queryValidPaths pool"}; ThreadPool pool{"queryValidPaths pool"};
auto doQuery = [&](const StorePath & path) { auto doQuery = [&](AsyncIoRoot & aio, const StorePath & path) {
checkInterrupt(); checkInterrupt();
bool exists = false; bool exists = false;
std::exception_ptr newExc{}; std::exception_ptr newExc{};
try { try {
queryPathInfo(path); aio.blockOn(queryPathInfo(path));
exists = true; exists = true;
} catch (InvalidPath &) { } catch (InvalidPath &) {
} catch (...) { } catch (...) {
@@ -853,7 +856,7 @@ try {
}; };
for (auto & path : paths) for (auto & path : paths)
pool.enqueue(std::bind(doQuery, path)); pool.enqueueWithAio(std::bind(doQuery, std::placeholders::_1, path));
TRY_AWAIT(pool.processAsync()); TRY_AWAIT(pool.processAsync());
@@ -881,7 +884,7 @@ try {
for (auto & i : paths) { for (auto & i : paths) {
s += printStorePath(i) + "\n"; s += printStorePath(i) + "\n";
auto info = queryPathInfo(i); auto info = TRY_AWAIT(queryPathInfo(i));
if (showHash) { if (showHash) {
s += info->narHash.to_string(Base::Base16, false) + "\n"; s += info->narHash.to_string(Base::Base16, false) + "\n";
@@ -952,7 +955,7 @@ try {
auto& jsonPath = jsonList.emplace_back(json::object()); auto& jsonPath = jsonList.emplace_back(json::object());
try { try {
auto info = queryPathInfo(storePath); auto info = TRY_AWAIT(queryPathInfo(storePath));
jsonPath["path"] = printStorePath(info->path); jsonPath["path"] = printStorePath(info->path);
jsonPath["valid"] = true; jsonPath["valid"] = true;
@@ -1024,7 +1027,7 @@ try {
StorePathSet closure; StorePathSet closure;
TRY_AWAIT(computeFSClosure(storePath, closure, false, false)); TRY_AWAIT(computeFSClosure(storePath, closure, false, false));
for (auto & p : closure) { for (auto & p : closure) {
auto info = queryPathInfo(p); auto info = TRY_AWAIT(queryPathInfo(p));
totalNarSize += info->narSize; totalNarSize += info->narSize;
auto narInfo = std::dynamic_pointer_cast<const NarInfo>( auto narInfo = std::dynamic_pointer_cast<const NarInfo>(
std::shared_ptr<const ValidPathInfo>(info)); std::shared_ptr<const ValidPathInfo>(info));
@@ -1106,7 +1109,7 @@ try {
{storePathS, srcUri, dstUri}); {storePathS, srcUri, dstUri});
PushActivity pact(act.id); PushActivity pact(act.id);
auto info = srcStore.queryPathInfo(storePath); auto info = TRY_AWAIT(srcStore.queryPathInfo(storePath));
// recompute store path on the chance dstStore does it differently // recompute store path on the chance dstStore does it differently
if (info->ca && info->references.empty()) { if (info->ca && info->references.empty()) {
@@ -1239,7 +1242,7 @@ try {
}; };
for (auto & missingPath : sortedMissing) { for (auto & missingPath : sortedMissing) {
auto info = srcStore.queryPathInfo(missingPath); auto info = TRY_AWAIT(srcStore.queryPathInfo(missingPath));
auto storePathForDst = computeStorePathForDst(*info); auto storePathForDst = computeStorePathForDst(*info);
pathsMap.insert_or_assign(missingPath, storePathForDst); pathsMap.insert_or_assign(missingPath, storePathForDst);
@@ -1411,7 +1414,7 @@ try {
if (!path.isDerivation()) { if (!path.isDerivation()) {
try { try {
auto info = queryPathInfo(path); auto info = TRY_AWAIT(queryPathInfo(path));
co_return info->deriver; co_return info->deriver;
} catch (InvalidPath &) { } catch (InvalidPath &) {
co_return std::nullopt; co_return std::nullopt;
+3 -2
View File
@@ -385,7 +385,7 @@ public:
* Query information about a valid path. It is permitted to omit * Query information about a valid path. It is permitted to omit
* the name part of the store path. * the name part of the store path.
*/ */
ref<const ValidPathInfo> queryPathInfo(const StorePath & path); kj::Promise<Result<ref<const ValidPathInfo>>> queryPathInfo(const StorePath & path);
/** /**
* Query the information about a realisation. * Query the information about a realisation.
@@ -420,7 +420,8 @@ protected:
* Queries the path info without caching. * Queries the path info without caching.
* Note to implementors: should return `nullptr` when the path is not found. * Note to implementors: should return `nullptr` when the path is not found.
*/ */
virtual std::shared_ptr<const ValidPathInfo> queryPathInfoUncached(const StorePath & path) = 0; virtual kj::Promise<Result<std::shared_ptr<const ValidPathInfo>>>
queryPathInfoUncached(const StorePath & path) = 0;
virtual kj::Promise<Result<std::shared_ptr<const Realisation>>> virtual kj::Promise<Result<std::shared_ptr<const Realisation>>>
queryRealisationUncached(const DrvOutput &) = 0; queryRealisationUncached(const DrvOutput &) = 0;
+14 -9
View File
@@ -67,17 +67,22 @@ try {
auto & beforeVersions = beforeClosure[name]; auto & beforeVersions = beforeClosure[name];
auto & afterVersions = afterClosure[name]; auto & afterVersions = afterClosure[name];
auto totalSize = [&](const std::map<std::string, std::map<StorePath, Info>> & versions) // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines)
{ auto totalSize = [&](const std::map<std::string, std::map<StorePath, Info>> & versions
uint64_t sum = 0; ) -> kj::Promise<Result<uint64_t>> {
for (auto & [_, paths] : versions) try {
for (auto & [path, _] : paths) uint64_t sum = 0;
sum += store->queryPathInfo(path)->narSize; for (auto & [_, paths] : versions)
return sum; for (auto & [path, _] : paths)
sum += TRY_AWAIT(store->queryPathInfo(path))->narSize;
co_return sum;
} catch (...) {
co_return result::current_exception();
}
}; };
auto beforeSize = totalSize(beforeVersions); auto beforeSize = TRY_AWAIT(totalSize(beforeVersions));
auto afterSize = totalSize(afterVersions); auto afterSize = TRY_AWAIT(totalSize(afterVersions));
auto sizeDelta = (int64_t) afterSize - (int64_t) beforeSize; auto sizeDelta = (int64_t) afterSize - (int64_t) beforeSize;
auto showDelta = std::abs(sizeDelta) >= 8 * 1024; auto showDelta = std::abs(sizeDelta) >= 8 * 1024;
+1 -1
View File
@@ -1439,7 +1439,7 @@ struct CmdFlakePrefetch : FlakeCommand, MixJSON
auto originalRef = getFlakeRef(); auto originalRef = getFlakeRef();
auto resolvedRef = aio().blockOn(originalRef.resolve(store)); auto resolvedRef = aio().blockOn(originalRef.resolve(store));
auto [tree, lockedRef] = aio().blockOn(resolvedRef.fetchTree(store)); auto [tree, lockedRef] = aio().blockOn(resolvedRef.fetchTree(store));
auto hash = store->queryPathInfo(tree.storePath)->narHash; auto hash = aio().blockOn(store->queryPathInfo(tree.storePath))->narHash;
if (json) { if (json) {
auto res = nlohmann::json::object(); auto res = nlohmann::json::object();
+2 -1
View File
@@ -2,6 +2,7 @@
#include "lix/libmain/shared.hh" #include "lix/libmain/shared.hh"
#include "lix/libstore/store-api.hh" #include "lix/libstore/store-api.hh"
#include "lix/libmain/common-args.hh" #include "lix/libmain/common-args.hh"
#include "lix/libutil/async.hh"
#include <algorithm> #include <algorithm>
#include <array> #include <array>
@@ -100,7 +101,7 @@ struct CmdPathInfo : StorePathsCommand, MixJSON
else { else {
for (auto & storePath : storePaths) { for (auto & storePath : storePaths) {
auto info = store->queryPathInfo(storePath); auto info = aio().blockOn(store->queryPathInfo(storePath));
auto storePathS = store->printStorePath(info->path); auto storePathS = store->printStorePath(info->path);
std::cout << storePathS; std::cout << storePathS;
+3 -3
View File
@@ -50,13 +50,13 @@ struct CmdCopySigs : StorePathsCommand
auto storePath = store->parseStorePath(storePathS); auto storePath = store->parseStorePath(storePathS);
auto info = store->queryPathInfo(storePath); auto info = aio.blockOn(store->queryPathInfo(storePath));
StringSet newSigs; StringSet newSigs;
for (auto & store2 : substituters) { for (auto & store2 : substituters) {
try { try {
auto info2 = store2->queryPathInfo(info->path); auto info2 = aio.blockOn(store2->queryPathInfo(info->path));
/* Don't import signatures that don't match this /* Don't import signatures that don't match this
binary. */ binary. */
@@ -130,7 +130,7 @@ struct CmdSign : StorePathsCommand
auto storePath = store->parseStorePath(storePathS); auto storePath = store->parseStorePath(storePathS);
auto info = store->queryPathInfo(storePath); auto info = aio.blockOn(store->queryPathInfo(storePath));
auto info2(*info); auto info2(*info);
info2.sigs.clear(); info2.sigs.clear();
+2 -2
View File
@@ -90,7 +90,7 @@ struct CmdVerify : StorePathsCommand
MaintainCount<std::atomic<size_t>> mcActive(active); MaintainCount<std::atomic<size_t>> mcActive(active);
update(); update();
auto info = store->queryPathInfo(storePath); auto info = aio.blockOn(store->queryPathInfo(storePath));
// Note: info->path can be different from storePath // Note: info->path can be different from storePath
// for binary cache stores when using --all (since we // for binary cache stores when using --all (since we
@@ -143,7 +143,7 @@ struct CmdVerify : StorePathsCommand
for (auto & store2 : substituters) { for (auto & store2 : substituters) {
if (validSigs >= actualSigsNeeded) break; if (validSigs >= actualSigsNeeded) break;
try { try {
auto info2 = store2->queryPathInfo(info->path); auto info2 = aio.blockOn(store2->queryPathInfo(info->path));
if (info2->isContentAddressed(*store)) validSigs = ValidPathInfo::maxSigs; if (info2->isContentAddressed(*store)) validSigs = ValidPathInfo::maxSigs;
doSigs(info2->sigs); doSigs(info2->sigs);
} catch (InvalidPath &) { } catch (InvalidPath &) {
+1 -1
View File
@@ -132,7 +132,7 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
for (auto & path : closure) for (auto & path : closure)
graph.emplace(path, Node { graph.emplace(path, Node {
.path = path, .path = path,
.refs = store->queryPathInfo(path)->references, .refs = aio().blockOn(store->queryPathInfo(path))->references,
.dist = path == dependencyPath ? 0 : inf .dist = path == dependencyPath ? 0 : inf
}); });
+4 -4
View File
@@ -79,7 +79,7 @@ int isValidPath(char * path)
SV * queryReferences(char * path) SV * queryReferences(char * path)
PPCODE: PPCODE:
try { try {
for (auto & i : store()->queryPathInfo(store()->parseStorePath(path))->references) for (auto & i : aio().blockOn(store()->queryPathInfo(store()->parseStorePath(path)))->references)
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(i).c_str(), 0))); XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(i).c_str(), 0)));
} catch (Error & e) { } catch (Error & e) {
croak("%s", e.what()); croak("%s", e.what());
@@ -89,7 +89,7 @@ SV * queryReferences(char * path)
SV * queryPathHash(char * path) SV * queryPathHash(char * path)
PPCODE: PPCODE:
try { try {
auto s = store()->queryPathInfo(store()->parseStorePath(path))->narHash.to_string(Base::Base32, true); auto s = aio().blockOn(store()->queryPathInfo(store()->parseStorePath(path)))->narHash.to_string(Base::Base32, true);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0))); XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) { } catch (Error & e) {
croak("%s", e.what()); croak("%s", e.what());
@@ -99,7 +99,7 @@ SV * queryPathHash(char * path)
SV * queryDeriver(char * path) SV * queryDeriver(char * path)
PPCODE: PPCODE:
try { try {
auto info = store()->queryPathInfo(store()->parseStorePath(path)); auto info = aio().blockOn(store()->queryPathInfo(store()->parseStorePath(path)));
if (!info->deriver) XSRETURN_UNDEF; if (!info->deriver) XSRETURN_UNDEF;
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(*info->deriver).c_str(), 0))); XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(*info->deriver).c_str(), 0)));
} catch (Error & e) { } catch (Error & e) {
@@ -110,7 +110,7 @@ SV * queryDeriver(char * path)
SV * queryPathInfo(char * path, int base32) SV * queryPathInfo(char * path, int base32)
PPCODE: PPCODE:
try { try {
auto info = store()->queryPathInfo(store()->parseStorePath(path)); auto info = aio().blockOn(store()->queryPathInfo(store()->parseStorePath(path)));
if (!info->deriver) if (!info->deriver)
XPUSHs(&PL_sv_undef); XPUSHs(&PL_sv_undef);
else else