// Copyright 2022 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.skyframe;

import static com.google.common.util.concurrent.MoreExecutors.directExecutor;

import com.google.common.base.Ascii;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.devtools.build.lib.actions.PackageRoots;
import com.google.devtools.build.lib.analysis.AnalysisPhaseCompleteEvent;
import com.google.devtools.build.lib.buildtool.SymlinkForest;
import com.google.devtools.build.lib.buildtool.SymlinkForest.SymlinkPlantingException;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSet.Node;
import com.google.devtools.build.lib.concurrent.ExecutorUtil;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.server.FailureDetails;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.skyframe.TopLevelStatusEvents.TopLevelTargetReadyForSymlinkPlanting;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.util.DetailedExitCode;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.Root;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;

/**
 * An implementation of PackageRoots that allows incremental updating of the packageRootsMap.
 *
 * <p>This class is also in charge of planting the necessary symlinks.
 */
public class IncrementalPackageRoots implements PackageRoots {

  // We only keep track of PackageIdentifier from external repos here as a memory optimization:
  // packages belong to the main repository all share the same root, which is singleSourceRoot.
  private final Map<PackageIdentifier, Root> threadSafeExternalRepoPackageRootsMap;

  @GuardedBy("stateLock")
  @Nullable
  private Set<NestedSet.Node> donePackages = Sets.newConcurrentHashSet();

  // Only tracks the symlinks lazily planted after the first eager planting wave.
  @GuardedBy("stateLock")
  @Nullable
  private Set<Path> lazilyPlantedSymlinks = Sets.newConcurrentHashSet();

  private final ListeningExecutorService symlinkPlantingPool;
  private final Object stateLock = new Object();
  private final Path execroot;
  private final Root singleSourceRoot;
  private final String prefix;

  private final ImmutableSet<Path> ignoredPaths;
  private final boolean useSiblingRepositoryLayout;

  private final boolean allowExternalRepositories;
  @Nullable private EventBus eventBus;

  // "maybe" because some conflicts in a case-insensitive FS may not be in a case-sensitive one.
  private ImmutableSet<String> maybeConflictingBaseNamesLowercase = ImmutableSet.of();

  private IncrementalPackageRoots(
      Path execroot,
      Root singleSourceRoot,
      EventBus eventBus,
      String prefix,
      ImmutableSet<Path> ignoredPaths,
      boolean useSiblingRepositoryLayout,
      boolean allowExternalRepositories) {
    this.threadSafeExternalRepoPackageRootsMap = Maps.newConcurrentMap();
    this.execroot = execroot;
    this.singleSourceRoot = singleSourceRoot;
    this.prefix = prefix;
    this.ignoredPaths = ignoredPaths;
    this.eventBus = eventBus;
    this.useSiblingRepositoryLayout = useSiblingRepositoryLayout;
    this.allowExternalRepositories = allowExternalRepositories;
    this.symlinkPlantingPool =
        MoreExecutors.listeningDecorator(
            Executors.newFixedThreadPool(
                Runtime.getRuntime().availableProcessors(),
                new ThreadFactoryBuilder().setNameFormat("Non-eager Symlink planter %d").build()));
  }

  public static IncrementalPackageRoots createAndRegisterToEventBus(
      Path execroot,
      Root singleSourceRoot,
      EventBus eventBus,
      String prefix,
      ImmutableSet<Path> ignoredPaths,
      boolean useSiblingRepositoryLayout,
      boolean allowExternalRepositories) {
    IncrementalPackageRoots incrementalPackageRoots =
        new IncrementalPackageRoots(
            execroot,
            singleSourceRoot,
            eventBus,
            prefix,
            ignoredPaths,
            useSiblingRepositoryLayout,
            allowExternalRepositories);
    eventBus.register(incrementalPackageRoots);
    return incrementalPackageRoots;
  }

