forked from lix-project/hydra
buildRemote(): Copy paths to the destination store in O(1) memory
This commit is contained in:
parent
cbcf6359b4
commit
7622cbfe37
|
@ -124,6 +124,38 @@ static void copyClosureTo(std::timed_mutex & sendMutex, ref<Store> destStore,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FIXME: use Store::topoSortPaths().
|
||||||
|
StorePaths topoSortPaths(const std::map<StorePath, ValidPathInfo> & paths)
|
||||||
|
{
|
||||||
|
StorePaths sorted;
|
||||||
|
StorePathSet visited;
|
||||||
|
|
||||||
|
std::function<void(const StorePath & path)> dfsVisit;
|
||||||
|
|
||||||
|
dfsVisit = [&](const StorePath & path) {
|
||||||
|
if (!visited.insert(path).second) return;
|
||||||
|
|
||||||
|
auto info = paths.find(path);
|
||||||
|
auto references = info == paths.end() ? StorePathSet() : info->second.references;
|
||||||
|
|
||||||
|
for (auto & i : references)
|
||||||
|
/* Don't traverse into paths that don't exist. That can
|
||||||
|
happen due to substitutes for non-existent paths. */
|
||||||
|
if (i != path && paths.count(i))
|
||||||
|
dfsVisit(i);
|
||||||
|
|
||||||
|
sorted.push_back(path);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto & i : paths)
|
||||||
|
dfsVisit(i.first);
|
||||||
|
|
||||||
|
std::reverse(sorted.begin(), sorted.end());
|
||||||
|
|
||||||
|
return sorted;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void State::buildRemote(ref<Store> destStore,
|
void State::buildRemote(ref<Store> destStore,
|
||||||
Machine::ptr machine, Step::ptr step,
|
Machine::ptr machine, Step::ptr step,
|
||||||
unsigned int maxSilentTime, unsigned int buildTimeout, unsigned int repeats,
|
unsigned int maxSilentTime, unsigned int buildTimeout, unsigned int repeats,
|
||||||
|
@ -148,6 +180,7 @@ void State::buildRemote(ref<Store> destStore,
|
||||||
|
|
||||||
updateStep(ssConnecting);
|
updateStep(ssConnecting);
|
||||||
|
|
||||||
|
// FIXME: rewrite to use Store.
|
||||||
Child child;
|
Child child;
|
||||||
openConnection(machine, tmpDir, logFD.get(), child);
|
openConnection(machine, tmpDir, logFD.get(), child);
|
||||||
|
|
||||||
|
@ -182,7 +215,7 @@ void State::buildRemote(ref<Store> destStore,
|
||||||
unsigned int remoteVersion;
|
unsigned int remoteVersion;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
to << SERVE_MAGIC_1 << 0x203;
|
to << SERVE_MAGIC_1 << 0x204;
|
||||||
to.flush();
|
to.flush();
|
||||||
|
|
||||||
unsigned int magic = readInt(from);
|
unsigned int magic = readInt(from);
|
||||||
|
@ -405,17 +438,26 @@ void State::buildRemote(ref<Store> destStore,
|
||||||
|
|
||||||
auto outputs = step->drv->outputPaths();
|
auto outputs = step->drv->outputPaths();
|
||||||
|
|
||||||
/* Query the size of the output paths. */
|
/* Get info about each output path. */
|
||||||
|
std::map<StorePath, ValidPathInfo> infos;
|
||||||
size_t totalNarSize = 0;
|
size_t totalNarSize = 0;
|
||||||
to << cmdQueryPathInfos;
|
to << cmdQueryPathInfos;
|
||||||
writeStorePaths(*localStore, to, outputs);
|
writeStorePaths(*localStore, to, outputs);
|
||||||
to.flush();
|
to.flush();
|
||||||
while (true) {
|
while (true) {
|
||||||
if (readString(from) == "") break;
|
auto storePathS = readString(from);
|
||||||
|
if (storePathS == "") break;
|
||||||
|
ValidPathInfo info(localStore->parseStorePath(storePathS));
|
||||||
|
assert(outputs.count(info.path));
|
||||||
readString(from); // deriver
|
readString(from); // deriver
|
||||||
readStrings<PathSet>(from); // references
|
info.references = readStorePaths<StorePathSet>(*localStore, from);
|
||||||
readLongLong(from); // download size
|
readLongLong(from); // download size
|
||||||
totalNarSize += readLongLong(from);
|
info.narSize = readLongLong(from);
|
||||||
|
totalNarSize += info.narSize;
|
||||||
|
info.narHash = Hash(readString(from), htSHA256);
|
||||||
|
info.ca = parseContentAddressOpt(readString(from));
|
||||||
|
readStrings<StringSet>(from); // sigs
|
||||||
|
infos.insert_or_assign(info.path, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalNarSize > maxOutputSize) {
|
if (totalNarSize > maxOutputSize) {
|
||||||
|
@ -423,13 +465,18 @@ void State::buildRemote(ref<Store> destStore,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copy each path. */
|
||||||
printMsg(lvlDebug, "copying outputs of ‘%s’ from ‘%s’ (%d bytes)",
|
printMsg(lvlDebug, "copying outputs of ‘%s’ from ‘%s’ (%d bytes)",
|
||||||
localStore->printStorePath(step->drvPath), machine->sshName, totalNarSize);
|
localStore->printStorePath(step->drvPath), machine->sshName, totalNarSize);
|
||||||
|
|
||||||
to << cmdExportPaths << 0;
|
auto pathsSorted = topoSortPaths(infos);
|
||||||
writeStorePaths(*localStore, to, outputs);
|
|
||||||
to.flush();
|
for (auto & path : pathsSorted) {
|
||||||
destStore->importPaths(from, /* result.accessor, */ NoCheckSigs);
|
auto & info = infos.find(path)->second;
|
||||||
|
to << cmdDumpStorePath << localStore->printStorePath(path);
|
||||||
|
to.flush();
|
||||||
|
destStore->addToStore(info, from);
|
||||||
|
}
|
||||||
|
|
||||||
auto now2 = std::chrono::steady_clock::now();
|
auto now2 = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue