diff options
author | 2015-03-17 20:55:30 +0000 | |
---|---|---|
committer | 2015-03-18 13:46:07 +0000 | |
commit | b889cf31f4f84516787faecac04b0c4cb1981bc5 (patch) | |
tree | c9f2455d27a1e33d80ce23aeb6209cf52a32f651 /src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java | |
parent | 0942ee952efbc35d5def38216fe70d54a2dcd558 (diff) |
On-the-fly target pattern resolution in SkyQueryEnvironment
Moves pattern resolving logic from TargetPatternFunction.Resolver to
a top level class. Adds a layer of abstraction to the Resolver
implementation enabling it to be backed by either an Environment or
a Graph, for use in SkyFunction evaluation or on-the-fly evaluation,
respectively. Finally, SkyQueryEnvironment#preloadOrThrow now checks
to see if each target pattern exists in the graph, and any that
don't will be resolved on-the-fly.
--
MOS_MIGRATED_REVID=88861201
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java b/src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java new file mode 100644 index 0000000000..901e8775c0 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java @@ -0,0 +1,116 @@ +// Copyright 2015 Google Inc. 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.skyframe; + +import com.google.common.collect.Iterables; +import com.google.devtools.build.lib.events.Event; +import com.google.devtools.build.lib.events.EventHandler; +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.PackageIdentifier; +import com.google.devtools.build.lib.packages.Target; +import com.google.devtools.build.lib.pkgcache.RecursivePackageProvider; +import com.google.devtools.build.lib.syntax.Label; +import com.google.devtools.build.lib.vfs.PathFragment; +import com.google.devtools.build.lib.vfs.RootedPath; +import com.google.devtools.build.skyframe.SkyFunction.Environment; +import com.google.devtools.build.skyframe.SkyKey; + +/** + * A {@link RecursivePackageProvider} backed by an {@link Environment}. Its methods + * may throw {@link MissingDepException} if the package values this depends on haven't been + * calculated and added to its environment. + * + * <p>That exception will be caught by the compute method in {@link TargetPatternFunction}, which + * then returns {@code null} in accordance with the skyframe missing dependency policy. + */ +public final class EnvironmentBackedRecursivePackageProvider implements RecursivePackageProvider { + + private final Environment env; + + public EnvironmentBackedRecursivePackageProvider(Environment env) { + this.env = env; + } + + @Override + public Package getPackage(EventHandler eventHandler, PackageIdentifier packageName) + throws NoSuchPackageException, MissingDepException { + SkyKey pkgKey = PackageValue.key(packageName); + Package pkg; + try { + PackageValue pkgValue = + (PackageValue) env.getValueOrThrow(pkgKey, NoSuchPackageException.class); + if (pkgValue == null) { + throw new MissingDepException(); + } + pkg = pkgValue.getPackage(); + } catch (NoSuchPackageException e) { + pkg = e.getPackage(); + if (pkg == null) { + throw e; + } + } + return pkg; + } + + @Override + public boolean isPackage(EventHandler eventHandler, String packageName) + throws MissingDepException { + SkyKey packageLookupKey = PackageLookupValue.key(new PathFragment(packageName)); + try { + PackageLookupValue packageLookupValue = + (PackageLookupValue) env.getValueOrThrow(packageLookupKey, NoSuchPackageException.class, + InconsistentFilesystemException.class); + if (packageLookupValue == null) { + throw new MissingDepException(); + } + return packageLookupValue.packageExists(); + } catch (NoSuchPackageException | InconsistentFilesystemException e) { + eventHandler.handle(Event.error(e.getMessage())); + return false; + } + } + + @Override + public Iterable<PathFragment> getPackagesUnderDirectory(RootedPath directory) + throws MissingDepException { + RecursivePkgValue lookup = (RecursivePkgValue) env.getValue(RecursivePkgValue.key(directory)); + if (lookup == null) { + // Typically a null value from Environment.getValue(k) means that either the key k is missing + // a dependency or an exception was thrown during evaluation of k. Here, if this getValue + // call returns null, it can only mean a missing dependency, because + // RecursivePkgFunction#compute never throws. + throw new MissingDepException(); + } + // TODO(bazel-team): Make RecursivePkgValue return NestedSet<PathFragment> so this transform is + // unnecessary. + return Iterables.transform(lookup.getPackages(), PathFragment.TO_PATH_FRAGMENT); + } + + @Override + public Target getTarget(EventHandler eventHandler, Label label) throws NoSuchPackageException, + NoSuchTargetException, MissingDepException { + return getPackage(eventHandler, label.getPackageIdentifier()).getTarget(label.getName()); + } + + /** + * Indicates that a missing dependency is needed before target parsing can proceed. Currently + * used only in skyframe to notify the framework of missing dependencies. Caught by the compute + * method in {@link com.google.devtools.build.lib.skyframe.TargetPatternFunction}, which then + * returns null in accordance with the skyframe missing dependency policy. + */ + class MissingDepException extends RuntimeException { + } +} |