Skip to content

Commit f948989

Browse files
[5.x] Remote: Fix "file not found" error when remote cache is changed from enabled to disabled. (#14321)
* Remote: Invalidate actions if previous build used BwoB and remote cache is changed from enabled to disabled. Part of #14252. PiperOrigin-RevId: 410243297 * In `ArchivedTreeArtifact`, make the assumption that the relative output path is always a single segment, and use this to serialize less data. This assumption holds because the origin of the relative output path (i.e. `bazel-out`) is `BlazeDirectories#getRelativeOutputPath`, which always returns a single-segment string. Instead of passing that around, just extract it from the tree artifact's exec path. Additionally, the public `ArchivedTreeArtifact#create` method is removed in order to enforce a consistent naming pattern for all instances. The codec supports custom derived tree roots even though there is currently no such serialization in skyframe (all serialized instances have the default `:archived_tree_artifacts`, but it was easy enough to be flexible). PiperOrigin-RevId: 406382340 * Remote: Don't load remote metadata from action cache if remote cache is disabled. Part of #14252. Closes #14252. PiperOrigin-RevId: 410448656 Co-authored-by: jhorvitz <[email protected]>
1 parent b587be3 commit f948989

24 files changed

+294
-268
lines changed

src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java

+8-10
Original file line numberDiff line numberDiff line change
@@ -401,19 +401,17 @@ public void repr(Printer printer) {
401401
*
402402
* @param execRoot the exec root in which this action is executed
403403
* @param bulkDeleter a helper to bulk delete outputs to avoid delegating to the filesystem
404-
* @param outputPrefixForArchivedArtifactsCleanup derived output prefix to construct archived tree
405-
* artifacts to be cleaned up. If null, no cleanup is needed.
404+
* @param cleanupArchivedArtifacts whether to clean up archived tree artifacts
406405
*/
407406
protected final void deleteOutputs(
408407
Path execRoot,
409408
ArtifactPathResolver pathResolver,
410409
@Nullable BulkDeleter bulkDeleter,
411-
@Nullable PathFragment outputPrefixForArchivedArtifactsCleanup)
410+
boolean cleanupArchivedArtifacts)
412411
throws IOException, InterruptedException {
413412
Iterable<Artifact> artifactsToDelete =
414-
outputPrefixForArchivedArtifactsCleanup != null
415-
? Iterables.concat(
416-
outputs, archivedTreeArtifactOutputs(outputPrefixForArchivedArtifactsCleanup))
413+
cleanupArchivedArtifacts
414+
? Iterables.concat(outputs, archivedTreeArtifactOutputs())
417415
: outputs;
418416
Iterable<PathFragment> additionalPathOutputsToDelete = getAdditionalPathOutputsToDelete();
419417
Iterable<PathFragment> directoryOutputsToDelete = getDirectoryOutputsToDelete();
@@ -452,10 +450,10 @@ protected Iterable<PathFragment> getDirectoryOutputsToDelete() {
452450
return ImmutableList.of();
453451
}
454452

455-
private Iterable<Artifact> archivedTreeArtifactOutputs(PathFragment derivedPathPrefix) {
453+
private Iterable<Artifact> archivedTreeArtifactOutputs() {
456454
return Iterables.transform(
457455
Iterables.filter(outputs, Artifact::isTreeArtifact),
458-
tree -> ArchivedTreeArtifact.createForTree((SpecialArtifact) tree, derivedPathPrefix));
456+
tree -> ArchivedTreeArtifact.createForTree((SpecialArtifact) tree));
459457
}
460458

461459
/**
@@ -581,9 +579,9 @@ public void prepare(
581579
Path execRoot,
582580
ArtifactPathResolver pathResolver,
583581
@Nullable BulkDeleter bulkDeleter,
584-
@Nullable PathFragment outputPrefixForArchivedArtifactsCleanup)
582+
boolean cleanupArchivedArtifacts)
585583
throws IOException, InterruptedException {
586-
deleteOutputs(execRoot, pathResolver, bulkDeleter, outputPrefixForArchivedArtifactsCleanup);
584+
deleteOutputs(execRoot, pathResolver, bulkDeleter, cleanupArchivedArtifacts);
587585
}
588586

589587
@Override

src/main/java/com/google/devtools/build/lib/actions/Action.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import com.google.devtools.build.lib.concurrent.ThreadSafety.ConditionallyThreadCompatible;
2121
import com.google.devtools.build.lib.vfs.BulkDeleter;
2222
import com.google.devtools.build.lib.vfs.Path;
23-
import com.google.devtools.build.lib.vfs.PathFragment;
2423
import java.io.IOException;
2524
import java.util.Map;
2625
import javax.annotation.Nullable;
@@ -92,7 +91,7 @@ void prepare(
9291
Path execRoot,
9392
ArtifactPathResolver pathResolver,
9493
@Nullable BulkDeleter bulkDeleter,
95-
@Nullable PathFragment outputPrefixForArchivedArtifactsCleanup)
94+
boolean cleanupArchivedArtifacts)
9695
throws IOException, InterruptedException;
9796

9897
/**

src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java

+14-19
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.google.common.collect.ImmutableMap;
2323
import com.google.common.collect.ImmutableSet;
2424
import com.google.common.flogger.GoogleLogger;
25+
import com.google.devtools.build.lib.actions.Artifact.ArchivedTreeArtifact;
2526
import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander;
2627
import com.google.devtools.build.lib.actions.Artifact.SourceArtifact;
2728
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
@@ -72,7 +73,6 @@ public class ActionCacheChecker {
7273
private final Predicate<? super Action> executionFilter;
7374
private final ArtifactResolver artifactResolver;
7475
private final CacheConfig cacheConfig;
75-
private final PathFragment derivedPathPrefix;
7676

7777
@Nullable private final ActionCache actionCache; // Null when not enabled.
7878

@@ -107,8 +107,7 @@ public ActionCacheChecker(
107107
ArtifactResolver artifactResolver,
108108
ActionKeyContext actionKeyContext,
109109
Predicate<? super Action> executionFilter,
110-
@Nullable CacheConfig cacheConfig,
111-
PathFragment derivedPathPrefix) {
110+
@Nullable CacheConfig cacheConfig) {
112111
this.executionFilter = executionFilter;
113112
this.actionKeyContext = actionKeyContext;
114113
this.artifactResolver = artifactResolver;
@@ -125,7 +124,6 @@ public ActionCacheChecker(
125124
} else {
126125
this.actionCache = null;
127126
}
128-
this.derivedPathPrefix = derivedPathPrefix;
129127
}
130128

131129
public boolean isActionExecutionProhibited(Action action) {
@@ -310,10 +308,7 @@ private CachedOutputMetadata(
310308
}
311309

312310
private static CachedOutputMetadata loadCachedOutputMetadata(
313-
Action action,
314-
ActionCache.Entry entry,
315-
MetadataHandler metadataHandler,
316-
PathFragment derivedPathPrefix) {
311+
Action action, ActionCache.Entry entry, MetadataHandler metadataHandler) {
317312
ImmutableMap.Builder<Artifact, RemoteFileArtifactValue> remoteFileMetadata =
318313
ImmutableMap.builder();
319314
ImmutableMap.Builder<SpecialArtifact, TreeArtifactValue> mergedTreeMetadata =
@@ -361,12 +356,9 @@ private static CachedOutputMetadata loadCachedOutputMetadata(
361356
cachedTreeMetadata
362357
.archivedFileValue()
363358
.map(
364-
fileArtifactValue -> {
365-
Artifact.ArchivedTreeArtifact archivedTreeArtifact =
366-
Artifact.ArchivedTreeArtifact.createForTree(parent, derivedPathPrefix);
367-
return ArchivedRepresentation.create(
368-
archivedTreeArtifact, fileArtifactValue);
369-
});
359+
fileArtifactValue ->
360+
ArchivedRepresentation.create(
361+
ArchivedTreeArtifact.createForTree(parent), fileArtifactValue));
370362
}
371363

372364
TreeArtifactValue.Builder merged = TreeArtifactValue.newBuilder(parent);
@@ -422,7 +414,8 @@ public Token getTokenIfNeedToExecute(
422414
EventHandler handler,
423415
MetadataHandler metadataHandler,
424416
ArtifactExpander artifactExpander,
425-
Map<String, String> remoteDefaultPlatformProperties)
417+
Map<String, String> remoteDefaultPlatformProperties,
418+
boolean isRemoteCacheEnabled)
426419
throws InterruptedException {
427420
// TODO(bazel-team): (2010) For RunfilesAction/SymlinkAction and similar actions that
428421
// produce only symlinks we should not check whether inputs are valid at all - all that matters
@@ -464,10 +457,12 @@ public Token getTokenIfNeedToExecute(
464457
}
465458
ActionCache.Entry entry = getCacheEntry(action);
466459
CachedOutputMetadata cachedOutputMetadata = null;
467-
// load remote metadata from action cache
468-
if (entry != null && !entry.isCorrupted() && cacheConfig.storeOutputMetadata()) {
469-
cachedOutputMetadata =
470-
loadCachedOutputMetadata(action, entry, metadataHandler, derivedPathPrefix);
460+
if (entry != null
461+
&& !entry.isCorrupted()
462+
&& cacheConfig.storeOutputMetadata()
463+
&& isRemoteCacheEnabled) {
464+
// load remote metadata from action cache
465+
cachedOutputMetadata = loadCachedOutputMetadata(action, entry, metadataHandler);
471466
}
472467

473468
if (mustExecute(

src/main/java/com/google/devtools/build/lib/actions/Artifact.java

+72-55
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec;
4242
import com.google.devtools.build.lib.skyframe.serialization.SerializationContext;
4343
import com.google.devtools.build.lib.skyframe.serialization.SerializationException;
44-
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
4544
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
4645
import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationConstant;
4746
import com.google.devtools.build.lib.starlarkbuildapi.FileApi;
@@ -309,7 +308,7 @@ public ArchivedTreeArtifact getArchivedTreeArtifact(SpecialArtifact treeArtifact
309308
/** A Predicate that evaluates to true if the Artifact is not a middleman artifact. */
310309
public static final Predicate<Artifact> MIDDLEMAN_FILTER = input -> !input.isMiddlemanArtifact();
311310

312-
protected final ArtifactRoot root;
311+
private final ArtifactRoot root;
313312

314313
private final int hashCode;
315314
private final PathFragment execPath;
@@ -978,7 +977,7 @@ boolean ownersEqual(Artifact other) {
978977

979978
@Override
980979
public PathFragment getRootRelativePath() {
981-
return root.isExternal() ? getExecPath().subFragment(2) : getExecPath();
980+
return getRoot().isExternal() ? getExecPath().subFragment(2) : getExecPath();
982981
}
983982

984983
@Override
@@ -1168,10 +1167,10 @@ public SpecialArtifact deserialize(DeserializationContext context, CodedInputStr
11681167
* TreeFileArtifact children} (and nothing else) of the tree artifact with their filesystem
11691168
* structure, relative to the {@linkplain SpecialArtifact#getExecPath() tree artifact directory}.
11701169
*/
1171-
@AutoCodec
11721170
public static final class ArchivedTreeArtifact extends DerivedArtifact {
1173-
private static final PathFragment ARCHIVED_ARTIFACTS_DERIVED_TREE_ROOT =
1171+
private static final PathFragment DEFAULT_DERIVED_TREE_ROOT =
11741172
PathFragment.create(":archived_tree_artifacts");
1173+
11751174
private final SpecialArtifact treeArtifact;
11761175

11771176
private ArchivedTreeArtifact(
@@ -1180,6 +1179,8 @@ private ArchivedTreeArtifact(
11801179
PathFragment execPath,
11811180
Object generatingActionKey) {
11821181
super(root, execPath, generatingActionKey);
1182+
Preconditions.checkArgument(
1183+
treeArtifact.isTreeArtifact(), "Not a tree artifact: %s", treeArtifact);
11831184
this.treeArtifact = treeArtifact;
11841185
}
11851186

@@ -1188,13 +1189,6 @@ public SpecialArtifact getParent() {
11881189
return treeArtifact;
11891190
}
11901191

1191-
/** Creates an archived tree artifact with a given {@code root} and {@code execPath}. */
1192-
public static ArchivedTreeArtifact create(
1193-
SpecialArtifact treeArtifact, ArtifactRoot root, PathFragment execPath) {
1194-
return new ArchivedTreeArtifact(
1195-
treeArtifact, root, execPath, treeArtifact.getGeneratingActionKey());
1196-
}
1197-
11981192
/**
11991193
* Creates an {@link ArchivedTreeArtifact} for a given tree artifact at the path inferred from
12001194
* the provided tree.
@@ -1206,13 +1200,12 @@ public static ArchivedTreeArtifact create(
12061200
* {@linkplain ArchivedTreeArtifact artifact} of: {@code
12071201
* bazel-out/:archived_tree_artifacts/k8-fastbuild/bin/directory.zip}.
12081202
*/
1209-
public static ArchivedTreeArtifact createForTree(
1210-
SpecialArtifact treeArtifact, PathFragment derivedPathPrefix) {
1211-
return createWithCustomDerivedTreeRoot(
1203+
public static ArchivedTreeArtifact createForTree(SpecialArtifact treeArtifact) {
1204+
return createInternal(
12121205
treeArtifact,
1213-
derivedPathPrefix,
1214-
ARCHIVED_ARTIFACTS_DERIVED_TREE_ROOT,
1215-
treeArtifact.getRootRelativePath().replaceName(treeArtifact.getFilename() + ".zip"));
1206+
DEFAULT_DERIVED_TREE_ROOT,
1207+
treeArtifact.getRootRelativePath().replaceName(treeArtifact.getFilename() + ".zip"),
1208+
treeArtifact.getGeneratingActionKey());
12161209
}
12171210

12181211
/**
@@ -1221,31 +1214,30 @@ public static ArchivedTreeArtifact createForTree(
12211214
*
12221215
* <p>Example: for a tree artifact with root of {@code bazel-out/k8-fastbuild/bin} returns an
12231216
* {@linkplain ArchivedTreeArtifact artifact} of: {@code
1224-
* bazel-out/{customDerivedTreeRoot}/k8-fastbuild/bin/{rootRelativePath}} with root of: {@code
1225-
* bazel-out/{customDerivedTreeRoot}/k8-fastbuild/bin}.
1217+
* bazel-out/{derivedTreeRoot}/k8-fastbuild/bin/{rootRelativePath}} with root of: {@code
1218+
* bazel-out/{derivedTreeRoot}/k8-fastbuild/bin}.
1219+
*
1220+
* <p>Such artifacts should only be used as outputs of intermediate spawns. Action execution
1221+
* results must come from {@link #createForTree}.
12261222
*/
12271223
public static ArchivedTreeArtifact createWithCustomDerivedTreeRoot(
1224+
SpecialArtifact treeArtifact, PathFragment derivedTreeRoot, PathFragment rootRelativePath) {
1225+
return createInternal(
1226+
treeArtifact, derivedTreeRoot, rootRelativePath, treeArtifact.getGeneratingActionKey());
1227+
}
1228+
1229+
private static ArchivedTreeArtifact createInternal(
12281230
SpecialArtifact treeArtifact,
1229-
PathFragment derivedPathPrefix,
1230-
PathFragment customDerivedTreeRoot,
1231-
PathFragment rootRelativePath) {
1232-
ArtifactRoot artifactRoot =
1233-
createRootForArchivedArtifact(
1234-
treeArtifact.getRoot(), derivedPathPrefix, customDerivedTreeRoot);
1235-
return create(
1236-
treeArtifact, artifactRoot, artifactRoot.getExecPath().getRelative(rootRelativePath));
1237-
}
1238-
1239-
private static ArtifactRoot createRootForArchivedArtifact(
1240-
ArtifactRoot treeArtifactRoot,
1241-
PathFragment derivedPathPrefix,
1242-
PathFragment customDerivedTreeRoot) {
1243-
return ArtifactRoot.asDerivedRoot(
1244-
getExecRoot(treeArtifactRoot),
1245-
// e.g. bazel-out/{customDerivedTreeRoot}/k8-fastbuild/bin
1246-
RootType.Output,
1247-
getExecPathWithinCustomDerivedRoot(
1248-
derivedPathPrefix, customDerivedTreeRoot, treeArtifactRoot.getExecPath()));
1231+
PathFragment derivedTreeRoot,
1232+
PathFragment rootRelativePath,
1233+
Object generatingActionKey) {
1234+
ArtifactRoot treeRoot = treeArtifact.getRoot();
1235+
PathFragment archiveRoot = embedDerivedTreeRoot(treeRoot.getExecPath(), derivedTreeRoot);
1236+
return new ArchivedTreeArtifact(
1237+
treeArtifact,
1238+
ArtifactRoot.asDerivedRoot(getExecRoot(treeRoot), RootType.Output, archiveRoot),
1239+
archiveRoot.getRelative(rootRelativePath),
1240+
generatingActionKey);
12491241
}
12501242

12511243
/**
@@ -1255,23 +1247,22 @@ private static ArtifactRoot createRootForArchivedArtifact(
12551247
* <p>Example: {@code bazel-out/k8-fastbuild/bin ->
12561248
* bazel-out/{customDerivedTreeRoot}/k8-fastbuild/bin}.
12571249
*/
1258-
public static PathFragment getExecPathWithinArchivedArtifactsTree(
1259-
PathFragment derivedPathPrefix, PathFragment execPath) {
1260-
return getExecPathWithinCustomDerivedRoot(
1261-
derivedPathPrefix, ARCHIVED_ARTIFACTS_DERIVED_TREE_ROOT, execPath);
1250+
public static PathFragment getExecPathWithinArchivedArtifactsTree(PathFragment execPath) {
1251+
return embedDerivedTreeRoot(execPath, DEFAULT_DERIVED_TREE_ROOT);
12621252
}
12631253

12641254
/**
12651255
* Translates provided output {@code execPath} to one under provided derived tree root.
12661256
*
12671257
* <p>Example: {@code bazel-out/k8-fastbuild/bin ->
1268-
* bazel-out/{customDerivedTreeRoot}/k8-fastbuild/bin}.
1258+
* bazel-out/{derivedTreeRoot}/k8-fastbuild/bin}.
12691259
*/
1270-
private static PathFragment getExecPathWithinCustomDerivedRoot(
1271-
PathFragment derivedPathPrefix, PathFragment customDerivedTreeRoot, PathFragment execPath) {
1272-
return derivedPathPrefix
1273-
.getRelative(customDerivedTreeRoot)
1274-
.getRelative(execPath.relativeTo(derivedPathPrefix));
1260+
private static PathFragment embedDerivedTreeRoot(
1261+
PathFragment execPath, PathFragment derivedTreeRoot) {
1262+
return execPath
1263+
.subFragment(0, 1)
1264+
.getRelative(derivedTreeRoot)
1265+
.getRelative(execPath.subFragment(1));
12751266
}
12761267

12771268
private static Path getExecRoot(ArtifactRoot artifactRoot) {
@@ -1284,16 +1275,42 @@ private static Path getExecRoot(ArtifactRoot artifactRoot) {
12841275
0, rootPathFragment.segmentCount() - artifactRoot.getExecPath().segmentCount());
12851276
return rootPath.getFileSystem().getPath(execRootPath);
12861277
}
1278+
}
12871279

1288-
@VisibleForSerialization
1289-
@AutoCodec.Instantiator
1290-
static ArchivedTreeArtifact createForDeserialization(
1291-
SpecialArtifact treeArtifact, ArtifactRoot root, PathFragment execPath) {
1280+
@SuppressWarnings("unused") // Codec used by reflection.
1281+
private static final class ArchivedTreeArtifactCodec
1282+
implements ObjectCodec<ArchivedTreeArtifact> {
1283+
1284+
@Override
1285+
public Class<ArchivedTreeArtifact> getEncodedClass() {
1286+
return ArchivedTreeArtifact.class;
1287+
}
1288+
1289+
@Override
1290+
public void serialize(
1291+
SerializationContext context, ArchivedTreeArtifact obj, CodedOutputStream codedOut)
1292+
throws SerializationException, IOException {
1293+
PathFragment derivedTreeRoot = obj.getRoot().getExecPath().subFragment(1, 2);
1294+
1295+
context.serialize(obj.getParent(), codedOut);
1296+
context.serialize(derivedTreeRoot, codedOut);
1297+
context.serialize(obj.getRootRelativePath(), codedOut);
1298+
}
1299+
1300+
@Override
1301+
public ArchivedTreeArtifact deserialize(
1302+
DeserializationContext context, CodedInputStream codedIn)
1303+
throws SerializationException, IOException {
1304+
SpecialArtifact treeArtifact = context.deserialize(codedIn);
1305+
PathFragment derivedTreeRoot = context.deserialize(codedIn);
1306+
PathFragment rootRelativePath = context.deserialize(codedIn);
12921307
Object generatingActionKey =
12931308
treeArtifact.hasGeneratingActionKey()
12941309
? treeArtifact.getGeneratingActionKey()
12951310
: OMITTED_FOR_SERIALIZATION;
1296-
return new ArchivedTreeArtifact(treeArtifact, root, execPath, generatingActionKey);
1311+
1312+
return ArchivedTreeArtifact.createInternal(
1313+
treeArtifact, derivedTreeRoot, rootRelativePath, generatingActionKey);
12971314
}
12981315
}
12991316

src/main/java/com/google/devtools/build/lib/bazel/BazelWorkspaceStatusModule.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ private String getAdditionalWorkspaceStatus(
113113
} catch (IOException e) {
114114
throw createExecutionException(e, Code.STDERR_IO_EXCEPTION);
115115
}
116-
return new String(stdoutStream.toByteArray(), UTF_8);
116+
return stdoutStream.toString(UTF_8);
117117
}
118118
} catch (BadExitStatusException e) {
119119
throw createExecutionException(e, Code.NON_ZERO_EXIT);
@@ -159,7 +159,7 @@ public void prepare(
159159
Path execRoot,
160160
ArtifactPathResolver pathResolver,
161161
@Nullable BulkDeleter bulkDeleter,
162-
@Nullable PathFragment outputPrefixForArchivedArtifactsCleanup)
162+
boolean cleanupArchivedArtifacts)
163163
throws IOException {
164164
// The default implementation of this method deletes all output files; override it to keep
165165
// the old stableStatus around. This way we can reuse the existing file (preserving its mtime)
@@ -356,8 +356,8 @@ public com.google.devtools.build.lib.shell.Command getCommand() {
356356
@Override
357357
public Iterable<Class<? extends OptionsBase>> getCommandOptions(Command command) {
358358
return "build".equals(command.name())
359-
? ImmutableList.<Class<? extends OptionsBase>>of(WorkspaceStatusAction.Options.class)
360-
: ImmutableList.<Class<? extends OptionsBase>>of();
359+
? ImmutableList.of(WorkspaceStatusAction.Options.class)
360+
: ImmutableList.of();
361361
}
362362

363363
@Override

0 commit comments

Comments
 (0)