Skip to content

Commit e860316

Browse files
Ola Rozenfelddslomov
authored andcommitted
Using an ActionFileInputCache for SHA1 digests used with remote execution.
-- MOS_MIGRATED_REVID=139613925
1 parent 74c6ad8 commit e860316

8 files changed

Lines changed: 71 additions & 15 deletions

File tree

src/main/java/com/google/devtools/build/lib/remote/ContentDigests.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,7 @@ public static ContentDigest buildDigest(byte[] digest, long size) {
8282
}
8383

8484
public static String toHexString(ContentDigest digest) {
85-
return digest.getSizeBytes() > 0
86-
? HashCode.fromBytes(digest.getDigest().toByteArray()).toString()
87-
: "";
85+
return HashCode.fromBytes(digest.getDigest().toByteArray()).toString();
8886
}
8987

9088
public static String toString(ContentDigest digest) {

src/main/java/com/google/devtools/build/lib/remote/GrpcActionCache.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,6 @@ public ActionResult getCachedActionResult(ActionKey actionKey) {
629629
ExecutionCacheReply reply = stub.getCachedResult(request);
630630
ExecutionCacheStatus status = reply.getStatus();
631631
if (!status.getSucceeded()
632-
&& status.getError() != ExecutionCacheStatus.ErrorCode.UNSUPPORTED
633632
&& status.getError() != ExecutionCacheStatus.ErrorCode.MISSING_RESULT) {
634633
throw new RuntimeException(status.getErrorDetail());
635634
}
@@ -650,7 +649,8 @@ public void setCachedActionResult(ActionKey actionKey, ActionResult result)
650649
.build();
651650
ExecutionCacheSetReply reply = stub.setCachedResult(request);
652651
ExecutionCacheStatus status = reply.getStatus();
653-
if (!status.getSucceeded()) {
652+
if (!status.getSucceeded()
653+
&& status.getError() != ExecutionCacheStatus.ErrorCode.UNSUPPORTED) {
654654
throw new RuntimeException(status.getErrorDetail());
655655
}
656656
}

src/main/java/com/google/devtools/build/lib/remote/README.md

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ this step.
99

1010
- Then you run Bazel pointing to the Hazelcast server.
1111

12-
bazel build --hazelcast_node=localhost:5701 --spawn_strategy=remote \
12+
bazel --host_jvm_args=-Dbazel.DigestFunction=SHA1 build \
13+
--hazelcast_node=localhost:5701 --spawn_strategy=remote \
1314
src/tools/generate_workspace:all
1415

1516
Above command will build generate_workspace with remote spawn strategy that uses
@@ -25,6 +26,33 @@ with default configuration.
2526

2627
- Then run Bazel pointing to the Hazelcast server and remote worker.
2728

28-
bazel build --hazelcast_node=localhost:5701 \
29+
bazel --host_jvm_args=-Dbazel.DigestFunction=SHA1 build \
30+
--hazelcast_node=localhost:5701 \
2931
--remote_worker=localhost:8080 \
3032
--spawn_strategy=remote src/tools/generate_workspace:all
33+
34+
# How to run a remote worker with a remote cache server.
35+
36+
- First you need to run a standalone Hazelcast server with default
37+
configuration. If you already have a separate Hazelcast cluster you can skip
38+
this step.
39+
40+
java -cp third_party/hazelcast/hazelcast-3.6.4.jar \
41+
com.hazelcast.core.server.StartServer
42+
43+
- Then run the remote cache server:
44+
45+
bazel-bin/src/tools/remote_worker/remote_cache --listen_port 8081
46+
47+
- The run the remote worker:
48+
49+
bazel-bin/src/tools/remote_worker/remote_worker \
50+
--work_path=/tmp/remote --listen_port 8080
51+
52+
- Then run Bazel pointing to the cache server and remote worker.
53+
54+
bazel --host_jvm_args=-Dbazel.DigestFunction=SHA1 build \
55+
--hazelcast_node=localhost:5701 \
56+
--remote_worker=localhost:8080 \
57+
--remote_cache=localhost:8081 \
58+
--spawn_strategy=remote src/tools/generate_workspace:all

src/main/java/com/google/devtools/build/lib/remote/RemoteActionCache.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,8 @@ void uploadAllResults(Path execRoot, Collection<Path> files, ActionResult.Builde
6161
throws IOException, InterruptedException;
6262

6363
/**
64-
* Put the file contents cache if it is not already in it. No-op if the file is already stored in
65-
* cache. The given path must be a full absolute path. Note: this is horribly inefficient, need to
66-
* patch through an overload that uses an ActionInputFile cache to compute the digests!
64+
* Put the file contents in cache if it is not already in it. No-op if the file is already stored
65+
* in cache. The given path must be a full absolute path.
6766
*
6867
* @return The key for fetching the file contents blob from cache.
6968
*/

src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
import com.google.devtools.build.lib.runtime.BlazeModule;
2525
import com.google.devtools.build.lib.runtime.Command;
2626
import com.google.devtools.build.lib.runtime.CommandEnvironment;
27+
import com.google.devtools.build.lib.util.AbruptExitException;
28+
import com.google.devtools.build.lib.util.ExitCode;
29+
import com.google.devtools.build.lib.vfs.FileSystem;
30+
import com.google.devtools.build.lib.vfs.FileSystem.HashFunction;
2731
import com.google.devtools.common.options.OptionsBase;
2832

2933
/** RemoteModule provides distributed cache and remote execution for Bazel. */
@@ -66,8 +70,17 @@ public void buildStarting(BuildStartingEvent event) {
6670
}
6771
// Otherwise actionCache remains null and remote caching/execution are disabled.
6872

69-
if (actionCache != null && RemoteWorkExecutor.isRemoteExecutionOptions(options)) {
70-
workExecutor = new RemoteWorkExecutor(options);
73+
if (actionCache != null) {
74+
HashFunction hf = FileSystem.getDigestFunction();
75+
if (hf != HashFunction.SHA1) {
76+
env.getBlazeModuleEnvironment().exit(new AbruptExitException(
77+
"Remote cache/execution requires SHA1 digests, got " + hf
78+
+ ", run with --host_jvm_args=-Dbazel.DigestFunction=SHA1",
79+
ExitCode.COMMAND_LINE_ERROR));
80+
}
81+
if (RemoteWorkExecutor.isRemoteExecutionOptions(options)) {
82+
workExecutor = new RemoteWorkExecutor(options);
83+
}
7184
}
7285
} catch (InvalidConfigurationException e) {
7386
env.getReporter().handle(Event.warn(e.toString()));

src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnStrategy.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121
import com.google.devtools.build.lib.actions.ActionExecutionContext;
2222
import com.google.devtools.build.lib.actions.ActionInput;
2323
import com.google.devtools.build.lib.actions.ActionInputHelper;
24+
import com.google.devtools.build.lib.actions.ActionStatusMessage;
2425
import com.google.devtools.build.lib.actions.ExecException;
2526
import com.google.devtools.build.lib.actions.ExecutionStrategy;
27+
import com.google.devtools.build.lib.actions.Executor;
2628
import com.google.devtools.build.lib.actions.Spawn;
2729
import com.google.devtools.build.lib.actions.SpawnActionContext;
2830
import com.google.devtools.build.lib.actions.Spawns;
@@ -128,6 +130,11 @@ private void execLocally(
128130
.handle(
129131
Event.warn(
130132
spawn.getMnemonic() + " unsupported operation for action cache (" + e + ")"));
133+
} catch (StatusRuntimeException e) {
134+
actionExecutionContext
135+
.getExecutor()
136+
.getEventHandler()
137+
.handle(Event.warn(spawn.getMnemonic() + " failed uploading results (" + e + ")"));
131138
}
132139
}
133140
}
@@ -147,6 +154,11 @@ private void passRemoteOutErr(ActionResult result, FileOutErr outErr) {
147154
}
148155
}
149156

157+
@Override
158+
public String toString() {
159+
return "remote";
160+
}
161+
150162
/** Executes the given {@code spawn}. */
151163
@Override
152164
public void exec(Spawn spawn, ActionExecutionContext actionExecutionContext)
@@ -158,7 +170,10 @@ public void exec(Spawn spawn, ActionExecutionContext actionExecutionContext)
158170

159171
ActionKey actionKey = null;
160172
String mnemonic = spawn.getMnemonic();
161-
EventHandler eventHandler = actionExecutionContext.getExecutor().getEventHandler();
173+
Executor executor = actionExecutionContext.getExecutor();
174+
EventHandler eventHandler = executor.getEventHandler();
175+
executor.getEventBus().post(
176+
ActionStatusMessage.runningStrategy(spawn.getResourceOwner(), "remote"));
162177

163178
try {
164179
// Temporary hack: the TreeNodeRepository should be created and maintained upstream!

src/test/java/com/google/devtools/build/lib/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,7 @@ java_test(
10321032
":foundations_testutil",
10331033
":test_runner",
10341034
":testutil",
1035+
"//src/main/java/com/google/devtools/build/lib:build-base",
10351036
"//src/main/java/com/google/devtools/build/lib:preconditions",
10361037
"//src/main/java/com/google/devtools/build/lib:vfs",
10371038
"//src/main/java/com/google/devtools/build/lib/actions",

src/tools/remote_worker/src/main/java/com/google/devtools/build/remote/RemoteCache.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,10 @@ public void onNext(CasUploadBlobRequest request) {
188188
offset == chunk.getOffset(),
189189
"Missing input chunk for digest %s",
190190
ContentDigests.toString(digest));
191-
chunk.getData().copyTo(blob, (int) offset);
192-
offset = (offset + chunk.getData().size()) % digest.getSizeBytes();
191+
if (digest.getSizeBytes() > 0) {
192+
chunk.getData().copyTo(blob, (int) offset);
193+
offset = (offset + chunk.getData().size()) % digest.getSizeBytes();
194+
}
193195
if (offset == 0) {
194196
ContentDigest uploadedDigest = cache.uploadBlob(blob);
195197
Preconditions.checkArgument(

0 commit comments

Comments
 (0)