Let `SkyKey` alone declare its value's shareability.
There are currently three methods for declaring shareability:
* `SkyFunctionName#getShareabilityOfValue`
* `SkyKey#getShareabilityOfValue`
* `SkyValue#dataIsShareable`
The former two are just "hints" - a return of `SOMETIMES` still requires checking the value. However, there is no enforcement of consistency - for example, we can have a particular `SkyFunctionName#getShareabilityOfValue` return `NEVER`, but that function may compute a value whose `SkyValue#dataIsShareable` returns `true`. This currently happens in practice.
My original plan was to check consistency in `SerializationCheckingGraph`, but it turns out that it's not too difficult to just make `SkyKey` the sole proprietor of shareability. This is strictly better than giving the responsibility to `SkyValue` because a remote storage fetch for a value need not be attempted if the key is not shareable (this is what the "hint" in `SkyKey` intended to achieve).
Replace `ShareabilityOfValue` with a simple boolean since the return of `SkyKey#valueIsShareable` is now definite.
PiperOrigin-RevId: 416937942
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionLookupData.java b/src/main/java/com/google/devtools/build/lib/actions/ActionLookupData.java
index 7e4c87e..4e4282c 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionLookupData.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ActionLookupData.java
@@ -18,7 +18,6 @@
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.skyframe.SkyFunctions;
import com.google.devtools.build.skyframe.ExecutionPhaseSkyKey;
-import com.google.devtools.build.skyframe.ShareabilityOfValue;
import com.google.devtools.build.skyframe.SkyFunctionName;
/** Data that uniquely identifies an action. */
@@ -44,7 +43,10 @@
: new ActionLookupData(actionLookupKey, actionIndex);
}
- /** Similar to {@link #create}, but the key will have {@link ShareabilityOfValue#NEVER}. */
+ /**
+ * Similar to {@link #create}, but the key will return {@code false} for {@link
+ * #valueIsShareable}.
+ */
public static ActionLookupData createUnshareable(
ActionLookupKey actionLookupKey, int actionIndex) {
return new UnshareableActionLookupData(actionLookupKey, actionIndex);
@@ -58,21 +60,25 @@
* Index of the action in question in the node keyed by {@link #getActionLookupKey}. Should be
* passed to {@link ActionLookupValue#getAction}.
*/
- public int getActionIndex() {
+ public final int getActionIndex() {
return actionIndex;
}
- public Label getLabel() {
+ public final Label getLabel() {
return actionLookupKey.getLabel();
}
@Override
- public int hashCode() {
- return 37 * actionLookupKey.hashCode() + actionIndex;
+ public final int hashCode() {
+ int hash = 1;
+ hash = 37 * hash + actionLookupKey.hashCode();
+ hash = 37 * hash + Integer.hashCode(actionIndex);
+ hash = 37 * hash + Boolean.hashCode(valueIsShareable());
+ return hash;
}
@Override
- public boolean equals(Object obj) {
+ public final boolean equals(Object obj) {
if (this == obj) {
return true;
}
@@ -81,7 +87,8 @@
}
ActionLookupData that = (ActionLookupData) obj;
return this.actionIndex == that.actionIndex
- && this.actionLookupKey.equals(that.actionLookupKey);
+ && this.actionLookupKey.equals(that.actionLookupKey)
+ && valueIsShareable() == that.valueIsShareable();
}
@Override
@@ -103,8 +110,8 @@
}
@Override
- public ShareabilityOfValue getShareabilityOfValue() {
- return ShareabilityOfValue.NEVER;
+ public boolean valueIsShareable() {
+ return false;
}
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/actions/Artifact.java b/src/main/java/com/google/devtools/build/lib/actions/Artifact.java
index 1213077..6c2ebc8 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/Artifact.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/Artifact.java
@@ -49,7 +49,6 @@
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
-import com.google.devtools.build.skyframe.ShareabilityOfValue;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.protobuf.CodedInputStream;
@@ -1117,8 +1116,8 @@
}
@Override
- public ShareabilityOfValue getShareabilityOfValue() {
- return isConstantMetadata() ? ShareabilityOfValue.NEVER : super.getShareabilityOfValue();
+ public boolean valueIsShareable() {
+ return !isConstantMetadata();
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/actions/FileArtifactValue.java b/src/main/java/com/google/devtools/build/lib/actions/FileArtifactValue.java
index 5800986..d74ed51 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/FileArtifactValue.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/FileArtifactValue.java
@@ -201,48 +201,34 @@
isFile,
isFile ? fileValue.getSize() : 0,
isFile ? fileValue.realFileStateValue().getContentsProxy() : null,
- isFile ? fileValue.getDigest() : null,
- /* isShareable=*/ true);
+ isFile ? fileValue.getDigest() : null);
}
public static FileArtifactValue createFromInjectedDigest(
- FileArtifactValue metadata, @Nullable byte[] digest, boolean isShareable) {
- return createForNormalFile(
- digest, metadata.getContentsProxy(), metadata.getSize(), isShareable);
+ FileArtifactValue metadata, @Nullable byte[] digest) {
+ return createForNormalFile(digest, metadata.getContentsProxy(), metadata.getSize());
}
@VisibleForTesting
public static FileArtifactValue createForTesting(Artifact artifact) throws IOException {
- Path path = artifact.getPath();
- boolean isShareable = !artifact.isConstantMetadata();
- // Caution: there's a race condition between stating the file and computing the
- // digest. We need to stat first, since we're using the stat to detect changes.
- // We follow symlinks here to be consistent with getDigest.
- return createFromStat(path, path.stat(Symlinks.FOLLOW), isShareable);
+ return createForTesting(artifact.getPath());
}
@VisibleForTesting
public static FileArtifactValue createForTesting(Path path) throws IOException {
- /*isShareable=*/
- // Caution: there's a race condition between stating the file and computing the
- // digest. We need to stat first, since we're using the stat to detect changes.
- // We follow symlinks here to be consistent with getDigest.
- return createFromStat(path, path.stat(Symlinks.FOLLOW), true);
+ // Caution: there's a race condition between stating the file and computing the digest. We need
+ // to stat first, since we're using the stat to detect changes. We follow symlinks here to be
+ // consistent with getDigest.
+ return createFromStat(path, path.stat(Symlinks.FOLLOW));
}
- public static FileArtifactValue createFromStat(Path path, FileStatus stat, boolean isShareable)
- throws IOException {
+ public static FileArtifactValue createFromStat(Path path, FileStatus stat) throws IOException {
return create(
- path, stat.isFile(), stat.getSize(), FileContentsProxy.create(stat), null, isShareable);
+ path, stat.isFile(), stat.getSize(), FileContentsProxy.create(stat), /*digest=*/ null);
}
private static FileArtifactValue create(
- Path path,
- boolean isFile,
- long size,
- FileContentsProxy proxy,
- @Nullable byte[] digest,
- boolean isShareable)
+ Path path, boolean isFile, long size, FileContentsProxy proxy, @Nullable byte[] digest)
throws IOException {
if (!isFile) {
// In this case, we need to store the mtime because the action cache uses mtime for
@@ -254,7 +240,7 @@
digest = DigestUtils.getDigestWithManualFallback(path, size);
}
Preconditions.checkState(digest != null, path);
- return createForNormalFile(digest, proxy, size, isShareable);
+ return createForNormalFile(digest, proxy, size);
}
public static FileArtifactValue createForVirtualActionInput(byte[] digest, long size) {
@@ -281,10 +267,8 @@
@VisibleForTesting
public static FileArtifactValue createForNormalFile(
- byte[] digest, @Nullable FileContentsProxy proxy, long size, boolean isShareable) {
- return isShareable
- ? new RegularFileArtifactValue(digest, proxy, size)
- : new UnshareableRegularFileArtifactValue(digest, proxy, size);
+ byte[] digest, @Nullable FileContentsProxy proxy, long size) {
+ return new RegularFileArtifactValue(digest, proxy, size);
}
/**
@@ -293,7 +277,7 @@
*/
public static FileArtifactValue createForNormalFileUsingPath(Path path, long size)
throws IOException {
- return create(path, true, size, null, null, true);
+ return create(path, /*isFile=*/ true, size, /*proxy=*/ null, /*digest=*/ null);
}
public static FileArtifactValue createForDirectoryWithHash(byte[] digest) {
@@ -310,7 +294,7 @@
*/
public static FileArtifactValue createProxy(byte[] digest) {
Preconditions.checkNotNull(digest);
- return createForNormalFile(digest, /*proxy=*/ null, /*size=*/ 0, /*isShareable=*/ true);
+ return createForNormalFile(digest, /*proxy=*/ null, /*size=*/ 0);
}
private static String bytesToString(byte[] bytes) {
@@ -447,8 +431,7 @@
}
}
- private static class RegularFileArtifactValue extends FileArtifactValue {
-
+ private static final class RegularFileArtifactValue extends FileArtifactValue {
private final byte[] digest;
@Nullable private final FileContentsProxy proxy;
private final long size;
@@ -462,20 +445,21 @@
@Override
public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
if (!(o instanceof RegularFileArtifactValue)) {
return false;
}
-
RegularFileArtifactValue that = (RegularFileArtifactValue) o;
return Arrays.equals(digest, that.digest)
&& Objects.equals(proxy, that.proxy)
- && size == that.size
- && dataIsShareable() == that.dataIsShareable();
+ && size == that.size;
}
@Override
public int hashCode() {
- return Objects.hash(Arrays.hashCode(digest), proxy, size, dataIsShareable());
+ return Objects.hash(Arrays.hashCode(digest), proxy, size);
}
@Override
@@ -535,18 +519,6 @@
}
}
- private static final class UnshareableRegularFileArtifactValue extends RegularFileArtifactValue {
- private UnshareableRegularFileArtifactValue(
- byte[] digest, @Nullable FileContentsProxy proxy, long size) {
- super(digest, proxy, size);
- }
-
- @Override
- public boolean dataIsShareable() {
- return false;
- }
- }
-
/** Metadata for remotely stored files. */
public static class RemoteFileArtifactValue extends FileArtifactValue {
private final byte[] digest;
@@ -575,14 +547,12 @@
return Arrays.equals(digest, that.digest)
&& size == that.size
&& locationIndex == that.locationIndex
- && Objects.equals(actionId, that.actionId)
- && dataIsShareable() == that.dataIsShareable();
+ && Objects.equals(actionId, that.actionId);
}
@Override
public int hashCode() {
- return Objects.hash(
- Arrays.hashCode(digest), size, locationIndex, actionId, dataIsShareable());
+ return Objects.hash(Arrays.hashCode(digest), size, locationIndex, actionId);
}
@Override
@@ -682,7 +652,12 @@
}
/** File stored inline in metadata. */
- public static class InlineFileArtifactValue extends FileArtifactValue {
+ public static final class InlineFileArtifactValue extends FileArtifactValue {
+
+ public static InlineFileArtifactValue create(byte[] bytes, HashFunction hashFunction) {
+ return new InlineFileArtifactValue(bytes, hashFunction.hashBytes(bytes).asBytes());
+ }
+
private final byte[] data;
private final byte[] digest;
@@ -691,30 +666,21 @@
this.digest = Preconditions.checkNotNull(digest);
}
- private InlineFileArtifactValue(byte[] bytes, HashFunction hashFunction) {
- this(bytes, hashFunction.hashBytes(bytes).asBytes());
- }
-
@Override
public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
if (!(o instanceof InlineFileArtifactValue)) {
return false;
}
-
InlineFileArtifactValue that = (InlineFileArtifactValue) o;
- return Arrays.equals(digest, that.digest) && dataIsShareable() == that.dataIsShareable();
+ return Arrays.equals(digest, that.digest);
}
@Override
public int hashCode() {
- return Objects.hash(Arrays.hashCode(digest), dataIsShareable());
- }
-
- public static InlineFileArtifactValue create(
- byte[] bytes, boolean shareable, HashFunction hashFunction) {
- return shareable
- ? new InlineFileArtifactValue(bytes, hashFunction)
- : new UnshareableInlineFileArtifactValue(bytes, hashFunction);
+ return Arrays.hashCode(digest);
}
public ByteArrayInputStream getInputStream() {
@@ -752,17 +718,6 @@
}
}
- private static final class UnshareableInlineFileArtifactValue extends InlineFileArtifactValue {
- UnshareableInlineFileArtifactValue(byte[] bytes, HashFunction hashFunction) {
- super(bytes, hashFunction);
- }
-
- @Override
- public boolean dataIsShareable() {
- return false;
- }
- }
-
/**
* Used to resolve source symlinks when diskless.
*
diff --git a/src/main/java/com/google/devtools/build/lib/exec/SingleBuildFileCache.java b/src/main/java/com/google/devtools/build/lib/exec/SingleBuildFileCache.java
index 7588e81..1a0ff62 100644
--- a/src/main/java/com/google/devtools/build/lib/exec/SingleBuildFileCache.java
+++ b/src/main/java/com/google/devtools/build/lib/exec/SingleBuildFileCache.java
@@ -60,7 +60,7 @@
Path path = ActionInputHelper.toInputPath(input, execRoot);
FileArtifactValue metadata;
try {
- metadata = FileArtifactValue.createFromStat(path, path.stat(Symlinks.FOLLOW), true);
+ metadata = FileArtifactValue.createFromStat(path, path.stat(Symlinks.FOLLOW));
} catch (IOException e) {
return new ActionInputMetadata(input, e);
}
diff --git a/src/main/java/com/google/devtools/build/lib/remote/common/RemoteActionFileArtifactValue.java b/src/main/java/com/google/devtools/build/lib/remote/common/RemoteActionFileArtifactValue.java
index e3e96f6..e3e30f7 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/common/RemoteActionFileArtifactValue.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/common/RemoteActionFileArtifactValue.java
@@ -46,18 +46,12 @@
&& getSize() == that.getSize()
&& getLocationIndex() == that.getLocationIndex()
&& Objects.equals(getActionId(), that.getActionId())
- && isExecutable == that.isExecutable
- && dataIsShareable() == that.dataIsShareable();
+ && isExecutable == that.isExecutable;
}
@Override
public int hashCode() {
return Objects.hash(
- Arrays.hashCode(getDigest()),
- getSize(),
- getLocationIndex(),
- getActionId(),
- isExecutable,
- dataIsShareable());
+ Arrays.hashCode(getDigest()), getSize(), getLocationIndex(), getActionId(), isExecutable);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java
index 1c1b7ee..60d1d48 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java
@@ -382,7 +382,7 @@
// Remove action from state map in case it's there (won't be unless it discovers inputs).
stateMap.remove(action);
- if (sketch != null && result.dataIsShareable()) {
+ if (sketch != null && actionLookupData.valueIsShareable()) {
topDownActionCache.put(sketch, result);
}
return result;
@@ -819,7 +819,7 @@
+ "SkyframeAwareAction which should be re-executed unconditionally. Action: %s",
action);
return ActionExecutionValue.createFromOutputStore(
- metadataHandler.getOutputStore(), /*outputSymlinks=*/ null, action, actionLookupData);
+ metadataHandler.getOutputStore(), /*outputSymlinks=*/ null, action);
}
metadataHandler.prepareForActionExecution();
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionValue.java
index a17fef5..65ee2fa 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionValue.java
@@ -21,8 +21,6 @@
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.devtools.build.lib.actions.Action;
-import com.google.devtools.build.lib.actions.ActionLookupData;
-import com.google.devtools.build.lib.actions.Actions;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.ArchivedTreeArtifact;
import com.google.devtools.build.lib.actions.Artifact.DerivedArtifact;
@@ -36,7 +34,6 @@
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.rules.cpp.IncludeScannable;
import com.google.devtools.build.lib.skyframe.TreeArtifactValue.ArchivedRepresentation;
-import com.google.devtools.build.skyframe.ShareabilityOfValue;
import com.google.devtools.build.skyframe.SkyValue;
import java.util.Map;
import java.util.NoSuchElementException;
@@ -46,7 +43,7 @@
/** A value representing an executed action. */
@Immutable
@ThreadSafe
-public class ActionExecutionValue implements SkyValue {
+public final class ActionExecutionValue implements SkyValue {
/** A map from each output artifact of this action to their {@link FileArtifactValue}s. */
private final ImmutableMap<Artifact, FileArtifactValue> artifactData;
@@ -107,31 +104,23 @@
static ActionExecutionValue createFromOutputStore(
OutputStore outputStore,
@Nullable ImmutableList<FilesetOutputSymlink> outputSymlinks,
- Action action,
- ActionLookupData lookupData) {
- return create(
+ Action action) {
+ return new ActionExecutionValue(
outputStore.getAllArtifactData(),
outputStore.getAllTreeArtifactData(),
outputSymlinks,
action instanceof IncludeScannable
? ((IncludeScannable) action).getDiscoveredModules()
- : null,
- !Actions.dependsOnBuildId(action)
- && lookupData.getShareabilityOfValue() != ShareabilityOfValue.NEVER);
+ : null);
}
@VisibleForTesting
- static ActionExecutionValue create(
+ public static ActionExecutionValue createForTesting(
ImmutableMap<Artifact, FileArtifactValue> artifactData,
ImmutableMap<Artifact, TreeArtifactValue> treeArtifactData,
- @Nullable ImmutableList<FilesetOutputSymlink> outputSymlinks,
- @Nullable NestedSet<Artifact> discoveredModules,
- boolean shareable) {
- return shareable
- ? new ActionExecutionValue(
- artifactData, treeArtifactData, outputSymlinks, discoveredModules)
- : new CrossServerUnshareableActionExecutionValue(
- artifactData, treeArtifactData, outputSymlinks, discoveredModules);
+ @Nullable ImmutableList<FilesetOutputSymlink> outputSymlinks) {
+ return new ActionExecutionValue(
+ artifactData, treeArtifactData, outputSymlinks, /*discoveredModules=*/ null);
}
/**
@@ -230,33 +219,12 @@
ActionExecutionValue o = (ActionExecutionValue) obj;
return artifactData.equals(o.artifactData)
&& treeArtifactData.equals(o.treeArtifactData)
- && dataIsShareable() == o.dataIsShareable()
&& Objects.equal(outputSymlinks, o.outputSymlinks);
}
@Override
public int hashCode() {
- return Objects.hashCode(artifactData, treeArtifactData);
- }
-
- /**
- * Subclass that reports this value cannot be shared across servers. Note that this is unrelated
- * to the concept of shared actions.
- */
- private static final class CrossServerUnshareableActionExecutionValue
- extends ActionExecutionValue {
- CrossServerUnshareableActionExecutionValue(
- ImmutableMap<Artifact, FileArtifactValue> artifactData,
- ImmutableMap<Artifact, TreeArtifactValue> treeArtifactData,
- @Nullable ImmutableList<FilesetOutputSymlink> outputSymlinks,
- @Nullable NestedSet<Artifact> discoveredModules) {
- super(artifactData, treeArtifactData, outputSymlinks, discoveredModules);
- }
-
- @Override
- public boolean dataIsShareable() {
- return false;
- }
+ return Objects.hashCode(artifactData, treeArtifactData, outputSymlinks);
}
private static <V> ImmutableMap<Artifact, V> transformMap(
@@ -327,13 +295,12 @@
action);
Map<OwnerlessArtifactWrapper, Artifact> newArtifactMap =
Maps.uniqueIndex(action.getOutputs(), OwnerlessArtifactWrapper::new);
- return create(
+ return new ActionExecutionValue(
transformMap(artifactData, newArtifactMap, action, (newArtifact, value) -> value),
transformMap(
treeArtifactData, newArtifactMap, action, ActionExecutionValue::transformSharedTree),
outputSymlinks,
// Discovered modules come from the action's inputs, and so don't need to be transformed.
- discoveredModules,
- dataIsShareable());
+ discoveredModules);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionMetadataHandler.java b/src/main/java/com/google/devtools/build/lib/skyframe/ActionMetadataHandler.java
index 52464a9..3171f12 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionMetadataHandler.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ActionMetadataHandler.java
@@ -556,8 +556,7 @@
injectedDigest =
DigestUtils.manuallyComputeDigest(artifactPathResolver.toPath(artifact), value.getSize());
}
- return FileArtifactValue.createFromInjectedDigest(
- value, injectedDigest, /*isShareable=*/ !artifact.isConstantMetadata());
+ return FileArtifactValue.createFromInjectedDigest(value, injectedDigest);
}
/**
@@ -608,7 +607,6 @@
rootedPathNoFollow,
statNoFollow,
digestWillBeInjected,
- artifact.isConstantMetadata(),
tsgm);
}
@@ -637,7 +635,6 @@
realRootedPath,
realStatWithDigest,
digestWillBeInjected,
- artifact.isConstantMetadata(),
tsgm);
}
@@ -645,7 +642,6 @@
RootedPath rootedPath,
FileStatusWithDigest stat,
boolean digestWillBeInjected,
- boolean isConstantMetadata,
@Nullable TimestampGranularityMonitor tsgm)
throws IOException {
if (stat == null) {
@@ -658,10 +654,7 @@
return stat.isDirectory()
? FileArtifactValue.createForDirectoryWithMtime(stat.getLastModifiedTime())
: FileArtifactValue.createForNormalFile(
- fileStateValue.getDigest(),
- fileStateValue.getContentsProxy(),
- stat.getSize(),
- /*isShareable=*/ !isConstantMetadata);
+ fileStateValue.getDigest(), fileStateValue.getContentsProxy(), stat.getSize());
}
private static void setPathReadOnlyAndExecutableIfFile(Path path) throws IOException {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactNestedSetKey.java b/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactNestedSetKey.java
index f535e92..c9f6fe5 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactNestedSetKey.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactNestedSetKey.java
@@ -17,7 +17,6 @@
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.skyframe.ExecutionPhaseSkyKey;
-import com.google.devtools.build.skyframe.ShareabilityOfValue;
import com.google.devtools.build.skyframe.SkyFunctionName;
/** SkyKey for {@code NestedSet<Artifact>}. */
@@ -47,10 +46,10 @@
}
@Override
- public ShareabilityOfValue getShareabilityOfValue() {
+ public boolean valueIsShareable() {
// ArtifactNestedSetValue is just a promise that data is available in memory. Not meant for
// cross-server sharing.
- return ShareabilityOfValue.NEVER;
+ return false;
}
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactNestedSetValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactNestedSetValue.java
index 7619343..0e78619 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactNestedSetValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactNestedSetValue.java
@@ -23,11 +23,4 @@
*/
@Immutable
@ThreadSafe
-public final class ArtifactNestedSetValue implements SkyValue {
-
- @Override
- public boolean dataIsShareable() {
- // This is just a promise that data is available in memory. Not meant for cross-server sharing.
- return false;
- }
-}
+public final class ArtifactNestedSetValue implements SkyValue {}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectCompletionValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectCompletionValue.java
index 6eb9b44..2e56754 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectCompletionValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectCompletionValue.java
@@ -49,8 +49,13 @@
public abstract AspectKey actionLookupKey();
@Override
- public SkyFunctionName functionName() {
+ public final SkyFunctionName functionName() {
return SkyFunctions.ASPECT_COMPLETION;
}
+
+ @Override
+ public final boolean valueIsShareable() {
+ return false;
+ }
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadValue.java
index 83b8c8e..609af60 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadValue.java
@@ -103,6 +103,13 @@
public SkyFunctionName functionName() {
return SkyFunctions.BZL_LOAD;
}
+
+ @Override
+ public final boolean valueIsShareable() {
+ // We don't guarantee that all constructs implement equality, meaning we can't correctly
+ // compare deserialized instances. This is currently the case for attribute descriptors.
+ return false;
+ }
}
/** A key for loading a .bzl during package loading (BUILD evaluation). */
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java
index e1a64e3..6518feb 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java
@@ -14,6 +14,7 @@
package com.google.devtools.build.lib.skyframe;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
@@ -23,10 +24,12 @@
import com.google.devtools.build.lib.packages.RuleVisibility;
import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
+import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
import com.google.devtools.build.skyframe.AbstractSkyKey;
import com.google.devtools.build.skyframe.Injectable;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyFunctionName;
+import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.util.Map;
import java.util.UUID;
@@ -38,7 +41,7 @@
* "precomputed" from skyframe's perspective and so the graph needs to be prepopulated with them
* (e.g. via injection).
*/
-public class PrecomputedValue implements SkyValue {
+public final class PrecomputedValue implements SkyValue {
/**
* An externally-injected precomputed value. Exists so that modules can inject precomputed values
* into Skyframe's graph.
@@ -47,9 +50,9 @@
*/
public static final class Injected {
private final Precomputed<?> precomputed;
- private final Supplier<? extends Object> supplier;
+ private final Supplier<?> supplier;
- private Injected(Precomputed<?> precomputed, Supplier<? extends Object> supplier) {
+ private Injected(Precomputed<?> precomputed, Supplier<?> supplier) {
this.precomputed = precomputed;
this.supplier = supplier;
}
@@ -81,7 +84,7 @@
public static final Precomputed<StarlarkSemantics> STARLARK_SEMANTICS =
new Precomputed<>("starlark_semantics");
- static final Precomputed<UUID> BUILD_ID = new UnsharablePrecomputed<>("build_id");
+ static final Precomputed<UUID> BUILD_ID = new Precomputed<>("build_id", /*shareable=*/ false);
public static final Precomputed<Map<String, String>> ACTION_ENV = new Precomputed<>("action_env");
@@ -131,15 +134,19 @@
*
* <p>Instances do not have internal state.
*/
- public static class Precomputed<T> {
- protected final Key key;
+ public static final class Precomputed<T> {
+ private final SkyKey key;
public Precomputed(String key) {
- this.key = Key.create(key);
+ this(key, /*shareable=*/ true);
+ }
+
+ private Precomputed(String key, boolean shareable) {
+ this.key = shareable ? Key.create(key) : UnshareableKey.create(key);
}
@VisibleForTesting
- public Key getKeyForTesting() {
+ public SkyKey getKeyForTesting() {
return key;
}
@@ -162,35 +169,19 @@
public void set(Injectable injectable, T value) {
injectable.inject(key, new PrecomputedValue(value));
}
- }
-
- private static class UnsharablePrecomputed<T> extends Precomputed<T> {
- private UnsharablePrecomputed(String key) {
- super(key);
- }
-
- /** Injects a new variable value. */
- @Override
- public void set(Injectable injectable, T value) {
- injectable.inject(key, new UnshareablePrecomputedValue(value));
- }
- }
-
- /** An unshareable version of {@link PrecomputedValue}. */
- private static final class UnshareablePrecomputedValue extends PrecomputedValue {
- private UnshareablePrecomputedValue(Object value) {
- super(value);
- }
@Override
- public boolean dataIsShareable() {
- return false;
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("key", key)
+ .add("shareable", key.valueIsShareable())
+ .toString();
}
}
/** {@link com.google.devtools.build.skyframe.SkyKey} for {@code PrecomputedValue}. */
@AutoCodec
- public static class Key extends AbstractSkyKey<String> {
+ public static final class Key extends AbstractSkyKey<String> {
private static final Interner<Key> interner = BlazeInterners.newWeakInterner();
private Key(String arg) {
@@ -207,4 +198,31 @@
return SkyFunctions.PRECOMPUTED;
}
}
+
+ /** Unshareable version of {@link Key}. */
+ @AutoCodec
+ @VisibleForSerialization
+ static final class UnshareableKey extends AbstractSkyKey<String> {
+ private static final Interner<UnshareableKey> interner = BlazeInterners.newWeakInterner();
+
+ private UnshareableKey(String arg) {
+ super(arg);
+ }
+
+ @AutoCodec.Instantiator
+ @VisibleForSerialization
+ static UnshareableKey create(String arg) {
+ return interner.intern(new UnshareableKey(arg));
+ }
+
+ @Override
+ public SkyFunctionName functionName() {
+ return SkyFunctions.PRECOMPUTED;
+ }
+
+ @Override
+ public boolean valueIsShareable() {
+ return false;
+ }
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java
index 9d8cd42..11c46c3 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java
@@ -13,10 +13,7 @@
// limitations under the License.
package com.google.devtools.build.lib.skyframe;
-import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
-import com.google.devtools.build.skyframe.FunctionHermeticity;
-import com.google.devtools.build.skyframe.ShareabilityOfValue;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
@@ -42,10 +39,7 @@
public static final SkyFunctionName BZL_COMPILE = SkyFunctionName.createHermetic("BZL_COMPILE");
public static final SkyFunctionName STARLARK_BUILTINS =
SkyFunctionName.createHermetic("STARLARK_BUILTINS");
- // Never shareable - we don't guarantee that all constructs implement equality, meaning we can't
- // correctly compare deserialized instances. This is currently the case for attribute descriptors.
- public static final SkyFunctionName BZL_LOAD =
- SkyFunctionName.create("BZL_LOAD", ShareabilityOfValue.NEVER, FunctionHermeticity.HERMETIC);
+ public static final SkyFunctionName BZL_LOAD = SkyFunctionName.createHermetic("BZL_LOAD");
public static final SkyFunctionName GLOB = SkyFunctionName.createHermetic("GLOB");
public static final SkyFunctionName PACKAGE = SkyFunctionName.createHermetic("PACKAGE");
static final SkyFunctionName PACKAGE_ERROR = SkyFunctionName.createHermetic("PACKAGE_ERROR");
@@ -89,35 +83,26 @@
static final SkyFunctionName TOP_LEVEL_ACTION_LOOKUP_CONFLICT_FINDING =
SkyFunctionName.createHermetic("TOP_LEVEL_ACTION_LOOKUP_CONFLICT_DETECTION");
public static final SkyFunctionName ASPECT = SkyFunctionName.createHermetic("ASPECT");
- static final SkyFunctionName LOAD_STARLARK_ASPECT =
- SkyFunctionName.createHermetic("LOAD_STARLARK_ASPECT");
static final SkyFunctionName TOP_LEVEL_ASPECTS =
SkyFunctionName.createHermetic("TOP_LEVEL_ASPECTS");
static final SkyFunctionName BUILD_TOP_LEVEL_ASPECTS_DETAILS =
SkyFunctionName.createHermetic("BUILD_TOP_LEVEL_ASPECTS_DETAILS");
public static final SkyFunctionName TARGET_COMPLETION =
- SkyFunctionName.create(
- "TARGET_COMPLETION", ShareabilityOfValue.NEVER, FunctionHermeticity.HERMETIC);
+ SkyFunctionName.createHermetic("TARGET_COMPLETION");
public static final SkyFunctionName ASPECT_COMPLETION =
- SkyFunctionName.create(
- "ASPECT_COMPLETION", ShareabilityOfValue.NEVER, FunctionHermeticity.HERMETIC);
- static final SkyFunctionName TEST_COMPLETION =
- SkyFunctionName.create(
- "TEST_COMPLETION", ShareabilityOfValue.NEVER, FunctionHermeticity.HERMETIC);
+ SkyFunctionName.createHermetic("ASPECT_COMPLETION");
+ static final SkyFunctionName TEST_COMPLETION = SkyFunctionName.createHermetic("TEST_COMPLETION");
public static final SkyFunctionName BUILD_CONFIGURATION =
SkyFunctionName.createHermetic("BUILD_CONFIGURATION");
- // Test actions are not shareable. Action execution can be nondeterministic, so is semi-hermetic.
+ // Action execution can be nondeterministic, so semi-hermetic.
public static final SkyFunctionName ACTION_EXECUTION =
SkyFunctionName.createSemiHermetic("ACTION_EXECUTION");
public static final SkyFunctionName ARTIFACT_NESTED_SET =
SkyFunctionName.createHermetic("ARTIFACT_NESTED_SET");
public static final SkyFunctionName PATH_CASING_LOOKUP =
SkyFunctionName.createHermetic("PATH_CASING_LOOKUP");
-
- @VisibleForTesting
- public static final SkyFunctionName RECURSIVE_FILESYSTEM_TRAVERSAL =
+ static final SkyFunctionName RECURSIVE_FILESYSTEM_TRAVERSAL =
SkyFunctionName.createHermetic("RECURSIVE_DIRECTORY_TRAVERSAL");
-
public static final SkyFunctionName FILESET_ENTRY =
SkyFunctionName.createHermetic("FILESET_ENTRY");
static final SkyFunctionName BUILD_INFO_COLLECTION =
@@ -148,14 +133,10 @@
SkyFunctionName.createHermetic("TOOLCHAIN_RESOLUTION");
public static final SkyFunctionName REPOSITORY_MAPPING =
SkyFunctionName.createHermetic("REPOSITORY_MAPPING");
- public static final SkyFunctionName REPO_MAPPING_FOR_BZLMOD_BZL_LOAD =
- SkyFunctionName.createHermetic("REPO_MAPPING_FOR_BZLMOD_BZL_LOAD");
public static final SkyFunctionName RESOLVED_FILE =
SkyFunctionName.createHermetic("RESOLVED_FILE");
public static final SkyFunctionName RESOLVED_HASH_VALUES =
SkyFunctionName.createHermetic("RESOLVED_HASH_VALUES");
- public static final SkyFunctionName LOCAL_CONFIG_PLATFORM =
- SkyFunctionName.createHermetic("LOCAL_CONFIG_PLATFORM");
public static final SkyFunctionName MODULE_FILE =
SkyFunctionName.createNonHermetic("MODULE_FILE");
public static final SkyFunctionName BUILD_DRIVER =
@@ -169,12 +150,7 @@
public static final SkyFunctionName SINGLE_EXTENSION_EVAL =
SkyFunctionName.createNonHermetic("SINGLE_EXTENSION_EVAL");
- public static Predicate<SkyKey> isSkyFunction(final SkyFunctionName functionName) {
- return new Predicate<SkyKey>() {
- @Override
- public boolean apply(SkyKey key) {
- return key.functionName().equals(functionName);
- }
- };
+ public static Predicate<SkyKey> isSkyFunction(SkyFunctionName functionName) {
+ return key -> key.functionName().equals(functionName);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java
index 3cfd0d8..3c90c17 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java
@@ -1264,8 +1264,7 @@
return ActionExecutionValue.createFromOutputStore(
this.metadataHandler.getOutputStore(),
actionExecutionContext.getOutputSymlinks(),
- action,
- actionLookupData);
+ action);
}
/** A closure to continue an asynchronously running action. */
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TargetCompletionValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/TargetCompletionValue.java
index ff34827..9ed1b2d 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TargetCompletionValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TargetCompletionValue.java
@@ -68,10 +68,15 @@
public abstract ConfiguredTargetKey actionLookupKey();
@Override
- public SkyFunctionName functionName() {
+ public final SkyFunctionName functionName() {
return SkyFunctions.TARGET_COMPLETION;
}
+ @Override
+ public final boolean valueIsShareable() {
+ return false;
+ }
+
abstract boolean willTest();
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TestCompletionValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/TestCompletionValue.java
index f55e507..cd2e12f 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TestCompletionValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TestCompletionValue.java
@@ -29,26 +29,22 @@
* A test completion value represents the completion of a test target. This includes the execution
* of all test shards and repeated runs, if applicable.
*/
-public class TestCompletionValue implements SkyValue {
+public final class TestCompletionValue implements SkyValue {
static final TestCompletionValue TEST_COMPLETION_MARKER = new TestCompletionValue();
private TestCompletionValue() { }
- @Override
- public boolean dataIsShareable() {
- return false;
- }
-
public static SkyKey key(
ConfiguredTargetKey lac,
- final TopLevelArtifactContext topLevelArtifactContext,
- final boolean exclusiveTesting) {
+ TopLevelArtifactContext topLevelArtifactContext,
+ boolean exclusiveTesting) {
return TestCompletionKey.create(lac, topLevelArtifactContext, exclusiveTesting);
}
- public static Iterable<SkyKey> keys(Collection<ConfiguredTarget> targets,
- final TopLevelArtifactContext topLevelArtifactContext,
- final boolean exclusiveTesting) {
+ public static Iterable<SkyKey> keys(
+ Collection<ConfiguredTarget> targets,
+ TopLevelArtifactContext topLevelArtifactContext,
+ boolean exclusiveTesting) {
return Iterables.transform(
targets,
ct ->
@@ -84,8 +80,13 @@
public abstract boolean exclusiveTesting();
@Override
- public SkyFunctionName functionName() {
+ public final SkyFunctionName functionName() {
return SkyFunctions.TEST_COMPLETION;
}
+
+ @Override
+ public final boolean valueIsShareable() {
+ return false;
+ }
}
}
diff --git a/src/main/java/com/google/devtools/build/skyframe/BUILD b/src/main/java/com/google/devtools/build/skyframe/BUILD
index 7ab3fdd..91c12d5 100644
--- a/src/main/java/com/google/devtools/build/skyframe/BUILD
+++ b/src/main/java/com/google/devtools/build/skyframe/BUILD
@@ -11,7 +11,6 @@
SKYFRAME_OBJECT_SRCS = [
"AbstractSkyKey.java",
"FunctionHermeticity.java",
- "ShareabilityOfValue.java",
"SkyFunctionName.java",
"SkyKey.java",
"SkyValue.java",
@@ -23,7 +22,7 @@
srcs = SKYFRAME_OBJECT_SRCS,
visibility = ["//visibility:public"],
deps = [
- "//third_party:caffeine",
+ "//src/main/java/com/google/devtools/build/lib/concurrent",
"//third_party:guava",
],
)
diff --git a/src/main/java/com/google/devtools/build/skyframe/ErrorTransienceValue.java b/src/main/java/com/google/devtools/build/skyframe/ErrorTransienceValue.java
index c3a84fb..941d03d 100644
--- a/src/main/java/com/google/devtools/build/skyframe/ErrorTransienceValue.java
+++ b/src/main/java/com/google/devtools/build/skyframe/ErrorTransienceValue.java
@@ -22,10 +22,26 @@
public final class ErrorTransienceValue implements SkyValue {
private static final SkyFunctionName FUNCTION_NAME =
- SkyFunctionName.create(
- "ERROR_TRANSIENCE", ShareabilityOfValue.NEVER, FunctionHermeticity.NONHERMETIC);
+ SkyFunctionName.createNonHermetic("ERROR_TRANSIENCE");
- @SerializationConstant public static final SkyKey KEY = () -> FUNCTION_NAME;
+ @SerializationConstant
+ public static final SkyKey KEY =
+ new SkyKey() {
+ @Override
+ public SkyFunctionName functionName() {
+ return FUNCTION_NAME;
+ }
+
+ @Override
+ public boolean valueIsShareable() {
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "ErrorTransienceValue.KEY";
+ }
+ };
@SerializationConstant
public static final ErrorTransienceValue INSTANCE = new ErrorTransienceValue();
@@ -33,11 +49,6 @@
private ErrorTransienceValue() {}
@Override
- public boolean dataIsShareable() {
- return false;
- }
-
- @Override
public int hashCode() {
// Not the prettiest, but since we always return false for equals throw exception here to catch
// any errors related to hash-based collections quickly.
diff --git a/src/main/java/com/google/devtools/build/skyframe/ShareabilityOfValue.java b/src/main/java/com/google/devtools/build/skyframe/ShareabilityOfValue.java
deleted file mode 100644
index 625c5db..0000000
--- a/src/main/java/com/google/devtools/build/skyframe/ShareabilityOfValue.java
+++ /dev/null
@@ -1,36 +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;
-
-/**
- * When the {@link NodeEntry#getValue} corresponding to a given {@link SkyFunctionName} is
- * shareable: always, sometimes (depending on the specific key argument and/or value), or never.
- *
- * <p>Values may be unshareable because they are just not serializable, or because they contain data
- * that cannot safely be re-used as-is by another invocation.
- *
- * <p>Unshareable data should not be serialized, since it will never be re-used. Attempts to fetch
- * serialized data will check this value and only perform the fetch if the value is not {@link
- * #NEVER}.
- */
-public enum ShareabilityOfValue {
- /**
- * Indicates that values produced by the function are shareable unless they override {@link
- * SkyValue#dataIsShareable}.
- */
- SOMETIMES,
- /** Indicates that values produced by the function are not shareable. */
- NEVER
-}
diff --git a/src/main/java/com/google/devtools/build/skyframe/SkyFunctionName.java b/src/main/java/com/google/devtools/build/skyframe/SkyFunctionName.java
index 623a8d2..3d3f356 100644
--- a/src/main/java/com/google/devtools/build/skyframe/SkyFunctionName.java
+++ b/src/main/java/com/google/devtools/build/skyframe/SkyFunctionName.java
@@ -13,23 +13,22 @@
// limitations under the License.
package com.google.devtools.build.skyframe;
-import com.github.benmanes.caffeine.cache.Cache;
-import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
+import com.google.common.collect.Interner;
+import com.google.devtools.build.lib.concurrent.BlazeInterners;
import java.util.Set;
/** An identifier for a {@code SkyFunction}. */
public final class SkyFunctionName {
- private static final Cache<NameOnlyWrapper, SkyFunctionName> interner =
- Caffeine.newBuilder().build();
+ private static final Interner<SkyFunctionName> interner = BlazeInterners.newStrongInterner();
/**
* A well-known key type intended for testing only. The associated SkyKey should have a String
* argument.
*/
- // Needs to be after the cache is initialized.
+ // Needs to be after the interner is initialized.
public static final SkyFunctionName FOR_TESTING = SkyFunctionName.createHermetic("FOR_TESTING");
/**
@@ -39,7 +38,7 @@
* opposed to transitively invalidated).
*/
public static SkyFunctionName createNonHermetic(String name) {
- return create(name, ShareabilityOfValue.SOMETIMES, FunctionHermeticity.NONHERMETIC);
+ return create(name, FunctionHermeticity.NONHERMETIC);
}
/**
@@ -47,7 +46,7 @@
* FunctionHermeticity#SEMI_HERMETIC semi-hermetic}.
*/
public static SkyFunctionName createSemiHermetic(String name) {
- return create(name, ShareabilityOfValue.SOMETIMES, FunctionHermeticity.SEMI_HERMETIC);
+ return create(name, FunctionHermeticity.SEMI_HERMETIC);
}
/**
@@ -55,47 +54,40 @@
* to be a deterministic function of its dependencies, not doing any external operations).
*/
public static SkyFunctionName createHermetic(String name) {
- return create(name, ShareabilityOfValue.SOMETIMES, FunctionHermeticity.HERMETIC);
+ return create(name, FunctionHermeticity.HERMETIC);
}
- public static SkyFunctionName create(
- String name, ShareabilityOfValue shareabilityOfValue, FunctionHermeticity hermeticity) {
- SkyFunctionName result = new SkyFunctionName(name, shareabilityOfValue, hermeticity);
- SkyFunctionName cached = interner.get(new NameOnlyWrapper(result), unused -> result);
+ private static SkyFunctionName create(String name, FunctionHermeticity hermeticity) {
+ SkyFunctionName cached = interner.intern(new SkyFunctionName(name, hermeticity));
Preconditions.checkState(
- result.equals(cached),
- "Tried to create SkyFunctionName objects with same name but different properties: %s %s",
- result,
- cached);
+ cached.hermeticity.equals(hermeticity),
+ "Tried to create SkyFunctionName objects with same name (%s) but different hermeticity"
+ + " (old=%s, new=%s)",
+ name,
+ cached.hermeticity,
+ hermeticity);
return cached;
}
private final String name;
- private final ShareabilityOfValue shareabilityOfValue;
private final FunctionHermeticity hermeticity;
- private SkyFunctionName(
- String name, ShareabilityOfValue shareabilityOfValue, FunctionHermeticity hermeticity) {
- this.name = name;
- this.shareabilityOfValue = shareabilityOfValue;
- this.hermeticity = hermeticity;
+ private SkyFunctionName(String name, FunctionHermeticity hermeticity) {
+ this.name = Preconditions.checkNotNull(name);
+ this.hermeticity = Preconditions.checkNotNull(hermeticity);
}
public String getName() {
return name;
}
- public ShareabilityOfValue getShareabilityOfValue() {
- return shareabilityOfValue;
- }
-
public FunctionHermeticity getHermeticity() {
return hermeticity;
}
@Override
public String toString() {
- return name + (shareabilityOfValue.equals(ShareabilityOfValue.NEVER) ? " (unshareable)" : "");
+ return name;
}
@Override
@@ -107,48 +99,26 @@
return false;
}
SkyFunctionName other = (SkyFunctionName) obj;
- return name.equals(other.name) && shareabilityOfValue.equals(other.shareabilityOfValue);
+ return name.equals(other.name);
}
@Override
public int hashCode() {
- // Don't bother incorporating serializabilityOfValue into hashCode: should always be the same.
+ // Don't bother incorporating hermeticity into hashCode: should always be the same.
return name.hashCode();
}
/**
* A predicate that returns true for {@link SkyKey}s that have the given {@link SkyFunctionName}.
*/
- public static Predicate<SkyKey> functionIs(final SkyFunctionName functionName) {
+ public static Predicate<SkyKey> functionIs(SkyFunctionName functionName) {
return skyKey -> functionName.equals(skyKey.functionName());
}
/**
* A predicate that returns true for {@link SkyKey}s that have the given {@link SkyFunctionName}.
*/
- public static Predicate<SkyKey> functionIsIn(final Set<SkyFunctionName> functionNames) {
+ public static Predicate<SkyKey> functionIsIn(Set<SkyFunctionName> functionNames) {
return skyKey -> functionNames.contains(skyKey.functionName());
}
-
- private static class NameOnlyWrapper {
- private final SkyFunctionName skyFunctionName;
-
- private NameOnlyWrapper(SkyFunctionName skyFunctionName) {
- this.skyFunctionName = skyFunctionName;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof NameOnlyWrapper)) {
- return false;
- }
- SkyFunctionName thatFunctionName = ((NameOnlyWrapper) obj).skyFunctionName;
- return this.skyFunctionName.getName().equals(thatFunctionName.name);
- }
-
- @Override
- public int hashCode() {
- return skyFunctionName.getName().hashCode();
- }
- }
}
diff --git a/src/main/java/com/google/devtools/build/skyframe/SkyKey.java b/src/main/java/com/google/devtools/build/skyframe/SkyKey.java
index 79284ac..f6cc4c0 100644
--- a/src/main/java/com/google/devtools/build/skyframe/SkyKey.java
+++ b/src/main/java/com/google/devtools/build/skyframe/SkyKey.java
@@ -33,7 +33,21 @@
return this;
}
- default ShareabilityOfValue getShareabilityOfValue() {
- return functionName().getShareabilityOfValue();
+ /**
+ * Returns {@code true} if this key produces a {@link SkyValue} that can be reused across builds.
+ *
+ * <p>Values may be unshareable because they are just not serializable, or because they contain
+ * data that cannot safely be reused as-is by another invocation, such as stamping information or
+ * "flaky" values like test statuses.
+ *
+ * <p>Unshareable data should not be serialized, since it will never be reused. Attempts to fetch
+ * a key's serialized data will call this method and only perform the fetch if it returns {@code
+ * true}.
+ *
+ * <p>The result of this method only applies to non-error values. In case of an error, {@link
+ * ErrorInfo#isTransitivelyTransient()} can be used to determine shareability.
+ */
+ default boolean valueIsShareable() {
+ return true;
}
}
diff --git a/src/main/java/com/google/devtools/build/skyframe/SkyValue.java b/src/main/java/com/google/devtools/build/skyframe/SkyValue.java
index 1c0e1c6..2d21e86 100644
--- a/src/main/java/com/google/devtools/build/skyframe/SkyValue.java
+++ b/src/main/java/com/google/devtools/build/skyframe/SkyValue.java
@@ -14,14 +14,4 @@
package com.google.devtools.build.skyframe;
/** A return value of a {@code SkyFunction}. */
-public interface SkyValue {
-
- /**
- * Returns true for values that can be reused across builds. Some values are inherently "flaky",
- * like test statuses or stamping information, and in certain circumstances, those values cannot
- * be shared across builds/servers.
- */
- default boolean dataIsShareable() {
- return true;
- }
-}
+public interface SkyValue {}
diff --git a/src/test/java/com/google/devtools/build/lib/exec/SpawnInputExpanderTest.java b/src/test/java/com/google/devtools/build/lib/exec/SpawnInputExpanderTest.java
index 07e50b7..77f8d20 100644
--- a/src/test/java/com/google/devtools/build/lib/exec/SpawnInputExpanderTest.java
+++ b/src/test/java/com/google/devtools/build/lib/exec/SpawnInputExpanderTest.java
@@ -96,8 +96,7 @@
FakeActionInputFileCache mockCache = new FakeActionInputFileCache();
mockCache.put(
artifact,
- FileArtifactValue.createForNormalFile(
- FAKE_DIGEST, /*proxy=*/ null, 0L, /*isShareable=*/ true));
+ FileArtifactValue.createForNormalFile(FAKE_DIGEST, /*proxy=*/ null, /*size=*/ 0L));
expander.addRunfilesToInputs(
inputMappings, supplier, mockCache, NO_ARTIFACT_EXPANDER, PathFragment.EMPTY_FRAGMENT);
@@ -115,8 +114,7 @@
FakeActionInputFileCache mockCache = new FakeActionInputFileCache();
mockCache.put(
artifact,
- FileArtifactValue.createForNormalFile(
- FAKE_DIGEST, /*proxy=*/ null, 0L, /*isShareable=*/ true));
+ FileArtifactValue.createForNormalFile(FAKE_DIGEST, /*proxy=*/ null, /*size=*/ 0L));
ArtifactExpander filesetExpander =
new ArtifactExpander() {
@@ -206,12 +204,10 @@
FakeActionInputFileCache mockCache = new FakeActionInputFileCache();
mockCache.put(
artifact1,
- FileArtifactValue.createForNormalFile(
- FAKE_DIGEST, /*proxy=*/ null, 1L, /*isShareable=*/ true));
+ FileArtifactValue.createForNormalFile(FAKE_DIGEST, /*proxy=*/ null, /*size=*/ 1L));
mockCache.put(
artifact2,
- FileArtifactValue.createForNormalFile(
- FAKE_DIGEST, /*proxy=*/ null, 12L, /*isShareable=*/ true));
+ FileArtifactValue.createForNormalFile(FAKE_DIGEST, /*proxy=*/ null, /*size=*/ 12L));
expander.addRunfilesToInputs(
inputMappings, supplier, mockCache, NO_ARTIFACT_EXPANDER, PathFragment.EMPTY_FRAGMENT);
@@ -237,8 +233,7 @@
FakeActionInputFileCache mockCache = new FakeActionInputFileCache();
mockCache.put(
artifact,
- FileArtifactValue.createForNormalFile(
- FAKE_DIGEST, /*proxy=*/ null, 1L, /*isShareable=*/ true));
+ FileArtifactValue.createForNormalFile(FAKE_DIGEST, /*proxy=*/ null, /*size=*/ 1L));
expander.addRunfilesToInputs(
inputMappings, supplier, mockCache, NO_ARTIFACT_EXPANDER, PathFragment.EMPTY_FRAGMENT);
@@ -262,8 +257,7 @@
FakeActionInputFileCache mockCache = new FakeActionInputFileCache();
mockCache.put(
artifact,
- FileArtifactValue.createForNormalFile(
- FAKE_DIGEST, /*proxy=*/ null, 1L, /*isShareable=*/ true));
+ FileArtifactValue.createForNormalFile(FAKE_DIGEST, /*proxy=*/ null, /*size=*/ 1L));
expander.addRunfilesToInputs(
inputMappings, supplier, mockCache, NO_ARTIFACT_EXPANDER, PathFragment.EMPTY_FRAGMENT);
diff --git a/src/test/java/com/google/devtools/build/lib/remote/FakeActionInputFileCache.java b/src/test/java/com/google/devtools/build/lib/remote/FakeActionInputFileCache.java
index 76dfc49..d29645c 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/FakeActionInputFileCache.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/FakeActionInputFileCache.java
@@ -47,10 +47,7 @@
Path path = execRoot.getRelative(input.getExecPath());
FileStatus stat = path.stat(Symlinks.FOLLOW);
return FileArtifactValue.createForNormalFile(
- HashCode.fromString(hexDigest).asBytes(),
- FileContentsProxy.create(stat),
- stat.getSize(),
- /*isShareable=*/ true);
+ HashCode.fromString(hexDigest).asBytes(), FileContentsProxy.create(stat), stat.getSize());
}
@Override
@@ -58,13 +55,13 @@
throw new UnsupportedOperationException();
}
- void setDigest(ActionInput input, String digest) {
+ private void setDigest(ActionInput input, String digest) {
cas.put(input, digest);
}
public Digest createScratchInput(ActionInput input, String content) throws IOException {
Path inputFile = execRoot.getRelative(input.getExecPath());
- FileSystemUtils.createDirectoryAndParents(inputFile.getParentDirectory());
+ inputFile.getParentDirectory().createDirectoryAndParents();
FileSystemUtils.writeContentAsLatin1(inputFile, content);
Digest digest = digestUtil.compute(inputFile);
setDigest(input, digest.getHash());
@@ -73,7 +70,7 @@
public Digest createScratchInputDirectory(ActionInput input, Tree content) throws IOException {
Path inputFile = execRoot.getRelative(input.getExecPath());
- FileSystemUtils.createDirectoryAndParents(inputFile);
+ inputFile.createDirectoryAndParents();
Digest digest = digestUtil.compute(content);
setDigest(input, digest.getHash());
return digest;
diff --git a/src/test/java/com/google/devtools/build/lib/remote/RemoteActionFileSystemTest.java b/src/test/java/com/google/devtools/build/lib/remote/RemoteActionFileSystemTest.java
index 85f324d..a34bb48 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/RemoteActionFileSystemTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/RemoteActionFileSystemTest.java
@@ -16,6 +16,7 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -28,7 +29,6 @@
import com.google.devtools.build.lib.actions.FileArtifactValue;
import com.google.devtools.build.lib.actions.FileArtifactValue.RemoteFileArtifactValue;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
-import com.google.devtools.build.lib.clock.JavaClock;
import com.google.devtools.build.lib.vfs.DigestHashFunction;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
@@ -41,26 +41,21 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
/** Tests for {@link RemoteActionFileSystem} */
@RunWith(JUnit4.class)
-public class RemoteActionFileSystemTest {
+public final class RemoteActionFileSystemTest {
private static final DigestHashFunction HASH_FUNCTION = DigestHashFunction.SHA256;
- @Mock private RemoteActionInputFetcher inputFetcher;
- private FileSystem fs;
- private Path execRoot;
- private ArtifactRoot outputRoot;
+ private final RemoteActionInputFetcher inputFetcher = mock(RemoteActionInputFetcher.class);
+ private final FileSystem fs = new InMemoryFileSystem(HASH_FUNCTION);
+ private final Path execRoot = fs.getPath("/exec");
+ private final ArtifactRoot outputRoot =
+ ArtifactRoot.asDerivedRoot(execRoot, RootType.Output, "out");
@Before
- public void setUp() throws IOException {
- MockitoAnnotations.initMocks(this);
- fs = new InMemoryFileSystem(new JavaClock(), HASH_FUNCTION);
- execRoot = fs.getPath("/exec");
- outputRoot = ArtifactRoot.asDerivedRoot(execRoot, RootType.Output, "out");
+ public void createOutputRoot() throws IOException {
outputRoot.getRoot().asPath().createDirectoryAndParents();
}
@@ -188,8 +183,7 @@
// Caution: there's a race condition between stating the file and computing the
// digest. We need to stat first, since we're using the stat to detect changes.
// We follow symlinks here to be consistent with getDigest.
- inputs.putWithNoDepOwner(
- a, FileArtifactValue.createFromStat(path, path.stat(Symlinks.FOLLOW), true));
+ inputs.putWithNoDepOwner(a, FileArtifactValue.createFromStat(path, path.stat(Symlinks.FOLLOW)));
return a;
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/ActionExecutionValueTransformSharedTreeArtifactsTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/ActionExecutionValueTransformSharedTreeArtifactsTest.java
index 938b8fb..0a31309 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/ActionExecutionValueTransformSharedTreeArtifactsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/ActionExecutionValueTransformSharedTreeArtifactsTest.java
@@ -256,12 +256,8 @@
private static ActionExecutionValue createActionExecutionValue(
ImmutableMap<Artifact, FileArtifactValue> fileArtifacts,
ImmutableMap<Artifact, TreeArtifactValue> treeArtifacts) {
- return ActionExecutionValue.create(
- fileArtifacts,
- treeArtifacts,
- /*outputSymlinks=*/ null,
- /*discoveredModules=*/ null,
- /*shareable=*/ true);
+ return ActionExecutionValue.createForTesting(
+ fileArtifacts, treeArtifacts, /*outputSymlinks=*/ null);
}
private static void createFile(Path file) throws IOException {
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/ActionMetadataHandlerTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/ActionMetadataHandlerTest.java
index a2e46f3..3544479 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/ActionMetadataHandlerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/ActionMetadataHandlerTest.java
@@ -106,8 +106,7 @@
public void withNonArtifactInput() throws Exception {
ActionInput input = ActionInputHelper.fromPath("foo/bar");
FileArtifactValue metadata =
- FileArtifactValue.createForNormalFile(
- new byte[] {1, 2, 3}, /*proxy=*/ null, 10L, /*isShareable=*/ true);
+ FileArtifactValue.createForNormalFile(new byte[] {1, 2, 3}, /*proxy=*/ null, /*size=*/ 10L);
ActionInputMap map = new ActionInputMap(1);
map.putWithNoDepOwner(input, metadata);
assertThat(map.getMetadata(input)).isEqualTo(metadata);
@@ -122,8 +121,7 @@
PathFragment path = PathFragment.create("src/a");
Artifact artifact = ActionsTestUtil.createArtifactWithRootRelativePath(sourceRoot, path);
FileArtifactValue metadata =
- FileArtifactValue.createForNormalFile(
- new byte[] {1, 2, 3}, /*proxy=*/ null, 10L, /*isShareable=*/ true);
+ FileArtifactValue.createForNormalFile(new byte[] {1, 2, 3}, /*proxy=*/ null, /*size=*/ 10L);
ActionInputMap map = new ActionInputMap(1);
map.putWithNoDepOwner(artifact, metadata);
ActionMetadataHandler handler =
@@ -411,10 +409,7 @@
// child is missing, getExistingFileArtifactValue will throw.
ActionExecutionValue actionExecutionValue =
ActionExecutionValue.createFromOutputStore(
- handler.getOutputStore(),
- /*outputSymlinks=*/ null,
- new NullAction(),
- ActionsTestUtil.NULL_ACTION_LOOKUP_DATA);
+ handler.getOutputStore(), /*outputSymlinks=*/ null, new NullAction());
tree.getChildren().forEach(actionExecutionValue::getExistingFileArtifactValue);
}
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTest.java
index 37edcb0..a727496 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTest.java
@@ -87,23 +87,23 @@
delegateActionExecutionFunction = new SimpleActionExecutionFunction(omittedOutputs);
}
- private void assertFileArtifactValueMatches(boolean expectDigest) throws Throwable {
+ private void assertFileArtifactValueMatches() throws Exception {
Artifact output = createDerivedArtifact("output");
Path path = output.getPath();
file(path, "contents");
- assertValueMatches(path.stat(), expectDigest ? path.getDigest() : null, evaluateFAN(output));
+ assertValueMatches(path.stat(), path.getDigest(), evaluateFAN(output));
}
@Test
- public void testBasicArtifact() throws Throwable {
+ public void testBasicArtifact() throws Exception {
fastDigest = false;
- assertFileArtifactValueMatches(/*expectDigest=*/ true);
+ assertFileArtifactValueMatches();
}
@Test
- public void testBasicArtifactWithXattr() throws Throwable {
+ public void testBasicArtifactWithXattr() throws Exception {
fastDigest = true;
- assertFileArtifactValueMatches(/*expectDigest=*/ true);
+ assertFileArtifactValueMatches();
}
@Test
@@ -335,12 +335,10 @@
FilesetOutputSymlink.createForTesting(
PathFragment.EMPTY_FRAGMENT, PathFragment.EMPTY_FRAGMENT, PathFragment.EMPTY_FRAGMENT);
ActionExecutionValue actionExecutionValue =
- ActionExecutionValue.create(
+ ActionExecutionValue.createForTesting(
ImmutableMap.of(artifact1, metadata1, artifact3, FileArtifactValue.DEFAULT_MIDDLEMAN),
ImmutableMap.of(treeArtifact, tree),
- ImmutableList.of(filesetOutputSymlink),
- /*discoveredModules=*/ null,
- /*shareable=*/ false);
+ ImmutableList.of(filesetOutputSymlink));
new SerializationTester(actionExecutionValue)
.addDependency(FileSystem.class, root.getFileSystem())
.addDependency(
@@ -430,11 +428,11 @@
}
}
- private FileArtifactValue evaluateFAN(Artifact artifact) throws Throwable {
+ private FileArtifactValue evaluateFAN(Artifact artifact) throws Exception {
return ((FileArtifactValue) evaluateArtifactValue(artifact));
}
- private SkyValue evaluateArtifactValue(Artifact artifact) throws Throwable {
+ private SkyValue evaluateArtifactValue(Artifact artifact) throws Exception {
SkyKey key = Artifact.key(artifact);
EvaluationResult<SkyValue> result = evaluate(ImmutableList.of(key).toArray(new SkyKey[0]));
if (result.hasError()) {
@@ -520,8 +518,7 @@
FileStatusWithDigestAdapter.adapt(path.statIfFound(Symlinks.NOFOLLOW)),
null);
FileArtifactValue withDigest =
- FileArtifactValue.createFromInjectedDigest(
- noDigest, path.getDigest(), !output.isConstantMetadata());
+ FileArtifactValue.createFromInjectedDigest(noDigest, path.getDigest());
artifactData.put(output, withDigest);
} else {
artifactData.put(output, FileArtifactValue.DEFAULT_MIDDLEMAN);
@@ -529,12 +526,10 @@
} catch (IOException e) {
throw new IllegalStateException(e);
}
- return ActionExecutionValue.create(
+ return ActionExecutionValue.createForTesting(
ImmutableMap.copyOf(artifactData),
ImmutableMap.copyOf(treeArtifactData),
- /*outputSymlinks=*/ null,
- /*discoveredModules=*/ null,
- /*shareable=*/ true);
+ /*outputSymlinks=*/ null);
}
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/FileArtifactValueTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/FileArtifactValueTest.java
index eac821f..0435a19 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/FileArtifactValueTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/FileArtifactValueTest.java
@@ -65,34 +65,16 @@
new EqualsTester()
.addEqualityGroup(
FileArtifactValue.createForNormalFile(
- toBytes("00112233445566778899AABBCCDDEEFF"),
- /*proxy=*/ null,
- 1L,
- /*isShareable=*/ true),
+ toBytes("00112233445566778899AABBCCDDEEFF"), /*proxy=*/ null, 1L),
FileArtifactValue.createForNormalFile(
- toBytes("00112233445566778899AABBCCDDEEFF"),
- /*proxy=*/ null,
- 1L,
- /*isShareable=*/ true))
+ toBytes("00112233445566778899AABBCCDDEEFF"), /*proxy=*/ null, 1L))
.addEqualityGroup(
FileArtifactValue.createForNormalFile(
- toBytes("00112233445566778899AABBCCDDEEFF"),
- /*proxy=*/ null,
- 2L,
- /*isShareable=*/ true))
+ toBytes("00112233445566778899AABBCCDDEEFF"), /*proxy=*/ null, 2L))
.addEqualityGroup(FileArtifactValue.createForDirectoryWithMtime(1))
.addEqualityGroup(
FileArtifactValue.createForNormalFile(
- toBytes("FFFFFF00000000000000000000000000"),
- /*proxy=*/ null,
- 1L,
- /*isShareable=*/ true))
- .addEqualityGroup(
- FileArtifactValue.createForNormalFile(
- toBytes("FFFFFF00000000000000000000000000"),
- /*proxy=*/ null,
- 1L,
- /*isShareable=*/ false))
+ toBytes("FFFFFF00000000000000000000000000"), /*proxy=*/ null, 1L))
.addEqualityGroup(
FileArtifactValue.createForDirectoryWithMtime(2),
FileArtifactValue.createForDirectoryWithMtime(2))
@@ -152,7 +134,7 @@
assertThrows(
"mtime for non-empty file should not be stored.",
UnsupportedOperationException.class,
- () -> value.getModifiedTime());
+ value::getModifiedTime);
}
@Test
@@ -174,12 +156,12 @@
assertThrows(
"mtime for non-empty file should not be stored.",
UnsupportedOperationException.class,
- () -> value.getModifiedTime());
+ value::getModifiedTime);
}
@Test
public void testIOException() throws Exception {
- final IOException exception = new IOException("beep");
+ IOException exception = new IOException("beep");
FileSystem fs =
new InMemoryFileSystem(DigestHashFunction.SHA256) {
@Override
@@ -188,6 +170,7 @@
}
@Override
+ @SuppressWarnings("UnsynchronizedOverridesSynchronized")
protected byte[] getFastDigest(PathFragment path) throws IOException {
throw exception;
}
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTest.java
index 856a10c..05d81af 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTest.java
@@ -181,7 +181,7 @@
new ExternalPackageFunction(BazelSkyframeExecutorConstants.EXTERNAL_PACKAGE_HELPER));
differencer = new SequencedRecordingDifferencer();
- evaluator = new InMemoryMemoizingEvaluator(skyFunctions.build(), differencer);
+ evaluator = new InMemoryMemoizingEvaluator(skyFunctions.buildOrThrow(), differencer);
driver = new SequentialBuildDriver(evaluator);
PrecomputedValue.BUILD_ID.set(differencer, UUID.randomUUID());
PrecomputedValue.PATH_PACKAGE_LOCATOR.set(differencer, pkgLocator.get());
@@ -930,39 +930,28 @@
FileStatusWithDigestAdapter.adapt(path.statIfFound(Symlinks.NOFOLLOW)),
null);
FileArtifactValue withDigest =
- FileArtifactValue.createFromInjectedDigest(
- noDigest, path.getDigest(), !output.isConstantMetadata());
+ FileArtifactValue.createFromInjectedDigest(noDigest, path.getDigest());
artifactData.put(output, withDigest);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
- return ActionExecutionValue.create(
+ return ActionExecutionValue.createForTesting(
ImmutableMap.copyOf(artifactData),
/*treeArtifactData=*/ ImmutableMap.of(),
- /*outputSymlinks=*/ null,
- /*discoveredModules=*/ null,
- /*shareable=*/ true);
+ /*outputSymlinks=*/ null);
}
private static ActionExecutionValue actionValueWithTreeArtifact(
SpecialArtifact output, TreeArtifactValue tree) {
- return ActionExecutionValue.create(
- ImmutableMap.of(),
- ImmutableMap.of(output, tree),
- /*outputSymlinks=*/ null,
- /*discoveredModules=*/ null,
- /*shareable=*/ true);
+ return ActionExecutionValue.createForTesting(
+ ImmutableMap.of(), ImmutableMap.of(output, tree), /*outputSymlinks=*/ null);
}
private static ActionExecutionValue actionValueWithRemoteArtifact(
Artifact output, RemoteFileArtifactValue value) {
- return ActionExecutionValue.create(
- ImmutableMap.of(output, value),
- ImmutableMap.of(),
- /*outputSymlinks=*/ null,
- /*discoveredModules=*/ null,
- /*actionDependsOnBuildId=*/ false);
+ return ActionExecutionValue.createForTesting(
+ ImmutableMap.of(output, value), ImmutableMap.of(), /*outputSymlinks=*/ null);
}
private RemoteFileArtifactValue createRemoteFileArtifactValue(String contents) {
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTestBase.java b/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTestBase.java
index ba07124..8f60dac 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTestBase.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTestBase.java
@@ -108,12 +108,10 @@
Map<Artifact, TreeArtifactValue> treeArtifactData = new HashMap<>();
treeArtifacts.injectTo(treeArtifactData::put);
- return ActionExecutionValue.create(
+ return ActionExecutionValue.createForTesting(
/*artifactData=*/ ImmutableMap.of(),
ImmutableMap.copyOf(treeArtifactData),
- /*outputSymlinks=*/ null,
- /*discoveredModules=*/ null,
- /*shareable=*/ true);
+ /*outputSymlinks=*/ null);
}
private static FileArtifactValue createMetadataFromFileSystem(Artifact artifact)
@@ -122,8 +120,7 @@
FileArtifactValue noDigest =
ActionMetadataHandler.fileArtifactValueFromArtifact(
artifact, FileStatusWithDigestAdapter.adapt(path.statIfFound(Symlinks.NOFOLLOW)), null);
- return FileArtifactValue.createFromInjectedDigest(
- noDigest, path.getDigest(), !artifact.isConstantMetadata());
+ return FileArtifactValue.createFromInjectedDigest(noDigest, path.getDigest());
}
void writeFile(Path path, String... lines) throws IOException {
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/TreeArtifactMetadataTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/TreeArtifactMetadataTest.java
index c95ba3f..6681cfd 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/TreeArtifactMetadataTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/TreeArtifactMetadataTest.java
@@ -16,7 +16,6 @@
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
-import com.google.common.base.Predicate;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -42,7 +41,6 @@
import com.google.devtools.build.lib.events.NullEventHandler;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileStatusWithDigestAdapter;
-import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Symlinks;
@@ -107,7 +105,7 @@
@Test
public void testEmptyTreeArtifacts() throws Exception {
- TreeArtifactValue value = doTestTreeArtifacts(ImmutableList.<PathFragment>of());
+ TreeArtifactValue value = doTestTreeArtifacts(ImmutableList.of());
// Additional test, only for this test method: we expect the FileArtifactValue is equal to
// the digest [0]
assertThat(value.getMetadata().getDigest()).isEqualTo(value.getDigest());
@@ -140,14 +138,8 @@
ImmutableList.of(PathFragment.create("one"), PathFragment.create("two"));
TreeArtifactValue valueOne = evaluateTreeArtifact(treeArtifact, children);
MemoizingEvaluator evaluator = driver.getGraphForTesting();
- evaluator.delete(
- new Predicate<SkyKey>() {
- @Override
- public boolean apply(SkyKey key) {
- // Delete action execution node to force our artifacts to be re-evaluated.
- return actions.contains(key.argument());
- }
- });
+ // Delete action execution node to force our artifacts to be re-evaluated.
+ evaluator.delete(key -> actions.contains(key.argument()));
TreeArtifactValue valueTwo = evaluateTreeArtifact(treeArtifact, children);
assertThat(valueOne.getDigest()).isNotSameInstanceAs(valueTwo.getDigest());
assertThat(valueOne).isEqualTo(valueTwo);
@@ -209,7 +201,7 @@
}
private static void file(Path path, String contents) throws Exception {
- FileSystemUtils.createDirectoryAndParents(path.getParentDirectory());
+ path.getParentDirectory().createDirectoryAndParents();
writeFile(path, contents);
}
@@ -223,7 +215,7 @@
ALL_OWNER,
SpecialArtifactType.TREE);
actions.add(new DummyAction(NestedSetBuilder.emptySet(Order.STABLE_ORDER), output));
- FileSystemUtils.createDirectoryAndParents(fullPath);
+ fullPath.createDirectoryAndParents();
return output;
}
@@ -282,20 +274,17 @@
FileStatusWithDigestAdapter.adapt(path.statIfFound(Symlinks.NOFOLLOW)),
null);
FileArtifactValue withDigest =
- FileArtifactValue.createFromInjectedDigest(
- noDigest, path.getDigest(), !output.isConstantMetadata());
+ FileArtifactValue.createFromInjectedDigest(noDigest, path.getDigest());
tree.putChild(suboutput, withDigest);
} catch (IOException e) {
throw new SkyFunctionException(e, Transience.TRANSIENT) {};
}
}
- return ActionExecutionValue.create(
+ return ActionExecutionValue.createForTesting(
/*artifactData=*/ ImmutableMap.of(),
ImmutableMap.of(output, tree.build()),
- /*outputSymlinks=*/ null,
- /*discoveredModules=*/ null,
- /*shareable=*/ true);
+ /*outputSymlinks=*/ null);
}
}
}
diff --git a/src/test/java/com/google/devtools/build/skyframe/GraphTester.java b/src/test/java/com/google/devtools/build/skyframe/GraphTester.java
index a94b501..a6d4d97 100644
--- a/src/test/java/com/google/devtools/build/skyframe/GraphTester.java
+++ b/src/test/java/com/google/devtools/build/skyframe/GraphTester.java
@@ -26,7 +26,6 @@
import com.google.devtools.build.lib.events.ExtendedEventHandler.Postable;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.util.Pair;
-import com.google.devtools.build.skyframe.SkyFunction.Environment;
import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
import java.util.HashMap;
import java.util.LinkedHashMap;
@@ -197,7 +196,7 @@
}
public TestFunction addDependency(SkyKey key) {
- deps.add(Pair.<SkyKey, SkyValue>of(key, null));
+ deps.add(Pair.of(key, null));
return this;
}
@@ -324,9 +323,7 @@
functionMap.put(functionName, function);
}
- /**
- * Simple value class that stores strings.
- */
+ /** Simple value class that stores strings. */
public static class StringValue implements SkyValue {
protected final String value;
@@ -340,6 +337,9 @@
@Override
public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
if (!(o instanceof StringValue)) {
return false;
}
@@ -353,7 +353,7 @@
@Override
public String toString() {
- return "StringValue: " + getValue();
+ return "StringValue: " + value;
}
public static StringValue of(String string) {
@@ -384,18 +384,6 @@
}
}
- /** An unshareable version of {@link StringValue}. */
- public static final class UnshareableStringValue extends StringValue {
- public UnshareableStringValue(String value) {
- super(value);
- }
-
- @Override
- public boolean dataIsShareable() {
- return false;
- }
- }
-
/**
* A callback interface to provide the value computation.
*/
@@ -405,32 +393,20 @@
throws InterruptedException;
}
- public static final ValueComputer COPY = new ValueComputer() {
- @Override
- public SkyValue compute(Map<SkyKey, SkyValue> deps, SkyFunction.Environment env) {
- return Iterables.getOnlyElement(deps.values());
- }
- };
+ public static final ValueComputer COPY = (deps, env) -> Iterables.getOnlyElement(deps.values());
- public static final ValueComputer CONCATENATE = new ValueComputer() {
- @Override
- public SkyValue compute(Map<SkyKey, SkyValue> deps, SkyFunction.Environment env) {
- StringBuilder result = new StringBuilder();
- for (SkyValue value : deps.values()) {
- result.append(((StringValue) value).value);
- }
- return new StringValue(result.toString());
- }
- };
+ public static final ValueComputer CONCATENATE =
+ (deps, env) -> {
+ StringBuilder result = new StringBuilder();
+ for (SkyValue value : deps.values()) {
+ result.append(((StringValue) value).value);
+ }
+ return new StringValue(result.toString());
+ };
- public static ValueComputer formatter(final SkyKey key, final String format) {
- return new ValueComputer() {
- @Override
- public SkyValue compute(Map<SkyKey, SkyValue> deps, Environment env)
- throws InterruptedException {
- return StringValue.of(String.format(format, StringValue.from(deps.get(key)).getValue()));
- }
- };
+ public static ValueComputer formatter(SkyKey key, String format) {
+ return (deps, env) ->
+ StringValue.of(String.format(format, StringValue.from(deps.get(key)).getValue()));
}
@AutoCodec.VisibleForSerialization