// Copyright 2019 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.sandbox;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.util.concurrent.SettableFuture;
import com.google.devtools.build.lib.shell.Subprocess;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;

/**
 * A sandboxfs implementation that uses an external sandboxfs binary to manage the mount point.
 *
 * <p>This implementation provides support for the reconfiguration protocol introduced in 0.2.0.
 */
final class RealSandboxfs02Process extends RealSandboxfsProcess {

  private static final Logger log = Logger.getLogger(RealSandboxfsProcess.class.getName());

  /**
   * Writer with which to send data to the sandboxfs instance. Null only after {@link #destroy()}
   * has been invoked.
   */
  @GuardedBy("this")
  private JsonWriter processStdIn;

  /**
   * Collection of active reconfiguration requests.
   *
   * <p>Each entry in this map is keyed by the identifier of the sandbox being affected by a
   * reconfiguration request and points to a future that is set when the request completes.
   *
   * <p>New entries can be added to this map at any time, but only before {@link #destroy} is
   * called. Once the sandboxfs instance has been destroyed, we do not expect any new requests to
   * come in. However, existing requests will be drained by the {@link ResponsesReader} thread.
   */
  private final ConcurrentMap<String, SettableFuture<Void>> inFlightRequests =
      new ConcurrentHashMap<>();

  /**
   * Thread that reads responses from sandboxfs and dispatches them to the futures maintained by
   * {@link #inFlightRequests}.
   */
  private final Thread responsesReader;

  /** Representation of a response returned by sandboxfs. */
  private static class Response {
    /** Identifier given in the request. Null if this carries a fatal error. */
    @Nullable final String id;

    /**
     * Error message returned by sandboxfs if not null. If {@link #id} is not null, then this error
     * corresponds to a specific request and is recoverable. Otherwise corresponds to a fatal
     * condition, in which case sandboxfs will have stopped listening for requests.
     */
    @Nullable final String error;

    /** Constructs a new response with the given values. */
    Response(@Nullable String id, @Nullable String error) {
      this.id = id;
      this.error = error;
    }
  }

  /**
   * A thread that reads responses from the sandboxfs output stream and dispatches them to the
   * futures awaiting for them.
   */
  private static class ResponsesReader extends Thread {

    private final JsonReader reader;
    private final ConcurrentMap<String, SettableFuture<Void>> inFlightRequests;

    ResponsesReader(
        JsonReader reader, ConcurrentMap<String, SettableFuture<Void>> inFlightRequests) {
      this.reader = reader;
      this.inFlightRequests = inFlightRequests;
    }

    /** Waits for responses and dispatches them. */
    private void processResponses() throws IOException {
      while (!Thread.interrupted() && reader.peek() != JsonToken.END_DOCUMENT) {
        Response response = readResponse(reader);
        if (response.id == null) {
          // Non-recoverable error: abort.
          throw new IOException(response.error != null ? response.error : "No error reported");
        }

        SettableFuture<Void> future = inFlightRequests.remove(response.id);
        if (future == null) {
          throw new IOException("sandboxfs returned response for unknown id " + response.id);
        }
        if (response.error == null) {
          future.set(null);
        } else {
          future.setException(new IOException(response.error));
        }
      }
    }

    @Override
    public void run() {
      try {
        processResponses();
      } catch (EOFException e) {
        // OK, nothing to do.
      } catch (IOException e) {
        log.log(Level.WARNING, "Failed to read responses from sandboxfs", e);
      }

      // sandboxfs has either replied with an unrecoverable error or has stopped providing
      // responses. Either way, we have to clean up any pending in-flight requests to unblock the
      // threads waiting for them.
      //
      // Given that we only get here once destroy() has been called, we do not expect any new
      // requests to show up in the inFlightRequests map. This is why we do not synchronize
      // accesses to the map during the iteration.
      while (!inFlightRequests.isEmpty()) {
        Iterator<Map.Entry<String, SettableFuture<Void>>> iter =
            inFlightRequests.entrySet().iterator();
        while (iter.hasNext()) {
          Map.Entry<String, SettableFuture<Void>> entry = iter.next();
          entry.getValue().cancel(true);
          iter.remove();
        }
      }
    }
  }