  /**
   * Eagerly plant the symlinks to the directories under the single source root. It's possible that
   * there's a conflict when we plant symlinks eagerly. In that case, we skip planting the
   * conflicting symlinks eagerly and wait until later in the build to see which of the conflicting
   * dir we actually need.
   *
   * <p>Eagerly planting the symlinks is much cheaper, hence we'd like to do it as much as possible
   * and only resort to the other route when really necessary.
   *
   * <p>Example: when we plant symlinks in a case-insensitive FS, "foo" and "Foo" would conflict:
   *
   * <pre>
   * /sourceroot
   *    ├── noclash
   *    ├── foo
   *    └── Foo
   *
   * /execroot
   *    ├── noclash -> /sourceroot/noclash
   *    ├── foo -> /sourceroot/foo
   *    └── Foo (clashing with foo in a case-insensitive FS)
   * </pre>
   *
   * We'd plant the symlink to "noclash" first, then wait to see whether we need "foo" or "Foo". If
   * we end up needing both, throw an error. See {@link #registerAndPlantMissingSymlinks}.
   */
  public void eagerlyPlantSymlinksToSingleSourceRoot() throws AbruptExitException {
    try {
      maybeConflictingBaseNamesLowercase =
          SymlinkForest.eagerlyPlantSymlinkForestSinglePackagePath(
              execroot,
              singleSourceRoot.asPath(),
              prefix,
              ignoredPaths,
              useSiblingRepositoryLayout);
    } catch (IOException e) {
      throwAbruptExitException(e);
    }
  }

  /** There is currently no use case for this method, and it should not be called. */
  @Override
  public Optional<ImmutableMap<PackageIdentifier, Root>> getPackageRootsMap() {
    throw new UnsupportedOperationException(
        "IncrementalPackageRoots does not provide the package roots map directly.");
  }

  @Override
  public PackageRootLookup getPackageRootLookup() {
    return packageId ->
        packageId.getRepository().isMain()
            ? singleSourceRoot
            : threadSafeExternalRepoPackageRootsMap.get(packageId);
  }

  // Intentionally don't allow concurrent events here to prevent a race condition between planting
  // a symlink and starting an action that requires that symlink. This race condition is possible
  // because of the various memoizations we use to avoid repeated work.
  @Subscribe
  public void topLevelTargetReadyForSymlinkPlanting(TopLevelTargetReadyForSymlinkPlanting event)
      throws AbruptExitException {
    if (allowExternalRepositories || !maybeConflictingBaseNamesLowercase.isEmpty()) {
      Set<NestedSet.Node> donePackagesLocalRef;
      Set<Path> lazilyPlantedSymlinksLocalRef;
      // May still race with analysisFinished, hence the synchronization.
      synchronized (stateLock) {
        if (donePackages == null || lazilyPlantedSymlinks == null) {
          return;
        }
        donePackagesLocalRef = donePackages;
        lazilyPlantedSymlinksLocalRef = lazilyPlantedSymlinks;
      }
      registerAndPlantMissingSymlinks(
          event.transitivePackagesForSymlinkPlanting(),
          donePackagesLocalRef,
          lazilyPlantedSymlinksLocalRef);
    }
  }

  @Subscribe
  public void analysisFinished(AnalysisPhaseCompleteEvent unused) {
    dropIntermediateStatesAndUnregisterFromEventBus();
  }

  /**
   * Lazily plant the required symlinks that couldn't be planted in the initial eager planting wave.
   *
   * <p>There are 2 possibilities: either we're planting symlinks to the external repos, or there's
   * potentially conflicting symlinks detected.
   */
  private void registerAndPlantMissingSymlinks(
      NestedSet<Package> packages, Set<Node> donePackagesRef, Set<Path> lazilyPlantedSymlinksRef)
      throws AbruptExitException {
    // Optimization to prune subsequent traversals.
    // A false negative does not affect correctness.
    if (donePackagesRef.contains(packages.toNode())) {
      return;
    }

    List<ListenableFuture<Void>> futures = new ArrayList<>(packages.getLeaves().size());
    synchronized (symlinkPlantingPool) {
      // Some other thread shut down the executor, exit now.
      if (symlinkPlantingPool.isShutdown()) {
        return;
      }
      for (Package pkg : packages.getLeaves()) {
        futures.add(
            symlinkPlantingPool.submit(
                () -> plantSingleSymlinkForPackage(pkg, lazilyPlantedSymlinksRef)));
      }
    }
    for (NestedSet<Package> transitive : packages.getNonLeaves()) {
      registerAndPlantMissingSymlinks(transitive, donePackagesRef, lazilyPlantedSymlinksRef);
    }
    // Now wait on the futures.
    try {
      Futures.whenAllSucceed(futures).call(() -> null, directExecutor()).get();
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      return; // Bail
    } catch (ExecutionException e) {
      if (e.getCause() instanceof AbruptExitException) {
        throw (AbruptExitException) e.getCause();
      }
      throw new IllegalStateException("Unexpected exception", e);
    }
    // Only update the memoization set now, after the symlinks are confirmed planted.
    donePackagesRef.add(packages.toNode());
  }

