Skip to content

Commit 46c3f17

Browse files
coeuvrecopybara-github
authored andcommitted
Remote: Cleanup the code that determines whether the spawn should accept/upload results from/to remote cache.
Remote cache (and execution) for an action can be controlled with following tags: - `no-remote-cache`: prevent remote caching, but allow local caching - `no-remote-exec`: prevent remote execution, but allow remote caching - `no-remote`: combine no-remote-cache and no-remote-exec - `no-cache`: extend no-remote-cache to also prevent local caching A combined cache is treated as remote cache, hence is disabled for actions that are tagged with `no-remote-cache` unless `--incompatible_remote_results_ignore_disk` is set in which case local component is enabled. Fixes #13621. Closes #13769. PiperOrigin-RevId: 388875505
1 parent 7484c98 commit 46c3f17

13 files changed

Lines changed: 350 additions & 77 deletions

File tree

src/main/java/com/google/devtools/build/docgen/templates/attributes/common/tags.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
Note: for the purposes of this tag, the disk-cache is considered a local cache, whereas
3535
the http and gRPC caches are considered remote.
3636
If a combined cache is specified (i.e. a cache with local and remote components),
37-
it's treated as a remote cache and disabled entirely.
37+
it's treated as a remote cache and disabled entirely unless <code>--incompatible_remote_results_ignore_disk</code>
38+
is set in which case the local components will be used.
3839
</li>
3940

4041
<li><code>no-remote-exec</code> keyword results in the action or test never being

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ public ActionResult upload(
158158
context, remotePathResolver, actionKey, action, command, outputs, outErr, resultBuilder);
159159
resultBuilder.setExitCode(exitCode);
160160
ActionResult result = resultBuilder.build();
161-
if (exitCode == 0 && !action.getDoNotCache()) {
161+
if (exitCode == 0) {
162162
cacheProtocol.uploadActionResult(context, actionKey, result);
163163
}
164164
return result;

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

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import static com.google.common.base.Preconditions.checkArgument;
1717
import static com.google.common.base.Preconditions.checkNotNull;
1818
import static com.google.common.base.Preconditions.checkState;
19+
import static com.google.common.base.Strings.isNullOrEmpty;
1920
import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
2021
import static com.google.common.util.concurrent.Futures.immediateFuture;
2122
import static com.google.common.util.concurrent.Futures.transform;
@@ -25,7 +26,13 @@
2526
import static com.google.devtools.build.lib.remote.util.Utils.getFromFuture;
2627
import static com.google.devtools.build.lib.remote.util.Utils.getInMemoryOutputPath;
2728
import static com.google.devtools.build.lib.remote.util.Utils.hasFilesToDownload;
29+
import static com.google.devtools.build.lib.remote.util.Utils.shouldAcceptCachedResultFromCombinedCache;
30+
import static com.google.devtools.build.lib.remote.util.Utils.shouldAcceptCachedResultFromDiskCache;
31+
import static com.google.devtools.build.lib.remote.util.Utils.shouldAcceptCachedResultFromRemoteCache;
2832
import static com.google.devtools.build.lib.remote.util.Utils.shouldDownloadAllSpawnOutputs;
33+
import static com.google.devtools.build.lib.remote.util.Utils.shouldUploadLocalResultsToCombinedDisk;
34+
import static com.google.devtools.build.lib.remote.util.Utils.shouldUploadLocalResultsToDiskCache;
35+
import static com.google.devtools.build.lib.remote.util.Utils.shouldUploadLocalResultsToRemoteCache;
2936

3037
import build.bazel.remote.execution.v2.Action;
3138
import build.bazel.remote.execution.v2.ActionResult;
@@ -266,19 +273,56 @@ public NetworkTime getNetworkTime() {
266273
}
267274
}
268275

