Skip to content

Commit d09983b

Browse files
bazel-iocoeuvre
andauthored
[7.2.0] Implement FinalizeArtifacts (bazelbuild#21942)
If `--experimental_remote_output_service` is set, Bazel issues a FinalizeArtifacts RPC to the output service after an action has been executed. Working towards bazelbuild#21630. Closes bazelbuild#21759. PiperOrigin-RevId: 618190373 Change-Id: I8ed981fcea7ebe146de0b1c48b1933392c86253f Commit bazelbuild@586bd13 Co-authored-by: Chi Wang <[email protected]>
1 parent 165a5f7 commit d09983b

File tree

2 files changed

+66
-3
lines changed

2 files changed

+66
-3
lines changed

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

+65-3
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,19 @@
2020

2121
import build.bazel.remote.execution.v2.DigestFunction;
2222
import com.google.devtools.build.lib.actions.Action;
23+
import com.google.devtools.build.lib.actions.Artifact;
24+
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
2325
import com.google.devtools.build.lib.actions.EnvironmentalExecException;
2426
import com.google.devtools.build.lib.actions.ExecException;
2527
import com.google.devtools.build.lib.actions.cache.OutputMetadataStore;
2628
import com.google.devtools.build.lib.events.EventHandler;
2729
import com.google.devtools.build.lib.remote.BazelOutputServiceProto.CleanRequest;
2830
import com.google.devtools.build.lib.remote.BazelOutputServiceProto.CleanResponse;
31+
import com.google.devtools.build.lib.remote.BazelOutputServiceProto.FinalizeArtifactsRequest;
32+
import com.google.devtools.build.lib.remote.BazelOutputServiceProto.FinalizeArtifactsResponse;
2933
import com.google.devtools.build.lib.remote.BazelOutputServiceProto.FinalizeBuildRequest;
3034
import com.google.devtools.build.lib.remote.BazelOutputServiceProto.FinalizeBuildResponse;
3135
import com.google.devtools.build.lib.remote.BazelOutputServiceProto.StageArtifactsRequest;
32-
import com.google.devtools.build.lib.remote.BazelOutputServiceProto.StageArtifactsRequest.Artifact;
3336
import com.google.devtools.build.lib.remote.BazelOutputServiceProto.StageArtifactsResponse;
3437
import com.google.devtools.build.lib.remote.BazelOutputServiceProto.StartBuildRequest;
3538
import com.google.devtools.build.lib.remote.BazelOutputServiceProto.StartBuildResponse;
@@ -64,6 +67,7 @@
6467
public class BazelOutputService implements OutputService {
6568

6669
private final String outputBaseId;
70+
private final Supplier<Path> execRootSupplier;
6771
private final Supplier<Path> outputPathSupplier;
6872
private final DigestFunction.Value digestFunction;
6973
private final RemoteOptions remoteOptions;
@@ -75,13 +79,15 @@ public class BazelOutputService implements OutputService {
7579

7680
public BazelOutputService(
7781
Path outputBase,
82+
Supplier<Path> execRootSupplier,
7883
Supplier<Path> outputPathSupplier,
7984
DigestFunction.Value digestFunction,
8085
RemoteOptions remoteOptions,
8186
boolean verboseFailures,
8287
RemoteRetrier retrier,
8388
ReferenceCountedChannel channel) {
8489
this.outputBaseId = DigestUtil.hashCodeToString(md5().hashString(outputBase.toString(), UTF_8));
90+
this.execRootSupplier = execRootSupplier;
8591
this.outputPathSupplier = outputPathSupplier;
8692
this.digestFunction = digestFunction;
8793
this.remoteOptions = remoteOptions;
@@ -247,7 +253,7 @@ protected void stageArtifacts(List<FileMetadata> files) throws IOException, Inte
247253
request.setBuildId(buildId);
248254
for (var file : files) {
249255
request.addArtifacts(
250-
Artifact.newBuilder()
256+
StageArtifactsRequest.Artifact.newBuilder()
251257
.setPath(file.path().relativeTo(outputPath).toString())
252258
.setLocator(
253259
Any.pack(FileArtifactLocator.newBuilder().setDigest(file.digest()).build()))
@@ -328,7 +334,63 @@ private FinalizeBuildResponse finalizeBuild(FinalizeBuildRequest request)
328334
@Override
329335
public void finalizeAction(Action action, OutputMetadataStore outputMetadataStore)
330336
throws IOException, EnvironmentalExecException, InterruptedException {
331-
// TODO(chiwang): implement this
337+
var execRoot = execRootSupplier.get();
338+
var outputPath = outputPathSupplier.get();
339+
340+
var request = FinalizeArtifactsRequest.newBuilder();
341+
request.setBuildId(buildId);
342+
for (var output : action.getOutputs()) {
343+
if (outputMetadataStore.artifactOmitted(output)) {
344+
continue;
345+
}
346+
347+
if (output.isTreeArtifact()) {
348+
// TODO(chiwang): Use TreeArtifactLocator
349+
var children = outputMetadataStore.getTreeArtifactChildren((SpecialArtifact) output);
350+
for (var child : children) {
351+
addArtifact(outputMetadataStore, execRoot, outputPath, request, child);
352+
}
353+
} else {
354+
addArtifact(outputMetadataStore, execRoot, outputPath, request, output);
355+
}
356+
}
357+
358+
var unused = finalizeArtifacts(request.build());
359+
}
360+
361+
private FinalizeArtifactsResponse finalizeArtifacts(FinalizeArtifactsRequest request)
362+
throws IOException, InterruptedException {
363+
return retrier.execute(
364+
() ->
365+
channel.withChannelBlocking(
366+
channel -> {
367+
try {
368+
return BazelOutputServiceGrpc.newBlockingStub(channel)
369+
.finalizeArtifacts(request);
370+
} catch (StatusRuntimeException e) {
371+
throw new IOException(e);
372+
}
373+
}));
374+
}
375+
376+
private void addArtifact(
377+
OutputMetadataStore outputMetadataStore,
378+
Path execRoot,
379+
Path outputPath,
380+
FinalizeArtifactsRequest.Builder builder,
381+
Artifact output)
382+
throws IOException, InterruptedException {
383+
checkState(!output.isTreeArtifact());
384+
var metadata = outputMetadataStore.getOutputMetadata(output);
385+
if (metadata.getType().isFile()) {
386+
var digest = DigestUtil.buildDigest(metadata.getDigest(), metadata.getSize());
387+
var path = execRoot.getRelative(output.getExecPath()).relativeTo(outputPath).toString();
388+
builder.addArtifacts(
389+
FinalizeArtifactsRequest.Artifact.newBuilder()
390+
.setPath(path)
391+
.setLocator(Any.pack(FileArtifactLocator.newBuilder().setDigest(digest).build()))
392+
.build());
393+
}
332394
}
333395

334396
@Override

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

+1
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ public void beforeCommand(CommandEnvironment env) throws AbruptExitException {
446446
outputService =
447447
new BazelOutputService(
448448
env.getOutputBase(),
449+
env::getExecRoot,
449450
() -> env.getDirectories().getOutputPath(env.getWorkspaceName()),
450451
digestUtil.getDigestFunction(),
451452
remoteOptions,

0 commit comments

Comments
 (0)