Replace `EvaluationVersionBehavior` with a method `NodeEntry#getMaxTransitiveSourceVersion`.
Both the graph version and the max transitive source version (if present) are provided to node entries in `setValue`. Nodes can choose which to use.
PiperOrigin-RevId: 414266059
diff --git a/src/main/java/com/google/devtools/build/skyframe/AbstractExceptionalParallelEvaluator.java b/src/main/java/com/google/devtools/build/skyframe/AbstractExceptionalParallelEvaluator.java
index 912fef9..4623cf5 100644
--- a/src/main/java/com/google/devtools/build/skyframe/AbstractExceptionalParallelEvaluator.java
+++ b/src/main/java/com/google/devtools/build/skyframe/AbstractExceptionalParallelEvaluator.java
@@ -95,7 +95,6 @@
GraphInconsistencyReceiver graphInconsistencyReceiver,
Supplier<ExecutorService> executorService,
CycleDetector cycleDetector,
- EvaluationVersionBehavior evaluationVersionBehavior,
int cpuHeavySkyKeysThreadPoolSize,
int executionJobsThreadPoolSize) {
super(
@@ -111,7 +110,6 @@
graphInconsistencyReceiver,
executorService,
cycleDetector,
- evaluationVersionBehavior,
cpuHeavySkyKeysThreadPoolSize,
executionJobsThreadPoolSize);
}
@@ -690,7 +688,7 @@
prevEntry.noDepsLastBuild(), "existing entry for %s has deps: %s", key, prevEntry);
}
prevEntry.markRebuilding();
- prevEntry.setValue(value, version);
+ prevEntry.setValue(value, version, /*maxTransitiveSourceVersion=*/ null);
// Now that this key's injected value is set, it is no longer dirty.
progressReceiver.injected(key);
}
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 fb2b1ad..4faad8b 100644
--- a/src/main/java/com/google/devtools/build/skyframe/AbstractParallelEvaluator.java
+++ b/src/main/java/com/google/devtools/build/skyframe/AbstractParallelEvaluator.java
@@ -102,8 +102,7 @@
DirtyTrackingProgressReceiver progressReceiver,
GraphInconsistencyReceiver graphInconsistencyReceiver,
Supplier<ExecutorService> executorService,
- CycleDetector cycleDetector,
- EvaluationVersionBehavior evaluationVersionBehavior) {
+ CycleDetector cycleDetector) {
this(
graph,
graphVersion,
@@ -117,7 +116,6 @@
graphInconsistencyReceiver,
executorService,
cycleDetector,
- evaluationVersionBehavior,
/*cpuHeavySkyKeysThreadPoolSize=*/ 0,
/*executionJobsThreadPoolSize=*/ 0);
}
@@ -135,7 +133,6 @@
GraphInconsistencyReceiver graphInconsistencyReceiver,
Supplier<ExecutorService> executorService,
CycleDetector cycleDetector,
- EvaluationVersionBehavior evaluationVersionBehavior,
int cpuHeavySkyKeysThreadPoolSize,
int executionJobsThreadPoolSize) {
this.graph = graph;
@@ -158,7 +155,6 @@
() ->
new NodeEntryVisitor(
quiescingExecutorSupplier.get(), progressReceiver, Evaluate::new),
- evaluationVersionBehavior,
/*mergingSkyframeAnalysisExecutionPhases=*/ executionJobsThreadPoolSize > 0);
}
diff --git a/src/main/java/com/google/devtools/build/skyframe/DelegatingNodeEntry.java b/src/main/java/com/google/devtools/build/skyframe/DelegatingNodeEntry.java
index d040549..3adda55 100644
--- a/src/main/java/com/google/devtools/build/skyframe/DelegatingNodeEntry.java
+++ b/src/main/java/com/google/devtools/build/skyframe/DelegatingNodeEntry.java
@@ -55,8 +55,10 @@
}
@Override
- public Set<SkyKey> setValue(SkyValue value, Version version) throws InterruptedException {
- return getDelegate().setValue(value, version);
+ public Set<SkyKey> setValue(
+ SkyValue value, Version graphVersion, @Nullable Version maxTransitiveSourceVersion)
+ throws InterruptedException {
+ return getDelegate().setValue(value, graphVersion, maxTransitiveSourceVersion);
}
@Override
@@ -92,6 +94,11 @@
}
@Override
+ public Version getMaxTransitiveSourceVersion() {
+ return getDelegate().getMaxTransitiveSourceVersion();
+ }
+
+ @Override
public DirtyState getDirtyState() {
return getDelegate().getDirtyState();
}
diff --git a/src/main/java/com/google/devtools/build/skyframe/EvaluationVersionBehavior.java b/src/main/java/com/google/devtools/build/skyframe/EvaluationVersionBehavior.java
deleted file mode 100644
index a4cc371..0000000
--- a/src/main/java/com/google/devtools/build/skyframe/EvaluationVersionBehavior.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2018 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.devtools.build.skyframe;
-
-/**
- * What version to give an evaluated node: the max of its child versions or the graph version. Even
- * for {@link #MAX_CHILD_VERSIONS} the version may still be the graph version depending on
- * properties of the {@link SkyFunction} (if it is {@link FunctionHermeticity#NONHERMETIC}) or the
- * error state of the node.
- *
- * <p>Should be set to {@link #MAX_CHILD_VERSIONS} unless the evaluation framework is being very
- * sneaky.
- */
-public enum EvaluationVersionBehavior {
- MAX_CHILD_VERSIONS,
- GRAPH_VERSION
-}
diff --git a/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java b/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java
index 9f507fb..b471603 100644
--- a/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java
+++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java
@@ -208,7 +208,6 @@
AbstractQueueVisitor.createExecutorService(
evaluationContext.getParallelism(), "skyframe-evaluator")),
new SimpleCycleDetector(),
- EvaluationVersionBehavior.GRAPH_VERSION,
evaluationContext.getCPUHeavySkyKeysThreadPoolSize(),
evaluationContext.getExecutionPhaseThreadPoolSize());
result = evaluator.eval(roots);
diff --git a/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java b/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java
index 38dc272..7084da7 100644
--- a/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java
+++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java
@@ -13,6 +13,8 @@
// limitations under the License.
package com.google.devtools.build.skyframe;
+import static com.google.common.base.MoreObjects.firstNonNull;
+
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -276,9 +278,11 @@
* version and the value.
*/
@Override
- public synchronized Set<SkyKey> setValue(SkyValue value, Version version)
+ public synchronized Set<SkyKey> setValue(
+ SkyValue value, Version graphVersion, @Nullable Version maxTransitiveSourceVersion)
throws InterruptedException {
Preconditions.checkState(isReady(), "Not ready (this=%s, value=%s)", this, value);
+ Version version = firstNonNull(maxTransitiveSourceVersion, graphVersion);
Preconditions.checkState(
this.lastChangedVersion.atMost(version) && this.lastEvaluatedVersion.atMost(version),
"Bad version (this=%s, version=%s, value=%s)",
@@ -300,29 +304,6 @@
return setStateFinishedAndReturnReverseDepsToSignal();
}
- /** An exception indicating that the node's value changed but its version did not. */
- public static final class ChangedValueAtSameVersionException extends IllegalStateException {
- private final SkyValue newValue;
-
- private ChangedValueAtSameVersionException(
- Version lastChangedVersion,
- Version newVersion,
- SkyValue newValue,
- InMemoryNodeEntry nodeEntry) {
- super(
- String.format(
- "Changed value but with the same version? "
- + "lastChangedVersion: %s, newVersion: %s newValue: %s, nodeEntry: %s",
- lastChangedVersion, newVersion, newValue, nodeEntry));
- this.newValue = newValue;
- }
-
- /** Returns the value that this node changed to. */
- public SkyValue getNewValue() {
- return newValue;
- }
- }
-
@Override
public DependencyState addReverseDepAndCheckIfDone(SkyKey reverseDep) {
if ((reverseDep == null || !keepReverseDeps()) && isDone()) {
diff --git a/src/main/java/com/google/devtools/build/skyframe/NodeEntry.java b/src/main/java/com/google/devtools/build/skyframe/NodeEntry.java
index afabf8d..9a87cf0 100644
--- a/src/main/java/com/google/devtools/build/skyframe/NodeEntry.java
+++ b/src/main/java/com/google/devtools/build/skyframe/NodeEntry.java
@@ -48,10 +48,10 @@
NEEDS_SCHEDULING,
/**
- * The node was already created, but isn't done yet. The evaluator is responsible for
- * signaling the reverse dependency node.
+ * The node was already created, but isn't done yet. The evaluator is responsible for signaling
+ * the reverse dependency node.
*/
- ALREADY_EVALUATING;
+ ALREADY_EVALUATING
}
/**
@@ -193,13 +193,24 @@
* reverse dependencies that are registered at the time of the {@code setValue} call. If b comes
* in before a, it is signaled (and re-scheduled) by a, otherwise it needs to do that itself.
*
- * <p>{@code version} indicates the graph version at which this node is being written. If the
- * entry determines that the new value is equal to the previous value, the entry will keep its
- * current version. Callers can query that version to see if the node considers its value to have
- * changed.
+ * <p>Nodes may elect to use either {@code graphVersion} or {@code maxTransitiveSourceVersion} (if
+ * not {@code null}) for their {@linkplain #getVersion version}. The choice can be distinguished
+ * by calling {@link #getMaxTransitiveSourceVersion} - a return of {@code null} indicates that the
+ * node uses the graph version.
+ *
+ * <p>If the entry determines that the new value is equal to the previous value, the entry may
+ * keep its current version. Callers can query that version to see if the node considers its value
+ * to have changed.
+ *
+ * @param value the new value of this node
+ * @param graphVersion the version of the graph at which this node is being written
+ * @param maxTransitiveSourceVersion the maximal version of this node's dependencies from source,
+ * or {@code null} if source versions are not being tracked
*/
@ThreadSafe
- Set<SkyKey> setValue(SkyValue value, Version version) throws InterruptedException;
+ Set<SkyKey> setValue(
+ SkyValue value, Version graphVersion, @Nullable Version maxTransitiveSourceVersion)
+ throws InterruptedException;
/**
* Queries if the node is done and adds the given key as a reverse dependency. The return code
@@ -303,13 +314,24 @@
@ThreadSafe
void forceRebuild();
- /**
- * Gets the current version of this entry.
- */
+ /** Returns the current version of this node. */
@ThreadSafe
Version getVersion();
/**
+ * Returns the maximal version of this node's dependencies from source.
+ *
+ * <p>This version should only be tracked when non-hermetic functions {@linkplain
+ * SkyFunction.Environment#injectVersionForNonHermeticFunction inject} source versions. Otherwise,
+ * returns {@code null} to signal that source versions are not being tracked.
+ */
+ @ThreadSafe
+ @Nullable
+ default Version getMaxTransitiveSourceVersion() {
+ return null;
+ }
+
+ /**
* Gets the current state of checking this dirty entry to see if it must be re-evaluated. Must be
* called each time evaluation of a dirty entry starts to find the proper action to perform next,
* as enumerated by {@link NodeEntry.DirtyState}.
diff --git a/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java b/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java
index b849010..7cd5e20 100644
--- a/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java
+++ b/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java
@@ -49,8 +49,7 @@
DirtyTrackingProgressReceiver progressReceiver,
GraphInconsistencyReceiver graphInconsistencyReceiver,
Supplier<ExecutorService> executorService,
- CycleDetector cycleDetector,
- EvaluationVersionBehavior evaluationVersionBehavior) {
+ CycleDetector cycleDetector) {
this(
graph,
graphVersion,
@@ -64,7 +63,6 @@
graphInconsistencyReceiver,
executorService,
cycleDetector,
- evaluationVersionBehavior,
/*cpuHeavySkyKeysThreadPoolSize=*/ 0,
/*executionJobsThreadPoolSize=*/ 0);
}
@@ -82,7 +80,6 @@
GraphInconsistencyReceiver graphInconsistencyReceiver,
Supplier<ExecutorService> executorService,
CycleDetector cycleDetector,
- EvaluationVersionBehavior evaluationVersionBehavior,
int cpuHeavySkyKeysThreadPoolSize,
int executionJobsThreadPoolSize) {
super(
@@ -98,7 +95,6 @@
graphInconsistencyReceiver,
executorService,
cycleDetector,
- evaluationVersionBehavior,
cpuHeavySkyKeysThreadPoolSize,
executionJobsThreadPoolSize);
}
diff --git a/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluatorContext.java b/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluatorContext.java
index 16e743d..62da390 100644
--- a/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluatorContext.java
+++ b/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluatorContext.java
@@ -46,7 +46,6 @@
private final EventFilter storedEventFilter;
private final ErrorInfoManager errorInfoManager;
private final GraphInconsistencyReceiver graphInconsistencyReceiver;
- private final EvaluationVersionBehavior evaluationVersionBehavior;
private final boolean mergingSkyframeAnalysisExecutionPhases;
/**
@@ -81,14 +80,12 @@
ErrorInfoManager errorInfoManager,
GraphInconsistencyReceiver graphInconsistencyReceiver,
Supplier<NodeEntryVisitor> visitorSupplier,
- EvaluationVersionBehavior evaluationVersionBehavior,
boolean mergingSkyframeAnalysisExecutionPhases) {
this.graph = graph;
this.graphVersion = graphVersion;
this.skyFunctions = skyFunctions;
this.reporter = reporter;
this.graphInconsistencyReceiver = graphInconsistencyReceiver;
- this.evaluationVersionBehavior = evaluationVersionBehavior;
this.replayingNestedSetEventVisitor =
new NestedSetVisitor<>(new NestedSetEventReceiver(reporter), emittedEventState.eventState);
this.replayingNestedSetPostableVisitor =
@@ -189,10 +186,6 @@
return errorInfoManager;
}
- EvaluationVersionBehavior getEvaluationVersionBehavior() {
- return evaluationVersionBehavior;
- }
-
boolean restartPermitted() {
return graphInconsistencyReceiver.restartPermitted();
}
diff --git a/src/main/java/com/google/devtools/build/skyframe/SkyFunction.java b/src/main/java/com/google/devtools/build/skyframe/SkyFunction.java
index 0601925..fc74426 100644
--- a/src/main/java/com/google/devtools/build/skyframe/SkyFunction.java
+++ b/src/main/java/com/google/devtools/build/skyframe/SkyFunction.java
@@ -394,10 +394,11 @@
}
/**
- * Injects non-hermetic {@link Version} information for this environment.
+ * Injects non-hermetic {@link Version} information for the currently evaluating {@link SkyKey}.
*
- * <p>This may be called during the course of {@link SkyFunction#compute(SkyKey, Environment)}
- * if the function discovers version information for the {@link SkyKey}.
+ * <p>This may be called during the course of {@link SkyFunction#compute} if the function
+ * determines that the currently evaluating key's source dependencies have not changed since the
+ * given {@code version}.
*
* <p>Environments that either do not need or wish to ignore non-hermetic version information
* may keep the default no-op implementation.
@@ -410,8 +411,8 @@
* <p>WARNING: Dependencies here MUST be done! Only use this function if you know what you're
* doing.
*
- * <p>If the {@link EvaluationVersionBehavior} is {@link
- * EvaluationVersionBehavior#MAX_CHILD_VERSIONS} then this method must not be called.
+ * <p>If {@linkplain NodeEntry#getMaxTransitiveSourceVersion max transitive source versions} are
+ * being tracked, then this method must not be called.
*/
void registerDependencies(Iterable<SkyKey> keys);
diff --git a/src/main/java/com/google/devtools/build/skyframe/SkyFunctionEnvironment.java b/src/main/java/com/google/devtools/build/skyframe/SkyFunctionEnvironment.java
index 06f735c..0f5d88a 100644
--- a/src/main/java/com/google/devtools/build/skyframe/SkyFunctionEnvironment.java
+++ b/src/main/java/com/google/devtools/build/skyframe/SkyFunctionEnvironment.java
@@ -13,7 +13,6 @@
// limitations under the License.
package com.google.devtools.build.skyframe;
-
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -74,10 +73,7 @@
private SkyValue value = null;
private ErrorInfo errorInfo = null;
- @Nullable private Version maxChildVersion = null;
-
- /** If present, takes precedence over {@link #maxChildVersion}. */
- @Nullable private Version injectedVersion = null;
+ @Nullable private Version maxTransitiveSourceVersion;
/**
* This is not {@code null} only during cycle detection and error bubbling. The nullness of this
@@ -108,8 +104,7 @@
private final Map<SkyKey, SkyValue> newlyRequestedDepsValues = new HashMap<>();
/**
- * Keys of dependencies registered via {@link #registerDependencies} if not using {@link
- * EvaluationVersionBehavior#MAX_CHILD_VERSIONS}.
+ * Keys of dependencies registered via {@link #registerDependencies}.
*
* <p>The {@link #registerDependencies} method is hacky. Deps registered through it may not have
* entries in {@link #newlyRequestedDepsValues}, but they are expected to be done. This set tracks
@@ -203,6 +198,13 @@
this.bubbleErrorInfo = bubbleErrorInfo;
this.oldDeps = Preconditions.checkNotNull(oldDeps);
this.evaluatorContext = Preconditions.checkNotNull(evaluatorContext);
+ // Cycles can lead to a state where the versions of done children don't accurately reflect the
+ // state that led to this node's value. Be conservative then.
+ this.maxTransitiveSourceVersion =
+ bubbleErrorInfo == null
+ && skyKey.functionName().getHermeticity() != FunctionHermeticity.NONHERMETIC
+ ? MinimalVersion.INSTANCE
+ : null;
this.previouslyRequestedDepsValues = batchPrefetch(throwIfPreviouslyRequestedDepsUndone);
Preconditions.checkState(
!this.previouslyRequestedDepsValues.containsKey(ErrorTransienceValue.KEY),
@@ -250,10 +252,10 @@
}
depValuesBuilder.put(entry.getKey(), !depDone ? NULL_MARKER : valueMaybeWithMetadata);
if (depDone) {
- maybeUpdateMaxChildVersion(entry.getValue());
+ maybeUpdateMaxTransitiveSourceVersion(entry.getValue());
}
}
- return depValuesBuilder.build();
+ return depValuesBuilder.buildOrThrow();
}
private void checkActive() {
@@ -338,7 +340,7 @@
triState == DependencyState.DONE, "%s %s %s", skyKey, triState, errorInfo);
state.addTemporaryDirectDeps(GroupedListHelper.create(ErrorTransienceValue.KEY));
state.signalDep(evaluatorContext.getGraphVersion(), ErrorTransienceValue.KEY);
- maxChildVersion = evaluatorContext.getGraphVersion();
+ maxTransitiveSourceVersion = null;
}
this.errorInfo = Preconditions.checkNotNull(errorInfo, skyKey);
@@ -400,7 +402,7 @@
result.put(key, valueOrNullMarker);
newlyRequestedDepsValues.put(key, valueOrNullMarker);
if (valueOrNullMarker != NULL_MARKER) {
- maybeUpdateMaxChildVersion(depEntry);
+ maybeUpdateMaxTransitiveSourceVersion(depEntry);
}
}
return result;
@@ -452,7 +454,7 @@
result.set(i, valueOrNullMarker);
newlyRequestedDepsValues.put(key, valueOrNullMarker);
if (valueOrNullMarker != NULL_MARKER) {
- maybeUpdateMaxChildVersion(depEntry);
+ maybeUpdateMaxTransitiveSourceVersion(depEntry);
}
}
return result;
@@ -535,7 +537,7 @@
Preconditions.checkState(!assertDone, "%s had not done: %s", skyKey, key);
continue;
}
- maybeUpdateMaxChildVersion(depEntry);
+ maybeUpdateMaxTransitiveSourceVersion(depEntry);
result.add(valueOrNullMarker);
}
return result;
@@ -834,33 +836,23 @@
}
}
- Version evaluationVersion = maxChildVersion;
- if (bubbleErrorInfo != null) {
- // Cycles can lead to a state where the versions of done children don't accurately reflect the
- // state that led to this node's value. Be conservative then.
- evaluationVersion = evaluatorContext.getGraphVersion();
- } else if (injectedVersion != null) {
- evaluationVersion = injectedVersion;
- } else if (evaluatorContext.getEvaluationVersionBehavior()
- == EvaluationVersionBehavior.GRAPH_VERSION
- || skyKey.functionName().getHermeticity() == FunctionHermeticity.NONHERMETIC) {
- evaluationVersion = evaluatorContext.getGraphVersion();
- } else if (evaluationVersion == null) {
- Preconditions.checkState(
- temporaryDirectDeps.isEmpty(),
- "No max child version found, but have direct deps: %s %s",
- skyKey,
- primaryEntry);
- evaluationVersion = evaluatorContext.getGraphVersion();
+ if (temporaryDirectDeps.isEmpty()
+ && skyKey.functionName().getHermeticity() != FunctionHermeticity.NONHERMETIC) {
+ maxTransitiveSourceVersion = null; // No dependencies on source.
}
- Version previousVersion = primaryEntry.getVersion();
- // If this entry is dirty, setValue may not actually change it, if it determines that
- // the data being written now is the same as the data already present in the entry.
- Set<SkyKey> reverseDeps = primaryEntry.setValue(valueWithMetadata, evaluationVersion);
+ Preconditions.checkState(
+ maxTransitiveSourceVersion == null || newlyRegisteredDeps.isEmpty(),
+ "Dependency registration not supported when tracking max transitive source versions");
- // Note that if this update didn't actually change the entry, this version may not be
- // evaluationVersion.
+ // If this entry is dirty, setValue may not actually change it, if it determines that the data
+ // being written now is the same as the data already present in the entry. We detect this case
+ // by comparing versions before and after setting the value.
+ Version previousVersion = primaryEntry.getVersion();
+ Set<SkyKey> reverseDeps =
+ primaryEntry.setValue(
+ valueWithMetadata, evaluatorContext.getGraphVersion(), maxTransitiveSourceVersion);
Version currentVersion = primaryEntry.getVersion();
+
// Tell the receiver that this value was built. If currentVersion.equals(evaluationVersion), it
// was evaluated this run, and so was changed. Otherwise, it is less than evaluationVersion, by
// the Preconditions check above, and was not actually changed this run -- when it was written
@@ -904,9 +896,6 @@
@Override
public void registerDependencies(Iterable<SkyKey> keys) {
- Preconditions.checkState(
- evaluatorContext.getEvaluationVersionBehavior() == EvaluationVersionBehavior.GRAPH_VERSION,
- "Dependency registration not supported when tracking max child versions");
newlyRequestedDeps.startGroup();
for (SkyKey key : keys) {
if (!previouslyRequestedDepsValues.containsKey(key)) {
@@ -921,17 +910,30 @@
public void injectVersionForNonHermeticFunction(Version version) {
Preconditions.checkState(
skyKey.functionName().getHermeticity() == FunctionHermeticity.NONHERMETIC, skyKey);
- injectedVersion = version;
+ Preconditions.checkState(
+ maxTransitiveSourceVersion == null,
+ "Multiple injected versions (%s, %s) for %s",
+ maxTransitiveSourceVersion,
+ version,
+ skyKey);
+ Preconditions.checkNotNull(version, skyKey);
+ Preconditions.checkState(
+ version.atMost(evaluatorContext.getGraphVersion()),
+ "Invalid injected version (%s > %s) for %s",
+ version,
+ evaluatorContext.getGraphVersion(),
+ skyKey);
+ maxTransitiveSourceVersion = version;
}
- private void maybeUpdateMaxChildVersion(NodeEntry depEntry) {
- if (skyKey.functionName().getHermeticity() != FunctionHermeticity.NONHERMETIC
- && evaluatorContext.getEvaluationVersionBehavior()
- == EvaluationVersionBehavior.MAX_CHILD_VERSIONS) {
- Version depVersion = depEntry.getVersion();
- if (maxChildVersion == null || maxChildVersion.atMost(depVersion)) {
- maxChildVersion = depVersion;
- }
+ private void maybeUpdateMaxTransitiveSourceVersion(NodeEntry depEntry) {
+ if (maxTransitiveSourceVersion == null
+ || skyKey.functionName().getHermeticity() == FunctionHermeticity.NONHERMETIC) {
+ return;
+ }
+ Version depMtsv = depEntry.getMaxTransitiveSourceVersion();
+ if (depMtsv == null || maxTransitiveSourceVersion.atMost(depMtsv)) {
+ maxTransitiveSourceVersion = depMtsv;
}
}
@@ -948,8 +950,7 @@
.add("newlyRequestedDeps", newlyRequestedDeps)
.add("childErrorInfos", childErrorInfos)
.add("depErrorKey", depErrorKey)
- .add("maxChildVersion", maxChildVersion)
- .add("injectedVersion", injectedVersion)
+ .add("maxTransitiveSourceVersion", maxTransitiveSourceVersion)
.add("bubbleErrorInfo", bubbleErrorInfo)
.add("evaluatorContext", evaluatorContext)
.toString();
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutorTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutorTest.java
index 7766cb3..8a23bd5 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutorTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutorTest.java
@@ -385,7 +385,7 @@
nodeEntry.addReverseDepAndCheckIfDone(null);
nodeEntry.markRebuilding();
try {
- nodeEntry.setValue(value, ignored -> false);
+ nodeEntry.setValue(value, ignored -> false, null);
} catch (InterruptedException e) {
throw new RuntimeException();
}
diff --git a/src/test/java/com/google/devtools/build/skyframe/DeterministicHelper.java b/src/test/java/com/google/devtools/build/skyframe/DeterministicHelper.java
index 0519adc..f9922b9 100644
--- a/src/test/java/com/google/devtools/build/skyframe/DeterministicHelper.java
+++ b/src/test/java/com/google/devtools/build/skyframe/DeterministicHelper.java
@@ -153,9 +153,11 @@
}
@Override
- public Set<SkyKey> setValue(SkyValue value, Version version) throws InterruptedException {
+ public Set<SkyKey> setValue(
+ SkyValue value, Version graphVersion, @Nullable Version maxTransitiveSourceVersion)
+ throws InterruptedException {
TreeSet<SkyKey> result = new TreeSet<>(ALPHABETICAL_SKYKEY_COMPARATOR);
- result.addAll(super.setValue(value, version));
+ result.addAll(super.setValue(value, graphVersion, maxTransitiveSourceVersion));
return result;
}
diff --git a/src/test/java/com/google/devtools/build/skyframe/EagerInvalidatorTest.java b/src/test/java/com/google/devtools/build/skyframe/EagerInvalidatorTest.java
index 9d26f88..c50a1dd 100644
--- a/src/test/java/com/google/devtools/build/skyframe/EagerInvalidatorTest.java
+++ b/src/test/java/com/google/devtools/build/skyframe/EagerInvalidatorTest.java
@@ -145,8 +145,7 @@
new DirtyTrackingProgressReceiver(null),
GraphInconsistencyReceiver.THROWING,
() -> AbstractQueueVisitor.createExecutorService(200, "test-pool"),
- new SimpleCycleDetector(),
- EvaluationVersionBehavior.MAX_CHILD_VERSIONS);
+ new SimpleCycleDetector());
graphVersion = graphVersion.next();
return evaluator.eval(ImmutableList.copyOf(keys));
}
diff --git a/src/test/java/com/google/devtools/build/skyframe/GraphTest.java b/src/test/java/com/google/devtools/build/skyframe/GraphTest.java
index 1445f18..8535a6b 100644
--- a/src/test/java/com/google/devtools/build/skyframe/GraphTest.java
+++ b/src/test/java/com/google/devtools/build/skyframe/GraphTest.java
@@ -211,7 +211,7 @@
waitForStart.countDown();
waitForAddedRdep.await(TestUtils.WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
entry.markRebuilding();
- entry.setValue(new StringValue("foo1"), startingVersion);
+ entry.setValue(new StringValue("foo1"), startingVersion, null);
waitForSetValue.countDown();
wrapper.waitForTasksAndMaybeThrow();
assertThat(ExecutorUtil.interruptibleShutdown(pool)).isFalse();
@@ -227,7 +227,7 @@
sameEntry.markDirty(DirtyType.CHANGE);
startEvaluation(sameEntry);
sameEntry.markRebuilding();
- sameEntry.setValue(new StringValue("foo2"), getNextVersion(startingVersion));
+ sameEntry.setValue(new StringValue("foo2"), getNextVersion(startingVersion), null);
assertThat(graph.get(null, Reason.OTHER, key).getValue()).isEqualTo(new StringValue("foo2"));
if (checkRdeps()) {
assertThat(graph.get(null, Reason.OTHER, key).getReverseDepsForDoneEntry())
@@ -284,7 +284,7 @@
entry.markRebuilding();
assertThat(valuesSet.add(key)).isTrue();
// Set to done.
- entry.setValue(new StringValue("bar" + keyNum), startingVersion);
+ entry.setValue(new StringValue("bar" + keyNum), startingVersion, null);
assertThat(entry.isDone()).isTrue();
}
} catch (InterruptedException e) {
@@ -335,7 +335,7 @@
NodeEntry entry = entries.get(key("foo" + i));
startEvaluation(entry);
entry.markRebuilding();
- entry.setValue(new StringValue("bar"), startingVersion);
+ entry.setValue(new StringValue("bar"), startingVersion, null);
}
assertThat(graph.get(null, Reason.OTHER, key("foo" + 0))).isNotNull();
@@ -380,7 +380,7 @@
Version nextVersion = getNextVersion(startingVersion);
entry.signalDep(nextVersion, dep);
- entry.setValue(new StringValue("bar" + keyNum), nextVersion);
+ entry.setValue(new StringValue("bar" + keyNum), nextVersion, null);
} catch (InterruptedException e) {
throw new IllegalStateException(keyNum + ", " + entry, e);
}
diff --git a/src/test/java/com/google/devtools/build/skyframe/InMemoryNodeEntryTest.java b/src/test/java/com/google/devtools/build/skyframe/InMemoryNodeEntryTest.java
index 7aa4998..550bcd3 100644
--- a/src/test/java/com/google/devtools/build/skyframe/InMemoryNodeEntryTest.java
+++ b/src/test/java/com/google/devtools/build/skyframe/InMemoryNodeEntryTest.java
@@ -754,7 +754,7 @@
entry.markRebuilding();
addTemporaryDirectDep(entry, originalChild);
entry.signalDep(ZERO_VERSION, originalChild);
- entry.setValue(originalValue, version);
+ entry.setValue(originalValue, version, null);
entry.addReverseDepAndCheckIfDone(key("parent1"));
InMemoryNodeEntry clone1 = entry.cloneNodeEntry();
entry.addReverseDepAndCheckIfDone(key("parent2"));
@@ -768,7 +768,7 @@
addTemporaryDirectDep(clone2, newChild);
clone2.signalDep(ONE_VERSION, newChild);
clone2.markRebuilding();
- clone2.setValue(updatedValue, version.next());
+ clone2.setValue(updatedValue, version.next(), null);
assertThat(entry.getVersion()).isEqualTo(version);
assertThat(clone1.getVersion()).isEqualTo(version);
@@ -812,7 +812,7 @@
entry.signalDep(ZERO_VERSION, dep);
}
}
- entry.setValue(new IntegerValue(42), IntVersion.of(42L));
+ entry.setValue(new IntegerValue(42), IntVersion.of(42L), null);
int i = 0;
GroupedList<SkyKey> entryGroupedDirectDeps =
GroupedList.create(entry.getCompressedDirectDepsForDoneEntry());
@@ -832,7 +832,7 @@
entry.markRebuilding();
entry.addTemporaryDirectDeps(GroupedListHelper.create(dep));
entry.signalDep(ZERO_VERSION, dep);
- entry.setValue(new IntegerValue(1), ZERO_VERSION);
+ entry.setValue(new IntegerValue(1), ZERO_VERSION, null);
assertThat(entry.hasAtLeastOneDep()).isTrue();
}
@@ -844,7 +844,7 @@
.isEqualTo(DependencyState.NEEDS_SCHEDULING);
entry.markRebuilding();
entry.addTemporaryDirectDeps(new GroupedListHelper<>());
- entry.setValue(new IntegerValue(1), ZERO_VERSION);
+ entry.setValue(new IntegerValue(1), ZERO_VERSION, null);
assertThat(entry.hasAtLeastOneDep()).isFalse();
}
@@ -853,7 +853,8 @@
throws InterruptedException {
return entry.setValue(
ValueWithMetadata.normal(value, errorInfo, NO_EVENTS, NO_POSTS),
- IntVersion.of(graphVersion));
+ IntVersion.of(graphVersion),
+ null);
}
private static void addTemporaryDirectDep(NodeEntry entry, SkyKey key) {
diff --git a/src/test/java/com/google/devtools/build/skyframe/NotifyingHelper.java b/src/test/java/com/google/devtools/build/skyframe/NotifyingHelper.java
index 409b3d9..53a3824 100644
--- a/src/test/java/com/google/devtools/build/skyframe/NotifyingHelper.java
+++ b/src/test/java/com/google/devtools/build/skyframe/NotifyingHelper.java
@@ -279,9 +279,11 @@
}
@Override
- public Set<SkyKey> setValue(SkyValue value, Version version) throws InterruptedException {
+ public Set<SkyKey> setValue(
+ SkyValue value, Version graphVersion, @Nullable Version maxTransitiveSourceVersion)
+ throws InterruptedException {
graphListener.accept(myKey, EventType.SET_VALUE, Order.BEFORE, value);
- Set<SkyKey> result = super.setValue(value, version);
+ Set<SkyKey> result = super.setValue(value, graphVersion, maxTransitiveSourceVersion);
graphListener.accept(myKey, EventType.SET_VALUE, Order.AFTER, value);
return result;
}
@@ -370,7 +372,7 @@
@Override
public String toString() {
- return MoreObjects.toStringHelper(this).add("delegate", getThinDelegate()).toString();
+ return MoreObjects.toStringHelper(this).add("delegate", delegate).toString();
}
}
diff --git a/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java b/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java
index cf929a9..a07e217 100644
--- a/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java
+++ b/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java
@@ -119,8 +119,7 @@
revalidationReceiver,
GraphInconsistencyReceiver.THROWING,
() -> AbstractQueueVisitor.createExecutorService(200, "test-pool"),
- new SimpleCycleDetector(),
- EvaluationVersionBehavior.MAX_CHILD_VERSIONS);
+ new SimpleCycleDetector());
}
private ParallelEvaluator makeEvaluator(