1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-15 15:02:42 +01:00

Use the hash modulo in the derivation outputs

Rather than storing the derivation outputs as `drvPath!outputName` internally,
store them as `drvHashModulo!outputName` (or `outputHash!outputName` for
fixed-output derivations).

This makes the storage slightly more opaque, but enables an earlier
cutoff in cases where a fixed-output dependency changes (but keeps the
same output hash) − same as what we already do for input-addressed
derivations.
This commit is contained in:
regnat 2020-12-09 16:56:56 +01:00
parent 8914e01e37
commit bab1cda0e6
7 changed files with 93 additions and 89 deletions

View file

@ -659,7 +659,7 @@ void LocalStore::registerDrvOutput(const Realisation & info)
auto state(_state.lock());
retrySQLite<void>([&]() {
state->stmts->RegisterRealisedOutput.use()
(info.id.drvPath.to_string())
(info.id.strHash())
(info.id.outputName)
(printStorePath(info.outPath))
.exec();
@ -879,17 +879,18 @@ StorePathSet LocalStore::queryValidDerivers(const StorePath & path)
// Try to resolve the derivation at path `original`, with a caching layer
// to make it more efficient
std::optional<StorePath> cachedResolve(
LocalStore & store,
const StorePath & original)
std::optional<Derivation> cachedResolve(
LocalStore& store,
const StorePath& original)
{
// This is quite dirty and leaky, but will disappear once #4340 is merged
static Sync<std::map<StorePath, std::optional<Derivation>>> resolutionsCache;
{
auto resolutions = drvPathResolutions.lock();
auto resolvedPathOptIter = resolutions->find(original);
if (resolvedPathOptIter != resolutions->end()) {
auto & [_, resolvedPathOpt] = *resolvedPathOptIter;
if (resolvedPathOpt)
return resolvedPathOpt;
auto resolutions = resolutionsCache.lock();
auto resolvedDrvIter = resolutions->find(original);
if (resolvedDrvIter != resolutions->end()) {
auto & [_, resolvedDrv] = *resolvedDrvIter;
return *resolvedDrv;
}
}
@ -898,12 +899,9 @@ std::optional<StorePath> cachedResolve(
auto attempt = drv.tryResolve(store);
if (!attempt)
return std::nullopt;
/* Just compute store path */
auto pathResolved =
writeDerivation(store, *std::move(attempt), NoRepair, true);
/* Store in memo table. */
drvPathResolutions.lock()->insert_or_assign(original, pathResolved);
return pathResolved;
resolutionsCache.lock()->insert_or_assign(original, *attempt);
return *attempt;
}
std::map<std::string, std::optional<StorePath>>
@ -933,26 +931,24 @@ LocalStore::queryPartialDerivationOutputMap(const StorePath& path_)
auto drv = readDerivation(path);
for (auto & output : drv.outputsAndOptPaths(*this)) {
outputs.emplace(output.first, std::nullopt);
}
auto resolvedDrv = cachedResolve(*this, path);
if (!resolvedDrv)
if (!resolvedDrv) {
for (auto& [outputName, _] : drv.outputsAndOptPaths(*this)) {
if (!outputs.count(outputName))
outputs.emplace(outputName, std::nullopt);
}
return outputs;
}
retrySQLite<void>([&]() {
auto state(_state.lock());
path = *resolvedDrv;
auto useQueryDerivationOutputs{
state->stmts->QueryAllRealisedOutputs.use()(path.to_string())};
while (useQueryDerivationOutputs.next())
outputs.insert_or_assign(
useQueryDerivationOutputs.getStr(0),
parseStorePath(useQueryDerivationOutputs.getStr(1)));
});
auto resolvedDrvHashes = staticOutputHashes(*this, *resolvedDrv);
for (auto& [outputName, hash] : resolvedDrvHashes) {
auto realisation = queryRealisation(DrvOutput{hash, outputName});
if (realisation)
outputs.insert_or_assign(outputName, realisation->outPath);
else
outputs.insert_or_assign(outputName, std::nullopt);
}
return outputs;
}
@ -1695,12 +1691,11 @@ std::optional<const Realisation> LocalStore::queryRealisation(
typedef std::optional<const Realisation> Ret;
return retrySQLite<Ret>([&]() -> Ret {
auto state(_state.lock());
auto use(state->stmts->QueryRealisedOutput.use()(id.drvPath.to_string())(
auto use(state->stmts->QueryRealisedOutput.use()(id.strHash())(
id.outputName));
if (!use.next())
return std::nullopt;
auto outputPath = parseStorePath(use.getStr(0));
auto resolvedDrv = StorePath(use.getStr(1));
return Ret{
Realisation{.id = id, .outPath = outputPath}};
});