aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java
diff options
context:
space:
mode:
authorGravatar ulfjack <ulfjack@google.com>2018-02-20 05:57:49 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2018-02-20 05:59:23 -0800
commit2c05aff6cf12d72b20435b152f71ca1f0bce55ec (patch)
tree6e07ea080543e7a0f1c0e7ab0a085bf90436da79 /src/main/java
parent9f608c2c17351c1e4e802db55d98542b15c9de88 (diff)
Provide a hacky way to get an ActionInput from BinTools
We have two places in internal code that require an ActionInput for an embedded tool. The embedded tool is currently not declared as an input to the corresponding actions, which in turn causes the remote execution to stat the file directly through SingleBuildFileCache. I'm working on removing SingleBuildFileCache, so this needs to be solved. This is the quick-and-dirty fix. A more principled fix might be to check in the relevant tools instead of embedding them into Bazel, but it's also significantly more work. PiperOrigin-RevId: 186292203
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/actions/cache/VirtualActionInput.java9
-rw-r--r--src/main/java/com/google/devtools/build/lib/exec/BinTools.java94
2 files changed, 103 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/actions/cache/VirtualActionInput.java b/src/main/java/com/google/devtools/build/lib/actions/cache/VirtualActionInput.java
index c43b0549bd..e4c52747e2 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/cache/VirtualActionInput.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/cache/VirtualActionInput.java
@@ -38,6 +38,15 @@ public interface VirtualActionInput extends ActionInput {
ByteString getBytes() throws IOException;
/**
+ * Returns the Metadata for this input if available. Null otherwise.
+ *
+ * @throws IOException
+ */
+ default Metadata getMetadata() throws IOException {
+ return null;
+ }
+
+ /**
* In some cases, we want empty files in the runfiles tree that have no corresponding artifact. We
* use instances of this class to represent those files.
*/
diff --git a/src/main/java/com/google/devtools/build/lib/exec/BinTools.java b/src/main/java/com/google/devtools/build/lib/exec/BinTools.java
index e6ca7fb382..c754386c56 100644
--- a/src/main/java/com/google/devtools/build/lib/exec/BinTools.java
+++ b/src/main/java/com/google/devtools/build/lib/exec/BinTools.java
@@ -17,15 +17,26 @@ package com.google.devtools.build.lib.exec;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.hash.Hasher;
+import com.google.common.io.ByteStreams;
+import com.google.devtools.build.lib.actions.ActionInput;
import com.google.devtools.build.lib.actions.EnvironmentalExecException;
import com.google.devtools.build.lib.actions.ExecException;
+import com.google.devtools.build.lib.actions.cache.Metadata;
+import com.google.devtools.build.lib.actions.cache.VirtualActionInput;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
+import com.google.devtools.build.lib.skyframe.FileArtifactValue;
import com.google.devtools.build.lib.vfs.Dirent;
+import com.google.devtools.build.lib.vfs.FileSystem.HashFunction;
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;
+import com.google.protobuf.ByteString;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
/**
* Initializes the &lt;execRoot>/_bin/ directory that contains auxiliary tools used during action
@@ -36,6 +47,7 @@ public final class BinTools {
private final Path embeddedBinariesRoot;
private final Path execrootParent;
private final ImmutableList<String> embeddedTools;
+ private ImmutableMap<String, ActionInput> actionInputs;
private Path binDir; // the working bin directory under execRoot
@@ -61,6 +73,16 @@ public final class BinTools {
this.binDir = null;
}
+ private ImmutableMap<String, ActionInput> populateActionInputMap() {
+ ImmutableMap.Builder<String, ActionInput> result = ImmutableMap.builder();
+ for (String embeddedPath : embeddedTools) {
+ PathFragment execPath = getExecPath(embeddedPath);
+ Path path = binDir.getRelative(execPath.getBaseName());
+ result.put(embeddedPath, new PathActionInput(path, execPath));
+ }
+ return result.build();
+ }
+
/**
* Creates an instance with the list of embedded tools obtained from scanning the directory
* into which said binaries were extracted by the launcher.
@@ -137,6 +159,16 @@ public final class BinTools {
}
}
+ /**
+ * Returns an action input for the given embedded tool.
+ */
+ public ActionInput getActionInput(String embeddedPath) {
+ if (actionInputs == null) {
+ actionInputs = populateActionInputMap();
+ }
+ return actionInputs.get(embeddedPath);
+ }
+
public PathFragment getExecPath(String embedPath) {
if (!embeddedTools.contains(embedPath)) {
return null;
@@ -194,4 +226,66 @@ public final class BinTools {
}
}
}
+
+ /** An ActionInput pointing at an absolute path. */
+ public static final class PathActionInput implements VirtualActionInput {
+ private final Path path;
+ private final PathFragment execPath;
+ private Metadata metadata;
+
+ public PathActionInput(Path path, PathFragment execPath) {
+ this.path = path;
+ this.execPath = execPath;
+ }
+
+ @Override
+ public void writeTo(OutputStream out) throws IOException {
+ try (InputStream in = path.getInputStream()) {
+ ByteStreams.copy(in, out);
+ }
+ }
+
+ @Override
+ public ByteString getBytes() throws IOException {
+ ByteString.Output out = ByteString.newOutput();
+ writeTo(out);
+ return out.toByteString();
+ }
+
+ @Override
+ public synchronized Metadata getMetadata() throws IOException {
+ // We intentionally delay hashing until it is necessary.
+ if (metadata == null) {
+ metadata = hash(path);
+ }
+ return metadata;
+ }
+
+ private static Metadata hash(Path path) throws IOException {
+ HashFunction hashFn = path.getFileSystem().getDigestFunction();
+ Hasher hasher = hashFn.getHash().newHasher();
+ int bytesCopied = 0;
+ try (InputStream in = path.getInputStream()) {
+ byte[] buffer = new byte[1024];
+ int len;
+ while ((len = in.read(buffer)) > 0) {
+ hasher.putBytes(buffer, 0, len);
+ bytesCopied += len;
+ }
+ }
+ return FileArtifactValue.createForVirtualActionInput(
+ hasher.hash().asBytes(),
+ bytesCopied);
+ }
+
+ @Override
+ public String getExecPathString() {
+ return execPath.getPathString();
+ }
+
+ @Override
+ public PathFragment getExecPath() {
+ return execPath;
+ }
+ }
}