Allow NodeEntries to prune their deps based on fingerprinting the dep group. This is useful in situations in which the deps themselves are forbidden from value-based pruning because of subtle version bugs.
PiperOrigin-RevId: 224922819
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 f0dadac..bd453ca3 100644
--- a/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java
+++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java
@@ -22,6 +22,7 @@
import com.google.devtools.build.lib.util.GroupedList.GroupedListHelper;
import com.google.devtools.build.skyframe.KeyToConsolidate.Op;
import com.google.devtools.build.skyframe.KeyToConsolidate.OpToStoreBare;
+import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -295,13 +296,21 @@
// although this method itself is synchronized, there are unsynchronized consumers of the version
// and the value.
@Override
- public synchronized Set<SkyKey> setValue(SkyValue value, Version version)
+ public synchronized Set<SkyKey> setValue(
+ SkyValue value, Version version, DepFingerprintList depFingerprintList)
throws InterruptedException {
Preconditions.checkState(isReady(), "%s %s", this, value);
+ if (depFingerprintList != null) {
+ logError(
+ new IllegalStateException(
+ String.format(
+ "Expect no depFingerprintList here: %s %s %s %s",
+ this, depFingerprintList, value, version)));
+ }
assertVersionCompatibleWhenSettingValue(version, value);
this.lastEvaluatedVersion = version;
- if (!isEligibleForChangePruning()) {
+ if (!isEligibleForChangePruningOnUnchangedValue()) {
this.lastChangedVersion = version;
this.value = value;
} else if (isDirty() && getDirtyBuildingState().unchangedFromLastBuild(value)) {
@@ -324,13 +333,13 @@
}
/**
- * Returns {@code true} if this node is eligible to be change-pruned when its value has not
+ * Returns {@code true} if this node is eligible to be change pruned when its value has not
* changed from the last build.
*
- * <p>Implementations need not check whether the value has changed - nodes will only be
- * change-pruned if the value has not changed.
+ * <p>Implementations need not check whether the value has changed - this will only be called if
+ * the value has not changed.
*/
- public boolean isEligibleForChangePruning() {
+ public boolean isEligibleForChangePruningOnUnchangedValue() {
return true;
}
@@ -624,8 +633,36 @@
}
@Override
+ public boolean canPruneDepsByFingerprint() {
+ return false;
+ }
+
+ @Nullable
+ @Override
+ public Iterable<SkyKey> getLastDirectDepsGroupWhenPruningDepsByFingerprint()
+ throws InterruptedException {
+ throw new UnsupportedOperationException(this.toString());
+ }
+
+ @Override
+ public boolean unmarkNeedsRebuildingIfGroupUnchangedUsingFingerprint(
+ BigInteger groupFingerprint) {
+ throw new UnsupportedOperationException(this.toString());
+ }
+
+ /**
+ * If this entry {@link #canPruneDepsByFingerprint} and has that data, returns a list of dep group
+ * fingerprints. Otherwise returns null.
+ */
+ @Nullable
+ public DepFingerprintList getDepFingerprintList() {
+ Preconditions.checkState(isDone(), this);
+ return null;
+ }
+
+ @Override
public synchronized void markRebuilding() {
- getDirtyBuildingState().markRebuilding(isEligibleForChangePruning());
+ getDirtyBuildingState().markRebuilding(isEligibleForChangePruningOnUnchangedValue());
}
@SuppressWarnings("unchecked")
@@ -715,8 +752,7 @@
return signaledDeps > NOT_EVALUATING_SENTINEL;
}
- @Override
- public synchronized String toString() {
+ protected synchronized MoreObjects.ToStringHelper toStringHelper() {
return MoreObjects.toStringHelper(this)
.add("identity", System.identityHashCode(this))
.add("value", value)
@@ -725,8 +761,12 @@
.add("directDeps", isDone() ? GroupedList.create(directDeps) : directDeps)
.add("signaledDeps", signaledDeps)
.add("reverseDeps", ReverseDepsUtility.toString(this))
- .add("dirtyBuildingState", dirtyBuildingState)
- .toString();
+ .add("dirtyBuildingState", dirtyBuildingState);
+ }
+
+ @Override
+ public final synchronized String toString() {
+ return toStringHelper().toString();
}
protected synchronized InMemoryNodeEntry cloneNodeEntry(InMemoryNodeEntry newEntry) {