// 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 static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.skyframe.SkyFunction.Reset;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * A node in the graph. All operations on this class are thread-safe.
 *
 * <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 {

  /**
   * Return code for {@link #addReverseDepAndCheckIfDone} and {@link
   * #checkIfDoneForDirtyReverseDep}.
   */
  enum DependencyState {
    /** The node is done. */
    DONE,

    /**
     * The node has not started evaluating, and needs to be scheduled for its first evaluation pass.
     * The caller getting this return value is responsible for scheduling its evaluation and
     * signaling the reverse dependency node when this node is done.
     */
    NEEDS_SCHEDULING,

    /**
     * The node was already created, but isn't done yet. The evaluator is responsible for signaling
     * the reverse dependency node.
     */
    ALREADY_EVALUATING
  }

  /** Represents the various states in a node's lifecycle. */
  enum LifecycleState {
    /**
     * The entry has never started evaluating. The next call to {@link #addReverseDepAndCheckIfDone}
     * will put the entry into the {@link #NEEDS_REBUILDING} state and return {@link
     * DependencyState#NEEDS_SCHEDULING}.
     */
    NOT_YET_EVALUATING,
    /**
     * The node's dependencies need to be checked to see if it needs to be rebuilt. The dependencies
     * must be obtained through calls to {@link #getNextDirtyDirectDeps} and checked.
     */
    CHECK_DEPENDENCIES,
    /**
     * All of the node's dependencies are unchanged, and the value itself was not marked changed, so
     * its current value is still valid -- it need not be rebuilt.
     */
    VERIFIED_CLEAN,
    /**
     * A rebuilding is required for one of the following reasons:
     *
     * <ol>
     *   <li>One of the node's dependencies changed.
     *   <li>The node is built by a {@link FunctionHermeticity#NONHERMETIC} function and its value
     *       is known to have changed due to state outside of Skyframe.
     *   <li>The node was {@linkplain DirtyType#REWIND rewound}.
     * </ol>
     */
    NEEDS_REBUILDING,
    /** A rebuilding is in progress. */
    REBUILDING,
    /** The node {@link #isDone}. */
    DONE,
  }

  /** Ways that a node may be dirtied. */
  enum DirtyType {

    /**
     * Indicates that the node is being marked dirty because it has a dependency that was marked
     * dirty.
     *
     * <p>A node P dirtied with {@code DIRTY} is re-evaluated during the evaluation phase if it is
     * requested and directly depends on some node C whose value changed since the last evaluation
     * of P. If it is requested and there is no such node C, P is {@linkplain #markClean marked
     * clean}.
     */
    DIRTY,

    /**
     * Indicates that the node is being marked dirty because its value from a previous evaluation is
     * no longer valid, even if none of its dependencies change.
     *
     * <p>This is typically used to indicate that a value produced by a {@link
     * FunctionHermeticity#NONHERMETIC} function is no longer valid because some state outside of
     * Skyframe has changed (e.g. a change to the filesystem).
     *
     * <p>A node dirtied with {@code CHANGE} is re-evaluated during the evaluation phase if it is
     * requested, regardless of the state of its dependencies. If it re-evaluates to the same value,
     * dirty parents are not necessarily re-evaluated.
     */
    CHANGE,

    /**
     * Similar to {@link #CHANGE} except may be used intra-evaluation to indicate that the node's
     * value (which may be from either a previous evaluation or the current evaluation) is no longer
     * valid.
     *
     * <p>A node dirtied with {@code REWIND} is re-evaluated during the evaluation phase if it is
     * requested, regardless of the state of its dependencies. Even if it re-evaluates to the same
     * value, dirty parents are re-evaluated.
     *
     * <p>Rewinding is tolerated but no-op if the node is already dirty or is done with an
     * {@linkplain #getErrorInfo() error} (regardless of the error's {@link
     * com.google.devtools.build.skyframe.SkyFunctionException.Transience}).
     */
    REWIND
  }

  /** Returns whether the entry has been built and is finished evaluating. */
  @ThreadSafe
  boolean isDone();

  /** Inverse of {@link #isDone}. */
  @ThreadSafe
  boolean isDirty();

  /**
   * Returns true if the entry is marked changed, meaning that it must be re-evaluated even if its
   * dependencies' values have not changed.
   */
  @ThreadSafe
  boolean isChanged();

  /**
   * Marks this node dirty as specified by the provided {@link DirtyType}.
   *
   * <p>{@code markDirty(DirtyType.DIRTY)} may only be called on a node P for which {@code
   * P.isDone() || P.isChanged()} (the latter is permitted but has no effect). Similarly, {@code
   * markDirty(DirtyType.CHANGE)} may only be called on a node P for which {@code P.isDone() ||
   * !P.isChanged()}. Otherwise, this will throw {@link IllegalStateException}.
   *
   * <p>{@code markDirty(DirtyType.REWIND)} may be called at any time (even multiple times
   * concurrently), although it only has an effect if the node {@link #isDone} with no error.
   *
   * @return if the node transitioned from done to dirty as a result of this call, a {@link
   *     MarkedDirtyResult} which may include the node's reverse deps; otherwise {@code null}
   */
  @Nullable
  @ThreadSafe
  MarkedDirtyResult markDirty(DirtyType dirtyType) throws InterruptedException;

  /**
   * Returned by {@link #markDirty} if that call changed the node from done to dirty.
   *
   * <p>For nodes marked dirty during invalidation ({@link DirtyType#DIRTY} and {@link
   * DirtyType#CHANGE}), contains a {@link Collection} of the node's reverse deps for efficiency, so
   * that the invalidator can schedule the invalidation of a node's reverse deps immediately
   * afterwards.
   *
   * <p>For nodes marked dirty intra-evaluation ({@link DirtyType#REWIND}), reverse deps are not
   * needed by the caller, so {@link #getReverseDepsUnsafe} must not be called.
   *
   * <p>Warning: {@link #getReverseDepsUnsafe()} may return a live view of the reverse deps
   * collection of the marked-dirty node. The consumer of this data must be careful only to iterate
   * over and consume its values while that collection is guaranteed not to change. This is true
   * during invalidation, because reverse deps don't change during invalidation.
   */
  abstract class MarkedDirtyResult {

    private static final MarkedDirtyResult RESULT_FOR_REWINDING =
        new MarkedDirtyResult() {
          @Override
          public Collection<SkyKey> getReverseDepsUnsafe() {
            throw new IllegalStateException("Should not need reverse deps for rewinding");
          }
        };

    public static MarkedDirtyResult withReverseDeps(Collection<SkyKey> reverseDepsUnsafe) {
      return new ResultWithReverseDeps(reverseDepsUnsafe);
    }

    static MarkedDirtyResult forRewinding() {
      return RESULT_FOR_REWINDING;
    }

    private MarkedDirtyResult() {}

    public abstract Collection<SkyKey> getReverseDepsUnsafe();

    private static final class ResultWithReverseDeps extends MarkedDirtyResult {
      private final Collection<SkyKey> reverseDepsUnsafe;

      private ResultWithReverseDeps(Collection<SkyKey> reverseDepsUnsafe) {
        this.reverseDepsUnsafe = checkNotNull(reverseDepsUnsafe);
      }

      @Override
      public Collection<SkyKey> getReverseDepsUnsafe() {
        return reverseDepsUnsafe;
      }
    }
  }

  /**
   * Returns the value stored in this entry. This method may only be called after the evaluation of
   * this node is complete, i.e., after {@link #setValue} has been called.
   */
  @ThreadSafe
  SkyValue getValue() throws InterruptedException;

  /**
   * Returns an immutable iterable of the direct deps of this node. This method may only be called
   * after the evaluation of this node is complete.
   *
   * <p>This method is not very efficient, but is only be called in limited circumstances -- when
   * the node is about to be deleted, or when the node is expected to have no direct deps (in which
   * case the overhead is not so bad). It should not be called repeatedly for the same node, since
   * each call takes time proportional to the number of direct deps of the node.
   */
  @ThreadSafe
  Iterable<SkyKey> getDirectDeps() throws InterruptedException;

  /**
   * Returns {@code true} if this node has at least one direct dep.
   *
   * <p>Prefer calling this over {@link #getDirectDeps} if possible.
   *
   * <p>This method may only be called after the evaluation of this node is complete.
   */
  @ThreadSafe
  boolean hasAtLeastOneDep() throws InterruptedException;

  /** Removes a reverse dependency, which must be present. */
  @ThreadSafe
  void removeReverseDep(SkyKey reverseDep) throws InterruptedException;

  /**
   * Removes any reverse dependencies that are in {@code deletedKeys}. Must only be called from an
   * invalidation that is deleting nodes from the graph. Sacrifices correctness checks (that the
   * deleted rdeps were actually rdeps of this entry) for better performance.
   */
  @ThreadSafe
  void removeReverseDepsFromDoneEntryDueToDeletion(Set<SkyKey> deletedKeys);

  /**
   * Returns a copy of the set of reverse dependencies. Note that this introduces a potential
   * check-then-act race; {@link #removeReverseDep} may fail for a key that is returned here.
   *
   * <p>May only be called on a done node entry.
   */
  @ThreadSafe
  Collection<SkyKey> getReverseDepsForDoneEntry() throws InterruptedException;

  /**
   * Returns raw {@link SkyValue} stored in this entry, which may include metadata associated with
   * it (like events and errors).
   *
   * <p>This method returns {@code null} if the evaluation of this node is not complete, i.e., after
   * node creation or dirtying and before {@link #setValue} has been called. Callers should assert
   * that the returned value is not {@code null} whenever they expect the node should be done.
   *
   * <p>Use the static methods of {@link ValueWithMetadata} to extract metadata if necessary.
   */
  @ThreadSafe
  @Nullable
  SkyValue getValueMaybeWithMetadata() throws InterruptedException;

  /**
   * Returns the last known value of this node, even if it was {@linkplain #markDirty marked dirty}.
   *
   * <p>Unlike {@link #getValue}, this method may be called at any point in the node's lifecycle.
   * Returns {@code null} if this node was never built or has no value because it is in error.
   */
  @ThreadSafe
  @Nullable
  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.
   */
  @Nullable
  @ThreadSafe
  ErrorInfo getErrorInfo() throws InterruptedException;

  /**
   * Returns the set of reverse deps that have been declared so far this build. Only for use in
   * debugging and when bubbling errors up in the --nokeep_going case, where we need to know what
   * parents this entry has.
   */
  @ThreadSafe
  Set<SkyKey> getInProgressReverseDeps();

  /**
   * Transitions the node from the EVALUATING to the DONE state and simultaneously sets it to the
   * given value and error state. It then returns the set of reverse dependencies that need to be
   * 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.
   *
   * <p>Nodes may elect to use either {@code graphVersion} or {@code maxTransitiveSourceVersion} (if
   * not {@code null}) for their {@linkplain #getVersion version}. The choice can be distinguished
   * by calling {@link #getMaxTransitiveSourceVersion} - a return of {@code null} indicates that the
   * node uses the graph version.
   *
   * <p>If the entry determines that the new value is equal to the previous value, the entry may
   * keep its current version. Callers can query that version to see if the node considers its value
   * to have changed.
   *
   * @param value the new value of this node
   * @param graphVersion the version of the graph at which this node is being written
   * @param maxTransitiveSourceVersion the maximal version of this node's dependencies from source,
   *     or {@code null} if source versions are not being tracked
   */
  @ThreadSafe
  Set<SkyKey> setValue(
      SkyValue value, Version graphVersion, @Nullable Version maxTransitiveSourceVersion)
      throws InterruptedException;

  /**
   * Queries if the node is done and adds the given key as a reverse dependency. The return code
   * indicates whether a) the node is done, b) the reverse dependency is the first one, so the node
   * needs to be scheduled, or c) the reverse dependency was added, and the node does not need to be
   * scheduled.
   *
   * <p>This method <b>must</b> be called before any processing of the entry. This encourages
   * callers to check that the entry is ready to be processed.
   *
   * <p>Adding the dependency and checking if the node needs to be scheduled is an atomic operation
   * to avoid a race where two threads work on two nodes, where one depends on the other (b depends
   * on a). In that case, we need to ensure that b is re-scheduled exactly once when a is done.
   * However, a may complete first, in which case b has to re-schedule itself. Also see {@link
   * #setValue}.
   *
   * <p>If the parameter is {@code null}, then no reverse dependency is added, but we still check if
   * the node needs to be scheduled.
   *
   * <p>If {@code reverseDep} is a rebuilding dirty entry that was already a reverse dep of this
   * entry, then {@link #checkIfDoneForDirtyReverseDep} must be called instead.
   */
  @ThreadSafe
  DependencyState addReverseDepAndCheckIfDone(@Nullable SkyKey reverseDep)
      throws InterruptedException;

  /**
   * Similar to {@link #addReverseDepAndCheckIfDone}, except that {@code reverseDep} must already be
   * a reverse dep of this entry. Should be used when reverseDep has been marked dirty and is
   * checking its dependencies for changes or is rebuilding. The caller must treat the return value
   * just as they would the return value of {@link #addReverseDepAndCheckIfDone} by scheduling this
   * node for evaluation if needed.
   */
  @ThreadSafe
  DependencyState checkIfDoneForDirtyReverseDep(SkyKey reverseDep) throws InterruptedException;

  Collection<SkyKey> getAllReverseDepsForNodeBeingDeleted();

  /**
   * Tell this entry that one of its dependencies is now done. Callers must check the return value,
   * and if true, they must re-schedule this node for evaluation.
   *
   * <p>Even if {@code childVersion} is not at most {@link #getVersion}, this entry may not rebuild,
   * in the case that the entry already rebuilt at {@code childVersion} and discovered that it had
   * the same value as at an earlier version. For instance, after evaluating at version v1, at
   * version v2, child has a new value, but parent re-evaluates and finds it has the same value,
   * child.getVersion() will return v2 and parent.getVersion() will return v1. At v3 parent is
   * dirtied and checks its dep on child. child signals parent with version v2. That should not in
   * and of itself trigger a rebuild, since parent has already rebuilt with child at v2.
   *
   * @param childVersion If this entry {@link #isDirty} and the last version at which this entry was
   *     evaluated did not include the changes at version {@code childVersion} (for instance, if
   *     {@code childVersion} is after the last version at which this entry was evaluated), then
   *     this entry records that one of its children has changed since it was last evaluated. Thus,
   *     the next call to {@link #getLifecycleState} will return {@link
   *     LifecycleState#NEEDS_REBUILDING}.
   * @param childForDebugging for use in debugging (can be used to identify specific children that
   *     invalidate this node)
   */
  @ThreadSafe
  boolean signalDep(Version childVersion, @Nullable SkyKey childForDebugging);

  /**
   * Marks this entry as up-to-date at this version.
   *
   * @return {@link NodeValueAndRdepsToSignal} containing the SkyValue and reverse deps to signal.
   */
  @ThreadSafe
  NodeValueAndRdepsToSignal markClean() throws InterruptedException;

  /**
   * Returned by {@link #markClean} after making a node as clean. This is an aggregate object that
   * contains the NodeEntry's SkyValue and its reverse dependencies that signal this node is done (a
   * subset of all of the node's reverse dependencies).
   */
  final class NodeValueAndRdepsToSignal {
    private final SkyValue value;
    private final Set<SkyKey> rDepsToSignal;

    public NodeValueAndRdepsToSignal(SkyValue value, Set<SkyKey> rDepsToSignal) {
      this.value = value;
      this.rDepsToSignal = rDepsToSignal;
    }

    SkyValue getValue() {
      return this.value;
    }

    Set<SkyKey> getRdepsToSignal() {
      return this.rDepsToSignal;
    }
  }

  /**
   * Called on a dirty node during {@linkplain LifecycleState#CHECK_DEPENDENCIES dependency
   * checking} to force the node to be re-evaluated, even if none of its dependencies are known to
   * have changed.
   *
   * <p>Used when a caller has reason to believe that re-evaluating may yield a new result, such as
   * when the prior evaluation encountered a transient error.
   */
  @ThreadSafe
  void forceRebuild();

  /** Returns the current version of this node. */
  @ThreadSafe
  Version getVersion();

  /**
   * Returns the maximal version of this node's dependencies from source.
   *
   * <p>This version should only be tracked when non-hermetic functions {@linkplain
   * SkyFunction.Environment#injectVersionForNonHermeticFunction inject} source versions. Otherwise,
   * returns {@code null} to signal that source versions are not being tracked.
   */
  @ThreadSafe
  @Nullable
  default Version getMaxTransitiveSourceVersion() {
    return null;
  }

  /**
   * Returns the state of this entry as enumerated by {@link LifecycleState}.
   *
   * <p>This method may be called at any time. Returns {@link LifecycleState#DONE} iff the node
   * {@link #isDone}.
   */
  @ThreadSafe
  LifecycleState getLifecycleState();

  /**
   * Should only be called if the entry is in the {@link LifecycleState#CHECK_DEPENDENCIES} state.
   * During the examination to see if the entry must be re-evaluated, this method returns the next
   * group of children to be checked. Callers should have already called {@link #getLifecycleState}
   * and received a return value of {@link LifecycleState#CHECK_DEPENDENCIES} before calling this
   * method -- any other return value from {@link #getLifecycleState} means that this method must
   * not be called, since whether or not the node needs to be rebuilt is already known.
   *
   * <p>Deps are returned in groups. The deps in each group were requested in parallel by the {@code
   * SkyFunction} last build, meaning independently of the values of any other deps in this group
   * (although possibly depending on deps in earlier groups). Thus the caller may check all the deps
   * in this group in parallel, since the deps in all previous groups are verified unchanged. See
   * {@link SkyFunction.Environment#getValuesAndExceptions} for more on dependency groups.
   *
   * @see DirtyBuildingState#getNextDirtyDirectDeps()
   */
  @ThreadSafe
  List<SkyKey> getNextDirtyDirectDeps() throws InterruptedException;

  /**
   * Returns all deps of a node that has not yet finished evaluating. In other words, if a node has
   * a reverse dep on this node, its key will be in the returned set here.
   *
   * <p>The returned set is the union of:
   *
   * <ul>
   *   <li>This node's {@linkplain #getTemporaryDirectDeps temporary direct deps}.
   *   <li>Deps from a previous evaluation, if this this node was {@linkplain #markDirty marked
   *       dirty} (all the elements that would have been returned by successive calls to {@link
   *       #getNextDirtyDirectDeps} or, equivalently, one call to {@link
   *       #getAllRemainingDirtyDirectDeps}).
   *   <li>This node's {@linkplain #getResetDirectDeps reset direct deps}.
   * </ul>
   *
   * <p>This method should only be called when this node is about to be deleted after an aborted
   * evaluation. After such an evaluation, any nodes that did not finish evaluating are deleted, as
   * are any nodes that depend on them, which are necessarily also not done. If this node is to be
   * deleted because of this, we must delete it as a reverse dep from other nodes. This method
   * returns that list of other nodes. This method may not be called on done nodes, since they do
   * not need to be deleted after aborted evaluations.
   *
   * <p>This method must not be called twice: the next thing done to this node after this method is
   * called should be the removal of the node from the graph.
   */
  ImmutableSet<SkyKey> getAllDirectDepsForIncompleteNode() throws InterruptedException;

  /**
   * If an entry {@link #isDirty}, returns all direct deps that were present last build, but have
   * not yet been verified to be present during the current build. Implementations may lazily remove
   * these deps, since in many cases they will be added back during this build, even though the node
   * may have a changed value. However, any elements of this returned set that have not been added
   * back by the end of evaluation <i>must</i> be removed from any done nodes, in order to preserve
   * graph consistency.
   *
   * <p>Returns the empty set if an entry is not dirty. In either case, the entry must already have
   * started evaluation.
   *
   * <p>This method does not mutate the entry. In particular, multiple calls to this method will
   * always produce the same result until the entry finishes evaluation. Contrast with {@link
   * #getAllDirectDepsForIncompleteNode}.
   */
  ImmutableSet<SkyKey> getAllRemainingDirtyDirectDeps() throws InterruptedException;

  /**
   * Notifies a node that it is about to be rebuilt. This method can only be called if the node
   * {@link LifecycleState#NEEDS_REBUILDING}. After this call, this node is ready to be rebuilt (it
   * will be in {@link LifecycleState#REBUILDING}).
   */
  void markRebuilding();

  /**
   * Returns the {@link GroupedDeps} of direct dependencies. This may only be called while the node
   * is being evaluated (i.e. before {@link #setValue} and after {@link #markDirty}.
   */
  @ThreadSafe
  GroupedDeps getTemporaryDirectDeps();

  @ThreadSafe
  boolean noDepsLastBuild();

  /**
   * Remove dep from direct deps. This should only be called if this entry is about to be committed
   * as a cycle node, but some of its children were not checked for cycles, either because the cycle
   * was discovered before some children were checked; some children didn't have a chance to finish
   * before the evaluator aborted; or too many cycles were found when it came time to check the
   * children.
   */
  @ThreadSafe
  void removeUnfinishedDeps(Set<SkyKey> unfinishedDeps);

  /**
   * Prepares this node to reset its evaluation from scratch in order to recover from an
   * inconsistency.
   *
   * <p>Temporary direct deps should be cleared by this call, as they will be added again when
   * requested during the restarted evaluation of this node. If the graph keeps dependency edges,
   * however, the temporary direct deps must be accounted for in {@link #getResetDirectDeps}.
   *
   * <p>Called on a {@link LifecycleState#REBUILDING} node when one of the following scenarios is
   * observed:
   *
   * <ol>
   *   <li>One or more already requested dependencies are not done. This may happen when a
   *       dependency's node was dropped from the graph to save memory, or if a dependency was
   *       {@linkplain DirtyType#REWIND rewound} by another node.
   *   <li>The corresponding {@link SkyFunction} for this node returned {@link Reset} to indicate
   *       that one or more dependencies were done but are in need of {@linkplain DirtyType#REWIND
   *       rewinding} to regenerate their values.
   * </ol>
   *
   * <p>This method is similar to calling {@link #markDirty} with {@link DirtyType#REWIND} with an
   * important distinction: rewinding is initiated on a <em>done</em> node because of an issue with
   * its <em>value</em>, while this method is called on a <em>building</em> node because of an issue
   * with a <em>dependency</em>. The dependency will be rewound if we are in scenario 2 above.
   *
   * <p>Reverse deps on the other hand should be preserved - parents waiting on this node are
   * unaware that it is being restarted and will not register themselves again, yet they still need
   * to be signaled when this node is done.
   */
  @ThreadSafe
  void resetEvaluationFromScratch();

  /**
   * If the graph keeps dependency edges and {@link #resetEvaluationFromScratch} has been called on
   * this node since it was last done, returns the set of temporary direct deps that were registered
   * prior to the restart. Otherwise, returns an empty set.
   *
   * <p>Called on a {@link LifecycleState#REBUILDING} node when it is about to finish evaluating.
   * Used to determine which of its {@linkplain #getTemporaryDirectDeps temporary direct deps} have
   * already registered a corresponding reverse dep, in order to avoid creating duplicate rdep
   * edges.
   *
   * <p>Like {@link #getAllRemainingDirtyDirectDeps}, keys in the returned set are assumed to have
   * already registered an rdep on this node. Unlike {@link #getAllRemainingDirtyDirectDeps},
   * however, deps in the returned set may have only been registered at the current evaluation
   * version, not a previous one.
   *
   * <p>If this node was reset multiple times since it was last done, must return deps requested
   * prior to <em>any</em> of those restarts, not just the most recent one.
   */
  @ThreadSafe
  ImmutableSet<SkyKey> getResetDirectDeps();

  /**
   * Adds a temporary direct dep in its own group.
   *
   * <p>The given dep must not be present in this node's existing temporary direct deps.
   */
  @ThreadSafe
  void addSingletonTemporaryDirectDep(SkyKey dep);

  /**
   * Adds a temporary direct group.
   *
   * <p>The group must be duplicate-free and not contain any deps in common with this node's
   * existing temporary direct deps.
   */
  @ThreadSafe
  void addTemporaryDirectDepGroup(List<SkyKey> group);

  /**
   * Adds temporary direct deps in groups.
   *
   * <p>The iteration order of the given deps along with the {@code groupSizes} parameter dictate
   * how deps are grouped. For example, if {@code deps = {a,b,c}} and {@code groupSizes = [2, 1]},
   * then there will be two groups: {@code [a,b]} and {@code [c]}. The sum of {@code groupSizes}
   * must equal the size of {@code deps}. Note that it only makes sense to call this method with a
   * set implementation that has a stable iteration order.
   *
   * <p>The given set of deps must not contain any deps in common with this node's existing
   * temporary direct deps.
   */
  @ThreadSafe
  void addTemporaryDirectDepsInGroups(Set<SkyKey> deps, List<Integer> groupSizes);

  void addExternalDep();

  /**
   * Returns true if the node has been signaled exactly as many times as it has temporary
   * dependencies, or if {@code getKey().supportsPartialReevaluation()}. This may only be called
   * while the node is being evaluated (i.e. before {@link #setValue} and after {@link #markDirty}).
   */
  @ThreadSafe
  boolean isReadyToEvaluate();

  /**
   * Returns true if the node has not been signaled exactly as many times as it has temporary
   * dependencies. This may only be called while the node is being evaluated (i.e. before {@link
   * #setValue} and after {@link #markDirty}).
   *
   * <p>The node must not complete or be reset while in this state because it may yet be signaled.
   */
  @ThreadSafe
  boolean hasUnsignaledDeps();
}
