diff options
author | Marius Bakke <mbakke@fastmail.com> | 2019-10-08 19:24:34 +0200 |
---|---|---|
committer | Marius Bakke <mbakke@fastmail.com> | 2019-10-08 19:24:34 +0200 |
commit | d1f3b333e6176a7879ab3742bbebb2a99f61a528 (patch) | |
tree | 8bd82ce68bd2534a48bf13c7256997f82dd1b3f4 /nix/libstore | |
parent | e01d384efcdaf564bbb221e43b81e087c8e2af06 (diff) | |
parent | 861907f01efb1cae7f260e8cb7b991d5034a486a (diff) | |
download | guix-d1f3b333e6176a7879ab3742bbebb2a99f61a528.tar.gz |
Merge branch 'master' into staging
Diffstat (limited to 'nix/libstore')
-rw-r--r-- | nix/libstore/build.cc | 65 | ||||
-rw-r--r-- | nix/libstore/builtins.cc | 4 | ||||
-rw-r--r-- | nix/libstore/gc.cc | 20 | ||||
-rw-r--r-- | nix/libstore/globals.cc | 2 | ||||
-rw-r--r-- | nix/libstore/globals.hh | 11 | ||||
-rw-r--r-- | nix/libstore/local-store.cc | 102 | ||||
-rw-r--r-- | nix/libstore/local-store.hh | 12 |
7 files changed, 101 insertions, 115 deletions
diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index fe7bf79069..74cd05417f 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -614,9 +614,7 @@ HookInstance::HookInstance() { debug("starting build hook"); - Path buildHook = getEnv("NIX_BUILD_HOOK"); - if (string(buildHook, 0, 1) != "/") buildHook = settings.nixLibexecDir + "/nix/" + buildHook; - buildHook = canonPath(buildHook); + const Path &buildHook = settings.guixProgram; /* Create a pipe to get the output of the child. */ fromHook.create(); @@ -642,13 +640,14 @@ HookInstance::HookInstance() if (dup2(builderOut.writeSide, 4) == -1) throw SysError("dupping builder's stdout/stderr"); - execl(buildHook.c_str(), buildHook.c_str(), settings.thisSystem.c_str(), + execl(buildHook.c_str(), buildHook.c_str(), "offload", + settings.thisSystem.c_str(), (format("%1%") % settings.maxSilentTime).str().c_str(), (format("%1%") % settings.printBuildTrace).str().c_str(), (format("%1%") % settings.buildTimeout).str().c_str(), NULL); - throw SysError(format("executing `%1%'") % buildHook); + throw SysError(format("executing `%1% offload'") % buildHook); }); pid.setSeparatePG(true); @@ -1581,7 +1580,7 @@ void DerivationGoal::buildDone() HookReply DerivationGoal::tryBuildHook() { - if (!settings.useBuildHook || getEnv("NIX_BUILD_HOOK") == "") return rpDecline; + if (!settings.useBuildHook) return rpDecline; if (!worker.hook) worker.hook = std::shared_ptr<HookInstance>(new HookInstance); @@ -1649,7 +1648,7 @@ HookReply DerivationGoal::tryBuildHook() set<int> fds; fds.insert(hook->fromHook.readSide); fds.insert(hook->builderOut.readSide); - worker.childStarted(shared_from_this(), hook->pid, fds, false, false); + worker.childStarted(shared_from_this(), hook->pid, fds, false, true); if (settings.printBuildTrace) printMsg(lvlError, format("@ build-started %1% - %2% %3% %4%") @@ -2864,15 +2863,6 @@ private: /* The store path that should be realised through a substitute. */ Path storePath; - /* The remaining substituters. */ - Paths subs; - - /* The current substituter. */ - Path sub; - - /* Whether any substituter can realise this path */ - bool hasSubstitute; - /* Path info returned by the substituter's query info operation. */ SubstitutablePathInfo info; @@ -2898,6 +2888,8 @@ private: typedef void (SubstitutionGoal::*GoalState)(); GoalState state; + void tryNext(); + public: SubstitutionGoal(const Path & storePath, Worker & worker, bool repair = false); ~SubstitutionGoal(); @@ -2915,7 +2907,6 @@ public: /* The states. */ void init(); - void tryNext(); void gotInfo(); void referencesValid(); void tryToRun(); @@ -2931,7 +2922,6 @@ public: SubstitutionGoal::SubstitutionGoal(const Path & storePath, Worker & worker, bool repair) : Goal(worker) - , hasSubstitute(false) , repair(repair) { this->storePath = storePath; @@ -2981,37 +2971,31 @@ void SubstitutionGoal::init() if (settings.readOnlyMode) throw Error(format("cannot substitute path `%1%' - no write access to the store") % storePath); - subs = settings.substituters; - tryNext(); } void SubstitutionGoal::tryNext() { - trace("trying next substituter"); + trace("trying substituter"); - if (subs.size() == 0) { + SubstitutablePathInfos infos; + PathSet dummy(singleton<PathSet>(storePath)); + worker.store.querySubstitutablePathInfos(dummy, infos); + SubstitutablePathInfos::iterator k = infos.find(storePath); + if (k == infos.end()) { /* None left. Terminate this goal and let someone else deal with it. */ debug(format("path `%1%' is required, but there is no substituter that can build it") % storePath); /* Hack: don't indicate failure if there were no substituters. In that case the calling derivation should just do a build. */ - amDone(hasSubstitute ? ecFailed : ecNoSubstituters); - return; + amDone(ecNoSubstituters); + return; } - sub = subs.front(); - subs.pop_front(); - - SubstitutablePathInfos infos; - PathSet dummy(singleton<PathSet>(storePath)); - worker.store.querySubstitutablePathInfos(sub, dummy, infos); - SubstitutablePathInfos::iterator k = infos.find(storePath); - if (k == infos.end()) { tryNext(); return; } + /* Found a substitute. */ info = k->second; - hasSubstitute = true; /* To maintain the closure invariant, we first have to realise the paths referenced by this one. */ @@ -3099,7 +3083,8 @@ void SubstitutionGoal::tryToRun() /* Fill in the arguments. */ Strings args; - args.push_back(baseNameOf(sub)); + args.push_back("guix"); + args.push_back("substitute"); args.push_back("--substitute"); args.push_back(storePath); args.push_back(destPath); @@ -3112,9 +3097,9 @@ void SubstitutionGoal::tryToRun() if (dup2(outPipe.writeSide, STDOUT_FILENO) == -1) throw SysError("cannot dup output pipe into stdout"); - execv(sub.c_str(), stringsToCharPtrs(args).data()); + execv(settings.guixProgram.c_str(), stringsToCharPtrs(args).data()); - throw SysError(format("executing `%1%'") % sub); + throw SysError(format("executing `%1% substitute'") % settings.guixProgram); }); pid.setSeparatePG(true); @@ -3127,7 +3112,9 @@ void SubstitutionGoal::tryToRun() state = &SubstitutionGoal::finished; if (settings.printBuildTrace) - printMsg(lvlError, format("@ substituter-started %1% %2%") % storePath % sub); + /* The second element in the message used to be the name of the + substituter but we're left with only one. */ + printMsg(lvlError, format("@ substituter-started %1% substitute") % storePath); } @@ -3193,9 +3180,7 @@ void SubstitutionGoal::finished() % storePath % status % e.msg()); } - /* Try the next substitute. */ - state = &SubstitutionGoal::tryNext; - worker.wakeUp(shared_from_this()); + amDone(ecFailed); return; } diff --git a/nix/libstore/builtins.cc b/nix/libstore/builtins.cc index f7c7d42484..4111ac4760 100644 --- a/nix/libstore/builtins.cc +++ b/nix/libstore/builtins.cc @@ -39,7 +39,7 @@ static void builtinDownload(const Derivation &drv, const char *const argv[] = { - "download", drvPath.c_str(), output.c_str(), NULL + "guix", "perform-download", drvPath.c_str(), output.c_str(), NULL }; /* Tell the script what the store file name is, so that @@ -50,7 +50,7 @@ static void builtinDownload(const Derivation &drv, /* Tell it about options such as "print-extended-build-trace". */ setenv("_NIX_OPTIONS", settings.pack().c_str(), 1); - const string program = settings.nixLibexecDir + "/download"; + const string program = settings.guixProgram; execv(program.c_str(), (char *const *) argv); throw SysError(format("failed to run download program '%1%'") % program); diff --git a/nix/libstore/gc.cc b/nix/libstore/gc.cc index 310b8792fe..c466996668 100644 --- a/nix/libstore/gc.cc +++ b/nix/libstore/gc.cc @@ -339,14 +339,11 @@ Roots LocalStore::findRoots() static void addAdditionalRoots(StoreAPI & store, PathSet & roots) { - Path rootFinder = getEnv("NIX_ROOT_FINDER", - settings.nixLibexecDir + "/list-runtime-roots"); + debug(format("executing `%1% gc --list-busy' to find additional roots") + % settings.guixProgram); - if (rootFinder.empty()) return; - - debug(format("executing `%1%' to find additional roots") % rootFinder); - - string result = runProgram(rootFinder); + const Strings args = { "gc", "--list-busy" }; + string result = runProgram(settings.guixProgram, false, args); StringSet paths = tokenizeString<StringSet>(result, "\n"); @@ -569,9 +566,8 @@ void LocalStore::removeUnusedLinks(const GCState & state) throw SysError(format("statting `%1%'") % path); if (st.st_nlink != 1) { - unsigned long long size = st.st_blocks * 512ULL; - actualSize += size; - unsharedSize += (st.st_nlink - 1) * size; + actualSize += st.st_size; + unsharedSize += (st.st_nlink - 1) * st.st_size; continue; } @@ -580,13 +576,13 @@ void LocalStore::removeUnusedLinks(const GCState & state) if (unlink(path.c_str()) == -1) throw SysError(format("deleting `%1%'") % path); - state.results.bytesFreed += st.st_blocks * 512; + state.results.bytesFreed += st.st_size; } struct stat st; if (stat(linksDir.c_str(), &st) == -1) throw SysError(format("statting `%1%'") % linksDir); - long long overhead = st.st_blocks * 512ULL; + long long overhead = st.st_size; printMsg(lvlInfo, format("note: currently hard linking saves %.2f MiB") % ((unsharedSize - actualSize - overhead) / (1024.0 * 1024.0))); diff --git a/nix/libstore/globals.cc b/nix/libstore/globals.cc index 6df20e7a52..0cc001fbe4 100644 --- a/nix/libstore/globals.cc +++ b/nix/libstore/globals.cc @@ -70,9 +70,9 @@ void Settings::processEnvironment() nixStateDir = canonPath(getEnv("GUIX_STATE_DIRECTORY", NIX_STATE_DIR)); nixDBPath = getEnv("GUIX_DATABASE_DIRECTORY", nixStateDir + "/db"); nixConfDir = canonPath(getEnv("GUIX_CONFIGURATION_DIRECTORY", GUIX_CONFIGURATION_DIRECTORY)); - nixLibexecDir = canonPath(getEnv("NIX_LIBEXEC_DIR", NIX_LIBEXEC_DIR)); nixBinDir = canonPath(getEnv("NIX_BIN_DIR", NIX_BIN_DIR)); nixDaemonSocketFile = canonPath(nixStateDir + DEFAULT_SOCKET_PATH); + guixProgram = canonPath(getEnv("GUIX", nixBinDir + "/guix")); } diff --git a/nix/libstore/globals.hh b/nix/libstore/globals.hh index b073f724b6..27616a2283 100644 --- a/nix/libstore/globals.hh +++ b/nix/libstore/globals.hh @@ -57,15 +57,15 @@ struct Settings { /* The directory where configuration files are stored. */ Path nixConfDir; - /* The directory where internal helper programs are stored. */ - Path nixLibexecDir; - /* The directory where the main programs are stored. */ Path nixBinDir; /* File name of the socket the daemon listens to. */ Path nixDaemonSocketFile; + /* Absolute file name of the 'guix' program. */ + Path guixProgram; + /* Whether to keep temporary directories of failed builds. */ bool keepFailed; @@ -112,11 +112,6 @@ struct Settings { means infinity. */ time_t buildTimeout; - /* The substituters. There are programs that can somehow realise - a store path without building, e.g., by downloading it or - copying it from a CD. */ - Paths substituters; - /* Whether to use build hooks (for distributed builds). Sometimes users want to disable this from the command-line. */ bool useBuildHook; diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc index 892d9300b1..3b08492c64 100644 --- a/nix/libstore/local-store.cc +++ b/nix/libstore/local-store.cc @@ -184,13 +184,15 @@ LocalStore::LocalStore(bool reserveSpace) LocalStore::~LocalStore() { try { - foreach (RunningSubstituters::iterator, i, runningSubstituters) { - if (i->second.disabled) continue; - i->second.to.close(); - i->second.from.close(); - i->second.error.close(); - if (i->second.pid != -1) - i->second.pid.wait(true); + if (runningSubstituter) { + RunningSubstituter &i = *runningSubstituter; + if (!i.disabled) { + i.to.close(); + i.from.close(); + i.error.close(); + if (i.pid != -1) + i.pid.wait(true); + } } } catch (...) { ignoreException(); @@ -808,11 +810,12 @@ void LocalStore::setSubstituterEnv() } -void LocalStore::startSubstituter(const Path & substituter, RunningSubstituter & run) +void LocalStore::startSubstituter(RunningSubstituter & run) { if (run.disabled || run.pid != -1) return; - debug(format("starting substituter program `%1%'") % substituter); + debug(format("starting substituter program `%1% substitute'") + % settings.guixProgram); Pipe toPipe, fromPipe, errorPipe; @@ -829,11 +832,10 @@ void LocalStore::startSubstituter(const Path & substituter, RunningSubstituter & throw SysError("dupping stdout"); if (dup2(errorPipe.writeSide, STDERR_FILENO) == -1) throw SysError("dupping stderr"); - execl(substituter.c_str(), substituter.c_str(), "--query", NULL); - throw SysError(format("executing `%1%'") % substituter); + execl(settings.guixProgram.c_str(), "guix", "substitute", "--query", NULL); + throw SysError(format("executing `%1%'") % settings.guixProgram); }); - run.program = baseNameOf(substituter); run.to = toPipe.writeSide.borrow(); run.from = run.fromBuf.fd = fromPipe.readSide.borrow(); run.error = errorPipe.readSide.borrow(); @@ -889,13 +891,14 @@ string LocalStore::getLineFromSubstituter(RunningSubstituter & run) if (errno == EINTR) continue; throw SysError("reading from substituter's stderr"); } - if (n == 0) throw EndOfFile(format("substituter `%1%' died unexpectedly") % run.program); + if (n == 0) throw EndOfFile(format("`%1% substitute' died unexpectedly") + % settings.guixProgram); err.append(buf, n); string::size_type p; while (((p = err.find('\n')) != string::npos) || ((p = err.find('\r')) != string::npos)) { string thing(err, 0, p + 1); - writeToStderr(run.program + ": " + thing); + writeToStderr("substitute: " + thing); err = string(err, p + 1); } } @@ -907,7 +910,7 @@ string LocalStore::getLineFromSubstituter(RunningSubstituter & run) unsigned char c; run.fromBuf(&c, 1); if (c == '\n') { - if (!err.empty()) printMsg(lvlError, run.program + ": " + err); + if (!err.empty()) printMsg(lvlError, "substitute: " + err); return res; } res += c; @@ -930,38 +933,47 @@ PathSet LocalStore::querySubstitutablePaths(const PathSet & paths) { PathSet res; - if (!settings.useSubstitutes) return res; - - foreach (Paths::iterator, i, settings.substituters) { - if (res.size() == paths.size()) break; - RunningSubstituter & run(runningSubstituters[*i]); - startSubstituter(*i, run); - if (run.disabled) continue; - string s = "have "; - foreach (PathSet::const_iterator, j, paths) - if (res.find(*j) == res.end()) { s += *j; s += " "; } - writeLine(run.to, s); - while (true) { - /* FIXME: we only read stderr when an error occurs, so - substituters should only write (short) messages to - stderr when they fail. I.e. they shouldn't write debug - output. */ - Path path = getLineFromSubstituter(run); - if (path == "") break; - res.insert(path); - } + if (!settings.useSubstitutes || paths.empty()) return res; + + if (!runningSubstituter) { + std::unique_ptr<RunningSubstituter>fresh(new RunningSubstituter); + runningSubstituter.swap(fresh); + } + + RunningSubstituter & run = *runningSubstituter; + startSubstituter(run); + + if (!run.disabled) { + string s = "have "; + foreach (PathSet::const_iterator, j, paths) + if (res.find(*j) == res.end()) { s += *j; s += " "; } + writeLine(run.to, s); + while (true) { + /* FIXME: we only read stderr when an error occurs, so + substituters should only write (short) messages to + stderr when they fail. I.e. they shouldn't write debug + output. */ + Path path = getLineFromSubstituter(run); + if (path == "") break; + res.insert(path); + } } + return res; } -void LocalStore::querySubstitutablePathInfos(const Path & substituter, - PathSet & paths, SubstitutablePathInfos & infos) +void LocalStore::querySubstitutablePathInfos(PathSet & paths, SubstitutablePathInfos & infos) { if (!settings.useSubstitutes) return; - RunningSubstituter & run(runningSubstituters[substituter]); - startSubstituter(substituter, run); + if (!runningSubstituter) { + std::unique_ptr<RunningSubstituter>fresh(new RunningSubstituter); + runningSubstituter.swap(fresh); + } + + RunningSubstituter & run = *runningSubstituter; + startSubstituter(run); if (run.disabled) return; string s = "info "; @@ -993,10 +1005,9 @@ void LocalStore::querySubstitutablePathInfos(const Path & substituter, void LocalStore::querySubstitutablePathInfos(const PathSet & paths, SubstitutablePathInfos & infos) { - PathSet todo = paths; - foreach (Paths::iterator, i, settings.substituters) { - if (todo.empty()) break; - querySubstitutablePathInfos(*i, todo, infos); + if (!paths.empty()) { + PathSet todo = paths; + querySubstitutablePathInfos(todo, infos); } } @@ -1224,8 +1235,9 @@ static void checkSecrecy(const Path & path) static std::string runAuthenticationProgram(const Strings & args) { - return runProgram(settings.nixLibexecDir + "/authenticate", - false, args); + Strings fullArgs = { "authenticate" }; + fullArgs.insert(fullArgs.end(), args.begin(), args.end()); // append + return runProgram(settings.guixProgram, false, fullArgs); } void LocalStore::exportPath(const Path & path, bool sign, diff --git a/nix/libstore/local-store.hh b/nix/libstore/local-store.hh index 4e6b4cfc1d..4113fafcb5 100644 --- a/nix/libstore/local-store.hh +++ b/nix/libstore/local-store.hh @@ -40,7 +40,6 @@ struct OptimiseStats struct RunningSubstituter { - Path program; Pid pid; AutoCloseFD to, from, error; FdSource fromBuf; @@ -52,8 +51,8 @@ struct RunningSubstituter class LocalStore : public StoreAPI { private: - typedef std::map<Path, RunningSubstituter> RunningSubstituters; - RunningSubstituters runningSubstituters; + /* The currently running substituter or empty. */ + std::unique_ptr<RunningSubstituter> runningSubstituter; Path linksDir; @@ -93,8 +92,8 @@ public: PathSet querySubstitutablePaths(const PathSet & paths); - void querySubstitutablePathInfos(const Path & substituter, - PathSet & paths, SubstitutablePathInfos & infos); + void querySubstitutablePathInfos(PathSet & paths, + SubstitutablePathInfos & infos); void querySubstitutablePathInfos(const PathSet & paths, SubstitutablePathInfos & infos); @@ -261,8 +260,7 @@ private: void removeUnusedLinks(const GCState & state); - void startSubstituter(const Path & substituter, - RunningSubstituter & runningSubstituter); + void startSubstituter(RunningSubstituter & runningSubstituter); string getLineFromSubstituter(RunningSubstituter & run); |