Aso track the output path of the realisation dependencies

This commit is contained in:
regnat 2021-05-26 16:09:02 +02:00
parent cb46d70794
commit 1f3ff0d193
7 changed files with 46 additions and 39 deletions

View file

@ -927,7 +927,7 @@ void DerivationGoal::resolvedFinished() {
auto newRealisation = *realisation; auto newRealisation = *realisation;
newRealisation.id = DrvOutput{initialOutputs.at(wantedOutput).outputHash, wantedOutput}; newRealisation.id = DrvOutput{initialOutputs.at(wantedOutput).outputHash, wantedOutput};
newRealisation.signatures.clear(); newRealisation.signatures.clear();
newRealisation.drvOutputDeps = drvOutputReferences(worker.store, *drv, realisation->outPath); newRealisation.dependentRealisations = drvOutputReferences(worker.store, *drv, realisation->outPath);
signRealisation(newRealisation); signRealisation(newRealisation);
worker.store.registerDrvOutput(newRealisation); worker.store.registerDrvOutput(newRealisation);
} else { } else {

View file

@ -711,19 +711,19 @@ void LocalStore::registerDrvOutput(const Realisation & info, CheckSigsFlag check
void LocalStore::registerDrvOutput(const Realisation & info) void LocalStore::registerDrvOutput(const Realisation & info)
{ {
settings.requireExperimentalFeature("ca-derivations"); settings.requireExperimentalFeature("ca-derivations");
auto state(_state.lock());
retrySQLite<void>([&]() { retrySQLite<void>([&]() {
auto state(_state.lock());
state->stmts->RegisterRealisedOutput state->stmts->RegisterRealisedOutput
.use()(info.id.strHash())(info.id.outputName)(printStorePath( .use()(info.id.strHash())(info.id.outputName)(printStorePath(
info.outPath))(concatStringsSep(" ", info.signatures)) info.outPath))(concatStringsSep(" ", info.signatures))
.exec(); .exec();
uint64_t myId = state->db.getLastInsertedRowId();
for (auto & [outputId, _] : info.dependentRealisations) {
state->stmts->AddRealisationRealisationReference
.use()(myId)(outputId.strHash())(outputId.outputName)
.exec();
}
}); });
uint64_t myId = state->db.getLastInsertedRowId();
for (auto& outputId : info.drvOutputDeps) {
state->stmts->AddRealisationRealisationReference
.use()(myId)(outputId.strHash())(outputId.outputName)
.exec();
}
} }
void LocalStore::cacheDrvOutputMapping(State & state, const uint64_t deriver, const string & outputName, const StorePath & output) void LocalStore::cacheDrvOutputMapping(State & state, const uint64_t deriver, const string & outputName, const StorePath & output)
@ -1730,22 +1730,26 @@ std::optional<const Realisation> LocalStore::queryRealisation(
auto signatures = auto signatures =
tokenizeString<StringSet>(useQueryRealisedOutput.getStr(2)); tokenizeString<StringSet>(useQueryRealisedOutput.getStr(2));
std::set<DrvOutput> drvOutputDeps; std::map<DrvOutput, StorePath> dependentRealisations;
auto useRealisationRefs( auto useRealisationRefs(
state->stmts->QueryRealisationRealisationReferences.use()( state->stmts->QueryRealisationRealisationReferences.use()(
realisationDbId)); realisationDbId));
while (useRealisationRefs.next()) while (useRealisationRefs.next()) {
drvOutputDeps.insert(DrvOutput{ auto depHash = useRealisationRefs.getStr(0);
Hash::parseAnyPrefixed(useRealisationRefs.getStr(0)), auto depOutputName = useRealisationRefs.getStr(1);
useRealisationRefs.getStr(1), auto useQueryRealisedOutput(
} state->stmts->QueryRealisedOutput.use()(depHash)(depOutputName));
); assert(useQueryRealisedOutput.next());
auto outputPath = parseStorePath(useQueryRealisedOutput.getStr(1));
auto depId = DrvOutput { Hash::parseAnyPrefixed(depHash), depOutputName };
dependentRealisations.insert({depId, outputPath});
}
return Ret{Realisation{ return Ret{Realisation{
.id = id, .id = id,
.outPath = outputPath, .outPath = outputPath,
.signatures = signatures, .signatures = signatures,
.drvOutputDeps = drvOutputDeps, .dependentRealisations = dependentRealisations,
}}; }};
}); });
} }

View file

@ -254,25 +254,22 @@ StorePaths Store::topoSortPaths(const StorePathSet & paths)
}}); }});
} }
std::set<DrvOutput> drvOutputReferences( std::map<DrvOutput, StorePath> drvOutputReferences(
const std::set<Realisation> inputRealisations, const std::set<Realisation> inputRealisations,
const StorePathSet pathReferences) const StorePathSet pathReferences)
{ {
std::set<DrvOutput> res; std::map<DrvOutput, StorePath> res;
std::map<StorePath, std::set<DrvOutput>> inputsByOutputPath; for (const auto & input : inputRealisations) {
for (const auto & input : inputRealisations) if (pathReferences.count(input.outPath)) {
inputsByOutputPath[input.outPath].insert(input.id); res.insert({input.id, input.outPath});
}
for (const auto & path : pathReferences) {
auto theseInputs = inputsByOutputPath[path];
res.insert(theseInputs.begin(), theseInputs.end());
} }
return res; return res;
} }
std::set<DrvOutput> drvOutputReferences( std::map<DrvOutput, StorePath> drvOutputReferences(
Store & store, Store & store,
const Derivation & drv, const Derivation & drv,
const StorePath & outputPath) const StorePath & outputPath)

