// 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.lib.actions;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.util.io.FileOutErr;
import javax.annotation.Nullable;

/**
 * A context that allows execution of {@link Spawn} instances similar to {@link SpawnStrategy}, but
 * with the additional restriction that during execution the {@link Spawn} must not be allowed to
 * modify the current execution root of the build. Instead, the {@link Spawn} should be executed in
 * a sandbox or on a remote system and its output files only be moved to the execution root.
 */
public interface SandboxedSpawnStrategy extends SpawnStrategy {

  /** Lambda interface to stop other instances of the same spawn before writing outputs. */
  @FunctionalInterface
  interface StopConcurrentSpawns {
    /**
     * Stops other instances of the same spawn before writing outputs. If {@code exitCode} != 0,
     * this may stop this instance instead by throwing InterruptedException, to allow the other
     * instance to succeed instead.
     *
     * <p>This should be called once by each of the concurrent spawns to ensure that the others are
     * stopped, thus preventing conflicts when writing to the output tree.
     *
     * @param exitCode 0 if the spawn executed successfully.
     * @param errorMessage An error message from the spawn execution, if {@code exitCode} != 0.
     * @param outErr Object representing the files containing stdout and stderr.
     */
    void stop(int exitCode, String errorMessage, FileOutErr outErr) throws InterruptedException;
  }

  /**
   * Executes the given spawn.
   *
   * <p>When the {@link SpawnStrategy} is about to write output files into the execroot, it first
   * asks any other concurrent instances of this same spawn (handled by other spawn runners when
   * dynamic scheduling is enabled) to stop by invoking the {@code stopConcurrentSpawns} lambda.
   *
   * @return a List of {@link SpawnResult}s containing metadata about the Spawn's execution. This
   *     will typically contain one element, but could contain no elements if spawn execution did
   *     not complete, or contain multiple elements if multiple sub-spawns were executed
   */
  ImmutableList<SpawnResult> exec(
      Spawn spawn,
      ActionExecutionContext actionExecutionContext,
      // TODO(jmmv): Inject an empty lambda instead of allowing this to be null. Need to find a way
      // to deal with non-null implying speculation in e.g. AbstractSpawnStrategy (if it matters).
      @Nullable StopConcurrentSpawns stopConcurrentSpawns)
      throws ExecException, InterruptedException;
}
