// 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.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
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.ForkJoinQuiescingExecutor;
import com.google.devtools.build.lib.concurrent.QuiescingExecutor;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.StoredEventHandler;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.profiler.ProfilerTask;
import com.google.devtools.build.lib.util.BlazeClock;
import com.google.devtools.build.lib.util.GroupedList.GroupedListHelper;
import com.google.devtools.build.lib.util.Preconditions;
import com.google.devtools.build.skyframe.EvaluationProgressReceiver.EvaluationState;
import com.google.devtools.build.skyframe.MemoizingEvaluator.EmittedEventState;
import com.google.devtools.build.skyframe.NodeEntry.DependencyState;
import com.google.devtools.build.skyframe.NodeEntry.DirtyState;
import com.google.devtools.build.skyframe.SkyFunctionException.ReifiedSkyFunctionException;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.annotation.Nullable;

/**
 * Evaluates a set of given functions ({@code SkyFunction}s) with arguments ({@code SkyKey}s).
 * Cycles are not allowed and are detected during the traversal.
 *
 * <p>This class implements multi-threaded evaluation. This is a fairly complex process that has
 * strong consistency requirements between the {@link ProcessableGraph}, the nodes in the graph of
 * type {@link NodeEntry}, the work queue, and the set of in-flight nodes.
 *
 * <p>The basic invariants are:
 *
 * <p>A node can be in one of three states: ready, waiting, and done. A node is ready if and only
 * if all of its dependencies have been signaled. A node is done if it has a value. It is waiting
 * if not all of its dependencies have been signaled.
 *
 * <p>A node must be in the work queue if and only if it is ready. It is an error for a node to be
 * in the work queue twice at the same time.
 *
 * <p>A node is considered in-flight if it has been created, and is not done yet. In case of an
 * interrupt, the work queue is discarded, and the in-flight set is used to remove partially
 * computed values.
 *
 * <p>Each evaluation of the graph takes place at a "version," which is currently given by a
 * non-negative {@code long}. The version can also be thought of as an "mtime." Each node in the
 * graph has a version, which is the last version at which its value changed. This version data is
 * used to avoid unnecessary re-evaluation of values. If a node is re-evaluated and found to have
 * the same data as before, its version (mtime) remains the same. If all of a node's children's
 * have the same version as before, its re-evaluation can be skipped.
 *
 * <p>This class is not intended for direct use, and is only exposed as public for use in
 * evaluation implementations outside of this package.
 */
public final class ParallelEvaluator implements Evaluator {

  /** Filters out events which should not be stored. */
  public interface EventFilter extends Predicate<Event> {
    /**
     * Returns true if any events should be stored. Otherwise, optimizations may be made to avoid
     * doing unnecessary work.
     */
    boolean storeEvents();
  }

  private final ProcessableGraph graph;
  private final Version graphVersion;

  private static class SkyValueSupplier implements Supplier<SkyValue> {

    private final NodeEntry state;

    public SkyValueSupplier(NodeEntry state) {
      this.state = state;
    }

    @Override
    public SkyValue get() {
      return state.getValue();
    }
  }

  /** An general interface for {@link ParallelEvaluator} to receive objects of type {@code T}. */
  public interface Receiver<T> {
    // TODO(dmarting): should we just make it a common object for all Bazel codebase?
    /**
     * Consumes the given object.
     */
    void accept(T object);
  }

  private final ImmutableMap<SkyFunctionName, ? extends SkyFunction> skyFunctions;

  private final EventHandler reporter;
  private final NestedSetVisitor<TaggedEvents> replayingNestedSetEventVisitor;
  private final boolean keepGoing;
  private final boolean storeErrorsAlongsideValues;
  private final int threadCount;
  @Nullable private final ForkJoinPool forkJoinPool;
  @Nullable private final EvaluationProgressReceiver progressReceiver;
  private final DirtyKeyTracker dirtyKeyTracker;
  private final Receiver<Collection<SkyKey>> inflightKeysReceiver;
  private final EventFilter storedEventFilter;

  public ParallelEvaluator(
      ProcessableGraph graph,
      Version graphVersion,
      ImmutableMap<SkyFunctionName, ? extends SkyFunction> skyFunctions,
      final EventHandler reporter,
      EmittedEventState emittedEventState,
      EventFilter storedEventFilter,
      boolean keepGoing,
      int threadCount,
      @Nullable EvaluationProgressReceiver progressReceiver,
      DirtyKeyTracker dirtyKeyTracker,
      Receiver<Collection<SkyKey>> inflightKeysReceiver) {
    this.graph = graph;
    this.skyFunctions = skyFunctions;
    this.graphVersion = graphVersion;
    this.inflightKeysReceiver = inflightKeysReceiver;
    this.reporter = Preconditions.checkNotNull(reporter);
    this.keepGoing = keepGoing;
    this.storeErrorsAlongsideValues = true;
    this.threadCount = threadCount;
    this.progressReceiver = progressReceiver;
    this.dirtyKeyTracker = Preconditions.checkNotNull(dirtyKeyTracker);
    this.replayingNestedSetEventVisitor =
        new NestedSetVisitor<>(new NestedSetEventReceiver(reporter), emittedEventState);
    this.storedEventFilter = storedEventFilter;
    this.forkJoinPool = null;
  }

  public ParallelEvaluator(
      ProcessableGraph graph,
      Version graphVersion,
      ImmutableMap<SkyFunctionName, ? extends SkyFunction> skyFunctions,
      final EventHandler reporter,
      EmittedEventState emittedEventState,
      EventFilter storedEventFilter,
      boolean keepGoing,
      boolean storeErrorsAlongsideValues,
      @Nullable EvaluationProgressReceiver progressReceiver,
      DirtyKeyTracker dirtyKeyTracker,
      Receiver<Collection<SkyKey>> inflightKeysReceiver,
      ForkJoinPool forkJoinPool) {
    this.graph = graph;
    this.skyFunctions = skyFunctions;
    this.graphVersion = graphVersion;
    this.inflightKeysReceiver = inflightKeysReceiver;
    this.reporter = Preconditions.checkNotNull(reporter);
    this.keepGoing = keepGoing;
    this.storeErrorsAlongsideValues = storeErrorsAlongsideValues;
    Preconditions.checkState(storeErrorsAlongsideValues || keepGoing);
    this.threadCount = 0;
    this.progressReceiver = progressReceiver;
    this.dirtyKeyTracker = Preconditions.checkNotNull(dirtyKeyTracker);
    this.replayingNestedSetEventVisitor =
        new NestedSetVisitor<>(new NestedSetEventReceiver(reporter), emittedEventState);
    this.storedEventFilter = storedEventFilter;
    this.forkJoinPool = Preconditions.checkNotNull(forkJoinPool);
  }

  /**
   * Receives the events from the NestedSet and delegates to the reporter.
   */
  private static class NestedSetEventReceiver implements NestedSetVisitor.Receiver<TaggedEvents> {

    private final EventHandler reporter;

    public NestedSetEventReceiver(EventHandler reporter) {
      this.reporter = reporter;
    }
    @Override
    public void accept(TaggedEvents events) {
      String tag = events.getTag();
      for (Event e : events.getEvents()) {
        reporter.handle(e.withTag(tag));
      }
    }
  }

  /**
   * A suitable {@link SkyFunction.Environment} implementation.
   */
  class SkyFunctionEnvironment extends AbstractSkyFunctionEnvironment {
    private boolean building = true;
    private SkyKey depErrorKey = null;
    private final SkyKey skyKey;
    private SkyValue value = null;
    private ErrorInfo errorInfo = null;
    private final Map<SkyKey, ValueWithMetadata> bubbleErrorInfo;
    /** The values previously declared as dependencies. */
    private final Map<SkyKey, NodeEntry> directDeps;

    /**
     * The grouped list of values requested during this build as dependencies. On a subsequent
     * build, if this value is dirty, all deps in the same dependency group can be checked in
     * parallel for changes. In other words, if dep1 and dep2 are in the same group, then dep1 will
     * be checked in parallel with dep2. See {@link #getValues} for more.
     */
    private final GroupedListHelper<SkyKey> newlyRequestedDeps = new GroupedListHelper<>();

    /**
     * The value visitor managing the thread pool. Used to enqueue parents when this value is
     * finished, and, during testing, to block until an exception is thrown if a value builder
     * requests that.
     */
    private final ValueVisitor visitor;

    /** The set of errors encountered while fetching children. */
    private final Collection<ErrorInfo> childErrorInfos = new LinkedHashSet<>();
    private final StoredEventHandler eventHandler =
        new StoredEventHandler() {
          @Override
          @SuppressWarnings("UnsynchronizedOverridesSynchronized") // only delegates to thread-safe.
          public void handle(Event e) {
            checkActive();
            if (storedEventFilter.apply(e)) {
              super.handle(e);
            } else {
              reporter.handle(e);
            }
          }
        };

    private SkyFunctionEnvironment(SkyKey skyKey, Set<SkyKey> directDeps, ValueVisitor visitor) {
      this(skyKey, directDeps, null, visitor);
    }

    private SkyFunctionEnvironment(SkyKey skyKey, Set<SkyKey> directDeps,
        @Nullable Map<SkyKey, ValueWithMetadata> bubbleErrorInfo, ValueVisitor visitor) {
      this.skyKey = skyKey;
      this.directDeps = Collections.unmodifiableMap(
          batchPrefetch(directDeps, /*assertDone=*/bubbleErrorInfo == null, skyKey));
      this.bubbleErrorInfo = bubbleErrorInfo;
      this.visitor = visitor;
    }

    private Map<SkyKey, NodeEntry> batchPrefetch(
        Set<SkyKey> keys, boolean assertDone, SkyKey keyForDebugging) {
      Map<SkyKey, NodeEntry> batchMap = graph.getBatch(keys);
      if (batchMap.size() != keys.size()) {
        throw new IllegalStateException("Missing keys for " + keyForDebugging + ": "
            + Sets.difference(keys, batchMap.keySet()));
      }
      if (assertDone) {
        for (Map.Entry<SkyKey, NodeEntry> entry : batchMap.entrySet()) {
          Preconditions.checkState(
              entry.getValue().isDone(), "%s had not done %s", keyForDebugging, entry);
        }
      }
      return batchMap;
    }