  /** A pair that represents the identifier and the path of a prefix as it will be serialized. */
  private static class Prefix {
    Integer id;
    String serializedPath;

    /**
     * Constructs a new prefix from its components.
     *
     * @param id the numerical identifier of the prefix
     * @param serializedPath the path of the prefix. Given that this is typically comes from a call
     *     to {@link Path#getParentDirectory()}, the value may be null or empty.
     */
    Prefix(Integer id, @Nullable PathFragment serializedPath) {
      this.id = id;
      if (serializedPath == null || serializedPath.isEmpty()) {
        this.serializedPath = "/";
      } else {
        this.serializedPath = serializedPath.getPathString();
      }
    }
  }

  /** Registers and assigns unique identifiers to path prefixes. */
  private static class Prefixes {
    /** Collection of all known path prefixes to this sandboxfs instance. */
    @GuardedBy("this")
    private final Map<PathFragment, Integer> prefixes = new HashMap<>();

    /** Last identifier assigned to a path prefix. */
    @GuardedBy("this")
    private Integer lastPrefixId = 1;

    /**
     * Registers the given path as a prefix.
     *
     * @param path the path to register as a prefix, which should always be the return value of a
     *     call to {@link Path#getParentDirectory()}. As a result, this should either be an absolute
     *     path, or a null or empty path.
     * @param newPrefixes tracker for any new prefixes registered by this function. If the given
     *     path is not yet known, it will be added to this collection.
     * @return the identifier for the prefix
     */
    private synchronized Integer registerPrefix(PathFragment path, ArrayList<Prefix> newPrefixes) {
      Integer id = prefixes.get(path);
      if (id != null) {
        return id;
      }

      id = lastPrefixId;
      prefixes.put(path, id);
      newPrefixes.add(new Prefix(id, path));
      lastPrefixId++;

      return id;
    }
  }

  /** Tracker for all known path prefixes to this sandboxfs instance. */
  private final Prefixes allPrefixes = new Prefixes();

  /**
   * Initializes a new sandboxfs process instance.
   *
   * @param process process handle for the already-running sandboxfs instance
   */
  RealSandboxfs02Process(Path mountPoint, Subprocess process) {
    super(mountPoint, process);

    this.processStdIn =
        new JsonWriter(
            new BufferedWriter(new OutputStreamWriter(process.getOutputStream(), UTF_8)));
    JsonReader processStdOut =
        new JsonReader(new BufferedReader(new InputStreamReader(process.getInputStream(), UTF_8)));

    // Must use lenient writing and parsing to accept a stream of separate top-level JSON objects.
    this.processStdIn.setLenient(true);
    processStdOut.setLenient(true);

    responsesReader = new ResponsesReader(processStdOut, inFlightRequests);
    responsesReader.start();
  }

  @Override
  public synchronized void destroy() {
    super.destroy();

    responsesReader.interrupt();
    try {
      responsesReader.join();
    } catch (InterruptedException e) {
      log.warning("Interrupted while waiting for responses processor thread");
      Thread.currentThread().interrupt();
    }

    processStdIn = null;
  }

  /**
   * Waits for a single response from sandboxfs and returns it.
   *
   * @param input the stream connected to sandboxfs's stdout
   * @return the response obtained from the stream
   * @throws IOException if sandboxfs fails to read from the stream for any reason, including EOF
   */
  private static Response readResponse(JsonReader input) throws IOException {
    input.beginObject();
    String id = null;
    String error = null;
    while (input.hasNext()) {
      String name = input.nextName();
      switch (name) {
        case "error":
          if (input.peek() == JsonToken.NULL) {
            input.nextNull();
          } else {
            checkState(error == null);
            error = input.nextString();
          }
          break;

        case "id":
          if (input.peek() == JsonToken.NULL) {
            input.nextNull();
          } else {
            checkState(id == null);
            id = input.nextString();
          }
          break;

        default:
          throw new IOException("Invalid field name in response: " + name);
      }
    }
    input.endObject();
    return new Response(id, error);
  }

