// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/leveldb/env_mojo.h"

#include <memory>

#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/task_scheduler/post_task.h"
#include "base/trace_event/trace_event.h"
#include "third_party/leveldatabase/chromium_logger.h"
#include "third_party/leveldatabase/src/include/leveldb/status.h"

using filesystem::mojom::FileError;
using leveldb_env::UMALogger;

namespace leveldb {

namespace {

const base::FilePath::CharType table_extension[] = FILE_PATH_LITERAL(".ldb");

Status FilesystemErrorToStatus(FileError error,
                               const std::string& filename,
                               leveldb_env::MethodID method) {
  if (error == FileError::OK)
    return Status::OK();

  std::string err_str =
      base::File::ErrorToString(base::File::Error(static_cast<int>(error)));

  char buf[512];
  snprintf(buf, sizeof(buf), "%s (MojoFSError: %d::%s)", err_str.c_str(),
           method, MethodIDToString(method));

  // TOOD(crbug.com/760362): Map FileError::NOT_FOUND to Status::NotFound, after
  //                         fixing LevelDB to handle the NotFound correctly.
  return Status::IOError(filename, buf);
}

class MojoFileLock : public FileLock {
 public:
  MojoFileLock(LevelDBMojoProxy::OpaqueLock* lock, const std::string& name)
      : fname_(name), lock_(lock) {}
  ~MojoFileLock() override { DCHECK(!lock_); }

  const std::string& name() const { return fname_; }

  LevelDBMojoProxy::OpaqueLock* TakeLock() {
    LevelDBMojoProxy::OpaqueLock* to_return = lock_;
    lock_ = nullptr;
    return to_return;
  }

 private:
  std::string fname_;
  LevelDBMojoProxy::OpaqueLock* lock_;
};

class MojoSequentialFile : public leveldb::SequentialFile {
 public:
  MojoSequentialFile(const std::string& fname,
                     base::File f,
                     const UMALogger* uma_logger)
      : filename_(fname), file_(std::move(f)), uma_logger_(uma_logger) {}
  ~MojoSequentialFile() override {}

  Status Read(size_t n, Slice* result, char* scratch) override {
    int bytes_read = file_.ReadAtCurrentPosNoBestEffort(
        scratch,
        static_cast<int>(n));
    if (bytes_read == -1) {
      base::File::Error error = base::File::GetLastFileError();
      uma_logger_->RecordOSError(leveldb_env::kSequentialFileRead, error);
      return MakeIOError(filename_, base::File::ErrorToString(error),
                         leveldb_env::kSequentialFileRead, error);
    }
    if (bytes_read > 0)
      uma_logger_->RecordBytesRead(bytes_read);
    *result = Slice(scratch, bytes_read);
    return Status::OK();
  }

  Status Skip(uint64_t n) override {
    if (file_.Seek(base::File::FROM_CURRENT, n) == -1) {
      base::File::Error error = base::File::GetLastFileError();
      uma_logger_->RecordOSError(leveldb_env::kSequentialFileSkip, error);
      return MakeIOError(filename_, base::File::ErrorToString(error),
                         leveldb_env::kSequentialFileSkip, error);
    }
    return Status::OK();
  }

 private:
  std::string filename_;
  base::File file_;
  const UMALogger* uma_logger_;

  DISALLOW_COPY_AND_ASSIGN(MojoSequentialFile);
};

class MojoRandomAccessFile : public leveldb::RandomAccessFile {
 public:
  MojoRandomAccessFile(const std::string& fname,
                       base::File file,
                       const UMALogger* uma_logger)
      : filename_(fname), file_(std::move(file)), uma_logger_(uma_logger) {}
  ~MojoRandomAccessFile() override {}

  Status Read(uint64_t offset,
              size_t n,
              Slice* result,
              char* scratch) const override {
    int bytes_read = file_.Read(offset, scratch, static_cast<int>(n));
    *result = Slice(scratch, (bytes_read < 0) ? 0 : bytes_read);
    if (bytes_read < 0) {
      uma_logger_->RecordOSError(leveldb_env::kRandomAccessFileRead,
                                 base::File::GetLastFileError());
      return MakeIOError(filename_, "Could not perform read",
                         leveldb_env::kRandomAccessFileRead);
    }
    if (bytes_read > 0)
      uma_logger_->RecordBytesRead(bytes_read);
    return Status::OK();
  }

 private:
  std::string filename_;
  mutable base::File file_;
  const UMALogger* uma_logger_;

