Skip to content

Commit 4d45839

Browse files
committedDec 17, 2020
Fix the detection of already built drv outputs
PRs #4370 and #4348 had a bad interaction in that the second broke the fist one in a not trivial way. The issue was that since #4348 the logic for detecting whether a derivation output is already built requires some logic that was specific to the `LocalStore`. It happens though that most of this logic could be upstreamed to any `Store`, which is what this commit does.
1 parent ae3c3e3 commit 4d45839

File tree

6 files changed

+78
-53
lines changed

6 files changed

+78
-53
lines changed
 

‎src/libstore/derivations.cc

+31-1
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,7 @@ static void rewriteDerivation(Store & store, BasicDerivation & drv, const String
745745

746746
}
747747

748-
std::optional<BasicDerivation> Derivation::tryResolve(Store & store) {
748+
std::optional<BasicDerivation> Derivation::tryResolveUncached(Store & store) {
749749
BasicDerivation resolved { *this };
750750

751751
// Input paths that we'll want to rewrite in the derivation
@@ -771,4 +771,34 @@ std::optional<BasicDerivation> Derivation::tryResolve(Store & store) {
771771
return resolved;
772772
}
773773

774+
std::optional<BasicDerivation> Derivation::tryResolve(Store& store)
775+
{
776+
auto drvPath = writeDerivation(store, *this, NoRepair, false);
777+
return Derivation::tryResolve(store, drvPath);
778+
}
779+
780+
std::optional<BasicDerivation> Derivation::tryResolve(Store& store, const StorePath& drvPath)
781+
{
782+
// This is quite dirty and leaky, but will disappear once #4340 is merged
783+
static Sync<std::map<StorePath, std::optional<Derivation>>> resolutionsCache;
784+
785+
{
786+
auto resolutions = resolutionsCache.lock();
787+
auto resolvedDrvIter = resolutions->find(drvPath);
788+
if (resolvedDrvIter != resolutions->end()) {
789+
auto & [_, resolvedDrv] = *resolvedDrvIter;
790+
return *resolvedDrv;
791+
}
792+
}
793+
794+
/* Try resolve drv and use that path instead. */
795+
auto drv = store.readDerivation(drvPath);
796+
auto attempt = drv.tryResolveUncached(store);
797+
if (!attempt)
798+
return std::nullopt;
799+
/* Store in memo table. */
800+
resolutionsCache.lock()->insert_or_assign(drvPath, *attempt);
801+
return *attempt;
802+
}
803+
774804
}

‎src/libstore/derivations.hh

+4
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,14 @@ struct Derivation : BasicDerivation
138138
139139
2. Input placeholders are replaced with realized input store paths. */
140140
std::optional<BasicDerivation> tryResolve(Store & store);
141+
static std::optional<BasicDerivation> tryResolve(Store & store, const StorePath & drvPath);
141142

142143
Derivation() = default;
143144
Derivation(const BasicDerivation & bd) : BasicDerivation(bd) { }
144145
Derivation(BasicDerivation && bd) : BasicDerivation(std::move(bd)) { }
146+
147+
private:
148+
std::optional<BasicDerivation> tryResolveUncached(Store & store);
145149
};
146150

147151

‎src/libstore/local-store.cc

+4-41
Original file line numberDiff line numberDiff line change
@@ -877,35 +877,9 @@ StorePathSet LocalStore::queryValidDerivers(const StorePath & path)
877877
});
878878
}
879879

880-
// Try to resolve the derivation at path `original`, with a caching layer
881-
// to make it more efficient
882-
std::optional<Derivation> cachedResolve(
883-
LocalStore& store,
884-
const StorePath& original)
885-
{
886-
// This is quite dirty and leaky, but will disappear once #4340 is merged
887-
static Sync<std::map<StorePath, std::optional<Derivation>>> resolutionsCache;
888-
{
889-
auto resolutions = resolutionsCache.lock();
890-
auto resolvedDrvIter = resolutions->find(original);
891-
if (resolvedDrvIter != resolutions->end()) {
892-
auto & [_, resolvedDrv] = *resolvedDrvIter;
893-
return *resolvedDrv;
894-
}
895-
}
896-
897-
/* Try resolve drv and use that path instead. */
898-
auto drv = store.readDerivation(original);
899-
auto attempt = drv.tryResolve(store);
900-
if (!attempt)
901-
return std::nullopt;
902-
/* Store in memo table. */
903-
resolutionsCache.lock()->insert_or_assign(original, *attempt);
904-
return *attempt;
905-
}
906880

