summary refs log tree commit diff
path: root/nix/libstore
diff options
context:
space:
mode:
Diffstat (limited to 'nix/libstore')
-rw-r--r--nix/libstore/build.cc52
-rw-r--r--nix/libstore/globals.hh5
-rw-r--r--nix/libstore/local-store.cc97
-rw-r--r--nix/libstore/local-store.hh12
4 files changed, 78 insertions, 88 deletions
diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc
index 9f1f88933a..ad53b81413 100644
--- a/nix/libstore/build.cc
+++ b/nix/libstore/build.cc
@@ -2863,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;
 
@@ -2897,6 +2888,8 @@ private:
     typedef void (SubstitutionGoal::*GoalState)();
     GoalState state;
 
+    void tryNext();
+
 public:
     SubstitutionGoal(const Path & storePath, Worker & worker, bool repair = false);
     ~SubstitutionGoal();
@@ -2914,7 +2907,6 @@ public:
 
     /* The states. */
     void init();
-    void tryNext();
     void gotInfo();
     void referencesValid();
     void tryToRun();
@@ -2930,7 +2922,6 @@ public:
 
 SubstitutionGoal::SubstitutionGoal(const Path & storePath, Worker & worker, bool repair)
     : Goal(worker)
-    , hasSubstitute(false)
     , repair(repair)
 {
     this->storePath = storePath;
@@ -2980,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. */
@@ -3098,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);
@@ -3111,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);
@@ -3126,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);
 }
 
 
@@ -3192,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/globals.hh b/nix/libstore/globals.hh
index 0d9315a41a..0069c85956 100644
--- a/nix/libstore/globals.hh
+++ b/nix/libstore/globals.hh
@@ -115,11 +115,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 951c35faf3..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);
     }
 }
 
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);