  /**
   * Registers a new in-flight operation for the given sandbox identifier.
   *
   * <p>The caller must wait for the returned operation using {@link #waitForRequest}.
   *
   * @param id the identifier of the sandbox for which the request will be issued. There can only be
   *     one in-flight request per identifier.
   * @return the future used to wait for the request's completion
   */
  private SettableFuture<Void> newRequest(String id) {
    SettableFuture<Void> future = SettableFuture.create();
    SettableFuture<Void> other = inFlightRequests.put(id, future);
    checkState(other == null, "Cannot have two in-flight requests for sandbox '%s'", id);
    return future;
  }

  /**
   * Waits for a request to complete and unregisters its in-flight operation.
   *
   * @param future the value returned by {@link #newRequest}.
   * @throws IOException if the request cannot be waited for or if it raised an error
   */
  private static void waitForRequest(SettableFuture<Void> future) throws IOException {
    try {
      future.get();
    } catch (ExecutionException e) {
      Throwable cause = e.getCause();
      if (cause instanceof IOException) {
        throw (IOException) cause;
      } else {
        throw new AssertionError("Unexpected exception type thrown by readResponse()", cause);
      }
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      throw new IOException("Interrupted while waiting for sandboxfs response");
    }
  }

  @Override
  @SuppressWarnings("UnnecessaryParentheses")
  public void createSandbox(String id, SandboxCreator creator) throws IOException {
    checkArgument(!PathFragment.containsSeparator(id));

    SettableFuture<Void> future = newRequest(id);
    synchronized (this) {
      processStdIn.beginObject();
      {
        processStdIn.name("C");
        processStdIn.beginObject();
        {
          processStdIn.name("i");
          processStdIn.value(id);
          processStdIn.name("m");
          processStdIn.beginArray();
          ArrayList<Prefix> newPrefixes = new ArrayList<>();
          creator.create(
              (path, underlyingPath, writable) -> {
                Integer pathPrefix =
                    allPrefixes.registerPrefix(path.getParentDirectory(), newPrefixes);
                Integer underlyingPathPrefix =
                    allPrefixes.registerPrefix(underlyingPath.getParentDirectory(), newPrefixes);

                // This synchronized block is theoretically unnecessary because the lock is already
                // held by the caller of this lambda. However, we need to reenter it to appease
                // the @GuardedBy clauses.
                synchronized (this) {
                  processStdIn.beginObject();
                  {
                    processStdIn.name("x");
                    processStdIn.value(pathPrefix);
                    processStdIn.name("p");
                    processStdIn.value(path.getBaseName());
                    processStdIn.name("y");
                    processStdIn.value(underlyingPathPrefix);
                    processStdIn.name("u");
                    processStdIn.value(underlyingPath.getBaseName());
                    if (writable) {
                      processStdIn.name("w");
                      processStdIn.value(writable);
                    }
                  }
                  processStdIn.endObject();
                }
              });
          processStdIn.endArray();
          if (!newPrefixes.isEmpty()) {
            processStdIn.name("q");
            processStdIn.beginObject();
            for (Prefix prefix : newPrefixes) {
              processStdIn.name(prefix.id.toString());
              processStdIn.value(prefix.serializedPath);
            }
            processStdIn.endObject();
          }
        }
        processStdIn.endObject();
      }
      processStdIn.endObject();

      processStdIn.flush();
    }
    waitForRequest(future);
  }

  @Override
  @SuppressWarnings("UnnecessaryParentheses")
  public void destroySandbox(String id) throws IOException {
    checkArgument(!PathFragment.containsSeparator(id));

    SettableFuture<Void> future = newRequest(id);
    synchronized (this) {
      processStdIn.beginObject();
      {
        processStdIn.name("D");
        processStdIn.value(id);
      }
      processStdIn.endObject();

      processStdIn.flush();
    }
    waitForRequest(future);
  }
}
