about summary refs log tree commit diff
path: root/src/libstore/local-store.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2008-08-02T12·54+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2008-08-02T12·54+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 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;
 }