// Copyright 2021 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.worker;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.flogger.GoogleLogger;
import com.google.devtools.build.lib.sandbox.SandboxHelpers;
import com.google.devtools.build.lib.sandbox.SandboxHelpers.SandboxInputs;
import com.google.devtools.build.lib.sandbox.SandboxHelpers.SandboxOutputs;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.worker.WorkerProtocol.WorkRequest;
import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * A multiplex worker proxy with sandboxing. The multiplexer process runs in {@code workDir}, while
 * each proxy has a fixed subdir where it sets up its files. The subdir is then passed to the worker
 * in {@link WorkRequest#sandbox_dir}. The worker implementation is responsible for reading from and
 * writing to that subdir only.
 */
public class SandboxedWorkerProxy extends WorkerProxy {
  private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
  /** The sandbox directory for the current request, inside {@code workDir}. */
  private final Path sandboxDir;

  private final PathFragment sandboxName;

  SandboxedWorkerProxy(
      WorkerKey workerKey,
      int workerId,
      Path logFile,
      WorkerMultiplexer workerMultiplexer,
      Path workDir) {
    super(workerKey, workerId, logFile, workerMultiplexer, workDir);
    sandboxName =
        PathFragment.create(
            Joiner.on(PathFragment.SEPARATOR_CHAR)
                .join(
                    "__sandbox",
                    Integer.toString(workerId),
                    workerKey.getExecRoot().getBaseName()));
    sandboxDir = this.workDir.getRelative(sandboxName);
  }

  @Override
  public boolean isSandboxed() {
    return true;
  }

  @Override
  public void prepareExecution(
      SandboxInputs inputFiles, SandboxOutputs outputs, Set<PathFragment> workerFiles)
      throws IOException, InterruptedException {
    workerMultiplexer.createSandboxedProcess(workDir, workerFiles, inputFiles);

    sandboxDir.createDirectoryAndParents();
    LinkedHashSet<PathFragment> dirsToCreate = new LinkedHashSet<>();
    Set<PathFragment> inputsToCreate = new HashSet<>();

    SandboxHelpers.populateInputsAndDirsToCreate(
        ImmutableSet.of(),
        inputsToCreate,
        dirsToCreate,
        Iterables.concat(inputFiles.getFiles().keySet(), inputFiles.getSymlinks().keySet()),
        outputs.files(),
        outputs.dirs());
    SandboxHelpers.cleanExisting(
        sandboxDir.getParentDirectory(), inputFiles, inputsToCreate, dirsToCreate, sandboxDir);
    // Finally, create anything that is still missing. This is non-strict only for historical
    // reasons, we haven't seen what would break if we make it strict.
    SandboxHelpers.createDirectories(dirsToCreate, sandboxDir, /* strict=*/ false);
    WorkerExecRoot.createInputs(inputsToCreate, inputFiles, sandboxDir);
  }

  /** Send the WorkRequest to multiplexer. */
  @Override
  protected void putRequest(WorkRequest request) throws IOException {
    // Modifying the request on the way out is not great. The alternatives are having the
    // spawn runner ask the worker for the dir or making the spawn runner understand the sandbox,
    // dir structure, neither of which are nice either.
    workerMultiplexer.putRequest(
        request.toBuilder().setSandboxDir(sandboxName.getPathString()).build());
  }

  @Override
  public void finishExecution(Path execRoot, SandboxOutputs outputs) throws IOException {
    SandboxHelpers.moveOutputs(outputs, sandboxDir, execRoot);
  }

  @Override
  synchronized void destroy() {
    super.destroy();
    try {
      workDir.deleteTree();
    } catch (IOException e) {
      logger.atWarning().withCause(e).log("Caught IOException while deleting workdir.");
    }
  }
}
