diff options
Diffstat (limited to 'src/main/java/com/google/devtools')
4 files changed, 555 insertions, 51 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/CachedSkylarkImportLookupValueAndDeps.java b/src/main/java/com/google/devtools/build/lib/skyframe/CachedSkylarkImportLookupValueAndDeps.java new file mode 100644 index 0000000000..eccb75644a --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/skyframe/CachedSkylarkImportLookupValueAndDeps.java @@ -0,0 +1,142 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.devtools.build.lib.skyframe; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.devtools.build.skyframe.SkyKey; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +class CachedSkylarkImportLookupValueAndDeps { + private final SkylarkImportLookupValue value; + // We store the deps separately so that we can let go of the value when the cache drops it. + final CachedSkylarkImportLookupFunctionDeps deps; + + private CachedSkylarkImportLookupValueAndDeps( + SkylarkImportLookupValue value, CachedSkylarkImportLookupFunctionDeps deps) { + this.value = value; + this.deps = deps; + } + + SkylarkImportLookupValue getValue() { + return value; + } + + static CachedSkylarkImportLookupValueAndDeps.Builder newBuilder() { + return new CachedSkylarkImportLookupValueAndDeps.Builder(); + } + + static class Builder { + private final CachedSkylarkImportLookupFunctionDeps.Builder depsBuilder = + CachedSkylarkImportLookupFunctionDeps.newBuilder(); + private SkylarkImportLookupValue value; + + @CanIgnoreReturnValue + Builder addDep(SkyKey key) { + depsBuilder.addDep(key); + return this; + } + + @CanIgnoreReturnValue + Builder addDeps(Iterable<SkyKey> keys) { + depsBuilder.addDeps(keys); + return this; + } + + @CanIgnoreReturnValue + Builder noteException(Exception e) { + depsBuilder.noteException(e); + return this; + } + + @CanIgnoreReturnValue + Builder addTransitiveDeps(CachedSkylarkImportLookupValueAndDeps transitiveDeps) { + depsBuilder.addTransitiveDeps(transitiveDeps.deps); + return this; + } + + @CanIgnoreReturnValue + Builder setValue(SkylarkImportLookupValue value) { + this.value = value; + return this; + } + + CachedSkylarkImportLookupValueAndDeps build() { + return new CachedSkylarkImportLookupValueAndDeps(value, depsBuilder.build()); + } + } + + static class CachedSkylarkImportLookupFunctionDeps implements Iterable<Iterable<SkyKey>> { + private final ImmutableList<Iterable<SkyKey>> deps; + + private CachedSkylarkImportLookupFunctionDeps(ImmutableList<Iterable<SkyKey>> deps) { + this.deps = deps; + } + + static CachedSkylarkImportLookupFunctionDeps.Builder newBuilder() { + return new CachedSkylarkImportLookupFunctionDeps.Builder(); + } + + @Override + public Iterator<Iterable<SkyKey>> iterator() { + return deps.iterator(); + } + + static class Builder { + private final List<Iterable<SkyKey>> deps = new ArrayList<>(); + private final AtomicReference<Exception> exceptionSeen = new AtomicReference<>(null); + + // We only add the ASTFileLookupFunction through this so we don't need to worry about memory + // optimizations by adding it raw. + @CanIgnoreReturnValue + Builder addDep(SkyKey key) { + deps.add(ImmutableList.of(key)); + return this; + } + + @CanIgnoreReturnValue + Builder addDeps(Iterable<SkyKey> keys) { + deps.add(keys); + return this; + } + + @CanIgnoreReturnValue + Builder noteException(Exception e) { + exceptionSeen.set(e); + return this; + } + + @CanIgnoreReturnValue + Builder addTransitiveDeps(CachedSkylarkImportLookupFunctionDeps transitiveDeps) { + Iterables.addAll(deps, transitiveDeps); + return this; + } + + CachedSkylarkImportLookupFunctionDeps build() { + // We expect that we don't handle any exceptions in SkylarkLookupImportFunction directly. + Preconditions.checkState( + exceptionSeen.get() == null, + "Caching a value in error?: %s %s", + deps, + exceptionSeen.get()); + return new CachedSkylarkImportLookupFunctionDeps(ImmutableList.copyOf(deps)); + } + } + } +} 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 8a6f603ca7..d69dd83137 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 @@ -77,7 +77,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -750,12 +749,10 @@ public class PackageFunction implements SkyFunction { } } else { // Inlining calls to SkylarkImportLookupFunction - LinkedHashMap<Label, SkylarkImportLookupValue> alreadyVisitedImports = - Maps.newLinkedHashMapWithExpectedSize(importLookupKeys.size()); for (SkyKey importLookupKey : importLookupKeys) { SkyValue skyValue = skylarkImportLookupFunctionForInlining.computeWithInlineCalls( - importLookupKey, env, alreadyVisitedImports); + importLookupKey, env, importLookupKeys.size()); if (skyValue == null) { Preconditions.checkState( env.valuesMissing(), "no skylark import value for %s", importLookupKey); 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 ad4c5a9d74..bdf07fa570 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 @@ -15,6 +15,8 @@ package com.google.devtools.build.lib.skyframe; import com.google.common.base.Preconditions; import com.google.common.base.Predicates; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -27,6 +29,7 @@ import com.google.common.collect.Multimap; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.cmdline.LabelSyntaxException; import com.google.devtools.build.lib.cmdline.PackageIdentifier; +import com.google.devtools.build.lib.concurrent.BlazeInterners; import com.google.devtools.build.lib.events.Event; import com.google.devtools.build.lib.events.EventHandler; import com.google.devtools.build.lib.events.ExtendedEventHandler.Postable; @@ -47,6 +50,7 @@ import com.google.devtools.build.lib.syntax.SkylarkImport; import com.google.devtools.build.lib.syntax.SkylarkSemantics; import com.google.devtools.build.lib.syntax.Statement; import com.google.devtools.build.lib.vfs.PathFragment; +import com.google.devtools.build.skyframe.RecordingSkyFunctionEnvironment; import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyFunctionException.Transience; @@ -57,22 +61,26 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.logging.Logger; import javax.annotation.Nullable; /** * A Skyframe function to look up and import a single Skylark extension. * - * <p> Given a {@link Label} referencing a Skylark file, attempts to locate the file and load it. - * The Label must be absolute, and must not reference the special {@code external} package. If - * loading is successful, returns a {@link SkylarkImportLookupValue} that encapsulates - * the loaded {@link Extension} and {@link SkylarkFileDependency} information. If loading is - * unsuccessful, throws a {@link SkylarkImportLookupFunctionException} that encapsulates the - * cause of the failure. + * <p>Given a {@link Label} referencing a Skylark file, attempts to locate the file and load it. The + * Label must be absolute, and must not reference the special {@code external} package. If loading + * is successful, returns a {@link SkylarkImportLookupValue} that encapsulates the loaded {@link + * Extension} and {@link SkylarkFileDependency} information. If loading is unsuccessful, throws a + * {@link SkylarkImportLookupFunctionException} that encapsulates the cause of the failure. */ public class SkylarkImportLookupFunction implements SkyFunction { private final RuleClassProvider ruleClassProvider; private final PackageFactory packageFactory; + private Cache<SkyKey, CachedSkylarkImportLookupValueAndDeps> skylarkImportLookupValueCache; + + private static final Logger logger = + Logger.getLogger(SkylarkImportLookupFunction.class.getName()); public SkylarkImportLookupFunction( RuleClassProvider ruleClassProvider, PackageFactory packageFactory) { @@ -81,11 +89,17 @@ public class SkylarkImportLookupFunction implements SkyFunction { } @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException, - InterruptedException { + @Nullable + public SkyValue compute(SkyKey skyKey, Environment env) + throws SkyFunctionException, InterruptedException { SkylarkImportLookupKey key = (SkylarkImportLookupKey) skyKey.argument(); try { - return computeInternal(key.importLabel, key.inWorkspace, env, null); + return computeInternal( + key.importLabel, + key.inWorkspace, + env, + /*alreadyVisited=*/ null, + /*inlineCachedValueBuilder=*/ null); } catch (InconsistentFilesystemException e) { throw new SkylarkImportLookupFunctionException(e, Transience.PERSISTENT); } catch (SkylarkImportFailedException e) { @@ -93,32 +107,103 @@ public class SkylarkImportLookupFunction implements SkyFunction { } } - SkyValue computeWithInlineCalls( - SkyKey skyKey, Environment env, LinkedHashMap<Label, SkylarkImportLookupValue> visited) + @Nullable + SkylarkImportLookupValue computeWithInlineCalls( + SkyKey skyKey, Environment env, int expectedSizeOfVisitedSet) throws InconsistentFilesystemException, SkylarkImportFailedException, InterruptedException { - return computeWithInlineCallsInternal(skyKey, env, visited); + // We use the visited set to track if there are any cyclic dependencies when loading the + // skylark file. + LinkedHashMap<Label, CachedSkylarkImportLookupValueAndDeps> visited = + new LinkedHashMap<>(expectedSizeOfVisitedSet); + CachedSkylarkImportLookupValueAndDeps cachedSkylarkImportLookupValueAndDeps = + computeWithInlineCallsInternal(skyKey, env, visited); + if (cachedSkylarkImportLookupValueAndDeps == null) { + return null; + } + for (Iterable<SkyKey> depGroup : cachedSkylarkImportLookupValueAndDeps.deps) { + // Because we automatically filter out deps we've seen before and we don't expect this to be + // a super large DAG of dependencies, we iterate through without checking for already visited + // deps. + env.getValues(depGroup); + } + return cachedSkylarkImportLookupValueAndDeps.getValue(); } - private SkyValue computeWithInlineCallsInternal( - SkyKey skyKey, Environment env, LinkedHashMap<Label, SkylarkImportLookupValue> visited) + @Nullable + private CachedSkylarkImportLookupValueAndDeps computeWithInlineCallsInternal( + SkyKey skyKey, + Environment env, + LinkedHashMap<Label, CachedSkylarkImportLookupValueAndDeps> visited) throws InconsistentFilesystemException, SkylarkImportFailedException, InterruptedException { SkylarkImportLookupKey key = (SkylarkImportLookupKey) skyKey.argument(); - SkylarkImportLookupValue precomputedResult = visited.get(key.importLabel); + CachedSkylarkImportLookupValueAndDeps precomputedResult = visited.get(key.importLabel); if (precomputedResult != null) { + // We have already registered all the deps for this value. return precomputedResult; } - return computeInternal( - key.importLabel, - key.inWorkspace, - env, - Preconditions.checkNotNull(visited, key.importLabel)); + // Note that we can't block other threads on the computation of this value due to a potential + // deadlock on a cycle. Although we are repeating some work, it is possible we have an import + // cycle where one thread starts at one side of the cycle and the other thread starts at the + // other side, and they then wait forever on the results of each others computations. + CachedSkylarkImportLookupValueAndDeps cachedSkylarkImportLookupValueAndDeps = + skylarkImportLookupValueCache.getIfPresent(skyKey); + if (cachedSkylarkImportLookupValueAndDeps != null) { + return cachedSkylarkImportLookupValueAndDeps; + } + + CachedSkylarkImportLookupValueAndDeps.Builder inlineCachedValueBuilder = + CachedSkylarkImportLookupValueAndDeps.newBuilder(); + Preconditions.checkState( + !(env instanceof RecordingSkyFunctionEnvironment), + "Found nested RecordingSkyFunctionEnvironment but it should have been stripped: %s", + env); + RecordingSkyFunctionEnvironment recordingEnv = + new RecordingSkyFunctionEnvironment( + env, + inlineCachedValueBuilder::addDep, + inlineCachedValueBuilder::addDeps, + inlineCachedValueBuilder::noteException); + SkylarkImportLookupValue value = + computeInternal( + key.importLabel, + key.inWorkspace, + recordingEnv, + Preconditions.checkNotNull(visited, key.importLabel), + inlineCachedValueBuilder); + + if (value != null) { + inlineCachedValueBuilder.setValue(value); + cachedSkylarkImportLookupValueAndDeps = inlineCachedValueBuilder.build(); + skylarkImportLookupValueCache.put(skyKey, cachedSkylarkImportLookupValueAndDeps); + visited.put(key.importLabel, cachedSkylarkImportLookupValueAndDeps); + } + return cachedSkylarkImportLookupValueAndDeps; + } + + public void resetCache() { + if (skylarkImportLookupValueCache != null) { + logger.info( + "Skylark inlining cache stats from earlier build: " + + skylarkImportLookupValueCache.stats()); + } + skylarkImportLookupValueCache = + CacheBuilder.newBuilder() + .concurrencyLevel(BlazeInterners.concurrencyLevel()) + .maximumSize(10000) + .recordStats() + .build(); } - private SkyValue computeInternal( + // It is vital that we don't return any value if any call to env#getValue(s)OrThrow throws an + // exception. We are allowed to wrap the thrown exception and rethrow it for any calling functions + // to handle though. + @Nullable + private SkylarkImportLookupValue computeInternal( Label fileLabel, boolean inWorkspace, Environment env, - @Nullable LinkedHashMap<Label, SkylarkImportLookupValue> alreadyVisited) + @Nullable LinkedHashMap<Label, CachedSkylarkImportLookupValueAndDeps> alreadyVisited, + @Nullable CachedSkylarkImportLookupValueAndDeps.Builder inlineCachedValueBuilder) throws InconsistentFilesystemException, SkylarkImportFailedException, InterruptedException { PathFragment filePath = fileLabel.toPathFragment(); @@ -150,8 +235,6 @@ public class SkylarkImportLookupFunction implements SkyFunction { // Process the load statements in the file. ImmutableList<SkylarkImport> imports = ast.getImports(); - Map<String, Extension> extensionsForImports = Maps.newHashMapWithExpectedSize(imports.size()); - ImmutableList.Builder<SkylarkFileDependency> fileDependencies = ImmutableList.builder(); ImmutableMap<String, Label> labelsForImports; // Find the labels corresponding to the load statements. @@ -174,6 +257,9 @@ public class SkylarkImportLookupFunction implements SkyFunction { skylarkImportMap = env.getValues(importLookupKeys); valuesMissing = env.valuesMissing(); } else { + Preconditions.checkNotNull( + inlineCachedValueBuilder, + "Expected inline cached value builder to be not-null when inlining."); // Inlining calls to SkylarkImportLookupFunction. if (alreadyVisited.containsKey(fileLabel)) { ImmutableList<Label> cycle = @@ -183,10 +269,16 @@ public class SkylarkImportLookupFunction implements SkyFunction { } alreadyVisited.put(fileLabel, null); skylarkImportMap = Maps.newHashMapWithExpectedSize(imports.size()); + + Preconditions.checkState( + env instanceof RecordingSkyFunctionEnvironment, + "Expected to be recording dep requests when inlining SkylarkImportLookupFunction: %s", + fileLabel); + Environment strippedEnv = ((RecordingSkyFunctionEnvironment) env).getDelegate(); for (SkyKey importLookupKey : importLookupKeys) { - SkyValue skyValue = - this.computeWithInlineCallsInternal(importLookupKey, env, alreadyVisited); - if (skyValue == null) { + CachedSkylarkImportLookupValueAndDeps cachedValue = + this.computeWithInlineCallsInternal(importLookupKey, strippedEnv, alreadyVisited); + if (cachedValue == null) { Preconditions.checkState( env.valuesMissing(), "no skylark import value for %s", importLookupKey); // We continue making inline calls even if some requested values are missing, to maximize @@ -194,7 +286,9 @@ public class SkylarkImportLookupFunction implements SkyFunction { // quadratic number of restarts. valuesMissing = true; } else { + SkyValue skyValue = cachedValue.getValue(); skylarkImportMap.put(importLookupKey, skyValue); + inlineCachedValueBuilder.addTransitiveDeps(cachedValue); } } // All imports traversed, this key can no longer be part of a cycle. @@ -206,6 +300,9 @@ public class SkylarkImportLookupFunction implements SkyFunction { } // Process the loaded imports. + Map<String, Extension> extensionsForImports = Maps.newHashMapWithExpectedSize(imports.size()); + ImmutableList.Builder<SkylarkFileDependency> fileDependencies = + ImmutableList.builderWithExpectedSize(labelsForImports.size()); for (Entry<String, Label> importEntry : labelsForImports.entrySet()) { String importString = importEntry.getKey(); Label importLabel = importEntry.getValue(); @@ -216,21 +313,13 @@ public class SkylarkImportLookupFunction implements SkyFunction { fileDependencies.add(importLookupValue.getDependency()); } - // Skylark UserDefinedFunction-s in that file will share this function definition Environment, - // which will be frozen by the time it is returned by createExtension. - Extension extension = createExtension( - ast, - fileLabel, - extensionsForImports, - skylarkSemantics, - env, - inWorkspace); + // #createExtension does not request values from the Environment. It may post events to the + // Environment, but events do not matter when caching SkylarkImportLookupValues. + Extension extension = + createExtension(ast, fileLabel, extensionsForImports, skylarkSemantics, env, inWorkspace); SkylarkImportLookupValue result = new SkylarkImportLookupValue( extension, new SkylarkFileDependency(fileLabel, fileDependencies.build())); - if (alreadyVisited != null) { - alreadyVisited.put(fileLabel, result); - } return result; } @@ -243,12 +332,13 @@ public class SkylarkImportLookupFunction implements SkyFunction { * @throws SkylarkImportFailedException */ @Nullable - static ImmutableMap<PathFragment, Label> labelsForAbsoluteImports( + private static ImmutableMap<PathFragment, Label> labelsForAbsoluteImports( ImmutableSet<PathFragment> pathsToLookup, Environment env) 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<>(); + ImmutableMap.Builder<PathFragment, Label> outputMap = + ImmutableMap.builderWithExpectedSize(pathsToLookup.size()); // The SkyKey here represents the directory containing an import PathFragment, hence there // can in general be multiple imports per lookup. @@ -309,7 +399,7 @@ public class SkylarkImportLookupFunction implements SkyFunction { throw new SkylarkImportFailedException(e); } - return outputMap.build(); + return outputMap.build(); } /** @@ -508,10 +598,5 @@ public class SkylarkImportLookupFunction implements SkyFunction { Transience transience) { super(e, transience); } - - private SkylarkImportLookupFunctionException(BuildFileNotFoundException e, - Transience transience) { - super(e, transience); - } } } diff --git a/src/main/java/com/google/devtools/build/skyframe/RecordingSkyFunctionEnvironment.java b/src/main/java/com/google/devtools/build/skyframe/RecordingSkyFunctionEnvironment.java new file mode 100644 index 0000000000..115fea1a7f --- /dev/null +++ b/src/main/java/com/google/devtools/build/skyframe/RecordingSkyFunctionEnvironment.java @@ -0,0 +1,280 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.devtools.build.skyframe; + +import com.google.devtools.build.lib.events.ExtendedEventHandler; +import com.google.devtools.build.lib.util.GroupedList; +import com.google.devtools.build.skyframe.SkyFunction.Environment; +import java.util.Map; +import java.util.function.Consumer; +import javax.annotation.Nullable; + +/** An environment that can observe the deps requested through getValue(s) calls. */ +public class RecordingSkyFunctionEnvironment implements Environment { + + private final Environment delegate; + private final Consumer<SkyKey> skyKeyReceiver; + private final Consumer<Iterable<SkyKey>> skyKeysReceiver; + private final Consumer<Exception> exceptionReceiver; + + public RecordingSkyFunctionEnvironment( + Environment delegate, + Consumer<SkyKey> skyKeyReceiver, + Consumer<Iterable<SkyKey>> skyKeysReceiver, + Consumer<Exception> exceptionReceiver) { + this.delegate = delegate; + this.skyKeyReceiver = skyKeyReceiver; + this.skyKeysReceiver = skyKeysReceiver; + this.exceptionReceiver = exceptionReceiver; + } + + private void recordDep(SkyKey key) { + skyKeyReceiver.accept(key); + } + + @SuppressWarnings("unchecked") // Cast Iterable<? extends SkyKey> to Iterable<SkyKey>. + private void recordDeps(Iterable<? extends SkyKey> keys) { + skyKeysReceiver.accept((Iterable<SkyKey>) keys); + } + + private void noteException(Exception e) { + exceptionReceiver.accept(e); + } + + public Environment getDelegate() { + return delegate; + } + + @Nullable + @Override + public SkyValue getValue(SkyKey valueName) throws InterruptedException { + recordDep(valueName); + return delegate.getValue(valueName); + } + + @Nullable + @Override + public <E extends Exception> SkyValue getValueOrThrow(SkyKey depKey, Class<E> exceptionClass) + throws E, InterruptedException { + recordDep(depKey); + try { + return delegate.getValueOrThrow(depKey, exceptionClass); + } catch (Exception e) { + noteException(e); + throw e; + } + } + + @Nullable + @Override + public <E1 extends Exception, E2 extends Exception> SkyValue getValueOrThrow( + SkyKey depKey, Class<E1> exceptionClass1, Class<E2> exceptionClass2) + throws E1, E2, InterruptedException { + recordDep(depKey); + try { + return delegate.getValueOrThrow(depKey, exceptionClass1, exceptionClass2); + } catch (Exception e) { + noteException(e); + throw e; + } + } + + @Nullable + @Override + public <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, InterruptedException { + recordDep(depKey); + try { + return delegate.getValueOrThrow(depKey, exceptionClass1, exceptionClass2, exceptionClass3); + } catch (Exception e) { + noteException(e); + throw e; + } + } + + @Nullable + @Override + public <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, InterruptedException { + recordDep(depKey); + try { + return delegate.getValueOrThrow( + depKey, exceptionClass1, exceptionClass2, exceptionClass3, exceptionClass4); + } catch (Exception e) { + noteException(e); + throw e; + } + } + + @Nullable + @Override + public < + 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 { + recordDep(depKey); + try { + return delegate.getValueOrThrow( + depKey, + exceptionClass1, + exceptionClass2, + exceptionClass3, + exceptionClass4, + exceptionClass5); + } catch (Exception e) { + noteException(e); + throw e; + } + } + + @Override + public Map<SkyKey, SkyValue> getValues(Iterable<SkyKey> depKeys) throws InterruptedException { + recordDeps(depKeys); + return delegate.getValues(depKeys); + } + + @Override + public <E extends Exception> Map<SkyKey, ValueOrException<E>> getValuesOrThrow( + Iterable<? extends SkyKey> depKeys, Class<E> exceptionClass) throws InterruptedException { + recordDeps(depKeys); + try { + return delegate.getValuesOrThrow(depKeys, exceptionClass); + } catch (Exception e) { + noteException(e); + throw e; + } + } + + @Override + public <E1 extends Exception, E2 extends Exception> + Map<SkyKey, ValueOrException2<E1, E2>> getValuesOrThrow( + Iterable<? extends SkyKey> depKeys, Class<E1> exceptionClass1, Class<E2> exceptionClass2) + throws InterruptedException { + recordDeps(depKeys); + try { + return delegate.getValuesOrThrow(depKeys, exceptionClass1, exceptionClass2); + } catch (Exception e) { + noteException(e); + throw e; + } + } + + @Override + public <E1 extends Exception, E2 extends Exception, E3 extends Exception> + Map<SkyKey, ValueOrException3<E1, E2, E3>> getValuesOrThrow( + Iterable<? extends SkyKey> depKeys, + Class<E1> exceptionClass1, + Class<E2> exceptionClass2, + Class<E3> exceptionClass3) + throws InterruptedException { + recordDeps(depKeys); + try { + return delegate.getValuesOrThrow(depKeys, exceptionClass1, exceptionClass2, exceptionClass3); + } catch (Exception e) { + noteException(e); + throw e; + } + } + + @Override + public <E1 extends Exception, E2 extends Exception, E3 extends Exception, E4 extends Exception> + Map<SkyKey, ValueOrException4<E1, E2, E3, E4>> getValuesOrThrow( + Iterable<? extends SkyKey> depKeys, + Class<E1> exceptionClass1, + Class<E2> exceptionClass2, + Class<E3> exceptionClass3, + Class<E4> exceptionClass4) + throws InterruptedException { + recordDeps(depKeys); + try { + return delegate.getValuesOrThrow( + depKeys, exceptionClass1, exceptionClass2, exceptionClass3, exceptionClass4); + } catch (Exception e) { + noteException(e); + throw e; + } + } + + @Override + 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<? extends SkyKey> depKeys, + Class<E1> exceptionClass1, + Class<E2> exceptionClass2, + Class<E3> exceptionClass3, + Class<E4> exceptionClass4, + Class<E5> exceptionClass5) + throws InterruptedException { + recordDeps(depKeys); + try { + return delegate.getValuesOrThrow( + depKeys, + exceptionClass1, + exceptionClass2, + exceptionClass3, + exceptionClass4, + exceptionClass5); + } catch (Exception e) { + noteException(e); + throw e; + } + } + + @Override + public boolean valuesMissing() { + return delegate.valuesMissing(); + } + + @Override + public ExtendedEventHandler getListener() { + return delegate.getListener(); + } + + @Override + public boolean inErrorBubblingForTesting() { + return delegate.inErrorBubblingForTesting(); + } + + @Nullable + @Override + public GroupedList<SkyKey> getTemporaryDirectDeps() { + return delegate.getTemporaryDirectDeps(); + } +} |