// 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.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.util.Set;
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 computing(SkyKey skyKey) {
    if (progressReceiver != null) {
      progressReceiver.computing(skyKey);
    }
  }

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

  @Override
  public void evaluated(SkyKey skyKey, Supplier<SkyValue> valueSupplier,
      EvaluationState state) {
    if (progressReceiver != null) {
      progressReceiver.evaluated(skyKey, valueSupplier, 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);
  }
}