907881
std::map<std::string, std::optional<StorePath>>
908-
LocalStore::queryPartialDerivationOutputMap(const StorePath& path_)
882+
LocalStore::queryDerivationOutputMapNoResolve(const StorePath& path_)
909883
{
910884
auto path = path_;
911885
auto outputs = retrySQLite<std::map<std::string, std::optional<StorePath>>>([&]() {
@@ -924,20 +898,9 @@ LocalStore::queryPartialDerivationOutputMap(const StorePath& path_)
924898
if (!settings.isExperimentalFeatureEnabled("ca-derivations"))
925899
return outputs;
926900

927-
auto drv = readDerivation(path);
928-
929-
auto resolvedDrv = cachedResolve(*this, path);
930-
931-
if (!resolvedDrv) {
932-
for (auto& [outputName, _] : drv.outputsAndOptPaths(*this)) {
933-
if (!outputs.count(outputName))
934-
outputs.emplace(outputName, std::nullopt);
935-
}
936-
return outputs;
937-
}
938-
939-
auto resolvedDrvHashes = staticOutputHashes(*this, *resolvedDrv);
940-
for (auto& [outputName, hash] : resolvedDrvHashes) {
901+
auto drv = readInvalidDerivation(path);
902+
auto drvHashes = staticOutputHashes(*this, drv);
903+
for (auto& [outputName, hash] : drvHashes) {
941904
auto realisation = queryRealisation(DrvOutput{hash, outputName});
942905
if (realisation)
943906
outputs.insert_or_assign(outputName, realisation->outPath);

‎src/libstore/local-store.hh

+1-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ public:
127127

128128
StorePathSet queryValidDerivers(const StorePath & path) override;
129129

130-
std::map<std::string, std::optional<StorePath>> queryPartialDerivationOutputMap(const StorePath & path) override;
130+
std::map<std::string, std::optional<StorePath>> queryDerivationOutputMapNoResolve(const StorePath & path) override;
131131

132132
std::optional<StorePath> queryPathFromHashPart(const std::string & hashPart) override;
133133

‎src/libstore/store-api.cc

+31-8
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,29 @@ bool Store::PathInfoCacheValue::isKnownNow()
366366
return std::chrono::steady_clock::now() < time_point + ttl;
367367
}
368368

369+
std::map<std::string, std::optional<StorePath>> Store::queryDerivationOutputMapNoResolve(const StorePath & path)
370+
{
371+
std::map<std::string, std::optional<StorePath>> outputs;
372+
auto drv = readInvalidDerivation(path);
373+
for (auto& [outputName, output] : drv.outputsAndOptPaths(*this)) {
374+
outputs.emplace(outputName, output.second);
375+
}
376+
return outputs;
377+
}
378+
379+
std::map<std::string, std::optional<StorePath>> Store::queryPartialDerivationOutputMap(const StorePath & path)
380+
{
381+
if (settings.isExperimentalFeatureEnabled("ca-derivations")) {
382+
auto resolvedDrv = Derivation::tryResolve(*this, path);
383+
if (resolvedDrv) {
384+
auto resolvedDrvPath = writeDerivation(*this, *resolvedDrv, NoRepair, true);
385+
if (isValidPath(resolvedDrvPath))
386+
return queryDerivationOutputMapNoResolve(resolvedDrvPath);
387+
}
388+
}
389+
return queryDerivationOutputMapNoResolve(path);
390+
}
391+
369392
OutputPathMap Store::queryDerivationOutputMap(const StorePath & path) {
370393
auto resp = queryPartialDerivationOutputMap(path);
371394
OutputPathMap result;
@@ -730,14 +753,14 @@ void Store::buildPaths(const std::vector<StorePathWithOutputs> & paths, BuildMod
730753

731754
for (auto & path : paths) {
732755
if (path.path.isDerivation()) {
733-
if (settings.isExperimentalFeatureEnabled("ca-derivations")) {
734-
for (auto & outputName : path.outputs) {
735-
if (!queryRealisation({path.path, outputName}))
736-
unsupported("buildPaths");
737-
}
738-
} else
739-
unsupported("buildPaths");
740-
756+
auto outPaths = queryPartialDerivationOutputMap(path.path);
757+
for (auto & outputName : path.outputs) {
758+
auto currentOutputPathIter = outPaths.find(outputName);
759+
if (currentOutputPathIter == outPaths.end() ||
760+
!currentOutputPathIter->second ||
761+
!isValidPath(*currentOutputPathIter->second))
762+
unsupported("buildPaths");
763+
}
741764
} else
742765
paths2.insert(path.path);
743766
}

‎src/libstore/store-api.hh

+7-2
Original file line numberDiff line numberDiff line change
@@ -416,8 +416,13 @@ public:
416416
/* Query the mapping outputName => outputPath for the given derivation. All
417417
outputs are mentioned so ones mising the mapping are mapped to
418418
`std::nullopt`. */
419-
virtual std::map<std::string, std::optional<StorePath>> queryPartialDerivationOutputMap(const StorePath & path)
420-
{ unsupported("queryPartialDerivationOutputMap"); }
419+
virtual std::map<std::string, std::optional<StorePath>> queryPartialDerivationOutputMap(const StorePath & path);
420+
421+
/*
422+
* Similar to `queryPartialDerivationOutputMap`, but doesn't try to resolve
423+
* the derivation
424+
*/
425+
virtual std::map<std::string, std::optional<StorePath>> queryDerivationOutputMapNoResolve(const StorePath & path);
421426

422427
/* Query the mapping outputName=>outputPath for the given derivation.
423428
Assume every output has a mapping and throw an exception otherwise. */

0 commit comments

Comments
 (0)
Please sign in to comment.