Remove ArtifactFileMetadata and replace it with FileArtifactValue.
A harmful side effect is the loss of the "digest must be present" assertion on RegularFileArtifactValue. I'm not a fan of this, however, in practice:
- There are other kinds of FileArtifactValues and it's not clear whether they are supposed to have digests or not
- The important invariant, that ActionExecutionValue supplies a digest in all sane cases, is not upheld at HEAD because ArtifactFileMetadata is not guaranteed to contain one.
The game plan is to re-instate that check when ActionExecutionValue is constructed (somehow) after getting rid of the PLACEHOLDER silliness, if possible.
In exchange, however, we get a saner treatment of output directories: before this change, we created ArtifactFileMetadata instances for them even though they were not, well, files.
RELNOTES: None.
PiperOrigin-RevId: 260909718
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java b/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java
index 4abf668..5c204bd 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java
@@ -553,6 +553,11 @@
}
@Override
+ public FileContentsProxy getContentsProxy() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public long getSize() {
return 0;
}
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ArtifactFileMetadata.java b/src/main/java/com/google/devtools/build/lib/actions/ArtifactFileMetadata.java
deleted file mode 100644
index 7756ae2..0000000
--- a/src/main/java/com/google/devtools/build/lib/actions/ArtifactFileMetadata.java
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright 2014 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.lib.actions;
-
-import com.google.common.base.Preconditions;
-import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
-import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
-import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
-import com.google.devtools.build.lib.util.BigIntegerFingerprint;
-import com.google.devtools.build.lib.vfs.PathFragment;
-import java.math.BigInteger;
-import java.util.Objects;
-import javax.annotation.Nullable;
-
-/**
- * A value that represents a file for the purposes of up-to-dateness checks of actions.
- *
- * <p>It always stands for an actual file. In particular, tree artifacts and middlemen do not have a
- * corresponding {@link ArtifactFileMetadata}. However, the file is not necessarily present in the
- * file system; this happens when intermediate build outputs are not downloaded (and maybe when an
- * input artifact of an action is missing?)
- *
- * <p>It makes its main appearance in {@code ActionExecutionValue.artifactData}. It has two main
- * uses:
- *
- * <ul>
- * <li>This is how dependent actions get hold of the output metadata of their generated inputs. In
- * this case, it will be transformed into a {@link FileArtifactValue} by {@code
- * ArtifactFunction}.
- * <li>This is how {@code FileSystemValueChecker} figures out which actions need to be invalidated
- * (just propagating the invalidation up from leaf nodes is not enough, because the output
- * tree may have been changed while Blaze was not looking)
- * </ul>
- *
- * <p>It would probably be possible to unify this and {@link FileArtifactValue} since they contain
- * much the same data. However, {@link FileArtifactValue} has a few other uses that are do not map
- * easily to {@link ArtifactFileMetadata}, mostly relating to ActionFS.
- */
-@Immutable
-@ThreadSafe
-public abstract class ArtifactFileMetadata {
- /**
- * Used as as placeholder in {@code OutputStore.artifactData} for artifacts that have entries in
- * {@code OutputStore.additionalOutputData}.
- */
- @AutoCodec public static final ArtifactFileMetadata PLACEHOLDER = new PlaceholderFileValue();
-
- // No implementations outside this class.
- private ArtifactFileMetadata() {}
-
- public boolean exists() {
- return realFileStateValue().getType() != FileStateType.NONEXISTENT;
- }
-
- /**
- * Returns true if this value corresponds to a file or symlink to an existing regular or special
- * file. If so, its parent directory is guaranteed to exist.
- */
- public boolean isFile() {
- return realFileStateValue().getType() == FileStateType.REGULAR_FILE;
- }
-
- /**
- * Returns true if the file is a directory or a symlink to an existing directory. If so, its
- * parent directory is guaranteed to exist.
- */
- public boolean isDirectory() {
- return realFileStateValue().getType() == FileStateType.DIRECTORY;
- }
-
- protected abstract FileStateValue realFileStateValue();
-
- public FileContentsProxy getContentsProxy() {
- return realFileStateValue().getContentsProxy();
- }
-
- public long getSize() {
- Preconditions.checkState(isFile(), this);
- return realFileStateValue().getSize();
- }
-
- @Nullable
- public byte[] getDigest() {
- Preconditions.checkState(isFile(), this);
- return realFileStateValue().getDigest();
- }
-
- /** Returns a quick fingerprint via a BigInteger */
- public BigInteger getFingerprint() {
- BigIntegerFingerprint fp = new BigIntegerFingerprint();
-
- // TODO(lberki): This could be replaced with addLong(getType().ordinal())
- // at the cost of making the order of elements in the enum affecting the fingerprint.
- fp.addBoolean(realFileStateValue().getType() == FileStateType.NONEXISTENT);
- fp.addBoolean(realFileStateValue().getType() == FileStateType.SPECIAL_FILE);
- fp.addBoolean(realFileStateValue().getType() == FileStateType.DIRECTORY);
- fp.addBoolean(realFileStateValue().getType() == FileStateType.REGULAR_FILE);
-
- if (isFile()) {
- fp.addLong(getSize());
- fp.addDigestedBytes(getDigest());
- }
- return fp.getFingerprint();
- }
-
- public static ArtifactFileMetadata forRegularFile(
- PathFragment pathFragment, FileStateValue fileStateValue) {
- return new Regular(pathFragment, fileStateValue);
- }
-
- /** Non-stub implementation of {@link ArtifactFileMetadata}. */
- private static final class Regular extends ArtifactFileMetadata {
- private final PathFragment realPath;
- private final FileStateValue realFileStateValue;
-
- Regular(PathFragment realPath, FileStateValue realFileStateValue) {
- this.realPath = Preconditions.checkNotNull(realPath);
- this.realFileStateValue = Preconditions.checkNotNull(realFileStateValue);
- }
-
- @Override
- public FileStateValue realFileStateValue() {
- return realFileStateValue;
- }
-
- @Override
- public FileContentsProxy getContentsProxy() {
- return realFileStateValue.getContentsProxy();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null) {
- return false;
- }
- if (obj.getClass() != Regular.class) {
- return false;
- }
- Regular other = (Regular) obj;
- return realPath.equals(other.realPath) && realFileStateValue.equals(other.realFileStateValue);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(realPath, realFileStateValue);
- }
-
- @Override
- public String toString() {
- return realPath + ", " + realFileStateValue;
- }
-
- @Override
- public BigInteger getFingerprint() {
- BigInteger original = super.getFingerprint();
- BigIntegerFingerprint fp = new BigIntegerFingerprint();
- fp.addBigIntegerOrdered(original);
- fp.addString(getClass().getCanonicalName());
- fp.addPath(realPath);
- fp.addBigIntegerOrdered(realFileStateValue.getValueFingerprint());
- return fp.getFingerprint();
- }
- }
-
- private static final class PlaceholderFileValue extends ArtifactFileMetadata {
- private static final BigInteger FINGERPRINT =
- new BigIntegerFingerprint().addString("PlaceholderFileValue").getFingerprint();
-
- private PlaceholderFileValue() {}
-
- @Override
- public FileStateValue realFileStateValue() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public FileContentsProxy getContentsProxy() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public BigInteger getFingerprint() {
- return FINGERPRINT;
- }
-
- @Override
- public String toString() {
- return "PlaceholderFileValue:Singleton";
- }
- }
-}
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 6a78998..d7cbc28 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
@@ -36,44 +36,32 @@
import javax.annotation.Nullable;
/**
- * State of a file system object for the execution phase.
+ * A value that represents a file for the purposes of up-to-dateness checks of actions.
*
- * <p>This is not used by Skyframe for invalidation, it is primarily used by the action cache and
- * the various {@link com.google.devtools.build.lib.exec.SpawnRunner} implementations.
+ * <p>It always stands for an actual file. In particular, tree artifacts and middlemen do not have a
+ * corresponding {@link FileArtifactValue}. However, the file is not necessarily present in the file
+ * system; this happens when intermediate build outputs are not downloaded (and maybe when an input
+ * artifact of an action is missing?)
*
- * <p>We have the following cases:
+ * <p>It makes its main appearance in {@code ActionExecutionValue.artifactData}. It has two main
+ * uses:
*
* <ul>
- * <li>an ordinary file, in which case we would expect to see a digest and size;
- * <li>a directory, in which case we would expect to see an mtime;
- * <li>an intentionally omitted file which the build system is aware of but doesn't actually
- * exist, where all access methods are unsupported;
- * <li>a "middleman marker" object, which has a null digest, 0 size, and mtime of 0.
- * <li>The "self data" of a TreeArtifact, where we would expect to see a digest representing the
- * artifact's contents, and a size of 0.
- * <li>a file that's only stored by a remote caching/execution system, in which case we would
- * expect to see a digest and size.
+ * <li>This is how dependent actions get hold of the output metadata of their generated inputs.
+ * <li>This is how {@code FileSystemValueChecker} figures out which actions need to be invalidated
+ * (just propagating the invalidation up from leaf nodes is not enough, because the output
+ * tree may have been changed while Blaze was not looking)
* </ul>
*/
@Immutable
@ThreadSafe
public abstract class FileArtifactValue implements SkyValue, HasDigest {
- @AutoCodec public static final FileArtifactValue DEFAULT_MIDDLEMAN = new SingletonMarkerValue();
- /** Data that marks that a file is not present on the filesystem. */
- @AutoCodec public static final FileArtifactValue MISSING_FILE_MARKER = new SingletonMarkerValue();
/**
- * Represents an omitted file -- we are aware of it but it doesn't exist. All access methods are
- * unsupported.
+ * Used as as placeholder in {@code OutputStore.artifactData} for artifacts that have entries in
+ * {@code OutputStore.additionalOutputData}.
*/
- @AutoCodec public static final FileArtifactValue OMITTED_FILE_MARKER = new OmittedFileValue();
-
- /**
- * Marker interface for singleton implementations of this class.
- *
- * <p>Needed for a correct implementation of {@code equals}.
- */
- public interface Singleton {}
+ @AutoCodec public static final FileArtifactValue PLACEHOLDER = new PlaceholderFileValue();
/**
* The type of the underlying file system object. If it is a regular file, then it is guaranteed
@@ -92,7 +80,7 @@
*
* <p>The return value is owned by this object and must not be modified.
*/
- @Nullable
+ @Override
public abstract byte[] getDigest();
/** Returns the file's size, or 0 if the underlying file system object is not a file. */
@@ -116,6 +104,7 @@
return null;
}
+
/**
* Index used to resolve remote files.
*
@@ -127,7 +116,7 @@
}
/** Returns {@code true} if this is a special marker as opposed to a representing a real file. */
- public final boolean isMarkerValue() {
+ public boolean isMarkerValue() {
return this instanceof Singleton;
}
@@ -180,6 +169,24 @@
}
}
+ public abstract FileContentsProxy getContentsProxy();
+
+ /**
+ * Marker interface for singleton implementations of this class.
+ *
+ * <p>Needed for a correct implementation of {@code equals}.
+ */
+ interface Singleton {}
+
+ @AutoCodec public static final FileArtifactValue DEFAULT_MIDDLEMAN = new SingletonMarkerValue();
+ /** Data that marks that a file is not present on the filesystem. */
+ @AutoCodec public static final FileArtifactValue MISSING_FILE_MARKER = new SingletonMarkerValue();
+ /**
+ * Represents an omitted file -- we are aware of it but it doesn't exist. All access methods are
+ * unsupported.
+ */
+ @AutoCodec public static final FileArtifactValue OMITTED_FILE_MARKER = new OmittedFileValue();
+
public static FileArtifactValue createForSourceArtifact(Artifact artifact, FileValue fileValue)
throws IOException {
Preconditions.checkState(artifact.isSourceArtifact());
@@ -195,20 +202,21 @@
}
@VisibleForTesting
- public static FileArtifactValue createForTesting(Artifact artifact, ArtifactFileMetadata metadata)
- throws IOException {
- boolean isFile = metadata.isFile();
+ public static FileArtifactValue injectDigestForTesting(
+ Artifact artifact, FileArtifactValue source) throws IOException {
+ boolean isFile = source.getType() == FileStateType.REGULAR_FILE;
+ FileContentsProxy proxy = source.getContentsProxy();
return create(
artifact.getPath(),
isFile,
- isFile ? metadata.getSize() : 0,
- isFile ? metadata.getContentsProxy() : null,
- isFile ? metadata.getDigest() : null,
+ isFile ? source.getSize() : 0,
+ proxy,
+ isFile ? source.getDigest() : null,
!artifact.isConstantMetadata());
}
public static FileArtifactValue createFromInjectedDigest(
- ArtifactFileMetadata metadata, @Nullable byte[] digest, boolean isShareable) {
+ FileArtifactValue metadata, @Nullable byte[] digest, boolean isShareable) {
return createForNormalFile(
digest, metadata.getContentsProxy(), metadata.getSize(), isShareable);
}
@@ -269,15 +277,6 @@
: new UnshareableRegularFileArtifactValue(digest, proxy, size);
}
- public static FileArtifactValue createFromMetadata(
- ArtifactFileMetadata artifactMetadata, boolean isShareable) {
- return createForNormalFile(
- artifactMetadata.getDigest(),
- artifactMetadata.getContentsProxy(),
- artifactMetadata.getSize(),
- isShareable);
- }
-
public static FileArtifactValue createForDirectoryWithHash(byte[] digest) {
return new HashedDirectoryArtifactValue(digest);
}
@@ -288,13 +287,17 @@
/**
* Creates a FileArtifactValue used as a 'proxy' input for other ArtifactValues. These are used in
- * {@link com.google.devtools.build.lib.actions.ActionCacheChecker}.
+ * {@link ActionCacheChecker}.
*/
public static FileArtifactValue createProxy(byte[] digest) {
Preconditions.checkNotNull(digest);
return createForNormalFile(digest, /*proxy=*/ null, /*size=*/ 0, /*isShareable=*/ true);
}
+ private static String bytesToString(byte[] bytes) {
+ return "0x" + BaseEncoding.base16().omitPadding().encode(bytes);
+ }
+
private static final class DirectoryArtifactValue extends FileArtifactValue {
private final long mtime;
@@ -314,6 +317,11 @@
}
@Override
+ public FileContentsProxy getContentsProxy() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public BigInteger getValueFingerprint() {
BigIntegerFingerprint fp = new BigIntegerFingerprint();
fp.addString(getClass().getCanonicalName());
@@ -361,6 +369,11 @@
}
@Override
+ public FileContentsProxy getContentsProxy() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public long getModifiedTime() {
return 0;
}
@@ -406,8 +419,9 @@
@Nullable private final FileContentsProxy proxy;
private final long size;
- private RegularFileArtifactValue(byte[] digest, @Nullable FileContentsProxy proxy, long size) {
- this.digest = Preconditions.checkNotNull(digest);
+ private RegularFileArtifactValue(
+ @Nullable byte[] digest, @Nullable FileContentsProxy proxy, long size) {
+ this.digest = digest;
this.proxy = proxy;
this.size = size;
}
@@ -423,6 +437,11 @@
}
@Override
+ public FileContentsProxy getContentsProxy() {
+ return proxy;
+ }
+
+ @Override
public long getSize() {
return size;
}
@@ -447,7 +466,8 @@
return MoreObjects.toStringHelper(this)
.add("digest", BaseEncoding.base16().lowerCase().encode(digest))
.add("size", size)
- .add("proxy", proxy).toString();
+ .add("proxy", proxy)
+ .toString();
}
@Override
@@ -468,7 +488,8 @@
@Override
public int hashCode() {
return (proxy != null ? 127 * proxy.hashCode() : 0)
- + 37 * Long.hashCode(getSize()) + Arrays.hashCode(getDigest());
+ + 37 * Long.hashCode(getSize())
+ + Arrays.hashCode(getDigest());
}
}
@@ -507,6 +528,11 @@
}
@Override
+ public FileContentsProxy getContentsProxy() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public long getSize() {
return size;
}
@@ -542,10 +568,6 @@
}
}
- private static String bytesToString(byte[] bytes) {
- return "0x" + BaseEncoding.base16().omitPadding().encode(bytes);
- }
-
/** File stored inline in metadata. */
public static class InlineFileArtifactValue extends FileArtifactValue {
private final byte[] data;
@@ -557,7 +579,8 @@
}
private InlineFileArtifactValue(byte[] bytes) {
- this(bytes,
+ this(
+ bytes,
DigestHashFunction.getDefaultUnchecked().getHashFunction().hashBytes(bytes).asBytes());
}
@@ -582,6 +605,11 @@
}
@Override
+ public FileContentsProxy getContentsProxy() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public long getSize() {
return data.length;
}
@@ -621,8 +649,7 @@
private final byte[] digest;
private final long size;
- public SourceFileArtifactValue(
- PathFragment execPath, byte[] digest, long size) {
+ public SourceFileArtifactValue(PathFragment execPath, byte[] digest, long size) {
this.execPath = Preconditions.checkNotNull(execPath);
this.digest = Preconditions.checkNotNull(digest);
this.size = size;
@@ -643,6 +670,11 @@
}
@Override
+ public FileContentsProxy getContentsProxy() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public long getSize() {
return size;
}
@@ -671,6 +703,11 @@
}
@Override
+ public FileContentsProxy getContentsProxy() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public long getSize() {
return 0;
}
@@ -709,6 +746,11 @@
}
@Override
+ public FileContentsProxy getContentsProxy() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public long getSize() {
throw new UnsupportedOperationException();
}
@@ -728,4 +770,61 @@
return "OMITTED_FILE_MARKER";
}
}
+
+ private static final class PlaceholderFileValue extends FileArtifactValue implements Singleton {
+ private static final BigInteger FINGERPRINT =
+ new BigIntegerFingerprint().addString("PlaceholderFileValue").getFingerprint();
+
+ private PlaceholderFileValue() {}
+
+ @Override
+ public long getSize() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public byte[] getDigest() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public FileContentsProxy getContentsProxy() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public BigInteger getValueFingerprint() {
+ return FINGERPRINT;
+ }
+
+ @Override
+ public String toString() {
+ return "PlaceholderFileValue:Singleton";
+ }
+
+ @Override
+ public FileStateType getType() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long getModifiedTime() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean wasModifiedSinceDigest(Path path) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isRemote() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isMarkerValue() {
+ throw new UnsupportedOperationException();
+ }
+ }
}
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 76fddb8..ffc04336 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
@@ -23,17 +23,14 @@
import com.google.devtools.build.lib.actions.ActionInputHelper;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.OwnerlessArtifactWrapper;
-import com.google.devtools.build.lib.actions.ArtifactFileMetadata;
import com.google.devtools.build.lib.actions.ArtifactOwner;
import com.google.devtools.build.lib.actions.FileArtifactValue;
-import com.google.devtools.build.lib.actions.FileStateValue;
import com.google.devtools.build.lib.actions.FileValue;
import com.google.devtools.build.lib.actions.FilesetOutputSymlink;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.util.BigIntegerFingerprint;
-import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.skyframe.SkyValue;
import java.math.BigInteger;
import java.util.Comparator;
@@ -64,9 +61,9 @@
* checked quickly against the actual filesystem on incremental builds.
*
* <p>If additional metadata is not needed here over what is in {@link #additionalOutputData}, the
- * value will be {@link ArtifactFileMetadata#PLACEHOLDER}.
+ * value will be {@link FileArtifactValue#PLACEHOLDER}.
*/
- private final ImmutableMap<Artifact, ArtifactFileMetadata> artifactData;
+ private final ImmutableMap<Artifact, FileArtifactValue> artifactData;
/** The TreeArtifactValue of all TreeArtifacts output by this Action. */
private final ImmutableMap<Artifact, TreeArtifactValue> treeArtifactData;
@@ -87,7 +84,7 @@
@Nullable private transient BigInteger valueFingerprint;
/**
- * @param artifactData Map from Artifacts to corresponding {@link ArtifactFileMetadata}.
+ * @param artifactData Map from Artifacts to corresponding {@link FileArtifactValue}.
* @param treeArtifactData All tree artifact data.
* @param additionalOutputData Map from Artifacts to values if the FileArtifactValue for this
* artifact cannot be derived from the corresponding FileValue (see {@link
@@ -97,7 +94,7 @@
* @param discoveredModules cpp modules discovered
*/
private ActionExecutionValue(
- Map<Artifact, ArtifactFileMetadata> artifactData,
+ Map<Artifact, FileArtifactValue> artifactData,
Map<Artifact, TreeArtifactValue> treeArtifactData,
Map<Artifact, FileArtifactValue> additionalOutputData,
@Nullable ImmutableList<FilesetOutputSymlink> outputSymlinks,
@@ -124,7 +121,7 @@
}
static ActionExecutionValue create(
- Map<Artifact, ArtifactFileMetadata> artifactData,
+ Map<Artifact, FileArtifactValue> artifactData,
Map<Artifact, TreeArtifactValue> treeArtifactData,
Map<Artifact, FileArtifactValue> additionalOutputData,
@Nullable ImmutableList<FilesetOutputSymlink> outputSymlinks,
@@ -155,7 +152,7 @@
* @return The data for each non-middleman output of this action, in the form of the {@link
* FileValue} that would be created for the file if it were to be read from disk.
*/
- ArtifactFileMetadata getData(Artifact artifact) {
+ FileArtifactValue getData(Artifact artifact) {
Preconditions.checkState(!additionalOutputData.containsKey(artifact),
"Should not be requesting data for already-constructed FileArtifactValue: %s", artifact);
return artifactData.get(artifact);
@@ -171,7 +168,7 @@
* returned by {@link #getData}. Primarily needed by {@link FilesystemValueChecker}, also
* called by {@link ArtifactFunction} when aggregating a {@link TreeArtifactValue}.
*/
- Map<Artifact, ArtifactFileMetadata> getAllFileValues() {
+ Map<Artifact, FileArtifactValue> getAllFileValues() {
return Maps.transformEntries(artifactData, this::transformIfPlaceholder);
}
@@ -202,7 +199,7 @@
.forEach(
(entry) -> {
fp.addPath(entry.getKey().getExecPath());
- fp.addBigIntegerOrdered(entry.getValue().getFingerprint());
+ fp.addBigIntegerOrdered(entry.getValue().getValueFingerprint());
});
sortMapByArtifactExecPathAndStream(treeArtifactData)
.forEach(
@@ -265,12 +262,11 @@
}
/** Transforms PLACEHOLDER values into normal instances. */
- private ArtifactFileMetadata transformIfPlaceholder(
- Artifact artifact, ArtifactFileMetadata value) {
+ private FileArtifactValue transformIfPlaceholder(Artifact artifact, FileArtifactValue value) {
Preconditions.checkState(!artifact.isTreeArtifact());
Preconditions.checkState(!artifact.isMiddlemanArtifact());
- if (value != ArtifactFileMetadata.PLACEHOLDER) {
+ if (value != FileArtifactValue.PLACEHOLDER) {
return value;
}
@@ -279,11 +275,8 @@
additionalOutputData.get(artifact),
"Placeholder without corresponding FileArtifactValue for: %s",
artifact);
- FileStateValue.RegularFileStateValue fileStateValue =
- new FileStateValue.RegularFileStateValue(
- metadata.getSize(), metadata.getDigest(), /*contentsProxy=*/ null);
- PathFragment pathFragment = artifact.getPath().asFragment();
- return ArtifactFileMetadata.forRegularFile(pathFragment, fileStateValue);
+
+ return metadata;
}
/**
@@ -293,7 +286,7 @@
private static final class CrossServerUnshareableActionExecutionValue
extends ActionExecutionValue {
CrossServerUnshareableActionExecutionValue(
- Map<Artifact, ArtifactFileMetadata> artifactData,
+ Map<Artifact, FileArtifactValue> artifactData,
Map<Artifact, TreeArtifactValue> treeArtifactData,
Map<Artifact, FileArtifactValue> additionalOutputData,
@Nullable ImmutableList<FilesetOutputSymlink> outputSymlinks,
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 4363a68..97ce7c6 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
@@ -27,10 +27,10 @@
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
-import com.google.devtools.build.lib.actions.ArtifactFileMetadata;
import com.google.devtools.build.lib.actions.ArtifactPathResolver;
import com.google.devtools.build.lib.actions.FileArtifactValue;
import com.google.devtools.build.lib.actions.FileArtifactValue.RemoteFileArtifactValue;
+import com.google.devtools.build.lib.actions.FileStateType;
import com.google.devtools.build.lib.actions.FileStateValue;
import com.google.devtools.build.lib.actions.cache.DigestUtils;
import com.google.devtools.build.lib.actions.cache.Md5Digest;
@@ -218,7 +218,7 @@
// Check for existing metadata. It may have been injected. In either case, this method is called
// from SkyframeActionExecutor to make sure that we have metadata for all action outputs, as the
// results are then stored in Skyframe (and the action cache).
- ArtifactFileMetadata fileMetadata = store.getArtifactData(artifact);
+ FileArtifactValue fileMetadata = store.getArtifactData(artifact);
if (fileMetadata != null) {
// Non-middleman artifacts should only have additionalOutputData if they have
// outputArtifactData. We don't assert this because of concurrency possibilities, but at least
@@ -229,10 +229,10 @@
if (value != null) {
return metadataFromValue(value);
}
- if (!fileMetadata.exists()) {
+ if (fileMetadata.getType() == FileStateType.NONEXISTENT) {
throw new FileNotFoundException(artifact.prettyPrint() + " does not exist");
}
- return FileArtifactValue.createFromMetadata(fileMetadata, !artifact.isConstantMetadata());
+ return fileMetadata;
}
// No existing metadata; this can happen if the output metadata is not injected after a spawn
@@ -247,7 +247,7 @@
//
// We only cache nonexistence here, not file system errors. It is unlikely that the file will be
// requested from this cache too many times.
- fileMetadata = constructArtifactFileMetadata(artifact, /*statNoFollow=*/ null);
+ fileMetadata = constructFileArtifactValue(artifact, /*statNoFollow=*/ null);
return maybeStoreAdditionalData(artifact, fileMetadata, null);
}
@@ -261,22 +261,22 @@
* additional data, even for normal (non-middleman) artifacts.
*/
private FileArtifactValue maybeStoreAdditionalData(
- Artifact artifact, ArtifactFileMetadata data, @Nullable byte[] injectedDigest)
+ Artifact artifact, FileArtifactValue data, @Nullable byte[] injectedDigest)
throws IOException {
- if (!data.exists()) {
+ if (data.getType() == FileStateType.NONEXISTENT) {
// Nonexistent files should only occur before executing an action.
throw new FileNotFoundException(artifact.prettyPrint() + " does not exist");
}
- boolean isFile = data.isFile();
+ boolean isFile = data.getType() == FileStateType.REGULAR_FILE;
if (isFile && !artifact.hasParent() && data.getDigest() != null) {
// We do not need to store the FileArtifactValue separately -- the digest is in the file value
// and that is all that is needed for this file's metadata.
- return FileArtifactValue.createFromMetadata(data, !artifact.isConstantMetadata());
+ return data;
}
final FileArtifactValue value;
- if (data.isDirectory()) {
+ if (data.getType() == FileStateType.DIRECTORY) {
// This branch is taken when the output of an action is a directory:
// - A Fileset (in this case, Blaze is correct)
// - A directory someone created in a local action (in this case, changes under the
@@ -382,14 +382,14 @@
for (TreeFileArtifact treeFileArtifact : contents) {
FileArtifactValue cachedValue = store.getAdditionalOutputData(treeFileArtifact);
if (cachedValue == null) {
- ArtifactFileMetadata fileMetadata = store.getArtifactData(treeFileArtifact);
+ FileArtifactValue fileMetadata = store.getArtifactData(treeFileArtifact);
// This is similar to what's present in getRealMetadataForArtifact, except
// we get back the ArtifactFileMetadata, not the metadata.
// We do not cache exceptions besides nonexistence here, because it is unlikely that the
// file will be requested from this cache too many times.
if (fileMetadata == null) {
try {
- fileMetadata = constructArtifactFileMetadata(treeFileArtifact, /*statNoFollow=*/ null);
+ fileMetadata = constructFileArtifactValue(treeFileArtifact, /*statNoFollow=*/ null);
} catch (FileNotFoundException e) {
String errorMessage = String.format(
"Failed to resolve relative path %s inside TreeArtifact %s. "
@@ -450,10 +450,10 @@
// Assumption: any non-Artifact output is 'virtual' and should be ignored here.
if (output instanceof Artifact) {
final Artifact artifact = (Artifact) output;
- // We have to add the artifact to injectedFiles before calling constructArtifactFileMetadata
+ // We have to add the artifact to injectedFiles before calling constructFileArtifactValue
// to avoid duplicate chmod calls.
store.injectedFiles().add(artifact);
- ArtifactFileMetadata fileMetadata;
+ FileArtifactValue fileMetadata;
try {
// This call may do an unnecessary call to Path#getFastDigest to see if the digest is
// readily available. We cannot pass the digest in, though, because if it is not available
@@ -461,8 +461,7 @@
// created for the
// same file, because the other one will be missing its digest.
fileMetadata =
- constructArtifactFileMetadata(
- artifact, FileStatusWithDigestAdapter.adapt(statNoFollow));
+ constructFileArtifactValue(artifact, FileStatusWithDigestAdapter.adapt(statNoFollow));
// Ensure the digest supplied matches the actual digest if it exists.
byte[] fileDigest = fileMetadata.getDigest();
if (fileDigest != null && !Arrays.equals(digest, fileDigest)) {
@@ -574,10 +573,10 @@
}
/**
- * Constructs a new {@link ArtifactFileMetadata}, saves it, and checks inconsistent data. This
- * calls chmod on the file if we're in executionMode.
+ * Constructs a new {@link FileArtifactValue}, saves it, and checks inconsistent data. This calls
+ * chmod on the file if we're in executionMode.
*/
- private ArtifactFileMetadata constructArtifactFileMetadata(
+ private FileArtifactValue constructFileArtifactValue(
Artifact artifact, @Nullable FileStatusWithDigest statNoFollow) throws IOException {
// We first chmod the output files before we construct the FileContentsProxy. The proxy may use
// ctime, which is affected by chmod.
@@ -586,23 +585,47 @@
setPathReadOnlyAndExecutable(artifact);
}
- ArtifactFileMetadata value =
- fileMetadataFromArtifact(
+ FileArtifactValue value =
+ fileArtifactValueFromArtifact(
artifact, artifactPathResolver, statNoFollow, getTimestampGranularityMonitor(artifact));
store.putArtifactData(artifact, value);
return value;
}
+ private static FileArtifactValue fileArtifactValueFromStat(
+ RootedPath rootedPath,
+ FileStatusWithDigest stat,
+ boolean isConstantMetadata,
+ TimestampGranularityMonitor tsgm)
+ throws IOException {
+ if (stat == null) {
+ return FileArtifactValue.MISSING_FILE_MARKER;
+ }
+
+ FileStateValue fileStateValue = FileStateValue.createWithStatNoFollow(rootedPath, stat, tsgm);
+
+ if (stat.isDirectory()) {
+ return FileArtifactValue.createForDirectoryWithMtime(stat.getLastModifiedTime());
+ } else {
+ return FileArtifactValue.createForNormalFile(
+ fileStateValue.getDigest(),
+ fileStateValue.getContentsProxy(),
+ stat.getSize(),
+ !isConstantMetadata);
+ }
+ }
+
@VisibleForTesting
- static ArtifactFileMetadata fileMetadataFromArtifact(
+ static FileArtifactValue fileArtifactValueFromArtifact(
Artifact artifact,
@Nullable FileStatusWithDigest statNoFollow,
@Nullable TimestampGranularityMonitor tsgm)
throws IOException {
- return fileMetadataFromArtifact(artifact, ArtifactPathResolver.IDENTITY, statNoFollow, tsgm);
+ return fileArtifactValueFromArtifact(
+ artifact, ArtifactPathResolver.IDENTITY, statNoFollow, tsgm);
}
- private static ArtifactFileMetadata fileMetadataFromArtifact(
+ private static FileArtifactValue fileArtifactValueFromArtifact(
Artifact artifact,
ArtifactPathResolver artifactPathResolver,
@Nullable FileStatusWithDigest statNoFollow,
@@ -611,31 +634,25 @@
Preconditions.checkState(!artifact.isTreeArtifact());
Preconditions.checkState(!artifact.isMiddlemanArtifact());
- Path path = artifactPathResolver.toPath(artifact);
- PathFragment pathFragment = path.asFragment();
- RootedPath rootedPath =
+ Path pathNoFollow = artifactPathResolver.toPath(artifact);
+ RootedPath rootedPathNoFollow =
RootedPath.toRootedPath(
artifactPathResolver.transformRoot(artifact.getRoot().getRoot()),
artifact.getRootRelativePath());
if (statNoFollow == null) {
- statNoFollow = FileStatusWithDigestAdapter.adapt(path.statIfFound(Symlinks.NOFOLLOW));
- if (statNoFollow == null) {
- return ArtifactFileMetadata.forRegularFile(
- pathFragment, FileStateValue.NONEXISTENT_FILE_STATE_NODE);
- }
+ statNoFollow = FileStatusWithDigestAdapter.adapt(pathNoFollow.statIfFound(Symlinks.NOFOLLOW));
}
- FileStateValue fileStateValue =
- FileStateValue.createWithStatNoFollow(rootedPath, statNoFollow, tsgm);
- if (!statNoFollow.isSymbolicLink()) {
- return ArtifactFileMetadata.forRegularFile(path.asFragment(), fileStateValue);
+ if (statNoFollow == null || !statNoFollow.isSymbolicLink()) {
+ return fileArtifactValueFromStat(
+ rootedPathNoFollow, statNoFollow, artifact.isConstantMetadata(), tsgm);
}
// We use FileStatus#isSymbolicLink over Path#isSymbolicLink to avoid the unnecessary stat
// done by the latter. We need to protect against symlink cycles since
// ArtifactFileMetadata#value assumes it's dealing with a file that's not in a symlink cycle.
- Path realPath = path.resolveSymbolicLinks();
- if (realPath.equals(path)) {
+ Path realPath = pathNoFollow.resolveSymbolicLinks();
+ if (realPath.equals(pathNoFollow)) {
throw new IOException("symlink cycle");
}
@@ -646,8 +663,10 @@
// TODO(bazel-team): consider avoiding a 'stat' here when the symlink target hasn't changed
// and is a source file (since changes to those are checked separately).
- FileStateValue realFileStateValue = FileStateValue.create(realRootedPath, tsgm);
- return ArtifactFileMetadata.forRegularFile(realPath.asFragment(), realFileStateValue);
+ FileStatus realStat = realRootedPath.asPath().statIfFound(Symlinks.NOFOLLOW);
+ FileStatusWithDigest realStatWithDigest = FileStatusWithDigestAdapter.adapt(realStat);
+ return fileArtifactValueFromStat(
+ realRootedPath, realStatWithDigest, artifact.isConstantMetadata(), tsgm);
}
private void setPathReadOnlyAndExecutable(Artifact artifact) throws IOException {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java
index d66c150..0e32d6f 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java
@@ -27,9 +27,9 @@
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.DerivedArtifact;
import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
-import com.google.devtools.build.lib.actions.ArtifactFileMetadata;
import com.google.devtools.build.lib.actions.ArtifactOwner;
import com.google.devtools.build.lib.actions.FileArtifactValue;
+import com.google.devtools.build.lib.actions.FileStateType;
import com.google.devtools.build.lib.actions.FileValue;
import com.google.devtools.build.lib.actions.FilesetTraversalParams.DirectTraversalRoot;
import com.google.devtools.build.lib.actions.FilesetTraversalParams.PackageBoundaryMode;
@@ -294,14 +294,18 @@
if (value != null) {
return value;
}
- ArtifactFileMetadata data =
+ FileArtifactValue data =
Preconditions.checkNotNull(actionValue.getData(artifact), "%s %s", artifact, actionValue);
Preconditions.checkNotNull(
data.getDigest(), "Digest should already have been calculated for %s (%s)", artifact, data);
// Directories are special-cased because their mtimes are used, so should have been constructed
// during execution of the action (in ActionMetadataHandler#maybeStoreAdditionalData).
- Preconditions.checkState(data.isFile(), "Unexpected not file %s (%s)", artifact, data);
- return FileArtifactValue.createFromMetadata(data, !artifact.isConstantMetadata());
+ Preconditions.checkState(
+ data.getType() == FileStateType.REGULAR_FILE,
+ "Unexpected not file %s (%s)",
+ artifact,
+ data);
+ return data;
}
@Nullable
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/FilesystemValueChecker.java b/src/main/java/com/google/devtools/build/lib/skyframe/FilesystemValueChecker.java
index d880c64..40bf9fd 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/FilesystemValueChecker.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/FilesystemValueChecker.java
@@ -25,8 +25,8 @@
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.ArtifactFileMetadata;
import com.google.devtools.build.lib.actions.FileArtifactValue;
+import com.google.devtools.build.lib.actions.FileStateType;
import com.google.devtools.build.lib.concurrent.ExecutorUtil;
import com.google.devtools.build.lib.concurrent.Sharder;
import com.google.devtools.build.lib.concurrent.ThrowableRecordingRunnableWrapper;
@@ -304,10 +304,10 @@
Pair<SkyKey, ActionExecutionValue> keyAndValue = fileToKeyAndValue.get(artifact);
ActionExecutionValue actionValue = keyAndValue.getSecond();
SkyKey key = keyAndValue.getFirst();
- ArtifactFileMetadata lastKnownData = actionValue.getAllFileValues().get(artifact);
+ FileArtifactValue lastKnownData = actionValue.getAllFileValues().get(artifact);
try {
- ArtifactFileMetadata newData =
- ActionMetadataHandler.fileMetadataFromArtifact(artifact, stat, tsgm);
+ FileArtifactValue newData =
+ ActionMetadataHandler.fileArtifactValueFromArtifact(artifact, stat, tsgm);
if (!newData.equals(lastKnownData)) {
updateIntraBuildModifiedCounter(stat != null ? stat.getLastChangeTime() : -1);
modifiedOutputFilesCounter.getAndIncrement();
@@ -403,20 +403,22 @@
ImmutableSet<PathFragment> knownModifiedOutputFiles,
Supplier<NavigableSet<PathFragment>> sortedKnownModifiedOutputFiles) {
boolean isDirty = false;
- for (Map.Entry<Artifact, ArtifactFileMetadata> entry :
- actionValue.getAllFileValues().entrySet()) {
+ for (Map.Entry<Artifact, FileArtifactValue> entry : actionValue.getAllFileValues().entrySet()) {
Artifact file = entry.getKey();
- ArtifactFileMetadata lastKnownData = entry.getValue();
+ FileArtifactValue lastKnownData = entry.getValue();
if (shouldCheckFile(knownModifiedOutputFiles, file)) {
try {
- ArtifactFileMetadata fileMetadata =
- ActionMetadataHandler.fileMetadataFromArtifact(file, null, tsgm);
+ FileArtifactValue fileMetadata =
+ ActionMetadataHandler.fileArtifactValueFromArtifact(file, null, tsgm);
FileArtifactValue fileValue = actionValue.getArtifactValue(file);
boolean lastSeenRemotely = (fileValue != null) && fileValue.isRemote();
- boolean trustRemoteValue = !fileMetadata.exists() && lastSeenRemotely;
+ boolean trustRemoteValue =
+ fileMetadata.getType() == FileStateType.NONEXISTENT && lastSeenRemotely;
if (!trustRemoteValue && !fileMetadata.equals(lastKnownData)) {
updateIntraBuildModifiedCounter(
- fileMetadata.exists() ? file.getPath().getLastModifiedTime(Symlinks.FOLLOW) : -1);
+ fileMetadata.getType() != FileStateType.NONEXISTENT
+ ? file.getPath().getLastModifiedTime(Symlinks.FOLLOW)
+ : -1);
modifiedOutputFilesCounter.getAndIncrement();
isDirty = true;
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/MinimalOutputStore.java b/src/main/java/com/google/devtools/build/lib/skyframe/MinimalOutputStore.java
index 7f07c14..0c9b9ca 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/MinimalOutputStore.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/MinimalOutputStore.java
@@ -15,7 +15,6 @@
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
-import com.google.devtools.build.lib.actions.ArtifactFileMetadata;
import com.google.devtools.build.lib.actions.FileArtifactValue;
/**
@@ -35,7 +34,7 @@
}
@Override
- void putArtifactData(Artifact artifact, ArtifactFileMetadata value) {}
+ void putArtifactData(Artifact artifact, FileArtifactValue value) {}
@Override
void addTreeArtifactContents(Artifact artifact, TreeFileArtifact contents) {}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/OutputStore.java b/src/main/java/com/google/devtools/build/lib/skyframe/OutputStore.java
index 60a0ef2..ed034bd 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/OutputStore.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/OutputStore.java
@@ -18,7 +18,6 @@
import com.google.common.collect.Sets;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
-import com.google.devtools.build.lib.actions.ArtifactFileMetadata;
import com.google.devtools.build.lib.actions.FileArtifactValue;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import java.util.Set;
@@ -40,8 +39,7 @@
@ThreadSafe
class OutputStore {
- private final ConcurrentMap<Artifact, ArtifactFileMetadata> artifactData =
- new ConcurrentHashMap<>();
+ private final ConcurrentMap<Artifact, FileArtifactValue> artifactData = new ConcurrentHashMap<>();
private final ConcurrentMap<Artifact, TreeArtifactValue> treeArtifactData =
new ConcurrentHashMap<>();
@@ -55,21 +53,21 @@
private final Set<Artifact> injectedFiles = Sets.newConcurrentHashSet();
@Nullable
- final ArtifactFileMetadata getArtifactData(Artifact artifact) {
+ final FileArtifactValue getArtifactData(Artifact artifact) {
return artifactData.get(artifact);
}
- void putArtifactData(Artifact artifact, ArtifactFileMetadata value) {
+ void putArtifactData(Artifact artifact, FileArtifactValue value) {
artifactData.put(artifact, value);
}
/**
* Returns data for output files that was computed during execution.
*
- * <p>The value is {@link ArtifactFileMetadata#PLACEHOLDER} if the artifact's metadata is not
- * fully captured in {@link #additionalOutputData}.
+ * <p>The value is {@link FileArtifactValue#PLACEHOLDER} if the artifact's metadata is not fully
+ * captured in {@link #additionalOutputData}.
*/
- final ImmutableMap<Artifact, ArtifactFileMetadata> getAllArtifactData() {
+ final ImmutableMap<Artifact, FileArtifactValue> getAllArtifactData() {
return ImmutableMap.copyOf(artifactData);
}
@@ -111,7 +109,7 @@
* <li>If the filesystem does not possess fast digests, then we will have additional output data
* for practically every artifact, since we will need to store their digests.
* <li>If we have a remote execution service injecting metadata, then we will just store that
- * metadata here, and put {@link ArtifactFileMetadata#PLACEHOLDER} objects into {@link
+ * metadata here, and put {@link FileArtifactValue#PLACEHOLDER} objects into {@link
* #outputArtifactData} if the filesystem supports fast digests, and the actual metadata if
* the filesystem does not support fast digests.
* <li>If the filesystem has fast digests <i>but</i> there is no remote execution injecting
@@ -123,13 +121,13 @@
* populated. Locally executed actions are the exception to this rule inside Google.
*
* <p>Moreover, there are some artifacts that are always stored here. First, middleman artifacts
- * have no corresponding {@link ArtifactFileMetadata}. Second, directories' metadata contain their
- * mtimes, which the {@link ArtifactFileMetadata} does not expose, so that has to be stored
+ * have no corresponding {@link FileArtifactValue}. Second, directories' metadata contain their
+ * mtimes, which the {@link FileArtifactValue} does not expose, so that has to be stored
* separately.
*
* <p>Note that for files that need digests, we can't easily inject the digest in the {@link
- * ArtifactFileMetadata} because it would complicate equality-checking on subsequent builds -- if
- * our filesystem doesn't do fast digests, the comparison value would not have a digest.
+ * FileArtifactValue} because it would complicate equality-checking on subsequent builds -- if our
+ * filesystem doesn't do fast digests, the comparison value would not have a digest.
*/
final ImmutableMap<Artifact, FileArtifactValue> getAllAdditionalOutputData() {
return ImmutableMap.copyOf(additionalOutputData);
@@ -167,7 +165,7 @@
// While `artifactValue` carries the important information, consumers also require an entry in
// `artifactData` so a `PLACEHOLDER` is added to `artifactData`.
- artifactData.put(output, ArtifactFileMetadata.PLACEHOLDER);
+ artifactData.put(output, FileArtifactValue.PLACEHOLDER);
additionalOutputData.put(output, artifactValue);
}
diff --git a/src/test/java/com/google/devtools/build/lib/actions/ActionInputMapTest.java b/src/test/java/com/google/devtools/build/lib/actions/ActionInputMapTest.java
index 5402175..c67e7a1 100644
--- a/src/test/java/com/google/devtools/build/lib/actions/ActionInputMapTest.java
+++ b/src/test/java/com/google/devtools/build/lib/actions/ActionInputMapTest.java
@@ -193,6 +193,21 @@
}
@Override
+ public boolean isRemote() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isMarkerValue() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public FileContentsProxy getContentsProxy() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
@SuppressWarnings("EqualsHashCode")
public boolean equals(Object o) {
if (!(o instanceof TestMetadata)) {
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 07a020b..9b1e112 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
@@ -31,7 +31,6 @@
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifactType;
import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
-import com.google.devtools.build.lib.actions.ArtifactFileMetadata;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.actions.BasicActionLookupValue;
import com.google.devtools.build.lib.actions.FileArtifactValue;
@@ -263,8 +262,8 @@
ActionLookupData dummyData = ActionLookupData.create(ALL_OWNER, 0);
Artifact.DerivedArtifact artifact1 = createDerivedArtifact("one");
Artifact.DerivedArtifact artifact2 = createDerivedArtifact("two");
- ArtifactFileMetadata metadata1 =
- ActionMetadataHandler.fileMetadataFromArtifact(artifact1, null, null);
+ FileArtifactValue metadata1 =
+ ActionMetadataHandler.fileArtifactValueFromArtifact(artifact1, null, null);
SpecialArtifact treeArtifact = createDerivedTreeArtifactOnly("tree");
treeArtifact.setGeneratingActionKey(dummyData);
TreeFileArtifact treeFileArtifact = ActionInputHelper.treeFileArtifact(treeArtifact, "subpath");
@@ -281,7 +280,7 @@
PathFragment.EMPTY_FRAGMENT, PathFragment.EMPTY_FRAGMENT, PathFragment.EMPTY_FRAGMENT);
ActionExecutionValue actionExecutionValue =
ActionExecutionValue.create(
- ImmutableMap.of(artifact1, metadata1, artifact2, ArtifactFileMetadata.PLACEHOLDER),
+ ImmutableMap.of(artifact1, metadata1, artifact2, FileArtifactValue.PLACEHOLDER),
ImmutableMap.of(treeArtifact, treeArtifactValue),
ImmutableMap.of(artifact3, FileArtifactValue.DEFAULT_MIDDLEMAN),
ImmutableList.of(filesetOutputSymlink),
@@ -289,7 +288,7 @@
true);
ActionExecutionValue valueWithFingerprint =
ActionExecutionValue.create(
- ImmutableMap.of(artifact1, metadata1, artifact2, ArtifactFileMetadata.PLACEHOLDER),
+ ImmutableMap.of(artifact1, metadata1, artifact2, FileArtifactValue.PLACEHOLDER),
ImmutableMap.of(treeArtifact, treeArtifactValue),
ImmutableMap.of(artifact3, FileArtifactValue.DEFAULT_MIDDLEMAN),
ImmutableList.of(filesetOutputSymlink),
@@ -417,7 +416,7 @@
private static class SimpleActionExecutionFunction implements SkyFunction {
@Override
public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
- Map<Artifact, ArtifactFileMetadata> artifactData = new HashMap<>();
+ Map<Artifact, FileArtifactValue> artifactData = new HashMap<>();
Map<Artifact, TreeArtifactValue> treeArtifactData = new HashMap<>();
Map<Artifact, FileArtifactValue> additionalOutputData = new HashMap<>();
ActionLookupData actionLookupData = (ActionLookupData) skyKey.argument();
@@ -439,10 +438,11 @@
treeFileArtifact2, FileArtifactValue.createForTesting(treeFileArtifact2)));
treeArtifactData.put(output, treeArtifactValue);
} else if (action.getActionType() == MiddlemanType.NORMAL) {
- ArtifactFileMetadata fileValue =
- ActionMetadataHandler.fileMetadataFromArtifact(output, null, null);
+ FileArtifactValue fileValue =
+ ActionMetadataHandler.fileArtifactValueFromArtifact(output, null, null);
artifactData.put(output, fileValue);
- additionalOutputData.put(output, FileArtifactValue.createForTesting(output, fileValue));
+ additionalOutputData.put(
+ output, FileArtifactValue.injectDigestForTesting(output, fileValue));
} else {
additionalOutputData.put(output, FileArtifactValue.DEFAULT_MIDDLEMAN);
}
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 55e4524..4d9e29a 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
@@ -30,7 +30,6 @@
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifactType;
import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
-import com.google.devtools.build.lib.actions.ArtifactFileMetadata;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.actions.FileArtifactValue;
import com.google.devtools.build.lib.actions.FileArtifactValue.RemoteFileArtifactValue;
@@ -729,14 +728,14 @@
// Presently these appear to be untested.
private ActionExecutionValue actionValue(Action action, boolean forceDigest) {
- Map<Artifact, ArtifactFileMetadata> artifactData = new HashMap<>();
+ Map<Artifact, FileArtifactValue> artifactData = new HashMap<>();
for (Artifact output : action.getOutputs()) {
try {
Path path = output.getPath();
FileStatusWithDigest stat =
forceDigest ? statWithDigest(path, path.statIfFound(Symlinks.NOFOLLOW)) : null;
artifactData.put(
- output, ActionMetadataHandler.fileMetadataFromArtifact(output, stat, null));
+ output, ActionMetadataHandler.fileArtifactValueFromArtifact(output, stat, null));
} catch (IOException e) {
throw new IllegalStateException(e);
}
@@ -764,7 +763,7 @@
}
private ActionExecutionValue actionValueWithTreeArtifacts(List<TreeFileArtifact> contents) {
- Map<Artifact, ArtifactFileMetadata> fileData = new HashMap<>();
+ Map<Artifact, FileArtifactValue> fileData = new HashMap<>();
Map<Artifact, Map<TreeFileArtifact, FileArtifactValue>> directoryData = new HashMap<>();
for (TreeFileArtifact output : contents) {
@@ -775,9 +774,9 @@
dirDatum = new HashMap<>();
directoryData.put(output.getParent(), dirDatum);
}
- ArtifactFileMetadata fileValue =
- ActionMetadataHandler.fileMetadataFromArtifact(output, null, null);
- dirDatum.put(output, FileArtifactValue.createForTesting(output, fileValue));
+ FileArtifactValue fileValue =
+ ActionMetadataHandler.fileArtifactValueFromArtifact(output, null, null);
+ dirDatum.put(output, FileArtifactValue.injectDigestForTesting(output, fileValue));
fileData.put(output, fileValue);
} catch (IOException e) {
throw new IllegalStateException(e);
@@ -822,7 +821,7 @@
private ActionExecutionValue actionValueWithRemoteArtifact(
Artifact output, RemoteFileArtifactValue value) {
return ActionExecutionValue.create(
- Collections.singletonMap(output, ArtifactFileMetadata.PLACEHOLDER),
+ Collections.singletonMap(output, FileArtifactValue.PLACEHOLDER),
ImmutableMap.of(),
Collections.singletonMap(output, value),
/* outputSymlinks= */ null,
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 adb9788..76407e4 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
@@ -32,7 +32,6 @@
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifactType;
import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
-import com.google.devtools.build.lib.actions.ArtifactFileMetadata;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.actions.BasicActionLookupValue;
import com.google.devtools.build.lib.actions.FileArtifactValue;
@@ -279,7 +278,7 @@
@Override
public SkyValue compute(SkyKey skyKey, Environment env)
throws SkyFunctionException, InterruptedException {
- Map<Artifact, ArtifactFileMetadata> fileData = new HashMap<>();
+ Map<Artifact, FileArtifactValue> fileData = new HashMap<>();
Map<TreeFileArtifact, FileArtifactValue> treeArtifactData = new HashMap<>();
ActionLookupData actionLookupData = (ActionLookupData) skyKey.argument();
ActionLookupValue actionLookupValue =
@@ -289,10 +288,11 @@
for (PathFragment subpath : testTreeArtifactContents) {
try {
TreeFileArtifact suboutput = ActionInputHelper.treeFileArtifact(output, subpath);
- ArtifactFileMetadata fileValue =
- ActionMetadataHandler.fileMetadataFromArtifact(suboutput, null, null);
+ FileArtifactValue fileValue =
+ ActionMetadataHandler.fileArtifactValueFromArtifact(suboutput, null, null);
fileData.put(suboutput, fileValue);
- treeArtifactData.put(suboutput, FileArtifactValue.createForTesting(suboutput, fileValue));
+ treeArtifactData.put(
+ suboutput, FileArtifactValue.injectDigestForTesting(suboutput, fileValue));
} catch (IOException e) {
throw new SkyFunctionException(e, Transience.TRANSIENT) {};
}