// Copyright 2014 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.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;

/**
 * Machinery to evaluate a single value.
 *
 * <p>The SkyFunction {@link #compute} implementation is supposed to access only direct
 * dependencies of the value. However, the direct dependencies need not be known in advance. The
 * implementation can request arbitrary values using {@link Environment#getValue}. If the values
 * are not ready, the call will return {@code null}; in that case the implementation should just
 * return {@code null}, in which case the missing dependencies will be computed and the {@link
 * #compute} method will be started again.
 * */
public interface SkyFunction {

  /**
   * When a value is requested, this method is called with the name of the value and a
   * dependency-tracking environment.
   *
   * <p>This method should return a non-{@code null} value, or {@code null} if any dependencies
   * were missing ({@link Environment#valuesMissing} was true before returning). In that case the
   * missing dependencies will be computed and the {@code compute} method called again.
   *
   * <p>This method should throw if it fails, or if one of its dependencies fails with an
   * exception and this method cannot recover. If one of its dependencies fails and this method can
   * enrich the exception with additional context, then this method should catch that exception and
   * throw another containing that additional context. If it has no such additional context, then
   * it should allow its dependency's exception to be thrown through it.
   *
   * @throws SkyFunctionException on failure
   * @throws InterruptedException if interrupted
   */
  @ThreadSafe
  @Nullable
  SkyValue compute(SkyKey skyKey, Environment env)
      throws SkyFunctionException, InterruptedException;

  /**
   * Extracts a tag (target label) from a SkyKey if it has one. Otherwise return {@code null}.
   *
   * <p>The tag is used for filtering out non-error event messages that do not match
   * --output_filter flag. If a SkyFunction returns {@code null} in this method it means that all
   * the info/warning messages associated with this value will be shown, no matter what
   * --output_filter says.
   */
  @Nullable
  String extractTag(SkyKey skyKey);

  /**
   * The services provided to the {@link SkyFunction} implementation by the graph implementation.
   */
  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.
     *
     * <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
     * important).
     */
    @Nullable
    SkyValue getValue(SkyKey valueName);

    /**
     * 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.
     *
     * <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.
     */
    @Nullable
    <E extends Exception> SkyValue getValueOrThrow(SkyKey depKey, Class<E> exceptionClass) throws E;
    @Nullable
    <E1 extends Exception, E2 extends Exception> SkyValue getValueOrThrow(SkyKey depKey,
        Class<E1> exceptionClass1, Class<E2> exceptionClass2) throws E1, E2;
    @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;
    @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;
    @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;

    /**
     * Requests {@code depKeys} "in parallel", independent of each others' values. These keys may be
     * thought of as a "dependency group" -- they are requested together by this value.
     *
     * <p>In general, if the result of one getValue call can affect the argument of a later getValue
     * call, the two calls cannot be merged into a single getValues call, since the result of the
     * first call might change on a later evaluation. Inversely, if the result of one getValue call
     * cannot affect the parameters of the next getValue call, the two keys can form a dependency
     * group and the two getValue calls merged into one getValues call.
     *
     * <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.
     *
     * <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}.
     *
     * <p>Example of when not to use getValues: A BestMatch value is built with key
     * &lt;potentialMatchesRef, matchCriterion&gt;. The {@link #compute} method first calls
     * getValue(PotentialMatches.key(potentialMatchesRef) and retrieves potentialMatches. It then
     * iterates through potentialMatches, calling getValue on each potential match until it finds
     * one that satisfies matchCriterion. In this case, if potentialMatches is (a, b, c), it would
     * be <i>incorrect</i> to call getValues({a, b, c}), because it is not known yet whether
     * requesting b or c will be necessary -- if a matches, then we will never call b or c.
     *
     * <p>Returns a map, {@code m}. For all {@code k} in {@code depKeys}, {@code m.containsKey(k)}
     * 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);

    /**
     * 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>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);
    <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);
    <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);

    /**
     * Returns whether there was a previous getValue[s][OrThrow] that indicated a missing
     * dependency. Formally, returns true iff at least one of the following occurred:
     *
     * <ul>
     *   <li>getValue[OrThrow](k[, c]) returned {@code null} for some k</li>
     *   <li>getValues(ks).get(k) == {@code null} for some ks and k such that ks.contains(k)</li>
     *   <li>
     *     getValuesOrThrow(ks, c).get(k).get() == {@code null} for some ks and k such that
     *     ks.contains(k)
     *   </li>
     * </ul>
     *
     * <p>If this returns true, the {@link SkyFunction} must return {@code null}.
     */
    boolean valuesMissing();

    /**
     * Returns the {@link EventHandler} that a SkyFunction should use to print any errors,
     * warnings, or progress messages during execution of {@link SkyFunction#compute}.
     */
    EventHandler getListener();

    /** Returns whether we are currently in error bubbling. */
    @VisibleForTesting
    boolean inErrorBubblingForTesting();
  }
}