269-
/** Returns {@code true} if the result of spawn may be cached remotely. */
270-
public boolean mayBeCachedRemotely(Spawn spawn) {
271-
return remoteCache != null && Spawns.mayBeCached(spawn) && Spawns.mayBeCachedRemotely(spawn);
276+
private static boolean useRemoteCache(RemoteOptions options) {
277+
return !isNullOrEmpty(options.remoteCache) || !isNullOrEmpty(options.remoteExecutor);
272278
}
273279

274-
/** Returns {@code true} if the result of spawn may be cached. */
275-
public boolean mayBeCached(Spawn spawn) {
276-
return remoteCache != null && Spawns.mayBeCached(spawn);
280+
private static boolean useDiskCache(RemoteOptions options) {
281+
return options.diskCache != null && !options.diskCache.isEmpty();
282+
}
283+
284+
/** Returns {@code true} if the {@code spawn} should accept cached results from remote cache. */
285+
public boolean shouldAcceptCachedResult(Spawn spawn) {
286+
if (remoteCache == null) {
287+
return false;
288+
}
289+
290+
if (useRemoteCache(remoteOptions)) {
291+
if (useDiskCache(remoteOptions)) {
292+
return shouldAcceptCachedResultFromCombinedCache(remoteOptions, spawn);
293+
} else {
294+
return shouldAcceptCachedResultFromRemoteCache(remoteOptions, spawn);
295+
}
296+
} else {
297+
return shouldAcceptCachedResultFromDiskCache(remoteOptions, spawn);
298+
}
299+
}
300+
301+
/**
302+
* Returns {@code true} if the local results of the {@code spawn} should be uploaded to remote
303+
* cache.
304+
*/
305+
public boolean shouldUploadLocalResults(Spawn spawn) {
306+
if (remoteCache == null) {
307+
return false;
308+
}
309+
310+
if (useRemoteCache(remoteOptions)) {
311+
if (useDiskCache(remoteOptions)) {
312+
return shouldUploadLocalResultsToCombinedDisk(remoteOptions, spawn);
313+
} else {
314+
return shouldUploadLocalResultsToRemoteCache(remoteOptions, spawn);
315+
}
316+
} else {
317+
return shouldUploadLocalResultsToDiskCache(remoteOptions, spawn);
318+
}
277319
}
278320

279321
/** Returns {@code true} if the spawn may be executed remotely. */
280322
public boolean mayBeExecutedRemotely(Spawn spawn) {
281-
return remoteCache != null && remoteExecutor != null && Spawns.mayBeExecutedRemotely(spawn);
323+
return remoteCache instanceof RemoteExecutionCache
324+
&& remoteExecutor != null
325+
&& Spawns.mayBeExecutedRemotely(spawn);
282326
}
283327

284328
/** Creates a new {@link RemoteAction} instance from spawn. */
@@ -313,7 +357,7 @@ public RemoteAction buildRemoteAction(Spawn spawn, SpawnExecutionContext context
313357
TracingMetadataUtils.buildMetadata(
314358
buildRequestId, commandId, actionKey.getDigest().getHash(), spawn.getResourceOwner());
315359
RemoteActionExecutionContext remoteActionExecutionContext =
316-
RemoteActionExecutionContext.create(metadata);
360+
RemoteActionExecutionContext.createForSpawn(spawn, metadata);
317361

318362
return new RemoteAction(
319363
spawn,
@@ -434,11 +478,13 @@ public int hashCode() {
434478
}
435479
}
436480

481+
437482
/** Lookup the remote cache for the given {@link RemoteAction}. {@code null} if not found. */
438483
@Nullable
439484
public RemoteActionResult lookupCache(RemoteAction action)
440485
throws IOException, InterruptedException {
441-
checkNotNull(remoteCache, "remoteCache can't be null");
486+
checkState(shouldAcceptCachedResult(action.spawn), "spawn doesn't accept cached result");
487+
442488
ActionResult actionResult =
443489
remoteCache.downloadActionResult(
444490
action.remoteActionExecutionContext, action.actionKey, /* inlineOutErr= */ false);
@@ -944,7 +990,8 @@ public InMemoryOutput downloadOutputs(RemoteAction action, RemoteActionResult re
944990
/** Upload outputs of a remote action which was executed locally to remote cache. */
945991
public void uploadOutputs(RemoteAction action)
946992
throws InterruptedException, IOException, ExecException {
947-
checkNotNull(remoteCache, "remoteCache can't be null");
993+
checkState(shouldUploadLocalResults(action.spawn), "spawn shouldn't upload local result");
994+
948995
Collection<Path> outputFiles =
949996
action.spawn.getOutputFiles().stream()
950997
.map((inp) -> execRoot.getRelative(inp.getExecPath()))
@@ -966,8 +1013,8 @@ public void uploadOutputs(RemoteAction action)
9661013
*/
9671014
public void uploadInputsIfNotPresent(RemoteAction action)
9681015
throws IOException, InterruptedException {
969-
checkNotNull(remoteCache, "remoteCache can't be null");
970-
checkState(remoteCache instanceof RemoteExecutionCache);
1016+
checkState(mayBeExecutedRemotely(action.spawn), "spawn can't be executed remotely");
1017+
9711018
RemoteExecutionCache remoteExecutionCache = (RemoteExecutionCache) remoteCache;
9721019
// Upload the command and all the inputs into the remote cache.
9731020
Map<Digest, Message> additionalInputs = Maps.newHashMapWithExpectedSize(2);
@@ -986,7 +1033,7 @@ public void uploadInputsIfNotPresent(RemoteAction action)
9861033
public RemoteActionResult executeRemotely(
9871034
RemoteAction action, boolean acceptCachedResult, OperationObserver observer)
9881035
throws IOException, InterruptedException {
989-
checkNotNull(remoteExecutor, "remoteExecutor can't be null");
1036+
checkState(mayBeExecutedRemotely(action.spawn), "spawn can't be executed remotely");
9901037

9911038
ExecuteRequest.Builder requestBuilder =
9921039
ExecuteRequest.newBuilder()

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

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import static com.google.devtools.build.lib.profiler.ProfilerTask.REMOTE_DOWNLOAD;
1818
import static com.google.devtools.build.lib.remote.util.Utils.createSpawnResult;
1919

20+
import com.google.common.annotations.VisibleForTesting;
2021
import com.google.common.base.Stopwatch;
2122
import com.google.common.base.Throwables;
2223
import com.google.devtools.build.lib.actions.ActionInput;
@@ -81,15 +82,17 @@ final class RemoteSpawnCache implements SpawnCache {
8182
this.remoteExecutionService = remoteExecutionService;
8283
}
8384

85+
@VisibleForTesting
86+
RemoteExecutionService getRemoteExecutionService() {
87+
return remoteExecutionService;
88+
}
89+
8490
@Override
8591
public CacheHandle lookup(Spawn spawn, SpawnExecutionContext context)
8692
throws InterruptedException, IOException, ExecException, ForbiddenActionInputException {
87-
boolean mayBeCached =
88-
remoteExecutionService.mayBeCachedRemotely(spawn)
89-
|| (!useRemoteCache(options) && remoteExecutionService.mayBeCached(spawn));
90-
if (!mayBeCached) {
91-
// returning SpawnCache.NO_RESULT_NO_STORE in case the caching is disabled or in case
92-
// the remote caching is disabled and the only configured cache is remote.
93+
boolean shouldAcceptCachedResult = remoteExecutionService.shouldAcceptCachedResult(spawn);
94+
boolean shouldUploadLocalResults = remoteExecutionService.shouldUploadLocalResults(spawn);
95+
if (!shouldAcceptCachedResult && !shouldUploadLocalResults) {
9396
return SpawnCache.NO_RESULT_NO_STORE;
9497
}
9598

@@ -102,8 +105,7 @@ public CacheHandle lookup(Spawn spawn, SpawnExecutionContext context)
102105
.setInputFiles(action.getInputFiles());
103106

104107
Profiler prof = Profiler.instance();
105-
if (options.remoteAcceptCached
106-
|| (options.incompatibleRemoteResultsIgnoreDisk && useDiskCache(options))) {
108+
if (shouldAcceptCachedResult) {
107109
context.report(SPAWN_CHECKING_CACHE_EVENT);
108110
// Metadata will be available in context.current() until we detach.
109111
// This is done via a thread-local variable.
@@ -162,8 +164,7 @@ public CacheHandle lookup(Spawn spawn, SpawnExecutionContext context)
162164

163165
context.prefetchInputs();
164166

165-
if (options.remoteUploadLocalResults
166-
|| (options.incompatibleRemoteResultsIgnoreDisk && useDiskCache(options))) {
167+
if (shouldUploadLocalResults) {
167168
return new CacheHandle() {
168169
@Override
169170
public boolean hasResult() {
@@ -249,14 +250,6 @@ private void report(Event evt) {
249250
}
250251
}
251252

252-
private static boolean useRemoteCache(RemoteOptions options) {
253-
return !isNullOrEmpty(options.remoteCache) || !isNullOrEmpty(options.remoteExecutor);
254-
}
255-
256-
private static boolean useDiskCache(RemoteOptions options) {
257-
return options.diskCache != null && !options.diskCache.isEmpty();
258-
}
259-
260253
@Override
261254
public boolean usefulInDynamicExecution() {
262255
return false;

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import com.google.devtools.build.lib.actions.SpawnMetrics;
3838
import com.google.devtools.build.lib.actions.SpawnResult;
3939
import com.google.devtools.build.lib.actions.SpawnResult.Status;
40-
import com.google.devtools.build.lib.actions.Spawns;
4140
import com.google.devtools.build.lib.actions.cache.VirtualActionInput;
4241
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
4342
import com.google.devtools.build.lib.events.Event;
@@ -170,12 +169,12 @@ public void reportExecutingIfNot() {
170169
public SpawnResult exec(Spawn spawn, SpawnExecutionContext context)
171170
throws ExecException, InterruptedException, IOException, ForbiddenActionInputException {
172171
Preconditions.checkArgument(
173-
Spawns.mayBeExecutedRemotely(spawn), "Spawn can't be executed remotely. This is a bug.");
172+
remoteExecutionService.mayBeExecutedRemotely(spawn),
173+
"Spawn can't be executed remotely. This is a bug.");
174174

175175
Stopwatch totalTime = Stopwatch.createStarted();
176-
boolean spawnCacheableRemotely = Spawns.mayBeCachedRemotely(spawn);
177-
boolean uploadLocalResults = remoteOptions.remoteUploadLocalResults && spawnCacheableRemotely;
178-
boolean acceptCachedResult = remoteOptions.remoteAcceptCached && spawnCacheableRemotely;
176+
boolean uploadLocalResults = remoteExecutionService.shouldUploadLocalResults(spawn);
177+
boolean acceptCachedResult = remoteExecutionService.shouldAcceptCachedResult(spawn);
179178

180179
RemoteAction action = remoteExecutionService.buildRemoteAction(spawn, context);
181180
SpawnMetrics.Builder spawnMetrics =

src/main/java/com/google/devtools/build/lib/remote/common/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ java_library(
2323
"//src/main/java/com/google/devtools/build/lib/vfs",
2424
"//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
2525
"//third_party:guava",
26+
"//third_party:jsr305",
2627
"//third_party/protobuf:protobuf_java",
2728
"@googleapis//:google_longrunning_operations_java_proto",
2829
"@remoteapis//:build_bazel_remote_execution_v2_remote_execution_java_proto",

src/main/java/com/google/devtools/build/lib/remote/common/RemoteActionExecutionContext.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,35 @@
1414
package com.google.devtools.build.lib.remote.common;
1515

1616
import build.bazel.remote.execution.v2.RequestMetadata;
17+
import com.google.devtools.build.lib.actions.Spawn;
18+
import javax.annotation.Nullable;
1719

1820
/** A context that provide remote execution related information for executing an action remotely. */
1921
public interface RemoteActionExecutionContext {
2022

21-
/** Get the {@link RequestMetadata} for the action being executed. */
23+
/** Returns the {@link Spawn} of the action being executed or {@code null}. */
24+
@Nullable
25+
Spawn getSpawn();
26+
27+
/** Returns the {@link RequestMetadata} for the action being executed. */
2228
RequestMetadata getRequestMetadata();
2329

2430
/**
25-
* Get the {@link NetworkTime} instance used to measure the network time during the action
31+
* Returns the {@link NetworkTime} instance used to measure the network time during the action
2632
* execution.
2733
*/
2834
NetworkTime getNetworkTime();
2935

3036
/** Creates a {@link SimpleRemoteActionExecutionContext} with given {@link RequestMetadata}. */
3137
static RemoteActionExecutionContext create(RequestMetadata metadata) {
32-
return new SimpleRemoteActionExecutionContext(metadata, new NetworkTime());
38+
return new SimpleRemoteActionExecutionContext(/*spawn=*/ null, metadata, new NetworkTime());
39+
}
40+
41+
/**
42+
* Creates a {@link SimpleRemoteActionExecutionContext} with given {@link Spawn} and {@link
43+
* RequestMetadata}.
44+
*/
45+
static RemoteActionExecutionContext createForSpawn(Spawn spawn, RequestMetadata metadata) {
46+
return new SimpleRemoteActionExecutionContext(spawn, metadata, new NetworkTime());
3347
}
3448
}

src/main/java/com/google/devtools/build/lib/remote/common/SimpleRemoteActionExecutionContext.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,29 @@
1414
package com.google.devtools.build.lib.remote.common;
1515

1616
import build.bazel.remote.execution.v2.RequestMetadata;
17+
import com.google.devtools.build.lib.actions.Spawn;
18+
import javax.annotation.Nullable;
1719

1820
/** A {@link RemoteActionExecutionContext} implementation */
1921
public class SimpleRemoteActionExecutionContext implements RemoteActionExecutionContext {
2022

23+
private final Spawn spawn;
2124
private final RequestMetadata requestMetadata;
2225
private final NetworkTime networkTime;
2326

2427
public SimpleRemoteActionExecutionContext(
25-
RequestMetadata requestMetadata, NetworkTime networkTime) {
28+
Spawn spawn, RequestMetadata requestMetadata, NetworkTime networkTime) {
29+
this.spawn = spawn;
2630
this.requestMetadata = requestMetadata;
2731
this.networkTime = networkTime;
2832
}
2933

34+
@Nullable
35+
@Override
36+
public Spawn getSpawn() {
37+
return spawn;
38+
}
39+
3040
@Override
3141
public RequestMetadata getRequestMetadata() {
3242
return requestMetadata;

src/main/java/com/google/devtools/build/lib/remote/disk/DiskAndRemoteCacheClient.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
// limitations under the License.
1414
package com.google.devtools.build.lib.remote.disk;
1515

16+
import static com.google.devtools.build.lib.remote.util.Utils.shouldAcceptCachedResultFromRemoteCache;
17+
import static com.google.devtools.build.lib.remote.util.Utils.shouldUploadLocalResultsToRemoteCache;
18+
1619
import build.bazel.remote.execution.v2.ActionResult;
1720
import build.bazel.remote.execution.v2.Digest;
1821
import com.google.common.base.Preconditions;
@@ -54,7 +57,7 @@ public void uploadActionResult(
5457
RemoteActionExecutionContext context, ActionKey actionKey, ActionResult actionResult)
5558
throws IOException, InterruptedException {
5659
diskCache.uploadActionResult(context, actionKey, actionResult);
57-
if (!options.incompatibleRemoteResultsIgnoreDisk || options.remoteUploadLocalResults) {
60+
if (shouldUploadLocalResultsToRemoteCache(options, context.getSpawn())) {
5861
remoteCache.uploadActionResult(context, actionKey, actionResult);
5962
}
6063
}
@@ -70,7 +73,7 @@ public ListenableFuture<Void> uploadFile(
7073
RemoteActionExecutionContext context, Digest digest, Path file) {
7174
try {
7275
diskCache.uploadFile(context, digest, file).get();
73-
if (!options.incompatibleRemoteResultsIgnoreDisk || options.remoteUploadLocalResults) {
76+
if (shouldUploadLocalResultsToRemoteCache(options, context.getSpawn())) {
7477
remoteCache.uploadFile(context, digest, file).get();
7578
}
7679
} catch (ExecutionException e) {
@@ -86,7 +89,7 @@ public ListenableFuture<Void> uploadBlob(
8689
RemoteActionExecutionContext context, Digest digest, ByteString data) {
8790
try {
8891
diskCache.uploadBlob(context, digest, data).get();
89-
if (!options.incompatibleRemoteResultsIgnoreDisk || options.remoteUploadLocalResults) {
92+
if (shouldUploadLocalResultsToRemoteCache(options, context.getSpawn())) {
9093
remoteCache.uploadBlob(context, digest, data).get();
9194
}
9295
} catch (ExecutionException e) {
@@ -145,7 +148,7 @@ public ListenableFuture<Void> downloadBlob(
145148
final OutputStream tempOut;
146149
tempOut = new LazyFileOutputStream(tempPath);
147150

148-
if (!options.incompatibleRemoteResultsIgnoreDisk || options.remoteAcceptCached) {
151+
if (shouldAcceptCachedResultFromRemoteCache(options, context.getSpawn())) {
149152
ListenableFuture<Void> download =
150153
closeStreamOnError(remoteCache.downloadBlob(context, digest, tempOut), tempOut);
151154
return Futures.transformAsync(
@@ -172,7 +175,7 @@ public ListenableFuture<ActionResult> downloadActionResult(
172175
return diskCache.downloadActionResult(context, actionKey, inlineOutErr);
173176
}
174177

175-
if (!options.incompatibleRemoteResultsIgnoreDisk || options.remoteAcceptCached) {
178+
if (shouldAcceptCachedResultFromRemoteCache(options, context.getSpawn())) {
176179
return Futures.transformAsync(
177180
remoteCache.downloadActionResult(context, actionKey, inlineOutErr),
178181
(actionResult) -> {

0 commit comments

Comments
 (0)