    private void checkActive() {
      Preconditions.checkState(building, skyKey);
    }

    private NestedSet<TaggedEvents> buildEvents(boolean missingChildren) {
      // Aggregate the nested set of events from the direct deps, also adding the events from
      // building this value.
      NestedSetBuilder<TaggedEvents> eventBuilder = NestedSetBuilder.stableOrder();
      ImmutableList<Event> events = eventHandler.getEvents();
      if (!events.isEmpty()) {
        eventBuilder.add(new TaggedEvents(getTagFromKey(), events));
      }
      if (storedEventFilter.storeEvents()) {
        // Only do the work of processing children if we're going to store events.
        Set<SkyKey> depKeys = graph.get(skyKey).getTemporaryDirectDeps();
        Map<SkyKey, ValueWithMetadata> deps = getValuesMaybeFromError(depKeys, bubbleErrorInfo);
        if (!missingChildren && depKeys.size() != deps.size()) {
          throw new IllegalStateException(
              "Missing keys for "
                  + skyKey
                  + ": "
                  + Sets.difference(depKeys, deps.keySet())
                  + ", "
                  + graph.get(skyKey));
        }
        for (ValueWithMetadata value : deps.values()) {
          eventBuilder.addTransitive(value.getTransitiveEvents());
        }
      }
      return eventBuilder.build();
    }

    /**
     * If this node has an error, that is, if errorInfo is non-null, do nothing. Otherwise, set
     * errorInfo to the union of the child errors that were recorded earlier by getValueOrException,
     * if there are any.
     *
     * <p>Child errors are remembered, if there are any and yet the parent recovered without
     * error, so that subsequent noKeepGoing evaluations can stop as soon as they encounter a
     * node whose (transitive) children had experienced an error, even if that (transitive)
     * parent node had been able to recover from it during a keepGoing build. This behavior can be
     * suppressed by setting {@link #storeErrorsAlongsideValues} to false, which will cause nodes
     * with values to have no stored error info. This may be useful if this graph will only ever be
     * used for keepGoing builds, since in that case storing errors from recovered nodes is
     * pointless.
     */
    private void finalizeErrorInfo() {
      if (errorInfo == null
          && (storeErrorsAlongsideValues || value == null)
          && !childErrorInfos.isEmpty()) {
        errorInfo = ErrorInfo.fromChildErrors(skyKey, childErrorInfos);
      }
    }

    private void setValue(SkyValue newValue) {
      Preconditions.checkState(errorInfo == null && bubbleErrorInfo == null,
          "%s %s %s %s", skyKey, newValue, errorInfo, bubbleErrorInfo);
      Preconditions.checkState(value == null, "%s %s %s", skyKey, value, newValue);
      value = newValue;
    }

    /**
     * Set this node to be in error. The node's value must not have already been set. However, all
     * 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(ErrorInfo errorInfo, boolean isDirectlyTransient) {
      Preconditions.checkState(value == null, "%s %s %s", skyKey, value, errorInfo);
      Preconditions.checkState(this.errorInfo == null,
          "%s %s %s", skyKey, this.errorInfo, errorInfo);

      if (isDirectlyTransient) {
        DependencyState triState =
            graph.get(ErrorTransienceValue.KEY).addReverseDepAndCheckIfDone(skyKey);
        Preconditions.checkState(triState == DependencyState.DONE,
            "%s %s %s", skyKey, triState, errorInfo);

        final NodeEntry state = graph.get(skyKey);
        state.addTemporaryDirectDeps(
            GroupedListHelper.create(ImmutableList.of(ErrorTransienceValue.KEY)));
        state.signalDep();
      }

      this.errorInfo = Preconditions.checkNotNull(errorInfo, skyKey);
    }

    private Map<SkyKey, ValueWithMetadata> getValuesMaybeFromError(Set<SkyKey> keys,
        @Nullable Map<SkyKey, ValueWithMetadata> bubbleErrorInfo) {
      ImmutableMap.Builder<SkyKey, ValueWithMetadata> builder = ImmutableMap.builder();
      ArrayList<SkyKey> missingKeys = new ArrayList<>(keys.size());
      for (SkyKey key : keys) {
        NodeEntry entry = directDeps.get(key);
        if (entry != null) {
          ValueWithMetadata valueWithMetadata =
              maybeWrapValueFromError(key, entry, bubbleErrorInfo);
          if (valueWithMetadata != null) {
            builder.put(key, valueWithMetadata);
          }
        } else {
          missingKeys.add(key);
        }
      }
      Map<SkyKey, NodeEntry> missingEntries = graph.getBatch(missingKeys);
      for (SkyKey key : missingKeys) {
        ValueWithMetadata valueWithMetadata = maybeWrapValueFromError(key, missingEntries.get(key),
            bubbleErrorInfo);
        if (valueWithMetadata != null) {
          builder.put(key, valueWithMetadata);
        }
      }
      return builder.build();
    }

    @Override
    protected ImmutableMap<SkyKey, ValueOrUntypedException> getValueOrUntypedExceptions(
        Set<SkyKey> depKeys) {
      checkActive();
      Map<SkyKey, ValueWithMetadata> values = getValuesMaybeFromError(depKeys, bubbleErrorInfo);
      ImmutableMap.Builder<SkyKey, ValueOrUntypedException> builder = ImmutableMap.builder();
      for (SkyKey depKey : depKeys) {
        Preconditions.checkState(!depKey.equals(ErrorTransienceValue.KEY));
        ValueWithMetadata value = values.get(depKey);
        if (value == null) {
          // If this entry is not yet done then (optionally) record the missing dependency and
          // return null.
          valuesMissing = true;
          if (bubbleErrorInfo != null) {
            // Values being built just for their errors don't get to request new children.
            builder.put(depKey, ValueOrExceptionUtils.ofNull());
            continue;
          }
          if (directDeps.containsKey(depKey)) {
            throw new IllegalStateException(
                "Undone key "
                    + depKey
                    + " was already in deps of "
                    + skyKey
                    + "( dep: "
                    + graph.get(depKey)
                    + ", parent: "
                    + graph.get(skyKey));
          }
          addDep(depKey);
          valuesMissing = true;
          builder.put(depKey, ValueOrExceptionUtils.ofNull());
          continue;
        }

        if (!directDeps.containsKey(depKey)) {
          // If this child is done, we will return it, but also record that it was newly requested
          // so that the dependency can be properly registered in the graph.
          addDep(depKey);
        }

        replayingNestedSetEventVisitor.visit(value.getTransitiveEvents());
        ErrorInfo errorInfo = value.getErrorInfo();

        if (errorInfo != null) {
          childErrorInfos.add(errorInfo);
        }

        if (value.getValue() != null && (keepGoing || errorInfo == null)) {
          // If the dep did compute a value, it is given to the caller if we are in keepGoing mode
          // or if we are in noKeepGoingMode and there were no errors computing it.
          builder.put(depKey, ValueOrExceptionUtils.ofValueUntyped(value.getValue()));
          continue;
        }

        // There was an error building the value, which we will either report by throwing an
        // exception or insulate the caller from by returning null.
        Preconditions.checkNotNull(errorInfo, "%s %s %s", skyKey, depKey, value);

        if (!keepGoing && errorInfo.getException() != null && bubbleErrorInfo == null) {
          // Child errors should not be propagated in noKeepGoing mode (except during error
          // bubbling). Instead we should fail fast.

          // We arbitrarily record the first child error.
          if (depErrorKey == null) {
            depErrorKey = depKey;
          }
          valuesMissing = true;
          builder.put(depKey, ValueOrExceptionUtils.ofNull());
          continue;
        }

        if (bubbleErrorInfo != null) {
          // Set interrupted status, to try to prevent the calling SkyFunction from doing anything
          // fancy after this. SkyFunctions executed during error bubbling are supposed to
          // (quickly) rethrow errors or return a value/null (but there's currently no way to
          // enforce this).
          Thread.currentThread().interrupt();
        }
        if (errorInfo.getException() != null) {
          // Give builder a chance to handle this exception.
          Exception e = errorInfo.getException();
          builder.put(depKey, ValueOrExceptionUtils.ofExn(e));
          continue;
        }
        // In a cycle.
        Preconditions.checkState(!Iterables.isEmpty(errorInfo.getCycleInfo()), "%s %s %s %s",
            skyKey, depKey, errorInfo, value);
        valuesMissing = true;
        builder.put(depKey, ValueOrExceptionUtils.ofNull());
      }
      return builder.build();
    }

    @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<SkyKey> depKeys,
            Class<E1> exceptionClass1,
            Class<E2> exceptionClass2,
            Class<E3> exceptionClass3,
            Class<E4> exceptionClass4,
            Class<E5> exceptionClass5) {
      newlyRequestedDeps.startGroup();
      Map<SkyKey, ValueOrException5<E1, E2, E3, E4, E5>> result = super.getValuesOrThrow(
          depKeys,
          exceptionClass1,
          exceptionClass2,
          exceptionClass3,
          exceptionClass4,
          exceptionClass5);
      newlyRequestedDeps.endGroup();
      return result;
    }

    private void addDep(SkyKey key) {
      if (!newlyRequestedDeps.contains(key)) {
        // dep may have been requested already this evaluation. If not, add it.
        newlyRequestedDeps.add(key);
      }
    }

    /**
     * If {@code !keepGoing} and there is at least one dep in error, returns a dep in error.
     * Otherwise returns {@code null}.
     */
    @Nullable
    private SkyKey getDepErrorKey() {
      return depErrorKey;
    }

    @Override
    public EventHandler getListener() {
      checkActive();
      return eventHandler;
    }

    private void doneBuilding() {
      building = false;
    }

