// 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.ExtendedEventHandler;
import com.google.devtools.build.lib.util.GroupedList;
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.
   *
   * <p>This method may return {@link #SENTINEL_FOR_RESTART_FROM_SCRATCH} in rare circumstances. See
   * its docs. Do not return this value unless you know exactly what you are doing.
   *
   * @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);

  /**
   * Sentinel value for {@link #compute} to return, indicating that something went wrong in external
   * state and the evaluation has to be restarted from scratch, ignoring any deps that the {@link
   * #compute} function may have declared during evaluation at this version (including deps declared
   * during previous calls that returned null). Common causes for returning this would be data loss,
   * if a dep's data is not actually available externally. In this case, the {@link SkyFunction}
   * will likely dirty the unusable dep to force its re-evalution when re-requested by the restarted
   * entry's computation.
   */
  SkyValue SENTINEL_FOR_RESTART_FROM_SCRATCH = new SkyValue() {};

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

    @Nullable
    <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, 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, 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, InterruptedException;

    /**
     * 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) 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.
     *
     * <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<? extends SkyKey> depKeys, Class<E> exceptionClass) throws InterruptedException;

    <E1 extends Exception, E2 extends Exception>
        Map<SkyKey, ValueOrException2<E1, E2>> getValuesOrThrow(
            Iterable<? extends 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<? extends 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<? extends 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<? extends 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
     * 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}.
     */
    ExtendedEventHandler getListener();

    /**
     * A live view of deps known to have already been requested either through an earlier call to
     * {@link SkyFunction#compute} or inferred during change pruning. Should return {@code null} if
     * unknown.
     */
    @Nullable
    default GroupedList<SkyKey> getTemporaryDirectDeps() {
      return null;
    }

    /**
     * Register dependencies on keys without necessarily requiring their values.
     *
     * <p>WARNING: Dependencies here MUST be done! Only use this function if you know what you're
     * doing.
     */
    default void registerDependencies(Iterable<SkyKey> keys) throws InterruptedException {
      getValues(keys);
    }

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