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

import com.google.common.base.Preconditions;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.common.options.OptionsProvider;
import com.sun.nio.file.ExtendedWatchEventModifier;
import java.io.IOException;
import java.nio.file.ClosedWatchServiceException;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchEvent.Kind;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashSet;
import java.util.Set;

/**
 * File system watcher for local filesystems. It's able to provide a list of changed files between
 * two consecutive calls. Uses the standard Java WatchService, which uses 'inotify' on Linux.
 */
public final class WatchServiceDiffAwareness extends LocalDiffAwareness {
  /**
   * Bijection from WatchKey to the (absolute) Path being watched. WatchKeys don't have this
   * functionality built-in so we do it ourselves.
   */
  private final HashBiMap<WatchKey, Path> watchKeyToDirBiMap = HashBiMap.create();

  private final boolean isWindows = OS.getCurrent() == OS.WINDOWS;

  /** Every directory is registered under this watch service. */
  private WatchService watchService;

  WatchServiceDiffAwareness(String watchRoot) {
    super(watchRoot);
  }

  private void init() {
    Preconditions.checkState(watchService == null);
    try {
      watchService = FileSystems.getDefault().newWatchService();
    } catch (IOException ignored) {
      // According to the docs, this can never happen with the default file system provider.
    }
  }

  @Override
  public View getCurrentView(OptionsProvider options) throws BrokenDiffAwarenessException {
    // We need to consider 4 cases for watchFs:
    // previous view    current view
    //  disabled         disabled  -> EVERYTHING_MODIFIED
    //  disabled         enabled   -> valid View (1)
    //  enabled          disabled  -> throw BrokenDiffAwarenessException
    //  enabled          enabled   -> valid View
    //
    // (1) When watchFs gets enabled, we need to consider both the delta from the previous view
    //     to the current view (1a), and from the current view to the next view (1b).
    // (1a) If watchFs was previously disabled, then previous view was either EVERYTHING_MODIFIED,
    //      or we threw a BrokenDiffAwarenessException. The first is safe because comparing it to
    //      any view results in ModifiedFileSet.EVERYTHING_MODIFIED. The second is safe because
    //      the previous diff awareness gets closed and we're now in a new instance; comparisons
    //      between views with different owners always results in
    //      ModifiedFileSet.EVERYTHING_MODIFIED.
    // (1b) On the next run, we want to see the files that were modified between the current and the
    //      next run. For that, the view we return needs to be valid; however, it's ok for it to
    //      contain files that are modified between init() and poll() below, because those are
    //      already taken into account for the current build, as we ended up with
    //      ModifiedFileSet.EVERYTHING_MODIFIED in the current build.
    boolean watchFs =
        options.getOptions(Options.class).watchFS
            &&
            // Guard WatchFs on Windows behind --experimental_windows_watchfs.
            (!isWindows || options.getOptions(Options.class).windowsWatchFS);
    if (watchFs && watchService == null) {
      init();
    } else if (!watchFs && (watchService != null)) {
      close();
      // The contract is that throwing BrokenDiffAwarenessException prevents reuse of the same
      // diff awareness object.
      // Consider this sequence of builds:
      // 1. build --watchfs    // startup the listener
      // 2. build --nowatchfs  // shutdown the listener
      // 3. build --watchfs    // startup the listener
      //
      // In the third build, we have to be careful not to reuse information from the first build,
      // since we don't know what changed between the second and third builds. One way to ensure
      // that is to carefully ensure that we increment the iteration numbers on every call;
      // LocalDiffAwareness will only return a Diff if the Views are in sequential order. The other
      // is to not reuse the DiffAwareness object, but create a new one; the DiffAwarenessManager
      // always assumes EVERYTHING_MODIFIED for different objects. That seems safer, so we're using
      // that here.
      throw new BrokenDiffAwarenessException("Switched off --watchfs again");
    }
    // If init() failed, then this if also applies.
    if (watchService == null) {
      return EVERYTHING_MODIFIED;
    }
    Set<Path> modifiedAbsolutePaths;
    if (isFirstCall()) {
      try {
        // Due to a known issue nested watches may result in errors on windows:
        // https://bugs.openjdk.java.net/browse/JDK-6972833
        // Therefore on windows we register using the special ExtendedWatchEventModifier.FILE_TREE
        // This watches a folder recursively so there is no need to apply this ourselves
        if (isWindows) {
          WatchKey key =
              watchRootPath.register(
                  watchService,
                  new Kind<?>[] {
                    StandardWatchEventKinds.ENTRY_CREATE,
                    StandardWatchEventKinds.ENTRY_MODIFY,
                    StandardWatchEventKinds.ENTRY_DELETE,
                  },
                  ExtendedWatchEventModifier.FILE_TREE);
          watchKeyToDirBiMap.put(key, watchRootPath);
        } else {
          registerSubDirectoriesAndReturnContents(watchRootPath);
        }
      } catch (IOException e) {
        close();
        throw new BrokenDiffAwarenessException(
            "Error encountered with local file system watcher " + e);
      }
      modifiedAbsolutePaths = ImmutableSet.of();
    } else {
      try {
        modifiedAbsolutePaths = collectChanges();
      } catch (BrokenDiffAwarenessException e) {
        close();
        throw e;
      } catch (IOException e) {
        close();
        throw new BrokenDiffAwarenessException(
            "Error encountered with local file system watcher " + e);
      } catch (ClosedWatchServiceException e) {
        throw new BrokenDiffAwarenessException(
            "Internal error with the local file system watcher " + e);
      }
    }
    return newView(modifiedAbsolutePaths);
  }

