diff options
author | Eelco Dolstra <e.dolstra@tudelft.nl> | 2008-08-02T12·54+0000 |
---|---|---|
committer | Eelco Dolstra <e.dolstra@tudelft.nl> | 2008-08-02T12·54+0000 |
commit | 3c92ea399d717dc45b3fa91424c0dadc0239ebf2 (patch) | |
tree | 7cde9f533a6ee575615da5452e04c05dc0939f02 /src/libstore/local-store.cc | |
parent | fc691e1cbdcddb8c553cba06d4089bc1b60e3d98 (diff) |
* Make nix-env --dry-run print the paths to be substituted correctly
again. (After the previous substituter mechanism refactoring I didn't update the code that obtains the references of substitutable paths.) This required some refactoring: the substituter programs are now kept running and receive/respond to info requests via stdin/stdout.
Diffstat (limited to 'src/libstore/local-store.cc')
-rw-r--r-- | src/libstore/local-store.cc | 117 |
1 files changed, 97 insertions, 20 deletions
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index d886ba558606..6926c49370d8 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -83,6 +83,13 @@ LocalStore::~LocalStore() { try { flushDelayedUpdates(); + + foreach (RunningSubstituters::iterator, i, runningSubstituters) { + i->second.toBuf.reset(); + i->second.to.reset(); + i->second.pid.wait(true); + } + } catch (...) { ignoreException(); } @@ -367,8 +374,6 @@ ValidPathInfo LocalStore::queryPathInfo(const Path & path) std::map<Path, ValidPathInfo>::iterator lookup = pathInfoCache.find(path); if (lookup != pathInfoCache.end()) return lookup->second; - //printMsg(lvlError, "queryPathInfo: " + path); - /* Read the info file. */ Path infoFile = infoFileFor(path); if (!pathExists(infoFile)) @@ -467,33 +472,105 @@ Path LocalStore::queryDeriver(const Path & path) } -PathSet LocalStore::querySubstitutablePaths() +void LocalStore::startSubstituter(const Path & substituter, RunningSubstituter & run) { - if (!substitutablePathsLoaded) { - for (Paths::iterator i = substituters.begin(); i != substituters.end(); ++i) { - debug(format("running `%1%' to find out substitutable paths") % *i); - Strings args; - args.push_back("--query-paths"); - Strings ss = tokenizeString(runProgram(*i, false, args), "\n"); - for (Strings::iterator j = ss.begin(); j != ss.end(); ++j) { - if (!isStorePath(*j)) - throw Error(format("`%1%' returned a bad substitutable path `%2%'") - % *i % *j); - substitutablePaths.insert(*j); - } + if (run.pid != -1) return; + + debug(format("starting substituter program `%1%'") % substituter); + + Pipe toPipe, fromPipe; + + toPipe.create(); + fromPipe.create(); + + run.pid = fork(); + + switch (run.pid) { + + case -1: + throw SysError("unable to fork"); + + case 0: /* child */ + try { + fromPipe.readSide.close(); + toPipe.writeSide.close(); + if (dup2(toPipe.readSide, STDIN_FILENO) == -1) + throw SysError("dupping stdin"); + if (dup2(fromPipe.writeSide, STDOUT_FILENO) == -1) + throw SysError("dupping stdout"); + closeMostFDs(set<int>()); + execl(substituter.c_str(), substituter.c_str(), "--query", NULL); + throw SysError(format("executing `%1%'") % substituter); + } catch (std::exception & e) { + std::cerr << "error: " << e.what() << std::endl; } - substitutablePathsLoaded = true; + quickExit(1); } - return substitutablePaths; + /* Parent. */ + + toPipe.readSide.close(); + fromPipe.writeSide.close(); + + run.toBuf = boost::shared_ptr<stdio_filebuf>(new stdio_filebuf(toPipe.writeSide.borrow(), std::ios_base::out)); + run.to = boost::shared_ptr<std::ostream>(new std::ostream(&*run.toBuf)); + + run.fromBuf = boost::shared_ptr<stdio_filebuf>(new stdio_filebuf(fromPipe.readSide.borrow(), std::ios_base::in)); + run.from = boost::shared_ptr<std::istream>(new std::istream(&*run.fromBuf)); } bool LocalStore::hasSubstitutes(const Path & path) { - if (!substitutablePathsLoaded) - querySubstitutablePaths(); - return substitutablePaths.find(path) != substitutablePaths.end(); + foreach (Paths::iterator, i, substituters) { + RunningSubstituter & run(runningSubstituters[*i]); + startSubstituter(*i, run); + + *run.to << "have\n" << path << "\n" << std::flush; + + string s; + + int res; + getline(*run.from, s); + if (!string2Int(s, res)) abort(); + + if (res) return true; + } + + return false; +} + + +bool LocalStore::querySubstitutablePathInfo(const Path & path, + SubstitutablePathInfo & info) +{ + foreach (Paths::iterator, i, substituters) { + RunningSubstituter & run(runningSubstituters[*i]); + startSubstituter(*i, run); + + *run.to << "info\n" << path << "\n" << std::flush; + + string s; + + int res; + getline(*run.from, s); + if (!string2Int(s, res)) abort(); + + if (res) { + getline(*run.from, info.deriver); + int nrRefs; + getline(*run.from, s); + if (!string2Int(s, nrRefs)) abort(); + while (nrRefs--) { + Path p; getline(*run.from, p); + info.references.insert(p); + } + info.downloadSize = 0; + return true; + } + } + + return false; } |