  DISALLOW_COPY_AND_ASSIGN(MojoRandomAccessFile);
};

class MojoWritableFile : public leveldb::WritableFile {
 public:
  MojoWritableFile(LevelDBMojoProxy::OpaqueDir* dir,
                   const std::string& fname,
                   base::File f,
                   scoped_refptr<LevelDBMojoProxy> thread,
                   const UMALogger* uma_logger)
      : filename_(fname),
        file_(std::move(f)),
        file_type_(kOther),
        dir_(dir),
        thread_(thread),
        uma_logger_(uma_logger) {
    base::FilePath path = base::FilePath::FromUTF8Unsafe(fname);
    if (base::StartsWith(path.BaseName().AsUTF8Unsafe(), "MANIFEST",
                         base::CompareCase::SENSITIVE)) {
      file_type_ = kManifest;
    } else if (path.MatchesExtension(table_extension)) {
      file_type_ = kTable;
    }
    parent_dir_ =
        base::FilePath::FromUTF8Unsafe(fname).DirName().AsUTF8Unsafe();
  }

  ~MojoWritableFile() override {}

  leveldb::Status Append(const leveldb::Slice& data) override {
    int bytes_written =
        file_.WriteAtCurrentPos(data.data(), static_cast<int>(data.size()));
    if (bytes_written != static_cast<int>(data.size())) {
      base::File::Error error = base::File::GetLastFileError();
      uma_logger_->RecordOSError(leveldb_env::kWritableFileAppend, error);
      return MakeIOError(filename_, base::File::ErrorToString(error),
                         leveldb_env::kWritableFileAppend, error);
    }
    if (bytes_written > 0)
      uma_logger_->RecordBytesWritten(bytes_written);
    return Status::OK();
  }

  leveldb::Status Close() override {
    file_.Close();
    return Status::OK();
  }

  leveldb::Status Flush() override {
    // base::File doesn't do buffered I/O (i.e. POSIX FILE streams) so nothing
    // to flush.
    return Status::OK();
  }

  leveldb::Status Sync() override {
    TRACE_EVENT0("leveldb", "MojoWritableFile::Sync");

    if (!file_.Flush()) {
      base::File::Error error = base::File::GetLastFileError();
      uma_logger_->RecordOSError(leveldb_env::kWritableFileSync, error);
      return MakeIOError(filename_, base::File::ErrorToString(error),
                         leveldb_env::kWritableFileSync, error);
    }

    // leveldb's implicit contract for Sync() is that if this instance is for a
    // manifest file then the directory is also sync'ed. See leveldb's
    // env_posix.cc.
    if (file_type_ == kManifest)
      return SyncParent();

    return Status::OK();
  }

 private:
  enum Type { kManifest, kTable, kOther };

  leveldb::Status SyncParent() {
    FileError error = thread_->SyncDirectory(dir_, parent_dir_);
    if (error != FileError::OK) {
      uma_logger_->RecordOSError(leveldb_env::kSyncParent,
                                 static_cast<base::File::Error>(error));
    }
    return error == FileError::OK
               ? Status::OK()
               : Status::IOError(filename_,
                                 base::File::ErrorToString(base::File::Error(
                                     static_cast<int>(error))));
  }

  std::string filename_;
  base::File file_;
  Type file_type_;
  LevelDBMojoProxy::OpaqueDir* dir_;
  std::string parent_dir_;
  scoped_refptr<LevelDBMojoProxy> thread_;
  const UMALogger* uma_logger_;

  DISALLOW_COPY_AND_ASSIGN(MojoWritableFile);
};

class Thread : public base::PlatformThread::Delegate {
 public:
  Thread(void (*function)(void* arg), void* arg)
      : function_(function), arg_(arg) {
    base::PlatformThreadHandle handle;
    bool success = base::PlatformThread::Create(0, this, &handle);
    DCHECK(success);
  }
  ~Thread() override {}
  void ThreadMain() override {
    (*function_)(arg_);
    delete this;
  }

 private:
  void (*function_)(void* arg);
  void* arg_;

  DISALLOW_COPY_AND_ASSIGN(Thread);
};

class Retrier {
 public:
  Retrier(leveldb_env::MethodID method, MojoRetrierProvider* provider)
      : start_(base::TimeTicks::Now()),
        limit_(start_ + base::TimeDelta::FromMilliseconds(
                            provider->MaxRetryTimeMillis())),
        last_(start_),
        time_to_sleep_(base::TimeDelta::FromMilliseconds(10)),
        success_(true),
        method_(method),
        last_error_(base::File::FILE_OK),
        provider_(provider) {}

