// Copyright 2018 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.annotations.VisibleForTesting;
import com.google.devtools.build.lib.actions.UserExecException;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.server.FailureDetails;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.server.FailureDetails.Worker.Code;
import com.google.devtools.build.lib.vfs.Path;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;

/**
 * A manager to instantiate and destroy multiplexers. There should only be one {@code
 * WorkerMultiplexer} corresponding to workers with the same {@code WorkerKey}. If the {@code
 * WorkerMultiplexer} has been constructed, other workers should point to the same one.
 */
public class WorkerMultiplexerManager {
  /**
   * A map from the hash of {@code WorkerKey} objects to the corresponding information about the
   * multiplexer instance.
   */
  private static final Map<WorkerKey, InstanceInfo> multiplexerInstance = new HashMap<>();

  private WorkerMultiplexerManager() {}

  /**
   * Returns a {@code WorkerMultiplexer} instance to {@code WorkerProxy}. {@code WorkerProxy}
   * objects with the same {@code WorkerKey} talk to the same {@code WorkerMultiplexer}. Also,
   * record how many {@code WorkerProxy} objects are talking to this {@code WorkerMultiplexer}.
   */
  public static synchronized WorkerMultiplexer getInstance(WorkerKey key, Path logFile) {
    InstanceInfo instanceInfo =
        multiplexerInstance.computeIfAbsent(
            key, k -> new InstanceInfo(new WorkerMultiplexer(logFile, k)));
    instanceInfo.increaseRefCount();
    return instanceInfo.getWorkerMultiplexer();
  }

  static void beforeCommand(Reporter reporter) {
    setReporter(reporter);
  }

  static void afterCommand() {
    setReporter(null);
  }

  /**
   * Sets the reporter for all existing multiplexer instances. This allows reporting problems
   * encountered while fetching an instance, e.g. during WorkerProxy validation.
   */
  private static synchronized void setReporter(@Nullable EventHandler reporter) {
    for (InstanceInfo m : multiplexerInstance.values()) {
      m.workerMultiplexer.setReporter(reporter);
    }
  }

  /** Removes a {@code WorkerProxy} instance and reference count since it is no longer in use. */
  public static synchronized void removeInstance(WorkerKey key) throws UserExecException {
    InstanceInfo instanceInfo = multiplexerInstance.get(key);
    if (instanceInfo == null) {
      throw createUserExecException(
          String.format(
              "Attempting to remove non-existent %s multiplexer instance.", key.getMnemonic()),
          Code.MULTIPLEXER_INSTANCE_REMOVAL_FAILURE);
    }
    instanceInfo.decreaseRefCount();
    if (instanceInfo.getRefCount() == 0) {
      instanceInfo.getWorkerMultiplexer().destroyMultiplexer();
      multiplexerInstance.remove(key);
    }
  }

  @VisibleForTesting
  static WorkerMultiplexer getMultiplexer(WorkerKey key) throws UserExecException {
    InstanceInfo instanceInfo = multiplexerInstance.get(key);
    if (instanceInfo == null) {
      throw createUserExecException(
          "Accessing non-existent multiplexer instance.", Code.MULTIPLEXER_DOES_NOT_EXIST);
    }
    return instanceInfo.getWorkerMultiplexer();
  }

  @VisibleForTesting
  static Integer getRefCount(WorkerKey key) throws UserExecException {
    InstanceInfo instanceInfo = multiplexerInstance.get(key);
    if (instanceInfo == null) {
      throw createUserExecException(
          "Accessing non-existent multiplexer instance.", Code.MULTIPLEXER_DOES_NOT_EXIST);
    }
    return instanceInfo.getRefCount();
  }

  @VisibleForTesting
  static Integer getInstanceCount() {
    return multiplexerInstance.keySet().size();
  }

  private static UserExecException createUserExecException(String message, Code detailedCode) {
    return new UserExecException(
        FailureDetail.newBuilder()
            .setMessage(message)
            .setWorker(FailureDetails.Worker.newBuilder().setCode(detailedCode))
            .build());
  }

  /** Contains the WorkerMultiplexer instance and reference count. */
  static class InstanceInfo {
    private final WorkerMultiplexer workerMultiplexer;
    private Integer refCount;

    public InstanceInfo(WorkerMultiplexer workerMultiplexer) {
      this.workerMultiplexer = workerMultiplexer;
      this.refCount = 0;
    }

    public void increaseRefCount() {
      refCount = refCount + 1;
    }

    public void decreaseRefCount() {
      refCount = refCount - 1;
    }

    public WorkerMultiplexer getWorkerMultiplexer() {
      return workerMultiplexer;
    }

    public Integer getRefCount() {
      return refCount;
    }
  }

  /** Resets the instances. For testing only. */
  @VisibleForTesting
  static void resetForTesting() {
    for (InstanceInfo i : multiplexerInstance.values()) {
      i.workerMultiplexer.destroyMultiplexer();
    }
    multiplexerInstance.clear();
  }

  /** Injects a given WorkerMultiplexer into the instance map with refcount 0. For testing only. */
  @VisibleForTesting
  static synchronized void injectForTesting(WorkerKey key, WorkerMultiplexer multiplexer) {
    multiplexerInstance.put(key, new InstanceInfo(multiplexer));
  }
}
