diff options
Diffstat (limited to 'src/main/java/com')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/actions/cache/VirtualActionInput.java | 9 | ||||
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/exec/BinTools.java | 94 |
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 <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; + } + } } |