    /**
     * Apply the change to the graph (mostly) atomically and signal all nodes that are waiting for
     * this node to complete. Adding nodes and signaling is not atomic, but may need to be changed
     * for interruptibility.
     *
     * <p>Parents are only enqueued if {@code enqueueParents} holds. Parents should be enqueued
     * unless (1) this node is being built after the main evaluation has aborted, or (2) this node
     * is being built with --nokeep_going, and so we are about to shut down the main evaluation
     * anyway.
     *
     * <p>The node entry is informed if the node's value and error are definitive via the flag
     * {@code completeValue}.
     */
    void commit(boolean enqueueParents) {
      NodeEntry primaryEntry = Preconditions.checkNotNull(graph.get(skyKey), skyKey);
      // Construct the definitive error info, if there is one.
      finalizeErrorInfo();

      // We have the following implications:
      // errorInfo == null => value != null => enqueueParents.
      // All these implications are strict:
      // (1) errorInfo != null && value != null happens for values with recoverable errors.
      // (2) value == null && enqueueParents happens for values that are found to have errors
      // during a --keep_going build.

      NestedSet<TaggedEvents> events = buildEvents(/*missingChildren=*/false);
      Version valueVersion;
      SkyValue valueWithMetadata;
      if (value == null) {
        Preconditions.checkNotNull(errorInfo, "%s %s", skyKey, primaryEntry);
        valueWithMetadata = ValueWithMetadata.error(errorInfo, events);
      } else {
        // We must be enqueueing parents if we have a value.
        Preconditions.checkState(enqueueParents, "%s %s", skyKey, primaryEntry);
        valueWithMetadata = ValueWithMetadata.normal(value, errorInfo, events);
      }
      // If this entry is dirty, setValue may not actually change it, if it determines that
      // the data being written now is the same as the data already present in the entry.
      // We could consider using max(childVersions) here instead of graphVersion. When full
      // versioning is implemented, this would allow evaluation at a version between
      // max(childVersions) and graphVersion to re-use this result.
      Set<SkyKey> reverseDeps = primaryEntry.setValue(valueWithMetadata, graphVersion);
      // Note that if this update didn't actually change the value entry, this version may not
      // be the graph version.
      valueVersion = primaryEntry.getVersion();
      Preconditions.checkState(valueVersion.atMost(graphVersion),
          "%s should be at most %s in the version partial ordering",
          valueVersion, graphVersion);
      if (progressReceiver != null) {
        // Tell the receiver that this value was built. If valueVersion.equals(graphVersion), it
        // was evaluated this run, and so was changed. Otherwise, it is less than graphVersion,
        // by the Preconditions check above, and was not actually changed this run -- when it was
        // written above, its version stayed below this update's version, so its value remains the
        // same as before.
        // We use a SkyValueSupplier here because it keeps a reference to the entry, allowing for
        // the receiver to be confident that the entry is readily accessible in memory.
        progressReceiver.evaluated(skyKey, new SkyValueSupplier(primaryEntry),
            valueVersion.equals(graphVersion) ? EvaluationState.BUILT : EvaluationState.CLEAN);
      }
      signalValuesAndEnqueueIfReady(enqueueParents ? visitor : null, reverseDeps, valueVersion);

      visitor.notifyDone(skyKey);
      replayingNestedSetEventVisitor.visit(events);
    }

    @Nullable
    private String getTagFromKey() {
      return skyFunctions.get(skyKey.functionName()).extractTag(skyKey);
    }

    /**
     * Gets the latch that is counted down when an exception is thrown in {@code
     * AbstractQueueVisitor}. For use in tests to check if an exception actually was thrown. Calling
     * {@code AbstractQueueVisitor#awaitExceptionForTestingOnly} can throw a spurious {@link
     * InterruptedException} because {@link CountDownLatch#await} checks the interrupted bit before
     * returning, even if the latch is already at 0. See bug "testTwoErrors is flaky".
     */
    CountDownLatch getExceptionLatchForTesting() {
      return visitor.getExceptionLatchForTestingOnly();
    }

    @Override
    public boolean inErrorBubblingForTesting() {
      return bubbleErrorInfo != null;
    }
  }

  private static final ErrorClassifier VALUE_VISITOR_ERROR_CLASSIFIER =
      new ErrorClassifier() {
        @Override
        protected ErrorClassification classifyException(Exception e) {
          if (e instanceof SchedulerException) {
            return ErrorClassification.CRITICAL;
          }
          if (e instanceof RuntimeException) {
            return ErrorClassification.CRITICAL_AND_LOG;
          }
          return ErrorClassification.NOT_CRITICAL;
        }
      };

  private class ValueVisitor {

    private final QuiescingExecutor quiescingExecutor;
    private final AtomicBoolean preventNewEvaluations = new AtomicBoolean(false);
    private final Set<SkyKey> inflightNodes = Sets.newConcurrentHashSet();
    private final Set<RuntimeException> crashes = Sets.newConcurrentHashSet();

    private ValueVisitor(ForkJoinPool forkJoinPool) {
      quiescingExecutor =
          new ForkJoinQuiescingExecutor(forkJoinPool, VALUE_VISITOR_ERROR_CLASSIFIER);
    }

    private ValueVisitor(int threadCount) {
      quiescingExecutor =
          new AbstractQueueVisitor(
              /*concurrent*/ true,
              threadCount,
              /*keepAliveTime=*/ 1,
              TimeUnit.SECONDS,
              /*failFastOnException*/ true,
              /*failFastOnInterrupt*/ true,
              "skyframe-evaluator",
              VALUE_VISITOR_ERROR_CLASSIFIER);
    }

    private void waitForCompletion() throws InterruptedException {
      quiescingExecutor.awaitQuiescence(/*interruptWorkers=*/ true);
    }

    private void enqueueEvaluation(SkyKey key) {
      // We unconditionally add the key to the set of in-flight nodes because even if evaluation is
      // never scheduled we still want to remove the previously created NodeEntry from the graph.
      // Otherwise we would leave the graph in a weird state (wasteful garbage in the best case and
      // inconsistent in the worst case).
      boolean newlyEnqueued = inflightNodes.add(key);
      // All nodes enqueued for evaluation will be either verified clean, re-evaluated, or cleaned
      // up after being in-flight when an error happens in nokeep_going mode or in the event of an
      // interrupt. In any of these cases, they won't be dirty anymore.
      if (newlyEnqueued) {
        dirtyKeyTracker.notDirty(key);
      }
      if (preventNewEvaluations.get()) {
        return;
      }
      if (newlyEnqueued && progressReceiver != null) {
        progressReceiver.enqueueing(key);
      }
      quiescingExecutor.execute(new Evaluate(this, key));
    }

    /**
     * Stop any new evaluations from being enqueued. Returns whether this was the first thread to
     * request a halt. If true, this thread should proceed to throw an exception. If false, another
     * thread already requested a halt and will throw an exception, and so this thread can simply
     * end.
     */
    private boolean preventNewEvaluations() {
      return preventNewEvaluations.compareAndSet(false, true);
    }

    private void noteCrash(RuntimeException e) {
      crashes.add(e);
    }

    private Collection<RuntimeException> getCrashes() {
      return crashes;
    }

    private void notifyDone(SkyKey key) {
      inflightNodes.remove(key);
    }

    private boolean isInflight(SkyKey key) {
      return inflightNodes.contains(key);
    }

    @VisibleForTesting
    private CountDownLatch getExceptionLatchForTestingOnly() {
      return quiescingExecutor.getExceptionLatchForTestingOnly();
    }
  }

  /**
   * If the entry is dirty and not already rebuilding, puts it in a state that it can rebuild, and
   * removes it as a reverse dep from any dirty direct deps it had yet to check.
   */
  private void maybeMarkRebuildingAndRemoveRemainingDirtyDirectDeps(SkyKey key, NodeEntry entry) {
    if (entry.isDirty() && entry.getDirtyState() != DirtyState.REBUILDING) {
      Collection<SkyKey> depsToRemove = entry.markRebuildingAndGetAllRemainingDirtyDirectDeps();
      Map<SkyKey, NodeEntry> depsToClearFrom = graph.getBatch(depsToRemove);
      if (depsToClearFrom.size() != depsToRemove.size()) {
        throw new IllegalStateException(
            "At least one dep of a dirty node wasn't present in the graph: "
                + Sets.difference(ImmutableSet.copyOf(depsToRemove), depsToClearFrom.keySet())
                + " for "
                + key
                + " with entry "
                + entry
                + ". Sizes: "
                + depsToRemove.size()
                + ", "
                + depsToClearFrom.size());
      }
      for (NodeEntry depEntry : depsToClearFrom.values()) {
        depEntry.removeReverseDep(key);
      }
    }
  }

  private enum DirtyOutcome {
    ALREADY_PROCESSED,
    NEEDS_EVALUATION
  }

  /**
   * An action that evaluates a value.
   */
  private class Evaluate implements Runnable {
    private final ValueVisitor visitor;
    /** The name of the value to be evaluated. */
    private final SkyKey skyKey;

    private Evaluate(ValueVisitor visitor, SkyKey skyKey) {
      this.visitor = visitor;
      this.skyKey = skyKey;
    }

    private void enqueueChild(SkyKey skyKey, NodeEntry entry, SkyKey child, NodeEntry childEntry,
        boolean dirtyParent) {
      Preconditions.checkState(!entry.isDone(), "%s %s", skyKey, entry);
      DependencyState dependencyState =
          dirtyParent
              ? childEntry.checkIfDoneForDirtyReverseDep(skyKey)
              : childEntry.addReverseDepAndCheckIfDone(skyKey);
      switch (dependencyState) {
        case DONE:
          if (entry.signalDep(childEntry.getVersion())) {
            // This can only happen if there are no more children to be added.
            visitor.enqueueEvaluation(skyKey);
          }
          break;
        case ALREADY_EVALUATING:
          break;
        case NEEDS_SCHEDULING:
          visitor.enqueueEvaluation(child);
          break;
      }
    }

