aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/local-store.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2008-08-02 12:54:35 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2008-08-02 12:54:35 +0000
commit3c92ea399d717dc45b3fa91424c0dadc0239ebf2 (patch)
tree7cde9f533a6ee575615da5452e04c05dc0939f02 /src/libstore/local-store.cc
parentfc691e1cbdcddb8c553cba06d4089bc1b60e3d98 (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.cc117
1 files changed, 97 insertions, 20 deletions
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index d886ba558..6926c4937 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;
}