Attempt #2 to submit commit e860316559eac366d47923a8eb4b5489a661aa35: Using an ActionFileInputCache for SHA1 digests used with remote execution.
I missed an important test failure -- turned out we have a remote execution
test that does not live under lib/remote.
--
MOS_MIGRATED_REVID=140135277
diff --git a/src/main/java/com/google/devtools/build/lib/remote/ContentDigests.java b/src/main/java/com/google/devtools/build/lib/remote/ContentDigests.java
index 9294189..e7772b2 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/ContentDigests.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/ContentDigests.java
@@ -82,9 +82,7 @@
}
public static String toHexString(ContentDigest digest) {
- return digest.getSizeBytes() > 0
- ? HashCode.fromBytes(digest.getDigest().toByteArray()).toString()
- : "";
+ return HashCode.fromBytes(digest.getDigest().toByteArray()).toString();
}
public static String toString(ContentDigest digest) {
diff --git a/src/main/java/com/google/devtools/build/lib/remote/GrpcActionCache.java b/src/main/java/com/google/devtools/build/lib/remote/GrpcActionCache.java
index 5004748..0563c68 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/GrpcActionCache.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/GrpcActionCache.java
@@ -629,7 +629,6 @@
ExecutionCacheReply reply = stub.getCachedResult(request);
ExecutionCacheStatus status = reply.getStatus();
if (!status.getSucceeded()
- && status.getError() != ExecutionCacheStatus.ErrorCode.UNSUPPORTED
&& status.getError() != ExecutionCacheStatus.ErrorCode.MISSING_RESULT) {
throw new RuntimeException(status.getErrorDetail());
}
@@ -650,7 +649,8 @@
.build();
ExecutionCacheSetReply reply = stub.setCachedResult(request);
ExecutionCacheStatus status = reply.getStatus();
- if (!status.getSucceeded()) {
+ if (!status.getSucceeded()
+ && status.getError() != ExecutionCacheStatus.ErrorCode.UNSUPPORTED) {
throw new RuntimeException(status.getErrorDetail());
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/remote/README.md b/src/main/java/com/google/devtools/build/lib/remote/README.md
index f778ede..b0598ac 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/README.md
+++ b/src/main/java/com/google/devtools/build/lib/remote/README.md
@@ -9,7 +9,8 @@
- Then you run Bazel pointing to the Hazelcast server.
- bazel build --hazelcast_node=localhost:5701 --spawn_strategy=remote \
+ bazel --host_jvm_args=-Dbazel.DigestFunction=SHA1 build \
+ --hazelcast_node=localhost:5701 --spawn_strategy=remote \
src/tools/generate_workspace:all
Above command will build generate_workspace with remote spawn strategy that uses
@@ -25,6 +26,33 @@
- Then run Bazel pointing to the Hazelcast server and remote worker.
- bazel build --hazelcast_node=localhost:5701 \
+ bazel --host_jvm_args=-Dbazel.DigestFunction=SHA1 build \
+ --hazelcast_node=localhost:5701 \
--remote_worker=localhost:8080 \
--spawn_strategy=remote src/tools/generate_workspace:all
+
+# How to run a remote worker with a remote cache server.
+
+- First you need to run a standalone Hazelcast server with default
+configuration. If you already have a separate Hazelcast cluster you can skip
+this step.
+
+ java -cp third_party/hazelcast/hazelcast-3.6.4.jar \
+ com.hazelcast.core.server.StartServer
+
+- Then run the remote cache server:
+
+ bazel-bin/src/tools/remote_worker/remote_cache --listen_port 8081
+
+- The run the remote worker:
+
+ bazel-bin/src/tools/remote_worker/remote_worker \
+ --work_path=/tmp/remote --listen_port 8080
+
+- Then run Bazel pointing to the cache server and remote worker.
+
+ bazel --host_jvm_args=-Dbazel.DigestFunction=SHA1 build \
+ --hazelcast_node=localhost:5701 \
+ --remote_worker=localhost:8080 \
+ --remote_cache=localhost:8081 \
+ --spawn_strategy=remote src/tools/generate_workspace:all
diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteActionCache.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteActionCache.java
index 62790e8..cc0720b 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/RemoteActionCache.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteActionCache.java
@@ -61,9 +61,8 @@
throws IOException, InterruptedException;
/**
- * Put the file contents cache if it is not already in it. No-op if the file is already stored in
- * cache. The given path must be a full absolute path. Note: this is horribly inefficient, need to
- * patch through an overload that uses an ActionInputFile cache to compute the digests!
+ * Put the file contents in cache if it is not already in it. No-op if the file is already stored
+ * in cache. The given path must be a full absolute path.
*
* @return The key for fetching the file contents blob from cache.
*/
diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java
index 52343b0..7d2845c 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java
@@ -24,6 +24,10 @@
import com.google.devtools.build.lib.runtime.BlazeModule;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
+import com.google.devtools.build.lib.util.AbruptExitException;
+import com.google.devtools.build.lib.util.ExitCode;
+import com.google.devtools.build.lib.vfs.FileSystem;
+import com.google.devtools.build.lib.vfs.FileSystem.HashFunction;
import com.google.devtools.common.options.OptionsBase;
/** RemoteModule provides distributed cache and remote execution for Bazel. */
@@ -66,8 +70,17 @@
}
// Otherwise actionCache remains null and remote caching/execution are disabled.
- if (actionCache != null && RemoteWorkExecutor.isRemoteExecutionOptions(options)) {
- workExecutor = new RemoteWorkExecutor(options);
+ if (actionCache != null) {
+ HashFunction hf = FileSystem.getDigestFunction();
+ if (hf != HashFunction.SHA1) {
+ env.getBlazeModuleEnvironment().exit(new AbruptExitException(
+ "Remote cache/execution requires SHA1 digests, got " + hf
+ + ", run with --host_jvm_args=-Dbazel.DigestFunction=SHA1",
+ ExitCode.COMMAND_LINE_ERROR));
+ }
+ if (RemoteWorkExecutor.isRemoteExecutionOptions(options)) {
+ workExecutor = new RemoteWorkExecutor(options);
+ }
}
} catch (InvalidConfigurationException e) {
env.getReporter().handle(Event.warn(e.toString()));
diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnStrategy.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnStrategy.java
index d2b30ce..a4dcf80 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnStrategy.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnStrategy.java
@@ -21,8 +21,10 @@
import com.google.devtools.build.lib.actions.ActionExecutionContext;
import com.google.devtools.build.lib.actions.ActionInput;
import com.google.devtools.build.lib.actions.ActionInputHelper;
+import com.google.devtools.build.lib.actions.ActionStatusMessage;
import com.google.devtools.build.lib.actions.ExecException;
import com.google.devtools.build.lib.actions.ExecutionStrategy;
+import com.google.devtools.build.lib.actions.Executor;
import com.google.devtools.build.lib.actions.Spawn;
import com.google.devtools.build.lib.actions.SpawnActionContext;
import com.google.devtools.build.lib.actions.Spawns;
@@ -128,6 +130,11 @@
.handle(
Event.warn(
spawn.getMnemonic() + " unsupported operation for action cache (" + e + ")"));
+ } catch (StatusRuntimeException e) {
+ actionExecutionContext
+ .getExecutor()
+ .getEventHandler()
+ .handle(Event.warn(spawn.getMnemonic() + " failed uploading results (" + e + ")"));
}
}
}
@@ -147,6 +154,11 @@
}
}
+ @Override
+ public String toString() {
+ return "remote";
+ }
+
/** Executes the given {@code spawn}. */
@Override
public void exec(Spawn spawn, ActionExecutionContext actionExecutionContext)
@@ -158,7 +170,10 @@
ActionKey actionKey = null;
String mnemonic = spawn.getMnemonic();
- EventHandler eventHandler = actionExecutionContext.getExecutor().getEventHandler();
+ Executor executor = actionExecutionContext.getExecutor();
+ EventHandler eventHandler = executor.getEventHandler();
+ executor.getEventBus().post(
+ ActionStatusMessage.runningStrategy(spawn.getResourceOwner(), "remote"));
try {
// Temporary hack: the TreeNodeRepository should be created and maintained upstream!
diff --git a/src/test/java/com/google/devtools/build/lib/BUILD b/src/test/java/com/google/devtools/build/lib/BUILD
index 9db93c0..47e35ea 100644
--- a/src/test/java/com/google/devtools/build/lib/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/BUILD
@@ -1041,6 +1041,7 @@
":foundations_testutil",
":test_runner",
":testutil",
+ "//src/main/java/com/google/devtools/build/lib:build-base",
"//src/main/java/com/google/devtools/build/lib:preconditions",
"//src/main/java/com/google/devtools/build/lib:vfs",
"//src/main/java/com/google/devtools/build/lib/actions",
diff --git a/src/test/shell/bazel/remote_execution_test.sh b/src/test/shell/bazel/remote_execution_test.sh
index 75bef52..897bdbb 100755
--- a/src/test/shell/bazel/remote_execution_test.sh
+++ b/src/test/shell/bazel/remote_execution_test.sh
@@ -69,7 +69,7 @@
cp bazel-bin/a/test ${TEST_TMPDIR}/test_expected
bazel clean --expunge
- bazel build \
+ bazel --host_jvm_args=-Dbazel.DigestFunction=SHA1 build \
--spawn_strategy=remote \
--hazelcast_node=localhost:${hazelcast_port} \
--remote_worker=localhost:${worker_port} \
diff --git a/src/tools/remote_worker/src/main/java/com/google/devtools/build/remote/RemoteCache.java b/src/tools/remote_worker/src/main/java/com/google/devtools/build/remote/RemoteCache.java
index 2e933f3..023145f 100644
--- a/src/tools/remote_worker/src/main/java/com/google/devtools/build/remote/RemoteCache.java
+++ b/src/tools/remote_worker/src/main/java/com/google/devtools/build/remote/RemoteCache.java
@@ -188,8 +188,10 @@
offset == chunk.getOffset(),
"Missing input chunk for digest %s",
ContentDigests.toString(digest));
- chunk.getData().copyTo(blob, (int) offset);
- offset = (offset + chunk.getData().size()) % digest.getSizeBytes();
+ if (digest.getSizeBytes() > 0) {
+ chunk.getData().copyTo(blob, (int) offset);
+ offset = (offset + chunk.getData().size()) % digest.getSizeBytes();
+ }
if (offset == 0) {
ContentDigest uploadedDigest = cache.uploadBlob(blob);
Preconditions.checkArgument(