  ~Retrier() {
    if (success_) {
      provider_->RecordRetryTime(method_, last_ - start_);
      if (last_error_ != base::File::FILE_OK) {
        DCHECK_LT(last_error_, 0);
        provider_->RecordRecoveredFromError(method_, last_error_);
      }
    }
  }

  bool ShouldKeepTrying(FileError error) {
    return ShouldKeepTrying(static_cast<base::File::Error>(error));
  }

  bool ShouldKeepTrying(base::File::Error last_error) {
    DCHECK_NE(last_error, base::File::FILE_OK);
    last_error_ = last_error;
    if (last_ < limit_) {
      base::PlatformThread::Sleep(time_to_sleep_);
      last_ = base::TimeTicks::Now();
      return true;
    }
    success_ = false;
    return false;
  }

 private:
  base::TimeTicks start_;
  base::TimeTicks limit_;
  base::TimeTicks last_;
  base::TimeDelta time_to_sleep_;
  bool success_;
  leveldb_env::MethodID method_;
  base::File::Error last_error_;
  MojoRetrierProvider* provider_;

  DISALLOW_COPY_AND_ASSIGN(Retrier);
};

}  // namespace

MojoEnv::MojoEnv(scoped_refptr<LevelDBMojoProxy> file_thread,
                 LevelDBMojoProxy::OpaqueDir* dir)
    : thread_(file_thread), dir_(dir) {}

MojoEnv::~MojoEnv() {
  thread_->UnregisterDirectory(dir_);
}

Status MojoEnv::NewSequentialFile(const std::string& fname,
                                  SequentialFile** result) {
  TRACE_EVENT1("leveldb", "MojoEnv::NewSequentialFile", "fname", fname);
  base::File f = thread_->OpenFileHandle(
      dir_, fname, filesystem::mojom::kFlagOpen | filesystem::mojom::kFlagRead);
  if (!f.IsValid()) {
    *result = nullptr;
    RecordOSError(leveldb_env::kNewSequentialFile, f.error_details());
    return MakeIOError(fname, "Unable to create sequential file",
                       leveldb_env::kNewSequentialFile, f.error_details());
  }

  *result = new MojoSequentialFile(fname, std::move(f), this);
  return Status::OK();
}

Status MojoEnv::NewRandomAccessFile(const std::string& fname,
                                    RandomAccessFile** result) {
  TRACE_EVENT1("leveldb", "MojoEnv::NewRandomAccessFile", "fname", fname);
  base::File f = thread_->OpenFileHandle(
      dir_, fname, filesystem::mojom::kFlagRead | filesystem::mojom::kFlagOpen);
  if (!f.IsValid()) {
    *result = nullptr;
    base::File::Error error_code = f.error_details();
    RecordOSError(leveldb_env::kNewRandomAccessFile, error_code);
    return MakeIOError(fname, base::File::ErrorToString(error_code),
                       leveldb_env::kNewRandomAccessFile, error_code);
  }

  *result = new MojoRandomAccessFile(fname, std::move(f), this);
  return Status::OK();
}

Status MojoEnv::NewWritableFile(const std::string& fname,
                                WritableFile** result) {
  TRACE_EVENT1("leveldb", "MojoEnv::NewWritableFile", "fname", fname);
  base::File f =
      thread_->OpenFileHandle(dir_, fname, filesystem::mojom::kCreateAlways |
                                               filesystem::mojom::kFlagWrite);
  if (!f.IsValid()) {
    *result = nullptr;
    RecordOSError(leveldb_env::kNewWritableFile, f.error_details());
    return MakeIOError(fname, "Unable to create writable file",
                       leveldb_env::kNewWritableFile, f.error_details());
  }

  *result = new MojoWritableFile(dir_, fname, std::move(f), thread_, this);
  return Status::OK();
}

Status MojoEnv::NewAppendableFile(const std::string& fname,
                                  WritableFile** result) {
  TRACE_EVENT1("leveldb", "MojoEnv::NewAppendableFile", "fname", fname);
  base::File f =
      thread_->OpenFileHandle(dir_, fname, filesystem::mojom::kFlagOpenAlways |
                                               filesystem::mojom::kFlagAppend);
  if (!f.IsValid()) {
    *result = nullptr;
    RecordOSError(leveldb_env::kNewAppendableFile, f.error_details());
    return MakeIOError(fname, "Unable to create appendable file",
                       leveldb_env::kNewAppendableFile, f.error_details());
  }

  *result = new MojoWritableFile(dir_, fname, std::move(f), thread_, this);
  return Status::OK();
}

bool MojoEnv::FileExists(const std::string& fname) {
  TRACE_EVENT1("leveldb", "MojoEnv::FileExists", "fname", fname);
  return thread_->FileExists(dir_, fname);
}

Status MojoEnv::GetChildren(const std::string& path,
                            std::vector<std::string>* result) {
  TRACE_EVENT1("leveldb", "MojoEnv::GetChildren", "path", path);
  FileError error = thread_->GetChildren(dir_, path, result);
  if (error != FileError::OK)
    RecordFileError(leveldb_env::kGetChildren, error);
  return FilesystemErrorToStatus(error, path, leveldb_env::kGetChildren);
}

Status MojoEnv::DeleteFile(const std::string& fname) {
  TRACE_EVENT1("leveldb", "MojoEnv::DeleteFile", "fname", fname);
  FileError error = thread_->Delete(dir_, fname, 0);
  if (error != FileError::OK)
    RecordFileError(leveldb_env::kDeleteFile, error);
  return FilesystemErrorToStatus(error, fname, leveldb_env::kDeleteFile);
}

Status MojoEnv::CreateDir(const std::string& dirname) {
  TRACE_EVENT1("leveldb", "MojoEnv::CreateDir", "dirname", dirname);
  Retrier retrier(leveldb_env::kCreateDir, this);
  FileError error;
  do {
    error = thread_->CreateDir(dir_, dirname);
  } while (error != FileError::OK && retrier.ShouldKeepTrying(error));
  if (error != FileError::OK)
    RecordFileError(leveldb_env::kCreateDir, error);
  return FilesystemErrorToStatus(error, dirname, leveldb_env::kCreateDir);
}

Status MojoEnv::DeleteDir(const std::string& dirname) {
  TRACE_EVENT1("leveldb", "MojoEnv::DeleteDir", "dirname", dirname);
  FileError error =
      thread_->Delete(dir_, dirname, filesystem::mojom::kDeleteFlagRecursive);
  if (error != FileError::OK)
    RecordFileError(leveldb_env::kDeleteDir, error);
  return FilesystemErrorToStatus(error, dirname, leveldb_env::kDeleteDir);
}

Status MojoEnv::GetFileSize(const std::string& fname, uint64_t* file_size) {
  TRACE_EVENT1("leveldb", "MojoEnv::GetFileSize", "fname", fname);
  FileError error = thread_->GetFileSize(dir_, fname, file_size);
  if (error != FileError::OK)
    RecordFileError(leveldb_env::kGetFileSize, error);
  return FilesystemErrorToStatus(error, fname, leveldb_env::kGetFileSize);
}

Status MojoEnv::RenameFile(const std::string& src, const std::string& target) {
  TRACE_EVENT2("leveldb", "MojoEnv::RenameFile", "src", src, "target", target);
  if (!thread_->FileExists(dir_, src))
    return Status::OK();
  Retrier retrier(leveldb_env::kRenameFile, this);
  FileError error;
  do {
    error = thread_->RenameFile(dir_, src, target);
  } while (error != FileError::OK && retrier.ShouldKeepTrying(error));
  if (error != FileError::OK)
    RecordFileError(leveldb_env::kRenameFile, error);
  return FilesystemErrorToStatus(error, src, leveldb_env::kRenameFile);
}

Status MojoEnv::LockFile(const std::string& fname, FileLock** lock) {
  TRACE_EVENT1("leveldb", "MojoEnv::LockFile", "fname", fname);

  Retrier retrier(leveldb_env::kLockFile, this);
  std::pair<FileError, LevelDBMojoProxy::OpaqueLock*> p;
  do {
    p = thread_->LockFile(dir_, fname);
  } while (p.first != FileError::OK && retrier.ShouldKeepTrying(p.first));

  if (p.first != FileError::OK)
    RecordFileError(leveldb_env::kLockFile, p.first);

  if (p.second)
    *lock = new MojoFileLock(p.second, fname);

  return FilesystemErrorToStatus(p.first, fname, leveldb_env::kLockFile);
}

Status MojoEnv::UnlockFile(FileLock* lock) {
  MojoFileLock* my_lock = reinterpret_cast<MojoFileLock*>(lock);

  std::string fname = my_lock ? my_lock->name() : "(invalid)";
  TRACE_EVENT1("leveldb", "MojoEnv::UnlockFile", "fname", fname);

  FileError error = thread_->UnlockFile(my_lock->TakeLock());
  if (error != FileError::OK)
    RecordFileError(leveldb_env::kUnlockFile, error);
  delete my_lock;
  return FilesystemErrorToStatus(error, fname, leveldb_env::kUnlockFile);
}

Status MojoEnv::GetTestDirectory(std::string* path) {
  // TODO(erg): This method is actually only used from the test harness in
  // leveldb. And when we go and port that test stuff to a
  // service_manager::ServiceTest,
  // we probably won't use it since the mojo filesystem actually handles
  // temporary filesystems just fine.
  NOTREACHED();
  return Status::OK();
}

Status MojoEnv::NewLogger(const std::string& fname, Logger** result) {
  TRACE_EVENT1("leveldb", "MojoEnv::NewLogger", "fname", fname);
  base::File f(thread_->OpenFileHandle(
      dir_, fname,
      filesystem::mojom::kCreateAlways | filesystem::mojom::kFlagWrite));
  if (!f.IsValid()) {
    *result = nullptr;
    RecordOSError(leveldb_env::kNewLogger, f.error_details());
    return MakeIOError(fname, "Unable to create log file",
                       leveldb_env::kNewLogger, f.error_details());
  }
  *result = new leveldb::ChromiumLogger(std::move(f));
  return Status::OK();
}

uint64_t MojoEnv::NowMicros() {
  return base::TimeTicks::Now().ToInternalValue();
}

void MojoEnv::SleepForMicroseconds(int micros) {
  // Round up to the next millisecond.
  base::PlatformThread::Sleep(base::TimeDelta::FromMicroseconds(micros));
}

void MojoEnv::Schedule(void (*function)(void* arg), void* arg) {
  base::PostTaskWithTraits(FROM_HERE,
                           {base::MayBlock(), base::WithBaseSyncPrimitives(),
                            base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
                           base::Bind(function, arg));
}

void MojoEnv::StartThread(void (*function)(void* arg), void* arg) {
  new Thread(function, arg);  // Will self-delete.
}

void MojoEnv::RecordErrorAt(leveldb_env::MethodID method) const {
  UMA_HISTOGRAM_ENUMERATION("MojoLevelDBEnv.IOError", method,
                            leveldb_env::kNumEntries);
}

void MojoEnv::RecordOSError(leveldb_env::MethodID method,
                            base::File::Error error) const {
  RecordErrorAt(method);
  std::string uma_name =
      std::string("MojoLevelDBEnv.IOError.BFE.") + MethodIDToString(method);
  base::UmaHistogramExactLinear(uma_name, -error, -base::File::FILE_ERROR_MAX);
}

void MojoEnv::RecordBytesRead(int amount) const {
  UMA_HISTOGRAM_COUNTS_10M("Storage.BytesRead.MojoLevelDBEnv", amount);
}

void MojoEnv::RecordBytesWritten(int amount) const {
  UMA_HISTOGRAM_COUNTS_10M("Storage.BytesWritten.MojoLevelDBEnv", amount);
}

int MojoEnv::MaxRetryTimeMillis() const {
  return 1000;
}

void MojoEnv::RecordRetryTime(leveldb_env::MethodID method,
                              base::TimeDelta time) const {
  std::string uma_name = std::string("MojoLevelDBEnv.TimeUntilSuccessFor") +
                         MethodIDToString(method);
  UmaHistogramCustomTimes(uma_name, time, base::TimeDelta::FromMilliseconds(1),
                          base::TimeDelta::FromMilliseconds(1001), 42);
}

void MojoEnv::RecordRecoveredFromError(leveldb_env::MethodID method,
                                       base::File::Error error) const {
  std::string uma_name =
      std::string("MojoLevelDBEnv.RetryRecoveredFromErrorIn") +
      MethodIDToString(method);
  base::UmaHistogramExactLinear(uma_name, -error, -base::File::FILE_ERROR_MAX);
}

void MojoEnv::RecordFileError(leveldb_env::MethodID method,
                              FileError error) const {
  RecordOSError(method, static_cast<base::File::Error>(error));
}

}  // namespace leveldb