View file

@ -33,7 +33,7 @@ void Realisation::closure(Store & store, std::set<Realisation> startOutputs, std
{ {
auto getDeps = [&](const Realisation& current) -> std::set<Realisation> { auto getDeps = [&](const Realisation& current) -> std::set<Realisation> {
std::set<Realisation> res; std::set<Realisation> res;
for (auto& currentDep : current.drvOutputDeps) { for (auto& [currentDep, _] : current.dependentRealisations) {
if (auto currentRealisation = store.queryRealisation(currentDep)) if (auto currentRealisation = store.queryRealisation(currentDep))
res.insert(*currentRealisation); res.insert(*currentRealisation);
else else
@ -60,14 +60,14 @@ void Realisation::closure(Store & store, std::set<Realisation> startOutputs, std
} }
nlohmann::json Realisation::toJSON() const { nlohmann::json Realisation::toJSON() const {
nlohmann::json jsonDrvOutputDeps; auto jsonDependentRealisations = nlohmann::json::object();
for (auto & dep : drvOutputDeps) for (auto & [depId, depOutPath] : dependentRealisations)
jsonDrvOutputDeps.push_back(dep.to_string()); jsonDependentRealisations.emplace(depId.to_string(), depOutPath.to_string());
return nlohmann::json{ return nlohmann::json{
{"id", id.to_string()}, {"id", id.to_string()},
{"outPath", outPath.to_string()}, {"outPath", outPath.to_string()},
{"signatures", signatures}, {"signatures", signatures},
{"drvOutputDeps", jsonDrvOutputDeps}, {"dependentRealisations", jsonDependentRealisations},
}; };
} }
@ -93,16 +93,16 @@ Realisation Realisation::fromJSON(
if (auto signaturesIterator = json.find("signatures"); signaturesIterator != json.end()) if (auto signaturesIterator = json.find("signatures"); signaturesIterator != json.end())
signatures.insert(signaturesIterator->begin(), signaturesIterator->end()); signatures.insert(signaturesIterator->begin(), signaturesIterator->end());
std::set <DrvOutput> drvOutputDeps; std::map <DrvOutput, StorePath> dependentRealisations;
if (auto jsonDependencies = json.find("drvOutputDeps"); jsonDependencies != json.end()) if (auto jsonDependencies = json.find("dependentRealisations"); jsonDependencies != json.end())
for (auto & jsonDep : *jsonDependencies) for (auto & [jsonDepId, jsonDepOutPath] : jsonDependencies->get<std::map<std::string, std::string>>())
drvOutputDeps.insert(DrvOutput::parse(jsonDep.get<std::string>())); dependentRealisations.insert({DrvOutput::parse(jsonDepId), StorePath(jsonDepOutPath)});
return Realisation{ return Realisation{
.id = DrvOutput::parse(getField("id")), .id = DrvOutput::parse(getField("id")),
.outPath = StorePath(getField("outPath")), .outPath = StorePath(getField("outPath")),
.signatures = signatures, .signatures = signatures,
.drvOutputDeps = drvOutputDeps, .dependentRealisations = dependentRealisations,
}; };
} }

View file

@ -28,7 +28,13 @@ struct Realisation {
StringSet signatures; StringSet signatures;
std::set<DrvOutput> drvOutputDeps; /**
* The realisations that are required for the current one to be valid.
*
* When importing this realisation, the store will first check that all its
* dependencies exist, and map to the correct output path
*/
std::map<DrvOutput, StorePath> dependentRealisations;
nlohmann::json toJSON() const; nlohmann::json toJSON() const;
static Realisation fromJSON(const nlohmann::json& json, const std::string& whence); static Realisation fromJSON(const nlohmann::json& json, const std::string& whence);

View file

@ -798,7 +798,7 @@ std::map<StorePath, StorePath> copyPaths(ref<Store> srcStore, ref<Store> dstStor
pool, Realisation::closure(*srcStore, toplevelRealisations), pool, Realisation::closure(*srcStore, toplevelRealisations),
[&](const Realisation& current) -> std::set<Realisation> { [&](const Realisation& current) -> std::set<Realisation> {
std::set<Realisation> children; std::set<Realisation> children;
for (const auto& drvOutput : current.drvOutputDeps) { for (const auto& [drvOutput, _] : current.dependentRealisations) {
auto currentChild = srcStore->queryRealisation(drvOutput); auto currentChild = srcStore->queryRealisation(drvOutput);
if (!currentChild) if (!currentChild)
throw Error( throw Error(

View file

@ -864,7 +864,7 @@ std::pair<std::string, Store::Params> splitUriAndParams(const std::string & uri)
std::optional<ContentAddress> getDerivationCA(const BasicDerivation & drv); std::optional<ContentAddress> getDerivationCA(const BasicDerivation & drv);
std::set<DrvOutput> drvOutputReferences( std::map<DrvOutput, StorePath> drvOutputReferences(
Store & store, Store & store,
const Derivation & drv, const Derivation & drv,
const StorePath & outputPath); const StorePath & outputPath);