Skip to content

Commit 438f0c9

Browse files
jincopybara-github
authored andcommitted
Make FrontierSerializer reuse the PROJECT.scl evaluated during loading phase for creating the active_directories matcher.
.. and delete the bespoke `PROJECT.scl` prefix matcher builder in `FrontierSerializer`. If `PROJECT.scl` file was not found but the matcher is needed a `LoadingFailedException` will thrown (see tests). Also move the serialization step from `SerializationModule#afterCommand` to the end of `BuildTool#buildTargets`. The `afterCommand` step unconditionally runs even if an exception was thrown earlier, which makes error handling significantly more complicated. `FrontierSerializer` is also refactored to avoid a cyclic dependency on `runtime.CommandEnvironment`, so it can be called from the `runtime` package. PiperOrigin-RevId: 671606525 Change-Id: Ie1037ddf270e3f8de0c8835fea6d513a01309fe3
1 parent 43dfa92 commit 438f0c9

File tree

11 files changed

+177
-336
lines changed

11 files changed

+177
-336
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,8 @@ java_library(
452452
"//src/main/java/com/google/devtools/build/lib/skyframe/config",
453453
"//src/main/java/com/google/devtools/build/lib/skyframe/rewinding:action_rewound_event",
454454
"//src/main/java/com/google/devtools/build/lib/skyframe/serialization",
455+
"//src/main/java/com/google/devtools/build/lib/skyframe/serialization/analysis:frontier_serializer",
456+
"//src/main/java/com/google/devtools/build/lib/skyframe/serialization/analysis:options",
455457
"//src/main/java/com/google/devtools/build/lib/util",
456458
"//src/main/java/com/google/devtools/build/lib/util:TestType",
457459
"//src/main/java/com/google/devtools/build/lib/util:abrupt_exit_exception",

src/main/java/com/google/devtools/build/lib/buildtool/AnalysisPhaseRunner.java

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package com.google.devtools.build.lib.buildtool;
1515

1616
import static com.google.devtools.build.lib.analysis.config.BuildConfigurationValue.configurationId;
17+
import static com.google.devtools.build.lib.server.FailureDetails.RemoteAnalysisCaching.Code.PROJECT_FILE_NOT_FOUND;
1718

1819
import com.google.common.base.Preconditions;
1920
import com.google.common.base.Stopwatch;
@@ -53,6 +54,7 @@
5354
import com.google.devtools.build.lib.runtime.CommandEnvironment;
5455
import com.google.devtools.build.lib.server.FailureDetails.BuildConfiguration.Code;
5556
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
57+
import com.google.devtools.build.lib.server.FailureDetails.RemoteAnalysisCaching;
5658
import com.google.devtools.build.lib.skyframe.AspectKeyCreator.AspectKey;
5759
import com.google.devtools.build.lib.skyframe.RepositoryMappingValue.RepositoryMappingResolutionException;
5860
import com.google.devtools.build.lib.skyframe.TargetPatternPhaseValue;
@@ -61,6 +63,7 @@
6163
import com.google.devtools.build.lib.skyframe.TopLevelStatusEvents.TopLevelTargetAnalyzedEvent;
6264
import com.google.devtools.build.lib.skyframe.TopLevelStatusEvents.TopLevelTargetSkippedEvent;
6365
import com.google.devtools.build.lib.skyframe.config.BuildConfigurationKey;
66+
import com.google.devtools.build.lib.skyframe.serialization.analysis.RemoteAnalysisCachingOptions;
6467
import com.google.devtools.build.lib.util.AbruptExitException;
6568
import com.google.devtools.build.lib.util.DetailedExitCode;
6669
import com.google.devtools.build.lib.util.RegexFilter;
@@ -169,7 +172,10 @@ public static AnalysisResult execute(
169172

170173
/**
171174
* Evaluates the PROJECT.scl file and set corresponding options, if required by specific feature
172-
* flags (e.g. canonical configurations).
175+
* flags (e.g. canonical configurations, remote analysis caching).
176+
*
177+
* <p>May have a side-effect from updating the fields in the {@link CommandEnvironment} {@code
178+
* env} parameter.
173179
*
174180
* <p>Shared by both Skymeld and non-Skymeld analysis.
175181
*/
@@ -179,12 +185,19 @@ static BuildOptions evaluateProjectFile(
179185
TargetPatternPhaseValue targetPatternPhaseValue,
180186
CommandEnvironment env)
181187
throws LoadingFailedException, InvalidConfigurationException {
188+
// Remote analysis caching feature flag.
189+
var analysisCachingOpts = env.getOptions().getOptions(RemoteAnalysisCachingOptions.class);
190+
boolean neededForAnalysisCaching =
191+
analysisCachingOpts != null
192+
&& !Strings.isNullOrEmpty(analysisCachingOpts.serializedFrontierProfile);
193+
182194
// Canonical configurations feature flag.
183195
String sclConfig = buildOptions.get(CoreOptions.class).sclConfig;
184196
boolean neededForSclConfig =
185197
!Strings.isNullOrEmpty(sclConfig) || request.getBuildOptions().enforceProjectConfigs;
186198

187-
if (!neededForSclConfig) {
199+
if (!(neededForSclConfig || neededForAnalysisCaching)) {
200+
// All feature flags disabled.
188201
return buildOptions;
189202
}
190203

@@ -194,7 +207,28 @@ static BuildOptions evaluateProjectFile(
194207
env.getSkyframeExecutor(),
195208
env.getReporter());
196209

197-
if (projectFile != null) {
210+
if (neededForAnalysisCaching) {
211+
if (projectFile == null) {
212+
// TODO: b/353233779 - consider falling back on full serialization when there is no
213+
// project matcher.
214+
String message =
215+
"Failed to find PROJECT.scl file for: " + targetPatternPhaseValue.getTargetLabels();
216+
throw new LoadingFailedException(
217+
message,
218+
DetailedExitCode.of(
219+
FailureDetail.newBuilder()
220+
.setMessage(message)
221+
.setRemoteAnalysisCaching(
222+
RemoteAnalysisCaching.newBuilder().setCode(PROJECT_FILE_NOT_FOUND))
223+
.build()));
224+
}
225+
env.getRuntime()
226+
.setActiveDirectoriesPrefixTrie(
227+
BuildTool.getWorkingSetMatcherForSkyfocus(
228+
projectFile, env.getSkyframeExecutor(), env.getReporter()));
229+
}
230+
231+
if (neededForSclConfig && projectFile != null) {
198232
// Do not apply canonical configurations if the project file doesn't exist.
199233
return BuildTool.applySclConfigs(
200234
buildOptions,

src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.google.common.base.Preconditions;
2222
import com.google.common.base.Splitter;
2323
import com.google.common.base.Stopwatch;
24+
import com.google.common.base.Strings;
2425
import com.google.common.base.Throwables;
2526
import com.google.common.collect.ImmutableList;
2627
import com.google.common.collect.ImmutableMultimap;
@@ -82,6 +83,8 @@
8283
import com.google.devtools.build.lib.skyframe.actiongraph.v2.AqueryOutputHandler.OutputType;
8384
import com.google.devtools.build.lib.skyframe.actiongraph.v2.InvalidAqueryOutputFormatException;
8485
import com.google.devtools.build.lib.skyframe.config.FlagSetValue;
86+
import com.google.devtools.build.lib.skyframe.serialization.analysis.FrontierSerializer;
87+
import com.google.devtools.build.lib.skyframe.serialization.analysis.RemoteAnalysisCachingOptions;
8588
import com.google.devtools.build.lib.util.AbruptExitException;
8689
import com.google.devtools.build.lib.util.CrashFailureDetails;
8790
import com.google.devtools.build.lib.util.DetailedExitCode;
@@ -97,6 +100,7 @@
97100
import java.io.OutputStream;
98101
import java.io.PrintStream;
99102
import java.util.Collection;
103+
import java.util.Optional;
100104
import javax.annotation.Nullable;
101105

102106
/**
@@ -266,6 +270,10 @@ public void buildTargets(BuildRequest request, BuildResult result, TargetValidat
266270
delayedFailureDetail.getMessage(), DetailedExitCode.of(delayedFailureDetail));
267271
}
268272

273+
if (env.getSkyframeExecutor() instanceof SequencedSkyframeExecutor) {
274+
serializeFrontier(request.getOptions(RemoteAnalysisCachingOptions.class));
275+
}
276+
269277
// Only consider builds with SequencedSkyframeExecutor.
270278
if (env.getSkyframeExecutor() instanceof SequencedSkyframeExecutor
271279
&& request.getBuildOptions().aqueryDumpAfterBuildFormat != null) {
@@ -756,6 +764,29 @@ public BuildResult processRequest(
756764
return result;
757765
}
758766

767+
private void serializeFrontier(@Nullable RemoteAnalysisCachingOptions options)
768+
throws InterruptedException, AbruptExitException {
769+
if (options == null || Strings.isNullOrEmpty(options.serializedFrontierProfile)) {
770+
return;
771+
}
772+
773+
Optional<FailureDetail> maybeFailureDetail =
774+
FrontierSerializer.dumpFrontierSerializationProfile(
775+
env.getRuntime().getAnalysisCodecRegistry(),
776+
env.getSkyframeBuildView().getArtifactFactory(),
777+
env.getRuntime().getRuleClassProvider(),
778+
env.getSkyframeExecutor(),
779+
// TODO: b/353233779 - consider falling back on full serialization when there is
780+
// no project matcher.
781+
env.getRuntime().getActiveDirectoriesPrefixTrie(),
782+
env.getReporter(),
783+
options.serializedFrontierProfile);
784+
785+
if (maybeFailureDetail.isPresent()) {
786+
throw new AbruptExitException(DetailedExitCode.of(maybeFailureDetail.get()));
787+
}
788+
}
789+
759790
private static void maybeSetStopOnFirstFailure(BuildRequest request, BuildResult result) {
760791
if (shouldStopOnFailure(request)) {
761792
result.setStopOnFirstFailure(true);

src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import com.google.devtools.build.lib.buildtool.buildevent.ProfilerStartedEvent;
5050
import com.google.devtools.build.lib.clock.BlazeClock;
5151
import com.google.devtools.build.lib.clock.Clock;
52+
import com.google.devtools.build.lib.collect.PathFragmentPrefixTrie;
5253
import com.google.devtools.build.lib.events.Event;
5354
import com.google.devtools.build.lib.events.ExtendedEventHandler;
5455
import com.google.devtools.build.lib.events.OutputFilter;
@@ -196,6 +197,8 @@ public final class BlazeRuntime implements BugReport.BlazeRuntimeInterface {
196197

197198
@Nullable // not all environments provide this
198199
private Supplier<ObjectCodecRegistry> analysisCodecRegistrySupplier;
200+
@Nullable // only present with PROJECT.scl
201+
private PathFragmentPrefixTrie activeDirectoriesPrefixTrie;
199202
private final InstrumentationOutputFactory instrumentationOutputFactory;
200203

201204
private BlazeRuntime(
@@ -518,6 +521,15 @@ public ImmutableMap<String, InfoItem> getInfoItems() {
518521
return infoItems;
519522
}
520523

524+
public void setActiveDirectoriesPrefixTrie(PathFragmentPrefixTrie trie) {
525+
this.activeDirectoriesPrefixTrie = trie;
526+
}
527+
528+
@Nullable
529+
public PathFragmentPrefixTrie getActiveDirectoriesPrefixTrie() {
530+
return activeDirectoriesPrefixTrie;
531+
}
532+
521533
public Iterable<BlazeModule> getBlazeModules() {
522534
return blazeModules;
523535
}

src/main/java/com/google/devtools/build/lib/skyframe/serialization/BUILD

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,6 @@ java_library(
5353
":serialization_registry_setup_helpers",
5454
"//src/main/java/com/google/devtools/build/lib:runtime",
5555
"//src/main/java/com/google/devtools/build/lib/analysis:blaze_directories",
56-
"//src/main/java/com/google/devtools/build/lib/skyframe/serialization/analysis:frontier_serializer",
57-
"//src/main/java/com/google/devtools/build/lib/skyframe/serialization/analysis:options",
58-
"//src/main/java/com/google/devtools/build/lib/util:abrupt_exit_exception",
59-
"//src/main/java/com/google/devtools/build/lib/util:detailed_exit_code",
60-
"//src/main/protobuf:failure_details_java_proto",
61-
"//third_party:guava",
62-
"//third_party:jsr305",
6356
],
6457
)
6558

src/main/java/com/google/devtools/build/lib/skyframe/serialization/SerializationModule.java

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -13,31 +13,14 @@
1313
// limitations under the License.
1414
package com.google.devtools.build.lib.skyframe.serialization;
1515

16-
import static com.google.common.base.Strings.isNullOrEmpty;
17-
1816
import com.google.devtools.build.lib.analysis.BlazeDirectories;
1917
import com.google.devtools.build.lib.runtime.BlazeModule;
2018
import com.google.devtools.build.lib.runtime.BlazeRuntime;
21-
import com.google.devtools.build.lib.runtime.CommandEnvironment;
2219
import com.google.devtools.build.lib.runtime.WorkspaceBuilder;
23-
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
24-
import com.google.devtools.build.lib.server.FailureDetails.RemoteAnalysisCaching.Code;
25-
import com.google.devtools.build.lib.skyframe.serialization.analysis.FrontierSerializer;
26-
import com.google.devtools.build.lib.skyframe.serialization.analysis.RemoteAnalysisCachingOptions;
27-
import com.google.devtools.build.lib.util.AbruptExitException;
28-
import com.google.devtools.build.lib.util.DetailedExitCode;
29-
import java.util.Optional;
30-
import javax.annotation.Nullable;
3120

3221
/** A {@link BlazeModule} to store Skyframe serialization lifecycle hooks. */
3322
public class SerializationModule extends BlazeModule {
3423

35-
@Nullable private RemoteAnalysisCachingOptions options;
36-
37-
// Retained only for analysis caching operations in afterCommand. Must be garbage collected once
38-
// it's no longer needed. See the javadoc for CommandEnvironment for more information.
39-
@Nullable private CommandEnvironment env;
40-
4124
@Override
4225
public void workspaceInit(
4326
BlazeRuntime runtime, BlazeDirectories directories, WorkspaceBuilder builder) {
@@ -58,47 +41,4 @@ public void workspaceInit(
5841
directories.getWorkspace().getBaseName())));
5942
}
6043

61-
@Override
62-
public void beforeCommand(CommandEnvironment env) throws AbruptExitException {
63-
RemoteAnalysisCachingOptions options =
64-
env.getOptions().getOptions(RemoteAnalysisCachingOptions.class);
65-
if (options == null) {
66-
// not a supported command
67-
return;
68-
}
69-
70-
if (!isNullOrEmpty(options.serializedFrontierProfile)) {
71-
this.options = options;
72-
this.env = env;
73-
}
74-
}
75-
76-
@Override
77-
public void afterCommand() throws AbruptExitException {
78-
if (options == null) {
79-
return;
80-
}
81-
82-
try {
83-
if (!isNullOrEmpty(options.serializedFrontierProfile)) {
84-
Optional<FailureDetail> failureDetail =
85-
FrontierSerializer.dumpFrontierSerializationProfile(
86-
env, options.serializedFrontierProfile);
87-
if (failureDetail.isPresent()) {
88-
throw new AbruptExitException(DetailedExitCode.of(failureDetail.get()));
89-
}
90-
}
91-
} catch (InterruptedException e) {
92-
throw new AbruptExitException(
93-
DetailedExitCode.of(
94-
FrontierSerializer.createFailureDetail(
95-
"frontier serializer was interrupted: " + e.getMessage(),
96-
Code.SERIALIZED_FRONTIER_PROFILE_FAILED)));
97-
} finally {
98-
// Do not retain these objects between invocations.
99-
this.options = null;
100-
this.env = null;
101-
System.gc();
102-
}
103-
}
10444
}

src/main/java/com/google/devtools/build/lib/skyframe/serialization/analysis/BUILD

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,22 @@ java_library(
1515
name = "frontier_serializer",
1616
srcs = ["FrontierSerializer.java"],
1717
deps = [
18-
"//src/main/java/com/google/devtools/build/lib:runtime",
1918
"//src/main/java/com/google/devtools/build/lib/actions:action_lookup_key",
2019
"//src/main/java/com/google/devtools/build/lib/actions:artifacts",
2120
"//src/main/java/com/google/devtools/build/lib/analysis:config/build_options",
22-
"//src/main/java/com/google/devtools/build/lib/analysis:config/invalid_configuration_exception",
2321
"//src/main/java/com/google/devtools/build/lib/cmdline",
2422
"//src/main/java/com/google/devtools/build/lib/collect",
2523
"//src/main/java/com/google/devtools/build/lib/events",
2624
"//src/main/java/com/google/devtools/build/lib/packages",
27-
"//src/main/java/com/google/devtools/build/lib/pkgcache",
2825
"//src/main/java/com/google/devtools/build/lib/skyframe:aspect_key_creator",
2926
"//src/main/java/com/google/devtools/build/lib/skyframe:prerequisite_package_function",
30-
"//src/main/java/com/google/devtools/build/lib/skyframe:project_value",
3127
"//src/main/java/com/google/devtools/build/lib/skyframe:skyframe_cluster",
32-
"//src/main/java/com/google/devtools/build/lib/skyframe:target_pattern_phase_value",
3328
"//src/main/java/com/google/devtools/build/lib/skyframe/serialization",
3429
"//src/main/java/com/google/devtools/build/lib/vfs",
3530
"//src/main/java/com/google/devtools/build/skyframe",
3631
"//src/main/java/com/google/devtools/build/skyframe:skyframe-objects",
3732
"//src/main/protobuf:failure_details_java_proto",
3833
"//third_party:guava",
39-
"//third_party:jsr305",
4034
"//third_party/protobuf:protobuf_java",
4135
],
4236
)

0 commit comments

Comments
 (0)