aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/skyframe/AbstractParallelEvaluator.java
diff options
context:
space:
mode:
authorGravatar janakr <janakr@google.com>2018-04-30 16:18:50 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-04-30 16:19:58 -0700
commit46706aef724c69016d9eae914cbe7a96349442c2 (patch)
treefdf8821a7077f4c973d0806bcbf21fdba9e4f158 /src/main/java/com/google/devtools/build/skyframe/AbstractParallelEvaluator.java
parentb9f8627289294407ef93efda894ce138f1881a38 (diff)
Allow SkyFunctions to return a sentinel value indicating that all of a node's in-progress data should be forgotten, and its evaluation should be restarted from scratch, as if it were freshly created/dirtied. To guard against this happening unexpectedly, any such events are passed to a GraphInconsistencyReceiver, which can verify that the SkyFunction is behaving properly.
This is the first change in a series to permit action rewinding when it is discovered that a previously generated input file is no longer available. When an action detects that one of its inputs is unusable, it can return this sentinel value, causing it to be re-evaluated from scratch. Follow-up changes will make the node corresponding to the input, and the node corresponding to the action that generated the input, dirty when this happens, causing the upstream action to be re-run, regenerating the desired input. Currently works for builds that do not keep edges, although follow-ups may make this possible for all builds. PiperOrigin-RevId: 194863097
Diffstat (limited to 'src/main/java/com/google/devtools/build/skyframe/AbstractParallelEvaluator.java')
-rw-r--r--src/main/java/com/google/devtools/build/skyframe/AbstractParallelEvaluator.java28
1 files changed, 28 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/skyframe/AbstractParallelEvaluator.java b/src/main/java/com/google/devtools/build/skyframe/AbstractParallelEvaluator.java
index 6ed51ad3f8..40ed157180 100644
--- a/src/main/java/com/google/devtools/build/skyframe/AbstractParallelEvaluator.java
+++ b/src/main/java/com/google/devtools/build/skyframe/AbstractParallelEvaluator.java
@@ -70,6 +70,7 @@ public abstract class AbstractParallelEvaluator {
boolean keepGoing,
int threadCount,
DirtyTrackingProgressReceiver progressReceiver,
+ GraphInconsistencyReceiver graphInconsistencyReceiver,
CycleDetector cycleDetector) {
this.graph = graph;
this.cycleDetector = cycleDetector;
@@ -85,6 +86,7 @@ public abstract class AbstractParallelEvaluator {
storedEventFilter,
errorInfoManager,
Evaluate::new,
+ graphInconsistencyReceiver,
threadCount);
}
@@ -98,6 +100,7 @@ public abstract class AbstractParallelEvaluator {
ErrorInfoManager errorInfoManager,
boolean keepGoing,
DirtyTrackingProgressReceiver progressReceiver,
+ GraphInconsistencyReceiver graphInconsistencyReceiver,
ForkJoinPool forkJoinPool,
CycleDetector cycleDetector) {
this.graph = graph;
@@ -114,6 +117,7 @@ public abstract class AbstractParallelEvaluator {
storedEventFilter,
errorInfoManager,
Evaluate::new,
+ graphInconsistencyReceiver,
Preconditions.checkNotNull(forkJoinPool));
}
@@ -442,6 +446,11 @@ public abstract class AbstractParallelEvaluator {
env.doneBuilding();
}
+ if (maybeEraseNodeToRestartFromScratch(skyKey, state, value)) {
+ evaluatorContext.getVisitor().enqueueEvaluation(skyKey);
+ return;
+ }
+
// Helper objects for all the newly requested deps that weren't known to the environment,
// and may contain duplicate elements.
GroupedListHelper<SkyKey> newDirectDeps = env.getNewlyRequestedDeps();
@@ -601,6 +610,25 @@ public abstract class AbstractParallelEvaluator {
private static final int MAX_REVERSEDEP_DUMP_LENGTH = 1000;
}
+ private boolean maybeEraseNodeToRestartFromScratch(
+ SkyKey key, NodeEntry entry, SkyValue returnedValue) {
+ if (!SkyFunction.SENTINEL_FOR_RESTART_FROM_SCRATCH.equals(returnedValue)) {
+ return false;
+ }
+ evaluatorContext
+ .getGraphInconsistencyReceiver()
+ .noteInconsistencyAndMaybeThrow(
+ key, /*otherKey=*/ null, GraphInconsistencyReceiver.Inconsistency.RESET_REQUESTED);
+ entry.resetForRestartFromScratch();
+ // TODO(mschaller): rdeps of children have to be handled here. If the graph does not keep edges,
+ // nothing has to be done, since there are no reverse deps to keep consistent. If the graph
+ // keeps edges, it's a harder problem. The reverse deps could just be removed, but in the case
+ // that this node is dirty, the deps shouldn't be removed, they should just be transformed back
+ // to "known reverse deps" from "reverse deps declared during this evaluation" (the inverse of
+ // NodeEntry#checkIfDoneForDirtyReverseDep). Such a method doesn't currently exist, but could.
+ return true;
+ }
+
void propagateEvaluatorContextCrashIfAny() {
if (!evaluatorContext.getVisitor().getCrashes().isEmpty()) {
evaluatorContext