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>
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    typedef enum {ecBusy, ecSuccess, ecFailed} ExitCode;
 | 
			
		||||
    typedef enum {ecBusy, ecSuccess, ecFailed, ecNoSubstituters} ExitCode;
 | 
			
		||||
    
 | 
			
		||||
protected:
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -111,6 +111,10 @@ protected:
 | 
			
		|||
    /* Number of goals we are/were waiting for that have failed. */
 | 
			
		||||
    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. */
 | 
			
		||||
    string name;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -119,7 +123,7 @@ protected:
 | 
			
		|||
 | 
			
		||||
    Goal(Worker & worker) : worker(worker)
 | 
			
		||||
    {
 | 
			
		||||
        nrFailed = 0;
 | 
			
		||||
        nrFailed = nrNoSubstituters = 0;
 | 
			
		||||
        exitCode = ecBusy;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -306,7 +310,9 @@ void Goal::waiteeDone(GoalPtr waitee, ExitCode result)
 | 
			
		|||
    trace(format("waitee `%1%' done; %2% left") %
 | 
			
		||||
        waitee->name % waitees.size());
 | 
			
		||||
    
 | 
			
		||||
    if (result == ecFailed) ++nrFailed;
 | 
			
		||||
    if (result == ecFailed || result == ecNoSubstituters) ++nrFailed;
 | 
			
		||||
 | 
			
		||||
    if (result == ecNoSubstituters) ++nrNoSubstituters;
 | 
			
		||||
    
 | 
			
		||||
    if (waitees.empty() || (result == ecFailed && !keepGoing)) {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -330,7 +336,7 @@ void Goal::amDone(ExitCode result)
 | 
			
		|||
{
 | 
			
		||||
    trace("done");
 | 
			
		||||
    assert(exitCode == ecBusy);
 | 
			
		||||
    assert(result == ecSuccess || result == ecFailed);
 | 
			
		||||
    assert(result == ecSuccess || result == ecFailed || result == ecNoSubstituters);
 | 
			
		||||
    exitCode = result;
 | 
			
		||||
    foreach (WeakGoals::iterator, i, waiters) {
 | 
			
		||||
        GoalPtr goal = i->lock();
 | 
			
		||||
| 
						 | 
				
			
			@ -736,6 +742,8 @@ HookInstance::~HookInstance()
 | 
			
		|||
 | 
			
		||||
typedef enum {rpAccept, rpDecline, rpPostpone} HookReply;
 | 
			
		||||
 | 
			
		||||
class SubstitutionGoal;
 | 
			
		||||
 | 
			
		||||
class DerivationGoal : public Goal
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
| 
						 | 
				
			
			@ -985,10 +993,8 @@ void DerivationGoal::haveDerivation()
 | 
			
		|||
    /* We are first going to try to create the invalid output paths
 | 
			
		||||
       through substitutes.  If that doesn't work, we'll build
 | 
			
		||||
       them. */
 | 
			
		||||
    foreach (PathSet::iterator, i, invalidOutputs)
 | 
			
		||||
        /* Don't bother creating a substitution goal if there are no
 | 
			
		||||
           substitutes. */
 | 
			
		||||
        if (queryBoolSetting("build-use-substitutes", true) && worker.store.hasSubstitutes(*i))
 | 
			
		||||
    if (queryBoolSetting("build-use-substitutes", true))
 | 
			
		||||
        foreach (PathSet::iterator, i, invalidOutputs)
 | 
			
		||||
            addWaitee(worker.makeSubstitutionGoal(*i));
 | 
			
		||||
    
 | 
			
		||||
    if (waitees.empty()) /* to prevent hang (no wake-up event) */
 | 
			
		||||
| 
						 | 
				
			
			@ -1002,10 +1008,10 @@ void DerivationGoal::outputsSubstituted()
 | 
			
		|||
{
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
    nrFailed = 0;
 | 
			
		||||
    nrFailed = nrNoSubstituters = 0;
 | 
			
		||||
 | 
			
		||||
    if (checkPathValidity(false).size() == 0) {
 | 
			
		||||
        amDone(ecSuccess);
 | 
			
		||||
| 
						 | 
				
			
			@ -2241,6 +2247,9 @@ private:
 | 
			
		|||
    /* 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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2282,6 +2291,7 @@ public:
 | 
			
		|||
 | 
			
		||||
SubstitutionGoal::SubstitutionGoal(const Path & storePath, Worker & worker)
 | 
			
		||||
    : Goal(worker)
 | 
			
		||||
    , hasSubstitute(false)
 | 
			
		||||
{
 | 
			
		||||
    this->storePath = storePath;
 | 
			
		||||
    state = &SubstitutionGoal::init;
 | 
			
		||||
| 
						 | 
				
			
			@ -2345,7 +2355,10 @@ void SubstitutionGoal::tryNext()
 | 
			
		|||
        /* 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);
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2358,6 +2371,7 @@ void SubstitutionGoal::tryNext()
 | 
			
		|||
    SubstitutablePathInfos::iterator k = infos.find(storePath);
 | 
			
		||||
    if (k == infos.end()) { tryNext(); return; }
 | 
			
		||||
    info = k->second;
 | 
			
		||||
    hasSubstitute = true;
 | 
			
		||||
 | 
			
		||||
    /* To maintain the closure invariant, we first have to realise the
 | 
			
		||||
       paths referenced by this one. */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue