build.cc: Don't use hasSubstitute()
Instead make a single call to querySubstitutablePathInfo() per derivation output. This is faster and prevents having to implement the "have" function in the binary cache substituter.
This commit is contained in:
parent
400e556b34
commit
425cc612ad
1 changed files with 25 additions and 11 deletions
|
@ -94,7 +94,7 @@ typedef map<Path, WeakGoalPtr> WeakGoalMap;
|
||||||
class Goal : public boost::enable_shared_from_this<Goal>
|
class Goal : public boost::enable_shared_from_this<Goal>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef enum {ecBusy, ecSuccess, ecFailed} ExitCode;
|
typedef enum {ecBusy, ecSuccess, ecFailed, ecNoSubstituters} ExitCode;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -111,6 +111,10 @@ protected:
|
||||||
/* Number of goals we are/were waiting for that have failed. */
|
/* Number of goals we are/were waiting for that have failed. */
|
||||||
unsigned int nrFailed;
|
unsigned int nrFailed;
|
||||||
|
|
||||||
|
/* Number of substitution goals we are/were waiting for that
|
||||||
|
failed because there are no substituters. */
|
||||||
|
unsigned int nrNoSubstituters;
|
||||||
|
|
||||||
/* Name of this goal for debugging purposes. */
|
/* Name of this goal for debugging purposes. */
|
||||||
string name;
|
string name;
|
||||||
|
|
||||||
|
@ -119,7 +123,7 @@ protected:
|
||||||
|
|
||||||
Goal(Worker & worker) : worker(worker)
|
Goal(Worker & worker) : worker(worker)
|
||||||
{
|
{
|
||||||
nrFailed = 0;
|
nrFailed = nrNoSubstituters = 0;
|
||||||
exitCode = ecBusy;
|
exitCode = ecBusy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +310,9 @@ void Goal::waiteeDone(GoalPtr waitee, ExitCode result)
|
||||||
trace(format("waitee `%1%' done; %2% left") %
|
trace(format("waitee `%1%' done; %2% left") %
|
||||||
waitee->name % waitees.size());
|
waitee->name % waitees.size());
|
||||||
|
|
||||||
if (result == ecFailed) ++nrFailed;
|
if (result == ecFailed || result == ecNoSubstituters) ++nrFailed;
|
||||||
|
|
||||||
|
if (result == ecNoSubstituters) ++nrNoSubstituters;
|
||||||
|
|
||||||
if (waitees.empty() || (result == ecFailed && !keepGoing)) {
|
if (waitees.empty() || (result == ecFailed && !keepGoing)) {
|
||||||
|
|
||||||
|
@ -330,7 +336,7 @@ void Goal::amDone(ExitCode result)
|
||||||
{
|
{
|
||||||
trace("done");
|
trace("done");
|
||||||
assert(exitCode == ecBusy);
|
assert(exitCode == ecBusy);
|
||||||
assert(result == ecSuccess || result == ecFailed);
|
assert(result == ecSuccess || result == ecFailed || result == ecNoSubstituters);
|
||||||
exitCode = result;
|
exitCode = result;
|
||||||
foreach (WeakGoals::iterator, i, waiters) {
|
foreach (WeakGoals::iterator, i, waiters) {
|
||||||
GoalPtr goal = i->lock();
|
GoalPtr goal = i->lock();
|
||||||
|
@ -736,6 +742,8 @@ HookInstance::~HookInstance()
|
||||||
|
|
||||||
typedef enum {rpAccept, rpDecline, rpPostpone} HookReply;
|
typedef enum {rpAccept, rpDecline, rpPostpone} HookReply;
|
||||||
|
|
||||||
|
class SubstitutionGoal;
|
||||||
|
|
||||||
class DerivationGoal : public Goal
|
class DerivationGoal : public Goal
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -985,10 +993,8 @@ void DerivationGoal::haveDerivation()
|
||||||
/* We are first going to try to create the invalid output paths
|
/* We are first going to try to create the invalid output paths
|
||||||
through substitutes. If that doesn't work, we'll build
|
through substitutes. If that doesn't work, we'll build
|
||||||
them. */
|
them. */
|
||||||
foreach (PathSet::iterator, i, invalidOutputs)
|
if (queryBoolSetting("build-use-substitutes", true))
|
||||||
/* Don't bother creating a substitution goal if there are no
|
foreach (PathSet::iterator, i, invalidOutputs)
|
||||||
substitutes. */
|
|
||||||
if (queryBoolSetting("build-use-substitutes", true) && worker.store.hasSubstitutes(*i))
|
|
||||||
addWaitee(worker.makeSubstitutionGoal(*i));
|
addWaitee(worker.makeSubstitutionGoal(*i));
|
||||||
|
|
||||||
if (waitees.empty()) /* to prevent hang (no wake-up event) */
|
if (waitees.empty()) /* to prevent hang (no wake-up event) */
|
||||||
|
@ -1002,10 +1008,10 @@ void DerivationGoal::outputsSubstituted()
|
||||||
{
|
{
|
||||||
trace("all outputs substituted (maybe)");
|
trace("all outputs substituted (maybe)");
|
||||||
|
|
||||||
if (nrFailed > 0 && !tryFallback)
|
if (nrFailed > 0 && nrFailed > nrNoSubstituters && !tryFallback)
|
||||||
throw Error(format("some substitutes for the outputs of derivation `%1%' failed; try `--fallback'") % drvPath);
|
throw Error(format("some substitutes for the outputs of derivation `%1%' failed; try `--fallback'") % drvPath);
|
||||||
|
|
||||||
nrFailed = 0;
|
nrFailed = nrNoSubstituters = 0;
|
||||||
|
|
||||||
if (checkPathValidity(false).size() == 0) {
|
if (checkPathValidity(false).size() == 0) {
|
||||||
amDone(ecSuccess);
|
amDone(ecSuccess);
|
||||||
|
@ -2241,6 +2247,9 @@ private:
|
||||||
/* The current substituter. */
|
/* The current substituter. */
|
||||||
Path sub;
|
Path sub;
|
||||||
|
|
||||||
|
/* Whether any substituter can realise this path */
|
||||||
|
bool hasSubstitute;
|
||||||
|
|
||||||
/* Path info returned by the substituter's query info operation. */
|
/* Path info returned by the substituter's query info operation. */
|
||||||
SubstitutablePathInfo info;
|
SubstitutablePathInfo info;
|
||||||
|
|
||||||
|
@ -2282,6 +2291,7 @@ public:
|
||||||
|
|
||||||
SubstitutionGoal::SubstitutionGoal(const Path & storePath, Worker & worker)
|
SubstitutionGoal::SubstitutionGoal(const Path & storePath, Worker & worker)
|
||||||
: Goal(worker)
|
: Goal(worker)
|
||||||
|
, hasSubstitute(false)
|
||||||
{
|
{
|
||||||
this->storePath = storePath;
|
this->storePath = storePath;
|
||||||
state = &SubstitutionGoal::init;
|
state = &SubstitutionGoal::init;
|
||||||
|
@ -2345,7 +2355,10 @@ void SubstitutionGoal::tryNext()
|
||||||
/* None left. Terminate this goal and let someone else deal
|
/* None left. Terminate this goal and let someone else deal
|
||||||
with it. */
|
with it. */
|
||||||
debug(format("path `%1%' is required, but there is no substituter that can build it") % storePath);
|
debug(format("path `%1%' is required, but there is no substituter that can build it") % storePath);
|
||||||
amDone(ecFailed);
|
/* 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2358,6 +2371,7 @@ void SubstitutionGoal::tryNext()
|
||||||
SubstitutablePathInfos::iterator k = infos.find(storePath);
|
SubstitutablePathInfos::iterator k = infos.find(storePath);
|
||||||
if (k == infos.end()) { tryNext(); return; }
|
if (k == infos.end()) { tryNext(); return; }
|
||||||
info = k->second;
|
info = k->second;
|
||||||
|
hasSubstitute = true;
|
||||||
|
|
||||||
/* To maintain the closure invariant, we first have to realise the
|
/* To maintain the closure invariant, we first have to realise the
|
||||||
paths referenced by this one. */
|
paths referenced by this one. */
|
||||||
|
|
Loading…
Reference in a new issue