diff options
186 files changed, 2322 insertions, 1912 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java b/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java index 00f918a17a..8bd3f4428a 100644 --- a/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java +++ b/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java @@ -32,10 +32,8 @@ import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.lib.vfs.Symlinks; - import java.io.IOException; import java.util.Collection; - import javax.annotation.Nullable; /** @@ -154,9 +152,11 @@ public abstract class AbstractAction implements Action, SkylarkValue { @Nullable @Override - public Iterable<Artifact> resolveInputsFromCache(ArtifactResolver artifactResolver, - PackageRootResolver resolver, Collection<PathFragment> inputPaths) - throws PackageRootResolutionException { + public Iterable<Artifact> resolveInputsFromCache( + ArtifactResolver artifactResolver, + PackageRootResolver resolver, + Collection<PathFragment> inputPaths) + throws PackageRootResolutionException, InterruptedException { throw new IllegalStateException( "Method must be overridden for actions that may have unknown inputs."); } diff --git a/src/main/java/com/google/devtools/build/lib/actions/Action.java b/src/main/java/com/google/devtools/build/lib/actions/Action.java index 01cf55472f..d7623de017 100644 --- a/src/main/java/com/google/devtools/build/lib/actions/Action.java +++ b/src/main/java/com/google/devtools/build/lib/actions/Action.java @@ -19,10 +19,8 @@ import com.google.devtools.build.lib.concurrent.ThreadSafety.ConditionallyThread import com.google.devtools.build.lib.profiler.Describable; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.PathFragment; - import java.io.IOException; import java.util.Collection; - import javax.annotation.Nullable; /** @@ -154,25 +152,25 @@ public interface Action extends ActionExecutionMetadata, Describable { throws ActionExecutionException, InterruptedException; /** - * Method used to resolve action inputs based on the information contained in - * the action cache. It will be called iff inputsKnown() is false for the - * given action instance and there is a related cache entry in the action - * cache. + * Method used to resolve action inputs based on the information contained in the action cache. It + * will be called iff inputsKnown() is false for the given action instance and there is a related + * cache entry in the action cache. * - * Method must be redefined for any action that may return - * inputsKnown() == false. + * <p>Method must be redefined for any action that may return inputsKnown() == false. * * @param artifactResolver the artifact factory that can be used to manufacture artifacts * @param resolver object which helps to resolve some of the artifacts * @param inputPaths List of relative (to the execution root) input paths * @return List of Artifacts corresponding to inputPaths, or null if some dependencies were - * missing and we need to try again later. + * missing and we need to try again later. * @throws PackageRootResolutionException on failure to determine package roots of inputPaths */ @Nullable Iterable<Artifact> resolveInputsFromCache( - ArtifactResolver artifactResolver, PackageRootResolver resolver, - Collection<PathFragment> inputPaths) throws PackageRootResolutionException; + ArtifactResolver artifactResolver, + PackageRootResolver resolver, + Collection<PathFragment> inputPaths) + throws PackageRootResolutionException, InterruptedException; /** * Informs the action that its inputs are {@code inputs}, and that its inputs are now known. Can diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java b/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java index 86cbd0a07f..b96a9e4111 100644 --- a/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java +++ b/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java @@ -27,13 +27,11 @@ import com.google.devtools.build.lib.events.EventHandler; import com.google.devtools.build.lib.events.EventKind; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.vfs.PathFragment; - import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; - import javax.annotation.Nullable; /** @@ -242,7 +240,7 @@ public class ActionCacheChecker { @Nullable public Iterable<Artifact> getCachedInputs(Action action, PackageRootResolver resolver) - throws PackageRootResolutionException { + throws PackageRootResolutionException, InterruptedException { ActionCache.Entry entry = getCacheEntry(action); if (entry == null || entry.isCorrupted()) { return ImmutableList.of(); diff --git a/src/main/java/com/google/devtools/build/lib/actions/ArtifactFactory.java b/src/main/java/com/google/devtools/build/lib/actions/ArtifactFactory.java index 1606c0e783..941ea1554c 100644 --- a/src/main/java/com/google/devtools/build/lib/actions/ArtifactFactory.java +++ b/src/main/java/com/google/devtools/build/lib/actions/ArtifactFactory.java @@ -26,13 +26,11 @@ import com.google.devtools.build.lib.util.Pair; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.PathFragment; - import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Objects; - import javax.annotation.Nullable; /** @@ -369,7 +367,7 @@ public class ArtifactFactory implements ArtifactResolver, ArtifactSerializer, Ar @Override public synchronized Map<PathFragment, Artifact> resolveSourceArtifacts( Iterable<PathFragment> execPaths, PackageRootResolver resolver) - throws PackageRootResolutionException { + throws PackageRootResolutionException, InterruptedException { Map<PathFragment, Artifact> result = new HashMap<>(); ArrayList<PathFragment> unresolvedPaths = new ArrayList<>(); diff --git a/src/main/java/com/google/devtools/build/lib/actions/ArtifactResolver.java b/src/main/java/com/google/devtools/build/lib/actions/ArtifactResolver.java index e7ea2f2c5f..58b36c9371 100644 --- a/src/main/java/com/google/devtools/build/lib/actions/ArtifactResolver.java +++ b/src/main/java/com/google/devtools/build/lib/actions/ArtifactResolver.java @@ -15,9 +15,7 @@ package com.google.devtools.build.lib.actions; import com.google.devtools.build.lib.vfs.PathFragment; - import java.util.Map; - import javax.annotation.Nullable; /** @@ -69,12 +67,13 @@ public interface ArtifactResolver { * @param execPaths list of exec paths of the artifacts to resolve * @param resolver object that helps to resolve package root of given paths * @return map which contains list of execPaths and corresponding Artifacts. Map can contain - * existing or new source Artifacts for the given execPaths. The artifact is null if the - * root cannot be determined and the artifact did not exist before. Return null if any - * dependencies are missing. + * existing or new source Artifacts for the given execPaths. The artifact is null if the root + * cannot be determined and the artifact did not exist before. Return null if any dependencies + * are missing. * @throws PackageRootResolutionException failure to determine package roots of {@code execPaths} */ @Nullable - Map<PathFragment, Artifact> resolveSourceArtifacts(Iterable<PathFragment> execPaths, - PackageRootResolver resolver) throws PackageRootResolutionException; + Map<PathFragment, Artifact> resolveSourceArtifacts( + Iterable<PathFragment> execPaths, PackageRootResolver resolver) + throws PackageRootResolutionException, InterruptedException; } diff --git a/src/main/java/com/google/devtools/build/lib/actions/PackageRootResolver.java b/src/main/java/com/google/devtools/build/lib/actions/PackageRootResolver.java index 0db0075ddc..2b7a3ca4d5 100644 --- a/src/main/java/com/google/devtools/build/lib/actions/PackageRootResolver.java +++ b/src/main/java/com/google/devtools/build/lib/actions/PackageRootResolver.java @@ -15,9 +15,7 @@ package com.google.devtools.build.lib.actions; import com.google.devtools.build.lib.vfs.PathFragment; - import java.util.Map; - import javax.annotation.Nullable; /** @@ -26,34 +24,33 @@ import javax.annotation.Nullable; public interface PackageRootResolver { /** - * Returns mapping from execPath to Root. Root will be null if the path has no containing - * package. + * Returns mapping from execPath to Root. Root will be null if the path has no containing package. * * @param execPaths the paths to find {@link Root}s for. The search for a containing package will - * start with the path's parent directory, since the path is assumed to be a file. - * @return mappings from {@code execPath} to {@link Root}, or null if for some reason we - * cannot determine the result at this time (such as when used within a SkyFunction) + * start with the path's parent directory, since the path is assumed to be a file. + * @return mappings from {@code execPath} to {@link Root}, or null if for some reason we cannot + * determine the result at this time (such as when used within a SkyFunction) * @throws PackageRootResolutionException if unable to determine package roots or lack thereof, - * typically caused by exceptions encountered while attempting to locate BUILD files + * typically caused by exceptions encountered while attempting to locate BUILD files */ @Nullable Map<PathFragment, Root> findPackageRootsForFiles(Iterable<PathFragment> execPaths) - throws PackageRootResolutionException; + throws PackageRootResolutionException, InterruptedException; /** - * Returns mapping from execPath to Root. Root will be null if the path has no containing - * package. Unlike {@link #findPackageRootsForFiles(Iterable)}, this function allows directories - * in the list of exec paths. + * Returns mapping from execPath to Root. Root will be null if the path has no containing package. + * Unlike {@link #findPackageRootsForFiles(Iterable)}, this function allows directories in the + * list of exec paths. * * @param execPaths the paths to find {@link Root}s for. The search for a containing package will - * start with the path's parent directory, since the path is assumed to be a file. - * @return mappings from {@code execPath} to {@link Root}, or null if for some reason we - * cannot determine the result at this time (such as when used within a SkyFunction) + * start with the path's parent directory, since the path is assumed to be a file. + * @return mappings from {@code execPath} to {@link Root}, or null if for some reason we cannot + * determine the result at this time (such as when used within a SkyFunction) * @throws PackageRootResolutionException if unable to determine package roots or lack thereof, - * typically caused by exceptions encountered while attempting to locate BUILD files + * typically caused by exceptions encountered while attempting to locate BUILD files */ // TODO(bazel-team): Remove this once we don't need to find package roots for directories. @Nullable Map<PathFragment, Root> findPackageRoots(Iterable<PathFragment> execPaths) - throws PackageRootResolutionException; + throws PackageRootResolutionException, InterruptedException; } diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java index fcdc3ec4c6..9f9a655069 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java @@ -127,13 +127,13 @@ public interface AnalysisEnvironment extends ActionRegistry { * Returns the Artifact that is used to hold the non-volatile workspace status for the current * build request. */ - Artifact getStableWorkspaceStatusArtifact(); + Artifact getStableWorkspaceStatusArtifact() throws InterruptedException; /** - * Returns the Artifact that is used to hold the volatile workspace status (e.g. build - * changelist) for the current build request. + * Returns the Artifact that is used to hold the volatile workspace status (e.g. build changelist) + * for the current build request. */ - Artifact getVolatileWorkspaceStatusArtifact(); + Artifact getVolatileWorkspaceStatusArtifact() throws InterruptedException; /** * Returns the Artifacts that contain the workspace status for the current build request. @@ -142,7 +142,8 @@ public interface AnalysisEnvironment extends ActionRegistry { * @param config the current build configuration. */ ImmutableList<Artifact> getBuildInfo( - RuleContext ruleContext, BuildInfoKey key, BuildConfiguration config); + RuleContext ruleContext, BuildInfoKey key, BuildConfiguration config) + throws InterruptedException; /** * Returns the set of orphan Artifacts (i.e. Artifacts without generating action). Should only be diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java index 5fed4a32fa..8b5eb241b8 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java @@ -81,7 +81,6 @@ import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.WalkableGraph; import com.google.devtools.common.options.Option; import com.google.devtools.common.options.OptionsBase; - import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -568,19 +567,26 @@ public class BuildView { String error = createErrorMessage(loadingResult, skyframeAnalysisResult); final WalkableGraph graph = skyframeAnalysisResult.getWalkableGraph(); - final ActionGraph actionGraph = new ActionGraph() { - @Nullable - @Override - public ActionAnalysisMetadata getGeneratingAction(Artifact artifact) { - ArtifactOwner artifactOwner = artifact.getArtifactOwner(); - if (artifactOwner instanceof ActionLookupValue.ActionLookupKey) { - SkyKey key = ActionLookupValue.key((ActionLookupValue.ActionLookupKey) artifactOwner); - ActionLookupValue val = (ActionLookupValue) graph.getValue(key); - return val == null ? null : val.getGeneratingAction(artifact); - } - return null; - } - }; + final ActionGraph actionGraph = + new ActionGraph() { + @Nullable + @Override + public ActionAnalysisMetadata getGeneratingAction(Artifact artifact) { + ArtifactOwner artifactOwner = artifact.getArtifactOwner(); + if (artifactOwner instanceof ActionLookupValue.ActionLookupKey) { + SkyKey key = ActionLookupValue.key((ActionLookupValue.ActionLookupKey) artifactOwner); + ActionLookupValue val; + try { + val = (ActionLookupValue) graph.getValue(key); + } catch (InterruptedException e) { + throw new IllegalStateException( + "Interruption not expected from this graph: " + key, e); + } + return val == null ? null : val.getGeneratingAction(artifact); + } + return null; + } + }; return new AnalysisResult( configuredTargets, aspects, diff --git a/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java b/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java index 5fd3d43822..5aed23d0f9 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java @@ -37,7 +37,6 @@ import com.google.devtools.build.lib.skyframe.WorkspaceStatusValue; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.skyframe.SkyFunction; - import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; @@ -49,7 +48,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; - import javax.annotation.Nullable; /** @@ -287,21 +285,21 @@ public class CachingAnalysisEnvironment implements AnalysisEnvironment { } @Override - public Artifact getStableWorkspaceStatusArtifact() { + public Artifact getStableWorkspaceStatusArtifact() throws InterruptedException { return ((WorkspaceStatusValue) skyframeEnv.getValue(WorkspaceStatusValue.SKY_KEY)) .getStableArtifact(); } @Override - public Artifact getVolatileWorkspaceStatusArtifact() { + public Artifact getVolatileWorkspaceStatusArtifact() throws InterruptedException { return ((WorkspaceStatusValue) skyframeEnv.getValue(WorkspaceStatusValue.SKY_KEY)) .getVolatileArtifact(); } // See SkyframeBuildView#getWorkspaceStatusValues for the code that this method is attempting to // verify. - private NullPointerException collectDebugInfoAndCrash( - BuildInfoKey key, BuildConfiguration config) { + private NullPointerException collectDebugInfoAndCrash(BuildInfoKey key, BuildConfiguration config) + throws InterruptedException { String debugInfo = key + " " + config; Preconditions.checkState(skyframeEnv.valuesMissing(), debugInfo); Map<BuildInfoKey, BuildInfoFactory> buildInfoFactories = Preconditions.checkNotNull( @@ -314,7 +312,8 @@ public class CachingAnalysisEnvironment implements AnalysisEnvironment { @Override public ImmutableList<Artifact> getBuildInfo( - RuleContext ruleContext, BuildInfoKey key, BuildConfiguration config) { + RuleContext ruleContext, BuildInfoKey key, BuildConfiguration config) + throws InterruptedException { boolean stamp = AnalysisUtils.isStampingEnabled(ruleContext, config); BuildInfoCollectionValue collectionValue = (BuildInfoCollectionValue) skyframeEnv.getValue(BuildInfoCollectionValue.key( diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfigurationCollectionFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfigurationCollectionFactory.java index 77c51d9e44..75ac3a0d53 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/ConfigurationCollectionFactory.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfigurationCollectionFactory.java @@ -21,7 +21,6 @@ import com.google.devtools.build.lib.analysis.config.ConfigurationFactory; import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; import com.google.devtools.build.lib.analysis.config.PackageProviderForConfigurations; import com.google.devtools.build.lib.events.EventHandler; - import javax.annotation.Nullable; /** @@ -31,9 +30,10 @@ public interface ConfigurationCollectionFactory { /** * Creates the top-level configuration for a build. * - * <p>Also it may create a set of BuildConfigurations and define a transition table over them. - * All configurations during a build should be accessible from this top-level configuration - * via configuration transitions. + * <p>Also it may create a set of BuildConfigurations and define a transition table over them. All + * configurations during a build should be accessible from this top-level configuration via + * configuration transitions. + * * @param configurationFactory the configuration factory * @param cache a cache for BuildConfigurations * @param loadedPackageProvider the package provider @@ -48,7 +48,8 @@ public interface ConfigurationCollectionFactory { Cache<String, BuildConfiguration> cache, PackageProviderForConfigurations loadedPackageProvider, BuildOptions buildOptions, - EventHandler errorEventListener) throws InvalidConfigurationException; + EventHandler errorEventListener) + throws InvalidConfigurationException, InterruptedException; /** * Returns the module the given configuration should use for choosing dynamic transitions. diff --git a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java index 6816b42e8d..10703ba8eb 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java @@ -45,14 +45,12 @@ import com.google.devtools.build.lib.syntax.EvalException; import com.google.devtools.build.lib.syntax.EvalUtils; import com.google.devtools.build.lib.util.OrderedSetMultimap; import com.google.devtools.build.lib.util.Preconditions; - import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; - import javax.annotation.Nullable; /** @@ -232,12 +230,15 @@ public abstract class DependencyResolver { } } - private void resolveExplicitAttributes(final RuleResolver depResolver) { + private void resolveExplicitAttributes(final RuleResolver depResolver) + throws InterruptedException { depResolver.attributeMap.visitLabels( new AttributeMap.AcceptsLabelAttribute() { @Override - public void acceptLabelAttribute(Label label, Attribute attribute) { - if (attribute.getType() == BuildType.NODEP_LABEL || attribute.isImplicit() + public void acceptLabelAttribute(Label label, Attribute attribute) + throws InterruptedException { + if (attribute.getType() == BuildType.NODEP_LABEL + || attribute.isImplicit() || attribute.isLateBound()) { return; } @@ -246,10 +247,8 @@ public abstract class DependencyResolver { }); } - /** - * Resolves the dependencies for all implicit attributes in this rule. - */ - private void resolveImplicitAttributes(RuleResolver depResolver) { + /** Resolves the dependencies for all implicit attributes in this rule. */ + private void resolveImplicitAttributes(RuleResolver depResolver) throws InterruptedException { // Since the attributes that come from aspects do not appear in attributeMap, we have to get // their values from somewhere else. This incidentally means that aspects attributes are not // configurable. It would be nice if that wasn't the case, but we'd have to revamp how @@ -455,7 +454,8 @@ public abstract class DependencyResolver { * @param attrName the name of the attribute to add dependency labels to * @param labels the dependencies to add */ - private void addExplicitDeps(RuleResolver depResolver, String attrName, Iterable<Label> labels) { + private void addExplicitDeps(RuleResolver depResolver, String attrName, Iterable<Label> labels) + throws InterruptedException { Rule rule = depResolver.rule; if (!rule.isAttrDefined(attrName, BuildType.LABEL_LIST) && !rule.isAttrDefined(attrName, BuildType.NODEP_LABEL_LIST)) { @@ -468,13 +468,16 @@ public abstract class DependencyResolver { } /** - * Converts the given multimap of attributes to labels into a multi map of attributes to - * {@link Dependency} objects using the proper configuration transition for each attribute. + * Converts the given multimap of attributes to labels into a multi map of attributes to {@link + * Dependency} objects using the proper configuration transition for each attribute. * * @throws IllegalArgumentException if the {@code node} does not refer to a {@link Rule} instance */ - public final Collection<Dependency> resolveRuleLabels(TargetAndConfiguration node, - OrderedSetMultimap<Attribute, Label> depLabels, NestedSetBuilder<Label> rootCauses) { + public final Collection<Dependency> resolveRuleLabels( + TargetAndConfiguration node, + OrderedSetMultimap<Attribute, Label> depLabels, + NestedSetBuilder<Label> rootCauses) + throws InterruptedException { Preconditions.checkArgument(node.getTarget() instanceof Rule); Rule rule = (Rule) node.getTarget(); OrderedSetMultimap<Attribute, Dependency> outgoingEdges = OrderedSetMultimap.create(); @@ -489,8 +492,12 @@ public abstract class DependencyResolver { return outgoingEdges.values(); } - private void visitPackageGroup(TargetAndConfiguration node, PackageGroup packageGroup, - NestedSetBuilder<Label> rootCauses, Collection<Dependency> outgoingEdges) { + private void visitPackageGroup( + TargetAndConfiguration node, + PackageGroup packageGroup, + NestedSetBuilder<Label> rootCauses, + Collection<Dependency> outgoingEdges) + throws InterruptedException { for (Label label : packageGroup.getIncludes()) { Target target = getTarget(packageGroup, label, rootCauses); if (target == null) { @@ -508,7 +515,7 @@ public abstract class DependencyResolver { } } - private ImmutableSet<AspectDescriptor> requiredAspects( + private static ImmutableSet<AspectDescriptor> requiredAspects( @Nullable Aspect aspect, Attribute attribute, final Target target, Rule originalRule) { if (!(target instanceof Rule)) { return ImmutableSet.of(); @@ -613,10 +620,10 @@ public abstract class DependencyResolver { } /** - * Resolves the given dep for the given attribute, including determining which - * configurations to apply to it. + * Resolves the given dep for the given attribute, including determining which configurations to + * apply to it. */ - void resolveDep(Attribute attribute, Label depLabel) { + void resolveDep(Attribute attribute, Label depLabel) throws InterruptedException { Target toTarget = getTarget(rule, depLabel, rootCauses); if (toTarget == null) { return; // Skip this round: we still need to Skyframe-evaluate the dep's target. @@ -633,13 +640,14 @@ public abstract class DependencyResolver { /** * Resolves the given dep for the given attribute using a pre-prepared configuration. * - * <p>Use this method with care: it skips Bazel's standard config transition semantics - * ({@link BuildConfiguration#evaluateTransition}). That means attributes passed through here - * won't obey standard rules on which configurations apply to their deps. This should only - * be done for special circumstances that really justify the difference. When in doubt, use - * {@link #resolveDep(Attribute, Label)}. + * <p>Use this method with care: it skips Bazel's standard config transition semantics ({@link + * BuildConfiguration#evaluateTransition}). That means attributes passed through here won't obey + * standard rules on which configurations apply to their deps. This should only be done for + * special circumstances that really justify the difference. When in doubt, use {@link + * #resolveDep(Attribute, Label)}. */ - void resolveDep(Attribute attribute, Label depLabel, BuildConfiguration config) { + void resolveDep(Attribute attribute, Label depLabel, BuildConfiguration config) + throws InterruptedException { Target toTarget = getTarget(rule, depLabel, rootCauses); if (toTarget == null) { return; // Skip this round: this is either a loading error or unevaluated Skyframe dep. @@ -686,8 +694,11 @@ public abstract class DependencyResolver { } } - private void visitTargetVisibility(TargetAndConfiguration node, - NestedSetBuilder<Label> rootCauses, Collection<Dependency> outgoingEdges) { + private void visitTargetVisibility( + TargetAndConfiguration node, + NestedSetBuilder<Label> rootCauses, + Collection<Dependency> outgoingEdges) + throws InterruptedException { Target target = node.getTarget(); for (Label label : target.getVisibility().getDependencyLabels()) { Target visibilityTarget = getTarget(target, label, rootCauses); @@ -733,22 +744,24 @@ public abstract class DependencyResolver { * @param to the missing target * @param e the exception that was thrown, e.g., by {@link #getTarget} */ - protected abstract void missingEdgeHook(Target from, Label to, NoSuchThingException e); + protected abstract void missingEdgeHook(Target from, Label to, NoSuchThingException e) + throws InterruptedException; /** * Returns the target by the given label. * * <p>Returns null if the target is not ready to be returned at this moment. If getTarget returns * null once or more during a {@link #dependentNodeMap} call, the results of that call will be - * incomplete. For use within Skyframe, where several iterations may be needed to discover - * all dependencies. + * incomplete. For use within Skyframe, where several iterations may be needed to discover all + * dependencies. */ @Nullable - protected abstract Target getTarget(Target from, Label label, NestedSetBuilder<Label> rootCauses); + protected abstract Target getTarget(Target from, Label label, NestedSetBuilder<Label> rootCauses) + throws InterruptedException; /** - * Returns the build configurations with the given options and fragments, in the same order as - * the input options. + * Returns the build configurations with the given options and fragments, in the same order as the + * input options. * * <p>Returns null if any configurations aren't ready to be returned at this moment. If * getConfigurations returns null once or more during a {@link #dependentNodeMap} call, the @@ -758,5 +771,6 @@ public abstract class DependencyResolver { @Nullable protected abstract List<BuildConfiguration> getConfigurations( Set<Class<? extends BuildConfiguration.Fragment>> fragments, - Iterable<BuildOptions> buildOptions) throws InvalidConfigurationException; + Iterable<BuildOptions> buildOptions) + throws InvalidConfigurationException, InterruptedException; } diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RedirectChaser.java b/src/main/java/com/google/devtools/build/lib/analysis/RedirectChaser.java index a908ada500..6a27b5c2a1 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/RedirectChaser.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/RedirectChaser.java @@ -71,7 +71,7 @@ public final class RedirectChaser { */ @Nullable public static Label followRedirects(ConfigurationEnvironment env, Label label, String name) - throws InvalidConfigurationException { + throws InvalidConfigurationException, InterruptedException { Label oldLabel = null; Set<Label> visitedLabels = new HashSet<>(); visitedLabels.add(label); diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java index 321c385d07..a829195965 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java @@ -391,7 +391,7 @@ public final class RuleContext extends TargetContext return getAnalysisEnvironment().getOwner(); } - public ImmutableList<Artifact> getBuildInfo(BuildInfoKey key) { + public ImmutableList<Artifact> getBuildInfo(BuildInfoKey key) throws InterruptedException { return getAnalysisEnvironment().getBuildInfo(this, key, getConfiguration()); } diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationEnvironment.java b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationEnvironment.java index d2439acf6d..ec55f60e8e 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationEnvironment.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationEnvironment.java @@ -24,9 +24,7 @@ import com.google.devtools.build.lib.packages.Package; import com.google.devtools.build.lib.packages.Target; import com.google.devtools.build.lib.pkgcache.LoadedPackageProvider; import com.google.devtools.build.lib.pkgcache.PackageProvider; -import com.google.devtools.build.lib.pkgcache.TargetProvider; import com.google.devtools.build.lib.vfs.Path; - import javax.annotation.Nullable; /** @@ -48,18 +46,19 @@ public interface ConfigurationEnvironment { * * @see TargetProvider#getTarget */ - Target getTarget(Label label) throws NoSuchPackageException, NoSuchTargetException; + Target getTarget(Label label) + throws NoSuchPackageException, NoSuchTargetException, InterruptedException; /** Returns a path for the given file within the given package. */ - Path getPath(Package pkg, String fileName); - + Path getPath(Package pkg, String fileName) throws InterruptedException; + /** Returns fragment based on fragment class and build options. */ - <T extends Fragment> T getFragment(BuildOptions buildOptions, Class<T> fragmentType) - throws InvalidConfigurationException; + <T extends Fragment> T getFragment(BuildOptions buildOptions, Class<T> fragmentType) + throws InvalidConfigurationException, InterruptedException; /** Returns global value of BlazeDirectories. */ @Nullable - BlazeDirectories getBlazeDirectories(); + BlazeDirectories getBlazeDirectories() throws InterruptedException; /** * An implementation backed by a {@link PackageProvider} instance. diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFactory.java index 31eb150cab..595f5271d2 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFactory.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFactory.java @@ -22,11 +22,9 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible; import com.google.devtools.build.lib.events.EventHandler; import com.google.devtools.build.lib.util.Preconditions; - import java.util.HashMap; import java.util.List; import java.util.Map; - import javax.annotation.Nullable; /** @@ -69,23 +67,27 @@ public final class ConfigurationFactory { @Nullable public BuildConfiguration createConfigurations( Cache<String, BuildConfiguration> cache, - PackageProviderForConfigurations loadedPackageProvider, BuildOptions buildOptions, + PackageProviderForConfigurations loadedPackageProvider, + BuildOptions buildOptions, EventHandler errorEventListener) - throws InvalidConfigurationException { + throws InvalidConfigurationException, InterruptedException { return configurationCollectionFactory.createConfigurations(this, cache, loadedPackageProvider, buildOptions, errorEventListener); } /** - * Returns a {@link com.google.devtools.build.lib.analysis.config.BuildConfiguration} based on - * the given set of build options. + * Returns a {@link com.google.devtools.build.lib.analysis.config.BuildConfiguration} based on the + * given set of build options. * * <p>If the configuration has already been created, re-uses it, otherwise, creates a new one. */ @Nullable - public BuildConfiguration getConfiguration(PackageProviderForConfigurations loadedPackageProvider, - BuildOptions buildOptions, boolean actionsDisabled, Cache<String, BuildConfiguration> cache) - throws InvalidConfigurationException { + public BuildConfiguration getConfiguration( + PackageProviderForConfigurations loadedPackageProvider, + BuildOptions buildOptions, + boolean actionsDisabled, + Cache<String, BuildConfiguration> cache) + throws InvalidConfigurationException, InterruptedException { String cacheKey = buildOptions.computeCacheKey(); BuildConfiguration result = cache.getIfPresent(cacheKey); diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFragmentFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFragmentFactory.java index 1ae9a66bb0..0c19502324 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFragmentFactory.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFragmentFactory.java @@ -15,7 +15,6 @@ package com.google.devtools.build.lib.analysis.config; import com.google.common.collect.ImmutableSet; import com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment; - import javax.annotation.Nullable; /** @@ -31,7 +30,7 @@ public interface ConfigurationFragmentFactory { */ @Nullable BuildConfiguration.Fragment create(ConfigurationEnvironment env, BuildOptions buildOptions) - throws InvalidConfigurationException; + throws InvalidConfigurationException, InterruptedException; /** * @return the exact type of the fragment this factory creates. diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/PackageProviderForConfigurations.java b/src/main/java/com/google/devtools/build/lib/analysis/config/PackageProviderForConfigurations.java index dddc786209..e493e482b4 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/PackageProviderForConfigurations.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/PackageProviderForConfigurations.java @@ -22,7 +22,6 @@ 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 java.io.IOException; /** @@ -35,18 +34,15 @@ public interface PackageProviderForConfigurations { * Adds dependency to fileName if needed. Used only in skyframe, for creating correct dependencies * for {@link com.google.devtools.build.lib.skyframe.ConfigurationCollectionValue}. */ - void addDependency(Package pkg, String fileName) throws LabelSyntaxException, IOException; - - /** - * Returns fragment based on fragment type and build options. - */ - <T extends Fragment> T getFragment(BuildOptions buildOptions, Class<T> fragmentType) - throws InvalidConfigurationException; - - /** - * Returns blaze directories and adds dependency to that value. - */ - BlazeDirectories getDirectories(); + void addDependency(Package pkg, String fileName) + throws LabelSyntaxException, IOException, InterruptedException; + + /** Returns fragment based on fragment type and build options. */ + <T extends Fragment> T getFragment(BuildOptions buildOptions, Class<T> fragmentType) + throws InvalidConfigurationException, InterruptedException; + + /** Returns blaze directories and adds dependency to that value. */ + BlazeDirectories getDirectories() throws InterruptedException; /** * Returns true if any dependency is missing (value of some node hasn't been evaluated yet). @@ -59,8 +55,9 @@ public interface PackageProviderForConfigurations { * function evaluation. * * @throws NoSuchPackageException if the package could not be found - * @throws NoSuchTargetException if the package was loaded successfully, but - * the specified {@link Target} was not found in it + * @throws NoSuchTargetException if the package was loaded successfully, but the specified {@link + * Target} was not found in it */ - Target getTarget(Label label) throws NoSuchPackageException, NoSuchTargetException; + Target getTarget(Label label) + throws NoSuchPackageException, NoSuchTargetException, InterruptedException; } diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/GitRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/GitRepositoryFunction.java index 0ba5c0f5e5..55c30dd316 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/GitRepositoryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/GitRepositoryFunction.java @@ -23,10 +23,8 @@ import com.google.devtools.build.lib.rules.repository.RepositoryFunction; import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.skyframe.SkyFunction.Environment; -import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyFunctionException.Transience; import com.google.devtools.build.skyframe.SkyValue; - import java.io.IOException; /** @@ -42,14 +40,13 @@ public class GitRepositoryFunction extends RepositoryFunction { @Override public SkyValue fetch( Rule rule, Path outputDirectory, BlazeDirectories directories, Environment env) - throws SkyFunctionException { + throws InterruptedException, RepositoryFunctionException { createDirectory(outputDirectory, rule); GitCloner.clone(rule, outputDirectory, env.getListener(), clientEnvironment); return RepositoryDirectoryValue.create(outputDirectory); } - protected void createDirectory(Path path, Rule rule) - throws RepositoryFunctionException { + protected static void createDirectory(Path path, Rule rule) throws RepositoryFunctionException { try { FileSystemUtils.createDirectoryAndParents(path); } catch (IOException e) { diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenJarFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenJarFunction.java index 28c4a00dcc..a18b4e089c 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenJarFunction.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenJarFunction.java @@ -23,12 +23,10 @@ import com.google.devtools.build.lib.analysis.BlazeDirectories; import com.google.devtools.build.lib.analysis.RuleDefinition; import com.google.devtools.build.lib.bazel.repository.downloader.HttpDownloader; import com.google.devtools.build.lib.bazel.rules.workspace.MavenJarRule; -import com.google.devtools.build.lib.cmdline.RepositoryName; import com.google.devtools.build.lib.packages.AggregatingAttributeMapper; import com.google.devtools.build.lib.packages.AttributeMap; import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.rules.repository.RepositoryDirectoryValue; -import com.google.devtools.build.lib.rules.repository.RepositoryFunction; import com.google.devtools.build.lib.syntax.EvalException; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.Fingerprint; @@ -36,7 +34,9 @@ import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.skyframe.SkyFunction.Environment; import com.google.devtools.build.skyframe.SkyFunctionException.Transience; import com.google.devtools.build.skyframe.SkyValue; - +import java.io.IOException; +import java.util.Map; +import javax.annotation.Nullable; import org.apache.maven.settings.Server; import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.RepositorySystemSession; @@ -50,11 +50,6 @@ import org.eclipse.aether.resolution.ArtifactRequest; import org.eclipse.aether.resolution.ArtifactResolutionException; import org.eclipse.aether.resolution.ArtifactResult; -import java.io.IOException; -import java.util.Map; - -import javax.annotation.Nullable; - /** * Implementation of maven_jar. */ @@ -68,7 +63,7 @@ public class MavenJarFunction extends HttpArchiveFunction { @Override protected byte[] getRuleSpecificMarkerData(Rule rule, Environment env) - throws RepositoryFunctionException { + throws RepositoryFunctionException, InterruptedException { MavenServerValue serverValue = getServer(rule, env); if (env.valuesMissing()) { return null; @@ -80,11 +75,11 @@ public class MavenJarFunction extends HttpArchiveFunction { .digestAndReset(); } - private MavenServerValue getServer(Rule rule, Environment env) - throws RepositoryFunctionException { + private static MavenServerValue getServer(Rule rule, Environment env) + throws RepositoryFunctionException, InterruptedException { AggregatingAttributeMapper mapper = AggregatingAttributeMapper.of(rule); - boolean hasRepository = mapper.has("repository", Type.STRING) - && !mapper.get("repository", Type.STRING).isEmpty(); + boolean hasRepository = + mapper.has("repository", Type.STRING) && !mapper.get("repository", Type.STRING).isEmpty(); boolean hasServer = mapper.has("server", Type.STRING) && !mapper.get("server", Type.STRING).isEmpty(); diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenServerFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenServerFunction.java index 73bfe2682c..ea85f50c80 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenServerFunction.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenServerFunction.java @@ -31,12 +31,14 @@ import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.lib.vfs.RootedPath; import com.google.devtools.build.skyframe.SkyFunction; -import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyFunctionException.Transience; import com.google.devtools.build.skyframe.SkyFunctionName; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - +import java.io.IOException; +import java.util.Arrays; +import java.util.Map; +import javax.annotation.Nullable; import org.apache.maven.settings.Server; import org.apache.maven.settings.Settings; import org.apache.maven.settings.building.DefaultSettingsBuilder; @@ -45,12 +47,6 @@ import org.apache.maven.settings.building.DefaultSettingsBuildingRequest; import org.apache.maven.settings.building.SettingsBuildingException; import org.apache.maven.settings.building.SettingsBuildingResult; -import java.io.IOException; -import java.util.Arrays; -import java.util.Map; - -import javax.annotation.Nullable; - /** * Implementation of maven_repository. */ @@ -66,7 +62,7 @@ public class MavenServerFunction implements SkyFunction { @Nullable @Override public SkyValue compute(SkyKey skyKey, Environment env) - throws SkyFunctionException { + throws InterruptedException, RepositoryFunctionException { String repository = (String) skyKey.argument(); Rule repositoryRule = null; try { @@ -175,7 +171,7 @@ public class MavenServerFunction implements SkyFunction { } private Map<String, FileValue> getDefaultSettingsFile( - BlazeDirectories directories, Environment env) { + BlazeDirectories directories, Environment env) throws InterruptedException { // The system settings file is at $M2_HOME/conf/settings.xml. String m2Home = System.getenv("M2_HOME"); ImmutableList.Builder<SkyKey> settingsFilesBuilder = ImmutableList.builder(); diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/NewGitRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/NewGitRepositoryFunction.java index 4a8c56fb5c..e41695f5ea 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/NewGitRepositoryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/NewGitRepositoryFunction.java @@ -20,7 +20,6 @@ import com.google.devtools.build.lib.rules.repository.NewRepositoryBuildFileHand import com.google.devtools.build.lib.rules.repository.RepositoryDirectoryValue; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.skyframe.SkyFunction.Environment; -import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyValue; /** @@ -30,7 +29,7 @@ public class NewGitRepositoryFunction extends GitRepositoryFunction { @Override public SkyValue fetch( Rule rule, Path outputDirectory, BlazeDirectories directories, Environment env) - throws SkyFunctionException { + throws InterruptedException, RepositoryFunctionException { NewRepositoryBuildFileHandler buildFileHandler = new NewRepositoryBuildFileHandler(directories.getWorkspace()); if (!buildFileHandler.prepareBuildFile(rule, env)) { diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java index 4ed66e965b..bfe4aec0a0 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java @@ -142,11 +142,12 @@ public class SkylarkRepositoryContext { + "during the analysis phase and thus cannot depends on a target result (the " + "label should point to a non-generated file)." ) - public SkylarkPath path(Object path) throws EvalException { + public SkylarkPath path(Object path) throws EvalException, InterruptedException { return getPath("path()", path); } - private SkylarkPath getPath(String method, Object path) throws EvalException { + private SkylarkPath getPath(String method, Object path) + throws EvalException, InterruptedException { if (path instanceof String) { PathFragment pathFragment = new PathFragment(path.toString()); return new SkylarkPath(pathFragment.isAbsolute() @@ -171,7 +172,8 @@ public class SkylarkRepositoryContext { "Create a symlink on the filesystem, the destination of the symlink should be in the " + "output directory. <code>from</code> can also be a label to a file." ) - public void symlink(Object from, Object to) throws RepositoryFunctionException, EvalException { + public void symlink(Object from, Object to) + throws RepositoryFunctionException, EvalException, InterruptedException { SkylarkPath fromPath = getPath("symlink()", from); SkylarkPath toPath = getPath("symlink()", to); try { @@ -198,26 +200,25 @@ public class SkylarkRepositoryContext { } @SkylarkCallable(name = "file", documented = false) - public void createFile(Object path) throws RepositoryFunctionException, EvalException { + public void createFile(Object path) + throws RepositoryFunctionException, EvalException, InterruptedException { createFile(path, ""); } - @SkylarkCallable( - name = "file", - documented = false - ) + @SkylarkCallable(name = "file", documented = false) public void createFile(Object path, String content) - throws RepositoryFunctionException, EvalException { + throws RepositoryFunctionException, EvalException, InterruptedException { createFile(path, content, true); } @SkylarkCallable( name = "file", - doc = "Generate a file in the output directory with the provided content. An optional third " - + "argument set the executable bit to on or off (default to True)." + doc = + "Generate a file in the output directory with the provided content. An optional third " + + "argument set the executable bit to on or off (default to True)." ) public void createFile(Object path, String content, Boolean executable) - throws RepositoryFunctionException, EvalException { + throws RepositoryFunctionException, EvalException, InterruptedException { SkylarkPath p = getPath("file()", path); try { checkInOutputDirectory(p); @@ -233,28 +234,25 @@ public class SkylarkRepositoryContext { } } - @SkylarkCallable( - name = "template", - documented = false - ) + @SkylarkCallable(name = "template", documented = false) public void createFileFromTemplate( Object path, Object template, Map<String, String> substitutions) - throws RepositoryFunctionException, EvalException { + throws RepositoryFunctionException, EvalException, InterruptedException { createFileFromTemplate(path, template, substitutions, true); } @SkylarkCallable( - name = "template", - doc = - "Generate a new file using a <code>template</code>. Every occurrence in " - + "<code>template</code> of a key of <code>substitutions</code> will be replaced by " - + "the corresponding value. The result is written in <code>path</code>. An optional" - + "<code>executable</code> argument (default to true) can be set to turn on or off" - + "the executable bit." + name = "template", + doc = + "Generate a new file using a <code>template</code>. Every occurrence in " + + "<code>template</code> of a key of <code>substitutions</code> will be replaced by " + + "the corresponding value. The result is written in <code>path</code>. An optional" + + "<code>executable</code> argument (default to true) can be set to turn on or off" + + "the executable bit." ) public void createFileFromTemplate( - Object path, Object template, Map<String, String> substitutions, Boolean executable) - throws RepositoryFunctionException, EvalException { + Object path, Object template, Map<String, String> substitutions, Boolean executable) + throws RepositoryFunctionException, EvalException, InterruptedException { SkylarkPath p = getPath("template()", path); SkylarkPath t = getPath("template()", template); try { @@ -522,7 +520,7 @@ public class SkylarkRepositoryContext { } // Resolve the label given by value into a file path. - private SkylarkPath getPathFromLabel(Label label) throws EvalException { + private SkylarkPath getPathFromLabel(Label label) throws EvalException, InterruptedException { // Look for package. if (label.getPackageIdentifier().getRepository().isDefault()) { try { diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelConfigurationCollection.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelConfigurationCollection.java index 4db1a92b53..0bc74f4948 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelConfigurationCollection.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelConfigurationCollection.java @@ -35,11 +35,9 @@ import com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition; import com.google.devtools.build.lib.packages.Attribute.SplitTransition; import com.google.devtools.build.lib.packages.Attribute.Transition; import com.google.devtools.build.lib.rules.cpp.CppRuleClasses.LipoTransition; - import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; - import javax.annotation.Nullable; /** @@ -53,7 +51,8 @@ public class BazelConfigurationCollection implements ConfigurationCollectionFact Cache<String, BuildConfiguration> cache, PackageProviderForConfigurations packageProvider, BuildOptions buildOptions, - EventHandler eventHandler) throws InvalidConfigurationException { + EventHandler eventHandler) + throws InvalidConfigurationException, InterruptedException { // Target configuration BuildConfiguration targetConfiguration = configurationFactory.getConfiguration( packageProvider, buildOptions, false, cache); @@ -114,29 +113,28 @@ public class BazelConfigurationCollection implements ConfigurationCollectionFact } /** - * Gets the correct host configuration for this build. The behavior - * depends on the value of the --distinct_host_configuration flag. + * Gets the correct host configuration for this build. The behavior depends on the value of the + * --distinct_host_configuration flag. * - * <p>With --distinct_host_configuration=false, we use identical configurations - * for the host and target, and you can ignore everything below. But please - * note: if you're cross-compiling for k8 on a piii machine, your build will - * fail. This is a stopgap measure. + * <p>With --distinct_host_configuration=false, we use identical configurations for the host and + * target, and you can ignore everything below. But please note: if you're cross-compiling for k8 + * on a piii machine, your build will fail. This is a stopgap measure. * - * <p>Currently, every build is (in effect) a cross-compile, in the strict - * sense that host and target configurations are unequal, thus we do not - * issue a "cross-compiling" warning. (Perhaps we should?) - * * - * @param requestConfig the requested target (not host!) configuration for - * this build. + * <p>Currently, every build is (in effect) a cross-compile, in the strict sense that host and + * target configurations are unequal, thus we do not issue a "cross-compiling" warning. (Perhaps + * we should?) * + * + * @param requestConfig the requested target (not host!) configuration for this build. * @param buildOptions the configuration options used for the target configuration */ @Nullable - private BuildConfiguration getHostConfigurationFromRequest( + private static BuildConfiguration getHostConfigurationFromRequest( ConfigurationFactory configurationFactory, PackageProviderForConfigurations loadedPackageProvider, - BuildConfiguration requestConfig, BuildOptions buildOptions, + BuildConfiguration requestConfig, + BuildOptions buildOptions, Cache<String, BuildConfiguration> cache) - throws InvalidConfigurationException { + throws InvalidConfigurationException, InterruptedException { BuildConfiguration.Options commonOptions = buildOptions.get(BuildConfiguration.Options.class); if (!commonOptions.useDistinctHostConfiguration) { return requestConfig; diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryFunction.java index b30dae6afb..f26bfc93c2 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryFunction.java @@ -44,11 +44,9 @@ import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CTool import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CrosstoolRelease; import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.ToolPath; import com.google.devtools.build.skyframe.SkyFunction.Environment; -import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyFunctionException.Transience; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -80,7 +78,7 @@ public class AndroidNdkRepositoryFunction extends RepositoryFunction { @Override public SkyValue fetch( Rule rule, Path outputDirectory, BlazeDirectories directories, Environment env) - throws SkyFunctionException { + throws InterruptedException, RepositoryFunctionException { prepareLocalRepositorySymlinkTree(rule, outputDirectory); PathFragment pathFragment = getTargetPath(rule, directories.getWorkspace()); Path ndkSymlinkTreeDirectory = outputDirectory.getRelative("ndk"); @@ -267,7 +265,7 @@ public class AndroidNdkRepositoryFunction extends RepositoryFunction { } private static NdkRelease getNdkRelease(Path directory, Environment env) - throws RepositoryFunctionException { + throws RepositoryFunctionException, InterruptedException { // For NDK r11+ Path releaseFilePath = directory.getRelative("ndk/source.properties"); diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryFunction.java index 7285c056bf..5852a19012 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryFunction.java @@ -33,7 +33,6 @@ import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyFunctionException.Transience; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.io.IOException; import java.util.Properties; @@ -49,7 +48,7 @@ public class AndroidSdkRepositoryFunction extends RepositoryFunction { @Override public SkyValue fetch( Rule rule, Path outputDirectory, BlazeDirectories directories, Environment env) - throws SkyFunctionException { + throws SkyFunctionException, InterruptedException { prepareLocalRepositorySymlinkTree(rule, outputDirectory); PathFragment pathFragment = getTargetPath(rule, directories.getWorkspace()); @@ -111,7 +110,7 @@ public class AndroidSdkRepositoryFunction extends RepositoryFunction { private static Properties getBuildToolsSourceProperties( Path directory, String buildToolsDirectory, Environment env) - throws RepositoryFunctionException { + throws RepositoryFunctionException, InterruptedException { Path sourcePropertiesFilePath = directory.getRelative( "build-tools/" + buildToolsDirectory + "/source.properties"); diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/genrule/GenRule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/genrule/GenRule.java index 418130b9eb..479bfce47f 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/genrule/GenRule.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/genrule/GenRule.java @@ -42,7 +42,6 @@ import com.google.devtools.build.lib.packages.TargetUtils; import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.vfs.PathFragment; - import java.util.List; import java.util.Map; @@ -62,7 +61,8 @@ public class GenRule implements RuleConfiguredTargetFactory { } @Override - public ConfiguredTarget create(RuleContext ruleContext) throws RuleErrorException { + public ConfiguredTarget create(RuleContext ruleContext) + throws RuleErrorException, InterruptedException { final List<Artifact> resolvedSrcs = Lists.newArrayList(); final NestedSet<Artifact> filesToBuild = diff --git a/src/main/java/com/google/devtools/build/lib/cmdline/TargetPatternResolver.java b/src/main/java/com/google/devtools/build/lib/cmdline/TargetPatternResolver.java index 8dc0f0a76a..a3aea666c7 100644 --- a/src/main/java/com/google/devtools/build/lib/cmdline/TargetPatternResolver.java +++ b/src/main/java/com/google/devtools/build/lib/cmdline/TargetPatternResolver.java @@ -95,7 +95,7 @@ public interface TargetPatternResolver<T> { * Returns true, if and only if the given package identifier corresponds to a package, i.e., a * file with the name {@code packageName/BUILD} exists in the appropriat repository. */ - boolean isPackage(PackageIdentifier packageIdentifier); + boolean isPackage(PackageIdentifier packageIdentifier) throws InterruptedException; /** * Returns the target kind of the given target, for example {@code cc_library rule}. diff --git a/src/main/java/com/google/devtools/build/lib/concurrent/AbstractQueueVisitor.java b/src/main/java/com/google/devtools/build/lib/concurrent/AbstractQueueVisitor.java index baab8847e7..01cdca1d3e 100644 --- a/src/main/java/com/google/devtools/build/lib/concurrent/AbstractQueueVisitor.java +++ b/src/main/java/com/google/devtools/build/lib/concurrent/AbstractQueueVisitor.java @@ -20,7 +20,6 @@ import com.google.common.util.concurrent.AtomicLongMap; import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.devtools.build.lib.concurrent.ErrorClassifier.ErrorClassification; import com.google.devtools.build.lib.util.Preconditions; - import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.RejectedExecutionException; @@ -29,7 +28,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.logging.Level; import java.util.logging.Logger; - import javax.annotation.Nullable; /** A {@link QuiescingExecutor} implementation that wraps an {@link ExecutorService}. */ @@ -143,7 +141,6 @@ public class AbstractQueueVisitor implements QuiescingExecutor { private final boolean ownExecutorService; private final ErrorClassifier errorClassifier; - private final ErrorHandler errorHandler; private static final Logger LOG = Logger.getLogger(AbstractQueueVisitor.class.getName()); @@ -176,25 +173,23 @@ public class AbstractQueueVisitor implements QuiescingExecutor { failFastOnException, poolName, EXECUTOR_FACTORY, - ErrorClassifier.DEFAULT, - ErrorHandler.NullHandler.INSTANCE); + ErrorClassifier.DEFAULT); } /** * Create the {@link AbstractQueueVisitor}. * * @param concurrent {@code true} if concurrency should be enabled. Only set to {@code false} for - * debugging. + * debugging. * @param parallelism a measure of parallelism for the {@link ExecutorService}, such as {@code - * parallelism} in {@link java.util.concurrent.ForkJoinPool}, or both {@code - * corePoolSize} and {@code maximumPoolSize} in {@link ThreadPoolExecutor}. + * parallelism} in {@link java.util.concurrent.ForkJoinPool}, or both {@code corePoolSize} and + * {@code maximumPoolSize} in {@link ThreadPoolExecutor}. * @param keepAliveTime the keep-alive time for the {@link ExecutorService}, if applicable. * @param units the time units of keepAliveTime. * @param failFastOnException if {@code true}, don't run new actions after an uncaught exception. * @param poolName sets the name of threads spawned by the {@link ExecutorService}. If {@code - * null}, default thread naming will be used. + * null}, default thread naming will be used. * @param errorClassifier an error classifier used to determine whether to log and/or stop jobs. - * @param errorHandler a handler for classified errors. */ public AbstractQueueVisitor( boolean concurrent, @@ -203,8 +198,7 @@ public class AbstractQueueVisitor implements QuiescingExecutor { TimeUnit units, boolean failFastOnException, String poolName, - ErrorClassifier errorClassifier, - ErrorHandler errorHandler) { + ErrorClassifier errorClassifier) { this( concurrent, parallelism, @@ -213,27 +207,25 @@ public class AbstractQueueVisitor implements QuiescingExecutor { failFastOnException, poolName, EXECUTOR_FACTORY, - errorClassifier, - errorHandler); + errorClassifier); } /** * Create the {@link AbstractQueueVisitor}. * * @param concurrent {@code true} if concurrency should be enabled. Only set to {@code false} for - * debugging. + * debugging. * @param parallelism a measure of parallelism for the {@link ExecutorService}, such as {@code - * parallelism} in {@link java.util.concurrent.ForkJoinPool}, or both {@code - * corePoolSize} and {@code maximumPoolSize} in {@link ThreadPoolExecutor}. + * parallelism} in {@link java.util.concurrent.ForkJoinPool}, or both {@code corePoolSize} and + * {@code maximumPoolSize} in {@link ThreadPoolExecutor}. * @param keepAliveTime the keep-alive time for the {@link ExecutorService}, if applicable. * @param units the time units of keepAliveTime. * @param failFastOnException if {@code true}, don't run new actions after an uncaught exception. * @param poolName sets the name of threads spawned by the {@link ExecutorService}. If {@code - * null}, default thread naming will be used. + * null}, default thread naming will be used. * @param executorFactory the factory for constructing the executor service if {@code concurrent} - * is {@code true}. + * is {@code true}. * @param errorClassifier an error classifier used to determine whether to log and/or stop jobs. - * @param errorHandler a handler for classified errors. */ public AbstractQueueVisitor( boolean concurrent, @@ -243,8 +235,7 @@ public class AbstractQueueVisitor implements QuiescingExecutor { boolean failFastOnException, String poolName, Function<ExecutorParams, ? extends ExecutorService> executorFactory, - ErrorClassifier errorClassifier, - ErrorHandler errorHandler) { + ErrorClassifier errorClassifier) { Preconditions.checkNotNull(poolName); Preconditions.checkNotNull(executorFactory); Preconditions.checkNotNull(errorClassifier); @@ -258,7 +249,6 @@ public class AbstractQueueVisitor implements QuiescingExecutor { parallelism, keepAliveTime, units, poolName, new BlockingStack<Runnable>())) : null; this.errorClassifier = errorClassifier; - this.errorHandler = errorHandler; } /** @@ -278,8 +268,7 @@ public class AbstractQueueVisitor implements QuiescingExecutor { executorService, shutdownOnCompletion, failFastOnException, - ErrorClassifier.DEFAULT, - ErrorHandler.NullHandler.INSTANCE); + ErrorClassifier.DEFAULT); } /** @@ -305,37 +294,32 @@ public class AbstractQueueVisitor implements QuiescingExecutor { this.ownExecutorService = shutdownOnCompletion; this.executorService = executorService; this.errorClassifier = ErrorClassifier.DEFAULT; - this.errorHandler = ErrorHandler.NullHandler.INSTANCE; } /** * Create the AbstractQueueVisitor. * * @param concurrent if {@code false}, run tasks inline instead of using the {@link - * ExecutorService}. + * ExecutorService}. * @param executorService The {@link ExecutorService} to use. * @param shutdownOnCompletion If {@code true}, pass ownership of the {@link ExecutorService} to - * this class. The service will be shut down after a - * call to {@link #awaitQuiescence}. Callers must not shut down the - * {@link ExecutorService} while queue visitors use it. + * this class. The service will be shut down after a call to {@link #awaitQuiescence}. Callers + * must not shut down the {@link ExecutorService} while queue visitors use it. * @param failFastOnException if {@code true}, don't run new actions after an uncaught exception. * @param errorClassifier an error classifier used to determine whether to log and/or stop jobs. - * @param errorHandler a handler for classified errors. */ public AbstractQueueVisitor( boolean concurrent, ExecutorService executorService, boolean shutdownOnCompletion, boolean failFastOnException, - ErrorClassifier errorClassifier, - ErrorHandler errorHandler) { + ErrorClassifier errorClassifier) { Preconditions.checkArgument(executorService != null || !concurrent); this.concurrent = concurrent; this.failFastOnException = failFastOnException; this.ownExecutorService = shutdownOnCompletion; this.executorService = executorService; this.errorClassifier = errorClassifier; - this.errorHandler = errorHandler; } /** @@ -358,8 +342,7 @@ public class AbstractQueueVisitor implements QuiescingExecutor { false, poolName, EXECUTOR_FACTORY, - ErrorClassifier.DEFAULT, - ErrorHandler.NullHandler.INSTANCE); + ErrorClassifier.DEFAULT); } @@ -437,7 +420,6 @@ public class AbstractQueueVisitor implements QuiescingExecutor { default: break; } - errorHandler.handle(e, errorClassification); if (unhandled == null || errorClassification.compareTo(errorClassifier.classify(unhandled)) > 0) { // Save the most severe error. diff --git a/src/main/java/com/google/devtools/build/lib/concurrent/ForkJoinQuiescingExecutor.java b/src/main/java/com/google/devtools/build/lib/concurrent/ForkJoinQuiescingExecutor.java index 54bb572665..45132a1cb7 100644 --- a/src/main/java/com/google/devtools/build/lib/concurrent/ForkJoinQuiescingExecutor.java +++ b/src/main/java/com/google/devtools/build/lib/concurrent/ForkJoinQuiescingExecutor.java @@ -23,15 +23,13 @@ import java.util.concurrent.ForkJoinTask; // maintaining AQV.remainingTasks. public class ForkJoinQuiescingExecutor extends AbstractQueueVisitor { - public ForkJoinQuiescingExecutor(ForkJoinPool forkJoinPool, ErrorClassifier errorClassifier, - ErrorHandler errorHandler) { + public ForkJoinQuiescingExecutor(ForkJoinPool forkJoinPool, ErrorClassifier errorClassifier) { super( /*concurrent=*/ true, forkJoinPool, /*shutdownOnCompletion=*/ true, /*failFastOnException=*/ true, - errorClassifier, - errorHandler); + errorClassifier); } @Override diff --git a/src/main/java/com/google/devtools/build/lib/packages/AbstractAttributeMapper.java b/src/main/java/com/google/devtools/build/lib/packages/AbstractAttributeMapper.java index f37613fd04..d89e278ab7 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/AbstractAttributeMapper.java +++ b/src/main/java/com/google/devtools/build/lib/packages/AbstractAttributeMapper.java @@ -136,7 +136,7 @@ public abstract class AbstractAttributeMapper implements AttributeMap { } @Override - public void visitLabels(AcceptsLabelAttribute observer) { + public void visitLabels(AcceptsLabelAttribute observer) throws InterruptedException { for (Attribute attribute : ruleClass.getAttributes()) { Type<?> type = attribute.getType(); // TODO(bazel-team): clean up the typing / visitation interface so we don't have to @@ -148,10 +148,9 @@ public abstract class AbstractAttributeMapper implements AttributeMap { } } - /** - * Visits all labels reachable from the given attribute. - */ - protected void visitLabels(Attribute attribute, AcceptsLabelAttribute observer) { + /** Visits all labels reachable from the given attribute. */ + protected void visitLabels(Attribute attribute, AcceptsLabelAttribute observer) + throws InterruptedException { Type<?> type = attribute.getType(); Object value = get(attribute.getName(), type); if (value != null) { // null values are particularly possible for computed defaults. diff --git a/src/main/java/com/google/devtools/build/lib/packages/AggregatingAttributeMapper.java b/src/main/java/com/google/devtools/build/lib/packages/AggregatingAttributeMapper.java index 454cd71bf9..4fab639d96 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/AggregatingAttributeMapper.java +++ b/src/main/java/com/google/devtools/build/lib/packages/AggregatingAttributeMapper.java @@ -86,8 +86,7 @@ public class AggregatingAttributeMapper extends AbstractAttributeMapper { } /** - * Override that also visits the rule's configurable attribute keys (which are - * themselves labels). + * Override that also visits the rule's configurable attribute keys (which are themselves labels). * * <p>Note that we directly parse the selectors rather than just calling {@link #visitAttribute} * to iterate over all possible values. That's because {@link #visitAttribute} can grow @@ -96,12 +95,14 @@ public class AggregatingAttributeMapper extends AbstractAttributeMapper { * path whenever actual value iteration isn't specifically needed. */ @Override - protected void visitLabels(Attribute attribute, AcceptsLabelAttribute observer) { + protected void visitLabels(Attribute attribute, AcceptsLabelAttribute observer) + throws InterruptedException { visitLabels(attribute, true, observer); } - private void visitLabels(Attribute attribute, boolean includeSelectKeys, - AcceptsLabelAttribute observer) { + private void visitLabels( + Attribute attribute, boolean includeSelectKeys, AcceptsLabelAttribute observer) + throws InterruptedException { Type<?> type = attribute.getType(); SelectorList<?> selectorList = getSelectorList(attribute.getName(), type); if (selectorList == null) { @@ -137,12 +138,13 @@ public class AggregatingAttributeMapper extends AbstractAttributeMapper { } /** - * Returns all labels reachable via the given attribute. If a label is listed multiple times, - * each instance appears in the returned list. + * Returns all labels reachable via the given attribute. If a label is listed multiple times, each + * instance appears in the returned list. * * @param includeSelectKeys whether to include config_setting keys for configurable attributes */ - public List<Label> getReachableLabels(String attributeName, boolean includeSelectKeys) { + public List<Label> getReachableLabels(String attributeName, boolean includeSelectKeys) + throws InterruptedException { final ImmutableList.Builder<Label> builder = ImmutableList.builder(); visitLabels(getAttributeDefinition(attributeName), includeSelectKeys, new AcceptsLabelAttribute() { @@ -520,8 +522,10 @@ public class AggregatingAttributeMapper extends AbstractAttributeMapper { return owner.get(attributeName, type); } if (!directMap.containsKey(attributeName)) { - throw new IllegalArgumentException("attribute \"" + attributeName - + "\" isn't available in this computed default context"); + throw new IllegalArgumentException( + "attribute \"" + + attributeName + + "\" isn't available in this computed default context"); } return type.cast(directMap.get(attributeName)); } @@ -531,34 +535,70 @@ public class AggregatingAttributeMapper extends AbstractAttributeMapper { return owner.isConfigurable(attributeName, type); } - @Override public String getName() { return owner.getName(); } - @Override public Label getLabel() { return owner.getLabel(); } - @Override public Iterable<String> getAttributeNames() { + @Override + public String getName() { + return owner.getName(); + } + + @Override + public Label getLabel() { + return owner.getLabel(); + } + + @Override + public Iterable<String> getAttributeNames() { return ImmutableList.<String>builder() - .addAll(directMap.keySet()).addAll(nonConfigurableAttributes).build(); + .addAll(directMap.keySet()) + .addAll(nonConfigurableAttributes) + .build(); } + @Override - public void visitLabels(AcceptsLabelAttribute observer) { owner.visitLabels(observer); } + public void visitLabels(AcceptsLabelAttribute observer) throws InterruptedException { + owner.visitLabels(observer); + } + @Override - public String getPackageDefaultHdrsCheck() { return owner.getPackageDefaultHdrsCheck(); } + public String getPackageDefaultHdrsCheck() { + return owner.getPackageDefaultHdrsCheck(); + } + @Override - public Boolean getPackageDefaultTestOnly() { return owner.getPackageDefaultTestOnly(); } + public Boolean getPackageDefaultTestOnly() { + return owner.getPackageDefaultTestOnly(); + } + @Override - public String getPackageDefaultDeprecation() { return owner.getPackageDefaultDeprecation(); } + public String getPackageDefaultDeprecation() { + return owner.getPackageDefaultDeprecation(); + } + @Override public ImmutableList<String> getPackageDefaultCopts() { return owner.getPackageDefaultCopts(); } - @Nullable @Override - public Type<?> getAttributeType(String attrName) { return owner.getAttributeType(attrName); } - @Nullable @Override public Attribute getAttributeDefinition(String attrName) { + + @Nullable + @Override + public Type<?> getAttributeType(String attrName) { + return owner.getAttributeType(attrName); + } + + @Nullable + @Override + public Attribute getAttributeDefinition(String attrName) { return owner.getAttributeDefinition(attrName); } - @Override public boolean isAttributeValueExplicitlySpecified(String attributeName) { + + @Override + public boolean isAttributeValueExplicitlySpecified(String attributeName) { return owner.isAttributeValueExplicitlySpecified(attributeName); } + @Override - public boolean has(String attrName, Type<?> type) { return owner.has(attrName, type); } + public boolean has(String attrName, Type<?> type) { + return owner.has(attrName, type); + } }; } } diff --git a/src/main/java/com/google/devtools/build/lib/packages/AttributeMap.java b/src/main/java/com/google/devtools/build/lib/packages/AttributeMap.java index b5c4508be5..3e62f2947d 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/AttributeMap.java +++ b/src/main/java/com/google/devtools/build/lib/packages/AttributeMap.java @@ -16,7 +16,6 @@ package com.google.devtools.build.lib.packages; import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.syntax.Type; - import javax.annotation.Nullable; /** @@ -91,19 +90,19 @@ public interface AttributeMap { /** * Accept a (Label, Attribute) pair describing a dependency edge. * - * @param label the target node of the (Rule, Label) edge. - * The source node should already be known. + * @param label the target node of the (Rule, Label) edge. The source node should already be + * known. * @param attribute the attribute. */ - void acceptLabelAttribute(Label label, Attribute attribute); + void acceptLabelAttribute(Label label, Attribute attribute) throws InterruptedException; } /** - * For all attributes that contain labels in their values (either by *being* a label or - * being a collection that includes labels), visits every label and notifies the - * specified observer at each visit. + * For all attributes that contain labels in their values (either by *being* a label or being a + * collection that includes labels), visits every label and notifies the specified observer at + * each visit. */ - void visitLabels(AcceptsLabelAttribute observer); + void visitLabels(AcceptsLabelAttribute observer) throws InterruptedException; // TODO(bazel-team): These methods are here to support computed defaults that inherit // package-level default values. Instead, we should auto-inherit and remove the computed diff --git a/src/main/java/com/google/devtools/build/lib/packages/DelegatingAttributeMapper.java b/src/main/java/com/google/devtools/build/lib/packages/DelegatingAttributeMapper.java index 174b9b9848..e57476c551 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/DelegatingAttributeMapper.java +++ b/src/main/java/com/google/devtools/build/lib/packages/DelegatingAttributeMapper.java @@ -17,7 +17,6 @@ import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.Preconditions; - import javax.annotation.Nullable; /** @@ -74,7 +73,7 @@ public class DelegatingAttributeMapper implements AttributeMap { } @Override - public void visitLabels(AcceptsLabelAttribute observer) { + public void visitLabels(AcceptsLabelAttribute observer) throws InterruptedException { delegate.visitLabels(observer); } diff --git a/src/main/java/com/google/devtools/build/lib/packages/ExternalPackageBuilder.java b/src/main/java/com/google/devtools/build/lib/packages/ExternalPackageBuilder.java index c6b000459b..dd9678a733 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/ExternalPackageBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/packages/ExternalPackageBuilder.java @@ -24,7 +24,6 @@ import com.google.devtools.build.lib.packages.Package.Builder; import com.google.devtools.build.lib.packages.RuleFactory.BuildLangTypedAttributeValuesMap; import com.google.devtools.build.lib.syntax.FuncallExpression; import com.google.devtools.build.lib.util.Preconditions; - import java.util.Map; /** @@ -69,7 +68,7 @@ public class ExternalPackageBuilder { return rule; } - void addBindRule( + static void addBindRule( Builder pkg, RuleClass bindRuleClass, Label virtual, @@ -102,7 +101,8 @@ public class ExternalPackageBuilder { rule.setVisibility(ConstantRuleVisibility.PUBLIC); } - private void overwriteRule(Package.Builder pkg, Rule rule) throws Package.NameConflictException { + private static void overwriteRule(Package.Builder pkg, Rule rule) + throws Package.NameConflictException, InterruptedException { Preconditions.checkArgument(rule.getOutputFiles().isEmpty()); Target old = pkg.targets.get(rule.getName()); if (old != null) { diff --git a/src/main/java/com/google/devtools/build/lib/packages/Globber.java b/src/main/java/com/google/devtools/build/lib/packages/Globber.java index 64d61796d3..a2f980c7ad 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/Globber.java +++ b/src/main/java/com/google/devtools/build/lib/packages/Globber.java @@ -29,14 +29,13 @@ public interface Globber { } /** - * Asynchronously starts the given glob computation and returns a token for fetching the - * result. + * Asynchronously starts the given glob computation and returns a token for fetching the result. * * @throws BadGlobException if any of the patterns in {@code includes} or {@code excludes} are * invalid. */ Token runAsync(List<String> includes, List<String> excludes, boolean excludeDirs) - throws BadGlobException; + throws BadGlobException, InterruptedException; /** * Fetches the result of a previously started glob computation. The returned list must be ordered diff --git a/src/main/java/com/google/devtools/build/lib/packages/Package.java b/src/main/java/com/google/devtools/build/lib/packages/Package.java index 90e3b59516..f1d9b51878 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/Package.java +++ b/src/main/java/com/google/devtools/build/lib/packages/Package.java @@ -1265,12 +1265,12 @@ public class Package { } } - void addRule(Rule rule) throws NameConflictException { + void addRule(Rule rule) throws NameConflictException, InterruptedException { checkForConflicts(rule); addRuleUnchecked(rule); } - private Builder beforeBuild() { + private Builder beforeBuild() throws InterruptedException { Preconditions.checkNotNull(pkg); Preconditions.checkNotNull(filename); Preconditions.checkNotNull(buildFileLabel); @@ -1323,7 +1323,7 @@ public class Package { } /** Intended for use by {@link com.google.devtools.build.lib.skyframe.PackageFunction} only. */ - public Builder buildPartial() { + public Builder buildPartial() throws InterruptedException { if (alreadyBuilt) { return this; } @@ -1371,7 +1371,7 @@ public class Package { return externalPackageData; } - public Package build() { + public Package build() throws InterruptedException { if (alreadyBuilt) { return pkg; } @@ -1399,14 +1399,15 @@ public class Package { } /** - * Precondition check for addRule. We must maintain these invariants of the - * package: - * - Each name refers to at most one target. - * - No rule with errors is inserted into the package. - * - The generating rule of every output file in the package must itself be - * in the package. + * Precondition check for addRule. We must maintain these invariants of the package: + * + * <ul> + * <li>Each name refers to at most one target. + * <li>No rule with errors is inserted into the package. + * <li>The generating rule of every output file in the package must itself be in the package. + * </ul> */ - private void checkForConflicts(Rule rule) throws NameConflictException { + private void checkForConflicts(Rule rule) throws NameConflictException, InterruptedException { String name = rule.getName(); Target existing = targets.get(name); if (existing != null) { @@ -1451,17 +1452,15 @@ public class Package { } /** - * A utility method that checks for conflicts between - * input file names and output file names for a rule from a build - * file. - * @param rule the rule whose inputs and outputs are - * to be checked for conflicts. - * @param outputFiles a set containing the names of output - * files to be generated by the rule. + * A utility method that checks for conflicts between input file names and output file names for + * a rule from a build file. + * + * @param rule the rule whose inputs and outputs are to be checked for conflicts. + * @param outputFiles a set containing the names of output files to be generated by the rule. * @throws NameConflictException if a conflict is found. */ private void checkForInputOutputConflicts(Rule rule, Set<String> outputFiles) - throws NameConflictException { + throws NameConflictException, InterruptedException { PathFragment packageFragment = rule.getLabel().getPackageFragment(); for (Label inputLabel : rule.getLabels()) { if (packageFragment.equals(inputLabel.getPackageFragment()) diff --git a/src/main/java/com/google/devtools/build/lib/packages/Rule.java b/src/main/java/com/google/devtools/build/lib/packages/Rule.java index dd5df33055..29af9a54c9 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/Rule.java +++ b/src/main/java/com/google/devtools/build/lib/packages/Rule.java @@ -398,10 +398,8 @@ public final class Rule implements Target, DependencyFilter.AttributeInfoProvide return false; } - /** - * Returns a new List instance containing all direct dependencies (all types). - */ - public Collection<Label> getLabels() { + /** Returns a new List instance containing all direct dependencies (all types). */ + public Collection<Label> getLabels() throws InterruptedException { final List<Label> labels = Lists.newArrayList(); AggregatingAttributeMapper.of(this).visitLabels(new AttributeMap.AcceptsLabelAttribute() { @Override @@ -413,29 +411,30 @@ public final class Rule implements Target, DependencyFilter.AttributeInfoProvide } /** - * Returns a new Collection containing all Labels that match a given Predicate, - * not including outputs. + * Returns a new Collection containing all Labels that match a given Predicate, not including + * outputs. * - * @param predicate A binary predicate that determines if a label should be - * included in the result. The predicate is evaluated with this rule and - * the attribute that contains the label. The label will be contained in the - * result iff (the predicate returned {@code true} and the labels are not outputs) + * @param predicate A binary predicate that determines if a label should be included in the + * result. The predicate is evaluated with this rule and the attribute that contains the + * label. The label will be contained in the result iff (the predicate returned {@code true} + * and the labels are not outputs) */ - public Collection<Label> getLabels(BinaryPredicate<? super Rule, Attribute> predicate) { + public Collection<Label> getLabels(BinaryPredicate<? super Rule, Attribute> predicate) + throws InterruptedException { return ImmutableSortedSet.copyOf(getTransitions(predicate).values()); } /** - * Returns a new Multimap containing all attributes that match a given Predicate and - * corresponding labels, not including outputs. + * Returns a new Multimap containing all attributes that match a given Predicate and corresponding + * labels, not including outputs. * - * @param predicate A binary predicate that determines if a label should be - * included in the result. The predicate is evaluated with this rule and - * the attribute that contains the label. The label will be contained in the - * result iff (the predicate returned {@code true} and the labels are not outputs) + * @param predicate A binary predicate that determines if a label should be included in the + * result. The predicate is evaluated with this rule and the attribute that contains the + * label. The label will be contained in the result iff (the predicate returned {@code true} + * and the labels are not outputs) */ public Multimap<Attribute, Label> getTransitions( - final BinaryPredicate<? super Rule, Attribute> predicate) { + final BinaryPredicate<? super Rule, Attribute> predicate) throws InterruptedException { final Multimap<Attribute, Label> transitions = HashMultimap.create(); // TODO(bazel-team): move this to AttributeMap, too. Just like visitLabels, which labels should // be visited may depend on the calling context. We shouldn't implicitly decide this for @@ -651,7 +650,7 @@ public final class Rule implements Target, DependencyFilter.AttributeInfoProvide // null-valued, with a packageFragment that is null...). The bug that prompted // the introduction of this code is #2210848 (NullPointerException in // Package.checkForConflicts() ). - void checkForNullLabels() { + void checkForNullLabels() throws InterruptedException { AggregatingAttributeMapper.of(this).visitLabels( new AttributeMap.AcceptsLabelAttribute() { @Override diff --git a/src/main/java/com/google/devtools/build/lib/packages/TargetUtils.java b/src/main/java/com/google/devtools/build/lib/packages/TargetUtils.java index 8a90c10ff5..85dc32044d 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/TargetUtils.java +++ b/src/main/java/com/google/devtools/build/lib/packages/TargetUtils.java @@ -18,10 +18,8 @@ import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.events.Location; import com.google.devtools.build.lib.syntax.Type; - import java.util.HashMap; import java.util.Map; - import javax.annotation.Nullable; /** @@ -185,7 +183,7 @@ public final class TargetUtils { return index != -1 ? ruleClass.substring(0, index) : ruleClass; } - private static boolean isExplicitDependency(Rule rule, Label label) { + private static boolean isExplicitDependency(Rule rule, Label label) throws InterruptedException { if (rule.getVisibility().getDependencyLabels().contains(label)) { return true; } @@ -227,11 +225,11 @@ public final class TargetUtils { } /** - * Return nicely formatted error message that {@link Label} label that was pointed to by - * {@link Target} target did not exist, due to {@link NoSuchThingException} e. + * Return nicely formatted error message that {@link Label} label that was pointed to by {@link + * Target} target did not exist, due to {@link NoSuchThingException} e. */ - public static String formatMissingEdge(@Nullable Target target, Label label, - NoSuchThingException e) { + public static String formatMissingEdge( + @Nullable Target target, Label label, NoSuchThingException e) throws InterruptedException { // instanceof returns false if target is null (which is exploited here) if (target instanceof Rule) { Rule rule = (Rule) target; diff --git a/src/main/java/com/google/devtools/build/lib/pkgcache/PackageProvider.java b/src/main/java/com/google/devtools/build/lib/pkgcache/PackageProvider.java index b99d797608..23464b4f8f 100644 --- a/src/main/java/com/google/devtools/build/lib/pkgcache/PackageProvider.java +++ b/src/main/java/com/google/devtools/build/lib/pkgcache/PackageProvider.java @@ -47,17 +47,19 @@ public interface PackageProvider extends TargetProvider { /** * Returns whether a package with the given name exists. That is, returns whether all the * following hold + * * <ol> - * <li>{@code packageName} is a valid package name</li> - * <li>there is a BUILD file for the package</li> - * <li>the package is not considered deleted via --deleted_packages</li> + * <li>{@code packageName} is a valid package name + * <li>there is a BUILD file for the package + * <li>the package is not considered deleted via --deleted_packages * </ol> * - * <p> If these don't hold, then attempting to read the package with {@link #getPackage} may fail + * <p>If these don't hold, then attempting to read the package with {@link #getPackage} may fail * or may return a package containing errors. * * @param eventHandler the eventHandler on which to report warnings and errors * @param packageName the name of the package. */ - boolean isPackage(EventHandler eventHandler, PackageIdentifier packageName); + boolean isPackage(EventHandler eventHandler, PackageIdentifier packageName) + throws InterruptedException; } diff --git a/src/main/java/com/google/devtools/build/lib/pkgcache/RecursivePackageProvider.java b/src/main/java/com/google/devtools/build/lib/pkgcache/RecursivePackageProvider.java index 37c81b0c52..bdf3baaee8 100644 --- a/src/main/java/com/google/devtools/build/lib/pkgcache/RecursivePackageProvider.java +++ b/src/main/java/com/google/devtools/build/lib/pkgcache/RecursivePackageProvider.java @@ -21,7 +21,6 @@ import com.google.devtools.build.lib.packages.NoSuchPackageException; import com.google.devtools.build.lib.packages.Package; import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.lib.vfs.RootedPath; - import java.util.Map; /** @@ -32,16 +31,18 @@ public interface RecursivePackageProvider extends PackageProvider { /** * Returns the names of all the packages under a given directory. * - * <p>Packages returned by this method and passed into - * {@link #bulkGetPackages(EventHandler, Iterable)} are expected to return successful - * {@link Package} values. + * <p>Packages returned by this method and passed into {@link #bulkGetPackages(EventHandler, + * Iterable)} are expected to return successful {@link Package} values. * * @param directory a {@link RootedPath} specifying the directory to search - * @param excludedSubdirectories a set of {@link PathFragment}s, all of which are beneath - * {@code directory}, specifying transitive subdirectories to exclude + * @param excludedSubdirectories a set of {@link PathFragment}s, all of which are beneath {@code + * directory}, specifying transitive subdirectories to exclude */ - Iterable<PathFragment> getPackagesUnderDirectory(RepositoryName repository, - PathFragment directory, ImmutableSet<PathFragment> excludedSubdirectories); + Iterable<PathFragment> getPackagesUnderDirectory( + RepositoryName repository, + PathFragment directory, + ImmutableSet<PathFragment> excludedSubdirectories) + throws InterruptedException; /** diff --git a/src/main/java/com/google/devtools/build/lib/pkgcache/TargetEdgeObserver.java b/src/main/java/com/google/devtools/build/lib/pkgcache/TargetEdgeObserver.java index 294920a526..9e30d9219d 100644 --- a/src/main/java/com/google/devtools/build/lib/pkgcache/TargetEdgeObserver.java +++ b/src/main/java/com/google/devtools/build/lib/pkgcache/TargetEdgeObserver.java @@ -18,7 +18,6 @@ import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.packages.Attribute; import com.google.devtools.build.lib.packages.NoSuchThingException; import com.google.devtools.build.lib.packages.Target; - import javax.annotation.Nullable; /** @@ -41,13 +40,13 @@ public interface TargetEdgeObserver { /** * Called when a Target has a reference to a non-existent target. * - * @param target the target. May be null (e.g. in the case of an implicit - * dependency on a subincluded file). - * @param to a label reference in the rule, which does not correspond - * to a valid target. + * @param target the target. May be null (e.g. in the case of an implicit dependency on a + * subincluded file). + * @param to a label reference in the rule, which does not correspond to a valid target. * @param e the corresponding exception thrown */ - void missingEdge(@Nullable Target target, Label to, NoSuchThingException e); + void missingEdge(@Nullable Target target, Label to, NoSuchThingException e) + throws InterruptedException; /** * Called when a node is discovered. May be called diff --git a/src/main/java/com/google/devtools/build/lib/pkgcache/TargetPatternResolverUtil.java b/src/main/java/com/google/devtools/build/lib/pkgcache/TargetPatternResolverUtil.java index d00db1e1e7..d8534caf52 100644 --- a/src/main/java/com/google/devtools/build/lib/pkgcache/TargetPatternResolverUtil.java +++ b/src/main/java/com/google/devtools/build/lib/pkgcache/TargetPatternResolverUtil.java @@ -49,9 +49,9 @@ public final class TargetPatternResolverUtil { return builder.build(); } - public static void validatePatternPackage(String originalPattern, - PathFragment packageNameFragment, TargetPatternResolver<?> resolver) - throws TargetParsingException { + public static void validatePatternPackage( + String originalPattern, PathFragment packageNameFragment, TargetPatternResolver<?> resolver) + throws TargetParsingException, InterruptedException { String packageName = packageNameFragment.toString(); // It's possible for this check to pass, but for // Label.validatePackageNameFull to report an error because the diff --git a/src/main/java/com/google/devtools/build/lib/query2/AbstractBlazeQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/AbstractBlazeQueryEnvironment.java index 07df0c6ce0..5df559945e 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/AbstractBlazeQueryEnvironment.java +++ b/src/main/java/com/google/devtools/build/lib/query2/AbstractBlazeQueryEnvironment.java @@ -33,7 +33,6 @@ import com.google.devtools.build.lib.query2.engine.QueryExpression; import com.google.devtools.build.lib.query2.engine.QueryUtil.AggregateAllCallback; import com.google.devtools.build.lib.query2.engine.VariableContext; import com.google.devtools.build.lib.util.Preconditions; - import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; @@ -165,7 +164,8 @@ public abstract class AbstractBlazeQueryEnvironment<T> } } - public abstract Target getTarget(Label label) throws TargetNotFoundException, QueryException; + public abstract Target getTarget(Label label) + throws TargetNotFoundException, QueryException, InterruptedException; protected boolean validateScope(Label label, boolean strict) throws QueryException { if (!labelFilter.apply(label)) { @@ -181,7 +181,7 @@ public abstract class AbstractBlazeQueryEnvironment<T> } public Set<T> evalTargetPattern(QueryExpression caller, String pattern) - throws QueryException { + throws QueryException, InterruptedException { try { preloadOrThrow(caller, ImmutableList.of(pattern)); } catch (TargetParsingException e) { diff --git a/src/main/java/com/google/devtools/build/lib/query2/BlazeQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/BlazeQueryEnvironment.java index a29c2c6093..ad6b54002a 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/BlazeQueryEnvironment.java +++ b/src/main/java/com/google/devtools/build/lib/query2/BlazeQueryEnvironment.java @@ -48,7 +48,6 @@ import com.google.devtools.build.lib.query2.engine.Uniquifier; import com.google.devtools.build.lib.query2.engine.VariableContext; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.vfs.PathFragment; - import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -136,7 +135,8 @@ public class BlazeQueryEnvironment extends AbstractBlazeQueryEnvironment<Target> @Override public void getTargetsMatchingPattern( - QueryExpression caller, String pattern, Callback<Target> callback) throws QueryException { + QueryExpression caller, String pattern, Callback<Target> callback) + throws QueryException, InterruptedException { // We can safely ignore the boolean error flag. The evaluateQuery() method above wraps the // entire query computation in an error sensor. diff --git a/src/main/java/com/google/devtools/build/lib/query2/BlazeTargetAccessor.java b/src/main/java/com/google/devtools/build/lib/query2/BlazeTargetAccessor.java index 81de429aa0..d345a27194 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/BlazeTargetAccessor.java +++ b/src/main/java/com/google/devtools/build/lib/query2/BlazeTargetAccessor.java @@ -38,7 +38,6 @@ import com.google.devtools.build.lib.query2.engine.QueryExpression; import com.google.devtools.build.lib.query2.engine.QueryVisibility; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.Preconditions; - import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -71,8 +70,9 @@ final class BlazeTargetAccessor implements TargetAccessor<Target> { } @Override - public List<Target> getLabelListAttr(QueryExpression caller, Target target, String attrName, - String errorMsgPrefix) throws QueryException { + public List<Target> getLabelListAttr( + QueryExpression caller, Target target, String attrName, String errorMsgPrefix) + throws QueryException, InterruptedException { Preconditions.checkArgument(target instanceof Rule); List<Target> result = new ArrayList<>(); @@ -163,7 +163,8 @@ final class BlazeTargetAccessor implements TargetAccessor<Target> { } @Override - public Set<QueryVisibility<Target>> getVisibility(Target target) throws QueryException { + public Set<QueryVisibility<Target>> getVisibility(Target target) + throws QueryException, InterruptedException { ImmutableSet.Builder<QueryVisibility<Target>> result = ImmutableSet.builder(); result.add(QueryVisibility.samePackage(target, this)); convertVisibility(result, target); @@ -172,9 +173,8 @@ final class BlazeTargetAccessor implements TargetAccessor<Target> { // CAUTION: keep in sync with ConfiguredTargetFactory#convertVisibility() private void convertVisibility( - ImmutableSet.Builder<QueryVisibility<Target>> packageSpecifications, - Target target) - throws QueryException { + ImmutableSet.Builder<QueryVisibility<Target>> packageSpecifications, Target target) + throws QueryException, InterruptedException { RuleVisibility ruleVisibility = target.getVisibility(); if (ruleVisibility instanceof ConstantRuleVisibility) { if (((ConstantRuleVisibility) ruleVisibility).isPubliclyVisible()) { @@ -203,7 +203,7 @@ final class BlazeTargetAccessor implements TargetAccessor<Target> { private void convertGroupVisibility( PackageGroup group, ImmutableSet.Builder<QueryVisibility<Target>> packageSpecifications) - throws QueryException, TargetNotFoundException { + throws QueryException, TargetNotFoundException, InterruptedException { for (Label include : group.getIncludes()) { convertGroupVisibility((PackageGroup) queryEnvironment.getTarget(include), packageSpecifications); diff --git a/src/main/java/com/google/devtools/build/lib/query2/ErrorPrintingTargetEdgeErrorObserver.java b/src/main/java/com/google/devtools/build/lib/query2/ErrorPrintingTargetEdgeErrorObserver.java index b129d59c2b..11b6f790d5 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/ErrorPrintingTargetEdgeErrorObserver.java +++ b/src/main/java/com/google/devtools/build/lib/query2/ErrorPrintingTargetEdgeErrorObserver.java @@ -45,7 +45,8 @@ class ErrorPrintingTargetEdgeErrorObserver extends TargetEdgeErrorObserver { @ThreadSafety.ThreadSafe @Override - public void missingEdge(Target target, Label label, NoSuchThingException e) { + public void missingEdge(Target target, Label label, NoSuchThingException e) + throws InterruptedException { eventHandler.handle(Event.error(TargetUtils.getLocationMaybe(target), TargetUtils.formatMissingEdge(target, label, e))); super.missingEdge(target, label, e); diff --git a/src/main/java/com/google/devtools/build/lib/query2/LabelVisitor.java b/src/main/java/com/google/devtools/build/lib/query2/LabelVisitor.java index 84098386fd..c0236010f2 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/LabelVisitor.java +++ b/src/main/java/com/google/devtools/build/lib/query2/LabelVisitor.java @@ -41,7 +41,6 @@ import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.Target; import com.google.devtools.build.lib.pkgcache.PackageProvider; import com.google.devtools.build.lib.pkgcache.TargetEdgeObserver; - import java.util.Collection; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; @@ -292,13 +291,12 @@ final class LabelVisitor { } /** - * Visit the specified labels and follow the transitive closure of their - * outbound dependencies. + * Visit the specified labels and follow the transitive closure of their outbound dependencies. * * @param targets the targets to visit */ @ThreadSafe - public void visitTargets(Iterable<Target> targets) { + public void visitTargets(Iterable<Target> targets) throws InterruptedException { for (Target target : targets) { visit(null, null, target, 0, 0); } @@ -340,13 +338,15 @@ final class LabelVisitor { private Runnable newVisitRunnable(final Target from, final Attribute attr, final Label label, final int depth, final int count) { - return new Runnable () { + return new Runnable() { @Override public void run() { try { - visit(from, attr, packageProvider.getTarget(eventHandler, label), depth + 1, count); - } catch (NoSuchThingException e) { - observeError(from, label, e); + try { + visit(from, attr, packageProvider.getTarget(eventHandler, label), depth + 1, count); + } catch (NoSuchThingException e) { + observeError(from, label, e); + } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } @@ -381,7 +381,8 @@ final class LabelVisitor { * @param rule the rule to visit */ @ThreadSafe - private void visitRule(final Rule rule, final int depth, final int count) { + private void visitRule(final Rule rule, final int depth, final int count) + throws InterruptedException { // Follow all labels defined by this rule: AggregatingAttributeMapper.of(rule).visitLabels(new AttributeMap.AcceptsLabelAttribute() { @Override @@ -404,11 +405,11 @@ final class LabelVisitor { /** * Visits the target and its package. * - * <p>Potentially blocking invocations into the package cache are - * enqueued in the worker pool if CONCURRENT. + * <p>Potentially blocking invocations into the package cache are enqueued in the worker pool if + * CONCURRENT. */ - private void visit( - Target from, Attribute attribute, final Target target, int depth, int count) { + private void visit(Target from, Attribute attribute, final Target target, int depth, int count) + throws InterruptedException { if (target == null) { throw new NullPointerException( String.format("'%s' attribute '%s'", @@ -439,12 +440,11 @@ final class LabelVisitor { } /** - * Visit the specified target. - * Called in a worker thread if CONCURRENT. + * Visit the specified target. Called in a worker thread if CONCURRENT. * * @param target the target to visit */ - private void visitTargetNode(Target target, int depth, int count) { + private void visitTargetNode(Target target, int depth, int count) throws InterruptedException { Integer minTargetDepth = visitedTargets.putIfAbsent(target.getLabel(), depth); if (minTargetDepth != null) { // The target was already visited at a greater depth. @@ -493,7 +493,8 @@ final class LabelVisitor { } } - private void observeError(Target from, Label label, NoSuchThingException e) { + private void observeError(Target from, Label label, NoSuchThingException e) + throws InterruptedException { for (TargetEdgeObserver observer : observers) { observer.missingEdge(from, label, e); } diff --git a/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java index 40d8a89810..2260282eb8 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java +++ b/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java @@ -18,8 +18,6 @@ import com.google.common.base.Ascii; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.base.Predicates; -import com.google.common.base.Supplier; -import com.google.common.base.Suppliers; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; @@ -82,6 +80,7 @@ import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.lib.vfs.RootedPath; import com.google.devtools.build.skyframe.EvaluationResult; +import com.google.devtools.build.skyframe.InterruptibleSupplier; import com.google.devtools.build.skyframe.SkyFunctionName; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; @@ -146,7 +145,7 @@ public class SkyQueryEnvironment extends AbstractBlazeQueryEnvironment<Target> // The following fields are set in the #beforeEvaluateQuery method. protected WalkableGraph graph; - private Supplier<ImmutableSet<PathFragment>> blacklistPatternsSupplier; + private InterruptibleSupplier<ImmutableSet<PathFragment>> blacklistPatternsSupplier; private RecursivePackageProviderBackedTargetPatternResolver resolver; public SkyQueryEnvironment( @@ -186,7 +185,7 @@ public class SkyQueryEnvironment extends AbstractBlazeQueryEnvironment<Target> checkEvaluationResult(result, universeKey); graph = result.getWalkableGraph(); - blacklistPatternsSupplier = Suppliers.memoize(new BlacklistSupplier(graph)); + blacklistPatternsSupplier = InterruptibleSupplier.Memoize.of(new BlacklistSupplier(graph)); ImmutableList<TargetPatternKey> universeTargetPatternKeys = PrepareDepsOfPatternsFunction.getTargetPatternKeys( @@ -345,7 +344,8 @@ public class SkyQueryEnvironment extends AbstractBlazeQueryEnvironment<Target> return new QueryEvalResult(!eventHandler.hasErrors(), empty.get()); } - private Map<Target, Collection<Target>> makeTargetsMap(Map<SkyKey, Iterable<SkyKey>> input) { + private Map<Target, Collection<Target>> makeTargetsMap(Map<SkyKey, Iterable<SkyKey>> input) + throws InterruptedException { ImmutableMap.Builder<Target, Collection<Target>> result = ImmutableMap.builder(); Map<SkyKey, Target> allTargets = @@ -365,15 +365,17 @@ public class SkyQueryEnvironment extends AbstractBlazeQueryEnvironment<Target> return result.build(); } - private Map<Target, Collection<Target>> getRawFwdDeps(Iterable<Target> targets) { + private Map<Target, Collection<Target>> getRawFwdDeps(Iterable<Target> targets) + throws InterruptedException { return makeTargetsMap(graph.getDirectDeps(makeTransitiveTraversalKeys(targets))); } - private Map<Target, Collection<Target>> getRawReverseDeps(Iterable<Target> targets) { + private Map<Target, Collection<Target>> getRawReverseDeps(Iterable<Target> targets) + throws InterruptedException { return makeTargetsMap(graph.getReverseDeps(makeTransitiveTraversalKeys(targets))); } - private Set<Label> getAllowedDeps(Rule rule) { + private Set<Label> getAllowedDeps(Rule rule) throws InterruptedException { Set<Label> allowedLabels = new HashSet<>(rule.getTransitions(dependencyFilter).values()); allowedLabels.addAll(rule.getVisibility().getDependencyLabels()); // We should add deps from aspects, otherwise they are going to be filtered out. @@ -381,7 +383,8 @@ public class SkyQueryEnvironment extends AbstractBlazeQueryEnvironment<Target> return allowedLabels; } - private Collection<Target> filterFwdDeps(Target target, Collection<Target> rawFwdDeps) { + private Collection<Target> filterFwdDeps(Target target, Collection<Target> rawFwdDeps) + throws InterruptedException { if (!(target instanceof Rule)) { return rawFwdDeps; } @@ -405,7 +408,7 @@ public class SkyQueryEnvironment extends AbstractBlazeQueryEnvironment<Target> } @Override - public Collection<Target> getFwdDeps(Iterable<Target> targets) { + public Collection<Target> getFwdDeps(Iterable<Target> targets) throws InterruptedException { Set<Target> result = new HashSet<>(); Map<Target, Collection<Target>> rawFwdDeps = getRawFwdDeps(targets); warnIfMissingTargets(targets, rawFwdDeps.keySet()); @@ -416,14 +419,15 @@ public class SkyQueryEnvironment extends AbstractBlazeQueryEnvironment<Target> } @Override - public Collection<Target> getReverseDeps(Iterable<Target> targets) { + public Collection<Target> getReverseDeps(Iterable<Target> targets) throws InterruptedException { Map<Target, Collection<Target>> rawReverseDeps = getRawReverseDeps(targets); warnIfMissingTargets(targets, rawReverseDeps.keySet()); return processRawReverseDeps(rawReverseDeps); } - private Collection<Target> processRawReverseDeps(Map<Target, Collection<Target>> rawReverseDeps) { + private Collection<Target> processRawReverseDeps(Map<Target, Collection<Target>> rawReverseDeps) + throws InterruptedException { Set<Target> result = CompactHashSet.create(); CompactHashSet<Target> visited = CompactHashSet.createWithExpectedSize(totalSizeOfCollections(rawReverseDeps.values())); @@ -457,7 +461,7 @@ public class SkyQueryEnvironment extends AbstractBlazeQueryEnvironment<Target> } @Override - public Set<Target> getTransitiveClosure(Set<Target> targets) { + public Set<Target> getTransitiveClosure(Set<Target> targets) throws InterruptedException { Set<Target> visited = new HashSet<>(); Collection<Target> current = targets; while (!current.isEmpty()) { @@ -471,7 +475,7 @@ public class SkyQueryEnvironment extends AbstractBlazeQueryEnvironment<Target> // Implemented with a breadth-first search. @Override - public Set<Target> getNodesOnPath(Target from, Target to) { + public Set<Target> getNodesOnPath(Target from, Target to) throws InterruptedException { // Tree of nodes visited so far. Map<Target, Target> nodeToParent = new HashMap<>(); // Contains all nodes left to visit in a (LIFO) stack. @@ -595,7 +599,8 @@ public class SkyQueryEnvironment extends AbstractBlazeQueryEnvironment<Target> } @Override - public Target getTarget(Label label) throws TargetNotFoundException, QueryException { + public Target getTarget(Label label) + throws TargetNotFoundException, QueryException, InterruptedException { SkyKey packageKey = PackageValue.key(label.getPackageIdentifier()); if (!graph.exists(packageKey)) { throw new QueryException(packageKey + " does not exist in graph"); @@ -617,7 +622,8 @@ public class SkyQueryEnvironment extends AbstractBlazeQueryEnvironment<Target> } } - public Map<PackageIdentifier, Package> bulkGetPackages(Iterable<PackageIdentifier> pkgIds) { + public Map<PackageIdentifier, Package> bulkGetPackages(Iterable<PackageIdentifier> pkgIds) + throws InterruptedException { Set<SkyKey> pkgKeys = ImmutableSet.copyOf(PackageValue.keys(pkgIds)); ImmutableMap.Builder<PackageIdentifier, Package> pkgResults = ImmutableMap.builder(); Map<SkyKey, SkyValue> packages = graph.getSuccessfulValues(pkgKeys); @@ -631,7 +637,7 @@ public class SkyQueryEnvironment extends AbstractBlazeQueryEnvironment<Target> @Override public void buildTransitiveClosure(QueryExpression caller, Set<Target> targets, int maxDepth) - throws QueryException { + throws QueryException, InterruptedException { // Everything has already been loaded, so here we just check for errors so that we can // pre-emptively throw/report if needed. Iterable<SkyKey> transitiveTraversalKeys = makeTransitiveTraversalKeys(targets); @@ -694,7 +700,8 @@ public class SkyQueryEnvironment extends AbstractBlazeQueryEnvironment<Target> } }; - private Map<SkyKey, Target> makeTargetsFromSkyKeys(Iterable<SkyKey> keys) { + private Map<SkyKey, Target> makeTargetsFromSkyKeys(Iterable<SkyKey> keys) + throws InterruptedException { Multimap<SkyKey, SkyKey> packageKeyToTargetKeyMap = ArrayListMultimap.create(); for (SkyKey key : keys) { Label label = SKYKEY_TO_LABEL.apply(key); @@ -776,7 +783,8 @@ public class SkyQueryEnvironment extends AbstractBlazeQueryEnvironment<Target> * * <p>Note that there may not be nodes in the graph corresponding to the returned SkyKeys. */ - private Collection<SkyKey> getSkyKeysForFileFragments(Iterable<PathFragment> pathFragments) { + private Collection<SkyKey> getSkyKeysForFileFragments(Iterable<PathFragment> pathFragments) + throws InterruptedException { Set<SkyKey> result = new HashSet<>(); Multimap<PathFragment, PathFragment> currentToOriginal = ArrayListMultimap.create(); for (PathFragment pathFragment : pathFragments) { @@ -898,7 +906,8 @@ public class SkyQueryEnvironment extends AbstractBlazeQueryEnvironment<Target> .build(); } - private static class BlacklistSupplier implements Supplier<ImmutableSet<PathFragment>> { + private static class BlacklistSupplier + implements InterruptibleSupplier<ImmutableSet<PathFragment>> { private final WalkableGraph graph; BlacklistSupplier(WalkableGraph graph) { @@ -906,7 +915,7 @@ public class SkyQueryEnvironment extends AbstractBlazeQueryEnvironment<Target> } @Override - public ImmutableSet<PathFragment> get() { + public ImmutableSet<PathFragment> get() throws InterruptedException { return ((BlacklistedPackagePrefixesValue) graph.getValue(BlacklistedPackagePrefixesValue.key())) .getPatterns(); diff --git a/src/main/java/com/google/devtools/build/lib/query2/TargetEdgeErrorObserver.java b/src/main/java/com/google/devtools/build/lib/query2/TargetEdgeErrorObserver.java index 3e81571067..06c60ce5d2 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/TargetEdgeErrorObserver.java +++ b/src/main/java/com/google/devtools/build/lib/query2/TargetEdgeErrorObserver.java @@ -43,15 +43,16 @@ class TargetEdgeErrorObserver implements TargetEdgeObserver { private volatile boolean hasErrors = false; /** - * Reports an unresolved label error and records the fact that an error was - * encountered. + * Reports an unresolved label error and records the fact that an error was encountered. + * * @param target the target that referenced the unresolved label * @param label the label that could not be resolved * @param e the exception that was thrown when the label could not be resolved */ @ThreadSafety.ThreadSafe @Override - public void missingEdge(Target target, Label label, NoSuchThingException e) { + public void missingEdge(Target target, Label label, NoSuchThingException e) + throws InterruptedException { hasErrors = true; } diff --git a/src/main/java/com/google/devtools/build/lib/query2/engine/QueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/engine/QueryEnvironment.java index 88a2ea99f1..9653841b1b 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/engine/QueryEnvironment.java +++ b/src/main/java/com/google/devtools/build/lib/query2/engine/QueryEnvironment.java @@ -14,11 +14,9 @@ package com.google.devtools.build.lib.query2.engine; import com.google.common.collect.ImmutableList; - import java.util.Collection; import java.util.List; import java.util.Set; - import javax.annotation.Nonnull; /** @@ -143,7 +141,7 @@ public interface QueryEnvironment<T> { * pattern, in 'blaze build' syntax. */ void getTargetsMatchingPattern(QueryExpression owner, String pattern, Callback<T> callback) - throws QueryException; + throws QueryException, InterruptedException; /** Ensures the specified target exists. */ // NOTE(bazel-team): this method is left here as scaffolding from a previous refactoring. It may @@ -151,17 +149,16 @@ public interface QueryEnvironment<T> { T getOrCreate(T target); /** Returns the direct forward dependencies of the specified targets. */ - Collection<T> getFwdDeps(Iterable<T> targets); + Collection<T> getFwdDeps(Iterable<T> targets) throws InterruptedException; /** Returns the direct reverse dependencies of the specified targets. */ - Collection<T> getReverseDeps(Iterable<T> targets); + Collection<T> getReverseDeps(Iterable<T> targets) throws InterruptedException; /** - * Returns the forward transitive closure of all of the targets in - * "targets". Callers must ensure that {@link #buildTransitiveClosure} - * has been called for the relevant subgraph. + * Returns the forward transitive closure of all of the targets in "targets". Callers must ensure + * that {@link #buildTransitiveClosure} has been called for the relevant subgraph. */ - Set<T> getTransitiveClosure(Set<T> targets); + Set<T> getTransitiveClosure(Set<T> targets) throws InterruptedException; /** * Construct the dependency graph for a depth-bounded forward transitive closure @@ -176,10 +173,8 @@ public interface QueryEnvironment<T> { Set<T> targetNodes, int maxDepth) throws QueryException, InterruptedException; - /** - * Returns the set of nodes on some path from "from" to "to". - */ - Set<T> getNodesOnPath(T from, T to); + /** Returns the set of nodes on some path from "from" to "to". */ + Set<T> getNodesOnPath(T from, T to) throws InterruptedException; /** * Eval an expression {@code expr} and pass the results to the {@code callback}. @@ -201,12 +196,12 @@ public interface QueryEnvironment<T> { void reportBuildFileError(QueryExpression expression, String msg) throws QueryException; /** - * Returns the set of BUILD, and optionally sub-included and Skylark files that define the given set of - * targets. Each such file is itself represented as a target in the result. + * Returns the set of BUILD, and optionally sub-included and Skylark files that define the given + * set of targets. Each such file is itself represented as a target in the result. */ Set<T> getBuildFiles( QueryExpression caller, Set<T> nodes, boolean buildFiles, boolean subincludes, boolean loads) - throws QueryException; + throws QueryException, InterruptedException; /** * Returns an object that can be used to query information about targets. Implementations should @@ -307,8 +302,9 @@ public interface QueryEnvironment<T> { * * @throws IllegalArgumentException if target is not a rule (according to {@link #isRule}) */ - List<T> getLabelListAttr(QueryExpression caller, T target, String attrName, - String errorMsgPrefix) throws QueryException; + List<T> getLabelListAttr( + QueryExpression caller, T target, String attrName, String errorMsgPrefix) + throws QueryException, InterruptedException; /** * If the attribute of the given name on the given target is a string list, then this method @@ -347,7 +343,7 @@ public interface QueryEnvironment<T> { * Returns the set of package specifications the given target is visible from, represented as * {@link QueryVisibility}s. */ - Set<QueryVisibility<T>> getVisibility(T from) throws QueryException; + Set<QueryVisibility<T>> getVisibility(T from) throws QueryException, InterruptedException; } /** List of the default query functions. */ diff --git a/src/main/java/com/google/devtools/build/lib/query2/engine/TestsFunction.java b/src/main/java/com/google/devtools/build/lib/query2/engine/TestsFunction.java index 02ce8cc405..77dc6b4899 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/engine/TestsFunction.java +++ b/src/main/java/com/google/devtools/build/lib/query2/engine/TestsFunction.java @@ -19,7 +19,6 @@ import com.google.devtools.build.lib.query2.engine.QueryEnvironment.Argument; import com.google.devtools.build.lib.query2.engine.QueryEnvironment.ArgumentType; import com.google.devtools.build.lib.query2.engine.QueryEnvironment.QueryFunction; import com.google.devtools.build.lib.query2.engine.QueryEnvironment.Setting; - import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -161,12 +160,12 @@ class TestsFunction implements QueryFunction { } /** - * Computes and returns the set of test rules in a particular suite. Uses - * dynamic programming---a memoized version of {@link #computeTestsInSuite}. + * Computes and returns the set of test rules in a particular suite. Uses dynamic + * programming---a memoized version of {@link #computeTestsInSuite}. * * @precondition env.getAccessor().isTestSuite(testSuite) */ - private Set<T> getTestsInSuite(T testSuite) throws QueryException { + private Set<T> getTestsInSuite(T testSuite) throws QueryException, InterruptedException { Set<T> tests = testsInSuite.get(testSuite); if (tests == null) { tests = Sets.newHashSet(); @@ -177,14 +176,15 @@ class TestsFunction implements QueryFunction { } /** - * Populates 'result' with all the tests associated with the specified - * 'testSuite'. Throws an exception if any target is missing. + * Populates 'result' with all the tests associated with the specified 'testSuite'. Throws an + * exception if any target is missing. * - * <p>CAUTION! Keep this logic consistent with {@code TestsSuiteConfiguredTarget}! + * <p>CAUTION! Keep this logic consistent with {@code TestsSuiteConfiguredTarget}! * * @precondition env.getAccessor().isTestSuite(testSuite) */ - private void computeTestsInSuite(T testSuite, Set<T> result) throws QueryException { + private void computeTestsInSuite(T testSuite, Set<T> result) + throws QueryException, InterruptedException { List<T> testsAndSuites = new ArrayList<>(); // Note that testsAndSuites can contain input file targets; the test_suite rule does not // restrict the set of targets that can appear in tests or suites. @@ -231,7 +231,8 @@ class TestsFunction implements QueryFunction { * * @precondition env.getAccessor().isTestSuite(testSuite) */ - private List<T> getPrerequisites(T testSuite, String attrName) throws QueryException { + private List<T> getPrerequisites(T testSuite, String attrName) + throws QueryException, InterruptedException { return env.getAccessor().getLabelListAttr(expression, testSuite, attrName, "couldn't expand '" + attrName + "' attribute of test_suite " + env.getAccessor().getLabel(testSuite) + ": "); diff --git a/src/main/java/com/google/devtools/build/lib/query2/engine/VisibleFunction.java b/src/main/java/com/google/devtools/build/lib/query2/engine/VisibleFunction.java index 03a2ccf2bb..f69f134bc1 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/engine/VisibleFunction.java +++ b/src/main/java/com/google/devtools/build/lib/query2/engine/VisibleFunction.java @@ -18,7 +18,6 @@ import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.query2.engine.QueryEnvironment.Argument; import com.google.devtools.build.lib.query2.engine.QueryEnvironment.ArgumentType; import com.google.devtools.build.lib.query2.engine.QueryEnvironment.QueryFunction; - import java.util.List; import java.util.Set; @@ -71,11 +70,9 @@ public class VisibleFunction implements QueryFunction { }); } - /** - * Returns true if {@code target} is visible to all targets in {@code toSet}. - */ - private static <T> boolean visibleToAll( - QueryEnvironment<T> env, Set<T> toSet, T target) throws QueryException { + /** Returns true if {@code target} is visible to all targets in {@code toSet}. */ + private static <T> boolean visibleToAll(QueryEnvironment<T> env, Set<T> toSet, T target) + throws QueryException, InterruptedException { for (T to : toSet) { if (!visible(env, to, target)) { return false; @@ -84,10 +81,9 @@ public class VisibleFunction implements QueryFunction { return true; } - /** - * Returns true if the target {@code from} is visible to the target {@code to}. - */ - public static <T> boolean visible(QueryEnvironment<T> env, T to, T from) throws QueryException { + /** Returns true if the target {@code from} is visible to the target {@code to}. */ + public static <T> boolean visible(QueryEnvironment<T> env, T to, T from) + throws QueryException, InterruptedException { Set<QueryVisibility<T>> visiblePackages = env.getAccessor().getVisibility(from); for (QueryVisibility<T> spec : visiblePackages) { if (spec.contains(to)) { diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java index 8afd3849a6..5119a21119 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java +++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java @@ -653,17 +653,27 @@ public final class SkylarkRuleContext { return attributesCollection.getExecutableRunfilesMap().get(executable); } - @SkylarkCallable(name = "info_file", structField = true, documented = false, - doc = "Returns the file that is used to hold the non-volatile workspace status for the " - + "current build request.") - public Artifact getStableWorkspaceStatus() { + @SkylarkCallable( + name = "info_file", + structField = true, + documented = false, + doc = + "Returns the file that is used to hold the non-volatile workspace status for the " + + "current build request." + ) + public Artifact getStableWorkspaceStatus() throws InterruptedException { return ruleContext.getAnalysisEnvironment().getStableWorkspaceStatusArtifact(); } - @SkylarkCallable(name = "version_file", structField = true, documented = false, - doc = "Returns the file that is used to hold the volatile workspace status for the " - + "current build request.") - public Artifact getVolatileWorkspaceStatus() { + @SkylarkCallable( + name = "version_file", + structField = true, + documented = false, + doc = + "Returns the file that is used to hold the volatile workspace status for the " + + "current build request." + ) + public Artifact getVolatileWorkspaceStatus() throws InterruptedException { return ruleContext.getAnalysisEnvironment().getVolatileWorkspaceStatusArtifact(); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java index 97715cb689..42e911842b 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java @@ -68,14 +68,12 @@ import com.google.devtools.build.lib.rules.java.ProguardHelper.ProguardOutput; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.vfs.PathFragment; - import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; - import javax.annotation.Nullable; /** @@ -798,7 +796,8 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { } private static Artifact getStubDex( - RuleContext ruleContext, JavaSemantics javaSemantics, boolean split) { + RuleContext ruleContext, JavaSemantics javaSemantics, boolean split) + throws InterruptedException { String attribute = split ? "$incremental_split_stub_application" : "$incremental_stub_application"; @@ -868,8 +867,12 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { /** Generates an uncompressed _deploy.jar of all the runtime jars. */ public static Artifact createDeployJar( - RuleContext ruleContext, JavaSemantics javaSemantics, AndroidCommon common, - JavaTargetAttributes attributes, Artifact deployJar) { + RuleContext ruleContext, + JavaSemantics javaSemantics, + AndroidCommon common, + JavaTargetAttributes attributes, + Artifact deployJar) + throws InterruptedException { new DeployArchiveBuilder(javaSemantics, ruleContext) .setOutputJar(deployJar) .setAttributes(attributes) diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java index 278606df1a..4b9c95003d 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java @@ -38,7 +38,6 @@ import com.google.devtools.common.options.Converters; import com.google.devtools.common.options.EnumConverter; import com.google.devtools.common.options.Option; import com.google.devtools.common.options.OptionsParsingException; - import java.util.List; import java.util.Set; @@ -375,7 +374,7 @@ public class AndroidConfiguration extends BuildConfiguration.Fragment { public static class Loader implements ConfigurationFragmentFactory { @Override public Fragment create(ConfigurationEnvironment env, BuildOptions buildOptions) - throws InvalidConfigurationException { + throws InvalidConfigurationException, InterruptedException { AndroidConfiguration.Options androidOptions = buildOptions.get(AndroidConfiguration.Options.class); Label androidSdk = RedirectChaser.followRedirects(env, androidOptions.sdk, "android_sdk"); diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java b/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java index 4e582aa296..cbffcd8f0e 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java @@ -65,7 +65,8 @@ public final class NativeLibs { String nativeDepsFileName, Multimap<String, TransitiveInfoCollection> depsByArchitecture, Map<String, CcToolchainProvider> toolchainMap, - Map<String, BuildConfiguration> configurationMap) { + Map<String, BuildConfiguration> configurationMap) + throws InterruptedException { Map<String, Iterable<Artifact>> result = new LinkedHashMap<>(); for (Map.Entry<String, Collection<TransitiveInfoCollection>> entry : depsByArchitecture.asMap().entrySet()) { diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java index c8fe054b50..740f5c00bf 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java +++ b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java @@ -34,12 +34,10 @@ import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable; import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory; import com.google.devtools.build.lib.util.Preconditions; - import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Map; - import javax.annotation.Nullable; /** A configuration containing flags required for Apple platforms and tools. */ @@ -444,7 +442,7 @@ public class AppleConfiguration extends BuildConfiguration.Fragment { public static class Loader implements ConfigurationFragmentFactory { @Override public AppleConfiguration create(ConfigurationEnvironment env, BuildOptions buildOptions) - throws InvalidConfigurationException { + throws InvalidConfigurationException, InterruptedException { AppleCommandLineOptions appleOptions = buildOptions.get(AppleCommandLineOptions.class); XcodeVersionProperties xcodeVersionProperties = getXcodeVersionProperties(env, appleOptions); @@ -487,18 +485,19 @@ public class AppleConfiguration extends BuildConfiguration.Fragment { } /** - * Uses the {@link AppleCommandLineOptions#xcodeVersion} and - * {@link AppleCommandLineOptions#xcodeVersionConfig} command line options to determine and - * return the effective xcode version properties. Returns absent if no explicit xcode version - * is declared, and host system defaults should be used. + * Uses the {@link AppleCommandLineOptions#xcodeVersion} and {@link + * AppleCommandLineOptions#xcodeVersionConfig} command line options to determine and return the + * effective xcode version properties. Returns absent if no explicit xcode version is declared, + * and host system defaults should be used. * * @param env the current configuration environment * @param appleOptions the command line options * @throws InvalidConfigurationException if the options given (or configuration targets) were * malformed and thus the xcode version could not be determined */ - private XcodeVersionProperties getXcodeVersionProperties(ConfigurationEnvironment env, - AppleCommandLineOptions appleOptions) throws InvalidConfigurationException { + private static XcodeVersionProperties getXcodeVersionProperties( + ConfigurationEnvironment env, AppleCommandLineOptions appleOptions) + throws InvalidConfigurationException, InterruptedException { Optional<DottedVersion> xcodeVersionCommandLineFlag = Optional.fromNullable(appleOptions.xcodeVersion); Label xcodeVersionConfigLabel = appleOptions.xcodeVersionConfig; diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java index b4b28435eb..67a3d9e556 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java +++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java @@ -35,10 +35,8 @@ import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.Target; import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; import com.google.devtools.build.lib.syntax.Type; - import java.util.List; import java.util.Map; - import javax.annotation.Nullable; /** @@ -55,9 +53,9 @@ public class XcodeConfig implements RuleConfiguredTargetFactory { } /** - * Uses the {@link AppleCommandLineOptions#xcodeVersion} and - * {@link AppleCommandLineOptions#xcodeVersionConfig} command line options to determine and - * return the effective xcode version and its properties. + * Uses the {@link AppleCommandLineOptions#xcodeVersion} and {@link + * AppleCommandLineOptions#xcodeVersionConfig} command line options to determine and return the + * effective xcode version and its properties. * * @param env the current configuration environment * @param xcodeConfigLabel the label for the xcode_config target to parse @@ -68,9 +66,12 @@ public class XcodeConfig implements RuleConfiguredTargetFactory { * @throws InvalidConfigurationException if the options given (or configuration targets) were * malformed and thus the xcode version could not be determined */ - public static XcodeVersionProperties resolveXcodeVersion(ConfigurationEnvironment env, - Label xcodeConfigLabel, Optional<DottedVersion> xcodeVersionOverrideFlag, - String errorDescription) throws InvalidConfigurationException { + static XcodeVersionProperties resolveXcodeVersion( + ConfigurationEnvironment env, + Label xcodeConfigLabel, + Optional<DottedVersion> xcodeVersionOverrideFlag, + String errorDescription) + throws InvalidConfigurationException, InterruptedException { Rule xcodeConfigRule = getRuleForLabel(xcodeConfigLabel, "xcode_config", env, errorDescription); @@ -88,16 +89,18 @@ public class XcodeConfig implements RuleConfiguredTargetFactory { /** * Returns the {@link XcodeVersionRuleData} associated with the {@code xcode_version} target - * explicitly defined in the {@code --xcode_version_config} build flag and selected by the - * {@code --xcode_version} flag. If {@code --xcode_version} is unspecified, then this - * will return the default rule data as specified in the {@code --xcode_version_config} target. - * Returns null if either the {@code --xcode_version} did not match any {@code xcode_version} - * target, or if {@code --xcode_version} is unspecified and {@code --xcode_version_config} - * specified no default target. + * explicitly defined in the {@code --xcode_version_config} build flag and selected by the {@code + * --xcode_version} flag. If {@code --xcode_version} is unspecified, then this will return the + * default rule data as specified in the {@code --xcode_version_config} target. Returns null if + * either the {@code --xcode_version} did not match any {@code xcode_version} target, or if {@code + * --xcode_version} is unspecified and {@code --xcode_version_config} specified no default target. */ - @Nullable private static XcodeVersionRuleData resolveExplicitlyDefinedVersion( - ConfigurationEnvironment env, Rule xcodeConfigTarget, - Optional<DottedVersion> versionOverrideFlag) throws InvalidConfigurationException { + @Nullable + private static XcodeVersionRuleData resolveExplicitlyDefinedVersion( + ConfigurationEnvironment env, + Rule xcodeConfigTarget, + Optional<DottedVersion> versionOverrideFlag) + throws InvalidConfigurationException, InterruptedException { Map<String, XcodeVersionRuleData> aliasesToVersionMap = aliasesToVersionMap(env, xcodeConfigTarget); @@ -129,11 +132,13 @@ public class XcodeConfig implements RuleConfiguredTargetFactory { } /** - * Returns the default xcode version to use, if no {@code --xcode_version} command line flag - * was specified. + * Returns the default xcode version to use, if no {@code --xcode_version} command line flag was + * specified. */ - @Nullable private static XcodeVersionRuleData getDefaultVersion(ConfigurationEnvironment env, - Rule xcodeConfigTarget) throws InvalidConfigurationException { + @Nullable + private static XcodeVersionRuleData getDefaultVersion( + ConfigurationEnvironment env, Rule xcodeConfigTarget) + throws InvalidConfigurationException, InterruptedException { Label defaultVersionLabel = NonconfigurableAttributeMapper.of(xcodeConfigTarget) .get(XcodeConfigRule.DEFAULT_ATTR_NAME, BuildType.LABEL); if (defaultVersionLabel != null) { @@ -146,15 +151,15 @@ public class XcodeConfig implements RuleConfiguredTargetFactory { } /** - * Returns a map where keys are "names" of xcode versions as defined by the configuration - * target, and values are the rule data objects which contain information regarding that - * xcode version. + * Returns a map where keys are "names" of xcode versions as defined by the configuration target, + * and values are the rule data objects which contain information regarding that xcode version. * * @throws InvalidConfigurationException if there are duplicate aliases (if two xcode versions * were registered to the same alias) */ - private static Map<String, XcodeVersionRuleData> aliasesToVersionMap(ConfigurationEnvironment env, - Rule xcodeConfigTarget) throws InvalidConfigurationException { + private static Map<String, XcodeVersionRuleData> aliasesToVersionMap( + ConfigurationEnvironment env, Rule xcodeConfigTarget) + throws InvalidConfigurationException, InterruptedException { List<Label> xcodeVersionLabels = NonconfigurableAttributeMapper.of(xcodeConfigTarget) .get(XcodeConfigRule.VERSIONS_ATTR_NAME, BuildType.LABEL_LIST); ImmutableList.Builder<XcodeVersionRuleData> xcodeVersionRuleListBuilder = @@ -206,12 +211,13 @@ public class XcodeConfig implements RuleConfiguredTargetFactory { } /** - * If the given label (following redirects) is a target for a rule of type {@code type}, - * then returns the {@link Rule} representing that target. Otherwise, throws a - * {@link InvalidConfigurationException}. + * If the given label (following redirects) is a target for a rule of type {@code type}, then + * returns the {@link Rule} representing that target. Otherwise, throws a {@link + * InvalidConfigurationException}. */ - private static Rule getRuleForLabel(Label label, String type, ConfigurationEnvironment env, - String description) throws InvalidConfigurationException { + private static Rule getRuleForLabel( + Label label, String type, ConfigurationEnvironment env, String description) + throws InvalidConfigurationException, InterruptedException { label = RedirectChaser.followRedirects(env, label, description); if (label == null) { diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java index 1856b04a19..d49415f6a4 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java @@ -396,7 +396,8 @@ public abstract class CcBinary implements RuleConfiguredTargetFactory { boolean fake, Artifact binary, LinkStaticness linkStaticness, - List<String> linkopts) { + List<String> linkopts) + throws InterruptedException { CppLinkActionBuilder builder = new CppLinkActionBuilder(context, binary) .setCrosstoolInputs(CppHelper.getToolchain(context).getLink()) diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcIncLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcIncLibrary.java index 8e2a5aa402..ead1c79d25 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcIncLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcIncLibrary.java @@ -24,13 +24,11 @@ import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.Runfiles; import com.google.devtools.build.lib.analysis.RunfilesProvider; import com.google.devtools.build.lib.analysis.actions.CreateIncSymlinkAction; -import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException; import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration; import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.vfs.PathFragment; - import java.util.ArrayList; import java.util.Arrays; @@ -58,7 +56,8 @@ public abstract class CcIncLibrary implements RuleConfiguredTargetFactory { } @Override - public ConfiguredTarget create(final RuleContext ruleContext) throws RuleErrorException { + public ConfiguredTarget create(final RuleContext ruleContext) + throws RuleErrorException, InterruptedException { FeatureConfiguration featureConfiguration = CcCommon.configureFeatures(ruleContext); PathFragment packageFragment = ruleContext.getPackageDirectory(); diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java index 73fd7095b1..3dd3f96515 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java @@ -92,7 +92,8 @@ public abstract class CcLibrary implements RuleConfiguredTargetFactory { } @Override - public ConfiguredTarget create(RuleContext context) throws RuleErrorException { + public ConfiguredTarget create(RuleContext context) + throws RuleErrorException, InterruptedException { RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(context); LinkTargetType linkType = getStaticLinkType(context); boolean linkStatic = context.attributes().get("linkstatic", Type.BOOLEAN); @@ -113,7 +114,7 @@ public abstract class CcLibrary implements RuleConfiguredTargetFactory { boolean linkStatic, boolean collectLinkstamp, boolean addDynamicRuntimeInputArtifactsToRunfiles) - throws RuleErrorException { + throws RuleErrorException, InterruptedException { FeatureConfiguration featureConfiguration = CcCommon.configureFeatures(ruleContext); final CcCommon common = new CcCommon(ruleContext); PrecompiledFiles precompiledFiles = new PrecompiledFiles(ruleContext); diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java index 43d43dcc95..2b78db3c0b 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java @@ -868,7 +868,7 @@ public final class CcLibraryHelper { * * @throws RuleErrorException */ - public Info build() throws RuleErrorException { + public Info build() throws RuleErrorException, InterruptedException { // Fail early if there is no lipo context collector on the rule - otherwise we end up failing // in lipo optimization. Preconditions.checkState( diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java index f56ffdd2a4..f24432db98 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java @@ -62,7 +62,8 @@ public class CcToolchain implements RuleConfiguredTargetFactory { new PathFragment("include/stdc-predef.h"); @Override - public ConfiguredTarget create(RuleContext ruleContext) throws RuleErrorException { + public ConfiguredTarget create(RuleContext ruleContext) + throws RuleErrorException, InterruptedException { TransitiveInfoCollection lipoContextCollector = ruleContext.getPrerequisite(":lipo_context_collector", Mode.DONT_CHECK); if (lipoContextCollector != null diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java index 91ff304ee0..3769518150 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java @@ -993,8 +993,10 @@ public class CppCompileAction extends AbstractAction @Override public Iterable<Artifact> resolveInputsFromCache( - ArtifactResolver artifactResolver, PackageRootResolver resolver, - Collection<PathFragment> inputPaths) throws PackageRootResolutionException { + ArtifactResolver artifactResolver, + PackageRootResolver resolver, + Collection<PathFragment> inputPaths) + throws PackageRootResolutionException, InterruptedException { // Note that this method may trigger a violation of the desirable invariant that getInputs() // is a superset of getMandatoryInputs(). See bug about an "action not in canonical form" // error message and the integration test test_crosstool_change_and_failure(). diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java index e5097f08d4..c59480fb96 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java @@ -39,7 +39,6 @@ import com.google.devtools.build.lib.packages.Target; import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig; - import javax.annotation.Nullable; /** @@ -69,7 +68,7 @@ public class CppConfigurationLoader implements ConfigurationFragmentFactory { @Override public CppConfiguration create(ConfigurationEnvironment env, BuildOptions options) - throws InvalidConfigurationException { + throws InvalidConfigurationException, InterruptedException { CppConfigurationParameters params = createParameters(env, options); if (params == null) { return null; @@ -113,7 +112,8 @@ public class CppConfigurationLoader implements ConfigurationFragmentFactory { @Nullable protected CppConfigurationParameters createParameters( - ConfigurationEnvironment env, BuildOptions options) throws InvalidConfigurationException { + ConfigurationEnvironment env, BuildOptions options) + throws InvalidConfigurationException, InterruptedException { BlazeDirectories directories = env.getBlazeDirectories(); if (directories == null) { return null; diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java index ab0eb4163b..5268ff4fbd 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java @@ -425,7 +425,7 @@ public class CppLinkActionBuilder { } /** Builds the Action as configured and returns it. */ - public CppLinkAction build() { + public CppLinkAction build() throws InterruptedException { Preconditions.checkState( (libraryIdentifier == null) == (linkType == LinkTargetType.EXECUTABLE)); if (interfaceOutput != null && (fake || linkType != LinkTargetType.DYNAMIC_LIBRARY)) { @@ -1026,7 +1026,7 @@ public class CppLinkActionBuilder { * #addLibraries}, and {@link #addLinkstamps}. */ public CppLinkActionBuilder addLinkParams( - CcLinkParams linkParams, RuleErrorConsumer errorListener) { + CcLinkParams linkParams, RuleErrorConsumer errorListener) throws InterruptedException { addLinkopts(linkParams.flattenedLinkopts()); addLibraries(linkParams.getLibraries()); ExtraLinkTimeLibraries extraLinkTimeLibraries = linkParams.getExtraLinkTimeLibraries(); diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java index ba76f3e56d..8e0120efe0 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java @@ -823,8 +823,9 @@ public final class CppModel { * * @throws RuleErrorException */ - public CcLinkingOutputs createCcLinkActions(CcCompilationOutputs ccOutputs, - Iterable<Artifact> nonCodeLinkerInputs) throws RuleErrorException { + public CcLinkingOutputs createCcLinkActions( + CcCompilationOutputs ccOutputs, Iterable<Artifact> nonCodeLinkerInputs) + throws RuleErrorException, InterruptedException { // For now only handle static links. Note that the dynamic library link below ignores linkType. // TODO(bazel-team): Either support non-static links or move this check to setLinkType(). Preconditions.checkState( diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java index 0a15404699..d8fbe78555 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java @@ -41,14 +41,12 @@ import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.Cross import com.google.protobuf.TextFormat; import com.google.protobuf.TextFormat.ParseException; import com.google.protobuf.UninitializedMessageException; - import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; - import javax.annotation.Nullable; /** @@ -171,7 +169,7 @@ public class CrosstoolConfigurationLoader { } private static CrosstoolProto getCrosstoolProtofromBuildFile( - ConfigurationEnvironment env, Label crosstoolTop) { + ConfigurationEnvironment env, Label crosstoolTop) throws InterruptedException { Target target; try { target = env.getTarget(crosstoolTop); @@ -202,7 +200,7 @@ public class CrosstoolConfigurationLoader { private static CrosstoolProto getCrosstoolProtoFromCrosstoolFile( ConfigurationEnvironment env, Label crosstoolTop) - throws IOException, InvalidConfigurationException { + throws IOException, InvalidConfigurationException, InterruptedException { final Path path; try { Package containingPackage = env.getTarget(crosstoolTop.getLocalTargetLabel("BUILD")) @@ -234,7 +232,7 @@ public class CrosstoolConfigurationLoader { private static CrosstoolFile findCrosstoolConfiguration( ConfigurationEnvironment env, Label crosstoolTop) - throws IOException, InvalidConfigurationException { + throws IOException, InvalidConfigurationException, InterruptedException { CrosstoolProto crosstoolProto = getCrosstoolProtofromBuildFile(env, crosstoolTop); if (crosstoolProto == null) { @@ -267,12 +265,11 @@ public class CrosstoolConfigurationLoader { } } - /** - * Reads a crosstool file. - */ + /** Reads a crosstool file. */ @Nullable public static CrosstoolConfigurationLoader.CrosstoolFile readCrosstool( - ConfigurationEnvironment env, Label crosstoolTop) throws InvalidConfigurationException { + ConfigurationEnvironment env, Label crosstoolTop) + throws InvalidConfigurationException, InterruptedException { crosstoolTop = RedirectChaser.followRedirects(env, crosstoolTop, "crosstool_top"); if (crosstoolTop == null) { return null; @@ -400,9 +397,11 @@ public class CrosstoolConfigurationLoader { } public static CrosstoolConfig.CrosstoolRelease getCrosstoolReleaseProto( - ConfigurationEnvironment env, BuildOptions options, - Label crosstoolTop, Function<String, String> cpuTransformer) - throws InvalidConfigurationException { + ConfigurationEnvironment env, + BuildOptions options, + Label crosstoolTop, + Function<String, String> cpuTransformer) + throws InvalidConfigurationException, InterruptedException { CrosstoolConfigurationLoader.CrosstoolFile file = readCrosstool(env, crosstoolTop); // Make sure that we have the requested toolchain in the result. Throw an exception if not. diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibrary.java index 52b2a0822a..5daeb2deaa 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibrary.java @@ -32,10 +32,8 @@ import com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink; * context. */ public interface ExtraLinkTimeLibrary { - /** - * Build the LibraryToLink inputs to pass to the C++ linker. - */ - NestedSet<LibraryToLink> buildLibraries(RuleContext context); + /** Build the LibraryToLink inputs to pass to the C++ linker. */ + NestedSet<LibraryToLink> buildLibraries(RuleContext context) throws InterruptedException; /** * Get a new Builder for this ExtraLinkTimeLibrary class. This acts diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java index 747ea822e0..db3fbf1815 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java @@ -38,7 +38,6 @@ import com.google.devtools.build.lib.vfs.RootedPath; import com.google.devtools.build.lib.vfs.ZipFileSystem; import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.LipoMode; import com.google.devtools.build.skyframe.SkyFunction; - import java.io.IOException; import java.util.Collection; import java.util.zip.ZipException; @@ -233,11 +232,14 @@ public class FdoSupport { return fdoRoot; } - /** - * Creates an initialized {@link FdoSupport} instance. - */ - static FdoSupport create(SkyFunction.Environment env, PathFragment fdoInstrument, - Path fdoProfile, LipoMode lipoMode, Path execRoot) throws IOException, FdoException { + /** Creates an initialized {@link FdoSupport} instance. */ + static FdoSupport create( + SkyFunction.Environment env, + PathFragment fdoInstrument, + Path fdoProfile, + LipoMode lipoMode, + Path execRoot) + throws IOException, FdoException, InterruptedException { FdoMode fdoMode; if (fdoProfile != null && isAutoFdo(fdoProfile.getBaseName())) { fdoMode = FdoMode.AUTO_FDO; diff --git a/src/main/java/com/google/devtools/build/lib/rules/extra/ExtraAction.java b/src/main/java/com/google/devtools/build/lib/rules/extra/ExtraAction.java index 88c967ae72..ef3e620296 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/extra/ExtraAction.java +++ b/src/main/java/com/google/devtools/build/lib/rules/extra/ExtraAction.java @@ -39,12 +39,10 @@ import com.google.devtools.build.lib.collect.nestedset.Order; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.PathFragment; - import java.io.IOException; import java.util.Collection; import java.util.Map; import java.util.Set; - import javax.annotation.Nullable; import javax.annotation.concurrent.GuardedBy; @@ -165,9 +163,11 @@ public final class ExtraAction extends SpawnAction { @Nullable @Override - public Iterable<Artifact> resolveInputsFromCache(ArtifactResolver artifactResolver, - PackageRootResolver resolver, Collection<PathFragment> inputPaths) - throws PackageRootResolutionException { + public Iterable<Artifact> resolveInputsFromCache( + ArtifactResolver artifactResolver, + PackageRootResolver resolver, + Collection<PathFragment> inputPaths) + throws PackageRootResolutionException, InterruptedException { // We update the inputs directly from the shadowed action. Set<PathFragment> extraActionPathFragments = ImmutableSet.copyOf(Artifact.asPathFragments(extraActionInputs)); diff --git a/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQuery.java b/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQuery.java index c5ebb6f8b3..2a336da0bf 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQuery.java +++ b/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQuery.java @@ -44,7 +44,6 @@ import com.google.devtools.build.lib.packages.BuildType; 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.RuleClass.ConfiguredTargetFactory.RuleErrorException; import com.google.devtools.build.lib.packages.Target; import com.google.devtools.build.lib.pkgcache.FilteringPolicies; import com.google.devtools.build.lib.pkgcache.FilteringPolicy; @@ -78,7 +77,6 @@ import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.ValueOrException; import com.google.devtools.common.options.OptionsParser; import com.google.devtools.common.options.OptionsParsingException; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -89,7 +87,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; - import javax.annotation.Nullable; /** @@ -168,7 +165,7 @@ public class GenQuery implements RuleConfiguredTargetFactory { // The transitive closure of these targets is an upper estimate on the labels // the query will touch - private Set<Target> getScope(RuleContext context) { + private static Set<Target> getScope(RuleContext context) throws InterruptedException { List<Label> scopeLabels = context.attributes().get("scope", BuildType.LABEL_LIST); Set<Target> scope = Sets.newHashSetWithExpectedSize(scopeLabels.size()); for (Label scopePart : scopeLabels) { @@ -199,8 +196,9 @@ public class GenQuery implements RuleConfiguredTargetFactory { } @Nullable - private Pair<ImmutableMap<PackageIdentifier, Package>, ImmutableMap<Label, Target>> - constructPackageMap(SkyFunction.Environment env, Collection<Target> scope) { + private static Pair<ImmutableMap<PackageIdentifier, Package>, ImmutableMap<Label, Target>> + constructPackageMap(SkyFunction.Environment env, Collection<Target> scope) + throws InterruptedException { // It is not necessary for correctness to construct intermediate NestedSets; we could iterate // over individual targets in scope immediately. However, creating a composite NestedSet first // saves us from iterating over the same sub-NestedSets multiple times. @@ -374,10 +372,9 @@ public class GenQuery implements RuleConfiguredTargetFactory { } @Override - public Map<String, ResolvedTargets<Target>> preloadTargetPatterns(EventHandler eventHandler, - Collection<String> patterns, - boolean keepGoing) - throws TargetParsingException { + public Map<String, ResolvedTargets<Target>> preloadTargetPatterns( + EventHandler eventHandler, Collection<String> patterns, boolean keepGoing) + throws TargetParsingException, InterruptedException { Preconditions.checkArgument(!keepGoing); boolean ok = true; Map<String, ResolvedTargets<Target>> preloadedPatterns = diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/DeployArchiveBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/java/DeployArchiveBuilder.java index 3e2b13ae58..43b567699d 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/DeployArchiveBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/DeployArchiveBuilder.java @@ -25,11 +25,9 @@ import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; import com.google.devtools.build.lib.analysis.actions.SpawnAction; import com.google.devtools.build.lib.collect.IterablesChain; import com.google.devtools.build.lib.util.Preconditions; - import java.util.HashSet; import java.util.List; import java.util.Set; - import javax.annotation.Nullable; /** @@ -193,10 +191,8 @@ public class DeployArchiveBuilder { return args; } - /** - * Builds the action as configured. - */ - public void build() { + /** Builds the action as configured. */ + public void build() throws InterruptedException { ImmutableList<Artifact> classpathResources = attributes.getClassPathResources(); Set<String> classPathResourceNames = new HashSet<>(); for (Artifact artifact : classpathResources) { diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java index a87e5b4ba5..934437c877 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java @@ -51,14 +51,12 @@ import com.google.devtools.build.lib.util.Pair; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.PathFragment; - import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; - import javax.annotation.Nullable; /** @@ -176,8 +174,13 @@ public class JavaCommon { * Creates an action to aggregate all metadata artifacts into a single * <target_name>_instrumented.jar file. */ - public static void createInstrumentedJarAction(RuleContext ruleContext, JavaSemantics semantics, - List<Artifact> metadataArtifacts, Artifact instrumentedJar, String mainClass) { + public static void createInstrumentedJarAction( + RuleContext ruleContext, + JavaSemantics semantics, + List<Artifact> metadataArtifacts, + Artifact instrumentedJar, + String mainClass) + throws InterruptedException { // In Jacoco's setup, metadata artifacts are real jars. new DeployArchiveBuilder(semantics, ruleContext) .setOutputJar(instrumentedJar) diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfigurationLoader.java index c6eda487fb..6ae2f22b81 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfigurationLoader.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfigurationLoader.java @@ -41,7 +41,7 @@ public class JavaConfigurationLoader implements ConfigurationFragmentFactory { @Override public JavaConfiguration create(ConfigurationEnvironment env, BuildOptions buildOptions) - throws InvalidConfigurationException { + throws InvalidConfigurationException, InterruptedException { CppConfiguration cppConfiguration = env.getFragment(buildOptions, CppConfiguration.class); if (cppConfiguration == null) { return null; diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java index 44247890e0..fa665c44aa 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java @@ -265,10 +265,14 @@ public interface JavaSemantics { * * @return new main class */ - String addCoverageSupport(JavaCompilationHelper helper, + String addCoverageSupport( + JavaCompilationHelper helper, JavaTargetAttributes.Builder attributes, - Artifact executable, Artifact instrumentationMetadata, - JavaCompilationArtifacts.Builder javaArtifactsBuilder, String mainClass); + Artifact executable, + Artifact instrumentationMetadata, + JavaCompilationArtifacts.Builder javaArtifactsBuilder, + String mainClass) + throws InterruptedException; /** * Return the JVM flags to be used in a Java binary. diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JvmConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/java/JvmConfigurationLoader.java index c127140e1e..904f8637de 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JvmConfigurationLoader.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JvmConfigurationLoader.java @@ -34,9 +34,7 @@ import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.Target; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.vfs.PathFragment; - import java.util.List; - import javax.annotation.Nullable; /** @@ -60,7 +58,7 @@ public final class JvmConfigurationLoader implements ConfigurationFragmentFactor @Override public Jvm create(ConfigurationEnvironment env, BuildOptions buildOptions) - throws InvalidConfigurationException { + throws InvalidConfigurationException, InterruptedException { JavaOptions javaOptions = buildOptions.get(JavaOptions.class); if (javaOptions.disableJvm) { // TODO(bazel-team): Instead of returning null here, add another method to the interface. @@ -92,8 +90,8 @@ public final class JvmConfigurationLoader implements ConfigurationFragmentFactor } @Nullable - private Jvm createDefault(ConfigurationEnvironment lookup, String javaHome, String cpu) - throws InvalidConfigurationException, LabelSyntaxException { + private static Jvm createDefault(ConfigurationEnvironment lookup, String javaHome, String cpu) + throws InvalidConfigurationException, LabelSyntaxException, InterruptedException { try { Label label = Label.parseAbsolute(javaHome); label = RedirectChaser.followRedirects(lookup, label, "jdk"); diff --git a/src/main/java/com/google/devtools/build/lib/rules/nativedeps/NativeDepsHelper.java b/src/main/java/com/google/devtools/build/lib/rules/nativedeps/NativeDepsHelper.java index 8b9f9fe878..b9896e90ca 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/nativedeps/NativeDepsHelper.java +++ b/src/main/java/com/google/devtools/build/lib/rules/nativedeps/NativeDepsHelper.java @@ -87,13 +87,16 @@ public abstract class NativeDepsHelper { * * @param ruleContext the rule context to determine the native deps library * @param linkParams the {@link CcLinkParams} for the rule, collected with linkstatic = 1 and - * linkshared = 1 + * linkshared = 1 * @return the native deps library runfiles. If the transitive deps closure of the rule contains - * no native code libraries, its fields are null. + * no native code libraries, its fields are null. */ - public static Artifact maybeCreateAndroidNativeDepsAction(final RuleContext ruleContext, - CcLinkParams linkParams, final BuildConfiguration configuration, - CcToolchainProvider toolchain) { + public static Artifact maybeCreateAndroidNativeDepsAction( + final RuleContext ruleContext, + CcLinkParams linkParams, + final BuildConfiguration configuration, + CcToolchainProvider toolchain) + throws InterruptedException { if (linkParams.getLibraries().isEmpty()) { return null; } @@ -128,7 +131,8 @@ public abstract class NativeDepsHelper { Artifact nativeDeps, String libraryIdentifier, Root bindirIfShared, - boolean useDynamicRuntime) { + boolean useDynamicRuntime) + throws InterruptedException { Preconditions.checkState( ruleContext.isLegalFragment(CppConfiguration.class), "%s does not have access to CppConfiguration", diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfigurationLoader.java index cb8503d428..a23a234d52 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfigurationLoader.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfigurationLoader.java @@ -30,7 +30,7 @@ import com.google.devtools.build.lib.analysis.config.InvalidConfigurationExcepti public class ObjcConfigurationLoader implements ConfigurationFragmentFactory { @Override public ObjcConfiguration create(ConfigurationEnvironment env, BuildOptions buildOptions) - throws InvalidConfigurationException { + throws InvalidConfigurationException, InterruptedException { Options options = buildOptions.get(BuildConfiguration.Options.class); ObjcCommandLineOptions objcOptions = buildOptions.get(ObjcCommandLineOptions.class); diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java index 39e6d2ce13..c870acc999 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java @@ -312,7 +312,7 @@ public final class ReleaseBundlingSupport { return this; } - private void registerEmbedLabelPlistAction() { + private void registerEmbedLabelPlistAction() throws InterruptedException { Artifact buildInfo = Iterables.getOnlyElement( ruleContext.getBuildInfo(ObjcBuildInfoFactory.KEY)); String generatedVersionPlistPath = getGeneratedVersionPlist().getShellEscapedExecPathString(); diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfigurationLoader.java index 2599cb139d..ff49b2d9b3 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfigurationLoader.java +++ b/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfigurationLoader.java @@ -26,7 +26,6 @@ import com.google.devtools.build.lib.rules.cpp.CppConfiguration; import com.google.devtools.build.lib.rules.cpp.CppOptions; import com.google.devtools.build.lib.rules.cpp.CrosstoolConfigurationLoader; import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig; - import javax.annotation.Nullable; /** @@ -47,7 +46,7 @@ public class PythonConfigurationLoader implements ConfigurationFragmentFactory { @Nullable private CrosstoolConfig.CToolchain getToolchain( ConfigurationEnvironment env, BuildOptions buildOptions, Label crosstoolTop) - throws InvalidConfigurationException { + throws InvalidConfigurationException, InterruptedException { CrosstoolConfigurationLoader.CrosstoolFile file = CrosstoolConfigurationLoader.readCrosstool(env, crosstoolTop); if (file == null) { @@ -59,7 +58,7 @@ public class PythonConfigurationLoader implements ConfigurationFragmentFactory { @Override public PythonConfiguration create(ConfigurationEnvironment env, BuildOptions buildOptions) - throws InvalidConfigurationException { + throws InvalidConfigurationException, InterruptedException { PythonOptions pythonOptions = buildOptions.get(PythonOptions.class); CppConfiguration cppConfiguration = env.getFragment(buildOptions, CppConfiguration.class); if (cppConfiguration == null) { diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PythonSemantics.java b/src/main/java/com/google/devtools/build/lib/rules/python/PythonSemantics.java index d45a8093e9..08fcb1b465 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/python/PythonSemantics.java +++ b/src/main/java/com/google/devtools/build/lib/rules/python/PythonSemantics.java @@ -41,10 +41,9 @@ public interface PythonSemantics { */ void collectRunfilesForBinary(RuleContext ruleContext, Runfiles.Builder builder, PyCommon common); - /** - * Extends the default runfiles of {@code py_binary} rules with custom elements. - */ - void collectDefaultRunfilesForBinary(RuleContext ruleContext, Runfiles.Builder builder); + /** Extends the default runfiles of {@code py_binary} rules with custom elements. */ + void collectDefaultRunfilesForBinary(RuleContext ruleContext, Runfiles.Builder builder) + throws InterruptedException; /** * Returns the coverage instrumentation specification to be used in Python rules. diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/LocalRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/LocalRepositoryFunction.java index 258cb960a0..b5f9071456 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/repository/LocalRepositoryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/rules/repository/LocalRepositoryFunction.java @@ -21,10 +21,8 @@ import com.google.devtools.build.lib.skyframe.FileValue; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.skyframe.SkyFunction.Environment; -import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyFunctionException.Transience; import com.google.devtools.build.skyframe.SkyValue; - import java.io.IOException; /** @@ -40,7 +38,7 @@ public class LocalRepositoryFunction extends RepositoryFunction { @Override public SkyValue fetch( Rule rule, Path outputDirectory, BlazeDirectories directories, Environment env) - throws SkyFunctionException { + throws InterruptedException, RepositoryFunctionException { PathFragment pathFragment = RepositoryFunction.getTargetPath(rule, directories.getWorkspace()); try { outputDirectory.createSymbolicLink(pathFragment); diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/NewLocalRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/NewLocalRepositoryFunction.java index eb77b57211..db79483635 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/repository/NewLocalRepositoryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/rules/repository/NewLocalRepositoryFunction.java @@ -27,7 +27,6 @@ import com.google.devtools.build.skyframe.SkyFunction.Environment; import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.io.IOException; /** @@ -43,7 +42,7 @@ public class NewLocalRepositoryFunction extends RepositoryFunction { @Override public SkyValue fetch( Rule rule, Path outputDirectory, BlazeDirectories directories, Environment env) - throws SkyFunctionException { + throws SkyFunctionException, InterruptedException { NewRepositoryBuildFileHandler buildFileHandler = new NewRepositoryBuildFileHandler(directories.getWorkspace()); diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/NewRepositoryBuildFileHandler.java b/src/main/java/com/google/devtools/build/lib/rules/repository/NewRepositoryBuildFileHandler.java index 456d80842f..18654e1da1 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/repository/NewRepositoryBuildFileHandler.java +++ b/src/main/java/com/google/devtools/build/lib/rules/repository/NewRepositoryBuildFileHandler.java @@ -32,7 +32,6 @@ import com.google.devtools.build.lib.vfs.RootedPath; import com.google.devtools.build.skyframe.SkyFunction.Environment; import com.google.devtools.build.skyframe.SkyFunctionException.Transience; import com.google.devtools.build.skyframe.SkyKey; - import java.io.IOException; /** @@ -59,7 +58,7 @@ public class NewRepositoryBuildFileHandler { * retrieved, written, or symlinked. */ public boolean prepareBuildFile(Rule rule, Environment env) - throws RepositoryFunctionException { + throws RepositoryFunctionException, InterruptedException { AggregatingAttributeMapper mapper = AggregatingAttributeMapper.of(rule); boolean hasBuildFile = mapper.isAttributeValueExplicitlySpecified("build_file"); @@ -115,7 +114,7 @@ public class NewRepositoryBuildFileHandler { } private FileValue getBuildFileValue(Rule rule, Environment env) - throws RepositoryFunctionException { + throws RepositoryFunctionException, InterruptedException { AggregatingAttributeMapper mapper = AggregatingAttributeMapper.of(rule); String buildFileAttribute = mapper.get("build_file", Type.STRING); RootedPath rootedBuild; @@ -200,4 +199,4 @@ public class NewRepositoryBuildFileHandler { Path buildFilePath = outputDirectory.getRelative("BUILD"); RepositoryFunction.createSymbolicLink(buildFilePath, buildFileValue.realRootedPath().asPath()); } -}
\ No newline at end of file +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java index 98e4ad9e71..cb01f3120c 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java @@ -132,21 +132,22 @@ public abstract class RepositoryFunction { * * <p>The {@code env} argument can be used to fetch Skyframe dependencies the repository * implementation needs on the following conditions: + * * <ul> - * <li>When a Skyframe value is missing, fetching must be restarted, thus, in order to avoid - * doing duplicate work, it's better to first request the Skyframe dependencies you need and - * only then start doing anything costly. - * <li>The output directory must be populated from within this method (and not from within - * another SkyFunction). This is because if it was populated in another SkyFunction, the - * repository function would be restarted <b>after</b> that SkyFunction has been run, and - * it would wipe the output directory clean. + * <li>When a Skyframe value is missing, fetching must be restarted, thus, in order to avoid doing + * duplicate work, it's better to first request the Skyframe dependencies you need and only + * then start doing anything costly. + * <li>The output directory must be populated from within this method (and not from within another + * SkyFunction). This is because if it was populated in another SkyFunction, the repository + * function would be restarted <b>after</b> that SkyFunction has been run, and it would wipe + * the output directory clean. * </ul> */ @ThreadSafe @Nullable public abstract SkyValue fetch( Rule rule, Path outputDirectory, BlazeDirectories directories, Environment env) - throws SkyFunctionException, InterruptedException; + throws SkyFunctionException, InterruptedException; /** * Whether fetching is done using local operations only. @@ -164,7 +165,7 @@ public abstract class RepositoryFunction { * to keep it working somehow) */ protected byte[] getRuleSpecificMarkerData(Rule rule, Environment env) - throws RepositoryFunctionException { + throws RepositoryFunctionException, InterruptedException { return new byte[] {}; } @@ -265,7 +266,7 @@ public abstract class RepositoryFunction { */ @Nullable public static Rule getRule(String repository, Environment env) - throws RepositoryFunctionException { + throws RepositoryFunctionException, InterruptedException { SkyKey packageLookupKey = PackageLookupValue.key(Label.EXTERNAL_PACKAGE_IDENTIFIER); PackageLookupValue packageLookupValue = (PackageLookupValue) env.getValue(packageLookupKey); @@ -298,9 +299,8 @@ public abstract class RepositoryFunction { } @Nullable - public static Rule getRule( - String ruleName, @Nullable String ruleClassName, Environment env) - throws RepositoryFunctionException { + public static Rule getRule(String ruleName, @Nullable String ruleClassName, Environment env) + throws RepositoryFunctionException, InterruptedException { try { return getRule(RepositoryName.create("@" + ruleName), ruleClassName, env); } catch (LabelSyntaxException e) { @@ -310,15 +310,15 @@ public abstract class RepositoryFunction { } /** - * Uses a remote repository name to fetch the corresponding Rule describing how to get it. - * This should be called from {@link SkyFunction#compute} functions, which should return null if - * this returns null. If {@code ruleClassName} is set, the rule found must have a matching rule - * class name. + * Uses a remote repository name to fetch the corresponding Rule describing how to get it. This + * should be called from {@link SkyFunction#compute} functions, which should return null if this + * returns null. If {@code ruleClassName} is set, the rule found must have a matching rule class + * name. */ @Nullable public static Rule getRule( RepositoryName repositoryName, @Nullable String ruleClassName, Environment env) - throws RepositoryFunctionException { + throws RepositoryFunctionException, InterruptedException { Rule rule = getRule(repositoryName.strippedName(), env); Preconditions.checkState( rule == null || ruleClassName == null || rule.getRuleClass().equals(ruleClassName), @@ -327,12 +327,12 @@ public abstract class RepositoryFunction { } /** - * Adds the repository's directory to the graph and, if it's a symlink, resolves it to an - * actual directory. + * Adds the repository's directory to the graph and, if it's a symlink, resolves it to an actual + * directory. */ @Nullable - public static FileValue getRepositoryDirectory(Path repositoryDirectory, Environment env) - throws RepositoryFunctionException { + protected static FileValue getRepositoryDirectory(Path repositoryDirectory, Environment env) + throws RepositoryFunctionException, InterruptedException { SkyKey outputDirectoryKey = FileValue.key(RootedPath.toRootedPath( repositoryDirectory, PathFragment.EMPTY_FRAGMENT)); FileValue value; @@ -354,21 +354,19 @@ public abstract class RepositoryFunction { } /** - * For files that are under $OUTPUT_BASE/external, add a dependency on the corresponding rule - * so that if the WORKSPACE file changes, the File/DirectoryStateValue will be re-evaluated. + * For files that are under $OUTPUT_BASE/external, add a dependency on the corresponding rule so + * that if the WORKSPACE file changes, the File/DirectoryStateValue will be re-evaluated. * - * Note that: - * - We don't add a dependency on the parent directory at the package root boundary, so - * the only transitive dependencies from files inside the package roots to external files - * are through symlinks. So the upwards transitive closure of external files is small. - * - The only way other than external repositories for external source files to get into the - * skyframe graph in the first place is through symlinks outside the package roots, which we - * neither want to encourage nor optimize for since it is not common. So the set of external - * files is small. + * <p>Note that: - We don't add a dependency on the parent directory at the package root boundary, + * so the only transitive dependencies from files inside the package roots to external files are + * through symlinks. So the upwards transitive closure of external files is small. - The only way + * other than external repositories for external source files to get into the skyframe graph in + * the first place is through symlinks outside the package roots, which we neither want to + * encourage nor optimize for since it is not common. So the set of external files is small. */ public static void addExternalFilesDependencies( RootedPath rootedPath, BlazeDirectories directories, Environment env) - throws IOException { + throws IOException, InterruptedException { Path externalRepoDir = getExternalRepositoryDirectory(directories); PathFragment repositoryPath = rootedPath.asPath().relativeTo(externalRepoDir); if (repositoryPath.segmentCount() == 0) { diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java index 7ba1e2daaf..3f0dc5ceae 100644 --- a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java +++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java @@ -34,7 +34,6 @@ import com.google.devtools.common.options.Option; import com.google.devtools.common.options.OptionsBase; import com.google.devtools.common.options.OptionsParser; import com.google.devtools.common.options.OptionsProvider; - import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.List; @@ -188,6 +187,8 @@ public class InfoCommand implements BlazeCommand { return e.getExitCode(); } catch (IOException e) { return ExitCode.LOCAL_ENVIRONMENTAL_ERROR; + } catch (InterruptedException e) { + return ExitCode.INTERRUPTED; } return ExitCode.SUCCESS; } diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java index 4677b4a509..52c9991369 100644 --- a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java +++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java @@ -94,10 +94,12 @@ public abstract class InfoItem { /** * Returns the value of the info key. The return value is directly printed to stdout. + * * @param env TODO(lpino): */ - public abstract byte[] get(Supplier<BuildConfiguration> configurationSupplier, - CommandEnvironment env) throws AbruptExitException; + public abstract byte[] get( + Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env) + throws AbruptExitException, InterruptedException; private static byte[] print(Object value) { if (value instanceof byte[]) { @@ -626,4 +628,4 @@ public abstract class InfoItem { return print(description); } } -}
\ No newline at end of file +} diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java index 8ec6f0ee02..19fb401ec0 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java @@ -196,11 +196,12 @@ public class ActionExecutionFunction implements SkyFunction, CompletionReceiver * the action cache's view of this action contains additional inputs, it will request metadata for * them, so we consider those inputs as dependencies of this action as well. Returns null if some * dependencies were missing and this ActionExecutionFunction needs to restart. + * * @throws ActionExecutionFunctionException */ @Nullable private AllInputs collectInputs(Action action, Environment env) - throws ActionExecutionFunctionException { + throws ActionExecutionFunctionException, InterruptedException { Iterable<Artifact> allKnownInputs = Iterables.concat( action.getInputs(), action.getRunfilesSupplier().getArtifacts()); if (action.inputsKnown()) { @@ -264,7 +265,7 @@ public class ActionExecutionFunction implements SkyFunction, CompletionReceiver @Override public Map<PathFragment, Root> findPackageRootsForFiles(Iterable<PathFragment> execPaths) - throws PackageRootResolutionException { + throws PackageRootResolutionException, InterruptedException { Preconditions.checkState(keysRequested.isEmpty(), "resolver should only be called once: %s %s", keysRequested, execPaths); // Create SkyKeys list based on execPaths. @@ -316,7 +317,7 @@ public class ActionExecutionFunction implements SkyFunction, CompletionReceiver @Override @Nullable public Map<PathFragment, Root> findPackageRoots(Iterable<PathFragment> execPaths) - throws PackageRootResolutionException { + throws PackageRootResolutionException, InterruptedException { // call sites for this implementation of PackageRootResolver shouldn't be passing in // directories. return findPackageRootsForFiles(execPaths); @@ -454,8 +455,10 @@ public class ActionExecutionFunction implements SkyFunction, CompletionReceiver } private static void addDiscoveredInputs( - Map<Artifact, FileArtifactValue> inputData, Iterable<Artifact> discoveredInputs, - Environment env) { + Map<Artifact, FileArtifactValue> inputData, + Iterable<Artifact> discoveredInputs, + Environment env) + throws InterruptedException { Set<SkyKey> keys = new HashSet<>(); for (Artifact artifact : discoveredInputs) { if (!inputData.containsKey(artifact)) { @@ -479,8 +482,8 @@ public class ActionExecutionFunction implements SkyFunction, CompletionReceiver } } - private void establishSkyframeDependencies(Environment env, Action action) - throws ActionExecutionException { + private static void establishSkyframeDependencies(Environment env, Action action) + throws ActionExecutionException, InterruptedException { // Before we may safely establish Skyframe dependencies, we must build all action inputs by // requesting their ArtifactValues. // This is very important to do, because the establishSkyframeDependencies method may request @@ -619,12 +622,12 @@ public class ActionExecutionFunction implements SkyFunction, CompletionReceiver } /** - * Declares skyframe dependencies for any {@code action}'s inputs that are not already in - * {@code knownInputs}. Returns the result of {@code env.getValues(...)} for these inputs, - * which should contain {@link Artifact} keys and {@link FileArtifactValue} or null values. + * Declares skyframe dependencies for any {@code action}'s inputs that are not already in {@code + * knownInputs}. Returns the result of {@code env.getValues(...)} for these inputs, which should + * contain {@link Artifact} keys and {@link FileArtifactValue} or null values. */ - private static Map<SkyKey, SkyValue> declareAdditionalDependencies(Environment env, - Action action, Set<Artifact> knownInputs) { + private static Map<SkyKey, SkyValue> declareAdditionalDependencies( + Environment env, Action action, Set<Artifact> knownInputs) throws InterruptedException { Preconditions.checkState(action.discoversInputs(), action); Iterable<Artifact> newArtifacts = Iterables.filter(action.getInputs(), Predicates.not(Predicates.in(knownInputs))); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionTemplateExpansionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ActionTemplateExpansionFunction.java index 59572f1b9a..6a18db78dd 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionTemplateExpansionFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/ActionTemplateExpansionFunction.java @@ -38,7 +38,7 @@ public class ActionTemplateExpansionFunction implements SkyFunction { @Override public SkyValue compute(SkyKey skyKey, Environment env) - throws ActionTemplateExpansionFunctionException { + throws ActionTemplateExpansionFunctionException, InterruptedException { ActionTemplateExpansionKey key = (ActionTemplateExpansionKey) skyKey.argument(); SpawnActionTemplate actionTemplate = key.getActionTemplate(); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java index f7007b7d59..cecc089d5b 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java @@ -54,7 +54,8 @@ class ArtifactFunction implements SkyFunction { } @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws ArtifactFunctionException { + public SkyValue compute(SkyKey skyKey, Environment env) + throws ArtifactFunctionException, InterruptedException { OwnedArtifact ownedArtifact = (OwnedArtifact) skyKey.argument(); Artifact artifact = ownedArtifact.getArtifact(); if (artifact.isSourceArtifact()) { @@ -116,9 +117,9 @@ class ArtifactFunction implements SkyFunction { } } - private TreeArtifactValue createTreeArtifactValueFromActionTemplate( + private static TreeArtifactValue createTreeArtifactValueFromActionTemplate( SpawnActionTemplate actionTemplate, Artifact treeArtifact, Environment env) - throws ArtifactFunctionException { + throws ArtifactFunctionException, InterruptedException { // Request the list of expanded actions from the ActionTemplate. ActionTemplateExpansionValue expansionValue = (ActionTemplateExpansionValue) env.getValue( ActionTemplateExpansionValue.key(actionTemplate)); @@ -167,7 +168,7 @@ class ArtifactFunction implements SkyFunction { } private FileArtifactValue createSourceValue(Artifact artifact, boolean mandatory, Environment env) - throws MissingInputFileException { + throws MissingInputFileException, InterruptedException { SkyKey fileSkyKey = FileValue.key(RootedPath.toRootedPath(artifact.getRoot().getPath(), artifact.getPath())); FileValue fileValue; @@ -253,7 +254,8 @@ class ArtifactFunction implements SkyFunction { Artifact artifact, ActionAnalysisMetadata action, FileArtifactValue value, - SkyFunction.Environment env) { + SkyFunction.Environment env) + throws InterruptedException { // This artifact aggregates other artifacts. Keep track of them so callers can find them. ImmutableList.Builder<Pair<Artifact, FileArtifactValue>> inputs = ImmutableList.builder(); for (Map.Entry<SkyKey, SkyValue> entry : @@ -286,8 +288,8 @@ class ArtifactFunction implements SkyFunction { return Label.print(((OwnedArtifact) skyKey.argument()).getArtifact().getOwner()); } - private ActionAnalysisMetadata extractActionFromArtifact( - Artifact artifact, SkyFunction.Environment env) { + private static ActionAnalysisMetadata extractActionFromArtifact( + Artifact artifact, SkyFunction.Environment env) throws InterruptedException { ArtifactOwner artifactOwner = artifact.getArtifactOwner(); Preconditions.checkState(artifactOwner instanceof ActionLookupKey, "", artifact, artifactOwner); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java index c1f8c335ec..d94be28632 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java @@ -57,7 +57,6 @@ import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import javax.annotation.Nullable; /** @@ -93,9 +92,9 @@ public final class AspectFunction implements SkyFunction { * @return {@code null} if dependencies cannot be satisfied. */ @Nullable - public static SkylarkAspect loadSkylarkAspect( + static SkylarkAspect loadSkylarkAspect( Environment env, Label extensionLabel, String skylarkValueName) - throws AspectCreationException { + throws AspectCreationException, InterruptedException { SkyKey importFileKey = SkylarkImportLookupValue.key(extensionLabel, false); try { SkylarkImportLookupValue skylarkImportLookupValue = @@ -275,8 +274,13 @@ public final class AspectFunction implements SkyFunction { } } - private SkyValue createAliasAspect(Environment env, Target originalTarget, Label aliasLabel, - Aspect aspect, AspectKey originalKey) { + private static SkyValue createAliasAspect( + Environment env, + Target originalTarget, + Label aliasLabel, + Aspect aspect, + AspectKey originalKey) + throws InterruptedException { SkyKey depKey = AspectValue.key(aliasLabel, originalKey.getAspectConfiguration(), originalKey.getBaseConfiguration(), diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationFunction.java index a25c3ac201..3f18f8502b 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationFunction.java @@ -29,7 +29,6 @@ import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; import com.google.devtools.build.skyframe.ValueOrException; - import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -52,7 +51,8 @@ public class BuildConfigurationFunction implements SkyFunction { } @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException { + public SkyValue compute(SkyKey skyKey, Environment env) + throws InterruptedException, BuildConfigurationFunctionException { BuildConfigurationValue.Key key = (BuildConfigurationValue.Key) skyKey.argument(); Set<Fragment> fragments; try { @@ -83,7 +83,7 @@ public class BuildConfigurationFunction implements SkyFunction { } private Set<Fragment> getConfigurationFragments(BuildConfigurationValue.Key key, Environment env) - throws InvalidConfigurationException { + throws InvalidConfigurationException, InterruptedException { // Get SkyKeys for the fragments we need to load. Set<SkyKey> fragmentKeys = new LinkedHashSet<>(); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BuildInfoCollectionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/BuildInfoCollectionFunction.java index 5edaf985e4..7361c1f564 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/BuildInfoCollectionFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/BuildInfoCollectionFunction.java @@ -26,7 +26,6 @@ import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.util.Map; /** @@ -46,7 +45,7 @@ public class BuildInfoCollectionFunction implements SkyFunction { } @Override - public SkyValue compute(SkyKey skyKey, Environment env) { + public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { final BuildInfoKeyAndConfig keyAndConfig = (BuildInfoKeyAndConfig) skyKey.argument(); WorkspaceStatusValue infoArtifactValue = (WorkspaceStatusValue) env.getValue(WorkspaceStatusValue.SKY_KEY); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/CollectPackagesUnderDirectoryFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/CollectPackagesUnderDirectoryFunction.java index 21d4eb2336..cef2a10779 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/CollectPackagesUnderDirectoryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/CollectPackagesUnderDirectoryFunction.java @@ -25,9 +25,7 @@ import com.google.devtools.build.lib.vfs.RootedPath; import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.util.Map; - import javax.annotation.Nullable; /** @@ -44,7 +42,7 @@ public class CollectPackagesUnderDirectoryFunction implements SkyFunction { } @Override - public SkyValue compute(SkyKey skyKey, Environment env) { + public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { return new MyTraversalFunction().visitDirectory((RecursivePkgKey) skyKey.argument(), env); } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/CompletionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/CompletionFunction.java index db9ab97534..6a3e6e45b7 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/CompletionFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/CompletionFunction.java @@ -46,15 +46,11 @@ import javax.annotation.Nullable; public final class CompletionFunction<TValue extends SkyValue, TResult extends SkyValue> implements SkyFunction { - /** - * A strategy for completing the build. - */ - public interface Completor<TValue, TResult extends SkyValue> { + /** A strategy for completing the build. */ + interface Completor<TValue, TResult extends SkyValue> { - /** - * Obtains an analysis result value from environment. - */ - TValue getValueFromSkyKey(SkyKey skyKey, Environment env); + /** Obtains an analysis result value from environment. */ + TValue getValueFromSkyKey(SkyKey skyKey, Environment env) throws InterruptedException; /** * Returns the options which determine the artifacts to build for the top-level targets. @@ -104,7 +100,8 @@ public final class CompletionFunction<TValue extends SkyValue, TResult extends S private static class TargetCompletor implements Completor<ConfiguredTargetValue, TargetCompletionValue> { @Override - public ConfiguredTargetValue getValueFromSkyKey(SkyKey skyKey, Environment env) { + public ConfiguredTargetValue getValueFromSkyKey(SkyKey skyKey, Environment env) + throws InterruptedException { TargetCompletionKey tcKey = (TargetCompletionKey) skyKey.argument(); LabelAndConfiguration lac = tcKey.labelAndConfiguration(); return (ConfiguredTargetValue) @@ -162,7 +159,8 @@ public final class CompletionFunction<TValue extends SkyValue, TResult extends S private static class AspectCompletor implements Completor<AspectValue, AspectCompletionValue> { @Override - public AspectValue getValueFromSkyKey(SkyKey skyKey, Environment env) { + public AspectValue getValueFromSkyKey(SkyKey skyKey, Environment env) + throws InterruptedException { AspectCompletionKey acKey = (AspectCompletionKey) skyKey.argument(); AspectKey aspectKey = acKey.aspectKey(); return (AspectValue) env.getValue(AspectValue.key(aspectKey)); @@ -237,7 +235,8 @@ public final class CompletionFunction<TValue extends SkyValue, TResult extends S @Nullable @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws CompletionFunctionException { + public SkyValue compute(SkyKey skyKey, Environment env) + throws CompletionFunctionException, InterruptedException { TValue value = completor.getValueFromSkyKey(skyKey, env); TopLevelArtifactContext topLevelContext = completor.getTopLevelArtifactContext(skyKey); if (env.valuesMissing()) { diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ConfigurationCollectionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ConfigurationCollectionFunction.java index d50e2a65d1..e73b2b4cd5 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/ConfigurationCollectionFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConfigurationCollectionFunction.java @@ -33,10 +33,8 @@ import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.util.ArrayList; import java.util.List; - import javax.annotation.Nullable; /** @@ -75,10 +73,12 @@ public class ConfigurationCollectionFunction implements SkyFunction { } /** Create the build configurations with the given options. */ - private BuildConfigurationCollection getConfigurations(Environment env, - PackageProviderForConfigurations loadedPackageProvider, BuildOptions buildOptions, + private BuildConfigurationCollection getConfigurations( + Environment env, + PackageProviderForConfigurations loadedPackageProvider, + BuildOptions buildOptions, ImmutableSet<String> multiCpu) - throws InvalidConfigurationException { + throws InvalidConfigurationException, InterruptedException { // We cache all the related configurations for this target configuration in a cache that is // dropped at the end of this method call. We instead rely on the cache for entire collections // for caching the target and related configurations, and on a dedicated host configuration @@ -115,11 +115,10 @@ public class ConfigurationCollectionFunction implements SkyFunction { return new BuildConfigurationCollection(targetConfigurations, hostConfiguration); } - /** - * Returns the host configuration, or null on missing Skyframe deps. - */ - private BuildConfiguration getHostConfiguration(Environment env, - BuildConfiguration targetConfiguration) throws InvalidConfigurationException { + /** Returns the host configuration, or null on missing Skyframe deps. */ + private static BuildConfiguration getHostConfiguration( + Environment env, BuildConfiguration targetConfiguration) + throws InvalidConfigurationException, InterruptedException { if (targetConfiguration.useDynamicConfigurations()) { BuildOptions hostOptions = HostTransition.INSTANCE.apply(targetConfiguration.getOptions()); SkyKey hostConfigKey = @@ -149,7 +148,9 @@ public class ConfigurationCollectionFunction implements SkyFunction { Cache<String, BuildConfiguration> cache, EventHandler originalEventListener, PackageProviderForConfigurations loadedPackageProvider, - BuildOptions buildOptions, String cpuOverride) throws InvalidConfigurationException { + BuildOptions buildOptions, + String cpuOverride) + throws InvalidConfigurationException, InterruptedException { ErrorSensingEventHandler eventHandler = new ErrorSensingEventHandler(originalEventListener); if (cpuOverride != null) { // TODO(bazel-team): Options classes should be immutable. This is a bit of a hack. diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ConfigurationFragmentFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ConfigurationFragmentFunction.java index f2a12e7b34..62bee585b6 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/ConfigurationFragmentFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConfigurationFragmentFunction.java @@ -43,7 +43,6 @@ import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.io.IOException; import java.util.HashSet; import java.util.LinkedHashSet; @@ -100,8 +99,11 @@ public final class ConfigurationFragmentFunction implements SkyFunction { * those returned from {@link BuildOptions#getAllLabels()}, and the implicit ones are those that * are returned from {@link Fragment#getImplicitLabels}. */ - private void sanityCheck(Fragment fragment, BuildOptions buildOptions, - PackageProviderForConfigurations packageProvider) throws InvalidConfigurationException { + private static void sanityCheck( + Fragment fragment, + BuildOptions buildOptions, + PackageProviderForConfigurations packageProvider) + throws InvalidConfigurationException, InterruptedException { if (fragment == null) { return; } @@ -134,8 +136,9 @@ public final class ConfigurationFragmentFunction implements SkyFunction { } } - private void collectAllTransitiveLabels(PackageProviderForConfigurations packageProvider, - Set<Label> reachableLabels, Label from) throws NoSuchThingException { + private static void collectAllTransitiveLabels( + PackageProviderForConfigurations packageProvider, Set<Label> reachableLabels, Label from) + throws NoSuchThingException, InterruptedException { if (!reachableLabels.add(from)) { return; } @@ -189,12 +192,13 @@ public final class ConfigurationFragmentFunction implements SkyFunction { } @Override - public Target getTarget(Label label) throws NoSuchPackageException, NoSuchTargetException { + public Target getTarget(Label label) + throws NoSuchPackageException, NoSuchTargetException, InterruptedException { return packageProvider.getTarget(label); } @Override - public Path getPath(Package pkg, String fileName) { + public Path getPath(Package pkg, String fileName) throws InterruptedException { Path result = pkg.getPackageDirectory().getRelative(fileName); try { packageProvider.addDependency(pkg, fileName); @@ -205,13 +209,13 @@ public final class ConfigurationFragmentFunction implements SkyFunction { } @Override - public <T extends Fragment> T getFragment(BuildOptions buildOptions, Class<T> fragmentType) - throws InvalidConfigurationException { + public <T extends Fragment> T getFragment(BuildOptions buildOptions, Class<T> fragmentType) + throws InvalidConfigurationException, InterruptedException { return packageProvider.getFragment(buildOptions, fragmentType); } @Override - public BlazeDirectories getBlazeDirectories() { + public BlazeDirectories getBlazeDirectories() throws InterruptedException { return packageProvider.getDirectories(); } } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java index 9a82ef4d98..0bd188a4f0 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java @@ -75,7 +75,6 @@ import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; import com.google.devtools.build.skyframe.ValueOrException; import com.google.devtools.build.skyframe.ValueOrException2; - import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashMap; @@ -84,7 +83,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Set; - import javax.annotation.Nullable; /** @@ -416,15 +414,18 @@ final class ConfiguredTargetFunction implements SkyFunction { * transitive closure. * * <p>This method is heavily performance-optimized. Because it, in aggregate, reads over every - * edge in the configured target graph, small inefficiencies can have observable impact on - * build analysis time. Keep this in mind when making modifications and performance-test any - * changes you make. + * edge in the configured target graph, small inefficiencies can have observable impact on build + * analysis time. Keep this in mind when making modifications and performance-test any changes you + * make. */ @Nullable - static OrderedSetMultimap<Attribute, Dependency> trimConfigurations(Environment env, - TargetAndConfiguration ctgValue, OrderedSetMultimap<Attribute, Dependency> originalDeps, - BuildConfiguration hostConfiguration, RuleClassProvider ruleClassProvider) - throws DependencyEvaluationException { + static OrderedSetMultimap<Attribute, Dependency> trimConfigurations( + Environment env, + TargetAndConfiguration ctgValue, + OrderedSetMultimap<Attribute, Dependency> originalDeps, + BuildConfiguration hostConfiguration, + RuleClassProvider ruleClassProvider) + throws DependencyEvaluationException, InterruptedException { // Maps each Skyframe-evaluated BuildConfiguration to the dependencies that need that // configuration. For cases where Skyframe isn't needed to get the configuration (e.g. when @@ -684,7 +685,7 @@ final class ConfiguredTargetFunction implements SkyFunction { Map<SkyKey, ConfiguredTarget> configuredTargetMap, Iterable<Dependency> deps, NestedSetBuilder<Package> transitivePackages) - throws AspectCreationException { + throws AspectCreationException, InterruptedException { OrderedSetMultimap<SkyKey, ConfiguredAspect> result = OrderedSetMultimap.create(); Set<SkyKey> aspectKeys = new HashSet<>(); for (Dependency dep : deps) { @@ -766,18 +767,21 @@ final class ConfiguredTargetFunction implements SkyFunction { } /** - * Returns the set of {@link ConfigMatchingProvider}s that key the configurable attributes - * used by this rule. + * Returns the set of {@link ConfigMatchingProvider}s that key the configurable attributes used by + * this rule. * - * <p>>If the configured targets supplying those providers aren't yet resolved by the - * dependency resolver, returns null. + * <p>>If the configured targets supplying those providers aren't yet resolved by the dependency + * resolver, returns null. */ @Nullable - static ImmutableMap<Label, ConfigMatchingProvider> getConfigConditions(Target target, - Environment env, SkyframeDependencyResolver resolver, TargetAndConfiguration ctgValue, + static ImmutableMap<Label, ConfigMatchingProvider> getConfigConditions( + Target target, + Environment env, + SkyframeDependencyResolver resolver, + TargetAndConfiguration ctgValue, NestedSetBuilder<Package> transitivePackages, NestedSetBuilder<Label> transitiveLoadingRootCauses) - throws DependencyEvaluationException { + throws DependencyEvaluationException, InterruptedException { if (!(target instanceof Rule)) { return NO_CONFIG_CONDITIONS; } @@ -847,15 +851,19 @@ final class ConfiguredTargetFunction implements SkyFunction { return ImmutableMap.copyOf(configConditions); } - /*** - * Resolves the targets referenced in depValueNames and returns their ConfiguredTarget instances. + /** + * * Resolves the targets referenced in depValueNames and returns their ConfiguredTarget + * instances. * * <p>Returns null if not all instances are available yet. */ @Nullable private static Map<SkyKey, ConfiguredTarget> resolveConfiguredTargetDependencies( - Environment env, Collection<Dependency> deps, NestedSetBuilder<Package> transitivePackages, - NestedSetBuilder<Label> transitiveLoadingRootCauses) throws DependencyEvaluationException { + Environment env, + Collection<Dependency> deps, + NestedSetBuilder<Package> transitivePackages, + NestedSetBuilder<Label> transitiveLoadingRootCauses) + throws DependencyEvaluationException, InterruptedException { boolean missedValues = env.valuesMissing(); boolean failed = false; Iterable<SkyKey> depKeys = Iterables.transform(deps, TO_KEYS); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupFunction.java index 09debbff4a..68c9ff8353 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupFunction.java @@ -18,7 +18,6 @@ import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import javax.annotation.Nullable; /** @@ -27,7 +26,7 @@ import javax.annotation.Nullable; public class ContainingPackageLookupFunction implements SkyFunction { @Override - public SkyValue compute(SkyKey skyKey, Environment env) { + public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { PackageIdentifier dir = (PackageIdentifier) skyKey.argument(); PackageLookupValue pkgLookupValue = (PackageLookupValue) env.getValue(PackageLookupValue.key(dir)); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/CoverageReportFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/CoverageReportFunction.java index 53d7a86102..70de5cc212 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/CoverageReportFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/CoverageReportFunction.java @@ -30,7 +30,7 @@ public class CoverageReportFunction implements SkyFunction { CoverageReportFunction() {} @Override - public SkyValue compute(SkyKey skyKey, Environment env) { + public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { Preconditions.checkState( CoverageReportValue.SKY_KEY.equals(skyKey), String.format( "Expected %s for SkyKey but got %s instead", CoverageReportValue.SKY_KEY, skyKey)); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingFunction.java index 3c1401c1d5..97ee8b78bc 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingFunction.java @@ -18,7 +18,6 @@ import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import javax.annotation.Nullable; /** @@ -28,7 +27,7 @@ public final class DirectoryListingFunction implements SkyFunction { @Override public SkyValue compute(SkyKey skyKey, Environment env) - throws DirectoryListingFunctionException { + throws DirectoryListingFunctionException, InterruptedException { RootedPath dirRootedPath = (RootedPath) skyKey.argument(); FileValue dirFileValue = (FileValue) env.getValue(FileValue.key(dirRootedPath)); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingStateFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingStateFunction.java index 0bb5249fcb..aa1fe760e2 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingStateFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingStateFunction.java @@ -18,7 +18,6 @@ import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.io.IOException; /** @@ -37,7 +36,7 @@ public class DirectoryListingStateFunction implements SkyFunction { @Override public SkyValue compute(SkyKey skyKey, Environment env) - throws DirectoryListingStateFunctionException { + throws DirectoryListingStateFunctionException, InterruptedException { RootedPath dirRootedPath = (RootedPath) skyKey.argument(); try { 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 index 92888d2427..96a65b59c3 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java @@ -36,7 +36,6 @@ 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; - import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -56,7 +55,7 @@ public final class EnvironmentBackedRecursivePackageProvider implements Recursiv @Override public Package getPackage(EventHandler eventHandler, PackageIdentifier packageName) - throws NoSuchPackageException, MissingDepException { + throws NoSuchPackageException, MissingDepException, InterruptedException { SkyKey pkgKey = PackageValue.key(packageName); PackageValue pkgValue = (PackageValue) env.getValueOrThrow(pkgKey, NoSuchPackageException.class); @@ -93,7 +92,7 @@ public final class EnvironmentBackedRecursivePackageProvider implements Recursiv @Override public boolean isPackage(EventHandler eventHandler, PackageIdentifier packageId) - throws MissingDepException { + throws MissingDepException, InterruptedException { SkyKey packageLookupKey = PackageLookupValue.key(packageId); try { PackageLookupValue packageLookupValue = @@ -111,9 +110,10 @@ public final class EnvironmentBackedRecursivePackageProvider implements Recursiv @Override public Iterable<PathFragment> getPackagesUnderDirectory( - RepositoryName repository, PathFragment directory, + RepositoryName repository, + PathFragment directory, ImmutableSet<PathFragment> excludedSubdirectories) - throws MissingDepException { + throws MissingDepException, InterruptedException { PathPackageLocator packageLocator = PrecomputedValue.PATH_PACKAGE_LOCATOR.get(env); if (packageLocator == null) { throw new MissingDepException(); @@ -156,8 +156,9 @@ public final class EnvironmentBackedRecursivePackageProvider implements Recursiv } @Override - public Target getTarget(EventHandler eventHandler, Label label) throws NoSuchPackageException, - NoSuchTargetException, MissingDepException { + public Target getTarget(EventHandler eventHandler, Label label) + throws NoSuchPackageException, NoSuchTargetException, MissingDepException, + InterruptedException { return getPackage(eventHandler, label.getPackageIdentifier()).getTarget(label.getName()); } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java b/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java index 792cc5fa13..b1b6259e90 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java @@ -23,7 +23,6 @@ import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.RootedPath; import com.google.devtools.build.skyframe.SkyFunction; - import java.io.IOException; import java.util.concurrent.atomic.AtomicReference; @@ -82,12 +81,12 @@ public class ExternalFilesHelper { * external repository). Such files are theoretically mutable, but certain Blaze flags may tell * Blaze to assume these files are immutable. * - * Note that {@link ExternalFilesHelper#maybeHandleExternalFile} is only used for - * {@link FileStateValue} and {@link DirectoryStateValue}, and also note that output files do - * not normally have corresponding {@link FileValue} instances (and thus also - * {@link FileStateValue} instances) in the Skyframe graph ({@link ArtifactFunction} only uses - * {@link FileValue}s for source files). But {@link FileStateValue}s for output files can still - * make their way into the Skyframe graph if e.g. a source file is a symlink to an output file. + * <p>Note that {@link ExternalFilesHelper#maybeHandleExternalFile} is only used for {@link + * FileStateValue} and {@link DirectoryListingStateValue}, and also note that output files do + * not normally have corresponding {@link FileValue} instances (and thus also {@link + * FileStateValue} instances) in the Skyframe graph ({@link ArtifactFunction} only uses {@link + * FileValue}s for source files). But {@link FileStateValue}s for output files can still make + * their way into the Skyframe graph if e.g. a source file is a symlink to an output file. */ // TODO(nharmata): Consider an alternative design where we have an OutputFileDiffAwareness. This // could work but would first require that we clean up all RootedPath usage. @@ -157,8 +156,8 @@ public class ExternalFilesHelper { * ERROR_OUT, it will throw an error instead. */ @ThreadSafe - public void maybeHandleExternalFile(RootedPath rootedPath, SkyFunction.Environment env) - throws IOException { + void maybeHandleExternalFile(RootedPath rootedPath, SkyFunction.Environment env) + throws IOException, InterruptedException { FileType fileType = getAndNoteFileType(rootedPath); if (fileType == FileType.INTERNAL) { return; diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ExternalPackageFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ExternalPackageFunction.java index 2e5cf268c1..8a7bdd92d9 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/ExternalPackageFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/ExternalPackageFunction.java @@ -18,7 +18,6 @@ import com.google.devtools.build.lib.vfs.RootedPath; import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import javax.annotation.Nullable; /** @@ -31,7 +30,7 @@ public class ExternalPackageFunction implements SkyFunction { @Nullable @Override - public SkyValue compute(SkyKey skyKey, Environment env) { + public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { RootedPath workspacePath = (RootedPath) skyKey.argument(); SkyKey key = WorkspaceFileValue.key(workspacePath); WorkspaceFileValue value = (WorkspaceFileValue) env.getValue(key); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/FileFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/FileFunction.java index 6eb962114c..8404f53aa7 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/FileFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/FileFunction.java @@ -28,12 +28,10 @@ import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyFunctionException.Transience; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.io.IOException; import java.util.ArrayList; import java.util.TreeSet; import java.util.concurrent.atomic.AtomicReference; - import javax.annotation.Nullable; /** @@ -51,7 +49,8 @@ public class FileFunction implements SkyFunction { } @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws FileFunctionException { + public SkyValue compute(SkyKey skyKey, Environment env) + throws FileFunctionException, InterruptedException { RootedPath rootedPath = (RootedPath) skyKey.argument(); RootedPath realRootedPath = null; FileStateValue realFileStateValue = null; @@ -132,9 +131,9 @@ public class FileFunction implements SkyFunction { * {@code null} if there was a missing dep. */ @Nullable - private Pair<RootedPath, FileStateValue> resolveFromAncestors( + private static Pair<RootedPath, FileStateValue> resolveFromAncestors( RootedPath rootedPath, Environment env) - throws FileFunctionException, FileOutsidePackageRootsException { + throws FileFunctionException, FileOutsidePackageRootsException, InterruptedException { PathFragment relativePath = rootedPath.getRelativePath(); RootedPath realRootedPath = rootedPath; FileValue parentFileValue = null; @@ -180,14 +179,17 @@ public class FileFunction implements SkyFunction { } /** - * Returns the symlink target and file state of {@code rootedPath}'s symlink to - * {@code symlinkTarget}, accounting for ancestor symlinks, or {@code null} if there was a - * missing dep. + * Returns the symlink target and file state of {@code rootedPath}'s symlink to {@code + * symlinkTarget}, accounting for ancestor symlinks, or {@code null} if there was a missing dep. */ @Nullable - private Pair<RootedPath, FileStateValue> getSymlinkTargetRootedPath(RootedPath rootedPath, - PathFragment symlinkTarget, TreeSet<Path> orderedSeenPaths, - Iterable<RootedPath> symlinkChain, Environment env) throws FileFunctionException { + private Pair<RootedPath, FileStateValue> getSymlinkTargetRootedPath( + RootedPath rootedPath, + PathFragment symlinkTarget, + TreeSet<Path> orderedSeenPaths, + Iterable<RootedPath> symlinkChain, + Environment env) + throws FileFunctionException, InterruptedException { RootedPath symlinkTargetRootedPath; if (symlinkTarget.isAbsolute()) { Path path = rootedPath.asPath().getFileSystem().getRootDirectory().getRelative( diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/FileStateFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/FileStateFunction.java index d77f7e3fc3..f2dfff824c 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/FileStateFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/FileStateFunction.java @@ -19,7 +19,6 @@ import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.io.IOException; import java.util.concurrent.atomic.AtomicReference; @@ -41,7 +40,8 @@ public class FileStateFunction implements SkyFunction { } @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws FileStateFunctionException { + public SkyValue compute(SkyKey skyKey, Environment env) + throws FileStateFunctionException, InterruptedException { RootedPath rootedPath = (RootedPath) skyKey.argument(); try { diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunction.java index 777794654f..f95274c648 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunction.java @@ -49,7 +49,8 @@ public final class FilesetEntryFunction implements SkyFunction { } @Override - public SkyValue compute(SkyKey key, Environment env) throws FilesetEntryFunctionException { + public SkyValue compute(SkyKey key, Environment env) + throws FilesetEntryFunctionException, InterruptedException { FilesetTraversalParams t = (FilesetTraversalParams) key.argument(); Preconditions.checkState( t.getNestedTraversal().isPresent() != t.getDirectTraversal().isPresent(), @@ -226,8 +227,9 @@ public final class FilesetEntryFunction implements SkyFunction { return null; } - private RecursiveFilesystemTraversalValue traverse(Environment env, String errorInfo, - DirectTraversal traversal) throws MissingDepException { + private static RecursiveFilesystemTraversalValue traverse( + Environment env, String errorInfo, DirectTraversal traversal) + throws MissingDepException, InterruptedException { SkyKey depKey = RecursiveFilesystemTraversalValue.key( new RecursiveFilesystemTraversalValue.TraversalRequest(traversal.getRoot().asRootedPath(), traversal.isGenerated(), traversal.getPackageBoundaryMode(), traversal.isPackage(), diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/FilesystemValueChecker.java b/src/main/java/com/google/devtools/build/lib/skyframe/FilesystemValueChecker.java index 6f78572939..4b9263e0e6 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/FilesystemValueChecker.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/FilesystemValueChecker.java @@ -45,7 +45,6 @@ import com.google.devtools.build.skyframe.SkyFunctionName; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; import com.google.devtools.build.skyframe.WalkableGraph; - import java.io.IOException; import java.util.Collection; import java.util.Collections; @@ -62,7 +61,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.Logger; - import javax.annotation.Nullable; /** @@ -123,9 +121,9 @@ public class FilesystemValueChecker { dirtinessChecker, /*checkMissingValues=*/true); } - private static interface ValueFetcher { + private interface ValueFetcher { @Nullable - SkyValue get(SkyKey key); + SkyValue get(SkyKey key) throws InterruptedException; } private static class WalkableGraphBackedValueFetcher implements ValueFetcher { @@ -137,7 +135,7 @@ public class FilesystemValueChecker { @Override @Nullable - public SkyValue get(SkyKey key) { + public SkyValue get(SkyKey key) throws InterruptedException { return walkableGraph.exists(key) ? walkableGraph.getValue(key) : null; } } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/GlobFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/GlobFunction.java index 06518314e8..ec3f7138bf 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/GlobFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/GlobFunction.java @@ -31,10 +31,8 @@ import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyFunctionException.Transience; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.util.Map; import java.util.regex.Pattern; - import javax.annotation.Nullable; /** @@ -54,7 +52,8 @@ public final class GlobFunction implements SkyFunction { } @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws GlobFunctionException { + public SkyValue compute(SkyKey skyKey, Environment env) + throws GlobFunctionException, InterruptedException { GlobDescriptor glob = (GlobDescriptor) skyKey.argument(); // Note that the glob's package is assumed to exist which implies that the package's BUILD file diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java b/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java index 26e5f1bbb3..5499189c9b 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java @@ -47,7 +47,6 @@ import com.google.devtools.build.lib.vfs.RootedPath; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; import com.google.devtools.build.skyframe.WalkableGraph; - import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -79,7 +78,7 @@ public final class GraphBackedRecursivePackageProvider implements RecursivePacka @Override public Package getPackage(EventHandler eventHandler, PackageIdentifier packageName) - throws NoSuchPackageException { + throws NoSuchPackageException, InterruptedException { SkyKey pkgKey = PackageValue.key(packageName); PackageValue pkgValue; @@ -98,8 +97,9 @@ public final class GraphBackedRecursivePackageProvider implements RecursivePacka } @Override - public Map<PackageIdentifier, Package> bulkGetPackages(EventHandler eventHandler, - Iterable<PackageIdentifier> pkgIds) throws NoSuchPackageException { + public Map<PackageIdentifier, Package> bulkGetPackages( + EventHandler eventHandler, Iterable<PackageIdentifier> pkgIds) + throws NoSuchPackageException, InterruptedException { Set<SkyKey> pkgKeys = ImmutableSet.copyOf(PackageValue.keys(pkgIds)); ImmutableMap.Builder<PackageIdentifier, Package> pkgResults = ImmutableMap.builder(); @@ -133,7 +133,8 @@ public final class GraphBackedRecursivePackageProvider implements RecursivePacka @Override - public boolean isPackage(EventHandler eventHandler, PackageIdentifier packageName) { + public boolean isPackage(EventHandler eventHandler, PackageIdentifier packageName) + throws InterruptedException { SkyKey packageLookupKey = PackageLookupValue.key(packageName); if (!graph.exists(packageLookupKey)) { // If the package lookup key does not exist in the graph, then it must not correspond to any @@ -158,8 +159,10 @@ public final class GraphBackedRecursivePackageProvider implements RecursivePacka @Override public Iterable<PathFragment> getPackagesUnderDirectory( - RepositoryName repository, PathFragment directory, - ImmutableSet<PathFragment> excludedSubdirectories) { + RepositoryName repository, + PathFragment directory, + ImmutableSet<PathFragment> excludedSubdirectories) + throws InterruptedException { PathFragment.checkAllPathsAreUnder(excludedSubdirectories, directory); // Check that this package is covered by at least one of our universe patterns. @@ -208,7 +211,8 @@ public final class GraphBackedRecursivePackageProvider implements RecursivePacka private void collectPackagesUnder( final RepositoryName repository, Set<TraversalInfo> traversals, - ImmutableList.Builder<PathFragment> builder) { + ImmutableList.Builder<PathFragment> builder) + throws InterruptedException { Map<TraversalInfo, SkyKey> traversalToKeyMap = Maps.asMap( traversals, @@ -256,7 +260,7 @@ public final class GraphBackedRecursivePackageProvider implements RecursivePacka @Override public Target getTarget(EventHandler eventHandler, Label label) - throws NoSuchPackageException, NoSuchTargetException { + throws NoSuchPackageException, NoSuchTargetException, InterruptedException { return getPackage(eventHandler, label.getPackageIdentifier()).getTarget(label.getName()); } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageErrorFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageErrorFunction.java index b277321342..17ba9bee28 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageErrorFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageErrorFunction.java @@ -24,7 +24,6 @@ import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyFunctionException.Transience; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import javax.annotation.Nullable; /** @@ -44,7 +43,8 @@ public class PackageErrorFunction implements SkyFunction { @Nullable @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws PackageErrorFunctionException { + public SkyValue compute(SkyKey skyKey, Environment env) + throws PackageErrorFunctionException, InterruptedException { PackageIdentifier packageIdentifier = (PackageIdentifier) skyKey.argument(); try { SkyKey packageKey = PackageValue.key(packageIdentifier); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java index 186232aeff..54edcf52e0 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java @@ -172,17 +172,19 @@ public class PackageFunction implements SkyFunction { } /** - * Marks the given dependencies, and returns those already present. Ignores any exception - * thrown while building the dependency, except for filesystem inconsistencies. + * Marks the given dependencies, and returns those already present. Ignores any exception thrown + * while building the dependency, except for filesystem inconsistencies. * * <p>We need to mark dependencies implicitly used by the legacy package loading code, but we * don't care about any skyframe errors since the package knows whether it's in error or not. */ private static Pair<? extends Map<PathFragment, PackageLookupValue>, Boolean> - getPackageLookupDepsAndPropagateInconsistentFilesystemExceptions( - PackageIdentifier packageIdentifier, - Iterable<SkyKey> depKeys, Environment env, boolean packageWasInError) - throws InternalInconsistentFilesystemException { + getPackageLookupDepsAndPropagateInconsistentFilesystemExceptions( + PackageIdentifier packageIdentifier, + Iterable<SkyKey> depKeys, + Environment env, + boolean packageWasInError) + throws InternalInconsistentFilesystemException, InterruptedException { Preconditions.checkState( Iterables.all(depKeys, SkyFunctions.isSkyFunction(SkyFunctions.PACKAGE_LOOKUP)), depKeys); boolean packageShouldBeInError = packageWasInError; @@ -216,7 +218,7 @@ public class PackageFunction implements SkyFunction { Environment env, boolean packageWasInError) throws InternalInconsistentFilesystemException, FileOutsidePackageRootsException, - SymlinkOutsidePackageRootsException { + SymlinkOutsidePackageRootsException, InterruptedException { Preconditions.checkState( Iterables.all(depKeys, SkyFunctions.isSkyFunction(SkyFunctions.FILE)), depKeys); boolean packageShouldBeInError = packageWasInError; @@ -249,7 +251,7 @@ public class PackageFunction implements SkyFunction { Environment env, boolean packageWasInError) throws InternalInconsistentFilesystemException, FileOutsidePackageRootsException, - SymlinkOutsidePackageRootsException { + SymlinkOutsidePackageRootsException, InterruptedException { Preconditions.checkState( Iterables.all(depKeys, SkyFunctions.isSkyFunction(SkyFunctions.GLOB)), depKeys); boolean packageShouldBeInError = packageWasInError; @@ -289,7 +291,7 @@ public class PackageFunction implements SkyFunction { PackageIdentifier packageIdentifier, boolean containsErrors) throws InternalInconsistentFilesystemException, FileOutsidePackageRootsException, - SymlinkOutsidePackageRootsException { + SymlinkOutsidePackageRootsException, InterruptedException { boolean packageShouldBeInError = containsErrors; // TODO(bazel-team): This means that many packages will have to be preprocessed twice. Ouch! @@ -368,11 +370,12 @@ public class PackageFunction implements SkyFunction { /** * Adds a dependency on the WORKSPACE file, representing it as a special type of package. + * * @throws PackageFunctionException if there is an error computing the workspace file or adding - * its rules to the //external package. + * its rules to the //external package. */ private SkyValue getExternalPackage(Environment env, Path packageLookupPath) - throws PackageFunctionException { + throws PackageFunctionException, InterruptedException { RootedPath workspacePath = RootedPath.toRootedPath( packageLookupPath, Label.EXTERNAL_PACKAGE_FILE_NAME); SkyKey workspaceKey = ExternalPackageFunction.key(workspacePath); @@ -567,7 +570,8 @@ public class PackageFunction implements SkyFunction { return new PackageValue(pkg); } - private FileValue getBuildFileValue(Environment env, RootedPath buildFileRootedPath) { + private static FileValue getBuildFileValue(Environment env, RootedPath buildFileRootedPath) + throws InterruptedException { FileValue buildFileValue; try { buildFileValue = (FileValue) env.getValueOrThrow(FileValue.key(buildFileRootedPath), @@ -747,7 +751,7 @@ public class PackageFunction implements SkyFunction { private static void handleLabelsCrossingSubpackagesAndPropagateInconsistentFilesystemExceptions( Path pkgRoot, PackageIdentifier pkgId, Package.Builder pkgBuilder, Environment env) - throws InternalInconsistentFilesystemException { + throws InternalInconsistentFilesystemException, InterruptedException { Set<SkyKey> containingPkgLookupKeys = Sets.newHashSet(); Map<Target, SkyKey> targetToKey = new HashMap<>(); for (Target target : pkgBuilder.getTargets()) { @@ -921,7 +925,7 @@ public class PackageFunction implements SkyFunction { @Override public Token runAsync(List<String> includes, List<String> excludes, boolean excludeDirs) - throws BadGlobException { + throws BadGlobException, InterruptedException { List<SkyKey> globKeys = new ArrayList<>(includes.size() + excludes.size()); LinkedHashSet<SkyKey> includesKeys = Sets.newLinkedHashSetWithExpectedSize(includes.size()); LinkedHashSet<SkyKey> excludesKeys = Sets.newLinkedHashSetWithExpectedSize(excludes.size()); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupFunction.java index 638f2eee8d..6e425e8dd7 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupFunction.java @@ -47,7 +47,8 @@ public class PackageLookupFunction implements SkyFunction { } @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws PackageLookupFunctionException { + public SkyValue compute(SkyKey skyKey, Environment env) + throws PackageLookupFunctionException, InterruptedException { PathPackageLocator pkgLocator = PrecomputedValue.PATH_PACKAGE_LOCATOR.get(env); PackageIdentifier packageKey = (PackageIdentifier) skyKey.argument(); if (PackageFunction.isDefaultsPackage(packageKey)) { @@ -94,9 +95,9 @@ public class PackageLookupFunction implements SkyFunction { } @Nullable - private FileValue getFileValue( + private static FileValue getFileValue( RootedPath fileRootedPath, Environment env, PackageIdentifier packageIdentifier) - throws PackageLookupFunctionException { + throws PackageLookupFunctionException, InterruptedException { String basename = fileRootedPath.asPath().getBaseName(); SkyKey fileSkyKey = FileValue.key(fileRootedPath); FileValue fileValue = null; @@ -122,12 +123,12 @@ public class PackageLookupFunction implements SkyFunction { return fileValue; } - private PackageLookupValue getPackageLookupValue( + private static PackageLookupValue getPackageLookupValue( Environment env, ImmutableList<Path> packagePathEntries, PackageIdentifier packageIdentifier, BuildFileName buildFileName) - throws PackageLookupFunctionException { + throws PackageLookupFunctionException, InterruptedException { // TODO(bazel-team): The following is O(n^2) on the number of elements on the package path due // to having restart the SkyFunction after every new dependency. However, if we try to batch // the missing value keys, more dependencies than necessary will be declared. This wart can be @@ -147,9 +148,9 @@ public class PackageLookupFunction implements SkyFunction { return PackageLookupValue.NO_BUILD_FILE_VALUE; } - private PackageLookupValue computeWorkspacePackageLookupValue( + private static PackageLookupValue computeWorkspacePackageLookupValue( Environment env, ImmutableList<Path> packagePathEntries) - throws PackageLookupFunctionException { + throws PackageLookupFunctionException, InterruptedException { PackageLookupValue result = getPackageLookupValue( env, packagePathEntries, Label.EXTERNAL_PACKAGE_IDENTIFIER, BuildFileName.WORKSPACE); @@ -182,11 +183,11 @@ public class PackageLookupFunction implements SkyFunction { * Gets a PackageLookupValue from a different Bazel repository. * * <p>To do this, it looks up the "external" package and finds a path mapping for the repository - * name.</p> + * name. */ - private PackageLookupValue computeExternalPackageLookupValue( + private static PackageLookupValue computeExternalPackageLookupValue( SkyKey skyKey, Environment env, PackageIdentifier packageIdentifier) - throws PackageLookupFunctionException { + throws PackageLookupFunctionException, InterruptedException { PackageIdentifier id = (PackageIdentifier) skyKey.argument(); SkyKey repositoryKey = RepositoryValue.key(id.getRepository()); RepositoryValue repositoryValue; diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PostConfiguredTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PostConfiguredTargetFunction.java index e221ae7be1..08eecd7828 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/PostConfiguredTargetFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PostConfiguredTargetFunction.java @@ -38,12 +38,10 @@ import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; - import javax.annotation.Nullable; /** @@ -134,8 +132,8 @@ public class PostConfiguredTargetFunction implements SkyFunction { * target, or null if not all dependencies have yet been SkyFrame-evaluated. */ @Nullable - private ImmutableMap<Label, ConfigMatchingProvider> getConfigurableAttributeConditions( - TargetAndConfiguration ctg, Environment env) { + private static ImmutableMap<Label, ConfigMatchingProvider> getConfigurableAttributeConditions( + TargetAndConfiguration ctg, Environment env) throws InterruptedException { if (!(ctg.getTarget() instanceof Rule)) { return ImmutableMap.of(); } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java index a5f7a6793d..bc9977e4c9 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java @@ -32,10 +32,8 @@ import com.google.devtools.build.skyframe.Injectable; import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.util.Map; import java.util.UUID; - import javax.annotation.Nullable; /** @@ -138,7 +136,7 @@ public final class PrecomputedValue implements SkyValue { return "<BuildVariable " + value + ">"; } - public static final void dependOnBuildId(SkyFunction.Environment env) { + public static void dependOnBuildId(SkyFunction.Environment env) throws InterruptedException { BUILD_ID.get(env); } @@ -166,7 +164,7 @@ public final class PrecomputedValue implements SkyValue { */ @Nullable @SuppressWarnings("unchecked") - public T get(SkyFunction.Environment env) { + public T get(SkyFunction.Environment env) throws InterruptedException { PrecomputedValue value = (PrecomputedValue) env.getValue(key); if (value == null) { return null; diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternFunction.java index 7524bee1c0..fc9cd81c55 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternFunction.java @@ -44,11 +44,9 @@ import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicReference; - import javax.annotation.Nullable; /** @@ -177,16 +175,17 @@ public class PrepareDepsOfPatternFunction implements SkyFunction { } @Override - public ResolvedTargets<Void> getTargetsInPackage(String originalPattern, - PackageIdentifier packageIdentifier, boolean rulesOnly) throws TargetParsingException { + public ResolvedTargets<Void> getTargetsInPackage( + String originalPattern, PackageIdentifier packageIdentifier, boolean rulesOnly) + throws TargetParsingException, InterruptedException { FilteringPolicy policy = rulesOnly ? FilteringPolicies.RULES_ONLY : FilteringPolicies.NO_FILTER; return getTargetsInPackage(originalPattern, packageIdentifier, policy); } - private ResolvedTargets<Void> getTargetsInPackage(String originalPattern, - PackageIdentifier packageIdentifier, FilteringPolicy policy) - throws TargetParsingException { + private ResolvedTargets<Void> getTargetsInPackage( + String originalPattern, PackageIdentifier packageIdentifier, FilteringPolicy policy) + throws TargetParsingException, InterruptedException { try { Package pkg = packageProvider.getPackage(env.getListener(), packageIdentifier); ResolvedTargets<Target> packageTargets = @@ -209,7 +208,7 @@ public class PrepareDepsOfPatternFunction implements SkyFunction { } @Override - public boolean isPackage(PackageIdentifier packageIdentifier) { + public boolean isPackage(PackageIdentifier packageIdentifier) throws InterruptedException { return packageProvider.isPackage(env.getListener(), packageIdentifier); } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfTargetsUnderDirectoryFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfTargetsUnderDirectoryFunction.java index b5b560a2c8..568b623c6e 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfTargetsUnderDirectoryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfTargetsUnderDirectoryFunction.java @@ -32,9 +32,7 @@ import com.google.devtools.build.lib.vfs.RootedPath; import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.util.Map; - import javax.annotation.Nullable; /** @@ -50,7 +48,7 @@ public class PrepareDepsOfTargetsUnderDirectoryFunction implements SkyFunction { } @Override - public SkyValue compute(SkyKey skyKey, Environment env) { + public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { PrepareDepsOfTargetsUnderDirectoryKey argument = (PrepareDepsOfTargetsUnderDirectoryKey) skyKey.argument(); FilteringPolicy filteringPolicy = argument.getFilteringPolicy(); @@ -102,13 +100,13 @@ public class PrepareDepsOfTargetsUnderDirectoryFunction implements SkyFunction { } @Override - public void visitPackageValue(Package pkg, Environment env) { + public void visitPackageValue(Package pkg, Environment env) throws InterruptedException { loadTransitiveTargets(env, pkg, filteringPolicy); } } private static void loadTransitiveTargets( - Environment env, Package pkg, FilteringPolicy filteringPolicy) { + Environment env, Package pkg, FilteringPolicy filteringPolicy) throws InterruptedException { ResolvedTargets<Target> packageTargets = TargetPatternResolverUtil.resolvePackageTargets(pkg, filteringPolicy); ImmutableList.Builder<SkyKey> builder = ImmutableList.builder(); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java index 24696d04f9..4c66e8fe47 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java @@ -39,7 +39,6 @@ import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; import com.google.devtools.build.skyframe.ValueOrException; import com.google.devtools.build.skyframe.ValueOrException4; - import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -105,25 +104,26 @@ abstract class RecursiveDirectoryTraversalFunction interface Visitor { /** - * Called iff the directory contains a package. Provides an {@link Environment} {@code env} - * so that the visitor may do additional lookups. {@link Environment#valuesMissing} will be - * checked afterwards. + * Called iff the directory contains a package. Provides an {@link Environment} {@code env} so + * that the visitor may do additional lookups. {@link Environment#valuesMissing} will be checked + * afterwards. */ - void visitPackageValue(Package pkg, Environment env); + void visitPackageValue(Package pkg, Environment env) throws InterruptedException; } /** - * Looks in the directory specified by {@code recursivePkgKey} for a package, does some work - * as specified by {@link Visitor} if such a package exists, then recursively does work in each + * Looks in the directory specified by {@code recursivePkgKey} for a package, does some work as + * specified by {@link Visitor} if such a package exists, then recursively does work in each * non-excluded subdirectory as specified by {@link #getSkyKeyForSubdirectory}, and finally - * aggregates the {@link Visitor} value along with values from each subdirectory as specified - * by {@link #aggregateWithSubdirectorySkyValues}, and returns that aggregation. + * aggregates the {@link Visitor} value along with values from each subdirectory as specified by + * {@link #aggregateWithSubdirectorySkyValues}, and returns that aggregation. * * <p>Returns null if {@code env.valuesMissing()} is true, checked after each call to one of * {@link RecursiveDirectoryTraversalFunction}'s abstract methods that were given {@code env}. * (And after each of {@code visitDirectory}'s own uses of {@code env}, of course.) */ - TReturn visitDirectory(RecursivePkgKey recursivePkgKey, Environment env) { + TReturn visitDirectory(RecursivePkgKey recursivePkgKey, Environment env) + throws InterruptedException { RootedPath rootedPath = recursivePkgKey.getRootedPath(); ImmutableSet<PathFragment> excludedPaths = recursivePkgKey.getExcludedPaths(); Path root = rootedPath.getRoot(); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java index b7f7b921d6..e122307ee7 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java @@ -31,12 +31,10 @@ import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; - import javax.annotation.Nullable; /** A {@link SkyFunction} to build {@link RecursiveFilesystemTraversalValue}s. */ @@ -109,7 +107,7 @@ public final class RecursiveFilesystemTraversalFunction implements SkyFunction { @Override public SkyValue compute(SkyKey skyKey, Environment env) - throws RecursiveFilesystemTraversalFunctionException { + throws RecursiveFilesystemTraversalFunctionException, InterruptedException { TraversalRequest traversal = (TraversalRequest) skyKey.argument(); try { // Stat the traversal root. @@ -204,7 +202,7 @@ public final class RecursiveFilesystemTraversalFunction implements SkyFunction { } private static FileInfo lookUpFileInfo(Environment env, TraversalRequest traversal) - throws MissingDepException { + throws MissingDepException, InterruptedException { // Stat the file. FileValue fileValue = (FileValue) getDependentSkyValue(env, FileValue.key(traversal.path)); if (fileValue.exists()) { @@ -279,8 +277,9 @@ public final class RecursiveFilesystemTraversalFunction implements SkyFunction { * {@link FileInfo} so the caller should use these instead of the old ones (this happens when * a package is found, but under a different root than expected) */ - private static PkgLookupResult checkIfPackage(Environment env, TraversalRequest traversal, - FileInfo rootInfo) throws MissingDepException { + private static PkgLookupResult checkIfPackage( + Environment env, TraversalRequest traversal, FileInfo rootInfo) + throws MissingDepException, InterruptedException { Preconditions.checkArgument(rootInfo.type.exists() && !rootInfo.type.isFile(), "{%s} {%s}", traversal, rootInfo); PackageLookupValue pkgLookup = (PackageLookupValue) getDependentSkyValue(env, @@ -315,8 +314,9 @@ public final class RecursiveFilesystemTraversalFunction implements SkyFunction { * * <p>The returned keys are of type {@link SkyFunctions#RECURSIVE_FILESYSTEM_TRAVERSAL}. */ - private static Collection<SkyKey> createRecursiveTraversalKeys(Environment env, - TraversalRequest traversal) throws MissingDepException { + private static Collection<SkyKey> createRecursiveTraversalKeys( + Environment env, TraversalRequest traversal) + throws MissingDepException, InterruptedException { // Use the traversal's path, even if it's a symlink. The contents of the directory, as listed // in the result, must be relative to it. DirectoryListingValue dirListing = (DirectoryListingValue) getDependentSkyValue(env, @@ -405,7 +405,7 @@ public final class RecursiveFilesystemTraversalFunction implements SkyFunction { } private static SkyValue getDependentSkyValue(Environment env, SkyKey key) - throws MissingDepException { + throws MissingDepException, InterruptedException { SkyValue value = env.getValue(key); if (env.valuesMissing()) { throw new MissingDepException(); @@ -419,8 +419,7 @@ public final class RecursiveFilesystemTraversalFunction implements SkyFunction { * <p>The keys must all be {@link SkyFunctions#RECURSIVE_FILESYSTEM_TRAVERSAL} keys. */ private static Collection<RecursiveFilesystemTraversalValue> traverseChildren( - Environment env, Iterable<SkyKey> keys) - throws MissingDepException { + Environment env, Iterable<SkyKey> keys) throws MissingDepException, InterruptedException { Map<SkyKey, SkyValue> values = env.getValues(keys); if (env.valuesMissing()) { throw new MissingDepException(); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePackageProviderBackedTargetPatternResolver.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePackageProviderBackedTargetPatternResolver.java index 642d8eae36..a01a1f4f33 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePackageProviderBackedTargetPatternResolver.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePackageProviderBackedTargetPatternResolver.java @@ -44,7 +44,6 @@ import com.google.devtools.build.lib.pkgcache.RecursivePackageProvider; import com.google.devtools.build.lib.pkgcache.TargetPatternResolverUtil; import com.google.devtools.build.lib.util.BatchCallback; import com.google.devtools.build.lib.vfs.PathFragment; - import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -171,7 +170,7 @@ public class RecursivePackageProviderBackedTargetPatternResolver } @Override - public boolean isPackage(PackageIdentifier packageIdentifier) { + public boolean isPackage(PackageIdentifier packageIdentifier) throws InterruptedException { return recursivePackageProvider.isPackage(eventHandler, packageIdentifier); } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunction.java index 607e9b2c4e..9b97b4be19 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunction.java @@ -27,9 +27,7 @@ import com.google.devtools.build.lib.vfs.RootedPath; import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.util.Map; - import javax.annotation.Nullable; /** @@ -48,7 +46,7 @@ public class RecursivePkgFunction implements SkyFunction { /** N.B.: May silently throw {@link NoSuchPackageException} in nokeep_going mode! */ @Override - public SkyValue compute(SkyKey skyKey, Environment env) { + public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { return new MyTraversalFunction().visitDirectory((RecursivePkgKey) skyKey.argument(), env); } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java index b5c0863d98..11d66001db 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java @@ -74,7 +74,6 @@ import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.lib.vfs.Symlinks; import com.google.devtools.build.skyframe.SkyFunction.Environment; import com.google.protobuf.ByteString; - import java.io.IOException; import java.util.Collection; import java.util.HashSet; @@ -92,7 +91,6 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; import java.util.concurrent.atomic.AtomicReference; - import javax.annotation.Nullable; /** @@ -503,7 +501,7 @@ public final class SkyframeActionExecutor implements ActionExecutionContextFacto @Nullable Iterable<Artifact> getActionCachedInputs(Action action, PackageRootResolver resolver) - throws PackageRootResolutionException { + throws PackageRootResolutionException, InterruptedException { return actionCacheChecker.getCachedInputs(action, resolver); } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeAwareAction.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeAwareAction.java index 6c2caf1128..43c0193d0e 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeAwareAction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeAwareAction.java @@ -40,7 +40,7 @@ import com.google.devtools.build.skyframe.SkyFunction.Environment; public interface SkyframeAwareAction { /** Wrapper and/or base class for exceptions raised in {@link #establishSkyframeDependencies}. */ - public static class ExceptionBase extends Exception { + class ExceptionBase extends Exception { public ExceptionBase(String message) { super(message); } @@ -53,11 +53,11 @@ public interface SkyframeAwareAction { /** * Establish dependencies on Skyframe values before executing the action. * - * <p><b>IMPORTANT</b>: actions that implement this interface should override - * {@code Action.executeUnconditionally} and return true. See {@link SkyframeAwareAction} why. + * <p><b>IMPORTANT</b>: actions that implement this interface should override {@code + * Action.executeUnconditionally} and return true. See {@link SkyframeAwareAction} why. * - * <p>This method should perform as little computation as possible: ideally it should request - * one or a few SkyValues, perhaps set some state somewhere and return. If this method needs to + * <p>This method should perform as little computation as possible: ideally it should request one + * or a few SkyValues, perhaps set some state somewhere and return. If this method needs to * perform anything more complicated than that, including perhaps some non-trivial computation, * you should implement that as a SkyFunction and request the corresponding SkyValue in this * method. @@ -69,5 +69,5 @@ public interface SkyframeAwareAction { * exceptions); that is the responsibility of the caller. It should return as soon as possible, * ready to be called again at a later time if need be. */ - void establishSkyframeDependencies(Environment env) throws ExceptionBase; + void establishSkyframeDependencies(Environment env) throws ExceptionBase, InterruptedException; } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java index 546a0e2575..2d80c522f5 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java @@ -73,13 +73,11 @@ import com.google.devtools.build.skyframe.EvaluationResult; import com.google.devtools.build.skyframe.SkyFunction.Environment; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Logger; - import javax.annotation.Nullable; /** @@ -430,7 +428,8 @@ public final class SkyframeBuildView { */ // TODO(bazel-team): Allow analysis to return null so the value builder can exit and wait for a // restart deps are not present. - private boolean getWorkspaceStatusValues(Environment env, BuildConfiguration config) { + private static boolean getWorkspaceStatusValues(Environment env, BuildConfiguration config) + throws InterruptedException { env.getValue(WorkspaceStatusValue.SKY_KEY); Map<BuildInfoKey, BuildInfoFactory> buildInfoFactories = PrecomputedValue.BUILD_INFO_FACTORIES.get(env); @@ -451,9 +450,13 @@ public final class SkyframeBuildView { /** Returns null if any build-info values are not ready. */ @Nullable - CachingAnalysisEnvironment createAnalysisEnvironment(ArtifactOwner owner, - boolean isSystemEnv, EventHandler eventHandler, - Environment env, BuildConfiguration config) { + CachingAnalysisEnvironment createAnalysisEnvironment( + ArtifactOwner owner, + boolean isSystemEnv, + EventHandler eventHandler, + Environment env, + BuildConfiguration config) + throws InterruptedException { if (config != null && !getWorkspaceStatusValues(env, config)) { return null; } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeDependencyResolver.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeDependencyResolver.java index 09fc0f2176..965c3fb4d0 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeDependencyResolver.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeDependencyResolver.java @@ -31,12 +31,10 @@ import com.google.devtools.build.lib.packages.TargetUtils; import com.google.devtools.build.skyframe.SkyFunction.Environment; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.ValueOrException; - import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; - import javax.annotation.Nullable; /** @@ -65,7 +63,8 @@ public final class SkyframeDependencyResolver extends DependencyResolver { } @Override - protected void missingEdgeHook(Target from, Label to, NoSuchThingException e) { + protected void missingEdgeHook(Target from, Label to, NoSuchThingException e) + throws InterruptedException { if (e instanceof NoSuchTargetException) { NoSuchTargetException nste = (NoSuchTargetException) e; if (to.equals(nste.getLabel())) { @@ -87,7 +86,8 @@ public final class SkyframeDependencyResolver extends DependencyResolver { @Nullable @Override - protected Target getTarget(Target from, Label label, NestedSetBuilder<Label> rootCauses) { + protected Target getTarget(Target from, Label label, NestedSetBuilder<Label> rootCauses) + throws InterruptedException { SkyKey key = PackageValue.key(label.getPackageIdentifier()); PackageValue packageValue; try { @@ -125,7 +125,8 @@ public final class SkyframeDependencyResolver extends DependencyResolver { @Override protected List<BuildConfiguration> getConfigurations( Set<Class<? extends BuildConfiguration.Fragment>> fragments, - Iterable<BuildOptions> buildOptions) throws InvalidConfigurationException { + Iterable<BuildOptions> buildOptions) + throws InvalidConfigurationException, InterruptedException { List<SkyKey> keys = new ArrayList<>(); for (BuildOptions options : buildOptions) { keys.add(BuildConfigurationValue.key(fragments, options)); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframePackageLoaderWithValueEnvironment.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframePackageLoaderWithValueEnvironment.java index 7ebb7b0018..ceda17193d 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframePackageLoaderWithValueEnvironment.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframePackageLoaderWithValueEnvironment.java @@ -32,7 +32,6 @@ import com.google.devtools.build.lib.vfs.RootedPath; import com.google.devtools.build.skyframe.MemoizingEvaluator; import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyKey; - import java.io.IOException; /** @@ -56,7 +55,7 @@ class SkyframePackageLoaderWithValueEnvironment implements PackageProviderForCon } private Package getPackage(final PackageIdentifier pkgIdentifier) - throws NoSuchPackageException { + throws NoSuchPackageException, InterruptedException { SkyKey key = PackageValue.key(pkgIdentifier); PackageValue value = (PackageValue) env.getValueOrThrow(key, NoSuchPackageException.class); if (value != null) { @@ -66,13 +65,15 @@ class SkyframePackageLoaderWithValueEnvironment implements PackageProviderForCon } @Override - public Target getTarget(Label label) throws NoSuchPackageException, NoSuchTargetException { + public Target getTarget(Label label) + throws NoSuchPackageException, NoSuchTargetException, InterruptedException { Package pkg = getPackage(label.getPackageIdentifier()); return pkg == null ? null : pkg.getTarget(label.getName()); } @Override - public void addDependency(Package pkg, String fileName) throws LabelSyntaxException, IOException { + public void addDependency(Package pkg, String fileName) + throws LabelSyntaxException, IOException, InterruptedException { RootedPath fileRootedPath = RootedPath.toRootedPath(pkg.getSourceRoot(), pkg.getPackageIdentifier().getSourceRoot().getRelative(fileName)); FileValue result = (FileValue) env.getValue(FileValue.key(fileRootedPath)); @@ -83,7 +84,7 @@ class SkyframePackageLoaderWithValueEnvironment implements PackageProviderForCon @Override public <T extends Fragment> T getFragment(BuildOptions buildOptions, Class<T> fragmentType) - throws InvalidConfigurationException { + throws InvalidConfigurationException, InterruptedException { ConfigurationFragmentValue fragmentNode = (ConfigurationFragmentValue) env.getValueOrThrow( ConfigurationFragmentValue.key(buildOptions, fragmentType, ruleClassProvider), InvalidConfigurationException.class); @@ -94,7 +95,7 @@ class SkyframePackageLoaderWithValueEnvironment implements PackageProviderForCon } @Override - public BlazeDirectories getDirectories() { + public BlazeDirectories getDirectories() throws InterruptedException { return PrecomputedValue.BLAZE_DIRECTORIES.get(env); } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java index c4889fa7d8..951d8a78b9 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java @@ -47,13 +47,11 @@ import com.google.devtools.build.skyframe.SkyFunctionException.Transience; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; import com.google.devtools.build.skyframe.ValueOrException2; - import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; - import javax.annotation.Nullable; /** @@ -211,17 +209,17 @@ public class SkylarkImportLookupFunction implements SkyFunction { } /** - * Computes the set of Labels corresponding to a collection of PathFragments representing - * absolute import paths. - * + * Computes the set of Labels corresponding to a collection of PathFragments representing absolute + * import paths. + * * @return a map from the computed {@link Label}s to the corresponding {@link PathFragment}s; - * {@code null} if any Skyframe dependencies are unavailable. + * {@code null} if any Skyframe dependencies are unavailable. * @throws SkylarkImportFailedException */ @Nullable static ImmutableMap<PathFragment, Label> labelsForAbsoluteImports( ImmutableSet<PathFragment> pathsToLookup, Environment env) - throws SkylarkImportFailedException { + throws SkylarkImportFailedException, InterruptedException { // Import PathFragments are absolute, so there is a 1-1 mapping from corresponding Labels. ImmutableMap.Builder<PathFragment, Label> outputMap = new ImmutableMap.Builder<>(); @@ -290,19 +288,17 @@ public class SkylarkImportLookupFunction implements SkyFunction { /** * Computes the set of {@link Label}s corresponding to a set of Skylark {@link LoadStatement}s. - * + * * @param imports a collection of Skylark {@link LoadStatement}s * @param containingFileLabel the {@link Label} of the file containing the load statements - * @return an {@link ImmutableMap} which maps a {@link String} used in the load statement to - * its corresponding {@Label}. Returns {@code null} if any Skyframe dependencies are - * unavailable. - * @throws SkylarkImportFailedException if no package can be found that contains the - * loaded file + * @return an {@link ImmutableMap} which maps a {@link String} used in the load statement to its + * corresponding {@Label}. Returns {@code null} if any Skyframe dependencies are unavailable. + * @throws SkylarkImportFailedException if no package can be found that contains the loaded file */ @Nullable static ImmutableMap<String, Label> findLabelsForLoadStatements( ImmutableCollection<SkylarkImport> imports, Label containingFileLabel, Environment env) - throws SkylarkImportFailedException { + throws SkylarkImportFailedException, InterruptedException { Preconditions.checkArgument( !containingFileLabel.getPackageIdentifier().getRepository().isDefault()); Map<String, Label> outputMap = Maps.newHashMapWithExpectedSize(imports.size()); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TargetMarkerFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TargetMarkerFunction.java index 736455ba2a..2aeba41d09 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/TargetMarkerFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/TargetMarkerFunction.java @@ -25,7 +25,6 @@ import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import javax.annotation.Nullable; /** @@ -37,7 +36,8 @@ import javax.annotation.Nullable; public final class TargetMarkerFunction implements SkyFunction { @Override - public SkyValue compute(SkyKey key, Environment env) throws TargetMarkerFunctionException { + public SkyValue compute(SkyKey key, Environment env) + throws TargetMarkerFunctionException, InterruptedException { try { return computeTargetMarkerValue(key, env); } catch (NoSuchTargetException e) { @@ -50,7 +50,7 @@ public final class TargetMarkerFunction implements SkyFunction { @Nullable static TargetMarkerValue computeTargetMarkerValue(SkyKey key, Environment env) - throws NoSuchTargetException, NoSuchPackageException { + throws NoSuchTargetException, NoSuchPackageException, InterruptedException { Label label = (Label) key.argument(); PathFragment pkgForLabel = label.getPackageFragment(); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternPhaseFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternPhaseFunction.java index 5215b7370a..60600caa1a 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternPhaseFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternPhaseFunction.java @@ -53,7 +53,7 @@ import javax.annotation.Nullable; final class TargetPatternPhaseFunction implements SkyFunction { @Override - public TargetPatternPhaseValue compute(SkyKey key, Environment env) { + public TargetPatternPhaseValue compute(SkyKey key, Environment env) throws InterruptedException { TargetPatternList options = (TargetPatternList) key.argument(); PackageValue packageValue = null; boolean workspaceError = false; @@ -189,8 +189,9 @@ final class TargetPatternPhaseFunction implements SkyFunction { * @param compileOneDependency if true, enables alternative interpretation of targetPatterns; see * {@link LoadingOptions#compileOneDependency} */ - private static ResolvedTargets<Target> getTargetsToBuild(Environment env, - List<String> targetPatterns, String offset, boolean compileOneDependency) { + private static ResolvedTargets<Target> getTargetsToBuild( + Environment env, List<String> targetPatterns, String offset, boolean compileOneDependency) + throws InterruptedException { List<SkyKey> patternSkyKeys = new ArrayList<>(); for (TargetPatternSkyKeyOrException keyOrException : TargetPatternValue.keys(targetPatterns, FilteringPolicies.FILTER_MANUAL, offset)) { @@ -253,8 +254,9 @@ final class TargetPatternPhaseFunction implements SkyFunction { * @param targetPatterns the list of command-line target patterns specified by the user * @param testFilter the test filter */ - private static ResolvedTargets<Target> determineTests(Environment env, - List<String> targetPatterns, String offset, TestFilter testFilter) { + private static ResolvedTargets<Target> determineTests( + Environment env, List<String> targetPatterns, String offset, TestFilter testFilter) + throws InterruptedException { List<SkyKey> patternSkyKeys = new ArrayList<>(); for (TargetPatternSkyKeyOrException keyOrException : TargetPatternValue.keys(targetPatterns, FilteringPolicies.FILTER_TESTS, offset)) { diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java index 7641f6eec9..e555b7df99 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java @@ -13,8 +13,6 @@ // limitations under the License. package com.google.devtools.build.lib.skyframe; -import com.google.common.base.Supplier; -import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; @@ -32,9 +30,9 @@ import com.google.devtools.build.lib.pkgcache.FilteringPolicies; import com.google.devtools.build.lib.pkgcache.FilteringPolicy; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.vfs.PathFragment; +import com.google.devtools.build.skyframe.InterruptibleSupplier; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; @@ -209,13 +207,15 @@ public final class TargetPatternValue implements SkyValue { return excludedSubdirectories; } - public ImmutableSet<PathFragment> getAllSubdirectoriesToExclude( - Iterable<PathFragment> blacklistedPackagePrefixes) { - return getAllSubdirectoriesToExclude(Suppliers.ofInstance(blacklistedPackagePrefixes)); + ImmutableSet<PathFragment> getAllSubdirectoriesToExclude( + Iterable<PathFragment> blacklistedPackagePrefixes) throws InterruptedException { + return getAllSubdirectoriesToExclude( + new InterruptibleSupplier.Instance<>(blacklistedPackagePrefixes)); } public ImmutableSet<PathFragment> getAllSubdirectoriesToExclude( - Supplier<? extends Iterable<PathFragment>> blacklistedPackagePrefixes) { + InterruptibleSupplier<? extends Iterable<PathFragment>> blacklistedPackagePrefixes) + throws InterruptedException { ImmutableSet.Builder<PathFragment> excludedPathsBuilder = ImmutableSet.builder(); excludedPathsBuilder.addAll(getExcludedSubdirectories()); if (parsedPattern.getType() == Type.TARGETS_BELOW_DIRECTORY) { diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternsResultBuilder.java b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternsResultBuilder.java index 575a0ff30e..3d0acf06af 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternsResultBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternsResultBuilder.java @@ -23,7 +23,6 @@ import com.google.devtools.build.lib.packages.Package; import com.google.devtools.build.lib.packages.Target; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.skyframe.WalkableGraph; - import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -43,10 +42,9 @@ abstract class TargetPatternsResultBuilder { hasError = true; } - /** - * Returns final set of targets and sets error flag if required. - */ - public ResolvedTargets<Target> build(WalkableGraph walkableGraph) throws TargetParsingException { + /** Returns final set of targets and sets error flag if required. */ + public ResolvedTargets<Target> build(WalkableGraph walkableGraph) + throws TargetParsingException, InterruptedException { precomputePackages(walkableGraph); ResolvedTargets.Builder<Target> resolvedTargetsBuilder = buildInternal(); if (hasError) { @@ -74,7 +72,7 @@ abstract class TargetPatternsResultBuilder { return resolvedTargetsBuilder; } - private void precomputePackages(WalkableGraph walkableGraph) { + private void precomputePackages(WalkableGraph walkableGraph) throws InterruptedException { Set<PackageIdentifier> packagesToRequest = getPackagesIdentifiers(); packages = Maps.newHashMapWithExpectedSize(packagesToRequest.size()); for (PackageIdentifier pkgIdentifier : packagesToRequest) { @@ -102,8 +100,8 @@ abstract class TargetPatternsResultBuilder { return packagesIdentifiers; } - private Package findPackageInGraph(PackageIdentifier pkgIdentifier, - WalkableGraph walkableGraph) { + private static Package findPackageInGraph( + PackageIdentifier pkgIdentifier, WalkableGraph walkableGraph) throws InterruptedException { return Preconditions.checkNotNull( ((PackageValue) walkableGraph.getValue(PackageValue.key(pkgIdentifier))), pkgIdentifier) .getPackage(); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TestCompletionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TestCompletionFunction.java index d277b1955a..3523d3370b 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/TestCompletionFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/TestCompletionFunction.java @@ -29,12 +29,8 @@ import com.google.devtools.build.skyframe.SkyValue; * runs. */ public final class TestCompletionFunction implements SkyFunction { - - public TestCompletionFunction() { - } - @Override - public SkyValue compute(SkyKey skyKey, Environment env) { + public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { TestCompletionValue.TestCompletionKey key = (TestCompletionValue.TestCompletionKey) skyKey.argument(); LabelAndConfiguration lac = key.labelAndConfiguration(); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TestSuiteExpansionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TestSuiteExpansionFunction.java index d5ecb25ae2..6324b2e03e 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/TestSuiteExpansionFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/TestSuiteExpansionFunction.java @@ -25,7 +25,6 @@ import com.google.devtools.build.lib.skyframe.TestSuiteExpansionValue.TestSuiteE import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashSet; @@ -33,7 +32,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; - import javax.annotation.Nullable; /** @@ -41,7 +39,7 @@ import javax.annotation.Nullable; */ final class TestSuiteExpansionFunction implements SkyFunction { @Override - public SkyValue compute(SkyKey key, Environment env) { + public SkyValue compute(SkyKey key, Environment env) throws InterruptedException { TestSuiteExpansion expansion = (TestSuiteExpansion) key.argument(); ResolvedTargets<Target> targets = labelsToTargets(env, expansion.getTargets(), false); List<SkyKey> testsInSuitesKeys = new ArrayList<>(); @@ -80,7 +78,7 @@ final class TestSuiteExpansionFunction implements SkyFunction { } static ResolvedTargets<Target> labelsToTargets( - Environment env, ImmutableSet<Label> labels, boolean hasError) { + Environment env, ImmutableSet<Label> labels, boolean hasError) throws InterruptedException { Set<PackageIdentifier> pkgIdentifiers = new LinkedHashSet<>(); for (Label label : labels) { pkgIdentifiers.add(label.getPackageIdentifier()); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TestsInSuiteFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TestsInSuiteFunction.java index 4556c762fb..18a747ee97 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/TestsInSuiteFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/TestsInSuiteFunction.java @@ -35,7 +35,6 @@ import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; import com.google.devtools.build.skyframe.ValueOrException; - import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -44,7 +43,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; - import javax.annotation.Nullable; /** @@ -54,7 +52,7 @@ import javax.annotation.Nullable; // TODO(ulfjack): What about test_suite rules that include each other. final class TestsInSuiteFunction implements SkyFunction { @Override - public SkyValue compute(SkyKey key, Environment env) { + public SkyValue compute(SkyKey key, Environment env) throws InterruptedException { TestsInSuite expansion = (TestsInSuite) key.argument(); ResolvedTargets<Target> result = computeTestsInSuite(env, expansion.getTestSuite(), expansion.isStrict()); @@ -65,13 +63,13 @@ final class TestsInSuiteFunction implements SkyFunction { } /** - * Populates 'result' with all the tests associated with the specified - * 'testSuite'. Throws an exception if any target is missing. + * Populates 'result' with all the tests associated with the specified 'testSuite'. Throws an + * exception if any target is missing. * - * <p>CAUTION! Keep this logic consistent with {@code TestSuite}! + * <p>CAUTION! Keep this logic consistent with {@code TestSuite}! */ - private ResolvedTargets<Target> computeTestsInSuite( - Environment env, Rule testSuite, boolean strict) { + private static ResolvedTargets<Target> computeTestsInSuite( + Environment env, Rule testSuite, boolean strict) throws InterruptedException { ResolvedTargets.Builder<Target> builder = ResolvedTargets.builder(); List<Target> testsAndSuites = new ArrayList<>(); // Note that testsAndSuites can contain input file targets; the test_suite rule does not @@ -132,8 +130,9 @@ final class TestsInSuiteFunction implements SkyFunction { * found a problem during the lookup process; the actual error message is reported to the * environment. */ - private boolean getPrerequisites(Environment env, Rule testSuite, String attrName, - List<Target> targets) { + private static boolean getPrerequisites( + Environment env, Rule testSuite, String attrName, List<Target> targets) + throws InterruptedException { List<Label> labels = NonconfigurableAttributeMapper.of(testSuite).get(attrName, BuildType.LABEL_LIST); Set<PackageIdentifier> pkgIdentifiers = new LinkedHashSet<>(); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveBaseTraversalFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveBaseTraversalFunction.java index 44b161b5a0..3bc1f30845 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveBaseTraversalFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveBaseTraversalFunction.java @@ -34,7 +34,6 @@ import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; import com.google.devtools.build.skyframe.ValueOrException2; - import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -42,7 +41,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; - import javax.annotation.Nullable; /** @@ -79,10 +77,13 @@ abstract class TransitiveBaseTraversalFunction<TProcessedTargets> implements Sky abstract TProcessedTargets processTarget(Label label, TargetAndErrorIfAny targetAndErrorIfAny); - abstract void processDeps(TProcessedTargets processedTargets, EventHandler eventHandler, + abstract void processDeps( + TProcessedTargets processedTargets, + EventHandler eventHandler, TargetAndErrorIfAny targetAndErrorIfAny, Iterable<Entry<SkyKey, ValueOrException2<NoSuchPackageException, NoSuchTargetException>>> - depEntries); + depEntries) + throws InterruptedException; /** * Returns a {@link SkyValue} based on the target and any errors it has, and the values @@ -97,11 +98,11 @@ abstract class TransitiveBaseTraversalFunction<TProcessedTargets> implements Sky */ @Nullable abstract TargetMarkerValue getTargetMarkerValue(SkyKey targetMarkerKey, Environment env) - throws NoSuchTargetException, NoSuchPackageException; + throws NoSuchTargetException, NoSuchPackageException, InterruptedException; @Override public SkyValue compute(SkyKey key, Environment env) - throws TransitiveBaseTraversalFunctionException { + throws TransitiveBaseTraversalFunctionException, InterruptedException { Label label = (Label) key.argument(); LoadTargetResults loadTargetResults; try { @@ -157,9 +158,11 @@ abstract class TransitiveBaseTraversalFunction<TProcessedTargets> implements Sky * <p>This method may return a precise set of aspect keys, but may need to request additional * dependencies from the env to do so. */ - private Iterable<SkyKey> getStrictLabelAspectKeys(Target target, - Map<SkyKey, ValueOrException2<NoSuchPackageException, NoSuchTargetException>> depMap, - Environment env) { + private Iterable<SkyKey> getStrictLabelAspectKeys( + Target target, + Map<SkyKey, ValueOrException2<NoSuchPackageException, NoSuchTargetException>> depMap, + Environment env) + throws InterruptedException { List<SkyKey> depKeys = Lists.newArrayList(); if (target instanceof Rule) { Map<Label, ValueOrException2<NoSuchPackageException, NoSuchTargetException>> labelDepMap = @@ -189,9 +192,10 @@ abstract class TransitiveBaseTraversalFunction<TProcessedTargets> implements Sky Attribute attr, Label toLabel, ValueOrException2<NoSuchPackageException, NoSuchTargetException> toVal, - Environment env); + Environment env) + throws InterruptedException; - private Iterable<SkyKey> getLabelDepKeys(Target target) { + private Iterable<SkyKey> getLabelDepKeys(Target target) throws InterruptedException { List<SkyKey> depKeys = Lists.newArrayList(); for (Label depLabel : getLabelDeps(target)) { depKeys.add(getKey(depLabel)); @@ -200,7 +204,7 @@ abstract class TransitiveBaseTraversalFunction<TProcessedTargets> implements Sky } // TODO(bazel-team): Unify this logic with that in LabelVisitor, and possibly DependencyResolver. - private static Iterable<Label> getLabelDeps(Target target) { + private static Iterable<Label> getLabelDeps(Target target) throws InterruptedException { final Set<Label> labels = new HashSet<>(); if (target instanceof OutputFile) { Rule rule = ((OutputFile) target).getGeneratingRule(); @@ -217,7 +221,7 @@ abstract class TransitiveBaseTraversalFunction<TProcessedTargets> implements Sky return labels; } - private static void visitRule(Target target, Set<Label> labels) { + private static void visitRule(Target target, Set<Label> labels) throws InterruptedException { labels.addAll(((Rule) target).getTransitions(DependencyFilter.NO_NODEP_ATTRIBUTES).values()); } @@ -295,7 +299,7 @@ abstract class TransitiveBaseTraversalFunction<TProcessedTargets> implements Sky } private LoadTargetResults loadTarget(Environment env, Label label) - throws NoSuchTargetException, NoSuchPackageException { + throws NoSuchTargetException, NoSuchPackageException, InterruptedException { SkyKey packageKey = PackageValue.key(label.getPackageIdentifier()); SkyKey targetKey = TargetMarkerValue.key(label); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java index 81e53e0429..b620259f25 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java @@ -118,10 +118,13 @@ public class TransitiveTargetFunction } @Override - void processDeps(TransitiveTargetValueBuilder builder, EventHandler eventHandler, + void processDeps( + TransitiveTargetValueBuilder builder, + EventHandler eventHandler, TargetAndErrorIfAny targetAndErrorIfAny, Iterable<Entry<SkyKey, ValueOrException2<NoSuchPackageException, NoSuchTargetException>>> - depEntries) { + depEntries) + throws InterruptedException { boolean successfulTransitiveLoading = builder.isSuccessfulTransitiveLoading(); Target target = targetAndErrorIfAny.getTarget(); NestedSetBuilder<Label> transitiveRootCauses = builder.getTransitiveRootCauses(); @@ -241,9 +244,13 @@ public class TransitiveTargetFunction } @Override - protected Collection<Label> getAspectLabels(Rule fromRule, Attribute attr, Label toLabel, + protected Collection<Label> getAspectLabels( + Rule fromRule, + Attribute attr, + Label toLabel, ValueOrException2<NoSuchPackageException, NoSuchTargetException> toVal, - final Environment env) { + final Environment env) + throws InterruptedException { SkyKey packageKey = PackageValue.key(toLabel.getPackageIdentifier()); try { PackageValue pkgValue = @@ -269,14 +276,15 @@ public class TransitiveTargetFunction @Override TargetMarkerValue getTargetMarkerValue(SkyKey targetMarkerKey, Environment env) - throws NoSuchTargetException, NoSuchPackageException { + throws NoSuchTargetException, NoSuchPackageException, InterruptedException { return (TargetMarkerValue) env.getValueOrThrow( targetMarkerKey, NoSuchTargetException.class, NoSuchPackageException.class); } - private void maybeReportErrorAboutMissingEdge( - Target target, Label depLabel, NoSuchThingException e, EventHandler eventHandler) { + private static void maybeReportErrorAboutMissingEdge( + Target target, Label depLabel, NoSuchThingException e, EventHandler eventHandler) + throws InterruptedException { if (e instanceof NoSuchTargetException) { NoSuchTargetException nste = (NoSuchTargetException) e; if (depLabel.equals(nste.getLabel())) { diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTraversalFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTraversalFunction.java index 1852793e70..0a85af09be 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTraversalFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTraversalFunction.java @@ -29,10 +29,8 @@ import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; import com.google.devtools.build.skyframe.ValueOrException2; - import java.util.Collection; import java.util.Map.Entry; - import javax.annotation.Nullable; /** @@ -117,7 +115,7 @@ public class TransitiveTraversalFunction @Override TargetMarkerValue getTargetMarkerValue(SkyKey targetMarkerKey, Environment env) - throws NoSuchTargetException, NoSuchPackageException { + throws NoSuchTargetException, NoSuchPackageException, InterruptedException { return TargetMarkerFunction.computeTargetMarkerValue(targetMarkerKey, env); } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceStatusFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceStatusFunction.java index 4cd9099ec2..12b36a4a31 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceStatusFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceStatusFunction.java @@ -25,7 +25,7 @@ public class WorkspaceStatusFunction implements SkyFunction { } @Override - public SkyValue compute(SkyKey skyKey, Environment env) { + public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { Preconditions.checkState( WorkspaceStatusValue.SKY_KEY.equals(skyKey), WorkspaceStatusValue.SKY_KEY); diff --git a/src/main/java/com/google/devtools/build/skyframe/AbstractSkyFunctionEnvironment.java b/src/main/java/com/google/devtools/build/skyframe/AbstractSkyFunctionEnvironment.java index a91fdbf722..a4954e9077 100644 --- a/src/main/java/com/google/devtools/build/skyframe/AbstractSkyFunctionEnvironment.java +++ b/src/main/java/com/google/devtools/build/skyframe/AbstractSkyFunctionEnvironment.java @@ -18,11 +18,9 @@ import com.google.common.base.Function; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import com.google.devtools.build.skyframe.ValueOrExceptionUtils.BottomException; - import java.util.Collections; import java.util.Map; import java.util.Set; - import javax.annotation.Nullable; /** @@ -32,14 +30,16 @@ import javax.annotation.Nullable; @VisibleForTesting public abstract class AbstractSkyFunctionEnvironment implements SkyFunction.Environment { protected boolean valuesMissing = false; - private <E extends Exception> ValueOrException<E> getValueOrException(SkyKey depKey, - Class<E> exceptionClass) { + private <E extends Exception> ValueOrException<E> getValueOrException( + SkyKey depKey, Class<E> exceptionClass) throws InterruptedException { return ValueOrExceptionUtils.downconvert( getValueOrException(depKey, exceptionClass, BottomException.class), exceptionClass); } - private <E1 extends Exception, E2 extends Exception> ValueOrException2<E1, E2> - getValueOrException(SkyKey depKey, Class<E1> exceptionClass1, Class<E2> exceptionClass2) { + private <E1 extends Exception, E2 extends Exception> + ValueOrException2<E1, E2> getValueOrException( + SkyKey depKey, Class<E1> exceptionClass1, Class<E2> exceptionClass2) + throws InterruptedException { return ValueOrExceptionUtils.downconvert(getValueOrException(depKey, exceptionClass1, exceptionClass2, BottomException.class), exceptionClass1, exceptionClass2); } @@ -49,7 +49,8 @@ public abstract class AbstractSkyFunctionEnvironment implements SkyFunction.Envi SkyKey depKey, Class<E1> exceptionClass1, Class<E2> exceptionClass2, - Class<E3> exceptionClass3) { + Class<E3> exceptionClass3) + throws InterruptedException { return ValueOrExceptionUtils.downconvert( getValueOrException(depKey, exceptionClass1, exceptionClass2, exceptionClass3, BottomException.class), @@ -64,7 +65,8 @@ public abstract class AbstractSkyFunctionEnvironment implements SkyFunction.Envi Class<E1> exceptionClass1, Class<E2> exceptionClass2, Class<E3> exceptionClass3, - Class<E4> exceptionClass4) { + Class<E4> exceptionClass4) + throws InterruptedException { return ValueOrExceptionUtils.downconvert( getValueOrException(depKey, exceptionClass1, exceptionClass2, exceptionClass3, exceptionClass4, BottomException.class), @@ -74,15 +76,20 @@ public abstract class AbstractSkyFunctionEnvironment implements SkyFunction.Envi exceptionClass4); } - private <E1 extends Exception, E2 extends Exception, E3 extends Exception, - E4 extends Exception, E5 extends Exception> + private < + E1 extends Exception, + E2 extends Exception, + E3 extends Exception, + E4 extends Exception, + E5 extends Exception> ValueOrException5<E1, E2, E3, E4, E5> getValueOrException( SkyKey depKey, Class<E1> exceptionClass1, Class<E2> exceptionClass2, Class<E3> exceptionClass3, Class<E4> exceptionClass4, - Class<E5> exceptionClass5) { + Class<E5> exceptionClass5) + throws InterruptedException { return getValueOrExceptions( ImmutableSet.of(depKey), exceptionClass1, @@ -92,7 +99,11 @@ public abstract class AbstractSkyFunctionEnvironment implements SkyFunction.Envi exceptionClass5).get(depKey); } - private <E1 extends Exception, E2 extends Exception, E3 extends Exception, E4 extends Exception, + private < + E1 extends Exception, + E2 extends Exception, + E3 extends Exception, + E4 extends Exception, E5 extends Exception> Map<SkyKey, ValueOrException5<E1, E2, E3, E4, E5>> getValueOrExceptions( Set<SkyKey> depKeys, @@ -100,7 +111,8 @@ public abstract class AbstractSkyFunctionEnvironment implements SkyFunction.Envi final Class<E2> exceptionClass2, final Class<E3> exceptionClass3, final Class<E4> exceptionClass4, - final Class<E5> exceptionClass5) { + final Class<E5> exceptionClass5) + throws InterruptedException { SkyFunctionException.validateExceptionType(exceptionClass1); SkyFunctionException.validateExceptionType(exceptionClass2); SkyFunctionException.validateExceptionType(exceptionClass3); @@ -158,11 +170,11 @@ public abstract class AbstractSkyFunctionEnvironment implements SkyFunction.Envi /** Implementations should set {@link #valuesMissing} as necessary. */ protected abstract Map<SkyKey, ValueOrUntypedException> getValueOrUntypedExceptions( - Set<SkyKey> depKeys); + Set<SkyKey> depKeys) throws InterruptedException; @Override @Nullable - public SkyValue getValue(SkyKey depKey) { + public SkyValue getValue(SkyKey depKey) throws InterruptedException { try { return getValueOrThrow(depKey, BottomException.class); } catch (BottomException e) { @@ -173,16 +185,15 @@ public abstract class AbstractSkyFunctionEnvironment implements SkyFunction.Envi @Override @Nullable public <E extends Exception> SkyValue getValueOrThrow(SkyKey depKey, Class<E> exceptionClass) - throws E { + throws E, InterruptedException { return getValueOrException(depKey, exceptionClass).get(); } @Override @Nullable public <E1 extends Exception, E2 extends Exception> SkyValue getValueOrThrow( - SkyKey depKey, - Class<E1> exceptionClass1, - Class<E2> exceptionClass2) throws E1, E2 { + SkyKey depKey, Class<E1> exceptionClass1, Class<E2> exceptionClass2) + throws E1, E2, InterruptedException { return getValueOrException(depKey, exceptionClass1, exceptionClass2).get(); } @@ -193,7 +204,8 @@ public abstract class AbstractSkyFunctionEnvironment implements SkyFunction.Envi SkyKey depKey, Class<E1> exceptionClass1, Class<E2> exceptionClass2, - Class<E3> exceptionClass3) throws E1, E2, E3 { + Class<E3> exceptionClass3) + throws E1, E2, E3, InterruptedException { return getValueOrException(depKey, exceptionClass1, exceptionClass2, exceptionClass3).get(); } @@ -204,7 +216,8 @@ public abstract class AbstractSkyFunctionEnvironment implements SkyFunction.Envi Class<E1> exceptionClass1, Class<E2> exceptionClass2, Class<E3> exceptionClass3, - Class<E4> exceptionClass4) throws E1, E2, E3, E4 { + Class<E4> exceptionClass4) + throws E1, E2, E3, E4, InterruptedException { return getValueOrException( depKey, exceptionClass1, @@ -214,7 +227,11 @@ public abstract class AbstractSkyFunctionEnvironment implements SkyFunction.Envi } @Override - public <E1 extends Exception, E2 extends Exception, E3 extends Exception, E4 extends Exception, + public < + E1 extends Exception, + E2 extends Exception, + E3 extends Exception, + E4 extends Exception, E5 extends Exception> SkyValue getValueOrThrow( SkyKey depKey, @@ -222,8 +239,8 @@ public abstract class AbstractSkyFunctionEnvironment implements SkyFunction.Envi Class<E2> exceptionClass2, Class<E3> exceptionClass3, Class<E4> exceptionClass4, - Class<E5> exceptionClass5 - ) throws E1, E2, E3, E4, E5 { + Class<E5> exceptionClass5) + throws E1, E2, E3, E4, E5, InterruptedException { return getValueOrException( depKey, exceptionClass1, @@ -234,14 +251,14 @@ public abstract class AbstractSkyFunctionEnvironment implements SkyFunction.Envi } @Override - public Map<SkyKey, SkyValue> getValues(Iterable<SkyKey> depKeys) { + public Map<SkyKey, SkyValue> getValues(Iterable<SkyKey> depKeys) throws InterruptedException { return Maps.transformValues(getValuesOrThrow(depKeys, BottomException.class), GET_VALUE_FROM_VOE); } @Override public <E extends Exception> Map<SkyKey, ValueOrException<E>> getValuesOrThrow( - Iterable<SkyKey> depKeys, Class<E> exceptionClass) { + Iterable<SkyKey> depKeys, Class<E> exceptionClass) throws InterruptedException { return Maps.transformValues( getValuesOrThrow(depKeys, exceptionClass, BottomException.class), makeSafeDowncastToVOEFunction(exceptionClass)); @@ -250,9 +267,8 @@ public abstract class AbstractSkyFunctionEnvironment implements SkyFunction.Envi @Override public <E1 extends Exception, E2 extends Exception> Map<SkyKey, ValueOrException2<E1, E2>> getValuesOrThrow( - Iterable<SkyKey> depKeys, - Class<E1> exceptionClass1, - Class<E2> exceptionClass2) { + Iterable<SkyKey> depKeys, Class<E1> exceptionClass1, Class<E2> exceptionClass2) + throws InterruptedException { return Maps.transformValues( getValuesOrThrow(depKeys, exceptionClass1, exceptionClass2, BottomException.class), makeSafeDowncastToVOE2Function(exceptionClass1, exceptionClass2)); @@ -264,7 +280,8 @@ public abstract class AbstractSkyFunctionEnvironment implements SkyFunction.Envi Iterable<SkyKey> depKeys, Class<E1> exceptionClass1, Class<E2> exceptionClass2, - Class<E3> exceptionClass3) { + Class<E3> exceptionClass3) + throws InterruptedException { return Maps.transformValues( getValuesOrThrow(depKeys, exceptionClass1, exceptionClass2, exceptionClass3, BottomException.class), @@ -278,7 +295,8 @@ public abstract class AbstractSkyFunctionEnvironment implements SkyFunction.Envi Class<E1> exceptionClass1, Class<E2> exceptionClass2, Class<E3> exceptionClass3, - Class<E4> exceptionClass4) { + Class<E4> exceptionClass4) + throws InterruptedException { return Maps.transformValues( getValuesOrThrow(depKeys, exceptionClass1, exceptionClass2, exceptionClass3, exceptionClass4, BottomException.class), @@ -287,15 +305,20 @@ public abstract class AbstractSkyFunctionEnvironment implements SkyFunction.Envi } @Override - public <E1 extends Exception, E2 extends Exception, E3 extends Exception, - E4 extends Exception, E5 extends Exception> + public < + E1 extends Exception, + E2 extends Exception, + E3 extends Exception, + E4 extends Exception, + E5 extends Exception> Map<SkyKey, ValueOrException5<E1, E2, E3, E4, E5>> getValuesOrThrow( Iterable<SkyKey> depKeys, Class<E1> exceptionClass1, Class<E2> exceptionClass2, Class<E3> exceptionClass3, Class<E4> exceptionClass4, - Class<E5> exceptionClass5) { + Class<E5> exceptionClass5) + throws InterruptedException { Set<SkyKey> keys = ImmutableSet.copyOf(depKeys); Map<SkyKey, ValueOrException5<E1, E2, E3, E4, E5>> result = getValueOrExceptions(keys, exceptionClass1, exceptionClass2, exceptionClass3, exceptionClass4, exceptionClass5); diff --git a/src/main/java/com/google/devtools/build/skyframe/BuildDriver.java b/src/main/java/com/google/devtools/build/skyframe/BuildDriver.java index 3172b4a133..4ebe244ea0 100644 --- a/src/main/java/com/google/devtools/build/skyframe/BuildDriver.java +++ b/src/main/java/com/google/devtools/build/skyframe/BuildDriver.java @@ -17,7 +17,6 @@ package com.google.devtools.build.skyframe; import com.google.devtools.build.lib.events.EventHandler; import com.google.devtools.build.lib.util.AbruptExitException; import com.google.devtools.common.options.OptionsClassProvider; - import javax.annotation.Nullable; /** A BuildDriver wraps a MemoizingEvaluator, passing along the proper Version. */ @@ -41,11 +40,11 @@ public interface BuildDriver { MemoizingEvaluator getGraphForTesting(); @Nullable - SkyValue getExistingValueForTesting(SkyKey key); + SkyValue getExistingValueForTesting(SkyKey key) throws InterruptedException; @Nullable - ErrorInfo getExistingErrorForTesting(SkyKey key); + ErrorInfo getExistingErrorForTesting(SkyKey key) throws InterruptedException; @Nullable - NodeEntry getEntryForTesting(SkyKey key); + NodeEntry getEntryForTesting(SkyKey key) throws InterruptedException; } diff --git a/src/main/java/com/google/devtools/build/skyframe/DelegatingNodeEntry.java b/src/main/java/com/google/devtools/build/skyframe/DelegatingNodeEntry.java index d714924e29..6bf77ec4e0 100644 --- a/src/main/java/com/google/devtools/build/skyframe/DelegatingNodeEntry.java +++ b/src/main/java/com/google/devtools/build/skyframe/DelegatingNodeEntry.java @@ -15,10 +15,8 @@ package com.google.devtools.build.skyframe; import com.google.devtools.build.lib.util.GroupedList; import com.google.devtools.build.lib.util.GroupedList.GroupedListHelper; - import java.util.Collection; import java.util.Set; - import javax.annotation.Nullable; /** Convenience class for {@link NodeEntry} implementations that delegate many operations. */ @@ -35,23 +33,23 @@ public abstract class DelegatingNodeEntry implements NodeEntry { } @Override - public SkyValue getValue() { + public SkyValue getValue() throws InterruptedException { return getDelegate().getValue(); } @Override - public SkyValue getValueMaybeWithMetadata() { + public SkyValue getValueMaybeWithMetadata() throws InterruptedException { return getDelegate().getValueMaybeWithMetadata(); } @Override - public SkyValue toValue() { + public SkyValue toValue() throws InterruptedException { return getDelegate().toValue(); } @Nullable @Override - public ErrorInfo getErrorInfo() { + public ErrorInfo getErrorInfo() throws InterruptedException { return getDelegate().getErrorInfo(); } @@ -61,7 +59,7 @@ public abstract class DelegatingNodeEntry implements NodeEntry { } @Override - public Set<SkyKey> setValue(SkyValue value, Version version) { + public Set<SkyKey> setValue(SkyValue value, Version version) throws InterruptedException { return getDelegate().setValue(value, version); } @@ -86,7 +84,7 @@ public abstract class DelegatingNodeEntry implements NodeEntry { } @Override - public Set<SkyKey> markClean() { + public Set<SkyKey> markClean() throws InterruptedException { return getDelegate().markClean(); } @@ -156,7 +154,7 @@ public abstract class DelegatingNodeEntry implements NodeEntry { } @Override - public Iterable<SkyKey> getDirectDeps() { + public Iterable<SkyKey> getDirectDeps() throws InterruptedException { return getDelegate().getDirectDeps(); } @@ -187,7 +185,7 @@ public abstract class DelegatingNodeEntry implements NodeEntry { @Override @Nullable - public MarkedDirtyResult markDirty(boolean isChanged) { + public MarkedDirtyResult markDirty(boolean isChanged) throws InterruptedException { return getThinDelegate().markDirty(isChanged); } diff --git a/src/main/java/com/google/devtools/build/skyframe/DelegatingWalkableGraph.java b/src/main/java/com/google/devtools/build/skyframe/DelegatingWalkableGraph.java index c56bf55132..5c22a05de2 100644 --- a/src/main/java/com/google/devtools/build/skyframe/DelegatingWalkableGraph.java +++ b/src/main/java/com/google/devtools/build/skyframe/DelegatingWalkableGraph.java @@ -13,8 +13,6 @@ // limitations under the License. package com.google.devtools.build.skyframe; -import com.google.common.base.Function; -import com.google.common.base.Predicates; import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; import com.google.devtools.build.lib.util.Preconditions; @@ -22,7 +20,6 @@ import com.google.devtools.build.skyframe.QueryableGraph.Reason; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; - import javax.annotation.Nullable; /** @@ -35,7 +32,7 @@ public class DelegatingWalkableGraph implements WalkableGraph { this.graph = graph; } - private NodeEntry getEntryForValue(SkyKey key) { + private NodeEntry getEntryForValue(SkyKey key) throws InterruptedException { NodeEntry entry = Preconditions.checkNotNull( graph.getBatch(null, Reason.WALKABLE_GRAPH_VALUE, ImmutableList.of(key)).get(key), @@ -45,7 +42,7 @@ public class DelegatingWalkableGraph implements WalkableGraph { } @Override - public boolean exists(SkyKey key) { + public boolean exists(SkyKey key) throws InterruptedException { NodeEntry entry = graph.getBatch(null, Reason.EXISTENCE_CHECKING, ImmutableList.of(key)).get(key); return entry != null && entry.isDone(); @@ -53,32 +50,35 @@ public class DelegatingWalkableGraph implements WalkableGraph { @Nullable @Override - public SkyValue getValue(SkyKey key) { + public SkyValue getValue(SkyKey key) throws InterruptedException { return getEntryForValue(key).getValue(); } - private static final Function<NodeEntry, SkyValue> GET_SKY_VALUE_FUNCTION = - new Function<NodeEntry, SkyValue>() { - @Nullable - @Override - public SkyValue apply(NodeEntry entry) { - return entry.isDone() ? entry.getValue() : null; - } - }; + private static SkyValue getValue(NodeEntry entry) throws InterruptedException { + return entry.isDone() ? entry.getValue() : null; + } @Override - public Map<SkyKey, SkyValue> getSuccessfulValues(Iterable<SkyKey> keys) { - return Maps.filterValues( - Maps.transformValues( - graph.getBatch(null, Reason.WALKABLE_GRAPH_VALUE, keys), - GET_SKY_VALUE_FUNCTION), - Predicates.notNull()); + public Map<SkyKey, SkyValue> getSuccessfulValues(Iterable<SkyKey> keys) + throws InterruptedException { + Map<SkyKey, ? extends NodeEntry> batchGet = + graph.getBatch(null, Reason.WALKABLE_GRAPH_VALUE, keys); + Map<SkyKey, SkyValue> result = Maps.newHashMapWithExpectedSize(batchGet.size()); + for (Entry<SkyKey, ? extends NodeEntry> entryPair : batchGet.entrySet()) { + SkyValue value = getValue(entryPair.getValue()); + if (value != null) { + result.put(entryPair.getKey(), value); + } + } + return result; } @Override - public Map<SkyKey, Exception> getMissingAndExceptions(Iterable<SkyKey> keys) { + public Map<SkyKey, Exception> getMissingAndExceptions(Iterable<SkyKey> keys) + throws InterruptedException { Map<SkyKey, Exception> result = new HashMap<>(); - Map<SkyKey, NodeEntry> graphResult = graph.getBatch(null, Reason.WALKABLE_GRAPH_VALUE, keys); + Map<SkyKey, ? extends NodeEntry> graphResult = + graph.getBatch(null, Reason.WALKABLE_GRAPH_VALUE, keys); for (SkyKey key : keys) { NodeEntry nodeEntry = graphResult.get(key); if (nodeEntry == null || !nodeEntry.isDone()) { @@ -95,16 +95,18 @@ public class DelegatingWalkableGraph implements WalkableGraph { @Nullable @Override - public Exception getException(SkyKey key) { + public Exception getException(SkyKey key) throws InterruptedException { ErrorInfo errorInfo = getEntryForValue(key).getErrorInfo(); return errorInfo == null ? null : errorInfo.getException(); } @Override - public Map<SkyKey, Iterable<SkyKey>> getDirectDeps(Iterable<SkyKey> keys) { - Map<SkyKey, NodeEntry> entries = graph.getBatch(null, Reason.WALKABLE_GRAPH_DEPS, keys); + public Map<SkyKey, Iterable<SkyKey>> getDirectDeps(Iterable<SkyKey> keys) + throws InterruptedException { + Map<SkyKey, ? extends NodeEntry> entries = + graph.getBatch(null, Reason.WALKABLE_GRAPH_DEPS, keys); Map<SkyKey, Iterable<SkyKey>> result = new HashMap<>(entries.size()); - for (Entry<SkyKey, NodeEntry> entry : entries.entrySet()) { + for (Entry<SkyKey, ? extends NodeEntry> entry : entries.entrySet()) { Preconditions.checkState(entry.getValue().isDone(), entry); result.put(entry.getKey(), entry.getValue().getDirectDeps()); } @@ -112,10 +114,12 @@ public class DelegatingWalkableGraph implements WalkableGraph { } @Override - public Map<SkyKey, Iterable<SkyKey>> getReverseDeps(Iterable<SkyKey> keys) { - Map<SkyKey, NodeEntry> entries = graph.getBatch(null, Reason.WALKABLE_GRAPH_RDEPS, keys); + public Map<SkyKey, Iterable<SkyKey>> getReverseDeps(Iterable<SkyKey> keys) + throws InterruptedException { + Map<SkyKey, ? extends NodeEntry> entries = + graph.getBatch(null, Reason.WALKABLE_GRAPH_RDEPS, keys); Map<SkyKey, Iterable<SkyKey>> result = new HashMap<>(entries.size()); - for (Entry<SkyKey, NodeEntry> entry : entries.entrySet()) { + for (Entry<SkyKey, ? extends NodeEntry> entry : entries.entrySet()) { Preconditions.checkState(entry.getValue().isDone(), entry); result.put(entry.getKey(), entry.getValue().getReverseDeps()); } diff --git a/src/main/java/com/google/devtools/build/skyframe/DirtyBuildingState.java b/src/main/java/com/google/devtools/build/skyframe/DirtyBuildingState.java index e8c5a464e3..a476275d00 100644 --- a/src/main/java/com/google/devtools/build/skyframe/DirtyBuildingState.java +++ b/src/main/java/com/google/devtools/build/skyframe/DirtyBuildingState.java @@ -18,7 +18,6 @@ import com.google.common.collect.ImmutableSet; import com.google.devtools.build.lib.util.GroupedList; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.skyframe.NodeEntry.DirtyState; - import java.util.Collection; import java.util.Set; @@ -48,7 +47,7 @@ public abstract class DirtyBuildingState extends BuildingState { protected final GroupedList<SkyKey> lastBuildDirectDeps; /** The value of the node the last time it was built. */ - protected abstract SkyValue getLastBuildValue(); + protected abstract SkyValue getLastBuildValue() throws InterruptedException; /** * Group of children to be checked next in the process of determining if this entry needs to be @@ -144,7 +143,7 @@ public abstract class DirtyBuildingState extends BuildingState { * <p>Changes in direct deps do <i>not</i> force this to return false. Only the value is * considered. */ - final boolean unchangedFromLastBuild(SkyValue newValue) { + final boolean unchangedFromLastBuild(SkyValue newValue) throws InterruptedException { checkFinishedBuildingWhenAboutToSetValue(); return !(newValue instanceof NotComparableSkyValue) && getLastBuildValue().equals(newValue); } diff --git a/src/main/java/com/google/devtools/build/skyframe/EagerInvalidator.java b/src/main/java/com/google/devtools/build/skyframe/EagerInvalidator.java index 5dba03dc28..71537e8333 100644 --- a/src/main/java/com/google/devtools/build/skyframe/EagerInvalidator.java +++ b/src/main/java/com/google/devtools/build/skyframe/EagerInvalidator.java @@ -20,10 +20,8 @@ import com.google.devtools.build.lib.concurrent.ExecutorParams; import com.google.devtools.build.skyframe.InvalidatingNodeVisitor.DeletingNodeVisitor; import com.google.devtools.build.skyframe.InvalidatingNodeVisitor.DirtyingNodeVisitor; import com.google.devtools.build.skyframe.InvalidatingNodeVisitor.InvalidationState; - import java.util.concurrent.ExecutorService; import java.util.concurrent.ForkJoinPool; - import javax.annotation.Nullable; /** @@ -106,8 +104,7 @@ public final class EagerInvalidator { state, dirtyKeyTracker, forkJoinPool, - supportInterruptions, - errorHandler); + supportInterruptions); } /** @@ -141,8 +138,7 @@ public final class EagerInvalidator { InvalidationState state, DirtyKeyTracker dirtyKeyTracker, ForkJoinPool forkJoinPool, - boolean supportInterruptions, - ErrorHandler errorHandler) + boolean supportInterruptions) throws InterruptedException { DirtyingNodeVisitor visitor = createInvalidatingVisitorIfNeeded( @@ -153,7 +149,7 @@ public final class EagerInvalidator { dirtyKeyTracker, forkJoinPool, supportInterruptions, - errorHandler); + ErrorHandler.NullHandler.INSTANCE); if (visitor != null) { visitor.run(); } diff --git a/src/main/java/com/google/devtools/build/skyframe/EvaluableGraph.java b/src/main/java/com/google/devtools/build/skyframe/EvaluableGraph.java index 6e93ce4ce3..51ba4031f6 100644 --- a/src/main/java/com/google/devtools/build/skyframe/EvaluableGraph.java +++ b/src/main/java/com/google/devtools/build/skyframe/EvaluableGraph.java @@ -20,18 +20,21 @@ import javax.annotation.Nullable; /** * Interface between a single version of the graph and the evaluator. Supports mutation of that * single version of the graph. + * + * <p>Certain graph implementations can throw {@link InterruptedException} when trying to retrieve + * node entries. Such exceptions should not be caught locally -- they should be allowed to propagate + * up. */ @ThreadSafe interface EvaluableGraph extends QueryableGraph, DeletableGraph { /** - * Like {@link QueryableGraph#getBatch}, except it creates a new node for each key - * not already present in the graph. Thus, the returned map will have an entry for each key in - * {@code keys}. + * Like {@link QueryableGraph#getBatch}, except it creates a new node for each key not already + * present in the graph. Thus, the returned map will have an entry for each key in {@code keys}. * * @param requestor if non-{@code null}, the node on behalf of which the given {@code keys} are * being requested. * @param reason the reason the nodes are being requested. */ - Map<SkyKey, NodeEntry> createIfAbsentBatch( - @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys); + Map<SkyKey, ? extends NodeEntry> createIfAbsentBatch( + @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys) throws InterruptedException; } diff --git a/src/main/java/com/google/devtools/build/skyframe/InMemoryGraph.java b/src/main/java/com/google/devtools/build/skyframe/InMemoryGraph.java index 02735c0e8e..edb80f080c 100644 --- a/src/main/java/com/google/devtools/build/skyframe/InMemoryGraph.java +++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryGraph.java @@ -14,9 +14,22 @@ package com.google.devtools.build.skyframe; import java.util.Map; +import javax.annotation.Nullable; /** {@link ProcessableGraph} that exposes the contents of the entire graph. */ interface InMemoryGraph extends ProcessableGraph { + @Override + Map<SkyKey, ? extends NodeEntry> createIfAbsentBatch( + @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys); + + @Nullable + @Override + NodeEntry get(@Nullable SkyKey requestor, Reason reason, SkyKey key); + + @Override + Map<SkyKey, ? extends NodeEntry> getBatch( + @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys); + /** * Returns a read-only live view of the nodes in the graph. All node are included. Dirty values * include their Node value. Values in error have a null value. @@ -30,5 +43,5 @@ interface InMemoryGraph extends ProcessableGraph { Map<SkyKey, SkyValue> getDoneValues(); // Only for use by MemoizingEvaluator#delete - Map<SkyKey, NodeEntry> getAllValues(); + Map<SkyKey, ? extends NodeEntry> getAllValues(); } diff --git a/src/main/java/com/google/devtools/build/skyframe/InMemoryGraphImpl.java b/src/main/java/com/google/devtools/build/skyframe/InMemoryGraphImpl.java index eca58b3b06..b5d2472100 100644 --- a/src/main/java/com/google/devtools/build/skyframe/InMemoryGraphImpl.java +++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryGraphImpl.java @@ -32,7 +32,7 @@ import javax.annotation.Nullable; */ public class InMemoryGraphImpl implements InMemoryGraph { - protected final ConcurrentMap<SkyKey, NodeEntry> nodeMap = + protected final ConcurrentMap<SkyKey, InMemoryNodeEntry> nodeMap = new MapMaker().initialCapacity(1024).concurrencyLevel(200).makeMap(); private final boolean keepEdges; @@ -50,7 +50,7 @@ public class InMemoryGraphImpl implements InMemoryGraph { } @Override - public NodeEntry get(@Nullable SkyKey requestor, Reason reason, SkyKey skyKey) { + public InMemoryNodeEntry get(@Nullable SkyKey requestor, Reason reason, SkyKey skyKey) { return nodeMap.get(skyKey); } @@ -58,7 +58,7 @@ public class InMemoryGraphImpl implements InMemoryGraph { public Map<SkyKey, NodeEntry> getBatch(SkyKey requestor, Reason reason, Iterable<SkyKey> keys) { ImmutableMap.Builder<SkyKey, NodeEntry> builder = ImmutableMap.builder(); for (SkyKey key : keys) { - NodeEntry entry = get(null, reason, key); + InMemoryNodeEntry entry = get(null, Reason.OTHER, key); if (entry != null) { builder.put(key, entry); } @@ -66,16 +66,17 @@ public class InMemoryGraphImpl implements InMemoryGraph { return builder.build(); } - protected NodeEntry createIfAbsent(SkyKey key) { - NodeEntry newval = keepEdges ? new InMemoryNodeEntry() : new EdgelessInMemoryNodeEntry(); - NodeEntry oldval = nodeMap.putIfAbsent(key, newval); + protected InMemoryNodeEntry createIfAbsent(SkyKey key) { + InMemoryNodeEntry newval = + keepEdges ? new InMemoryNodeEntry() : new EdgelessInMemoryNodeEntry(); + InMemoryNodeEntry oldval = nodeMap.putIfAbsent(key, newval); return oldval == null ? newval : oldval; } @Override - public Map<SkyKey, NodeEntry> createIfAbsentBatch( + public Map<SkyKey, InMemoryNodeEntry> createIfAbsentBatch( @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys) { - ImmutableMap.Builder<SkyKey, NodeEntry> builder = ImmutableMap.builder(); + ImmutableMap.Builder<SkyKey, InMemoryNodeEntry> builder = ImmutableMap.builder(); for (SkyKey key : keys) { builder.put(key, createIfAbsent(key)); } @@ -87,9 +88,9 @@ public class InMemoryGraphImpl implements InMemoryGraph { return Collections.unmodifiableMap( Maps.transformValues( nodeMap, - new Function<NodeEntry, SkyValue>() { + new Function<InMemoryNodeEntry, SkyValue>() { @Override - public SkyValue apply(NodeEntry entry) { + public SkyValue apply(InMemoryNodeEntry entry) { return entry.toValue(); } })); @@ -101,9 +102,9 @@ public class InMemoryGraphImpl implements InMemoryGraph { Maps.filterValues( Maps.transformValues( nodeMap, - new Function<NodeEntry, SkyValue>() { + new Function<InMemoryNodeEntry, SkyValue>() { @Override - public SkyValue apply(NodeEntry entry) { + public SkyValue apply(InMemoryNodeEntry entry) { return entry.isDone() ? entry.getValue() : null; } }), @@ -111,12 +112,12 @@ public class InMemoryGraphImpl implements InMemoryGraph { } @Override - public Map<SkyKey, NodeEntry> getAllValues() { + public Map<SkyKey, InMemoryNodeEntry> getAllValues() { return Collections.unmodifiableMap(nodeMap); } @VisibleForTesting - protected ConcurrentMap<SkyKey, NodeEntry> getNodeMap() { + protected ConcurrentMap<SkyKey, ? extends NodeEntry> getNodeMap() { return nodeMap; } diff --git a/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java b/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java index 38604ed50d..972d020e3b 100644 --- a/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java +++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java @@ -39,7 +39,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; - import javax.annotation.Nullable; /** @@ -112,13 +111,16 @@ public final class InMemoryMemoizingEvaluator implements MemoizingEvaluator { @Override public void delete(final Predicate<SkyKey> deletePredicate) { valuesToDelete.addAll( - Maps.filterEntries(graph.getAllValues(), new Predicate<Entry<SkyKey, NodeEntry>>() { - @Override - public boolean apply(Entry<SkyKey, NodeEntry> input) { - Preconditions.checkNotNull(input.getKey(), "Null SkyKey in entry: %s", input); - return input.getValue().isDirty() || deletePredicate.apply(input.getKey()); - } - }).keySet()); + Maps.filterEntries( + graph.getAllValues(), + new Predicate<Entry<SkyKey, ? extends NodeEntry>>() { + @Override + public boolean apply(Entry<SkyKey, ? extends NodeEntry> input) { + Preconditions.checkNotNull(input.getKey(), "Null SkyKey in entry: %s", input); + return input.getValue().isDirty() || deletePredicate.apply(input.getKey()); + } + }) + .keySet()); } @Override @@ -209,12 +211,18 @@ public final class InMemoryMemoizingEvaluator implements MemoizingEvaluator { SkyValue newValue = entry.getValue(); NodeEntry prevEntry = graph.get(null, Reason.OTHER, key); if (prevEntry != null && prevEntry.isDone()) { - Iterable<SkyKey> directDeps = prevEntry.getDirectDeps(); - Preconditions.checkState(Iterables.isEmpty(directDeps), - "existing entry for %s has deps: %s", key, directDeps); - if (newValue.equals(prevEntry.getValue()) - && !valuesToDirty.contains(key) && !valuesToDelete.contains(key)) { - it.remove(); + try { + Iterable<SkyKey> directDeps = prevEntry.getDirectDeps(); + Preconditions.checkState( + Iterables.isEmpty(directDeps), "existing entry for %s has deps: %s", key, directDeps); + if (newValue.equals(prevEntry.getValue()) + && !valuesToDirty.contains(key) + && !valuesToDelete.contains(key)) { + it.remove(); + } + } catch (InterruptedException e) { + throw new IllegalStateException( + "InMemoryGraph does not throw: " + entry + ", " + prevEntry, e); } } } @@ -227,7 +235,11 @@ public final class InMemoryMemoizingEvaluator implements MemoizingEvaluator { if (valuesToInject.isEmpty()) { return; } - ParallelEvaluator.injectValues(valuesToInject, version, graph, dirtyKeyTracker); + try { + ParallelEvaluator.injectValues(valuesToInject, version, graph, dirtyKeyTracker); + } catch (InterruptedException e) { + throw new IllegalStateException("InMemoryGraph doesn't throw interrupts", e); + } // Start with a new map to avoid bloat since clear() does not downsize the map. valuesToInject = new HashMap<>(); } @@ -268,13 +280,21 @@ public final class InMemoryMemoizingEvaluator implements MemoizingEvaluator { @Override @Nullable public SkyValue getExistingValueForTesting(SkyKey key) { NodeEntry entry = getExistingEntryForTesting(key); - return isDone(entry) ? entry.getValue() : null; + try { + return isDone(entry) ? entry.getValue() : null; + } catch (InterruptedException e) { + throw new IllegalStateException("InMemoryGraph does not throw" + key + ", " + entry, e); + } } @Override @Nullable public ErrorInfo getExistingErrorForTesting(SkyKey key) { NodeEntry entry = getExistingEntryForTesting(key); - return isDone(entry) ? entry.getErrorInfo() : null; + try { + return isDone(entry) ? entry.getErrorInfo() : null; + } catch (InterruptedException e) { + throw new IllegalStateException("InMemoryGraph does not throw" + key + ", " + entry, e); + } } @Nullable @@ -300,7 +320,11 @@ public final class InMemoryMemoizingEvaluator implements MemoizingEvaluator { for (NodeEntry entry : graph.getAllValues().values()) { nodes++; if (entry.isDone()) { - edges += Iterables.size(entry.getDirectDeps()); + try { + edges += Iterables.size(entry.getDirectDeps()); + } catch (InterruptedException e) { + throw new IllegalStateException("InMemoryGraph doesn't throw: " + entry, e); + } } } out.println("Node count: " + nodes); @@ -315,14 +339,18 @@ public final class InMemoryMemoizingEvaluator implements MemoizingEvaluator { } }; - for (Entry<SkyKey, NodeEntry> mapPair : graph.getAllValues().entrySet()) { + for (Entry<SkyKey, ? extends NodeEntry> mapPair : graph.getAllValues().entrySet()) { SkyKey key = mapPair.getKey(); NodeEntry entry = mapPair.getValue(); if (entry.isDone()) { out.print(keyFormatter.apply(key)); out.print("|"); - out.println(Joiner.on('|').join( - Iterables.transform(entry.getDirectDeps(), keyFormatter))); + try { + out.println( + Joiner.on('|').join(Iterables.transform(entry.getDirectDeps(), keyFormatter))); + } catch (InterruptedException e) { + throw new IllegalStateException("InMemoryGraph doesn't throw: " + entry, e); + } } } } diff --git a/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java b/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java index 9ba0dbeee3..82d692201d 100644 --- a/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java +++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java @@ -21,11 +21,9 @@ import com.google.common.collect.Iterables; import com.google.devtools.build.lib.util.GroupedList; import com.google.devtools.build.lib.util.GroupedList.GroupedListHelper; import com.google.devtools.build.lib.util.Preconditions; - import java.util.Collection; import java.util.List; import java.util.Set; - import javax.annotation.Nullable; /** @@ -163,9 +161,13 @@ public class InMemoryNodeEntry implements NodeEntry { if (isDone()) { return getErrorInfo() == null ? getValue() : null; } else if (isChanged() || isDirty()) { - return (getDirtyBuildingState().getLastBuildValue() == null) - ? null - : ValueWithMetadata.justValue(getDirtyBuildingState().getLastBuildValue()); + SkyValue lastBuildValue = null; + try { + lastBuildValue = getDirtyBuildingState().getLastBuildValue(); + } catch (InterruptedException e) { + throw new IllegalStateException("Interruption unexpected: " + this, e); + } + return (lastBuildValue == null) ? null : ValueWithMetadata.justValue(lastBuildValue); } else { // Value has not finished evaluating. It's probably about to be cleaned from the graph. return null; @@ -230,7 +232,8 @@ public class InMemoryNodeEntry implements NodeEntry { } @Override - public synchronized Set<SkyKey> setValue(SkyValue value, Version version) { + public synchronized Set<SkyKey> setValue(SkyValue value, Version version) + throws InterruptedException { Preconditions.checkState(isReady(), "%s %s", this, value); // This check may need to be removed when we move to a non-linear versioning sequence. Preconditions.checkState( @@ -370,7 +373,7 @@ public class InMemoryNodeEntry implements NodeEntry { } @Override - public synchronized Set<SkyKey> markClean() { + public synchronized Set<SkyKey> markClean() throws InterruptedException { this.value = getDirtyBuildingState().getLastBuildValue(); Preconditions.checkState(isReady(), "Should be ready when clean: %s", this); Preconditions.checkState( diff --git a/src/main/java/com/google/devtools/build/skyframe/InterruptibleSupplier.java b/src/main/java/com/google/devtools/build/skyframe/InterruptibleSupplier.java new file mode 100644 index 0000000000..5f4ab55749 --- /dev/null +++ b/src/main/java/com/google/devtools/build/skyframe/InterruptibleSupplier.java @@ -0,0 +1,63 @@ +// Copyright 2016 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.skyframe; + +import javax.annotation.Nullable; + +/** Supplier that may throw {@link InterruptedException} when value is retrieved. */ +public interface InterruptibleSupplier<T> { + T get() throws InterruptedException; + + class Instance<T> implements InterruptibleSupplier<T> { + private final T instance; + + public Instance(T instance) { + this.instance = instance; + } + + @Override + public T get() { + return instance; + } + } + + class Memoize<T> implements InterruptibleSupplier<T> { + private final InterruptibleSupplier<T> delegate; + private @Nullable T value = null; + + private Memoize(InterruptibleSupplier<T> delegate) { + this.delegate = delegate; + } + + public static <S> InterruptibleSupplier<S> of(InterruptibleSupplier<S> delegate) { + if (delegate instanceof Memoize) { + return delegate; + } + return new Memoize<>(delegate); + } + + @Override + public T get() throws InterruptedException { + if (value != null) { + return value; + } + synchronized (this) { + if (value == null) { + value = delegate.get(); + } + } + return value; + } + } +} diff --git a/src/main/java/com/google/devtools/build/skyframe/InvalidatingNodeVisitor.java b/src/main/java/com/google/devtools/build/skyframe/InvalidatingNodeVisitor.java index 543ccf4c42..096fc2d49b 100644 --- a/src/main/java/com/google/devtools/build/skyframe/InvalidatingNodeVisitor.java +++ b/src/main/java/com/google/devtools/build/skyframe/InvalidatingNodeVisitor.java @@ -22,7 +22,6 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Sets; import com.google.devtools.build.lib.concurrent.AbstractQueueVisitor; import com.google.devtools.build.lib.concurrent.ErrorClassifier; -import com.google.devtools.build.lib.concurrent.ErrorHandler; import com.google.devtools.build.lib.concurrent.ExecutorParams; import com.google.devtools.build.lib.concurrent.ForkJoinQuiescingExecutor; import com.google.devtools.build.lib.concurrent.QuiescingExecutor; @@ -31,7 +30,6 @@ import com.google.devtools.build.lib.util.Pair; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.skyframe.QueryableGraph.Reason; import com.google.devtools.build.skyframe.ThinNodeEntry.MarkedDirtyResult; - import java.util.ArrayList; import java.util.Collections; import java.util.Map; @@ -41,7 +39,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.TimeUnit; - import javax.annotation.Nullable; /** @@ -113,8 +110,7 @@ public abstract class InvalidatingNodeVisitor<TGraph extends QueryableGraph> { /*failFastOnException=*/ true, "skyframe-invalidator", executorFactory, - errorClassifier, - ErrorHandler.NullHandler.INSTANCE); + errorClassifier); this.graph = Preconditions.checkNotNull(graph); this.invalidationReceiver = invalidationReceiver; this.dirtyKeyTracker = Preconditions.checkNotNull(dirtyKeyTracker); @@ -126,9 +122,8 @@ public abstract class InvalidatingNodeVisitor<TGraph extends QueryableGraph> { @Nullable EvaluationProgressReceiver invalidationReceiver, InvalidationState state, DirtyKeyTracker dirtyKeyTracker, - ForkJoinPool forkJoinPool, - ErrorHandler errorHandler) { - this.executor = new ForkJoinQuiescingExecutor(forkJoinPool, errorClassifier, errorHandler); + ForkJoinPool forkJoinPool) { + this.executor = new ForkJoinQuiescingExecutor(forkJoinPool, errorClassifier); this.graph = Preconditions.checkNotNull(graph); this.invalidationReceiver = invalidationReceiver; this.dirtyKeyTracker = Preconditions.checkNotNull(dirtyKeyTracker); @@ -270,7 +265,7 @@ public abstract class InvalidatingNodeVisitor<TGraph extends QueryableGraph> { for (SkyKey key : unvisitedKeys) { pendingVisitations.add(Pair.of(key, InvalidationType.DELETED)); } - final Map<SkyKey, NodeEntry> entries = + final Map<SkyKey, ? extends NodeEntry> entries = graph.getBatch(null, Reason.INVALIDATION, unvisitedKeys); for (final SkyKey key : unvisitedKeys) { executor.execute( @@ -303,13 +298,23 @@ public abstract class InvalidatingNodeVisitor<TGraph extends QueryableGraph> { entry.isDone() ? ImmutableSet.<SkyKey>of() : entry.getTemporaryDirectDeps().toSet(); - Iterable<SkyKey> directDeps = - entry.isDone() - ? entry.getDirectDeps() - : entry.getAllDirectDepsForIncompleteNode(); - Map<SkyKey, NodeEntry> depMap = + Iterable<SkyKey> directDeps; + try { + directDeps = + entry.isDone() + ? entry.getDirectDeps() + : entry.getAllDirectDepsForIncompleteNode(); + } catch (InterruptedException e) { + throw new IllegalStateException( + "Deletion cannot happen on a graph that may have blocking operations: " + + key + + ", " + + entry, + e); + } + Map<SkyKey, ? extends NodeEntry> depMap = graph.getBatch(key, Reason.INVALIDATION, directDeps); - for (Map.Entry<SkyKey, NodeEntry> directDepEntry : depMap.entrySet()) { + for (Map.Entry<SkyKey, ? extends NodeEntry> directDepEntry : depMap.entrySet()) { NodeEntry dep = directDepEntry.getValue(); if (dep != null) { if (dep.isDone() || !signalingDeps.contains(directDepEntry.getKey())) { @@ -373,9 +378,8 @@ public abstract class InvalidatingNodeVisitor<TGraph extends QueryableGraph> { InvalidationState state, DirtyKeyTracker dirtyKeyTracker, ForkJoinPool forkJoinPool, - boolean supportInterruptions, - ErrorHandler errorHandler) { - super(graph, invalidationReceiver, state, dirtyKeyTracker, forkJoinPool, errorHandler); + boolean supportInterruptions) { + super(graph, invalidationReceiver, state, dirtyKeyTracker, forkJoinPool); this.supportInterruptions = supportInterruptions; } @@ -435,8 +439,16 @@ public abstract class InvalidatingNodeVisitor<TGraph extends QueryableGraph> { pendingVisitations.add(Pair.of(key, invalidationType)); } } - final Map<SkyKey, ? extends ThinNodeEntry> entries = - graph.getBatch(null, Reason.INVALIDATION, keysToGet); + final Map<SkyKey, ? extends ThinNodeEntry> entries; + try { + entries = graph.getBatch(null, Reason.INVALIDATION, keysToGet); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + // This can only happen if the main thread has been interrupted, and so the + // AbstractQueueVisitor is shutting down. We haven't yet removed the pending visitations, so + // we can resume next time. + return; + } if (enqueueingKeyForExistenceCheck != null && entries.size() != keysToGet.size()) { Set<SkyKey> missingKeys = Sets.difference(ImmutableSet.copyOf(keysToGet), entries.keySet()); throw new IllegalStateException( @@ -471,7 +483,16 @@ public abstract class InvalidatingNodeVisitor<TGraph extends QueryableGraph> { // method. // Any exception thrown should be unrecoverable. // This entry remains in the graph in this dirty state until it is re-evaluated. - MarkedDirtyResult markedDirtyResult = entry.markDirty(isChanged); + MarkedDirtyResult markedDirtyResult = null; + try { + markedDirtyResult = entry.markDirty(isChanged); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + // This can only happen if the main thread has been interrupted, and so the + // AbstractQueueVisitor is shutting down. We haven't yet removed the pending + // visitation, so we can resume next time. + return; + } if (markedDirtyResult == null) { // Another thread has already dirtied this node. Don't do anything in this thread. if (supportInterruptions) { diff --git a/src/main/java/com/google/devtools/build/skyframe/MemoizingEvaluator.java b/src/main/java/com/google/devtools/build/skyframe/MemoizingEvaluator.java index cfbff0a447..5c8236ae01 100644 --- a/src/main/java/com/google/devtools/build/skyframe/MemoizingEvaluator.java +++ b/src/main/java/com/google/devtools/build/skyframe/MemoizingEvaluator.java @@ -19,10 +19,8 @@ import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.collect.nestedset.NestedSetVisitor; import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadHostile; import com.google.devtools.build.lib.events.EventHandler; - import java.io.PrintStream; import java.util.Map; - import javax.annotation.Nullable; /** @@ -118,7 +116,7 @@ public interface MemoizingEvaluator { */ @VisibleForTesting @Nullable - ErrorInfo getExistingErrorForTesting(SkyKey key); + ErrorInfo getExistingErrorForTesting(SkyKey key) throws InterruptedException; @Nullable NodeEntry getExistingEntryForTesting(SkyKey key); diff --git a/src/main/java/com/google/devtools/build/skyframe/NodeEntry.java b/src/main/java/com/google/devtools/build/skyframe/NodeEntry.java index 8b7b09193d..82df6fa2ff 100644 --- a/src/main/java/com/google/devtools/build/skyframe/NodeEntry.java +++ b/src/main/java/com/google/devtools/build/skyframe/NodeEntry.java @@ -16,10 +16,8 @@ package com.google.devtools.build.skyframe; import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe; import com.google.devtools.build.lib.util.GroupedList; import com.google.devtools.build.lib.util.GroupedList.GroupedListHelper; - import java.util.Collection; import java.util.Set; - import javax.annotation.Nullable; /** @@ -27,6 +25,9 @@ import javax.annotation.Nullable; * * <p>This interface is public only for the benefit of alternative graph implementations outside of * the package. + * + * <p>Certain graph implementations' node entries can throw {@link InterruptedException} on various + * accesses. Such exceptions should not be caught locally -- they should be allowed to propagate up. */ public interface NodeEntry extends ThinNodeEntry { /** @@ -81,7 +82,7 @@ public interface NodeEntry extends ThinNodeEntry { * this node is complete, i.e., after {@link #setValue} has been called. */ @ThreadSafe - SkyValue getValue(); + SkyValue getValue() throws InterruptedException; /** * Returns an immutable iterable of the direct deps of this node. This method may only be called @@ -93,7 +94,7 @@ public interface NodeEntry extends ThinNodeEntry { * each call takes time proportional to the number of direct deps of the node. */ @ThreadSafe - Iterable<SkyKey> getDirectDeps(); + Iterable<SkyKey> getDirectDeps() throws InterruptedException; /** Removes a reverse dependency. */ @ThreadSafe @@ -123,21 +124,19 @@ public interface NodeEntry extends ThinNodeEntry { * <p>Use the static methods of {@link ValueWithMetadata} to extract metadata if necessary. */ @ThreadSafe - SkyValue getValueMaybeWithMetadata(); + SkyValue getValueMaybeWithMetadata() throws InterruptedException; - /** - * Returns the value, even if dirty or changed. Returns null otherwise. - */ + /** Returns the value, even if dirty or changed. Returns null otherwise. */ @ThreadSafe - SkyValue toValue(); + SkyValue toValue() throws InterruptedException; /** - * Returns the error, if any, associated to this node. This method may only be called after - * the evaluation of this node is complete, i.e., after {@link #setValue} has been called. + * Returns the error, if any, associated to this node. This method may only be called after the + * evaluation of this node is complete, i.e., after {@link #setValue} has been called. */ @Nullable @ThreadSafe - ErrorInfo getErrorInfo(); + ErrorInfo getErrorInfo() throws InterruptedException; /** * Returns the set of reverse deps that have been declared so far this build. Only for use in @@ -153,10 +152,9 @@ public interface NodeEntry extends ThinNodeEntry { * signaled. * * <p>This is an atomic operation to avoid a race where two threads work on two nodes, where one - * node depends on another (b depends on a). When a finishes, it signals <b>exactly</b> the set - * of reverse dependencies that are registered at the time of the {@code setValue} call. If b - * comes in before a, it is signaled (and re-scheduled) by a, otherwise it needs to do that - * itself. + * node depends on another (b depends on a). When a finishes, it signals <b>exactly</b> the set of + * reverse dependencies that are registered at the time of the {@code setValue} call. If b comes + * in before a, it is signaled (and re-scheduled) by a, otherwise it needs to do that itself. * * <p>{@code version} indicates the graph version at which this node is being written. If the * entry determines that the new value is equal to the previous value, the entry will keep its @@ -164,7 +162,7 @@ public interface NodeEntry extends ThinNodeEntry { * changed. */ @ThreadSafe - Set<SkyKey> setValue(SkyValue value, Version version); + Set<SkyKey> setValue(SkyValue value, Version version) throws InterruptedException; /** * Queries if the node is done and adds the given key as a reverse dependency. The return code @@ -238,7 +236,7 @@ public interface NodeEntry extends ThinNodeEntry { * @return {@link Set} of reverse dependencies to signal that this node is done. */ @ThreadSafe - Set<SkyKey> markClean(); + Set<SkyKey> markClean() throws InterruptedException; /** * Forces this node to be re-evaluated, even if none of its dependencies are known to have diff --git a/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java b/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java index 7353e5425c..834a614ea1 100644 --- a/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java +++ b/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java @@ -31,7 +31,6 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.collect.nestedset.NestedSetVisitor; import com.google.devtools.build.lib.concurrent.AbstractQueueVisitor; import com.google.devtools.build.lib.concurrent.ErrorClassifier; -import com.google.devtools.build.lib.concurrent.ErrorHandler; import com.google.devtools.build.lib.concurrent.ForkJoinQuiescingExecutor; import com.google.devtools.build.lib.concurrent.QuiescingExecutor; import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible; @@ -132,7 +131,16 @@ public final class ParallelEvaluator implements Evaluator { @Override public SkyValue get() { - return state.getValue(); + try { + return state.getValue(); + } catch (InterruptedException e) { + throw new IllegalStateException( + "Graph implementations in which value retrieval can block should not be used in " + + "frameworks that use the value in EvaluationProgressReceiver, since that could " + + "result in significant slowdowns: " + + state, + e); + } } } @@ -157,7 +165,6 @@ public final class ParallelEvaluator implements Evaluator { private final DirtyKeyTracker dirtyKeyTracker; private final Receiver<Collection<SkyKey>> inflightKeysReceiver; private final EventFilter storedEventFilter; - private final ErrorHandler errorHandler; public ParallelEvaluator( ProcessableGraph graph, @@ -185,7 +192,6 @@ public final class ParallelEvaluator implements Evaluator { new NestedSetVisitor<>(new NestedSetEventReceiver(reporter), emittedEventState); this.storedEventFilter = storedEventFilter; this.forkJoinPool = null; - this.errorHandler = ErrorHandler.NullHandler.INSTANCE; } public ParallelEvaluator( @@ -200,8 +206,7 @@ public final class ParallelEvaluator implements Evaluator { @Nullable EvaluationProgressReceiver progressReceiver, DirtyKeyTracker dirtyKeyTracker, Receiver<Collection<SkyKey>> inflightKeysReceiver, - ForkJoinPool forkJoinPool, - ErrorHandler errorHandler) { + ForkJoinPool forkJoinPool) { this.graph = graph; this.skyFunctions = skyFunctions; this.graphVersion = graphVersion; @@ -217,13 +222,10 @@ public final class ParallelEvaluator implements Evaluator { new NestedSetVisitor<>(new NestedSetEventReceiver(reporter), emittedEventState); this.storedEventFilter = storedEventFilter; this.forkJoinPool = Preconditions.checkNotNull(forkJoinPool); - this.errorHandler = errorHandler; } - private Map<SkyKey, NodeEntry> getBatchValues( - SkyKey parent, - Reason reason, - Iterable<SkyKey> keys) { + private Map<SkyKey, ? extends NodeEntry> getBatchValues( + SkyKey parent, Reason reason, Iterable<SkyKey> keys) throws InterruptedException { return graph.getBatch(parent, reason, keys); } @@ -301,7 +303,8 @@ public final class ParallelEvaluator implements Evaluator { }; private SkyFunctionEnvironment( - SkyKey skyKey, GroupedList<SkyKey> directDeps, Set<SkyKey> oldDeps, ValueVisitor visitor) { + SkyKey skyKey, GroupedList<SkyKey> directDeps, Set<SkyKey> oldDeps, ValueVisitor visitor) + throws InterruptedException { this(skyKey, directDeps, null, oldDeps, visitor); } @@ -310,7 +313,8 @@ public final class ParallelEvaluator implements Evaluator { GroupedList<SkyKey> directDeps, @Nullable Map<SkyKey, ValueWithMetadata> bubbleErrorInfo, Set<SkyKey> oldDeps, - ValueVisitor visitor) { + ValueVisitor visitor) + throws InterruptedException { this.skyKey = skyKey; this.oldDeps = oldDeps; this.directDeps = Collections.unmodifiableMap(batchPrefetch( @@ -323,9 +327,13 @@ public final class ParallelEvaluator implements Evaluator { skyKey); } - private Map<SkyKey, NodeEntry> batchPrefetch( - SkyKey requestor, GroupedList<SkyKey> depKeys, Set<SkyKey> oldDeps, boolean assertDone, - SkyKey keyForDebugging) { + private Map<SkyKey, ? extends NodeEntry> batchPrefetch( + SkyKey requestor, + GroupedList<SkyKey> depKeys, + Set<SkyKey> oldDeps, + boolean assertDone, + SkyKey keyForDebugging) + throws InterruptedException { Iterable<SkyKey> depKeysAsIterable = Iterables.concat(depKeys); Iterable<SkyKey> keysToPrefetch = depKeysAsIterable; if (PREFETCH_OLD_DEPS) { @@ -333,10 +341,12 @@ public final class ParallelEvaluator implements Evaluator { keysToPrefetchBuilder.addAll(depKeysAsIterable).addAll(oldDeps); keysToPrefetch = keysToPrefetchBuilder.build(); } - Map<SkyKey, NodeEntry> batchMap = getBatchValues(requestor, Reason.PREFETCH, keysToPrefetch); + Map<SkyKey, ? extends NodeEntry> batchMap = + getBatchValues(requestor, Reason.PREFETCH, keysToPrefetch); if (PREFETCH_OLD_DEPS) { - batchMap = ImmutableMap.copyOf( - Maps.filterKeys(batchMap, Predicates.in(ImmutableSet.copyOf(depKeysAsIterable)))); + batchMap = + ImmutableMap.<SkyKey, NodeEntry>copyOf( + Maps.filterKeys(batchMap, Predicates.in(ImmutableSet.copyOf(depKeysAsIterable)))); } if (batchMap.size() != depKeys.numElements()) { throw new IllegalStateException( @@ -346,7 +356,7 @@ public final class ParallelEvaluator implements Evaluator { + Sets.difference(depKeys.toSet(), batchMap.keySet())); } if (assertDone) { - for (Map.Entry<SkyKey, NodeEntry> entry : batchMap.entrySet()) { + for (Map.Entry<SkyKey, ? extends NodeEntry> entry : batchMap.entrySet()) { Preconditions.checkState( entry.getValue().isDone(), "%s had not done %s", keyForDebugging, entry); } @@ -358,7 +368,8 @@ public final class ParallelEvaluator implements Evaluator { Preconditions.checkState(building, skyKey); } - private NestedSet<TaggedEvents> buildEvents(NodeEntry entry, boolean missingChildren) { + private NestedSet<TaggedEvents> buildEvents(NodeEntry entry, boolean missingChildren) + throws InterruptedException { // Aggregate the nested set of events from the direct deps, also adding the events from // building this value. NestedSetBuilder<TaggedEvents> eventBuilder = NestedSetBuilder.stableOrder(); @@ -426,7 +437,8 @@ public final class ParallelEvaluator implements Evaluator { * dependencies of this node <i>must</i> already have been registered, since this method may * register a dependence on the error transience node, which should always be the last dep. */ - private void setError(NodeEntry state, ErrorInfo errorInfo, boolean isDirectlyTransient) { + private void setError(NodeEntry state, ErrorInfo errorInfo, boolean isDirectlyTransient) + throws InterruptedException { Preconditions.checkState(value == null, "%s %s %s", skyKey, value, errorInfo); Preconditions.checkState(this.errorInfo == null, "%s %s %s", skyKey, this.errorInfo, errorInfo); @@ -454,7 +466,8 @@ public final class ParallelEvaluator implements Evaluator { @Nullable SkyKey requestor, Iterable<SkyKey> keys, @Nullable Map<SkyKey, ValueWithMetadata> bubbleErrorInfo, - int keySize) { + int keySize) + throws InterruptedException { ImmutableMap.Builder<SkyKey, SkyValue> builder = ImmutableMap.builder(); ArrayList<SkyKey> missingKeys = new ArrayList<>(keySize); for (SkyKey key : keys) { @@ -468,7 +481,7 @@ public final class ParallelEvaluator implements Evaluator { missingKeys.add(key); } } - Map<SkyKey, NodeEntry> missingEntries = + Map<SkyKey, ? extends NodeEntry> missingEntries = getBatchValues(requestor, Reason.DEP_REQUESTED, missingKeys); for (SkyKey key : missingKeys) { builder.put(key, maybeGetValueFromError(key, missingEntries.get(key), bubbleErrorInfo)); @@ -477,8 +490,8 @@ public final class ParallelEvaluator implements Evaluator { } @Override - protected Map<SkyKey, ValueOrUntypedException> getValueOrUntypedExceptions( - Set<SkyKey> depKeys) { + protected Map<SkyKey, ValueOrUntypedException> getValueOrUntypedExceptions(Set<SkyKey> depKeys) + throws InterruptedException { checkActive(); Preconditions.checkState( !depKeys.contains(ErrorTransienceValue.KEY), @@ -578,15 +591,20 @@ public final class ParallelEvaluator implements Evaluator { } @Override - public <E1 extends Exception, E2 extends Exception, E3 extends Exception, - E4 extends Exception, E5 extends Exception> + public < + E1 extends Exception, + E2 extends Exception, + E3 extends Exception, + E4 extends Exception, + E5 extends Exception> Map<SkyKey, ValueOrException5<E1, E2, E3, E4, E5>> getValuesOrThrow( Iterable<SkyKey> depKeys, Class<E1> exceptionClass1, Class<E2> exceptionClass2, Class<E3> exceptionClass3, Class<E4> exceptionClass4, - Class<E5> exceptionClass5) { + Class<E5> exceptionClass5) + throws InterruptedException { newlyRequestedDeps.startGroup(); Map<SkyKey, ValueOrException5<E1, E2, E3, E4, E5>> result = super.getValuesOrThrow( depKeys, @@ -638,7 +656,7 @@ public final class ParallelEvaluator implements Evaluator { * <p>The node entry is informed if the node's value and error are definitive via the flag * {@code completeValue}. */ - void commit(NodeEntry primaryEntry, boolean enqueueParents) { + void commit(NodeEntry primaryEntry, boolean enqueueParents) throws InterruptedException { // Construct the definitive error info, if there is one. finalizeErrorInfo(); @@ -664,10 +682,8 @@ public final class ParallelEvaluator implements Evaluator { // Remove the rdep on this entry for each of its old deps that is no longer a direct dep. Set<SkyKey> depsToRemove = Sets.difference(oldDeps, primaryEntry.getTemporaryDirectDeps().toSet()); - Collection<NodeEntry> oldDepEntries = graph.getBatch( - skyKey, - Reason.RDEP_REMOVAL, - depsToRemove).values(); + Collection<? extends NodeEntry> oldDepEntries = + graph.getBatch(skyKey, Reason.RDEP_REMOVAL, depsToRemove).values(); for (NodeEntry oldDepEntry : oldDepEntries) { oldDepEntry.removeReverseDep(skyKey); } @@ -754,7 +770,7 @@ public final class ParallelEvaluator implements Evaluator { private ValueVisitor(ForkJoinPool forkJoinPool) { quiescingExecutor = - new ForkJoinQuiescingExecutor(forkJoinPool, VALUE_VISITOR_ERROR_CLASSIFIER, errorHandler); + new ForkJoinQuiescingExecutor(forkJoinPool, VALUE_VISITOR_ERROR_CLASSIFIER); } private ValueVisitor(int threadCount) { @@ -766,8 +782,7 @@ public final class ParallelEvaluator implements Evaluator { TimeUnit.SECONDS, /*failFastOnException*/ true, "skyframe-evaluator", - VALUE_VISITOR_ERROR_CLASSIFIER, - errorHandler); + VALUE_VISITOR_ERROR_CLASSIFIER); } private void waitForCompletion() throws InterruptedException { @@ -884,14 +899,15 @@ public final class ParallelEvaluator implements Evaluator { * Returns true if this depGroup consists of the error transience value and the error transience * value is newer than the entry, meaning that the entry must be re-evaluated. */ - private boolean invalidatedByErrorTransience(Collection<SkyKey> depGroup, NodeEntry entry) { + private boolean invalidatedByErrorTransience(Collection<SkyKey> depGroup, NodeEntry entry) + throws InterruptedException { return depGroup.size() == 1 && depGroup.contains(ErrorTransienceValue.KEY) && !graph.get( null, Reason.OTHER, ErrorTransienceValue.KEY).getVersion().atMost(entry.getVersion()); } - private DirtyOutcome maybeHandleDirtyNode(NodeEntry state) { + private DirtyOutcome maybeHandleDirtyNode(NodeEntry state) throws InterruptedException { if (!state.isDirty()) { return DirtyOutcome.NEEDS_EVALUATION; } @@ -934,9 +950,9 @@ public final class ParallelEvaluator implements Evaluator { // is done, then it is the parent's responsibility to notice that, which we do here. // We check the deps for errors so that we don't continue building this node if it has // a child error. - Map<SkyKey, NodeEntry> entriesToCheck = + Map<SkyKey, ? extends NodeEntry> entriesToCheck = graph.getBatch(skyKey, Reason.OTHER, directDepsToCheck); - for (Map.Entry<SkyKey, NodeEntry> entry : entriesToCheck.entrySet()) { + for (Entry<SkyKey, ? extends NodeEntry> entry : entriesToCheck.entrySet()) { if (entry.getValue().isDone() && entry.getValue().getErrorInfo() != null) { // If any child has an error, we arbitrarily add a dep on the first one (needed // for error bubbling) and throw an exception coming from it. @@ -945,7 +961,7 @@ public final class ParallelEvaluator implements Evaluator { state.addTemporaryDirectDeps(GroupedListHelper.create(ImmutableList.of(errorKey))); errorEntry.checkIfDoneForDirtyReverseDep(skyKey); // Perform the necessary bookkeeping for any deps that are not being used. - for (Map.Entry<SkyKey, NodeEntry> depEntry : entriesToCheck.entrySet()) { + for (Entry<SkyKey, ? extends NodeEntry> depEntry : entriesToCheck.entrySet()) { if (!depEntry.getKey().equals(errorKey)) { depEntry.getValue().removeReverseDep(skyKey); } @@ -969,8 +985,10 @@ public final class ParallelEvaluator implements Evaluator { // TODO(bazel-team): If this signals the current node, consider falling through to the // VERIFIED_CLEAN case below directly, without scheduling a new Evaluate(). - for (Map.Entry<SkyKey, NodeEntry> e : graph.createIfAbsentBatch( - skyKey, Reason.ENQUEUING_CHILD, directDepsToCheck).entrySet()) { + for (Map.Entry<SkyKey, ? extends NodeEntry> e : + graph + .createIfAbsentBatch(skyKey, Reason.ENQUEUING_CHILD, directDepsToCheck) + .entrySet()) { SkyKey directDep = e.getKey(); NodeEntry directDepEntry = e.getValue(); enqueueChild(skyKey, state, directDep, directDepEntry, /*depAlreadyExists=*/ true); @@ -1005,6 +1023,7 @@ public final class ParallelEvaluator implements Evaluator { @Override public void run() { + try { NodeEntry state = Preconditions.checkNotNull( graph.get(null, Reason.EVALUATION, skyKey), skyKey); @@ -1047,8 +1066,8 @@ public final class ParallelEvaluator implements Evaluator { } } - Map<SkyKey, NodeEntry> newlyRequestedDeps = - getBatchValues(skyKey, Reason.RDEP_ADDITION, env.newlyRequestedDeps); + Map<SkyKey, ? extends NodeEntry> newlyRequestedDeps = + getBatchValues(skyKey, Reason.RDEP_ADDITION, env.newlyRequestedDeps); boolean isTransitivelyTransient = reifiedBuilderException.isTransient(); for (NodeEntry depEntry : Iterables.concat(env.directDeps.values(), newlyRequestedDeps.values())) { @@ -1073,11 +1092,6 @@ public final class ParallelEvaluator implements Evaluator { } throw SchedulerException.ofError(errorInfo, skyKey); } - } catch (InterruptedException ie) { - // InterruptedException cannot be thrown by Runnable.run, so we must wrap it. - // Interrupts can be caught by both the Evaluator and the AbstractQueueVisitor. - // The former will unwrap the IE and propagate it as is; the latter will throw a new IE. - throw SchedulerException.ofInterruption(ie, skyKey); } catch (RuntimeException re) { // Programmer error (most likely NPE or a failed precondition in a SkyFunction). Output // some context together with the exception. @@ -1127,24 +1141,24 @@ public final class ParallelEvaluator implements Evaluator { skyKey, state, childErrorKey); - if (newDirectDeps.contains(childErrorKey)) { - // Add this dep if it was just requested. In certain rare race conditions (see - // MemoizingEvaluatorTest.cachedErrorCausesRestart) this dep may have already been - // requested. - state.addTemporaryDirectDeps(GroupedListHelper.create(ImmutableList.of(childErrorKey))); - DependencyState childErrorState; - if (oldDeps.contains(childErrorKey)) { - childErrorState = childErrorEntry.checkIfDoneForDirtyReverseDep(skyKey); - } else { - childErrorState = childErrorEntry.addReverseDepAndCheckIfDone(skyKey); - } - Preconditions.checkState( - childErrorState == DependencyState.DONE, - "skyKey: %s, state: %s childErrorKey: %s", - skyKey, - state, - childErrorKey, - childErrorEntry); + if (newDirectDeps.contains(childErrorKey)) { + // Add this dep if it was just requested. In certain rare race conditions (see + // MemoizingEvaluatorTest.cachedErrorCausesRestart) this dep may have already been + // requested. + state.addTemporaryDirectDeps(GroupedListHelper.create(ImmutableList.of(childErrorKey))); + DependencyState childErrorState; + if (oldDeps.contains(childErrorKey)) { + childErrorState = childErrorEntry.checkIfDoneForDirtyReverseDep(skyKey); + } else { + childErrorState = childErrorEntry.addReverseDepAndCheckIfDone(skyKey); + } + Preconditions.checkState( + childErrorState == DependencyState.DONE, + "skyKey: %s, state: %s childErrorKey: %s", + skyKey, + state, + childErrorKey, + childErrorEntry); } ErrorInfo childErrorInfo = Preconditions.checkNotNull(childErrorEntry.getErrorInfo()); visitor.preventNewEvaluations(); @@ -1180,8 +1194,8 @@ public final class ParallelEvaluator implements Evaluator { return; } - for (Map.Entry<SkyKey, NodeEntry> e - : graph.createIfAbsentBatch(skyKey, Reason.ENQUEUING_CHILD, newDirectDeps).entrySet()) { + for (Entry<SkyKey, ? extends NodeEntry> e : + graph.createIfAbsentBatch(skyKey, Reason.ENQUEUING_CHILD, newDirectDeps).entrySet()) { SkyKey newDirectDep = e.getKey(); NodeEntry newDirectDepEntry = e.getValue(); enqueueChild( @@ -1191,6 +1205,12 @@ public final class ParallelEvaluator implements Evaluator { newDirectDepEntry, /*depAlreadyExists=*/ oldDeps.contains(newDirectDep)); } + } catch (InterruptedException ie) { + // InterruptedException cannot be thrown by Runnable.run, so we must wrap it. + // Interrupts can be caught by both the Evaluator and the AbstractQueueVisitor. + // The former will unwrap the IE and propagate it as is; the latter will throw a new IE. + throw SchedulerException.ofInterruption(ie, skyKey); + } // It is critical that there is no code below this point. } @@ -1219,17 +1239,16 @@ public final class ParallelEvaluator implements Evaluator { /** * Signals all parents that this node is finished. If visitor is not null, also enqueues any - * parents that are ready. If visitor is null, indicating that we are building this node after - * the main build aborted, then skip any parents that are already done (that can happen with - * cycles). + * parents that are ready. If visitor is null, indicating that we are building this node after the + * main build aborted, then skip any parents that are already done (that can happen with cycles). */ private void signalValuesAndEnqueueIfReady( - @Nullable ValueVisitor visitor, SkyKey skyKey, Iterable<SkyKey> keys, Version version) { + @Nullable ValueVisitor visitor, SkyKey skyKey, Iterable<SkyKey> keys, Version version) + throws InterruptedException { // No fields of the entry are needed here, since we're just enqueuing for evaluation, but more // importantly, these hints are not respected for not-done nodes. If they are, we may need to // alter this hint. - Map<SkyKey, NodeEntry> batch = - graph.getBatch(skyKey, Reason.SIGNAL_DEP, keys); + Map<SkyKey, ? extends NodeEntry> batch = graph.getBatch(skyKey, Reason.SIGNAL_DEP, keys); if (visitor != null) { for (SkyKey key : keys) { NodeEntry entry = Preconditions.checkNotNull(batch.get(key), key); @@ -1252,7 +1271,8 @@ public final class ParallelEvaluator implements Evaluator { * If child is not done, removes {@param inProgressParent} from {@param child}'s reverse deps. * Returns whether child should be removed from inProgressParent's entry's direct deps. */ - private boolean removeIncompleteChildForCycle(SkyKey inProgressParent, SkyKey child) { + private boolean removeIncompleteChildForCycle(SkyKey inProgressParent, SkyKey child) + throws InterruptedException { NodeEntry childEntry = graph.get(inProgressParent, Reason.CYCLE_CHECKING, child); if (!isDoneForBuild(childEntry)) { childEntry.removeInProgressReverseDep(inProgressParent); @@ -1272,7 +1292,7 @@ public final class ParallelEvaluator implements Evaluator { private static void registerNewlyDiscoveredDepsForDoneEntry( SkyKey skyKey, NodeEntry entry, - Map<SkyKey, NodeEntry> newlyRequestedDepMap, + Map<SkyKey, ? extends NodeEntry> newlyRequestedDepMap, Set<SkyKey> oldDeps, SkyFunctionEnvironment env) { Set<SkyKey> unfinishedDeps = new HashSet<>(); @@ -1300,7 +1320,8 @@ public final class ParallelEvaluator implements Evaluator { Preconditions.checkState(entry.isReady(), "%s %s %s", skyKey, entry, env.newlyRequestedDeps); } - private void informProgressReceiverThatValueIsDone(SkyKey key, NodeEntry entry) { + private void informProgressReceiverThatValueIsDone(SkyKey key, NodeEntry entry) + throws InterruptedException { if (progressReceiver != null) { Preconditions.checkState(entry.isDone(), entry); SkyValue value = entry.getValue(); @@ -1327,7 +1348,8 @@ public final class ParallelEvaluator implements Evaluator { // directly without launching the heavy machinery, spawning threads, etc. // Inform progressReceiver that these nodes are done to be consistent with the main code path. boolean allAreDone = true; - Map<SkyKey, NodeEntry> batch = getBatchValues(null, Reason.PRE_OR_POST_EVALUATION, skyKeySet); + Map<SkyKey, ? extends NodeEntry> batch = + getBatchValues(null, Reason.PRE_OR_POST_EVALUATION, skyKeySet); for (SkyKey key : skyKeySet) { if (!isDoneForBuild(batch.get(key))) { allAreDone = false; @@ -1401,8 +1423,8 @@ public final class ParallelEvaluator implements Evaluator { graph, dirtyKeyTracker); } - for (Map.Entry<SkyKey, NodeEntry> e - : graph.createIfAbsentBatch(null, Reason.PRE_OR_POST_EVALUATION, skyKeys).entrySet()) { + for (Entry<SkyKey, ? extends NodeEntry> e : + graph.createIfAbsentBatch(null, Reason.PRE_OR_POST_EVALUATION, skyKeys).entrySet()) { SkyKey skyKey = e.getKey(); NodeEntry entry = e.getValue(); // This must be equivalent to the code in enqueueChild above, in order to be thread-safe. @@ -1477,23 +1499,31 @@ public final class ParallelEvaluator implements Evaluator { } /** - * Walk up graph to find a top-level node (without parents) that wanted this failure. Store - * the failed nodes along the way in a map, with ErrorInfos that are appropriate for that layer. + * Walk up graph to find a top-level node (without parents) that wanted this failure. Store the + * failed nodes along the way in a map, with ErrorInfos that are appropriate for that layer. * Example: + * + * <pre> * foo bar * \ / * unrequested baz * \ | * failed-node + * </pre> + * * User requests foo, bar. When failed-node fails, we look at its parents. unrequested is not * in-flight, so we replace failed-node by baz and repeat. We look at baz's parents. foo is - * in-flight, so we replace baz by foo. Since foo is a top-level node and doesn't have parents, - * we then break, since we know a top-level node, foo, that depended on the failed node. + * in-flight, so we replace baz by foo. Since foo is a top-level node and doesn't have parents, we + * then break, since we know a top-level node, foo, that depended on the failed node. * - * There's the potential for a weird "track jump" here in the case: + * <p>There's the potential for a weird "track jump" here in the case: + * + * <pre> * foo * / \ * fail1 fail2 + * </pre> + * * If fail1 and fail2 fail simultaneously, fail2 may start propagating up in the loop below. * However, foo requests fail1 first, and then throws an exception based on that. This is not * incorrect, but may be unexpected. @@ -1506,8 +1536,9 @@ public final class ParallelEvaluator implements Evaluator { * <p>Note that we are not propagating error to the first top-level node but to the highest one, * because during this process we can add useful information about error from other nodes. */ - private Map<SkyKey, ValueWithMetadata> bubbleErrorUp(final ErrorInfo leafFailure, - SkyKey errorKey, Iterable<SkyKey> skyKeys, ValueVisitor visitor) { + private Map<SkyKey, ValueWithMetadata> bubbleErrorUp( + final ErrorInfo leafFailure, SkyKey errorKey, Iterable<SkyKey> skyKeys, ValueVisitor visitor) + throws InterruptedException { Set<SkyKey> rootValues = ImmutableSet.copyOf(skyKeys); ErrorInfo error = leafFailure; Map<SkyKey, ValueWithMetadata> bubbleErrorInfo = new HashMap<>(); @@ -1651,9 +1682,9 @@ public final class ParallelEvaluator implements Evaluator { } /** - * Constructs an {@link EvaluationResult} from the {@link #graph}. Looks for cycles if there - * are unfinished nodes but no error was already found through bubbling up - * (as indicated by {@code bubbleErrorInfo} being null). + * Constructs an {@link EvaluationResult} from the {@link #graph}. Looks for cycles if there are + * unfinished nodes but no error was already found through bubbling up (as indicated by {@code + * bubbleErrorInfo} being null). * * <p>{@code visitor} may be null, but only in the case where all graph entries corresponding to * {@code skyKeys} are known to be in the DONE state ({@code entry.isDone()} returns true). @@ -1662,7 +1693,8 @@ public final class ParallelEvaluator implements Evaluator { @Nullable ValueVisitor visitor, Iterable<SkyKey> skyKeys, @Nullable Map<SkyKey, ValueWithMetadata> bubbleErrorInfo, - boolean catastrophe) { + boolean catastrophe) + throws InterruptedException { Preconditions.checkState( catastrophe == (keepGoing && bubbleErrorInfo != null), "Catastrophe not consistent with keepGoing mode and bubbleErrorInfo: %s %s %s %s", @@ -1739,8 +1771,11 @@ public final class ParallelEvaluator implements Evaluator { } private <T extends SkyValue> void checkForCycles( - Iterable<SkyKey> badRoots, EvaluationResult.Builder<T> result, final ValueVisitor visitor, - boolean keepGoing) { + Iterable<SkyKey> badRoots, + EvaluationResult.Builder<T> result, + final ValueVisitor visitor, + boolean keepGoing) + throws InterruptedException { try (AutoProfiler p = AutoProfiler.logged("Checking for Skyframe cycles", LOG, 10)) { for (SkyKey root : badRoots) { ErrorInfo errorInfo = checkForCycles(root, visitor, keepGoing); @@ -1774,13 +1809,13 @@ public final class ParallelEvaluator implements Evaluator { /** * The algorithm for this cycle detector is as follows. We visit the graph depth-first, keeping * track of the path we are currently on. We skip any DONE nodes (they are transitively - * error-free). If we come to a node already on the path, we immediately construct a cycle. If - * we are in the noKeepGoing case, we return ErrorInfo with that cycle to the caller. Otherwise, - * we continue. Once all of a node's children are done, we construct an error value for it, based - * on those children. Finally, when the original root's node is constructed, we return its - * ErrorInfo. + * error-free). If we come to a node already on the path, we immediately construct a cycle. If we + * are in the noKeepGoing case, we return ErrorInfo with that cycle to the caller. Otherwise, we + * continue. Once all of a node's children are done, we construct an error value for it, based on + * those children. Finally, when the original root's node is constructed, we return its ErrorInfo. */ - private ErrorInfo checkForCycles(SkyKey root, ValueVisitor visitor, boolean keepGoing) { + private ErrorInfo checkForCycles(SkyKey root, ValueVisitor visitor, boolean keepGoing) + throws InterruptedException { // The number of cycles found. Do not keep on searching for more cycles after this many were // found. int cyclesFound = 0; @@ -1926,7 +1961,7 @@ public final class ParallelEvaluator implements Evaluator { // out. // TODO(janakr): If graph implementations start using these hints for not-done nodes, we may // have to change this. - Map<SkyKey, NodeEntry> childrenNodes = + Map<SkyKey, ? extends NodeEntry> childrenNodes = graph.getBatch(key, Reason.EXISTENCE_CHECKING, children); Preconditions.checkState(childrenNodes.size() == Iterables.size(children), childrenNodes); children = Maps.filterValues(childrenNodes, new Predicate<NodeEntry>() { @@ -1962,7 +1997,8 @@ public final class ParallelEvaluator implements Evaluator { * @param children child nodes to query for errors. * @return List of ErrorInfos from all children that had errors. */ - private List<ErrorInfo> getChildrenErrorsForCycle(SkyKey parent, Iterable<SkyKey> children) { + private List<ErrorInfo> getChildrenErrorsForCycle(SkyKey parent, Iterable<SkyKey> children) + throws InterruptedException { List<ErrorInfo> allErrors = new ArrayList<>(); boolean foundCycle = false; for (NodeEntry childNode : getAndCheckDoneBatchForCycle(parent, children).values()) { @@ -1984,11 +2020,11 @@ public final class ParallelEvaluator implements Evaluator { * @return List of ErrorInfos from all children that had errors. */ private List<ErrorInfo> getChildrenErrorsForCycleChecking( - Iterable<SkyKey> children, SkyKey unfinishedChild) { + Iterable<SkyKey> children, SkyKey unfinishedChild) throws InterruptedException { List<ErrorInfo> allErrors = new ArrayList<>(); - Set<Entry<SkyKey, NodeEntry>> childEntries = + Set<? extends Entry<SkyKey, ? extends NodeEntry>> childEntries = getBatchValues(null, Reason.CYCLE_CHECKING, children).entrySet(); - for (Entry<SkyKey, NodeEntry> childMapEntry : childEntries) { + for (Entry<SkyKey, ? extends NodeEntry> childMapEntry : childEntries) { SkyKey childKey = childMapEntry.getKey(); NodeEntry childNodeEntry = childMapEntry.getValue(); ErrorInfo errorInfo = getErrorMaybe(childKey, childNodeEntry, @@ -2001,7 +2037,8 @@ public final class ParallelEvaluator implements Evaluator { } @Nullable - private ErrorInfo getErrorMaybe(SkyKey key, NodeEntry childNodeEntry, boolean allowUnfinished) { + private static ErrorInfo getErrorMaybe( + SkyKey key, NodeEntry childNodeEntry, boolean allowUnfinished) throws InterruptedException { Preconditions.checkNotNull(childNodeEntry, key); if (!allowUnfinished) { return checkDone(key, childNodeEntry).getErrorInfo(); @@ -2027,7 +2064,8 @@ public final class ParallelEvaluator implements Evaluator { NodeEntry entry, @Nullable SkyKey cycleChild, Iterable<SkyKey> toVisit, - int cycleLength) { + int cycleLength) + throws InterruptedException { GroupedList<SkyKey> directDeps = entry.getTemporaryDirectDeps(); Set<SkyKey> unvisitedDeps = Sets.newHashSetWithExpectedSize(directDeps.numElements()); Iterables.addAll(unvisitedDeps, Iterables.concat(directDeps)); @@ -2069,7 +2107,7 @@ public final class ParallelEvaluator implements Evaluator { } private Set<SkyKey> removeIncompleteChildrenForCycle( - SkyKey key, NodeEntry entry, Iterable<SkyKey> children) { + SkyKey key, NodeEntry entry, Iterable<SkyKey> children) throws InterruptedException { Set<SkyKey> unfinishedDeps = new HashSet<>(); for (SkyKey child : children) { if (removeIncompleteChildForCycle(key, child)) { @@ -2086,14 +2124,14 @@ public final class ParallelEvaluator implements Evaluator { return entry; } - private NodeEntry getAndCheckDoneForCycle(SkyKey key) { + private NodeEntry getAndCheckDoneForCycle(SkyKey key) throws InterruptedException { return checkDone(key, graph.get(null, Reason.CYCLE_CHECKING, key)); } - private Map<SkyKey, NodeEntry> getAndCheckDoneBatchForCycle( - SkyKey parent, Iterable<SkyKey> keys) { - Map<SkyKey, NodeEntry> nodes = getBatchValues(parent, Reason.CYCLE_CHECKING, keys); - for (Map.Entry<SkyKey, NodeEntry> nodeEntryMapEntry : nodes.entrySet()) { + private Map<SkyKey, ? extends NodeEntry> getAndCheckDoneBatchForCycle( + SkyKey parent, Iterable<SkyKey> keys) throws InterruptedException { + Map<SkyKey, ? extends NodeEntry> nodes = getBatchValues(parent, Reason.CYCLE_CHECKING, keys); + for (Entry<SkyKey, ? extends NodeEntry> nodeEntryMapEntry : nodes.entrySet()) { checkDone(nodeEntryMapEntry.getKey(), nodeEntryMapEntry.getValue()); } return nodes; @@ -2104,7 +2142,8 @@ public final class ParallelEvaluator implements Evaluator { private static SkyValue maybeGetValueFromError( SkyKey key, @Nullable NodeEntry entry, - @Nullable Map<SkyKey, ValueWithMetadata> bubbleErrorInfo) { + @Nullable Map<SkyKey, ValueWithMetadata> bubbleErrorInfo) + throws InterruptedException { SkyValue value = bubbleErrorInfo == null ? null : bubbleErrorInfo.get(key); if (value != null) { Preconditions.checkNotNull( @@ -2127,8 +2166,9 @@ public final class ParallelEvaluator implements Evaluator { Map<SkyKey, SkyValue> injectionMap, Version version, EvaluableGraph graph, - DirtyKeyTracker dirtyKeyTracker) { - Map<SkyKey, NodeEntry> prevNodeEntries = + DirtyKeyTracker dirtyKeyTracker) + throws InterruptedException { + Map<SkyKey, ? extends NodeEntry> prevNodeEntries = graph.createIfAbsentBatch(null, Reason.OTHER, injectionMap.keySet()); for (Map.Entry<SkyKey, SkyValue> injectionEntry : injectionMap.entrySet()) { SkyKey key = injectionEntry.getKey(); diff --git a/src/main/java/com/google/devtools/build/skyframe/QueryableGraph.java b/src/main/java/com/google/devtools/build/skyframe/QueryableGraph.java index f76c0aeeb7..028684471b 100644 --- a/src/main/java/com/google/devtools/build/skyframe/QueryableGraph.java +++ b/src/main/java/com/google/devtools/build/skyframe/QueryableGraph.java @@ -15,10 +15,15 @@ package com.google.devtools.build.skyframe; import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe; import java.util.Map; - import javax.annotation.Nullable; -/** A graph that exposes its entries and structure, for use by classes that must traverse it. */ +/** + * A graph that exposes its entries and structure, for use by classes that must traverse it. + * + * <p>Certain graph implementations can throw {@link InterruptedException} when trying to retrieve + * node entries. Such exceptions should not be caught locally -- they should be allowed to propagate + * up. + */ @ThreadSafe public interface QueryableGraph { /** @@ -29,18 +34,19 @@ public interface QueryableGraph { * @param reason the reason the node is being requested. */ @Nullable - NodeEntry get(@Nullable SkyKey requestor, Reason reason, SkyKey key); + NodeEntry get(@Nullable SkyKey requestor, Reason reason, SkyKey key) throws InterruptedException; /** * Fetches all the given nodes. Returns a map {@code m} such that, for all {@code k} in {@code * keys}, {@code m.get(k).equals(e)} iff {@code get(k) == e} and {@code e != null}, and {@code * !m.containsKey(k)} iff {@code get(k) == null}. - * + * * @param requestor if non-{@code null}, the node on behalf of which the given {@code keys} are * being requested. * @param reason the reason the nodes are being requested. */ - Map<SkyKey, NodeEntry> getBatch(@Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys); + Map<SkyKey, ? extends NodeEntry> getBatch( + @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys) throws InterruptedException; /** * The reason that a node is being looked up in the Skyframe graph. diff --git a/src/main/java/com/google/devtools/build/skyframe/QueryableGraphBackedSkyFunctionEnvironment.java b/src/main/java/com/google/devtools/build/skyframe/QueryableGraphBackedSkyFunctionEnvironment.java index 79ed64056a..ef9616707f 100644 --- a/src/main/java/com/google/devtools/build/skyframe/QueryableGraphBackedSkyFunctionEnvironment.java +++ b/src/main/java/com/google/devtools/build/skyframe/QueryableGraphBackedSkyFunctionEnvironment.java @@ -13,19 +13,14 @@ // limitations under the License. package com.google.devtools.build.skyframe; -import com.google.common.base.Function; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; -import com.google.common.collect.Sets; import com.google.devtools.build.lib.events.EventHandler; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.skyframe.QueryableGraph.Reason; -import java.util.HashMap; import java.util.Map; import java.util.Set; -import javax.annotation.Nullable; - /** * A {@link SkyFunction.Environment} backed by a {@link QueryableGraph}. For use when a single * SkyFunction needs recomputation, and its dependencies do not need to be evaluated. Any missing @@ -41,41 +36,40 @@ public class QueryableGraphBackedSkyFunctionEnvironment extends AbstractSkyFunct this.eventHandler = eventHandler; } - private static final Function<NodeEntry, ValueOrUntypedException> NODE_ENTRY_TO_UNTYPED_VALUE = - new Function<NodeEntry, ValueOrUntypedException>() { - @Override - public ValueOrUntypedException apply(@Nullable NodeEntry nodeEntry) { - if (nodeEntry == null || !nodeEntry.isDone()) { - return ValueOrExceptionUtils.ofNull(); - } - SkyValue maybeWrappedValue = nodeEntry.getValueMaybeWithMetadata(); - SkyValue justValue = ValueWithMetadata.justValue(maybeWrappedValue); - if (justValue != null) { - return ValueOrExceptionUtils.ofValueUntyped(justValue); - } - ErrorInfo errorInfo = - Preconditions.checkNotNull(ValueWithMetadata.getMaybeErrorInfo(maybeWrappedValue)); - Exception exception = errorInfo.getException(); + private static ValueOrUntypedException toUntypedValue(NodeEntry nodeEntry) + throws InterruptedException { + if (nodeEntry == null || !nodeEntry.isDone()) { + return ValueOrExceptionUtils.ofNull(); + } + SkyValue maybeWrappedValue = nodeEntry.getValueMaybeWithMetadata(); + SkyValue justValue = ValueWithMetadata.justValue(maybeWrappedValue); + if (justValue != null) { + return ValueOrExceptionUtils.ofValueUntyped(justValue); + } + ErrorInfo errorInfo = + Preconditions.checkNotNull(ValueWithMetadata.getMaybeErrorInfo(maybeWrappedValue)); + Exception exception = errorInfo.getException(); - if (exception != null) { - // Give SkyFunction#compute a chance to handle this exception. - return ValueOrExceptionUtils.ofExn(exception); - } - // In a cycle. - Preconditions.checkState( - !Iterables.isEmpty(errorInfo.getCycleInfo()), "%s %s", errorInfo, maybeWrappedValue); - return ValueOrExceptionUtils.ofNull(); - } - }; + if (exception != null) { + // Give SkyFunction#compute a chance to handle this exception. + return ValueOrExceptionUtils.ofExn(exception); + } + // In a cycle. + Preconditions.checkState( + !Iterables.isEmpty(errorInfo.getCycleInfo()), "%s %s", errorInfo, maybeWrappedValue); + return ValueOrExceptionUtils.ofNull(); + } @Override - protected Map<SkyKey, ValueOrUntypedException> getValueOrUntypedExceptions(Set<SkyKey> depKeys) { - Map<SkyKey, NodeEntry> resultMap = queryableGraph.getBatch(null, Reason.DEP_REQUESTED, depKeys); - Map<SkyKey, NodeEntry> resultWithMissingKeys = new HashMap<>(resultMap); - for (SkyKey missingDep : Sets.difference(depKeys, resultMap.keySet())) { - resultWithMissingKeys.put(missingDep, null); + protected Map<SkyKey, ValueOrUntypedException> getValueOrUntypedExceptions(Set<SkyKey> depKeys) + throws InterruptedException { + Map<SkyKey, ? extends NodeEntry> resultMap = + queryableGraph.getBatch(null, Reason.DEP_REQUESTED, depKeys); + Map<SkyKey, ValueOrUntypedException> result = Maps.newHashMapWithExpectedSize(depKeys.size()); + for (SkyKey dep : depKeys) { + result.put(dep, toUntypedValue(resultMap.get(dep))); } - return Maps.transformValues(resultWithMissingKeys, NODE_ENTRY_TO_UNTYPED_VALUE); + return result; } @Override diff --git a/src/main/java/com/google/devtools/build/skyframe/SequentialBuildDriver.java b/src/main/java/com/google/devtools/build/skyframe/SequentialBuildDriver.java index c65f681e8d..905c25fc65 100644 --- a/src/main/java/com/google/devtools/build/skyframe/SequentialBuildDriver.java +++ b/src/main/java/com/google/devtools/build/skyframe/SequentialBuildDriver.java @@ -16,7 +16,6 @@ package com.google.devtools.build.skyframe; import com.google.devtools.build.lib.events.EventHandler; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.common.options.OptionsClassProvider; - import javax.annotation.Nullable; /** @@ -60,7 +59,7 @@ public class SequentialBuildDriver implements BuildDriver { @Nullable @Override - public ErrorInfo getExistingErrorForTesting(SkyKey key) { + public ErrorInfo getExistingErrorForTesting(SkyKey key) throws InterruptedException { return memoizingEvaluator.getExistingErrorForTesting(key); } diff --git a/src/main/java/com/google/devtools/build/skyframe/SkyFunction.java b/src/main/java/com/google/devtools/build/skyframe/SkyFunction.java index 637c202999..6bd52c6150 100644 --- a/src/main/java/com/google/devtools/build/skyframe/SkyFunction.java +++ b/src/main/java/com/google/devtools/build/skyframe/SkyFunction.java @@ -16,9 +16,7 @@ package com.google.devtools.build.skyframe; import com.google.common.annotations.VisibleForTesting; import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe; import com.google.devtools.build.lib.events.EventHandler; - import java.util.Map; - import javax.annotation.Nullable; /** @@ -67,56 +65,83 @@ public interface SkyFunction { String extractTag(SkyKey skyKey); /** - * The services provided to the {@link SkyFunction} implementation by the graph implementation. + * The services provided to the {@link SkyFunction#compute} implementation by the Skyframe + * evaluation framework. */ interface Environment { /** * Returns a direct dependency. If the specified value is not in the set of already evaluated - * direct dependencies, returns {@code null}. Also returns {@code null} if the specified - * value has already been evaluated and found to be in error. + * direct dependencies, returns {@code null}. Also returns {@code null} if the specified value + * has already been evaluated and found to be in error. * * <p>On a subsequent evaluation, if any of this value's dependencies have changed they will be - * re-evaluated in the same order as originally requested by the {@code SkyFunction} using - * this {@code getValue} call (see {@link #getValues} for when preserving the order is not + * re-evaluated in the same order as originally requested by the {@code SkyFunction} using this + * {@code getValue} call (see {@link #getValues} for when preserving the order is not * important). + * + * <p>This method and the ones below may throw {@link InterruptedException}. Such exceptions + * must not be caught by the {@link SkyFunction#compute} implementation. Instead, they should be + * propagated up to the caller of {@link SkyFunction#compute}. */ @Nullable - SkyValue getValue(SkyKey valueName); + SkyValue getValue(SkyKey valueName) throws InterruptedException; /** * Returns a direct dependency. If the specified value is not in the set of already evaluated - * direct dependencies, returns {@code null}. If the specified value has already been - * evaluated and found to be in error, throws the exception coming from the error, so long as - * the exception is of one of the specified types. SkyFunction implementations may use this - * method to continue evaluation even if one of their dependencies is in error by catching - * the thrown exception and proceeding. The caller must specify the exception type(s) that - * might be thrown using the {@code exceptionClass} argument(s). If the dependency's - * exception is not an instance of {@code exceptionClass}, {@code null} is returned. + * direct dependencies, returns {@code null}. If the specified value has already been evaluated + * and found to be in error, throws the exception coming from the error, so long as the + * exception is of one of the specified types. SkyFunction implementations may use this method + * to continue evaluation even if one of their dependencies is in error by catching the thrown + * exception and proceeding. The caller must specify the exception type(s) that might be thrown + * using the {@code exceptionClass} argument(s). If the dependency's exception is not an + * instance of {@code exceptionClass}, {@code null} is returned. * * <p>The exception class given cannot be a supertype or a subtype of {@link RuntimeException}, - * or a subtype of {@link InterruptedException}. See - * {@link SkyFunctionException#validateExceptionType} for details. + * or a subtype of {@link InterruptedException}. See {@link + * SkyFunctionException#validateExceptionType} for details. */ @Nullable - <E extends Exception> SkyValue getValueOrThrow(SkyKey depKey, Class<E> exceptionClass) throws E; + <E extends Exception> SkyValue getValueOrThrow(SkyKey depKey, Class<E> exceptionClass) + throws E, InterruptedException; + @Nullable - <E1 extends Exception, E2 extends Exception> SkyValue getValueOrThrow(SkyKey depKey, - Class<E1> exceptionClass1, Class<E2> exceptionClass2) throws E1, E2; + <E1 extends Exception, E2 extends Exception> SkyValue getValueOrThrow( + SkyKey depKey, Class<E1> exceptionClass1, Class<E2> exceptionClass2) + throws E1, E2, InterruptedException; + @Nullable <E1 extends Exception, E2 extends Exception, E3 extends Exception> SkyValue getValueOrThrow( - SkyKey depKey, Class<E1> exceptionClass1, Class<E2> exceptionClass2, - Class<E3> exceptionClass3) throws E1, E2, E3; + SkyKey depKey, + Class<E1> exceptionClass1, + Class<E2> exceptionClass2, + Class<E3> exceptionClass3) + throws E1, E2, E3, InterruptedException; + @Nullable <E1 extends Exception, E2 extends Exception, E3 extends Exception, E4 extends Exception> - SkyValue getValueOrThrow(SkyKey depKey, Class<E1> exceptionClass1, - Class<E2> exceptionClass2, Class<E3> exceptionClass3, Class<E4> exceptionClass4) - throws E1, E2, E3, E4; + SkyValue getValueOrThrow( + SkyKey depKey, + Class<E1> exceptionClass1, + Class<E2> exceptionClass2, + Class<E3> exceptionClass3, + Class<E4> exceptionClass4) + throws E1, E2, E3, E4, InterruptedException; + @Nullable - <E1 extends Exception, E2 extends Exception, E3 extends Exception, E4 extends Exception, - E5 extends Exception> - SkyValue getValueOrThrow(SkyKey depKey, Class<E1> exceptionClass1, - Class<E2> exceptionClass2, Class<E3> exceptionClass3, Class<E4> exceptionClass4, - Class<E5> exceptionClass5) throws E1, E2, E3, E4, E5; + < + E1 extends Exception, + E2 extends Exception, + E3 extends Exception, + E4 extends Exception, + E5 extends Exception> + SkyValue getValueOrThrow( + SkyKey depKey, + Class<E1> exceptionClass1, + Class<E2> exceptionClass2, + Class<E3> exceptionClass3, + Class<E4> exceptionClass4, + Class<E5> exceptionClass5) + throws E1, E2, E3, E4, E5, InterruptedException; /** * Requests {@code depKeys} "in parallel", independent of each others' values. These keys may be @@ -131,27 +156,27 @@ public interface SkyFunction { * <p>This means that on subsequent evaluations, when checking to see if dependencies require * re-evaluation, all the values in this group may be simultaneously checked. A SkyFunction * should request a dependency group if checking the deps serially on a subsequent evaluation - * would take too long, and if the {@link #compute} method would request all deps anyway as - * long as no earlier deps had changed. SkyFunction.Environment implementations may also - * choose to request these deps in parallel on the first evaluation, potentially speeding it up. + * would take too long, and if the {@link #compute} method would request all deps anyway as long + * as no earlier deps had changed. SkyFunction.Environment implementations may also choose to + * request these deps in parallel on the first evaluation, potentially speeding it up. * - * <p>While re-evaluating every value in the group may take longer than re-evaluating just - * the first one and finding that it has changed, no extra work is done: the contract of the + * <p>While re-evaluating every value in the group may take longer than re-evaluating just the + * first one and finding that it has changed, no extra work is done: the contract of the * dependency group means that the {@link #compute} method, when called to re-evaluate this * value, will request all values in the group again anyway, so they would have to have been * built in any case. * * <p>Example of when to use getValues: A ListProcessor value is built with key inputListRef. - * The {@link #compute} method first calls getValue(InputList.key(inputListRef)), and - * retrieves inputList. It then iterates through inputList, calling getValue on each input. - * Finally, it processes the whole list and returns. Say inputList is (a, b, c). Since the - * {@link #compute} method will unconditionally call getValue(a), getValue(b), and getValue - * (c), the {@link #compute} method can instead just call getValues({a, b, c}). If the value - * is later dirtied the evaluator will evaluate a, b, and c in parallel (assuming the inputList - * value was unchanged), and re-evaluate the ListProcessor value only if at least one of them - * was changed. On the other hand, if the InputList changes to be (a, b, d), then the - * evaluator will see that the first dep has changed, and call the {@link #compute} method to - * re-evaluate from scratch, without considering the dep group of {a, b, c}. + * The {@link #compute} method first calls getValue(InputList.key(inputListRef)), and retrieves + * inputList. It then iterates through inputList, calling getValue on each input. Finally, it + * processes the whole list and returns. Say inputList is (a, b, c). Since the {@link #compute} + * method will unconditionally call getValue(a), getValue(b), and getValue (c), the {@link + * #compute} method can instead just call getValues({a, b, c}). If the value is later dirtied + * the evaluator will evaluate a, b, and c in parallel (assuming the inputList value was + * unchanged), and re-evaluate the ListProcessor value only if at least one of them was changed. + * On the other hand, if the InputList changes to be (a, b, d), then the evaluator will see that + * the first dep has changed, and call the {@link #compute} method to re-evaluate from scratch, + * without considering the dep group of {a, b, c}. * * <p>Example of when not to use getValues: A BestMatch value is built with key * <potentialMatchesRef, matchCriterion>. The {@link #compute} method first calls @@ -165,43 +190,64 @@ public interface SkyFunction { * is {@code true}, and, {@code m.get(k) != null} iff the dependency was already evaluated and * was not in error. */ - Map<SkyKey, SkyValue> getValues(Iterable<SkyKey> depKeys); + Map<SkyKey, SkyValue> getValues(Iterable<SkyKey> depKeys) throws InterruptedException; /** - * Similar to {@link #getValues} but allows the caller to specify a set of types that are - * proper subtypes of Exception (see {@link SkyFunctionException} for more details) to find - * out whether any of the dependencies' evaluations resulted in exceptions of those types. - * The returned objects may throw when attempting to retrieve their value. + * Similar to {@link #getValues} but allows the caller to specify a set of types that are proper + * subtypes of Exception (see {@link SkyFunctionException} for more details) to find out whether + * any of the dependencies' evaluations resulted in exceptions of those types. The returned + * objects may throw when attempting to retrieve their value. * - * <p>Callers should prioritize their responsibility to detect and handle errors in the - * returned map over their responsibility to return {@code null} if values are missing. This - * is because in nokeep_going evaluations, an error from a low level dependency is given a - * chance to be enriched by its reverse-dependencies, if possible. + * <p>Callers should prioritize their responsibility to detect and handle errors in the returned + * map over their responsibility to return {@code null} if values are missing. This is because + * in nokeep_going evaluations, an error from a low level dependency is given a chance to be + * enriched by its reverse-dependencies, if possible. * - * <p>Returns a map, {@code m}. For all {@code k} in {@code depKeys}, {@code m.get(k) != - * null}. For all {@code v} such that there is some {@code k} such that {@code m.get(k) == - * v}, the following is true: {@code v.get() != null} iff the dependency {@code k} was - * already evaluated and was not in error. {@code v.get()} throws {@code E} iff the - * dependency {@code k} was already evaluated with an error in the specified set of {@link - * Exception} types. + * <p>Returns a map, {@code m}. For all {@code k} in {@code depKeys}, {@code m.get(k) != null}. + * For all {@code v} such that there is some {@code k} such that {@code m.get(k) == v}, the + * following is true: {@code v.get() != null} iff the dependency {@code k} was already evaluated + * and was not in error. {@code v.get()} throws {@code E} iff the dependency {@code k} was + * already evaluated with an error in the specified set of {@link Exception} types. */ <E extends Exception> Map<SkyKey, ValueOrException<E>> getValuesOrThrow( - Iterable<SkyKey> depKeys, Class<E> exceptionClass); - <E1 extends Exception, E2 extends Exception> Map<SkyKey, ValueOrException2<E1, E2>> - getValuesOrThrow(Iterable<SkyKey> depKeys, Class<E1> exceptionClass1, - Class<E2> exceptionClass2); + Iterable<SkyKey> depKeys, Class<E> exceptionClass) throws InterruptedException; + + <E1 extends Exception, E2 extends Exception> + Map<SkyKey, ValueOrException2<E1, E2>> getValuesOrThrow( + Iterable<SkyKey> depKeys, Class<E1> exceptionClass1, Class<E2> exceptionClass2) + throws InterruptedException; + <E1 extends Exception, E2 extends Exception, E3 extends Exception> - Map<SkyKey, ValueOrException3<E1, E2, E3>> getValuesOrThrow(Iterable<SkyKey> depKeys, - Class<E1> exceptionClass1, Class<E2> exceptionClass2, Class<E3> exceptionClass3); + Map<SkyKey, ValueOrException3<E1, E2, E3>> getValuesOrThrow( + Iterable<SkyKey> depKeys, + Class<E1> exceptionClass1, + Class<E2> exceptionClass2, + Class<E3> exceptionClass3) + throws InterruptedException; + <E1 extends Exception, E2 extends Exception, E3 extends Exception, E4 extends Exception> - Map<SkyKey, ValueOrException4<E1, E2, E3, E4>> getValuesOrThrow(Iterable<SkyKey> depKeys, - Class<E1> exceptionClass1, Class<E2> exceptionClass2, Class<E3> exceptionClass3, - Class<E4> exceptionClass4); - <E1 extends Exception, E2 extends Exception, E3 extends Exception, E4 extends Exception, - E5 extends Exception> - Map<SkyKey, ValueOrException5<E1, E2, E3, E4, E5>> getValuesOrThrow(Iterable<SkyKey> depKeys, - Class<E1> exceptionClass1, Class<E2> exceptionClass2, Class<E3> exceptionClass3, - Class<E4> exceptionClass4, Class<E5> exceptionClass5); + Map<SkyKey, ValueOrException4<E1, E2, E3, E4>> getValuesOrThrow( + Iterable<SkyKey> depKeys, + Class<E1> exceptionClass1, + Class<E2> exceptionClass2, + Class<E3> exceptionClass3, + Class<E4> exceptionClass4) + throws InterruptedException; + + < + E1 extends Exception, + E2 extends Exception, + E3 extends Exception, + E4 extends Exception, + E5 extends Exception> + Map<SkyKey, ValueOrException5<E1, E2, E3, E4, E5>> getValuesOrThrow( + Iterable<SkyKey> depKeys, + Class<E1> exceptionClass1, + Class<E2> exceptionClass2, + Class<E3> exceptionClass3, + Class<E4> exceptionClass4, + Class<E5> exceptionClass5) + throws InterruptedException; /** * Returns whether there was a previous getValue[s][OrThrow] that indicated a missing diff --git a/src/main/java/com/google/devtools/build/skyframe/ThinNodeEntry.java b/src/main/java/com/google/devtools/build/skyframe/ThinNodeEntry.java index f81355c271..1ef077c103 100644 --- a/src/main/java/com/google/devtools/build/skyframe/ThinNodeEntry.java +++ b/src/main/java/com/google/devtools/build/skyframe/ThinNodeEntry.java @@ -15,7 +15,6 @@ package com.google.devtools.build.skyframe; import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe; import com.google.devtools.build.lib.util.Preconditions; - import javax.annotation.Nullable; /** @@ -47,23 +46,23 @@ public interface ThinNodeEntry { /** * Marks this node dirty, or changed if {@code isChanged} is true. The node is put in the - * just-created state. It will be re-evaluated if necessary during the evaluation phase, - * but if it has not changed, it will not force a re-evaluation of its parents. + * just-created state. It will be re-evaluated if necessary during the evaluation phase, but if it + * has not changed, it will not force a re-evaluation of its parents. * - * <p>{@code markDirty(b)} must not be called on an undone node if {@code isChanged() == b}. - * It is the caller's responsibility to ensure that this does not happen. Calling - * {@code markDirty(false)} when {@code isChanged() == true} has no effect. The idea here is that - * the caller will only ever want to call {@code markDirty()} a second time if a transition from a + * <p>{@code markDirty(b)} must not be called on an undone node if {@code isChanged() == b}. It is + * the caller's responsibility to ensure that this does not happen. Calling {@code + * markDirty(false)} when {@code isChanged() == true} has no effect. The idea here is that the + * caller will only ever want to call {@code markDirty()} a second time if a transition from a * dirty-unchanged state to a dirty-changed state is required. * - * @return A {@link ThinNodeEntry.MarkedDirtyResult} if the node was previously clean, and - * {@code null} if it was already dirty. If it was already dirty, the caller should abort its - * handling of this node, since another thread is already dealing with it. Note the warning on - * {@link ThinNodeEntry.MarkedDirtyResult} regarding the collection it provides. + * @return A {@link ThinNodeEntry.MarkedDirtyResult} if the node was previously clean, and {@code + * null} if it was already dirty. If it was already dirty, the caller should abort its + * handling of this node, since another thread is already dealing with it. Note the warning on + * {@link ThinNodeEntry.MarkedDirtyResult} regarding the collection it provides. */ @Nullable @ThreadSafe - MarkedDirtyResult markDirty(boolean isChanged); + MarkedDirtyResult markDirty(boolean isChanged) throws InterruptedException; /** * Returned by {@link #markDirty} if that call changed the node from clean to dirty. Contains an diff --git a/src/main/java/com/google/devtools/build/skyframe/WalkableGraph.java b/src/main/java/com/google/devtools/build/skyframe/WalkableGraph.java index 7c7a7e8954..9f71f1fdb1 100644 --- a/src/main/java/com/google/devtools/build/skyframe/WalkableGraph.java +++ b/src/main/java/com/google/devtools/build/skyframe/WalkableGraph.java @@ -15,15 +15,17 @@ package com.google.devtools.build.skyframe; import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe; import com.google.devtools.build.lib.events.EventHandler; - import java.util.Collection; import java.util.Map; - import javax.annotation.Nullable; /** * Read-only graph that exposes the dependents, dependencies (reverse dependents), and value and * exception (if any) of a given node. + * + * <p>Certain graph implementations can throw {@link InterruptedException} when trying to retrieve + * node entries. Such exceptions should not be caught locally -- they should be allowed to propagate + * up. */ @ThreadSafe public interface WalkableGraph { @@ -33,21 +35,21 @@ public interface WalkableGraph { * given node does not exist, this method should be called before any others, since the others * throw a {@link RuntimeException} on failure to access a node. */ - boolean exists(SkyKey key); + boolean exists(SkyKey key) throws InterruptedException; /** * Returns the value of the given key, or {@code null} if it has no value due to an error during * its computation. A node with this key must exist in the graph. */ @Nullable - SkyValue getValue(SkyKey key); + SkyValue getValue(SkyKey key) throws InterruptedException; /** * Returns a map giving the values of the given keys for done keys that were successfully - * computed. Or in other words, it filters out non-existent nodes, pending nodes and nodes - * that produced an exception. + * computed. Or in other words, it filters out non-existent nodes, pending nodes and nodes that + * produced an exception. */ - Map<SkyKey, SkyValue> getSuccessfulValues(Iterable<SkyKey> keys); + Map<SkyKey, SkyValue> getSuccessfulValues(Iterable<SkyKey> keys) throws InterruptedException; /** * Returns a map giving exceptions associated to the given keys for done keys. Keys not present in @@ -56,26 +58,27 @@ public interface WalkableGraph { * for {@code key} if and only if the node for {@code key} did <i>not</i> evaluate successfully * without error. */ - Map<SkyKey, Exception> getMissingAndExceptions(Iterable<SkyKey> keys); + Map<SkyKey, Exception> getMissingAndExceptions(Iterable<SkyKey> keys) throws InterruptedException; /** * Returns the exception thrown when computing the node with the given key, if any. If the node * was computed successfully, returns null. A node with this key must exist and be done in the * graph. */ - @Nullable Exception getException(SkyKey key); + @Nullable + Exception getException(SkyKey key) throws InterruptedException; /** * Returns a map giving the direct dependencies of the nodes with the given keys. A node for each * given key must exist and be done in the graph. */ - Map<SkyKey, Iterable<SkyKey>> getDirectDeps(Iterable<SkyKey> keys); + Map<SkyKey, Iterable<SkyKey>> getDirectDeps(Iterable<SkyKey> keys) throws InterruptedException; /** * Returns a map giving the reverse dependencies of the nodes with the given keys. A node for each * given key must exist and be done in the graph. */ - Map<SkyKey, Iterable<SkyKey>> getReverseDeps(Iterable<SkyKey> keys); + Map<SkyKey, Iterable<SkyKey>> getReverseDeps(Iterable<SkyKey> keys) throws InterruptedException; /** Provides a WalkableGraph on demand after preparing it. */ interface WalkableGraphFactory { diff --git a/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationTest.java b/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationTest.java index 53009de1e9..8f9e44311b 100644 --- a/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationTest.java +++ b/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationTest.java @@ -221,13 +221,11 @@ public class BuildConfigurationTest extends ConfigurationTestCase { @Override public Fragment create(ConfigurationEnvironment env, BuildOptions buildOptions) - throws InvalidConfigurationException { + throws InvalidConfigurationException, InterruptedException { for (Class<? extends Fragment> fragmentType : dependsOn) { env.getFragment(buildOptions, fragmentType); } - return new Fragment() { - - }; + return new Fragment() {}; } }; } diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/ActionTester.java b/src/test/java/com/google/devtools/build/lib/analysis/util/ActionTester.java index eca845975c..58eab302a4 100644 --- a/src/test/java/com/google/devtools/build/lib/analysis/util/ActionTester.java +++ b/src/test/java/com/google/devtools/build/lib/analysis/util/ActionTester.java @@ -31,14 +31,15 @@ public class ActionTester { /** * Returns a new action instance. The parameter {@code i} is used to vary the parameters used to - * create the action. Implementations should do something like this: - * <code><pre> + * create the action. Implementations should do something like this: <code> + * <pre> * return new MyAction(owner, inputs, outputs, configuration, * (i & 1) == 0 ? a1 : a2, * (i & 2) == 0 ? b1 : b2, * (i & 4) == 0 ? c1 : c2); * (i & 16) == 0 ? d1 : d2); - * </pre></code> + * </pre> + * </code> * * <p>The wrap-around (in this case at 32) is intentional and is checked for by the testing * method. @@ -50,7 +51,7 @@ public class ActionTester { * <p>Furthermore, when called with identical parameters, this method should return different * instances (i.e. according to {@code ==}), but they should have the same key. */ - Action generate(int i); + Action generate(int i) throws InterruptedException; } /** diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisTestUtil.java b/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisTestUtil.java index 304d964fdf..d046a234d0 100644 --- a/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisTestUtil.java +++ b/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisTestUtil.java @@ -52,7 +52,6 @@ import com.google.devtools.build.lib.testutil.TestConstants; import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.skyframe.SkyFunction; - import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -165,18 +164,19 @@ public final class AnalysisTestUtil { } @Override - public Artifact getStableWorkspaceStatusArtifact() { + public Artifact getStableWorkspaceStatusArtifact() throws InterruptedException { return original.getStableWorkspaceStatusArtifact(); } @Override - public Artifact getVolatileWorkspaceStatusArtifact() { + public Artifact getVolatileWorkspaceStatusArtifact() throws InterruptedException { return original.getVolatileWorkspaceStatusArtifact(); } @Override - public ImmutableList<Artifact> getBuildInfo(RuleContext ruleContext, BuildInfoKey key, - BuildConfiguration config) { + public ImmutableList<Artifact> getBuildInfo( + RuleContext ruleContext, BuildInfoKey key, BuildConfiguration config) + throws InterruptedException { return original.getBuildInfo(ruleContext, key, config); } diff --git a/src/test/java/com/google/devtools/build/lib/concurrent/AbstractQueueVisitorTest.java b/src/test/java/com/google/devtools/build/lib/concurrent/AbstractQueueVisitorTest.java index 8f6d389b98..7be04c4547 100644 --- a/src/test/java/com/google/devtools/build/lib/concurrent/AbstractQueueVisitorTest.java +++ b/src/test/java/com/google/devtools/build/lib/concurrent/AbstractQueueVisitorTest.java @@ -26,21 +26,18 @@ import com.google.common.util.concurrent.Uninterruptibles; import com.google.devtools.build.lib.concurrent.ErrorClassifier.ErrorClassification; import com.google.devtools.build.lib.testutil.TestThread; import com.google.devtools.build.lib.testutil.TestUtils; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; /** * Tests for AbstractQueueVisitor. @@ -350,20 +347,8 @@ public class AbstractQueueVisitorTest { ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 3, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); - final AtomicBoolean throwableSeen = new AtomicBoolean(false); - ErrorHandler errorHandler = new ErrorHandler() { - @Override - public void handle(Throwable t, ErrorClassification classification) { - if (t == THROWABLE) { - assertThat(classification).isEqualTo(ErrorClassification.CRITICAL); - throwableSeen.compareAndSet(false, true); - } else { - fail(); - } - } - }; - final AbstractQueueVisitor visitor = createQueueVisitorWithConstantErrorClassification( - executor, ErrorClassification.CRITICAL, errorHandler); + final AbstractQueueVisitor visitor = + createQueueVisitorWithConstantErrorClassification(executor, ErrorClassification.CRITICAL); final CountDownLatch latch1 = new CountDownLatch(1); final AtomicBoolean wasInterrupted = new AtomicBoolean(false); @@ -386,6 +371,7 @@ public class AbstractQueueVisitorTest { visitor.execute(r1); latch1.await(); visitor.execute(throwingRunnable()); + CountDownLatch exnLatch = visitor.getExceptionLatchForTestingOnly(); try { visitor.awaitQuiescence(/*interruptWorkers=*/ true); @@ -396,7 +382,7 @@ public class AbstractQueueVisitorTest { assertTrue(wasInterrupted.get()); assertTrue(executor.isShutdown()); - assertTrue(throwableSeen.get()); + assertTrue(exnLatch.await(0, TimeUnit.MILLISECONDS)); } @Test @@ -404,20 +390,9 @@ public class AbstractQueueVisitorTest { ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); final Error error = new Error("bad!"); - final AtomicBoolean criticalErrorSeen = new AtomicBoolean(false); - ErrorHandler errorHandler = new ErrorHandler() { - @Override - public void handle(Throwable t, ErrorClassification classification) { - if (t == error) { - assertThat(classification).isEqualTo(ErrorClassification.AS_CRITICAL_AS_POSSIBLE); - criticalErrorSeen.compareAndSet(false, true); - } else { - fail(); - } - } - }; - AbstractQueueVisitor visitor = createQueueVisitorWithConstantErrorClassification( - executor, ErrorClassification.NOT_CRITICAL, errorHandler); + AbstractQueueVisitor visitor = + createQueueVisitorWithConstantErrorClassification( + executor, ErrorClassification.NOT_CRITICAL); final CountDownLatch latch = new CountDownLatch(1); final AtomicBoolean sleepFinished = new AtomicBoolean(false); final AtomicBoolean sleepInterrupted = new AtomicBoolean(false); @@ -444,6 +419,7 @@ public class AbstractQueueVisitorTest { } } }; + CountDownLatch exnLatch = visitor.getExceptionLatchForTestingOnly(); visitor.execute(errorRunnable); visitor.execute(sleepRunnable); Error thrownError = null; @@ -457,7 +433,7 @@ public class AbstractQueueVisitorTest { assertTrue(sleepInterrupted.get()); assertFalse(sleepFinished.get()); assertEquals(error, thrownError); - assertTrue(criticalErrorSeen.get()); + assertTrue(exnLatch.await(0, TimeUnit.MILLISECONDS)); } private static class ClassifiedException extends RuntimeException { @@ -472,7 +448,6 @@ public class AbstractQueueVisitorTest { public void mostSevereErrorPropagated() throws Exception { ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); - final Set<Throwable> seenErrors = Sets.newConcurrentHashSet(); final ClassifiedException criticalException = new ClassifiedException(ErrorClassification.CRITICAL); final ClassifiedException criticalAndLogException = @@ -485,21 +460,13 @@ public class AbstractQueueVisitorTest { : ErrorClassification.NOT_CRITICAL; } }; - ErrorHandler errorHandler = new ErrorHandler() { - @Override - public void handle(Throwable t, ErrorClassification classification) { - assertThat(classification).isEqualTo(errorClassifier.classify(t)); - seenErrors.add(t); - } - }; AbstractQueueVisitor visitor = new AbstractQueueVisitor( - /*concurrent=*/ true, - executor, - /*shutdownOnCompletion=*/ true, - /*failFastOnException=*/ false, - errorClassifier, - errorHandler); + /*concurrent=*/ true, + executor, + /*shutdownOnCompletion=*/ true, + /*failFastOnException=*/ false, + errorClassifier); final CountDownLatch exnLatch = visitor.getExceptionLatchForTestingOnly(); Runnable criticalExceptionRunnable = new Runnable() { @Override @@ -532,7 +499,6 @@ public class AbstractQueueVisitorTest { exn = e; } assertEquals(criticalAndLogException, exn); - assertThat(seenErrors).containsExactly(criticalException, criticalAndLogException); } private static Runnable throwingRunnable() { @@ -636,8 +602,7 @@ public class AbstractQueueVisitorTest { } private static AbstractQueueVisitor createQueueVisitorWithConstantErrorClassification( - ThreadPoolExecutor executor, final ErrorClassification classification, - ErrorHandler errorHandler) { + ThreadPoolExecutor executor, final ErrorClassification classification) { return new AbstractQueueVisitor( /*concurrent=*/ true, executor, @@ -648,7 +613,6 @@ public class AbstractQueueVisitorTest { protected ErrorClassification classifyException(Exception e) { return classification; } - }, - errorHandler); + }); } } diff --git a/src/test/java/com/google/devtools/build/lib/packages/WorkspaceFactoryTest.java b/src/test/java/com/google/devtools/build/lib/packages/WorkspaceFactoryTest.java index ef81f436ed..84a6a29c31 100644 --- a/src/test/java/com/google/devtools/build/lib/packages/WorkspaceFactoryTest.java +++ b/src/test/java/com/google/devtools/build/lib/packages/WorkspaceFactoryTest.java @@ -28,14 +28,12 @@ import com.google.devtools.build.lib.syntax.ParserInputSource; import com.google.devtools.build.lib.testutil.Scratch; import com.google.devtools.build.lib.testutil.TestRuleClassProvider; import com.google.devtools.build.lib.vfs.Path; - +import java.io.IOException; +import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import java.io.IOException; -import java.util.List; - /** * Tests for WorkspaceFactory. */ @@ -137,7 +135,7 @@ public class WorkspaceFactoryTest { this.exception = exception; } - public Package getPackage() { + public Package getPackage() throws InterruptedException { return builder.build(); } diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionTest.java index d16068eee6..b2bd91a8b8 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionTest.java @@ -158,10 +158,10 @@ public class CppLinkActionTest extends BuildViewTestCase { new ActionCombinationFactory() { @Override - public Action generate(int i) { + public Action generate(int i) throws InterruptedException { CppLinkActionBuilder builder = - new CppLinkActionBuilder(ruleContext, (i & 2) == 0 - ? dynamicOutputFile : staticOutputFile) { + new CppLinkActionBuilder( + ruleContext, (i & 2) == 0 ? dynamicOutputFile : staticOutputFile) { @Override protected Artifact getInterfaceSoBuilder() { return interfaceSoBuilder; @@ -209,10 +209,10 @@ public class CppLinkActionTest extends BuildViewTestCase { new ActionCombinationFactory() { @Override - public Action generate(int i) { + public Action generate(int i) throws InterruptedException { CppLinkActionBuilder builder = - new CppLinkActionBuilder(ruleContext, (i & 2) == 0 - ? staticOutputFile : dynamicOutputFile) { + new CppLinkActionBuilder( + ruleContext, (i & 2) == 0 ? staticOutputFile : dynamicOutputFile) { @Override protected Artifact getInterfaceSoBuilder() { return interfaceSoBuilder; @@ -372,7 +372,8 @@ public class CppLinkActionTest extends BuildViewTestCase { } } - private void assertError(String expectedSubstring, CppLinkActionBuilder builder) { + private static void assertError(String expectedSubstring, CppLinkActionBuilder builder) + throws InterruptedException { try { builder.build(); fail(); diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternsFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternsFunctionTest.java index a21c6f5826..869423e55b 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternsFunctionTest.java +++ b/src/test/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternsFunctionTest.java @@ -30,13 +30,11 @@ import com.google.devtools.build.skyframe.EvaluationResult; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; import com.google.devtools.build.skyframe.WalkableGraph; - +import java.io.IOException; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import java.io.IOException; - /** Tests for {@link com.google.devtools.build.lib.skyframe.PrepareDepsOfPatternsFunction}. */ @RunWith(JUnit4.class) public class PrepareDepsOfPatternsFunctionTest extends BuildViewTestCase { @@ -250,16 +248,18 @@ public class PrepareDepsOfPatternsFunctionTest extends BuildViewTestCase { scratch.file("bar/BUILD"); } - private void assertValidValue(WalkableGraph graph, SkyKey key) { + private static void assertValidValue(WalkableGraph graph, SkyKey key) + throws InterruptedException { assertValidValue(graph, key, /*expectTransitiveException=*/ false); } /** - * A node in the walkable graph may have both a value and an exception. This happens when one - * of a node's transitive dependencies throws an exception, but its parent recovers from it. + * A node in the walkable graph may have both a value and an exception. This happens when one of a + * node's transitive dependencies throws an exception, but its parent recovers from it. */ - private void assertValidValue( - WalkableGraph graph, SkyKey key, boolean expectTransitiveException) { + private static void assertValidValue( + WalkableGraph graph, SkyKey key, boolean expectTransitiveException) + throws InterruptedException { assertTrue(graph.exists(key)); assertNotNull(graph.getValue(key)); if (expectTransitiveException) { @@ -269,7 +269,8 @@ public class PrepareDepsOfPatternsFunctionTest extends BuildViewTestCase { } } - private Exception assertException(WalkableGraph graph, SkyKey key) { + private static Exception assertException(WalkableGraph graph, SkyKey key) + throws InterruptedException { assertTrue(graph.exists(key)); assertNull(graph.getValue(key)); Exception exception = graph.getException(key); diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeAwareActionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeAwareActionTest.java index de989417da..7f08e04d95 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeAwareActionTest.java +++ b/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeAwareActionTest.java @@ -248,7 +248,8 @@ public class SkyframeAwareActionTest extends TimestampBuilderTestCase { } @Override - public void establishSkyframeDependencies(Environment env) throws ExceptionBase { + public void establishSkyframeDependencies(Environment env) + throws ExceptionBase, InterruptedException { // Establish some Skyframe dependency. A real action would then use this to compute and // cache data for the execute(...) method. env.getValue(actionDepKey); diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeLabelVisitorTestCase.java b/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeLabelVisitorTestCase.java index 25ddfc3b3c..80650fdf84 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeLabelVisitorTestCase.java +++ b/src/test/java/com/google/devtools/build/lib/skyframe/SkyframeLabelVisitorTestCase.java @@ -48,9 +48,6 @@ import com.google.devtools.build.skyframe.DelegatingWalkableGraph; import com.google.devtools.build.skyframe.InMemoryMemoizingEvaluator; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.WalkableGraph; - -import org.junit.Before; - import java.io.IOException; import java.util.ArrayList; import java.util.Collection; @@ -58,8 +55,8 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; - import javax.annotation.Nullable; +import org.junit.Before; abstract public class SkyframeLabelVisitorTestCase extends PackageLoadingTestCase { // Convenience constants, so test args are readable vs true/false @@ -179,7 +176,8 @@ abstract public class SkyframeLabelVisitorTestCase extends PackageLoadingTestCas * loaded targets. */ public static Set<Label> getVisitedLabels( - Iterable<Label> startingLabels, SkyframeExecutor skyframeExecutor) { + Iterable<Label> startingLabels, SkyframeExecutor skyframeExecutor) + throws InterruptedException { final WalkableGraph graph = new DelegatingWalkableGraph( ((InMemoryMemoizingEvaluator) skyframeExecutor.getEvaluatorForTesting()) diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceASTFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceASTFunctionTest.java index 4d61274456..832cb1c5c7 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceASTFunctionTest.java +++ b/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceASTFunctionTest.java @@ -27,7 +27,8 @@ import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.lib.vfs.RootedPath; import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyFunctionException; - +import java.io.IOException; +import java.util.List; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -35,9 +36,6 @@ import org.junit.runners.JUnit4; import org.mockito.Matchers; import org.mockito.Mockito; -import java.io.IOException; -import java.util.List; - /** * Test for WorkspaceASTFunction. */ @@ -65,7 +63,7 @@ public class WorkspaceASTFunctionTest extends BuildViewTestCase { workspacePath.getParentDirectory(), new PathFragment(workspacePath.getBaseName())); } - private SkyFunction.Environment getEnv() { + private SkyFunction.Environment getEnv() throws InterruptedException { SkyFunction.Environment env = Mockito.mock(SkyFunction.Environment.class); Mockito.when(env.getValue(Matchers.argThat(new SkyKeyMatchers(SkyFunctions.FILE)))) .thenReturn(fakeWorkspaceFileValue); diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunctionTest.java index 612debd861..6a5955721a 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunctionTest.java +++ b/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunctionTest.java @@ -36,7 +36,7 @@ import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyFunctionName; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - +import java.io.IOException; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; import org.junit.Before; @@ -48,8 +48,6 @@ import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import java.io.IOException; - /** * Test for {@link WorkspaceFileFunction}. */ @@ -148,7 +146,7 @@ public class WorkspaceFileFunctionTest extends BuildViewTestCase { public void describeTo(Description description) {} } - private SkyFunction.Environment getEnv() { + private SkyFunction.Environment getEnv() throws InterruptedException { SkyFunction.Environment env = Mockito.mock(SkyFunction.Environment.class); Mockito.when(env.getValue(Matchers.argThat(new SkyKeyMatchers(SkyFunctions.FILE)))) .thenReturn(fakeWorkspaceFileValue); diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/util/SkyframeExecutorTestUtils.java b/src/test/java/com/google/devtools/build/lib/skyframe/util/SkyframeExecutorTestUtils.java index 34218e67c8..34fb706b09 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/util/SkyframeExecutorTestUtils.java +++ b/src/test/java/com/google/devtools/build/lib/skyframe/util/SkyframeExecutorTestUtils.java @@ -34,10 +34,8 @@ import com.google.devtools.build.skyframe.EvaluationResult; import com.google.devtools.build.skyframe.MemoizingEvaluator; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; - import java.util.Collection; import java.util.List; - import javax.annotation.Nullable; /** @@ -57,11 +55,11 @@ public class SkyframeExecutorTestUtils { } /** - * Returns an existing error info, or {@code null} if the given key is not currently in the - * graph. + * Returns an existing error info, or {@code null} if the given key is not currently in the graph. */ @Nullable - public static ErrorInfo getExistingError(SkyframeExecutor skyframeExecutor, SkyKey key) { + public static ErrorInfo getExistingError(SkyframeExecutor skyframeExecutor, SkyKey key) + throws InterruptedException { return skyframeExecutor.getEvaluatorForTesting().getExistingErrorForTesting(key); } @@ -165,10 +163,11 @@ public class SkyframeExecutorTestUtils { * Returns the error info for an existing target value, or {@code null} if there is not an * appropriate target value key in the graph. * - * This helper is provided so legacy tests don't need to know about details of skyframe keys. + * <p>This helper is provided so legacy tests don't need to know about details of skyframe keys. */ @Nullable - public static ErrorInfo getExistingFailedTarget(SkyframeExecutor skyframeExecutor, Label label) { + public static ErrorInfo getExistingFailedTarget(SkyframeExecutor skyframeExecutor, Label label) + throws InterruptedException { SkyKey key = TargetMarkerValue.key(label); return getExistingError(skyframeExecutor, key); } diff --git a/src/test/java/com/google/devtools/build/skyframe/DeterministicHelper.java b/src/test/java/com/google/devtools/build/skyframe/DeterministicHelper.java index f2a1560f54..b27d2ef6e7 100644 --- a/src/test/java/com/google/devtools/build/skyframe/DeterministicHelper.java +++ b/src/test/java/com/google/devtools/build/skyframe/DeterministicHelper.java @@ -20,7 +20,6 @@ import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; - import javax.annotation.Nullable; /** @@ -77,7 +76,8 @@ public class DeterministicHelper extends NotifyingHelper { return entry == null ? null : new DeterministicValueEntry(key, entry); } - private static Map<SkyKey, NodeEntry> makeDeterministic(Map<SkyKey, NodeEntry> map) { + private static Map<SkyKey, ? extends NodeEntry> makeDeterministic( + Map<SkyKey, ? extends NodeEntry> map) { Map<SkyKey, NodeEntry> result = new TreeMap<>(ALPHABETICAL_SKYKEY_COMPARATOR); result.putAll(map); return result; @@ -89,10 +89,9 @@ public class DeterministicHelper extends NotifyingHelper { } @Override - public Map<SkyKey, NodeEntry> getBatch( - @Nullable SkyKey requestor, - Reason reason, - Iterable<SkyKey> keys) { + public Map<SkyKey, ? extends NodeEntry> getBatch( + @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys) + throws InterruptedException { return makeDeterministic(super.getBatch(requestor, reason, keys)); } } @@ -112,16 +111,16 @@ public class DeterministicHelper extends NotifyingHelper { } @Override - public Map<SkyKey, NodeEntry> createIfAbsentBatch( - @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys) { + public Map<SkyKey, ? extends NodeEntry> createIfAbsentBatch( + @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys) + throws InterruptedException { return makeDeterministic(super.createIfAbsentBatch(requestor, reason, keys)); } @Override - public Map<SkyKey, NodeEntry> getBatch( - @Nullable SkyKey requestor, - Reason reason, - Iterable<SkyKey> keys) { + public Map<SkyKey, ? extends NodeEntry> getBatch( + @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys) + throws InterruptedException { return makeDeterministic(super.getBatch(requestor, reason, keys)); } } diff --git a/src/test/java/com/google/devtools/build/skyframe/DeterministicInMemoryGraph.java b/src/test/java/com/google/devtools/build/skyframe/DeterministicInMemoryGraph.java index a0233838ec..79904d0bff 100644 --- a/src/test/java/com/google/devtools/build/skyframe/DeterministicInMemoryGraph.java +++ b/src/test/java/com/google/devtools/build/skyframe/DeterministicInMemoryGraph.java @@ -14,6 +14,7 @@ package com.google.devtools.build.skyframe; import java.util.Map; +import javax.annotation.Nullable; /** * {@link DeterministicHelper.DeterministicProcessableGraph} that implements the {@link @@ -27,6 +28,36 @@ class DeterministicInMemoryGraph extends DeterministicHelper.DeterministicProces } @Override + public Map<SkyKey, ? extends NodeEntry> createIfAbsentBatch( + @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys) { + try { + return super.createIfAbsentBatch(requestor, reason, keys); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } + } + + @Nullable + @Override + public NodeEntry get(@Nullable SkyKey requestor, Reason reason, SkyKey key) { + try { + return super.get(requestor, reason, key); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } + } + + @Override + public Map<SkyKey, ? extends NodeEntry> getBatch( + @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys) { + try { + return super.getBatch(requestor, reason, keys); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } + } + + @Override public Map<SkyKey, SkyValue> getValues() { return ((InMemoryGraph) delegate).getValues(); } @@ -36,8 +67,9 @@ class DeterministicInMemoryGraph extends DeterministicHelper.DeterministicProces return ((InMemoryGraph) delegate).getDoneValues(); } + @Override - public Map<SkyKey, NodeEntry> getAllValues() { + public Map<SkyKey, ? extends NodeEntry> getAllValues() { return ((InMemoryGraph) delegate).getAllValues(); } } diff --git a/src/test/java/com/google/devtools/build/skyframe/EvaluationResultSubject.java b/src/test/java/com/google/devtools/build/skyframe/EvaluationResultSubject.java index 5c99281a61..c86d6cfd48 100644 --- a/src/test/java/com/google/devtools/build/skyframe/EvaluationResultSubject.java +++ b/src/test/java/com/google/devtools/build/skyframe/EvaluationResultSubject.java @@ -53,13 +53,13 @@ public class EvaluationResultSubject extends Subject<EvaluationResultSubject, Ev .named("Error entry for " + getDisplaySubject()); } - public IterableSubject hasDirectDepsInGraphThat(SkyKey parent) { + public IterableSubject hasDirectDepsInGraphThat(SkyKey parent) throws InterruptedException { return assertThat( getSubject().getWalkableGraph().getDirectDeps(ImmutableList.of(parent)).get(parent)) .named("Direct deps for " + parent + " in " + getDisplaySubject()); } - public IterableSubject hasReverseDepsInGraphThat(SkyKey child) { + public IterableSubject hasReverseDepsInGraphThat(SkyKey child) throws InterruptedException { return assertThat( getSubject().getWalkableGraph().getReverseDeps(ImmutableList.of(child)).get(child)) .named("Reverse deps for " + child + " in " + getDisplaySubject()); diff --git a/src/test/java/com/google/devtools/build/skyframe/GraphConcurrencyTest.java b/src/test/java/com/google/devtools/build/skyframe/GraphConcurrencyTest.java index ca011cbb31..fa5a7dfaf7 100644 --- a/src/test/java/com/google/devtools/build/skyframe/GraphConcurrencyTest.java +++ b/src/test/java/com/google/devtools/build/skyframe/GraphConcurrencyTest.java @@ -31,9 +31,6 @@ import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.skyframe.GraphTester.StringValue; import com.google.devtools.build.skyframe.NodeEntry.DependencyState; import com.google.devtools.build.skyframe.QueryableGraph.Reason; -import org.junit.Before; -import org.junit.Test; - import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -43,6 +40,8 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import org.junit.Before; +import org.junit.Test; /** Base class for concurrency sanity tests on {@link EvaluableGraph} implementations. */ public abstract class GraphConcurrencyTest { @@ -76,12 +75,12 @@ public abstract class GraphConcurrencyTest { } @Test - public void createIfAbsentBatchSanity() { + public void createIfAbsentBatchSanity() throws InterruptedException { graph.createIfAbsentBatch(null, Reason.OTHER, ImmutableList.of(key("cat"), key("dog"))); } @Test - public void createIfAbsentConcurrentWithGet() { + public void createIfAbsentConcurrentWithGet() throws InterruptedException { int numIters = 50; final SkyKey key = key("key"); for (int i = 0; i < numIters; i++) { @@ -91,7 +90,11 @@ public abstract class GraphConcurrencyTest { new Runnable() { @Override public void run() { - graph.get(null, Reason.OTHER, key); + try { + graph.get(null, Reason.OTHER, key); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } } })); t.start(); @@ -111,7 +114,11 @@ public abstract class GraphConcurrencyTest { public void run() { TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions( startThreads, "threads not started"); - graph.createIfAbsentBatch(null, Reason.OTHER, ImmutableList.of(key)); + try { + graph.createIfAbsentBatch(null, Reason.OTHER, ImmutableList.of(key)); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } } }; Runnable noCreateRunnable = @@ -120,7 +127,11 @@ public abstract class GraphConcurrencyTest { public void run() { TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions( startThreads, "threads not started"); - graph.get(null, Reason.OTHER, key); + try { + graph.get(null, Reason.OTHER, key); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } } }; List<Thread> threads = new ArrayList<>(2 * numThreads); @@ -236,13 +247,22 @@ public abstract class GraphConcurrencyTest { new Runnable() { public void run() { for (SkyKey key : keys) { - NodeEntry entry = graph.get(null, Reason.OTHER, key); + NodeEntry entry = null; + try { + entry = graph.get(null, Reason.OTHER, key); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } if (entry == null) { nodeCreated.add(key); } } - Map<SkyKey, NodeEntry> entries = - graph.createIfAbsentBatch(null, Reason.OTHER, keys); + Map<SkyKey, ? extends NodeEntry> entries; + try { + entries = graph.createIfAbsentBatch(null, Reason.OTHER, keys); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } for (Integer keyNum : ImmutableList.of(keyNum1, keyNum2)) { SkyKey key = key("foo" + keyNum); NodeEntry entry = entries.get(key); @@ -251,12 +271,20 @@ public abstract class GraphConcurrencyTest { if (startEvaluation(entry).equals(DependencyState.NEEDS_SCHEDULING)) { assertTrue(valuesSet.add(key)); // Set to done. - entry.setValue(new StringValue("bar" + keyNum), startingVersion); + try { + entry.setValue(new StringValue("bar" + keyNum), startingVersion); + } catch (InterruptedException e) { + throw new IllegalStateException(key + ", " + entry, e); + } assertThat(entry.isDone()).isTrue(); } } // This shouldn't cause any problems from the other threads. - graph.createIfAbsentBatch(null, Reason.OTHER, keys); + try { + graph.createIfAbsentBatch(null, Reason.OTHER, keys); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } } }; pool.execute(wrapper.wrap(r)); @@ -278,8 +306,7 @@ public abstract class GraphConcurrencyTest { /** * Initially calling {@link NodeEntry#setValue} and then making sure concurrent calls to {@link - * QueryableGraph#get} and {@link QueryableGraph#getBatchWithFieldHints} do not interfere with the - * node. + * QueryableGraph#get} and {@link QueryableGraph#getBatch} do not interfere with the node. */ @Test public void testDoneToDirty() throws Exception { @@ -291,7 +318,7 @@ public abstract class GraphConcurrencyTest { for (int i = 0; i < numKeys; i++) { keys.add(key("foo" + i)); } - Map<SkyKey, NodeEntry> entries = graph.createIfAbsentBatch(null, Reason.OTHER, keys); + Map<SkyKey, ? extends NodeEntry> entries = graph.createIfAbsentBatch(null, Reason.OTHER, keys); for (int i = 0; i < numKeys; i++) { NodeEntry entry = entries.get(key("foo" + i)); startEvaluation(entry); @@ -325,15 +352,28 @@ public abstract class GraphConcurrencyTest { } catch (InterruptedException e) { throw new AssertionError(e); } - NodeEntry entry = graph.get(null, Reason.OTHER, key("foo" + keyNum)); - entry.markDirty(true); + NodeEntry entry = null; + try { + entry = graph.get(null, Reason.OTHER, key("foo" + keyNum)); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } + try { + entry.markDirty(true); + } catch (InterruptedException e) { + throw new IllegalStateException(keyNum + ", " + entry, e); + } // Make some changes, like adding a dep and rdep. entry.addReverseDepAndCheckIfDone(key("rdep")); entry.markRebuilding(); addTemporaryDirectDep(entry, key("dep")); entry.signalDep(); // Move node from dirty back to done. - entry.setValue(new StringValue("bar" + keyNum), getNextVersion(startingVersion)); + try { + entry.setValue(new StringValue("bar" + keyNum), getNextVersion(startingVersion)); + } catch (InterruptedException e) { + throw new IllegalStateException(keyNum + ", " + entry, e); + } } }; @@ -347,13 +387,18 @@ public abstract class GraphConcurrencyTest { } catch (InterruptedException e) { throw new AssertionError(e); } - NodeEntry entry = graph.get(null, Reason.OTHER, key("foo" + keyNum)); + NodeEntry entry = null; + try { + entry = graph.get(null, Reason.OTHER, key("foo" + keyNum)); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } assertNotNull(entry); // Requests for the value are made at the same time that the version increments from // the base. Check that there is no problem in requesting the version and that the // number is sane. - assertThat(entry.getVersion()).isAnyOf(startingVersion, - getNextVersion(startingVersion)); + assertThat(entry.getVersion()) + .isAnyOf(startingVersion, getNextVersion(startingVersion)); getCountDownLatch.countDown(); } }; @@ -380,7 +425,12 @@ public abstract class GraphConcurrencyTest { } catch (InterruptedException e) { throw new AssertionError(e); } - Map<SkyKey, NodeEntry> batchMap = graph.getBatch(null, Reason.OTHER, batch); + Map<SkyKey, ? extends NodeEntry> batchMap = null; + try { + batchMap = graph.getBatch(null, Reason.OTHER, batch); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } getBatchCountDownLatch.countDown(); assertThat(batchMap).hasSize(batch.size()); for (NodeEntry entry : batchMap.values()) { @@ -411,7 +461,7 @@ public abstract class GraphConcurrencyTest { } } - private DependencyState startEvaluation(NodeEntry entry) { + private static DependencyState startEvaluation(NodeEntry entry) { return entry.addReverseDepAndCheckIfDone(null); } diff --git a/src/test/java/com/google/devtools/build/skyframe/InMemoryNodeEntryTest.java b/src/test/java/com/google/devtools/build/skyframe/InMemoryNodeEntryTest.java index 23c1fca413..00681c8d3b 100644 --- a/src/test/java/com/google/devtools/build/skyframe/InMemoryNodeEntryTest.java +++ b/src/test/java/com/google/devtools/build/skyframe/InMemoryNodeEntryTest.java @@ -32,16 +32,13 @@ import com.google.devtools.build.lib.util.GroupedList.GroupedListHelper; import com.google.devtools.build.skyframe.NodeEntry.DependencyState; import com.google.devtools.build.skyframe.SkyFunctionException.ReifiedSkyFunctionException; import com.google.devtools.build.skyframe.SkyFunctionException.Transience; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - import java.util.ArrayList; import java.util.List; import java.util.Set; - import javax.annotation.Nullable; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; /** * Tests for {@link InMemoryNodeEntry}. @@ -69,7 +66,7 @@ public class InMemoryNodeEntryTest { } @Test - public void signalEntry() { + public void signalEntry() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. SkyKey dep1 = key("dep1"); @@ -95,7 +92,7 @@ public class InMemoryNodeEntryTest { } @Test - public void reverseDeps() { + public void reverseDeps() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); SkyKey mother = key("mother"); SkyKey father = key("father"); @@ -111,7 +108,7 @@ public class InMemoryNodeEntryTest { } @Test - public void errorValue() { + public void errorValue() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. ReifiedSkyFunctionException exception = new ReifiedSkyFunctionException( @@ -125,7 +122,7 @@ public class InMemoryNodeEntryTest { } @Test - public void errorAndValue() { + public void errorAndValue() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. ReifiedSkyFunctionException exception = new ReifiedSkyFunctionException( @@ -138,7 +135,7 @@ public class InMemoryNodeEntryTest { } @Test - public void crashOnNullErrorAndValue() { + public void crashOnNullErrorAndValue() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. try { @@ -162,7 +159,7 @@ public class InMemoryNodeEntryTest { } @Test - public void crashOnDifferentValue() { + public void crashOnDifferentValue() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. setValue(entry, new SkyValue() {}, /*errorInfo=*/null, /*graphVersion=*/0L); @@ -176,7 +173,7 @@ public class InMemoryNodeEntryTest { } @Test - public void dirtyLifecycle() { + public void dirtyLifecycle() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. SkyKey dep = key("dep"); @@ -208,7 +205,7 @@ public class InMemoryNodeEntryTest { } @Test - public void changedLifecycle() { + public void changedLifecycle() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. SkyKey dep = key("dep"); @@ -237,7 +234,7 @@ public class InMemoryNodeEntryTest { } @Test - public void markDirtyThenChanged() { + public void markDirtyThenChanged() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. addTemporaryDirectDep(entry, key("dep")); @@ -261,7 +258,7 @@ public class InMemoryNodeEntryTest { @Test - public void markChangedThenDirty() { + public void markChangedThenDirty() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. addTemporaryDirectDep(entry, key("dep")); @@ -284,7 +281,7 @@ public class InMemoryNodeEntryTest { } @Test - public void crashOnTwiceMarkedChanged() { + public void crashOnTwiceMarkedChanged() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. setValue(entry, new SkyValue() {}, /*errorInfo=*/null, /*graphVersion=*/0L); @@ -300,7 +297,7 @@ public class InMemoryNodeEntryTest { } @Test - public void crashOnTwiceMarkedDirty() { + public void crashOnTwiceMarkedDirty() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. addTemporaryDirectDep(entry, key("dep")); @@ -316,7 +313,7 @@ public class InMemoryNodeEntryTest { } @Test - public void crashOnAddReverseDepTwice() { + public void crashOnAddReverseDepTwice() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); SkyKey parent = key("parent"); assertEquals(DependencyState.NEEDS_SCHEDULING, entry.addReverseDepAndCheckIfDone(parent)); @@ -331,7 +328,7 @@ public class InMemoryNodeEntryTest { } @Test - public void crashOnAddReverseDepTwiceAfterDone() { + public void crashOnAddReverseDepTwiceAfterDone() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. setValue(entry, new SkyValue() {}, /*errorInfo=*/null, /*graphVersion=*/0L); @@ -348,7 +345,7 @@ public class InMemoryNodeEntryTest { } @Test - public void crashOnAddReverseDepBeforeAfterDone() { + public void crashOnAddReverseDepBeforeAfterDone() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); SkyKey parent = key("parent"); assertEquals(DependencyState.NEEDS_SCHEDULING, entry.addReverseDepAndCheckIfDone(parent)); @@ -364,7 +361,7 @@ public class InMemoryNodeEntryTest { } @Test - public void pruneBeforeBuild() { + public void pruneBeforeBuild() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); SkyKey dep = key("dep"); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. @@ -412,7 +409,7 @@ public class InMemoryNodeEntryTest { } @Test - public void pruneAfterBuild() { + public void pruneAfterBuild() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. SkyKey dep = key("dep"); @@ -435,7 +432,7 @@ public class InMemoryNodeEntryTest { } @Test - public void noPruneWhenDetailsChange() { + public void noPruneWhenDetailsChange() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. SkyKey dep = key("dep"); @@ -471,7 +468,7 @@ public class InMemoryNodeEntryTest { } @Test - public void pruneWhenDepGroupReordered() { + public void pruneWhenDepGroupReordered() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. SkyKey dep = key("dep"); @@ -511,7 +508,7 @@ public class InMemoryNodeEntryTest { } @Test - public void errorInfoCannotBePruned() { + public void errorInfoCannotBePruned() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. SkyKey dep = key("dep"); @@ -538,7 +535,7 @@ public class InMemoryNodeEntryTest { } @Test - public void getDependencyGroup() { + public void getDependencyGroup() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. SkyKey dep = key("dep"); @@ -562,7 +559,7 @@ public class InMemoryNodeEntryTest { } @Test - public void maintainDependencyGroupAfterRemoval() { + public void maintainDependencyGroupAfterRemoval() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. SkyKey dep = key("dep"); @@ -592,7 +589,7 @@ public class InMemoryNodeEntryTest { } @Test - public void pruneWhenDepsChange() { + public void pruneWhenDepsChange() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. SkyKey dep = key("dep"); @@ -616,7 +613,7 @@ public class InMemoryNodeEntryTest { } @Test - public void checkDepsOneByOne() { + public void checkDepsOneByOne() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(null); // Start evaluation. List<SkyKey> deps = new ArrayList<>(); @@ -643,7 +640,7 @@ public class InMemoryNodeEntryTest { } @Test - public void signalOnlyNewParents() { + public void signalOnlyNewParents() throws InterruptedException { NodeEntry entry = new InMemoryNodeEntry(); entry.addReverseDepAndCheckIfDone(key("parent")); setValue(entry, new SkyValue() {}, /*errorInfo=*/null, /*graphVersion=*/0L); @@ -657,7 +654,7 @@ public class InMemoryNodeEntryTest { } @Test - public void testClone() { + public void testClone() throws InterruptedException { InMemoryNodeEntry entry = new InMemoryNodeEntry(); IntVersion version = IntVersion.of(0); IntegerValue originalValue = new IntegerValue(42); @@ -701,7 +698,7 @@ public class InMemoryNodeEntryTest { } @Test - public void getGroupedDirectDeps() { + public void getGroupedDirectDeps() throws InterruptedException { InMemoryNodeEntry entry = new InMemoryNodeEntry(); ImmutableList<ImmutableSet<SkyKey>> groupedDirectDeps = ImmutableList.of( ImmutableSet.of(key("1A")), @@ -726,8 +723,9 @@ public class InMemoryNodeEntryTest { } } - private static Set<SkyKey> setValue(NodeEntry entry, SkyValue value, - @Nullable ErrorInfo errorInfo, long graphVersion) { + private static Set<SkyKey> setValue( + NodeEntry entry, SkyValue value, @Nullable ErrorInfo errorInfo, long graphVersion) + throws InterruptedException { return entry.setValue( ValueWithMetadata.normal(value, errorInfo, NO_EVENTS), IntVersion.of(graphVersion)); } diff --git a/src/test/java/com/google/devtools/build/skyframe/MemoizingEvaluatorTest.java b/src/test/java/com/google/devtools/build/skyframe/MemoizingEvaluatorTest.java index 7b55d6f37c..0afcb62c5c 100644 --- a/src/test/java/com/google/devtools/build/skyframe/MemoizingEvaluatorTest.java +++ b/src/test/java/com/google/devtools/build/skyframe/MemoizingEvaluatorTest.java @@ -33,6 +33,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import com.google.common.base.Predicates; +import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -987,7 +988,7 @@ public class MemoizingEvaluatorTest { new SkyFunction() { @Nullable @Override - public SkyValue compute(SkyKey skyKey, Environment env) { + public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { env.getValues(ImmutableList.of(leafKey, bKey)); return null; } @@ -1229,17 +1230,20 @@ public class MemoizingEvaluatorTest { tester.set(dep2, new StringValue("dep2")); // otherTop should request the deps one at a time, so that it can be in the CHECK_DEPENDENCIES // state even after one dep is re-evaluated. - tester.getOrCreate(otherTop).setBuilder(new NoExtractorFunction() { - @Override - public SkyValue compute(SkyKey skyKey, Environment env) { - env.getValue(dep1); - if (env.valuesMissing()) { - return null; - } - env.getValue(dep2); - return env.valuesMissing() ? null : new StringValue("otherTop"); - } - }); + tester + .getOrCreate(otherTop) + .setBuilder( + new NoExtractorFunction() { + @Override + public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { + env.getValue(dep1); + if (env.valuesMissing()) { + return null; + } + env.getValue(dep2); + return env.valuesMissing() ? null : new StringValue("otherTop"); + } + }); // Prime the graph with otherTop, so we can dirty it next build. assertEquals(new StringValue("otherTop"), tester.evalAndGet(/*keepGoing=*/false, otherTop)); // Mark dep1 changed, so otherTop will be dirty and request re-evaluation of dep1. @@ -1787,23 +1791,28 @@ public class MemoizingEvaluatorTest { tester.set(groupDepA, new StringValue("depC")); tester.set(groupDepB, new StringValue("")); tester.getOrCreate(depC).setHasError(true); - tester.getOrCreate(topKey).setBuilder(new NoExtractorFunction() { - @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException { - StringValue val = ((StringValue) env.getValues( - ImmutableList.of(groupDepA, groupDepB)).get(groupDepA)); - if (env.valuesMissing()) { - return null; - } - String nextDep = val.getValue(); - try { - env.getValueOrThrow(GraphTester.toSkyKey(nextDep), SomeErrorException.class); - } catch (SomeErrorException e) { - throw new GenericFunctionException(e, Transience.PERSISTENT); - } - return env.valuesMissing() ? null : new StringValue("top"); - } - }); + tester + .getOrCreate(topKey) + .setBuilder( + new NoExtractorFunction() { + @Override + public SkyValue compute(SkyKey skyKey, Environment env) + throws SkyFunctionException, InterruptedException { + StringValue val = + ((StringValue) + env.getValues(ImmutableList.of(groupDepA, groupDepB)).get(groupDepA)); + if (env.valuesMissing()) { + return null; + } + String nextDep = val.getValue(); + try { + env.getValueOrThrow(GraphTester.toSkyKey(nextDep), SomeErrorException.class); + } catch (SomeErrorException e) { + throw new GenericFunctionException(e, Transience.PERSISTENT); + } + return env.valuesMissing() ? null : new StringValue("top"); + } + }); EvaluationResult<StringValue> evaluationResult = tester.eval( /*keepGoing=*/true, groupDepA, depC); @@ -1892,20 +1901,25 @@ public class MemoizingEvaluatorTest { tester.set(firstKey, new StringValue("biding")); tester.set(slowAddingDep, new StringValue("dep")); final AtomicInteger numTopInvocations = new AtomicInteger(0); - tester.getOrCreate(top).setBuilder(new NoExtractorFunction() { - @Override - public SkyValue compute(SkyKey key, SkyFunction.Environment env) { - numTopInvocations.incrementAndGet(); - if (delayTopSignaling.get()) { - // The reporter will be given firstKey's warning to emit when it is requested as a dep - // below, if firstKey is already built, so we release the reporter's latch beforehand. - topRestartedBuild.countDown(); - } - // top's builder just requests both deps in a group. - env.getValuesOrThrow(ImmutableList.of(firstKey, slowAddingDep), SomeErrorException.class); - return env.valuesMissing() ? null : new StringValue("top"); - } - }); + tester + .getOrCreate(top) + .setBuilder( + new NoExtractorFunction() { + @Override + public SkyValue compute(SkyKey key, SkyFunction.Environment env) + throws InterruptedException { + numTopInvocations.incrementAndGet(); + if (delayTopSignaling.get()) { + // The reporter will be given firstKey's warning to emit when it is requested as a dep + // below, if firstKey is already built, so we release the reporter's latch beforehand. + topRestartedBuild.countDown(); + } + // top's builder just requests both deps in a group. + env.getValuesOrThrow( + ImmutableList.of(firstKey, slowAddingDep), SomeErrorException.class); + return env.valuesMissing() ? null : new StringValue("top"); + } + }); reporter = new DelegatingEventHandler(reporter) { @Override @@ -2581,7 +2595,7 @@ public class MemoizingEvaluatorTest { .setBuilder( new SkyFunction() { @Override - public SkyValue compute(SkyKey skyKey, Environment env) { + public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { topEvaluated.set(true); return env.getValue(leaf) == null ? null : fixedTopValue; } @@ -2636,7 +2650,7 @@ public class MemoizingEvaluatorTest { .setBuilder( new SkyFunction() { @Override - public SkyValue compute(SkyKey skyKey, Environment env) { + public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { topEvaluated.set(true); return env.getValue(other) == null || env.getValue(leaf) == null @@ -2682,27 +2696,29 @@ public class MemoizingEvaluatorTest { public void changedChildChangesDepOfParent() throws Exception { initializeTester(); final SkyKey buildFile = GraphTester.toSkyKey("buildFile"); - ValueComputer authorDrink = new ValueComputer() { - @Override - public SkyValue compute(Map<SkyKey, SkyValue> deps, SkyFunction.Environment env) { - String author = ((StringValue) deps.get(buildFile)).getValue(); - StringValue beverage; - switch (author) { - case "hemingway": - beverage = (StringValue) env.getValue(GraphTester.toSkyKey("absinthe")); - break; - case "joyce": - beverage = (StringValue) env.getValue(GraphTester.toSkyKey("whiskey")); - break; - default: - throw new IllegalStateException(author); - } - if (beverage == null) { - return null; - } - return new StringValue(author + " drank " + beverage.getValue()); - } - }; + ValueComputer authorDrink = + new ValueComputer() { + @Override + public SkyValue compute(Map<SkyKey, SkyValue> deps, SkyFunction.Environment env) + throws InterruptedException { + String author = ((StringValue) deps.get(buildFile)).getValue(); + StringValue beverage; + switch (author) { + case "hemingway": + beverage = (StringValue) env.getValue(GraphTester.toSkyKey("absinthe")); + break; + case "joyce": + beverage = (StringValue) env.getValue(GraphTester.toSkyKey("whiskey")); + break; + default: + throw new IllegalStateException(author); + } + if (beverage == null) { + return null; + } + return new StringValue(author + " drank " + beverage.getValue()); + } + }; tester.set(buildFile, new StringValue("hemingway")); SkyKey absinthe = GraphTester.toSkyKey("absinthe"); @@ -3267,7 +3283,8 @@ public class MemoizingEvaluatorTest { .setBuilder( new SkyFunction() { @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException { + public SkyValue compute(SkyKey skyKey, Environment env) + throws SkyFunctionException, InterruptedException { otherStarted.countDown(); int invocations = numOtherInvocations.incrementAndGet(); // And given that otherErrorKey waits for errorKey's error to be committed before @@ -3865,6 +3882,15 @@ public class MemoizingEvaluatorTest { */ @Test public void shutDownBuildOnCachedError_Verified() throws Exception { + // TrackingInvalidationReceiver does unnecessary examination of node values. + initializeTester( + new TrackingInvalidationReceiver() { + @Override + public void evaluated( + SkyKey skyKey, Supplier<SkyValue> skyValueSupplier, EvaluationState state) { + evaluated.add(skyKey); + } + }); // errorKey will be invalidated due to its dependence on invalidatedKey, but later revalidated // since invalidatedKey re-evaluates to the same value on a subsequent build. SkyKey errorKey = GraphTester.toSkyKey("error"); @@ -3991,6 +4017,15 @@ public class MemoizingEvaluatorTest { */ @Test public void cachedErrorCausesRestart() throws Exception { + // TrackingInvalidationReceiver does unnecessary examination of node values. + initializeTester( + new TrackingInvalidationReceiver() { + @Override + public void evaluated( + SkyKey skyKey, Supplier<SkyValue> skyValueSupplier, EvaluationState state) { + evaluated.add(skyKey); + } + }); final SkyKey errorKey = GraphTester.toSkyKey("error"); SkyKey invalidatedKey = GraphTester.toSkyKey("invalidated"); final SkyKey topKey = GraphTester.toSkyKey("top"); @@ -4074,22 +4109,23 @@ public class MemoizingEvaluatorTest { SkyKey parent2Key = GraphTester.toSkyKey("parent2"); final SkyKey errorKey = GraphTester.toSkyKey("error"); final SkyKey otherKey = GraphTester.toSkyKey("other"); - SkyFunction parentBuilder = new SkyFunction() { - @Override - public SkyValue compute(SkyKey skyKey, Environment env) { - env.getValue(errorKey); - env.getValue(otherKey); - if (env.valuesMissing()) { - return null; - } - return new StringValue("parent"); - } + SkyFunction parentBuilder = + new SkyFunction() { + @Override + public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { + env.getValue(errorKey); + env.getValue(otherKey); + if (env.valuesMissing()) { + return null; + } + return new StringValue("parent"); + } - @Override - public String extractTag(SkyKey skyKey) { - return null; - } - }; + @Override + public String extractTag(SkyKey skyKey) { + return null; + } + }; tester.getOrCreate(parent1Key).setBuilder(parentBuilder); tester.getOrCreate(parent2Key).setBuilder(parentBuilder); tester.getOrCreate(errorKey).setConstantValue(new StringValue("no error yet")); @@ -4400,12 +4436,12 @@ public class MemoizingEvaluatorTest { } @Nullable - public SkyValue getExistingValue(SkyKey key) { + public SkyValue getExistingValue(SkyKey key) throws InterruptedException { return driver.getExistingValueForTesting(key); } @Nullable - public SkyValue getExistingValue(String key) { + public SkyValue getExistingValue(String key) throws InterruptedException { return getExistingValue(toSkyKey(key)); } } diff --git a/src/test/java/com/google/devtools/build/skyframe/NotifyingHelper.java b/src/test/java/com/google/devtools/build/skyframe/NotifyingHelper.java index ad9a591eb8..5adbe45eb6 100644 --- a/src/test/java/com/google/devtools/build/skyframe/NotifyingHelper.java +++ b/src/test/java/com/google/devtools/build/skyframe/NotifyingHelper.java @@ -21,7 +21,6 @@ import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe; import com.google.devtools.build.lib.util.GroupedList; import java.util.Map; import java.util.Set; - import javax.annotation.Nullable; /** @@ -87,10 +86,9 @@ public class NotifyingHelper { } @Override - public Map<SkyKey, NodeEntry> getBatch( - @Nullable SkyKey requestor, - Reason reason, - Iterable<SkyKey> keys) { + public Map<SkyKey, ? extends NodeEntry> getBatch( + @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys) + throws InterruptedException { return Maps.transformEntries( delegate.getBatch(requestor, reason, keys), notifyingHelper.wrapEntry); @@ -98,7 +96,8 @@ public class NotifyingHelper { @Nullable @Override - public NodeEntry get(@Nullable SkyKey requestor, Reason reason, SkyKey key) { + public NodeEntry get(@Nullable SkyKey requestor, Reason reason, SkyKey key) + throws InterruptedException { return notifyingHelper.wrapEntry(key, delegate.get(requestor, reason, key)); } } @@ -122,8 +121,9 @@ public class NotifyingHelper { } @Override - public Map<SkyKey, NodeEntry> createIfAbsentBatch( - @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys) { + public Map<SkyKey, ? extends NodeEntry> createIfAbsentBatch( + @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys) + throws InterruptedException { for (SkyKey key : keys) { notifyingHelper.graphListener.accept(key, EventType.CREATE_IF_ABSENT, Order.BEFORE, null); } @@ -245,7 +245,7 @@ public class NotifyingHelper { } @Override - public Set<SkyKey> setValue(SkyValue value, Version version) { + public Set<SkyKey> setValue(SkyValue value, Version version) throws InterruptedException { graphListener.accept(myKey, EventType.SET_VALUE, Order.BEFORE, value); Set<SkyKey> result = super.setValue(value, version); graphListener.accept(myKey, EventType.SET_VALUE, Order.AFTER, value); @@ -253,7 +253,7 @@ public class NotifyingHelper { } @Override - public MarkedDirtyResult markDirty(boolean isChanged) { + public MarkedDirtyResult markDirty(boolean isChanged) throws InterruptedException { graphListener.accept(myKey, EventType.MARK_DIRTY, Order.BEFORE, isChanged); MarkedDirtyResult result = super.markDirty(isChanged); graphListener.accept(myKey, EventType.MARK_DIRTY, Order.AFTER, isChanged); @@ -261,7 +261,7 @@ public class NotifyingHelper { } @Override - public Set<SkyKey> markClean() { + public Set<SkyKey> markClean() throws InterruptedException { graphListener.accept(myKey, EventType.MARK_CLEAN, Order.BEFORE, this); Set<SkyKey> result = super.markClean(); graphListener.accept(myKey, EventType.MARK_CLEAN, Order.AFTER, this); @@ -287,7 +287,7 @@ public class NotifyingHelper { } @Override - public SkyValue getValueMaybeWithMetadata() { + public SkyValue getValueMaybeWithMetadata() throws InterruptedException { graphListener.accept(myKey, EventType.GET_VALUE_WITH_METADATA, Order.BEFORE, this); return super.getValueMaybeWithMetadata(); } diff --git a/src/test/java/com/google/devtools/build/skyframe/NotifyingInMemoryGraph.java b/src/test/java/com/google/devtools/build/skyframe/NotifyingInMemoryGraph.java index 752dac7001..31242dac47 100644 --- a/src/test/java/com/google/devtools/build/skyframe/NotifyingInMemoryGraph.java +++ b/src/test/java/com/google/devtools/build/skyframe/NotifyingInMemoryGraph.java @@ -14,6 +14,7 @@ package com.google.devtools.build.skyframe; import java.util.Map; +import javax.annotation.Nullable; /** {@link NotifyingHelper} that additionally implements the {@link InMemoryGraph} interface. */ class NotifyingInMemoryGraph extends NotifyingHelper.NotifyingProcessableGraph @@ -23,6 +24,36 @@ class NotifyingInMemoryGraph extends NotifyingHelper.NotifyingProcessableGraph } @Override + public Map<SkyKey, ? extends NodeEntry> createIfAbsentBatch( + @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys) { + try { + return super.createIfAbsentBatch(requestor, reason, keys); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } + } + + @Nullable + @Override + public NodeEntry get(@Nullable SkyKey requestor, Reason reason, SkyKey key) { + try { + return super.get(requestor, reason, key); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } + } + + @Override + public Map<SkyKey, ? extends NodeEntry> getBatch( + @Nullable SkyKey requestor, Reason reason, Iterable<SkyKey> keys) { + try { + return super.getBatch(requestor, reason, keys); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } + } + + @Override public Map<SkyKey, SkyValue> getValues() { return ((InMemoryGraph) delegate).getValues(); } @@ -33,7 +64,7 @@ class NotifyingInMemoryGraph extends NotifyingHelper.NotifyingProcessableGraph } @Override - public Map<SkyKey, NodeEntry> getAllValues() { + public Map<SkyKey, ? extends NodeEntry> getAllValues() { return ((InMemoryGraph) delegate).getAllValues(); } } diff --git a/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java b/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java index 9c87572818..c8464b4291 100644 --- a/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java +++ b/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java @@ -48,14 +48,6 @@ import com.google.devtools.build.skyframe.NotifyingHelper.Listener; import com.google.devtools.build.skyframe.NotifyingHelper.Order; import com.google.devtools.build.skyframe.ParallelEvaluator.EventFilter; import com.google.devtools.build.skyframe.SkyFunctionException.Transience; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -67,8 +59,13 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; - import javax.annotation.Nullable; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; /** * Tests for {@link ParallelEvaluator}. @@ -202,36 +199,38 @@ public class ParallelEvaluatorTest { */ @Test public void interruptedEvaluatorThread() throws Exception { - runInterruptionTest(new SkyFunctionFactory() { - @Override - public SkyFunction create(final Semaphore threadStarted, final String[] errorMessage) { - return new SkyFunction() { - // No need to synchronize access to this field; we always request just one more - // dependency, so it's only one SkyFunction running at any time. - private int valueIdCounter = 0; - + runInterruptionTest( + new SkyFunctionFactory() { @Override - public SkyValue compute(SkyKey key, Environment env) { - // Signal the waiting test thread that the Evaluator thread has really started. - threadStarted.release(); + public SkyFunction create(final Semaphore threadStarted, final String[] errorMessage) { + return new SkyFunction() { + // No need to synchronize access to this field; we always request just one more + // dependency, so it's only one SkyFunction running at any time. + private int valueIdCounter = 0; - // Keep the evaluator busy until the test's thread gets scheduled and can - // interrupt the Evaluator's thread. - env.getValue(GraphTester.toSkyKey("a" + valueIdCounter++)); + @Override + public SkyValue compute(SkyKey key, Environment env) throws InterruptedException { + // Signal the waiting test thread that the Evaluator thread has really started. + threadStarted.release(); - // This method never throws InterruptedException, therefore it's the responsibility - // of the Evaluator to detect the interrupt and avoid calling subsequent SkyFunctions. - return null; - } + // Keep the evaluator busy until the test's thread gets scheduled and can + // interrupt the Evaluator's thread. + env.getValue(GraphTester.toSkyKey("a" + valueIdCounter++)); - @Nullable - @Override - public String extractTag(SkyKey skyKey) { - return null; + // This method never throws InterruptedException, therefore it's the responsibility + // of the Evaluator to detect the interrupt and avoid calling subsequent + // SkyFunctions. + return null; + } + + @Nullable + @Override + public String extractTag(SkyKey skyKey) { + return null; + } + }; } - }; - } - }); + }); } private void runPartialResultOnInterruption(boolean buildFastFirst) throws Exception { @@ -1263,7 +1262,8 @@ public class ParallelEvaluatorTest { new SkyFunction() { @Nullable @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException { + public SkyValue compute(SkyKey skyKey, Environment env) + throws SkyFunctionException, InterruptedException { Map<SkyKey, ValueOrException<SomeErrorException>> values = env.getValuesOrThrow( ImmutableList.of(errorKey, otherKey), SomeErrorException.class); @@ -1488,7 +1488,7 @@ public class ParallelEvaluatorTest { class ParentFunction implements SkyFunction { @Override - public SkyValue compute(SkyKey skyKey, Environment env) { + public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { SkyValue dep = env.getValue(SkyKey.create(childType, "billy the kid")); if (dep == null) { return null; @@ -1579,27 +1579,32 @@ public class ParallelEvaluatorTest { SkyKey topKey = GraphTester.toSkyKey("top"); final SkyKey parentKey = GraphTester.toSkyKey("parent"); tester.getOrCreate(parentKey).addDependency(errorKey).setComputedValue(CONCATENATE); - tester.getOrCreate(topKey).setBuilder(new SkyFunction() { - @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws GenericFunctionException { - try { - if (env.getValueOrThrow(parentKey, SomeErrorException.class) == null) { - return null; - } - } catch (SomeErrorException e) { - assertEquals(e.toString(), exception, e); - } - if (keepGoing) { - return topValue; - } else { - throw new GenericFunctionException(topException, Transience.PERSISTENT); - } - } - @Override - public String extractTag(SkyKey skyKey) { - throw new UnsupportedOperationException(); - } - }); + tester + .getOrCreate(topKey) + .setBuilder( + new SkyFunction() { + @Override + public SkyValue compute(SkyKey skyKey, Environment env) + throws GenericFunctionException, InterruptedException { + try { + if (env.getValueOrThrow(parentKey, SomeErrorException.class) == null) { + return null; + } + } catch (SomeErrorException e) { + assertEquals(e.toString(), exception, e); + } + if (keepGoing) { + return topValue; + } else { + throw new GenericFunctionException(topException, Transience.PERSISTENT); + } + } + + @Override + public String extractTag(SkyKey skyKey) { + throw new UnsupportedOperationException(); + } + }); tester.getOrCreate(topKey).addErrorDependency(errorKey, new StringValue("recovered")) .setComputedValue(CONCATENATE); EvaluationResult<StringValue> result = eval(keepGoing, ImmutableList.of(topKey)); @@ -1742,29 +1747,33 @@ public class ParallelEvaluatorTest { tester.set(dep, new StringValue("child" + i)); } final SomeErrorException parentExn = new SomeErrorException("parent error"); - tester.getOrCreate(parentKey).setBuilder(new SkyFunction() { - @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException { - try { - SkyValue value = env.getValueOrThrow(errorDep, SomeErrorException.class); - if (value == null) { - return null; - } - } catch (SomeErrorException e) { - // Recover from the child error. - } - env.getValues(deps); - if (env.valuesMissing()) { - return null; - } - throw new GenericFunctionException(parentExn, Transience.PERSISTENT); - } + tester + .getOrCreate(parentKey) + .setBuilder( + new SkyFunction() { + @Override + public SkyValue compute(SkyKey skyKey, Environment env) + throws SkyFunctionException, InterruptedException { + try { + SkyValue value = env.getValueOrThrow(errorDep, SomeErrorException.class); + if (value == null) { + return null; + } + } catch (SomeErrorException e) { + // Recover from the child error. + } + env.getValues(deps); + if (env.valuesMissing()) { + return null; + } + throw new GenericFunctionException(parentExn, Transience.PERSISTENT); + } - @Override - public String extractTag(SkyKey skyKey) { - return null; - } - }); + @Override + public String extractTag(SkyKey skyKey) { + return null; + } + }); EvaluationResult<StringValue> evaluationResult = eval(keepGoing, ImmutableList.of(parentKey)); assertTrue(evaluationResult.hasError()); assertEquals(keepGoing ? parentExn : childExn, evaluationResult.getError().getException()); @@ -1891,46 +1900,55 @@ public class ParallelEvaluatorTest { // The parent should be built exactly twice: once during normal evaluation and once // during error bubbling. final AtomicInteger numParentInvocations = new AtomicInteger(0); - tester.getOrCreate(parentKey).setBuilder(new SkyFunction() { - @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException { - int invocations = numParentInvocations.incrementAndGet(); - if (handleChildError) { - try { - SkyValue value = env.getValueOrThrow(childKey, SomeErrorException.class); - // On the first invocation, either the child error should already be cached and not - // propagated, or it should be computed freshly and not propagated. On the second build - // (error bubbling), the child error should be propagated. - assertTrue("bogus non-null value " + value, value == null); - assertEquals("parent incorrectly re-computed during normal evaluation", 1, invocations); - assertFalse("child error not propagated during error bubbling", - env.inErrorBubblingForTesting()); - return value; - } catch (SomeErrorException e) { - assertTrue("child error propagated during normal evaluation", - env.inErrorBubblingForTesting()); - assertEquals(2, invocations); - return null; - } - } else { - if (invocations == 1) { - assertFalse("parent's first computation should be during normal evaluation", - env.inErrorBubblingForTesting()); - return env.getValue(childKey); - } else { - assertEquals(2, invocations); - assertTrue("parent incorrectly re-computed during normal evaluation", - env.inErrorBubblingForTesting()); - return env.getValue(childKey); - } - } - } + tester + .getOrCreate(parentKey) + .setBuilder( + new SkyFunction() { + @Override + public SkyValue compute(SkyKey skyKey, Environment env) + throws SkyFunctionException, InterruptedException { + int invocations = numParentInvocations.incrementAndGet(); + if (handleChildError) { + try { + SkyValue value = env.getValueOrThrow(childKey, SomeErrorException.class); + // On the first invocation, either the child error should already be cached and + // not propagated, or it should be computed freshly and not propagated. On the + // second build (error bubbling), the child error should be propagated. + assertTrue("bogus non-null value " + value, value == null); + assertEquals( + "parent incorrectly re-computed during normal evaluation", 1, invocations); + assertFalse( + "child error not propagated during error bubbling", + env.inErrorBubblingForTesting()); + return value; + } catch (SomeErrorException e) { + assertTrue( + "child error propagated during normal evaluation", + env.inErrorBubblingForTesting()); + assertEquals(2, invocations); + return null; + } + } else { + if (invocations == 1) { + assertFalse( + "parent's first computation should be during normal evaluation", + env.inErrorBubblingForTesting()); + return env.getValue(childKey); + } else { + assertEquals(2, invocations); + assertTrue( + "parent incorrectly re-computed during normal evaluation", + env.inErrorBubblingForTesting()); + return env.getValue(childKey); + } + } + } - @Override - public String extractTag(SkyKey skyKey) { - return null; - } - }); + @Override + public String extractTag(SkyKey skyKey) { + return null; + } + }); if (childErrorCached) { // Ensure that the child is already in the graph. evalValueInError(childKey); @@ -1979,19 +1997,23 @@ public class ParallelEvaluatorTest { final SkyKey otherKey = GraphTester.toSkyKey("otherKey"); final AtomicInteger numOtherParentInvocations = new AtomicInteger(0); final AtomicInteger numErrorParentInvocations = new AtomicInteger(0); - tester.getOrCreate(otherParentKey).setBuilder(new SkyFunction() { - @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException { - int invocations = numOtherParentInvocations.incrementAndGet(); - assertEquals("otherParentKey should not be restarted", 1, invocations); - return env.getValue(otherKey); - } + tester + .getOrCreate(otherParentKey) + .setBuilder( + new SkyFunction() { + @Override + public SkyValue compute(SkyKey skyKey, Environment env) + throws SkyFunctionException, InterruptedException { + int invocations = numOtherParentInvocations.incrementAndGet(); + assertEquals("otherParentKey should not be restarted", 1, invocations); + return env.getValue(otherKey); + } - @Override - public String extractTag(SkyKey skyKey) { - return null; - } - }); + @Override + public String extractTag(SkyKey skyKey) { + return null; + } + }); tester .getOrCreate(otherKey) .setBuilder( @@ -2026,33 +2048,38 @@ public class ParallelEvaluatorTest { return null; } }); - tester.getOrCreate(errorParentKey).setBuilder(new SkyFunction() { - @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException { - int invocations = numErrorParentInvocations.incrementAndGet(); - try { - SkyValue value = env.getValueOrThrow(errorKey, SomeErrorException.class); - assertTrue("bogus non-null value " + value, value == null); - if (invocations == 1) { - return null; - } else { - assertFalse(env.inErrorBubblingForTesting()); - fail("RACE CONDITION: errorParentKey was restarted!"); - return null; - } - } catch (SomeErrorException e) { - assertTrue("child error propagated during normal evaluation", - env.inErrorBubblingForTesting()); - assertEquals(2, invocations); - return null; - } - } + tester + .getOrCreate(errorParentKey) + .setBuilder( + new SkyFunction() { + @Override + public SkyValue compute(SkyKey skyKey, Environment env) + throws SkyFunctionException, InterruptedException { + int invocations = numErrorParentInvocations.incrementAndGet(); + try { + SkyValue value = env.getValueOrThrow(errorKey, SomeErrorException.class); + assertTrue("bogus non-null value " + value, value == null); + if (invocations == 1) { + return null; + } else { + assertFalse(env.inErrorBubblingForTesting()); + fail("RACE CONDITION: errorParentKey was restarted!"); + return null; + } + } catch (SomeErrorException e) { + assertTrue( + "child error propagated during normal evaluation", + env.inErrorBubblingForTesting()); + assertEquals(2, invocations); + return null; + } + } - @Override - public String extractTag(SkyKey skyKey) { - return null; - } - }); + @Override + public String extractTag(SkyKey skyKey) { + return null; + } + }); graph = new NotifyingHelper.NotifyingProcessableGraph( new InMemoryGraphImpl(), @@ -2143,41 +2170,49 @@ public class ParallelEvaluatorTest { final SkyKey parentKey = GraphTester.toSkyKey("parent"); final SkyKey childKey = GraphTester.toSkyKey("child"); final AtomicBoolean errorPropagated = new AtomicBoolean(false); - tester.getOrCreate(grandparentKey).setBuilder(new SkyFunction() { - @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException { - try { - return env.getValueOrThrow(parentKey, SomeErrorException.class); - } catch (SomeErrorException e) { - errorPropagated.set(true); - throw new GenericFunctionException(e, Transience.PERSISTENT); - } - } + tester + .getOrCreate(grandparentKey) + .setBuilder( + new SkyFunction() { + @Override + public SkyValue compute(SkyKey skyKey, Environment env) + throws SkyFunctionException, InterruptedException { + try { + return env.getValueOrThrow(parentKey, SomeErrorException.class); + } catch (SomeErrorException e) { + errorPropagated.set(true); + throw new GenericFunctionException(e, Transience.PERSISTENT); + } + } - @Override - public String extractTag(SkyKey skyKey) { - return null; - } - }); - tester.getOrCreate(parentKey).setBuilder(new SkyFunction() { - @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException { - if (explicitlyPropagateError) { - try { - return env.getValueOrThrow(childKey, SomeErrorException.class); - } catch (SomeErrorException e) { - throw new GenericFunctionException(e, childKey); - } - } else { - return env.getValue(childKey); - } - } + @Override + public String extractTag(SkyKey skyKey) { + return null; + } + }); + tester + .getOrCreate(parentKey) + .setBuilder( + new SkyFunction() { + @Override + public SkyValue compute(SkyKey skyKey, Environment env) + throws SkyFunctionException, InterruptedException { + if (explicitlyPropagateError) { + try { + return env.getValueOrThrow(childKey, SomeErrorException.class); + } catch (SomeErrorException e) { + throw new GenericFunctionException(e, childKey); + } + } else { + return env.getValue(childKey); + } + } - @Override - public String extractTag(SkyKey skyKey) { - return null; - } - }); + @Override + public String extractTag(SkyKey skyKey) { + return null; + } + }); tester.getOrCreate(childKey).setHasError(/*hasError=*/true); EvaluationResult<StringValue> result = eval(keepGoing, ImmutableList.of(grandparentKey)); assertTrue(result.hasError()); diff --git a/src/test/java/com/google/devtools/build/skyframe/WalkableGraphUtils.java b/src/test/java/com/google/devtools/build/skyframe/WalkableGraphUtils.java index 6c6f0c7b2a..7095371508 100644 --- a/src/test/java/com/google/devtools/build/skyframe/WalkableGraphUtils.java +++ b/src/test/java/com/google/devtools/build/skyframe/WalkableGraphUtils.java @@ -19,11 +19,13 @@ import com.google.common.collect.Iterables; /** Utility methods for querying (r)deps of nodes from {@link WalkableGraph}s more concisely. */ public class WalkableGraphUtils { - public static Iterable<SkyKey> getDirectDeps(WalkableGraph graph, SkyKey key) { + public static Iterable<SkyKey> getDirectDeps(WalkableGraph graph, SkyKey key) + throws InterruptedException { return Iterables.getOnlyElement(graph.getDirectDeps(ImmutableList.of(key)).values()); } - public static Iterable<SkyKey> getReverseDeps(WalkableGraph graph, SkyKey key) { + public static Iterable<SkyKey> getReverseDeps(WalkableGraph graph, SkyKey key) + throws InterruptedException { return Iterables.getOnlyElement(graph.getReverseDeps(ImmutableList.of(key)).values()); } } diff --git a/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/GenerateWorkspace.java b/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/GenerateWorkspace.java index 164742a162..8cea85b150 100644 --- a/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/GenerateWorkspace.java +++ b/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/GenerateWorkspace.java @@ -27,7 +27,6 @@ import com.google.devtools.build.lib.vfs.UnixFileSystem; import com.google.devtools.build.workspace.maven.DefaultModelResolver; import com.google.devtools.build.workspace.maven.Resolver; import com.google.devtools.common.options.OptionsParser; - import java.io.File; import java.io.IOException; import java.io.PrintStream; @@ -48,7 +47,7 @@ public class GenerateWorkspace { private final List<String> inputs; private final Path outputDir; - public static void main(String[] args) { + public static void main(String[] args) throws InterruptedException { OptionsParser parser = OptionsParser.newOptionsParser(GenerateWorkspaceOptions.class); parser.parseAndExitUponError(args); GenerateWorkspaceOptions options = parser.getOptions(GenerateWorkspaceOptions.class); @@ -99,7 +98,7 @@ public class GenerateWorkspace { ? new JavaIoFileSystem() : new UnixFileSystem(); } - private void generateFromWorkspace(List<String> projects) { + private void generateFromWorkspace(List<String> projects) throws InterruptedException { for (String project : projects) { WorkspaceResolver workspaceResolver = new WorkspaceResolver(resolver, handler); Path projectPath = fileSystem.getPath(getAbsolute(project)).getRelative("WORKSPACE"); diff --git a/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/WorkspaceResolver.java b/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/WorkspaceResolver.java index 2ad60eef33..736469f095 100644 --- a/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/WorkspaceResolver.java +++ b/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/WorkspaceResolver.java @@ -41,12 +41,10 @@ import com.google.devtools.build.workspace.maven.DefaultModelResolver; import com.google.devtools.build.workspace.maven.Resolver; import com.google.devtools.build.workspace.maven.Resolver.InvalidArtifactCoordinateException; import com.google.devtools.build.workspace.maven.Rule; - -import org.apache.maven.model.building.ModelSource; -import org.apache.maven.model.resolution.UnresolvableModelException; - import java.io.IOException; import java.util.List; +import org.apache.maven.model.building.ModelSource; +import org.apache.maven.model.resolution.UnresolvableModelException; /** * Finds the transitive dependencies of a WORKSPACE file. @@ -73,10 +71,8 @@ public class WorkspaceResolver { this.environmentExtensions = environmentExtensions.build(); } - /** - * Converts the WORKSPACE file content into an ExternalPackage. - */ - public Package parse(Path workspacePath) { + /** Converts the WORKSPACE file content into an ExternalPackage. */ + public Package parse(Path workspacePath) throws InterruptedException { Package.Builder builder = Package.newExternalPackageBuilder( Package.Builder.DefaultHelper.INSTANCE, workspacePath, |