  private Void plantSingleSymlinkForPackage(Package pkg, Set<Path> lazilyPlantedSymlinksRef)
      throws AbruptExitException {
    try {
      PackageIdentifier pkgId = pkg.getPackageIdentifier();
      if (isExternalRepository(pkgId) && pkg.getSourceRoot().isPresent()) {
        threadSafeExternalRepoPackageRootsMap.putIfAbsent(
            pkg.getPackageIdentifier(), pkg.getSourceRoot().get());
        SymlinkForest.plantSingleSymlinkForExternalRepo(
            pkgId.getRepository(),
            pkg.getSourceRoot().get().asPath(),
            execroot,
            useSiblingRepositoryLayout,
            lazilyPlantedSymlinksRef);
      } else if (!maybeConflictingBaseNamesLowercase.isEmpty()) {
        String originalBaseName = pkgId.getTopLevelDir();
        String baseNameLowercase = Ascii.toLowerCase(originalBaseName);

        // As Skymeld only supports single package path at the moment, we only seek to symlink to
        // the top-level dir i.e. what's directly under the source root.
        Path link = execroot.getRelative(originalBaseName);
        Path target = singleSourceRoot.getRelative(originalBaseName);

        if (originalBaseName.isEmpty()
            || !maybeConflictingBaseNamesLowercase.contains(baseNameLowercase)
            || !SymlinkForest.symlinkShouldBePlanted(
                prefix, ignoredPaths, useSiblingRepositoryLayout, originalBaseName, target)) {
          // We should have already eagerly planted a symlink for this, or there's nothing to do.
          return null;
        }

        if (lazilyPlantedSymlinksRef.add(link)) {
          try {
            link.createSymbolicLink(target);
          } catch (IOException e) {
            StringBuilder errorMessage =
                new StringBuilder(
                    String.format("Failed to plant a symlink: %s -> %s", link, target));
            if (link.exists() && link.isSymbolicLink()) {
              // If the link already exists, it must mean that we're planting from a
              // case-insensitive file system and this is a legitimate conflict.
              // TODO(b/295300378) We technically can go deeper here and try to create the subdirs
              // to try to resolve the conflict, but the complexity isn't worth it at the moment
              // and the non-skymeld code path isn't doing any better. Revisit if necessary.
              Path existingTarget = link.resolveSymbolicLinks();
              if (!existingTarget.equals(target)) {
                errorMessage.append(
                    String.format(
                        ". Found an existing conflicting symlink: %s -> %s", link, existingTarget));
              }
            }

            throw new SymlinkPlantingException(errorMessage.toString(), e);
          }
        }
      }
    } catch (IOException | SymlinkPlantingException e) {
      throwAbruptExitException(e);
    }
    return null;
  }

  private static void throwAbruptExitException(Exception e) throws AbruptExitException {
    throw new AbruptExitException(
        DetailedExitCode.of(
            FailureDetail.newBuilder()
                .setMessage("Failed to prepare the symlink forest: " + e)
                .setSymlinkForest(
                    FailureDetails.SymlinkForest.newBuilder()
                        .setCode(FailureDetails.SymlinkForest.Code.CREATION_FAILED))
                .build()),
        e);
  }

  private static boolean isExternalRepository(PackageIdentifier pkgId) {
    return !pkgId.getRepository().isMain();
  }

  /**
   * Drops the intermediate states and stop receiving new events.
   *
   * <p>This essentially makes this instance read-only. Should be called when and only when all
   * analysis work is done in the build to free up some memory.
   */
  private void dropIntermediateStatesAndUnregisterFromEventBus() {
    // This instance is retained after a build via ArtifactFactory, so it's important that we remove
    // the reference to the eventBus here for it to be GC'ed.
    Preconditions.checkNotNull(eventBus).unregister(this);
    eventBus = null;

    synchronized (stateLock) {
      donePackages = null;
      lazilyPlantedSymlinks = null;
      maybeConflictingBaseNamesLowercase = ImmutableSet.of();
    }
    synchronized (symlinkPlantingPool) {
      if (!symlinkPlantingPool.isShutdown()
          && ExecutorUtil.interruptibleShutdown(symlinkPlantingPool)) {
        // Preserve the interrupt status.
        Thread.currentThread().interrupt();
      }
    }
  }
}
