From 8ffd502c419b79d44e2178603cf151ed8abbbc40 Mon Sep 17 00:00:00 2001 From: dbabkin Date: Fri, 23 Mar 2018 04:40:02 -0700 Subject: Implement TargetProviderForQueryEnvironment. DirectTargetProvider works with WalkableGraph directly. If it fails to find target, then last try to use delegate TargetProvider which supposed to be PackageManager from SkyframeExecutor. RELNOTES:none PiperOrigin-RevId: 190204106 --- .../runtime/TargetProviderForQueryEnvironment.java | 87 ++++++++++++++++++++++ .../build/lib/runtime/commands/QueryCommand.java | 12 ++- .../SkyframeExecutorWrappingWalkableGraph.java | 2 +- 3 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/google/devtools/build/lib/runtime/TargetProviderForQueryEnvironment.java diff --git a/src/main/java/com/google/devtools/build/lib/runtime/TargetProviderForQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/runtime/TargetProviderForQueryEnvironment.java new file mode 100644 index 0000000000..3df131222e --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/runtime/TargetProviderForQueryEnvironment.java @@ -0,0 +1,87 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.devtools.build.lib.runtime; + +import com.google.common.base.Preconditions; +import com.google.common.base.Throwables; +import com.google.devtools.build.lib.cmdline.Label; +import com.google.devtools.build.lib.cmdline.PackageIdentifier; +import com.google.devtools.build.lib.events.ExtendedEventHandler; +import com.google.devtools.build.lib.packages.BuildFileContainsErrorsException; +import com.google.devtools.build.lib.packages.NoSuchPackageException; +import com.google.devtools.build.lib.packages.NoSuchTargetException; +import com.google.devtools.build.lib.packages.Package; +import com.google.devtools.build.lib.packages.Target; +import com.google.devtools.build.lib.pkgcache.TargetProvider; +import com.google.devtools.build.lib.skyframe.PackageValue; +import com.google.devtools.build.skyframe.SkyKey; +import com.google.devtools.build.skyframe.SkyValue; +import com.google.devtools.build.skyframe.WalkableGraph; +import java.util.Optional; + +/** + * Serves as TargetProvider using WalkableGraph as direct access to graph. Refers to delegate in + * case if WalkableGraph has not value for specific key. + */ +public class TargetProviderForQueryEnvironment implements TargetProvider { + + private final WalkableGraph walkableGraph; + + /** + * If WalkableGraph has not node requested, then delegate used as fall back strategy. + */ + private final TargetProvider delegate; + + public TargetProviderForQueryEnvironment(WalkableGraph walkableGraph, TargetProvider delegate) { + this.walkableGraph = Preconditions.checkNotNull(walkableGraph); + this.delegate = Preconditions.checkNotNull(delegate); + } + + @Override + public Target getTarget(ExtendedEventHandler eventHandler, Label label) + throws NoSuchPackageException, NoSuchTargetException, InterruptedException { + + Optional optional = getPackageFromWalkableGraph(label.getPackageIdentifier()); + if (optional.isPresent()) { + return optional.get().getTarget(label.getName()); + } + + return delegate.getTarget(eventHandler, label); + } + + private Optional getPackageFromWalkableGraph(PackageIdentifier pkgId) + throws InterruptedException, NoSuchPackageException { + + SkyKey packageKey = PackageValue.key(pkgId); + SkyValue skyValue = walkableGraph.getValue(packageKey); + + if (skyValue != null) { + PackageValue packageValue = (PackageValue) skyValue; + return Optional.of(packageValue.getPackage()); + } + + Exception exception = walkableGraph.getException(packageKey); + if (exception != null) { + // PackageFunction should be catching, swallowing, and rethrowing all transitive + // errors as NoSuchPackageExceptions or constructing packages with errors. + Throwables.propagateIfPossible(exception, NoSuchPackageException.class); + throw new IllegalStateException("Unexpected Exception type from PackageValue for " + pkgId); + } + if (walkableGraph.isCycle(packageKey)) { + throw new BuildFileContainsErrorsException( + pkgId, "Cycle encountered while loading package " + pkgId); + } + return Optional.empty(); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/QueryCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/QueryCommand.java index 119712284e..b9e071ce6a 100644 --- a/src/main/java/com/google/devtools/build/lib/runtime/commands/QueryCommand.java +++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/QueryCommand.java @@ -42,10 +42,13 @@ import com.google.devtools.build.lib.runtime.Command; import com.google.devtools.build.lib.runtime.CommandEnvironment; import com.google.devtools.build.lib.runtime.KeepGoingOption; import com.google.devtools.build.lib.runtime.LoadingPhaseThreadsOption; +import com.google.devtools.build.lib.runtime.TargetProviderForQueryEnvironment; +import com.google.devtools.build.lib.skyframe.SkyframeExecutorWrappingWalkableGraph; import com.google.devtools.build.lib.util.AbruptExitException; import com.google.devtools.build.lib.util.ExitCode; import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.Path; +import com.google.devtools.build.skyframe.WalkableGraph; import com.google.devtools.common.options.OptionsParser; import com.google.devtools.common.options.OptionsProvider; import java.io.BufferedOutputStream; @@ -283,12 +286,19 @@ public final class QueryCommand implements BlazeCommand { public static AbstractBlazeQueryEnvironment newQueryEnvironment(CommandEnvironment env, boolean keepGoing, boolean orderedResults, List universeScope, int loadingPhaseThreads, Set settings) { + + WalkableGraph walkableGraph = + SkyframeExecutorWrappingWalkableGraph.of(env.getSkyframeExecutor()); + + TargetProviderForQueryEnvironment targetProviderForQueryEnvironment = + new TargetProviderForQueryEnvironment(walkableGraph, env.getPackageManager()); + return env.getRuntime() .getQueryEnvironmentFactory() .create( env.getPackageManager().newTransitiveLoader(), env.getSkyframeExecutor(), - env.getPackageManager(), + targetProviderForQueryEnvironment, env.getPackageManager(), env.newTargetPatternEvaluator(), keepGoing, diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutorWrappingWalkableGraph.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutorWrappingWalkableGraph.java index 42029c15d9..75a8a03d8a 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutorWrappingWalkableGraph.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutorWrappingWalkableGraph.java @@ -26,7 +26,7 @@ import javax.annotation.Nullable; /** {@link WalkableGraph} backed by a {@link SkyframeExecutor}. */ public class SkyframeExecutorWrappingWalkableGraph extends DelegatingWalkableGraph { - public SkyframeExecutorWrappingWalkableGraph(MemoizingEvaluator evaluator) { + private SkyframeExecutorWrappingWalkableGraph(MemoizingEvaluator evaluator) { super( new QueryableGraph() { @Nullable -- cgit v1.2.3