//===- FileSystemStatCache.cpp - Caching for 'stat' calls -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file defines the FileSystemStatCache interface.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/FileSystemStatCache.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/VirtualFileSystem.h"
#include <utility>

using namespace clang;

void FileSystemStatCache::anchor() {}

/// FileSystemStatCache::get - Get the 'stat' information for the specified
/// path, using the cache to accelerate it if possible.  This returns true if
/// the path does not exist or false if it exists.
///
/// If isFile is true, then this lookup should only return success for files
/// (not directories).  If it is false this lookup should only return
/// success for directories (not files).  On a successful file lookup, the
/// implementation can optionally fill in FileDescriptor with a valid
/// descriptor and the client guarantees that it will close it.
std::error_code FileSystemStatCache::get(StringRef Path,
                                         llvm::vfs::Status &Status, bool isFile,
                                         std::unique_ptr<llvm::vfs::File> *F,
                                         FileSystemStatCache *Cache,
                                         llvm::vfs::FileSystem &FS,
                                         bool IsText) {
  bool isForDir = !isFile;
  std::error_code RetCode;

  // If we have a cache, use it to resolve the stat query.
  if (Cache)
    RetCode = Cache->getStat(Path, Status, isFile, F, FS);
  else if (isForDir || !F) {
    // If this is a directory or a file descriptor is not needed and we have
    // no cache, just go to the file system.
    llvm::ErrorOr<llvm::vfs::Status> StatusOrErr = FS.status(Path);
    if (!StatusOrErr) {
      RetCode = StatusOrErr.getError();
    } else {
      Status = *StatusOrErr;
    }
  } else {
    // Otherwise, we have to go to the filesystem.  We can always just use
    // 'stat' here, but (for files) the client is asking whether the file exists
    // because it wants to turn around and *open* it.  It is more efficient to
    // do "open+fstat" on success than it is to do "stat+open".
    //
    // Because of this, check to see if the file exists with 'open'.  If the
    // open succeeds, use fstat to get the stat info.
    auto OwnedFile =
        IsText ? FS.openFileForRead(Path) : FS.openFileForReadBinary(Path);

    if (!OwnedFile) {
      // If the open fails, our "stat" fails.
      RetCode = OwnedFile.getError();
    } else {
      // Otherwise, the open succeeded.  Do an fstat to get the information
      // about the file.  We'll end up returning the open file descriptor to the
      // client to do what they please with it.
      llvm::ErrorOr<llvm::vfs::Status> StatusOrErr = (*OwnedFile)->status();
      if (StatusOrErr) {
        Status = *StatusOrErr;
        *F = std::move(*OwnedFile);
      } else {
        // fstat rarely fails.  If it does, claim the initial open didn't
        // succeed.
        *F = nullptr;
        RetCode = StatusOrErr.getError();
      }
    }
  }

  // If the path doesn't exist, return failure.
  if (RetCode)
    return RetCode;

  // If the path exists, make sure that its "directoryness" matches the clients
  // demands.
  if (Status.isDirectory() != isForDir) {
    // If not, close the file if opened.
    if (F)
      *F = nullptr;
    return std::make_error_code(
        Status.isDirectory() ?
            std::errc::is_a_directory : std::errc::not_a_directory);
  }

  return std::error_code();
}

std::error_code
MemorizeStatCalls::getStat(StringRef Path, llvm::vfs::Status &Status,
                           bool isFile,
                           std::unique_ptr<llvm::vfs::File> *F,
                           llvm::vfs::FileSystem &FS) {
  auto err = get(Path, Status, isFile, F, nullptr, FS);
  if (err) {
    // Do not cache failed stats, it is easy to construct common inconsistent
    // situations if we do, and they are not important for PCH performance
    // (which currently only needs the stats to construct the initial
    // FileManager entries).
    return err;
  }

  // Cache file 'stat' results and directories with absolutely paths.
  if (!Status.isDirectory() || llvm::sys::path::is_absolute(Path))
    StatCalls[Path] = Status;

  return std::error_code();
}
