aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/build/derivation-goal.cc
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2023-02-14 13:25:55 -0500
committerJohn Ericson <John.Ericson@Obsidian.Systems>2023-04-15 11:01:31 -0400
commit0f2b5146c79895ac10362b6da56b535fc3d963a4 (patch)
treeb9739b8b5a999a1c819c75bc1e5c6009441d1786 /src/libstore/build/derivation-goal.cc
parent37fca662b0acef3c104a159709a394832e297dda (diff)
Make restarting state machines explicit
If my memory is correct, @edolstra objected to modifying `wantedOutputs` upon falling back to doing a build (as we did before), because we should only modify it in response to new requests --- *actual* wants --- and not because we are "incidentally" building all the outptus beyond what may have been requested. That's a fair point, and the alternative is to replace the boolean soup with proper enums: Instead of modifying `wantedOuputs` som more, we'll modify `needsRestart` to indicate we are passed the need.
Diffstat (limited to 'src/libstore/build/derivation-goal.cc')
-rw-r--r--src/libstore/build/derivation-goal.cc49
1 files changed, 39 insertions, 10 deletions
diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc
index 606f9fd48..5bb664bff 100644
--- a/src/libstore/build/derivation-goal.cc
+++ b/src/libstore/build/derivation-goal.cc
@@ -145,8 +145,20 @@ void DerivationGoal::work()
void DerivationGoal::addWantedOutputs(const OutputsSpec & outputs)
{
auto newWanted = wantedOutputs.union_(outputs);
- if (!newWanted.isSubsetOf(wantedOutputs))
- needRestart = true;
+ switch (needRestart) {
+ case NeedRestartForMoreOutputs::OutputsUnmodifedDontNeed:
+ if (!newWanted.isSubsetOf(wantedOutputs))
+ needRestart = NeedRestartForMoreOutputs::OutputsAddedDoNeed;
+ break;
+ case NeedRestartForMoreOutputs::OutputsAddedDoNeed:
+ /* No need to check whether we added more outputs, because a
+ restart is already queued up. */
+ break;
+ case NeedRestartForMoreOutputs::BuildInProgressWillNotNeed:
+ /* We are already building all outputs, so it doesn't matter if
+ we now want more. */
+ break;
+ };
wantedOutputs = newWanted;
}
@@ -297,12 +309,29 @@ void DerivationGoal::outputsSubstitutionTried()
In particular, it may be the case that the hole in the closure is
an output of the current derivation, which causes a loop if retried.
*/
- if (nrIncompleteClosure > 0 && nrIncompleteClosure == nrFailed) retrySubstitution = true;
+ {
+ bool substitutionFailed =
+ nrIncompleteClosure > 0 &&
+ nrIncompleteClosure == nrFailed;
+ switch (retrySubstitution) {
+ case RetrySubstitution::NoNeed:
+ if (substitutionFailed)
+ retrySubstitution = RetrySubstitution::YesNeed;
+ break;
+ case RetrySubstitution::YesNeed:
+ // Should not be able to reach this state from here.
+ assert(false);
+ break;
+ case RetrySubstitution::AlreadyRetried:
+ debug("substitution failed again, but we already retried once. Not retrying again.");
+ break;
+ }
+ }
nrFailed = nrNoSubstituters = nrIncompleteClosure = 0;
- if (needRestart) {
- needRestart = false;
+ if (needRestart == NeedRestartForMoreOutputs::OutputsAddedDoNeed) {
+ needRestart = NeedRestartForMoreOutputs::OutputsUnmodifedDontNeed;
haveDerivation();
return;
}
@@ -330,9 +359,9 @@ void DerivationGoal::outputsSubstitutionTried()
produced using a substitute. So we have to build instead. */
void DerivationGoal::gaveUpOnSubstitution()
{
- /* Make sure checkPathValidity() from now on checks all
- outputs. */
- wantedOutputs = OutputsSpec::All { };
+ /* At this point we are building all outputs, so if more are wanted there
+ is no need to restart. */
+ needRestart = NeedRestartForMoreOutputs::BuildInProgressWillNotNeed;
/* The inputs must be built before we can build this goal. */
inputDrvOutputs.clear();
@@ -455,8 +484,8 @@ void DerivationGoal::inputsRealised()
return;
}
- if (retrySubstitution && !retriedSubstitution) {
- retriedSubstitution = true;
+ if (retrySubstitution == RetrySubstitution::YesNeed) {
+ retrySubstitution = RetrySubstitution::AlreadyRetried;
haveDerivation();
return;
}