// Copyright 2016 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.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.util.Set;
import java.util.function.Supplier;
import javax.annotation.Nullable;

/**
 * A delegating {@link EvaluationProgressReceiver} that tracks inflight nodes, nodes which
 * are being evaluated or scheduled for evaluation, and dirty nodes.
 */
public class DirtyTrackingProgressReceiver implements EvaluationProgressReceiver {

  @Nullable private final EvaluationProgressReceiver progressReceiver;
  private final Set<SkyKey> dirtyKeys = Sets.newConcurrentHashSet();
  private Set<SkyKey> inflightKeys = Sets.newConcurrentHashSet();

  public DirtyTrackingProgressReceiver(@Nullable EvaluationProgressReceiver progressReceiver) {
    this.progressReceiver = progressReceiver;
  }

  /** Called when a node is injected into the graph, and not evaluated. */
  protected void injected(SkyKey skyKey) {
    // This node was never evaluated, but is now clean and need not be re-evaluated
    inflightKeys.remove(skyKey);
    removeFromDirtySet(skyKey);
  }

  @Override
  public void invalidated(SkyKey skyKey, InvalidationState state) {
    if (progressReceiver != null) {
      progressReceiver.invalidated(skyKey, state);
    }

    switch (state) {
      case DELETED:
        // This key was removed from the graph, so no longer needs to be marked as dirty.
        removeFromDirtySet(skyKey);
        break;
      case DIRTY:
        addToDirtySet(skyKey);
        break;
      default:
        throw new IllegalStateException(state.toString());
    }
  }

  @Override
  public void enqueueing(SkyKey skyKey) {
    enqueueing(skyKey, false);
  }

  /**
   * Called when a node was requested to be enqueued but wasn't because either an interrupt or
   * an error (in nokeep_going mode) had occurred.
   */
  protected void enqueueAfterError(SkyKey skyKey) {
    enqueueing(skyKey, true);
  }

  private void enqueueing(SkyKey skyKey, boolean afterError) {
    // We unconditionally add the key to the set of in-flight nodes even if evaluation is never
    // scheduled, because 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 = inflightKeys.add(skyKey);
    if (newlyEnqueued) {
      // 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.
      removeFromDirtySet(skyKey);
      if (progressReceiver != null && !afterError) {
        // Only tell the external listener the node was enqueued if no there was neither an error
        // or interrupt.
        progressReceiver.enqueueing(skyKey);
      }
    }
  }

  @Override
  public void stateStarting(SkyKey skyKey, NodeState nodeState) {
    if (progressReceiver != null) {
      progressReceiver.stateStarting(skyKey, nodeState);
    }
  }

  @Override
  public void stateEnding(SkyKey skyKey, NodeState nodeState, long elapsedTimeNanos) {
    if (progressReceiver != null) {
      progressReceiver.stateEnding(skyKey, nodeState, elapsedTimeNanos);
    }
  }

  @Override
  public void evaluated(
      SkyKey skyKey,
      @Nullable SkyValue value,
      Supplier<EvaluationSuccessState> evaluationSuccessState,
      EvaluationState state) {
    if (progressReceiver != null) {
      progressReceiver.evaluated(skyKey, value, evaluationSuccessState, state);
    }

    // This key was either built or marked clean, so we can remove it from both the dirty and
    // inflight nodes.
    inflightKeys.remove(skyKey);
    removeFromDirtySet(skyKey);
  }

  /** Returns if the key is enqueued for evaluation. */
  protected boolean isInflight(SkyKey skyKey) {
    return inflightKeys.contains(skyKey);
  }

  /** Returns the set of all keys that are enqueued for evaluation, and resets the set to empty. */
  protected Set<SkyKey> getAndClearInflightKeys() {
    Set<SkyKey> keys = inflightKeys;
    inflightKeys = Sets.newConcurrentHashSet();
    return keys;
  }

  /**
   * Returns the set of all dirty keys that have not been enqueued.
   * This is useful for garbage collection, where we would not want to remove dirty nodes that are
   * needed for evaluation (in the downward transitive closure of the set of the evaluation's
   * top level nodes).
   */
  protected Set<SkyKey> getUnenqueuedDirtyKeys(){
    return ImmutableSet.copyOf(dirtyKeys);
  }

  protected void addToDirtySet(SkyKey skyKey) {
    dirtyKeys.add(skyKey);
  }

  protected void removeFromDirtySet(SkyKey skyKey) {
    dirtyKeys.remove(skyKey);
  }
}