    /**
     * 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) {
      return depGroup.size() == 1
          && depGroup.contains(ErrorTransienceValue.KEY)
          && !graph.get(ErrorTransienceValue.KEY).getVersion().atMost(entry.getVersion());
    }

    private DirtyOutcome maybeHandleDirtyNode(NodeEntry state) {
      if (!state.isDirty()) {
        return DirtyOutcome.NEEDS_EVALUATION;
      }
      switch (state.getDirtyState()) {
        case CHECK_DEPENDENCIES:
          // Evaluating a dirty node for the first time, and checking its children to see if any
          // of them have changed. Note that there must be dirty children for this to happen.

          // Check the children group by group -- we don't want to evaluate a value that is no
          // longer needed because an earlier dependency changed. For example, //foo:foo depends
          // on target //bar:bar and is built. Then foo/BUILD is modified to remove the dependence
          // on bar, and bar/BUILD is deleted. Reloading //bar:bar would incorrectly throw an
          // exception. To avoid this, we must reload foo/BUILD first, at which point we will
          // discover that it has changed, and re-evaluate target //foo:foo from scratch.
          // On the other hand, when an action requests all of its inputs, we can safely check all
          // of them in parallel on a subsequent build. So we allow checking an entire group in
          // parallel here, if the node builder requested a group last build.
          // Note: every dep returned here must either have this node re-registered for it (using
          // checkIfDoneForDirtyReverseDep) and be registered as a direct dep of this node, or have
          // its reverse dep on this node removed. Failing to do either one of these would result in
          // a graph inconsistency, where the child had a reverse dep on this node, but this node
          // had no kind of dependency on the child.
          Collection<SkyKey> directDepsToCheck = state.getNextDirtyDirectDeps();

          if (invalidatedByErrorTransience(directDepsToCheck, state)) {
            // If this dep is the ErrorTransienceValue and the ErrorTransienceValue has been
            // updated then we need to force a rebuild. We would like to just signal the entry as
            // usual, but we can't, because then the ErrorTransienceValue would remain as a dep,
            // which would be incorrect if, for instance, the value re-evaluated to a non-error.
            state.forceRebuild();
            graph.get(ErrorTransienceValue.KEY).removeReverseDep(skyKey);
            return DirtyOutcome.NEEDS_EVALUATION;
          }
          if (!keepGoing) {
            // This check ensures that we maintain the invariant that if a node with an error is
            // reached during a no-keep-going build, none of its currently building parents
            // finishes building. If the child isn't done building yet, it will detect on its own
            // that it has an error (see the VERIFIED_CLEAN case below). On the other hand, if it
            // 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 = graph.getBatch(directDepsToCheck);
            for (Map.Entry<SkyKey, 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.
                SkyKey errorKey = entry.getKey();
                NodeEntry errorEntry = entry.getValue();
                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()) {
                  if (!depEntry.getKey().equals(errorKey)) {
                    depEntry.getValue().removeReverseDep(skyKey);
                  }
                }
                if (!visitor.preventNewEvaluations()) {
                  // An error was already thrown in the evaluator. Don't do anything here.
                  return DirtyOutcome.ALREADY_PROCESSED;
                }
                throw SchedulerException.ofError(errorEntry.getErrorInfo(), entry.getKey());
              }
            }
          }
          // It is safe to add these deps back to the node -- even if one of them has changed, the
          // contract of pruning is that the node will request these deps again when it rebuilds.
          // We must add these deps before enqueuing them, so that the node knows that it depends
          // on them. If one of these deps is the error transience node, the check we did above
          // in #invalidatedByErrorTransience means that the error transience node is not newer
          // than this node, so we are going to mark it clean (since the error transience node is
          // always the last dep).
          state.addTemporaryDirectDepsGroupToDirtyEntry(directDepsToCheck);

          for (Map.Entry<SkyKey, NodeEntry> e
              : graph.createIfAbsentBatch(directDepsToCheck).entrySet()) {
            SkyKey directDep = e.getKey();
            NodeEntry directDepEntry = e.getValue();
            enqueueChild(skyKey, state, directDep, directDepEntry, /*dirtyParent=*/ true);
          }
          return DirtyOutcome.ALREADY_PROCESSED;
        case VERIFIED_CLEAN:
          // No child has a changed value. This node can be marked done and its parents signaled
          // without any re-evaluation.
          visitor.notifyDone(skyKey);
          Set<SkyKey> reverseDeps = state.markClean();
          if (progressReceiver != null) {
            // Tell the receiver that the value was not actually changed this run.
            progressReceiver.evaluated(skyKey, new SkyValueSupplier(state), EvaluationState.CLEAN);
          }
          if (!keepGoing && state.getErrorInfo() != null) {
            if (!visitor.preventNewEvaluations()) {
              return DirtyOutcome.ALREADY_PROCESSED;
            }
            throw SchedulerException.ofError(state.getErrorInfo(), skyKey);
          }
          signalValuesAndEnqueueIfReady(visitor, reverseDeps, state.getVersion());
          return DirtyOutcome.ALREADY_PROCESSED;
        case NEEDS_REBUILDING:
          maybeMarkRebuildingAndRemoveRemainingDirtyDirectDeps(skyKey, state);
          // Fall through to REBUILDING case.
        case REBUILDING:
          return DirtyOutcome.NEEDS_EVALUATION;
        default:
          throw new IllegalStateException("key: " + skyKey + ", entry: " + state);
      }
    }

    @Override
    public void run() {
      NodeEntry state = Preconditions.checkNotNull(graph.get(skyKey), skyKey);
      Preconditions.checkState(state.isReady(), "%s %s", skyKey, state);
      if (maybeHandleDirtyNode(state) == DirtyOutcome.ALREADY_PROCESSED) {
        return;
      }

      // TODO(bazel-team): Once deps are requested in a deterministic order within a group, or the
      // framework is resilient to rearranging group order, change this so that
      // SkyFunctionEnvironment "follows along" as the node builder runs, iterating through the
      // direct deps that were requested on a previous run. This would allow us to avoid the
      // conversion of the direct deps into a set.
      Set<SkyKey> directDeps = state.getTemporaryDirectDeps();
      Preconditions.checkState(!directDeps.contains(ErrorTransienceValue.KEY),
          "%s cannot have a dep on ErrorTransienceValue during building: %s", skyKey, state);
      // Get the corresponding SkyFunction and call it on this value.
      SkyFunctionEnvironment env = new SkyFunctionEnvironment(skyKey, directDeps, visitor);
      SkyFunctionName functionName = skyKey.functionName();
      SkyFunction factory = skyFunctions.get(functionName);
      Preconditions.checkState(factory != null,
          "Unable to find SkyFunction '%s' for SkyValue with key '%s'", functionName, state);

      SkyValue value = null;
      long startTime = BlazeClock.instance().nanoTime();
      try {
        value = factory.compute(skyKey, env);
      } catch (final SkyFunctionException builderException) {
        ReifiedSkyFunctionException reifiedBuilderException =
            new ReifiedSkyFunctionException(builderException, skyKey);
        // Propagated transitive errors are treated the same as missing deps.
        if (reifiedBuilderException.getRootCauseSkyKey().equals(skyKey)) {
          boolean shouldFailFast = !keepGoing || builderException.isCatastrophic();
          if (shouldFailFast) {
            // After we commit this error to the graph but before the eval call completes with the
            // error there is a race-like opportunity for the error to be used, either by an
            // in-flight computation or by a future computation.
            if (!visitor.preventNewEvaluations()) {
              // This is not the first error encountered, so we ignore it so that we can terminate
              // with the first error.
              return;
            }
          }

          Map<SkyKey, NodeEntry> newlyRequestedDeps = graph.getBatch(env.newlyRequestedDeps);
          boolean isTransitivelyTransient = reifiedBuilderException.isTransient();
          for (NodeEntry depEntry
              : Iterables.concat(env.directDeps.values(), newlyRequestedDeps.values())) {
            if (!isDoneForBuild(depEntry)) {
              continue;
            }
            ErrorInfo depError = depEntry.getErrorInfo();
            if (depError != null) {
              isTransitivelyTransient |= depError.isTransient();
            }
          }
          ErrorInfo errorInfo = ErrorInfo.fromException(reifiedBuilderException,
              isTransitivelyTransient);
          registerNewlyDiscoveredDepsForDoneEntry(skyKey, state, newlyRequestedDeps, env);
          env.setError(errorInfo, /*isDirectlyTransient=*/ reifiedBuilderException.isTransient());
          env.commit(/*enqueueParents=*/keepGoing);
          if (!shouldFailFast) {
            return;
          }
          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.
        String msg = prepareCrashMessage(skyKey, state.getInProgressReverseDeps());
        RuntimeException ex = new RuntimeException(msg, re);
        visitor.noteCrash(ex);
        throw ex;
      } finally {
        env.doneBuilding();
        long elapsedTimeNanos =  BlazeClock.instance().nanoTime() - startTime;
        if (elapsedTimeNanos > 0)  {
          if (progressReceiver != null) {
            progressReceiver.computed(skyKey, elapsedTimeNanos);
          }
          Profiler.instance().logSimpleTaskDuration(startTime, elapsedTimeNanos,
              ProfilerTask.SKYFUNCTION, skyKey);
        }
      }

      GroupedListHelper<SkyKey> newDirectDeps = env.newlyRequestedDeps;

      if (value != null) {
        Preconditions.checkState(!env.valuesMissing(), "Evaluation of %s returned non-null value "
            + "but requested dependencies that weren't computed yet (one of %s), ValueEntry: %s",
            skyKey, newDirectDeps, state);
        env.setValue(value);
        registerNewlyDiscoveredDepsForDoneEntry(skyKey, state,
            graph.getBatch(env.newlyRequestedDeps), env);
        env.commit(/*enqueueParents=*/true);
        return;
      }

      if (env.getDepErrorKey() != null) {
        Preconditions.checkState(!keepGoing, "%s %s %s", skyKey, state, env.getDepErrorKey());
        // We encountered a child error in noKeepGoing mode, so we want to fail fast. But we first
        // need to add the edge between the current node and the child error it requested so that
        // error bubbling can occur. Note that this edge will subsequently be removed during graph
        // cleaning (since the current node will never be committed to the graph).
        SkyKey childErrorKey = env.getDepErrorKey();
        NodeEntry childErrorEntry = Preconditions.checkNotNull(graph.get(childErrorKey),
            "skyKey: %s, state: %s childErrorKey: %s", skyKey, state, childErrorKey);
        Preconditions.checkState(
            !state.getTemporaryDirectDeps().contains(childErrorKey),
            "Done error was already know: %s %s %s %s",
            skyKey,
            state,
            childErrorKey,
            childErrorEntry);
        Preconditions.checkState(
            newDirectDeps.contains(childErrorKey), "%s %s %s", state, childErrorKey, newDirectDeps);
        state.addTemporaryDirectDeps(GroupedListHelper.create(ImmutableList.of(childErrorKey)));
        DependencyState 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();
        throw SchedulerException.ofError(childErrorInfo, childErrorKey);
      }

      // TODO(bazel-team): This code is not safe to interrupt, because we would lose the state in
      // newDirectDeps.

      // TODO(bazel-team): An ill-behaved SkyFunction can throw us into an infinite loop where we
      // add more dependencies on every run. [skyframe-core]

      // Add all new keys to the set of known deps.
      state.addTemporaryDirectDeps(newDirectDeps);

      // If there were no newly requested dependencies, at least one of them was in error or there
      // is a bug in the SkyFunction implementation. The environment has collected its errors, so we
      // just order it to be built.
      if (newDirectDeps.isEmpty()) {
        // TODO(bazel-team): This means a bug in the SkyFunction. What to do?
        Preconditions.checkState(!env.childErrorInfos.isEmpty(),
            "Evaluation of SkyKey failed and no dependencies were requested: %s %s", skyKey, state);
        Preconditions.checkState(
            keepGoing,
            "nokeep_going evaluation should have failed on first child error: %s %s %s",
            skyKey,
            state,
            env.childErrorInfos);
        // If the child error was catastrophic, committing this parent to the graph is not
        // necessary, but since we don't do error bubbling in catastrophes, it doesn't violate any
        // invariants either.
        env.commit(/*enqueueParents=*/ true);
        return;
      }

      for (Map.Entry<SkyKey, NodeEntry> e : graph.createIfAbsentBatch(newDirectDeps).entrySet()) {
        SkyKey newDirectDep = e.getKey();
        NodeEntry newDirectDepEntry = e.getValue();
        enqueueChild(skyKey, state, newDirectDep, newDirectDepEntry, /*dirtyParent=*/ false);
      }
      // It is critical that there is no code below this point.
    }

    private String prepareCrashMessage(SkyKey skyKey, Iterable<SkyKey> reverseDeps) {
      StringBuilder reverseDepDump = new StringBuilder();
      for (SkyKey key : reverseDeps) {
        if (reverseDepDump.length() > MAX_REVERSEDEP_DUMP_LENGTH) {
          reverseDepDump.append(", ...");
          break;
        }
        if (reverseDepDump.length() > 0) {
          reverseDepDump.append(", ");
        }
        reverseDepDump.append("'");
        reverseDepDump.append(key.toString());
        reverseDepDump.append("'");
      }

      return String.format(
          "Unrecoverable error while evaluating node '%s' (requested by nodes %s)",
          skyKey, reverseDepDump);
    }

    private static final int MAX_REVERSEDEP_DUMP_LENGTH = 1000;
  }

  /**
   * 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).
   */
  private void signalValuesAndEnqueueIfReady(
      @Nullable ValueVisitor visitor, Iterable<SkyKey> keys, Version version) {
    Map<SkyKey, NodeEntry> batch = graph.getBatch(keys);
    if (visitor != null) {
      for (SkyKey key : keys) {
        NodeEntry entry = Preconditions.checkNotNull(batch.get(key), key);
        if (entry.signalDep(version)) {
          visitor.enqueueEvaluation(key);
        }
      }
    } else {
      for (SkyKey key : keys) {
        NodeEntry entry = Preconditions.checkNotNull(batch.get(key), key);
        if (!entry.isDone()) {
          // In cycles, we can have parents that are already done.
          entry.signalDep(version);
        }
      }
    }
  }

  /**
   * 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 removeIncompleteChild(SkyKey inProgressParent, SkyKey child) {
    NodeEntry childEntry = graph.get(child);
    if (!isDoneForBuild(childEntry)) {
      childEntry.removeInProgressReverseDep(inProgressParent);
      return true;
    }
    return false;
  }

  /**
   * Add any additional deps that were registered during the run of a builder that finished by
   * creating a node or throwing an error. Builders may throw errors even if all their deps were
   * not provided -- we trust that a SkyFunction may be know it should throw an error even if not
   * all of its requested deps are done. However, that means we're assuming the SkyFunction would
   * throw that same error if all of its requested deps were done. Unfortunately, there is no way to
   * enforce that condition.
   */
  private void registerNewlyDiscoveredDepsForDoneEntry(
      SkyKey skyKey, NodeEntry entry, Map<SkyKey, NodeEntry> newlyRequestedDepMap,
      SkyFunctionEnvironment env) {
    Set<SkyKey> unfinishedDeps = new HashSet<>();
   for (SkyKey dep : env.newlyRequestedDeps) {
      if (!isDoneForBuild(newlyRequestedDepMap.get(dep))) {
        unfinishedDeps.add(dep);
      }
    }
    env.newlyRequestedDeps.remove(unfinishedDeps);
    entry.addTemporaryDirectDeps(env.newlyRequestedDeps);
    for (SkyKey newDep : env.newlyRequestedDeps) {
      // Note that this depEntry can't be null. If env.newlyRequestedDeps contained a key with a
      // null entry, then it would have been added to unfinishedDeps and then removed from
      // env.newlyRequestedDeps just above this loop.
      NodeEntry depEntry = Preconditions.checkNotNull(newlyRequestedDepMap.get(newDep), newDep);
      DependencyState triState = depEntry.addReverseDepAndCheckIfDone(skyKey);
      Preconditions.checkState(DependencyState.DONE == triState,
          "new dep %s was not already done for %s. ValueEntry: %s. DepValueEntry: %s",
          newDep, skyKey, entry, depEntry);
      entry.signalDep();
    }
    Preconditions.checkState(entry.isReady(), "%s %s %s", skyKey, entry, env.newlyRequestedDeps);
  }

  private void informProgressReceiverThatValueIsDone(SkyKey key) {
    if (progressReceiver != null) {
      NodeEntry entry = graph.get(key);
      Preconditions.checkState(entry.isDone(), entry);
      SkyValue value = entry.getValue();
      Version valueVersion = entry.getVersion();
      Preconditions.checkState(valueVersion.atMost(graphVersion),
          "%s should be at most %s in the version partial ordering", valueVersion, graphVersion);
      // For most nodes we do not inform the progress receiver if they were already done when we
      // retrieve them, but top-level nodes are presumably of more interest.
      // If valueVersion is not equal to graphVersion, it must be less than it (by the
      // Preconditions check above), and so the node is clean.
      progressReceiver.evaluated(key, Suppliers.ofInstance(value), valueVersion.equals(graphVersion)
          ? EvaluationState.BUILT
          : EvaluationState.CLEAN);
    }
  }

  @Override
  @ThreadCompatible
  public <T extends SkyValue> EvaluationResult<T> eval(Iterable<SkyKey> skyKeys)
      throws InterruptedException {
    ImmutableSet<SkyKey> skyKeySet = ImmutableSet.copyOf(skyKeys);

    // Optimization: if all required node values are already present in the cache, return them
    // 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 = graph.getBatch(skyKeySet);
    for (SkyKey key : skyKeySet) {
      if (!isDoneForBuild(batch.get(key))) {
        allAreDone = false;
        break;
      }
    }
    if (allAreDone) {
      for (SkyKey skyKey : skyKeySet) {
        informProgressReceiverThatValueIsDone(skyKey);
      }
      // Note that the 'catastrophe' parameter doesn't really matter here (it's only used for
      // sanity checking).
      return constructResult(null, skyKeySet, null, /*catastrophe=*/false);
    }

    if (!keepGoing) {
      Set<SkyKey> cachedErrorKeys = new HashSet<>();
      for (SkyKey skyKey : skyKeySet) {
        NodeEntry entry = graph.get(skyKey);
        if (entry == null) {
          continue;
        }
        if (entry.isDone() && entry.getErrorInfo() != null) {
          informProgressReceiverThatValueIsDone(skyKey);
          cachedErrorKeys.add(skyKey);
        }
      }

      // Errors, even cached ones, should halt evaluations not in keepGoing mode.
      if (!cachedErrorKeys.isEmpty()) {
        // Note that the 'catastrophe' parameter doesn't really matter here (it's only used for
        // sanity checking).
        return constructResult(null, cachedErrorKeys, null, /*catastrophe=*/false);
      }
    }

    // We delay this check until we know that some kind of evaluation is necessary, since !keepGoing
    // and !keepsEdges are incompatible only in the case of a failed evaluation -- there is no
    // need to be overly harsh to callers who are just trying to retrieve a cached result.
    Preconditions.checkState(keepGoing || !(graph instanceof InMemoryGraph)
        || ((InMemoryGraph) graph).keepsEdges(),
        "nokeep_going evaluations are not allowed if graph edges are not kept: %s", skyKeys);

    Profiler.instance().startTask(ProfilerTask.SKYFRAME_EVAL, skyKeySet);
    try {
      ValueVisitor valueVisitor =
          forkJoinPool == null ? new ValueVisitor(threadCount) : new ValueVisitor(forkJoinPool);
      return eval(skyKeySet, valueVisitor);
    } finally {
      Profiler.instance().completeTask(ProfilerTask.SKYFRAME_EVAL);
    }
  }

  @ThreadCompatible
  private <T extends SkyValue> EvaluationResult<T> eval(ImmutableSet<SkyKey> skyKeys,
      ValueVisitor visitor) throws InterruptedException {
    // We unconditionally add the ErrorTransienceValue here, to ensure that it will be created, and
    // in the graph, by the time that it is needed. Creating it on demand in a parallel context sets
    // up a race condition, because there is no way to atomically create a node and set its value.
    NodeEntry errorTransienceEntry = Iterables.getOnlyElement(
        graph.createIfAbsentBatch(ImmutableList.of(ErrorTransienceValue.KEY)).values());
    if (!errorTransienceEntry.isDone()) {
      injectValues(
          ImmutableMap.of(ErrorTransienceValue.KEY, (SkyValue) ErrorTransienceValue.INSTANCE),
          graphVersion,
          graph,
          dirtyKeyTracker);
    }
    for (Map.Entry<SkyKey, NodeEntry> e : graph.createIfAbsentBatch(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.
      switch (entry.addReverseDepAndCheckIfDone(null)) {
        case NEEDS_SCHEDULING:
          visitor.enqueueEvaluation(skyKey);
          break;
        case DONE:
          informProgressReceiverThatValueIsDone(skyKey);
          break;
        case ALREADY_EVALUATING:
          break;
        default:
          throw new IllegalStateException(entry + " for " + skyKey + " in unknown state");
      }
    }
    try {
      return waitForCompletionAndConstructResult(visitor, skyKeys);
    } finally {
      inflightKeysReceiver.accept(visitor.inflightNodes);
    }
  }

  private <T extends SkyValue> EvaluationResult<T> waitForCompletionAndConstructResult(
      ValueVisitor visitor, Iterable<SkyKey> skyKeys) throws InterruptedException {
    Map<SkyKey, ValueWithMetadata> bubbleErrorInfo = null;
    boolean catastrophe = false;
    try {
      visitor.waitForCompletion();
    } catch (final SchedulerException e) {
      if (!visitor.getCrashes().isEmpty()) {
        reporter.handle(Event.error("Crashes detected: " + visitor.getCrashes()));
        throw Iterables.getFirst(visitor.getCrashes(), null);
      }
      Throwables.propagateIfPossible(e.getCause(), InterruptedException.class);
      if (Thread.interrupted()) {
        // As per the contract of AbstractQueueVisitor#work, if an unchecked exception is thrown and
        // the build is interrupted, the thrown exception is what will be rethrown. Since the user
        // presumably wanted to interrupt the build, we ignore the thrown SchedulerException (which
        // doesn't indicate a programming bug) and throw an InterruptedException.
        throw new InterruptedException();
      }

      SkyKey errorKey = Preconditions.checkNotNull(e.getFailedValue(), e);
      // ErrorInfo could only be null if SchedulerException wrapped an InterruptedException, but
      // that should have been propagated.
      ErrorInfo errorInfo = Preconditions.checkNotNull(e.getErrorInfo(), errorKey);
      if (!keepGoing) {
        bubbleErrorInfo = bubbleErrorUp(errorInfo, errorKey, skyKeys, visitor);
      } else {
        Preconditions.checkState(
            errorInfo.isCatastrophic(),
            "Scheduler exception only thrown for catastrophe in keep_going evaluation: %s",
            e);
        catastrophe = true;
        // Bubbling the error up requires that graph edges are present for done nodes. This is not
        // always the case in a keepGoing evaluation, since it is assumed that done nodes do not
        // need to be traversed. In this case, we hope the caller is tolerant of a possibly empty
        // result, and return prematurely.
        bubbleErrorInfo =
            ImmutableMap.of(
                errorKey,
                ValueWithMetadata.wrapWithMetadata(
                    graph.get(errorKey).getValueMaybeWithMetadata()));
      }
    }
    Preconditions.checkState(visitor.getCrashes().isEmpty(), visitor.getCrashes());

    // Successful evaluation, either because keepGoing or because we actually did succeed.
    // TODO(bazel-team): Maybe report root causes during the build for lower latency.
    return constructResult(visitor, skyKeys, bubbleErrorInfo, catastrophe);
  }

  /**
   * 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:
   *                      foo   bar
   *                        \   /
   *           unrequested   baz
   *                     \    |
   *                      failed-node
   * 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.
   *
   * There's the potential for a weird "track jump" here in the case:
   *                        foo
   *                       / \
   *                   fail1 fail2
   * 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.
   *
   * <p>Returns a map of errors that have been constructed during the bubbling up, so that the
   * appropriate error can be returned to the caller, even though that error was not written to the
   * graph. If a cycle is detected during the bubbling, this method aborts and returns null so that
   * the normal cycle detection can handle the cycle.
   *
   * <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) {
    Set<SkyKey> rootValues = ImmutableSet.copyOf(skyKeys);
    ErrorInfo error = leafFailure;
    Map<SkyKey, ValueWithMetadata> bubbleErrorInfo = new HashMap<>();
    boolean externalInterrupt = false;
    while (true) {
      NodeEntry errorEntry = Preconditions.checkNotNull(graph.get(errorKey), errorKey);
      Iterable<SkyKey> reverseDeps = errorEntry.isDone()
          ? errorEntry.getReverseDeps()
          : errorEntry.getInProgressReverseDeps();
      // We should break from loop only when node doesn't have any parents.
      if (Iterables.isEmpty(reverseDeps)) {
        Preconditions.checkState(rootValues.contains(errorKey),
            "Current key %s has to be a top-level key: %s", errorKey, rootValues);
        break;
      }
      SkyKey parent = null;
      NodeEntry parentEntry = null;
      for (SkyKey bubbleParent : reverseDeps) {
        if (bubbleErrorInfo.containsKey(bubbleParent)) {
          // We are in a cycle. Don't try to bubble anything up -- cycle detection will kick in.
          return null;
        }
        NodeEntry bubbleParentEntry = Preconditions.checkNotNull(graph.get(bubbleParent),
            "parent %s of %s not in graph", bubbleParent, errorKey);
        // Might be the parent that requested the error.
        if (bubbleParentEntry.isDone()) {
          // This parent is cached from a previous evaluate call. We shouldn't bubble up to it
          // since any error message produced won't be meaningful to this evaluate call.
          // The child error must also be cached from a previous build.
          Preconditions.checkState(errorEntry.isDone(), "%s %s", errorEntry, bubbleParentEntry);
          Version parentVersion = bubbleParentEntry.getVersion();
          Version childVersion = errorEntry.getVersion();
          Preconditions.checkState(childVersion.atMost(graphVersion)
              && !childVersion.equals(graphVersion),
              "child entry is not older than the current graph version, but had a done parent. "
              + "child: %s childEntry: %s, childVersion: %s"
              + "bubbleParent: %s bubbleParentEntry: %s, parentVersion: %s, graphVersion: %s",
              errorKey, errorEntry, childVersion,
              bubbleParent, bubbleParentEntry, parentVersion, graphVersion);
          Preconditions.checkState(parentVersion.atMost(graphVersion)
              && !parentVersion.equals(graphVersion),
              "parent entry is not older than the current graph version. "
              + "child: %s childEntry: %s, childVersion: %s"
              + "bubbleParent: %s bubbleParentEntry: %s, parentVersion: %s, graphVersion: %s",
              errorKey, errorEntry, childVersion,
              bubbleParent, bubbleParentEntry, parentVersion, graphVersion);
          continue;
        }
        if (visitor.isInflight(bubbleParent)
            && bubbleParentEntry.getTemporaryDirectDeps().contains(errorKey)) {
          // Only bubble up to parent if it's part of this build. If this node was dirtied and
          // re-evaluated, but in a build without this parent, we may try to bubble up to that
          // parent. Don't -- it's not part of the build.
          // Similarly, the parent may not yet have requested this dep in its dirtiness-checking
          // process. Don't bubble up to it in that case either.
          parent = bubbleParent;
          parentEntry = bubbleParentEntry;
          break;
        }
      }
      if (parent == null) {
        Preconditions.checkState(
            rootValues.contains(errorKey),
            "Current key %s has to be a top-level key: %s, %s",
            errorKey,
            rootValues,
            errorEntry);
        break;
      }
      Preconditions.checkNotNull(parentEntry, "%s %s", errorKey, parent);
      errorKey = parent;
      SkyFunction factory = skyFunctions.get(parent.functionName());
      if (parentEntry.isDirty()) {
        switch (parentEntry.getDirtyState()) {
          case CHECK_DEPENDENCIES:
            // If this value's child was bubbled up to, it did not signal this value, and so we must
            // manually make it ready to build.
            parentEntry.signalDep();
            // Fall through to NEEDS_REBUILDING, since state is now NEEDS_REBUILDING.
          case NEEDS_REBUILDING:
            maybeMarkRebuildingAndRemoveRemainingDirtyDirectDeps(parent, parentEntry);
            // Fall through to REBUILDING.
          case REBUILDING:
            break;
          default:
            throw new AssertionError(parent + " not in valid dirty state: " + parentEntry);
        }
      }
      SkyFunctionEnvironment env =
          new SkyFunctionEnvironment(parent, ImmutableSet.<SkyKey>of(), bubbleErrorInfo, visitor);
      externalInterrupt = externalInterrupt || Thread.currentThread().isInterrupted();
      try {
        // This build is only to check if the parent node can give us a better error. We don't
        // care about a return value.
        factory.compute(parent, env);
      } catch (InterruptedException interruptedException) {
        // Do nothing.
        // This throw happens if the builder requested the failed node, and then checked the
        // interrupted state later -- getValueOrThrow sets the interrupted bit after the failed
        // value is requested, to prevent the builder from doing too much work.
      } catch (SkyFunctionException builderException) {
        // Clear interrupted status. We're not listening to interrupts here.
        Thread.interrupted();
        ReifiedSkyFunctionException reifiedBuilderException =
            new ReifiedSkyFunctionException(builderException, parent);
        if (reifiedBuilderException.getRootCauseSkyKey().equals(parent)) {
          error = ErrorInfo.fromException(reifiedBuilderException,
              /*isTransitivelyTransient=*/ false);
          bubbleErrorInfo.put(errorKey,
              ValueWithMetadata.error(ErrorInfo.fromChildErrors(errorKey, ImmutableSet.of(error)),
                  env.buildEvents(/*missingChildren=*/true)));
          continue;
        }
      } finally {
        // Clear interrupted status. We're not listening to interrupts here.
        Thread.interrupted();
      }
      // Builder didn't throw an exception, so just propagate this one up.
      bubbleErrorInfo.put(errorKey,
          ValueWithMetadata.error(ErrorInfo.fromChildErrors(errorKey, ImmutableSet.of(error)),
              env.buildEvents(/*missingChildren=*/true)));
    }

    // Reset the interrupt bit if there was an interrupt from outside this evaluator interrupt.
    // Note that there are internal interrupts set in the node builder environment if an error
    // bubbling node calls getValueOrThrow() on a node in error.
    if (externalInterrupt) {
      Thread.currentThread().interrupt();
    }
    return bubbleErrorInfo;
  }

  /**
   * 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).
   */
  private <T extends SkyValue> EvaluationResult<T> constructResult(
      @Nullable ValueVisitor visitor,
      Iterable<SkyKey> skyKeys,
      @Nullable Map<SkyKey, ValueWithMetadata> bubbleErrorInfo,
      boolean catastrophe) {
    Preconditions.checkState(
        catastrophe == (keepGoing && bubbleErrorInfo != null),
        "Catastrophe not consistent with keepGoing mode and bubbleErrorInfo: %s %s %s %s",
        skyKeys,
        catastrophe,
        keepGoing,
        bubbleErrorInfo);
    EvaluationResult.Builder<T> result = EvaluationResult.builder();
    List<SkyKey> cycleRoots = new ArrayList<>();
    for (SkyKey skyKey : skyKeys) {
      ValueWithMetadata valueWithMetadata = getValueMaybeFromError(skyKey, bubbleErrorInfo);
      // Cycle checking: if there is a cycle, evaluation cannot progress, therefore,
      // the final values will not be in DONE state when the work runs out.
      if (valueWithMetadata == null) {
        // Don't look for cycles if the build failed for a known reason.
        if (bubbleErrorInfo == null) {
          cycleRoots.add(skyKey);
        }
        continue;
      }
      SkyValue value = valueWithMetadata.getValue();
      // TODO(bazel-team): Verify that message replay is fast and works in failure
      // modes [skyframe-core]
      // Note that replaying events here is only necessary on null builds, because otherwise we
      // would have already printed the transitive messages after building these values.
      replayingNestedSetEventVisitor.visit(valueWithMetadata.getTransitiveEvents());
      ErrorInfo errorInfo = valueWithMetadata.getErrorInfo();
      Preconditions.checkState(value != null || errorInfo != null, skyKey);
      if (!keepGoing && errorInfo != null) {
        // value will be null here unless the value was already built on a prior keepGoing build.
        result.addError(skyKey, errorInfo);
        continue;
      }
      if (value == null) {
        // Note that we must be in the keepGoing case. Only make this value an error if it doesn't
        // have a value. The error shouldn't matter to the caller since the value succeeded after a
        // fashion.
        result.addError(skyKey, errorInfo);
      } else {
        result.addResult(skyKey, value);
      }
    }
    if (!cycleRoots.isEmpty()) {
      Preconditions.checkState(visitor != null, skyKeys);
      checkForCycles(cycleRoots, result, visitor, keepGoing);
    }
    if (catastrophe) {
      // We may not have a top-level node completed. Inform the caller of the catastrophic exception
      // that shut down the evaluation so that it has some context.
      ErrorInfo errorInfo =
          Preconditions.checkNotNull(
              Iterables.getOnlyElement(bubbleErrorInfo.values()).getErrorInfo(),
              "bubbleErrorInfo should have contained element with errorInfo: %s",
              bubbleErrorInfo);
      Preconditions.checkState(
          errorInfo.isCatastrophic(),
          "bubbleErrorInfo should have contained element with catastrophe: %s",
          bubbleErrorInfo);
      result.setCatastrophe(errorInfo.getException());
    }
    EvaluationResult<T> builtResult = result.build();
    Preconditions.checkState(
        bubbleErrorInfo == null || builtResult.hasError(),
        "If an error bubbled up, some top-level node must be in error: %s %s %s",
        bubbleErrorInfo,
        skyKeys,
        builtResult);
    return builtResult;
  }

  private <T extends SkyValue> void checkForCycles(
      Iterable<SkyKey> badRoots, EvaluationResult.Builder<T> result, final ValueVisitor visitor,
      boolean keepGoing) {
    for (SkyKey root : badRoots) {
      ErrorInfo errorInfo = checkForCycles(root, visitor, keepGoing);
      if (errorInfo == null) {
        // This node just wasn't finished when evaluation aborted -- there were no cycles below it.
        Preconditions.checkState(!keepGoing, "", root, badRoots);
        continue;
      }
      Preconditions.checkState(!Iterables.isEmpty(errorInfo.getCycleInfo()),
          "%s was not evaluated, but was not part of a cycle", root);
      result.addError(root, errorInfo);
      if (!keepGoing) {
        return;
      }
    }
  }

  /**
   * Marker value that we push onto a stack before we push a node's children on. When the marker
   * value is popped, we know that all the children are finished. We would use null instead, but
   * ArrayDeque does not permit null elements.
   */
  private static final SkyKey CHILDREN_FINISHED =
      SkyKey.create(SkyFunctionName.create("MARKER"), "MARKER");

  /** The max number of cycles we will report to the user for a given root, to avoid OOMing. */
  private static final int MAX_CYCLES = 20;

  /**
   * 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.
   */
  private ErrorInfo checkForCycles(SkyKey root, ValueVisitor visitor, boolean keepGoing) {
    // The number of cycles found. Do not keep on searching for more cycles after this many were
    // found.
    int cyclesFound = 0;
    // The path through the graph currently being visited.
    List<SkyKey> graphPath = new ArrayList<>();
    // Set of nodes on the path, to avoid expensive searches through the path for cycles.
    Set<SkyKey> pathSet = new HashSet<>();

    // Maintain a stack explicitly instead of recursion to avoid stack overflows
    // on extreme graphs (with long dependency chains).
    Deque<SkyKey> toVisit = new ArrayDeque<>();

    toVisit.push(root);

    // The procedure for this check is as follows: we visit a node, push it onto the graph stack,
    // push a marker value onto the toVisit stack, and then push all of its children onto the
    // toVisit stack. Thus, when the marker node comes to the top of the toVisit stack, we have
    // visited the downward transitive closure of the value. At that point, all of its children must
    // be finished, and so we can build the definitive error info for the node, popping it off the
    // graph stack.
    while (!toVisit.isEmpty()) {
      SkyKey key = toVisit.pop();

      NodeEntry entry;
      if (key == CHILDREN_FINISHED) {
        // A marker node means we are done with all children of a node. Since all nodes have
        // errors, we must have found errors in the children when that happens.
        key = graphPath.remove(graphPath.size() - 1);
        entry = Preconditions.checkNotNull(graph.get(key), key);
        pathSet.remove(key);
        // Skip this node if it was first/last node of a cycle, and so has already been processed.
        if (entry.isDone()) {
          continue;
        }
        if (!keepGoing) {
          // in the --nokeep_going mode, we would have already returned if we'd found a cycle below
          // this node. The fact that we haven't means that there were no cycles below this node
          // -- it just hadn't finished evaluating. So skip it.
          continue;
        }
        if (cyclesFound < MAX_CYCLES) {
          // Value must be ready, because all of its children have finished, so we can build its
          // error.
          Preconditions.checkState(entry.isReady(), "%s not ready. ValueEntry: %s", key, entry);
        } else if (!entry.isReady()) {
          removeIncompleteChildrenForCycle(key, entry, entry.getTemporaryDirectDeps());
        }
        maybeMarkRebuildingAndRemoveRemainingDirtyDirectDeps(key, entry);
        Set<SkyKey> directDeps = entry.getTemporaryDirectDeps();
        // Find out which children have errors. Similar logic to that in Evaluate#run().
        List<ErrorInfo> errorDeps = getChildrenErrorsForCycle(directDeps);
        Preconditions.checkState(!errorDeps.isEmpty(),
            "Value %s was not successfully evaluated, but had no child errors. ValueEntry: %s", key,
            entry);
        SkyFunctionEnvironment env = new SkyFunctionEnvironment(key, directDeps, visitor);
        env.setError(ErrorInfo.fromChildErrors(key, errorDeps), /*isDirectlyTransient=*/false);
        env.commit(/*enqueueParents=*/false);
      } else {
        entry = graph.get(key);
      }

      Preconditions.checkNotNull(entry, key);
      // Nothing to be done for this node if it already has an entry.
      if (entry.isDone()) {
        continue;
      }
      if (cyclesFound == MAX_CYCLES) {
        // Do not keep on searching for cycles indefinitely, to avoid excessive runtime/OOMs.
        continue;
      }

      if (pathSet.contains(key)) {
        int cycleStart = graphPath.indexOf(key);
        // Found a cycle!
        cyclesFound++;
        Iterable<SkyKey> cycle = graphPath.subList(cycleStart, graphPath.size());
        // Put this node into a consistent state for building if it is dirty.
        if (entry.isDirty() && entry.getDirtyState() == NodeEntry.DirtyState.CHECK_DEPENDENCIES) {
          // In the check deps state, entry has exactly one child not done yet. Note that this node
          // must be part of the path to the cycle we have found (since done nodes cannot be in
          // cycles, and this is the only missing one). Thus, it will not be removed below in
          // removeDescendantsOfCycleValue, so it is safe here to signal that it is done.
          entry.signalDep();
          maybeMarkRebuildingAndRemoveRemainingDirtyDirectDeps(key, entry);
        }
        if (keepGoing) {
          // Any children of this node that we haven't already visited are not worth visiting,
          // since this node is about to be done. Thus, the only child worth visiting is the one in
          // this cycle, the cycleChild (which may == key if this cycle is a self-edge).
          SkyKey cycleChild = selectCycleChild(key, graphPath, cycleStart);
          removeDescendantsOfCycleValue(key, entry, cycleChild, toVisit,
                  graphPath.size() - cycleStart);
          ValueWithMetadata dummyValue = ValueWithMetadata.wrapWithMetadata(new SkyValue() {});


          SkyFunctionEnvironment env =
              new SkyFunctionEnvironment(key, entry.getTemporaryDirectDeps(),
                  ImmutableMap.of(cycleChild, dummyValue), visitor);

          // Construct error info for this node. Get errors from children, which are all done
          // except possibly for the cycleChild.
          List<ErrorInfo> allErrors =
              getChildrenErrors(entry.getTemporaryDirectDeps(), /*unfinishedChild=*/cycleChild);
          CycleInfo cycleInfo = new CycleInfo(cycle);
          // Add in this cycle.
          allErrors.add(ErrorInfo.fromCycle(cycleInfo));
          env.setError(ErrorInfo.fromChildErrors(key, allErrors), /*isTransient=*/false);
          env.commit(/*enqueueParents=*/false);
          continue;
        } else {
          // We need to return right away in the noKeepGoing case, so construct the cycle (with the
          // path) and return.
          Preconditions.checkState(graphPath.get(0).equals(root),
              "%s not reached from %s. ValueEntry: %s", key, root, entry);
          return ErrorInfo.fromCycle(new CycleInfo(graphPath.subList(0, cycleStart), cycle));
        }
      }

      // This node is not yet known to be in a cycle. So process its children.
      Iterable<SkyKey> children = entry.getTemporaryDirectDeps();
      if (Iterables.isEmpty(children)) {
        continue;
      }
      // Prefetch all children, in case our graph performs better with a primed cache.
      graph.getBatch(children);

      // This marker flag will tell us when all this node's children have been processed.
      toVisit.push(CHILDREN_FINISHED);
      // This node is now part of the path through the graph.
      graphPath.add(key);
      pathSet.add(key);
      for (SkyKey nextValue : children) {
        toVisit.push(nextValue);
      }
    }
    return keepGoing ? getAndCheckDone(root).getErrorInfo() : null;
  }

  /**
   * Returns the child of this node that is in the cycle that was just found. If the cycle is a
   * self-edge, returns the node itself.
   */
  private static SkyKey selectCycleChild(SkyKey key, List<SkyKey> graphPath, int cycleStart) {
    return cycleStart + 1 == graphPath.size() ? key : graphPath.get(cycleStart + 1);
  }

  /**
   * Get all the errors of child nodes. There must be at least one cycle amongst them.
   *
   * @param children child nodes to query for errors.
   * @return List of ErrorInfos from all children that had errors.
   */
  private List<ErrorInfo> getChildrenErrorsForCycle(Iterable<SkyKey> children) {
    List<ErrorInfo> allErrors = new ArrayList<>();
    boolean foundCycle = false;
    for (SkyKey child : children) {
      ErrorInfo errorInfo = getAndCheckDone(child).getErrorInfo();
      if (errorInfo != null) {
        foundCycle |= !Iterables.isEmpty(errorInfo.getCycleInfo());
        allErrors.add(errorInfo);
      }
    }
    Preconditions.checkState(foundCycle, "", children, allErrors);
    return allErrors;
  }

  /**
   * Get all the errors of child nodes.
   *
   * @param children child nodes to query for errors.
   * @param unfinishedChild child which is allowed to not be done.
   * @return List of ErrorInfos from all children that had errors.
   */
  private List<ErrorInfo> getChildrenErrors(Iterable<SkyKey> children, SkyKey unfinishedChild) {
    List<ErrorInfo> allErrors = new ArrayList<>();
    for (SkyKey child : children) {
      ErrorInfo errorInfo = getErrorMaybe(child, /*allowUnfinished=*/child.equals(unfinishedChild));
      if (errorInfo != null) {
        allErrors.add(errorInfo);
      }
    }
    return allErrors;
  }

  @Nullable
  private ErrorInfo getErrorMaybe(SkyKey key, boolean allowUnfinished) {
    if (!allowUnfinished) {
      return getAndCheckDone(key).getErrorInfo();
    }
    NodeEntry entry = Preconditions.checkNotNull(graph.get(key), key);
    return entry.isDone() ? entry.getErrorInfo() : null;
  }

  /**
   * Removes direct children of key from toVisit and from the entry itself, and makes the entry
   * ready if necessary. We must do this because it would not make sense to try to build the
   * children after building the entry. It would violate the invariant that a parent can only be
   * built after its children are built; See bug "Precondition error while evaluating a Skyframe
   * graph with a cycle".
   *
   * @param key SkyKey of node in a cycle.
   * @param entry NodeEntry of node in a cycle.
   * @param cycleChild direct child of key in the cycle, or key itself if the cycle is a self-edge.
   * @param toVisit list of remaining nodes to visit by the cycle-checker.
   * @param cycleLength the length of the cycle found.
   */
  private void removeDescendantsOfCycleValue(SkyKey key, NodeEntry entry,
      @Nullable SkyKey cycleChild, Iterable<SkyKey> toVisit, int cycleLength) {
    Set<SkyKey> unvisitedDeps = new HashSet<>(entry.getTemporaryDirectDeps());
    unvisitedDeps.remove(cycleChild);
    // Remove any children from this node that are not part of the cycle we just found. They are
    // irrelevant to the node as it stands, and if they are deleted from the graph because they are
    // not built by the end of cycle-checking, we would have dangling references.
    removeIncompleteChildrenForCycle(key, entry, unvisitedDeps);
    if (!entry.isReady()) {
      // The entry has at most one undone dep now, its cycleChild. Signal to make entry ready. Note
      // that the entry can conceivably be ready if its cycleChild already found a different cycle
      // and was built.
      entry.signalDep();
    }
    maybeMarkRebuildingAndRemoveRemainingDirtyDirectDeps(key, entry);
    Preconditions.checkState(entry.isReady(), "%s %s %s", key, cycleChild, entry);
    Iterator<SkyKey> it = toVisit.iterator();
    while (it.hasNext()) {
      SkyKey descendant = it.next();
      if (descendant == CHILDREN_FINISHED) {
        // Marker value, delineating the end of a group of children that were enqueued.
        cycleLength--;
        if (cycleLength == 0) {
          // We have seen #cycleLength-1 marker values, and have arrived at the one for this value,
          // so we are done.
          return;
        }
        continue; // Don't remove marker values.
      }
      if (cycleLength == 1) {
        // Remove the direct children remaining to visit of the cycle node.
        Preconditions.checkState(unvisitedDeps.contains(descendant),
            "%s %s %s %s %s", key, descendant, cycleChild, unvisitedDeps, entry);
        it.remove();
      }
    }
    throw new IllegalStateException("There were not " + cycleLength + " groups of children in "
        + toVisit + " when trying to remove children of " + key + " other than " + cycleChild);
  }

  private void removeIncompleteChildrenForCycle(SkyKey key, NodeEntry entry,
      Iterable<SkyKey> children) {
    Set<SkyKey> unfinishedDeps = new HashSet<>();
    for (SkyKey child : children) {
      if (removeIncompleteChild(key, child)) {
        unfinishedDeps.add(child);
      }
    }
    entry.removeUnfinishedDeps(unfinishedDeps);
  }

  private NodeEntry getAndCheckDone(SkyKey key) {
    NodeEntry entry = graph.get(key);
    Preconditions.checkNotNull(entry, key);
    Preconditions.checkState(entry.isDone(), "%s %s", key, entry);
    return entry;
  }

  private ValueWithMetadata maybeWrapValueFromError(SkyKey key, @Nullable NodeEntry entry,
      @Nullable Map<SkyKey, ValueWithMetadata> bubbleErrorInfo) {
    SkyValue value = bubbleErrorInfo == null ? null : bubbleErrorInfo.get(key);
    if (value != null) {
      Preconditions.checkNotNull(entry,
          "Value cannot have error before evaluation started", key, value);
      return ValueWithMetadata.wrapWithMetadata(value);
    }
    return isDoneForBuild(entry)
        ? ValueWithMetadata.wrapWithMetadata(entry.getValueMaybeWithMetadata())
        : null;
  }

  @Nullable
  private ValueWithMetadata getValueMaybeFromError(SkyKey key,
      @Nullable Map<SkyKey, ValueWithMetadata> bubbleErrorInfo) {
    return maybeWrapValueFromError(key, graph.get(key), bubbleErrorInfo);
  }

  /**
   * Return true if the entry does not need to be re-evaluated this build. The entry will need to
   * be re-evaluated if it is not done, but also if it was not completely evaluated last build and
   * this build is keepGoing.
   */
  private boolean isDoneForBuild(@Nullable NodeEntry entry) {
    return entry != null && entry.isDone();
  }

  static void injectValues(
      Map<SkyKey, SkyValue> injectionMap,
      Version version,
      EvaluableGraph graph,
      DirtyKeyTracker dirtyKeyTracker) {
    Map<SkyKey, NodeEntry> prevNodeEntries = graph.createIfAbsentBatch(injectionMap.keySet());
    for (Map.Entry<SkyKey, SkyValue> injectionEntry : injectionMap.entrySet()) {
      SkyKey key = injectionEntry.getKey();
      SkyValue value = injectionEntry.getValue();
      NodeEntry prevEntry = prevNodeEntries.get(key);
      DependencyState newState = prevEntry.addReverseDepAndCheckIfDone(null);
      Preconditions.checkState(
          newState != DependencyState.ALREADY_EVALUATING, "%s %s", key, prevEntry);
      if (prevEntry.isDirty()) {
        Preconditions.checkState(
            newState == DependencyState.NEEDS_SCHEDULING, "%s %s", key, prevEntry);
        // There was an existing entry for this key in the graph.
        // Get the node in the state where it is able to accept a value.

        // Check that the previous node has no dependencies. Overwriting a value with deps with an
        // injected value (which is by definition deps-free) needs a little additional bookkeeping
        // (removing reverse deps from the dependencies), but more importantly it's something that
        // we want to avoid, because it indicates confusion of input values and derived values.
        Preconditions.checkState(
            prevEntry.noDepsLastBuild(), "existing entry for %s has deps: %s", key, prevEntry);
        // Put the node into a "rebuilding" state and verify that there were no dirty deps
        // remaining.
        Preconditions.checkState(
            prevEntry.markRebuildingAndGetAllRemainingDirtyDirectDeps().isEmpty(),
            "%s %s",
            key,
            prevEntry);
      }
      prevEntry.setValue(value, version);
      // Now that this key's injected value is set, it is no longer dirty.
      dirtyKeyTracker.notDirty(key);
    }
  }
}