  @Override
  public void close() {
    if (watchService != null) {
      try {
        watchService.close();
      } catch (IOException ignored) {
        // Nothing we can do here.
      }
    }
  }

  /** Returns the changed files caught by the watch service. */
  private Set<Path> collectChanges() throws BrokenDiffAwarenessException, IOException {
    Set<Path> createdFilesAndDirectories = new HashSet<>();
    Set<Path> deletedOrModifiedFilesAndDirectories = new HashSet<>();
    Set<Path> deletedTrackedDirectories = new HashSet<>();

    WatchKey watchKey;
    while ((watchKey = watchService.poll()) != null) {
      Path dir = watchKeyToDirBiMap.get(watchKey);
      Preconditions.checkArgument(dir != null);

      // We replay all the events for this watched directory in chronological order and
      // construct the diff of this directory since the last #collectChanges call.
      for (WatchEvent<?> event : watchKey.pollEvents()) {
        Kind<?> kind = event.kind();
        if (kind == StandardWatchEventKinds.OVERFLOW) {
          // TODO(bazel-team): find out when an overflow might happen, and maybe handle it more
          // gently.
          throw new BrokenDiffAwarenessException(
              "Overflow when watching local filesystem for " + "changes");
        }
        if (event.context() == null) {
          // The WatchService documentation mentions that WatchEvent#context may return null, but
          // doesn't explain how/why it would do so. Looking at the implementation, it only
          // happens on an overflow event. But we make no assumptions about that implementation
          // detail here.
          throw new BrokenDiffAwarenessException(
              "Insufficient information from local file system " + "watcher");
        }
        // For the events we've registered, the context given is a relative path.
        Path relativePath = (Path) event.context();
        Path path = dir.resolve(relativePath);
        Preconditions.checkState(path.isAbsolute(), path);
        if (kind == StandardWatchEventKinds.ENTRY_CREATE) {
          createdFilesAndDirectories.add(path);
          deletedOrModifiedFilesAndDirectories.remove(path);
        } else if (kind == StandardWatchEventKinds.ENTRY_DELETE) {
          createdFilesAndDirectories.remove(path);
          deletedOrModifiedFilesAndDirectories.add(path);
          WatchKey deletedDirectoryKey = watchKeyToDirBiMap.inverse().get(path);
          if (deletedDirectoryKey != null) {
            // If the deleted directory has children, then there will also be events for the
            // WatchKey of the directory itself. WatchService#poll doesn't specify the order in
            // which WatchKeys are returned, so the key for the directory itself may be processed
            // *after* the current key (the parent of the deleted directory), and so we don't want
            // to remove the deleted directory from our bimap just yet.
            //
            // For example, suppose we have the file '/root/a/foo.txt' and are watching the
            // directories '/root' and '/root/a'. If the directory '/root/a' gets deleted then the
            // following is a valid sequence of events by key.
            //
            // WatchKey '/root/'
            // WatchEvent EVENT_MODIFY 'a'
            // WatchEvent EVENT_DELETE 'a'
            // WatchKey '/root/a'
            // WatchEvent EVENT_DELETE 'foo.txt'
            deletedTrackedDirectories.add(path);
            // Since inotify uses inodes under the covers we cancel our registration on this key to
            // avoid getting WatchEvents from a new directory that happens to have the same inode.
            deletedDirectoryKey.cancel();
          }
        } else if (kind == StandardWatchEventKinds.ENTRY_MODIFY) {
          // If a file was created and then modified, then the net diff is that it was
          // created.
          if (!createdFilesAndDirectories.contains(path)) {
            deletedOrModifiedFilesAndDirectories.add(path);
          }
        }
      }

      if (!watchKey.reset()) {
        // Watcher got deleted, directory no longer valid.
        watchKeyToDirBiMap.remove(watchKey);
      }
    }

    for (Path path : deletedTrackedDirectories) {
      WatchKey staleKey = watchKeyToDirBiMap.inverse().get(path);
      watchKeyToDirBiMap.remove(staleKey);
    }
    if (watchKeyToDirBiMap.isEmpty()) {
      // No more directories to watch, something happened the root directory being watched.
      throw new IOException("Root directory " + watchRootPath + " became inaccessible.");
    }

    Set<Path> changedPaths = new HashSet<>();
    for (Path path : createdFilesAndDirectories) {
      if (Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS)) {
        // This is a new directory, so changes to it since its creation have not been watched.
        // We manually traverse the directory tree to register all the new subdirectories and find
        // all the new subdirectories and files.
        changedPaths.addAll(registerSubDirectoriesAndReturnContents(path));
      } else {
        changedPaths.add(path);
      }
    }
    changedPaths.addAll(deletedOrModifiedFilesAndDirectories);
    return changedPaths;
  }

  /**
   * Traverses directory tree to register subdirectories. Returns all paths traversed (as absolute
   * paths).
   */
  private Set<Path> registerSubDirectoriesAndReturnContents(Path rootDir) throws IOException {
    Set<Path> visitedAbsolutePaths = new HashSet<>();
    // Note that this does not follow symlinks.
    Files.walkFileTree(rootDir, new WatcherFileVisitor(visitedAbsolutePaths));
    return visitedAbsolutePaths;
  }

  /** File visitor used by Files.walkFileTree() upon traversing subdirectories. */
  private class WatcherFileVisitor extends SimpleFileVisitor<Path> {

    private final Set<Path> visitedAbsolutePaths;

    private WatcherFileVisitor(Set<Path> visitedPaths) {
      this.visitedAbsolutePaths = visitedPaths;
    }

    @Override
    public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
      Preconditions.checkState(path.isAbsolute(), path);
      visitedAbsolutePaths.add(path);
      return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes attrs)
        throws IOException {
      // It's important that we register the directory before we visit its children. This way we
      // are guaranteed to see new files/directories either on this #getDiff or the next one.
      // Otherwise, e.g., an intra-build creation of a child directory will be forever missed if it
      // happens before the directory is listed as part of the visitation.
      Preconditions.checkState(path.isAbsolute(), path);
      // On windows we register the root path with ExtendedWatchEventModifier.FILE_TREE
      // Therefore there is no need to register recursive watchers
      if (!isWindows) {
        WatchKey key =
            path.register(
                watchService,
                StandardWatchEventKinds.ENTRY_CREATE,
                StandardWatchEventKinds.ENTRY_MODIFY,
                StandardWatchEventKinds.ENTRY_DELETE);
        watchKeyToDirBiMap.put(key, path);
      }
      visitedAbsolutePaths.add(path);
      return FileVisitResult.CONTINUE;
    }
  }
}
