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

#include "components/persistent_cache/sqlite/sqlite_backend_impl.h"

#include <memory>
#include <optional>
#include <tuple>
#include <utility>

#include "base/check_op.h"
#include "base/containers/span.h"
#include "base/memory/ptr_util.h"
#include "base/memory/unsafe_shared_memory_region.h"
#include "base/metrics/histogram_functions.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/strcat.h"
#include "base/strings/string_view_util.h"
#include "base/timer/elapsed_timer.h"
#include "base/trace_event/trace_event.h"
#include "base/types/expected.h"
#include "base/types/expected_macros.h"
#include "components/persistent_cache/backend_type.h"
#include "components/persistent_cache/pending_backend.h"
#include "components/persistent_cache/sqlite/vfs/sandboxed_file.h"
#include "components/persistent_cache/sqlite/vfs/sqlite_sandboxed_vfs.h"
#include "components/persistent_cache/transaction_error.h"
#include "sql/database.h"
#include "sql/statement.h"
#include "sql/transaction.h"

namespace {

std::string GetFullHistogramName(std::string_view name, bool read_write) {
  return base::StrCat({"PersistentCache.", name, ".SQLite",
                       (read_write ? ".ReadWrite" : ".ReadOnly")});
}

}  // namespace

namespace persistent_cache {

// static
std::optional<SqliteVfsFileSet> SqliteBackendImpl::BindToFileSet(
    PendingBackend pending_backend) {
  // Write-ahead logging requires single connection.
  CHECK(!pending_backend.sqlite_data.wal_file.IsValid() ||
        !pending_backend.sqlite_data.shared_lock.IsValid());
  // Write-ahead logging requires read-write access.
  CHECK(!pending_backend.sqlite_data.wal_file.IsValid() ||
        pending_backend.read_write);

  base::WritableSharedMemoryMapping mapped_shared_lock;
  if (pending_backend.sqlite_data.shared_lock.IsValid()) {
    mapped_shared_lock = pending_backend.sqlite_data.shared_lock.Map();
    if (!mapped_shared_lock.IsValid()) {
      return std::nullopt;  // Failed to map the shared lock.
    }
  }

  const auto access_rights = pending_backend.read_write
                                 ? SandboxedFile::AccessRights::kReadWrite
                                 : SandboxedFile::AccessRights::kReadOnly;

  auto db_file = std::make_unique<SandboxedFile>(
      std::move(pending_backend.sqlite_data.db_file), access_rights,
      std::move(mapped_shared_lock));
  auto journal_file = std::make_unique<SandboxedFile>(
      std::move(pending_backend.sqlite_data.journal_file), access_rights);
  std::unique_ptr<SandboxedFile> wal_file;
  if (pending_backend.sqlite_data.wal_file.IsValid()) {
    wal_file = std::make_unique<SandboxedFile>(
        std::move(pending_backend.sqlite_data.wal_file), access_rights);
  }

  return SqliteVfsFileSet(std::move(db_file), std::move(journal_file),
                          std::move(wal_file),
                          std::move(pending_backend.sqlite_data.shared_lock));
}

// static
std::unique_ptr<Backend> SqliteBackendImpl::Bind(
    PendingBackend pending_backend) {
  const auto access_rights = pending_backend.read_write
                                 ? SandboxedFile::AccessRights::kReadWrite
                                 : SandboxedFile::AccessRights::kReadOnly;

  auto file_set = BindToFileSet(std::move(pending_backend));
  if (!file_set.has_value()) {
    return nullptr;
  }

  auto instance = base::WrapUnique(new SqliteBackendImpl(*std::move(file_set)));

  base::ElapsedTimer timer;
  if (!instance->Initialize()) {
    return nullptr;
  }

  base::UmaHistogramMicrosecondsTimes(
      GetFullHistogramName(
          "BackendInitialize",
          access_rights == SandboxedFile::AccessRights::kReadWrite),
      timer.Elapsed());
  return instance;
}

SqliteBackendImpl::SqliteBackendImpl(SqliteVfsFileSet vfs_file_set)
    : database_path_(vfs_file_set.GetDbVirtualFilePath()),
      vfs_file_set_(std::move(vfs_file_set)),
      unregister_runner_(
          SqliteSandboxedVfsDelegate::GetInstance()->RegisterSandboxedFiles(
              vfs_file_set_)),
      db_(std::in_place,
          sql::DatabaseOptions()
              .set_read_only(vfs_file_set_.read_only())
              // Set the database's locking_mode to EXCLUSIVE if the file set
              // supports only a single connection to the database.
              .set_exclusive_locking(vfs_file_set_.is_single_connection())
              // Enable write-ahead logging if such a file is provided.
              .set_wal_mode(vfs_file_set_.wal_journal_mode())
              .set_vfs_name_discouraged(
                  SqliteSandboxedVfsDelegate::kSqliteVfsName)
              // Prevent SQLite from trying to use mmap, as SandboxedVfs does
              // not currently support this.
              .set_mmap_enabled(false),
          sql::Database::Tag("PersistentCache")) {}

SqliteBackendImpl::~SqliteBackendImpl() {
  base::AutoLock lock(lock_, base::subtle::LockTracking::kEnabled);
  db_.reset();
}

bool SqliteBackendImpl::Initialize() {
  TRACE_EVENT0("persistent_cache", "initialize");

  // Open  `db_` under `lock_` with lock tracking enabled. This allows this
  // class to be usable from multiple threads even though `sql::Database` is
  // sequence bound.
  base::AutoLock lock(lock_, base::subtle::LockTracking::kEnabled);

  if (!db_->Open(database_path_)) {
    TRACE_EVENT_INSTANT1("persistent_cache", "open_failed",
                         TRACE_EVENT_SCOPE_THREAD, "error_code",
                         db_->GetErrorCode());
    return false;
  }

  if (!db_->Execute(
          "CREATE TABLE IF NOT EXISTS entries(key TEXT PRIMARY KEY UNIQUE NOT "
          "NULL, content BLOB NOT NULL, input_signature INTEGER, "
          "write_timestamp INTEGER)")) {
    TRACE_EVENT_INSTANT1("persistent_cache", "create_failed",
                         TRACE_EVENT_SCOPE_THREAD, "error_code",
                         db_->GetErrorCode());
    return false;
  }

  return true;
}

base::expected<std::optional<EntryMetadata>, TransactionError>
SqliteBackendImpl::Find(std::string_view key, BufferProvider buffer_provider) {
  base::AutoLock lock(lock_, base::subtle::LockTracking::kEnabled);
  CHECK_GT(key.length(), 0ull);
  TRACE_EVENT0("persistent_cache", "Find");

  ASSIGN_OR_RETURN(auto metadata, FindImpl(key, buffer_provider),
                   [](int error_code) {
                     TRACE_EVENT_INSTANT1("persistent_cache", "find_failed",
                                          TRACE_EVENT_SCOPE_THREAD,
                                          "error_code", error_code);
                     return TranslateError(error_code);
                   });
  return metadata;
}

base::expected<void, TransactionError> SqliteBackendImpl::Insert(
    std::string_view key,
    base::span<const uint8_t> content,
    EntryMetadata metadata) {
  base::AutoLock lock(lock_, base::subtle::LockTracking::kEnabled);

  CHECK_GT(key.length(), 0ull);
  TRACE_EVENT0("persistent_cache", "insert");

  CHECK_EQ(metadata.write_timestamp, 0)
      << "Write timestamp is generated by SQLite so it should not be specified "
         "manually";

  RETURN_IF_ERROR(InsertImpl(key, content, std::move(metadata)),
                  [](int error_code) {
                    TRACE_EVENT_INSTANT1("persistent_cache", "insert_failed",
                                         TRACE_EVENT_SCOPE_THREAD, "error_code",
                                         error_code);
                    return TranslateError(error_code);
                  });

  return base::ok();
}

base::expected<void, int> SqliteBackendImpl::ExecuteStatementForTesting(
    base::cstring_view statement) {
  base::AutoLock lock(lock_, base::subtle::LockTracking::kEnabled);

  if (!db_->Execute(statement)) {
    return base::unexpected(db_->GetErrorCode());
  }

  return base::ok();
}

base::expected<std::optional<EntryMetadata>, int> SqliteBackendImpl::FindImpl(
    std::string_view key,
    BufferProvider buffer_provider) {
  // Begin an explicit read transaction under which multiple statements will be
  // used to read from the database if the database may have multiple
  // connections. A transaction is not necessary if the database is opened for a
  // single connection, as it is not possible for another connection to modify
  // the database between the statements below.
  std::optional<sql::Transaction> transaction;
  if (!vfs_file_set_.is_single_connection() &&
      !transaction.emplace(&*db_).Begin()) {
    return base::unexpected(db_->GetErrorCode());
  }

  // Read the rowid and metadata.
  sql::Statement stm = sql::Statement(
      db_->GetCachedStatement(SQL_FROM_HERE,
                              "SELECT rowid, input_signature, write_timestamp "
                              "FROM entries WHERE key = ?"));
  DCHECK(stm.is_valid());

  stm.BindString(0, key);

  if (!stm.Step()) {
    if (stm.Succeeded()) {
      // Cache miss. Do not run `buffer_provider`, return no value.
      return std::nullopt;
    }
    // Error stepping.
    return base::unexpected(db_->GetErrorCode());
  }

  // Open a handle to get the size of the content.
  if (auto blob =
          db_->GetStreamingBlob("entries", "content", stm.ColumnInt64(0),
                                /*readonly=*/true);
      blob.has_value()) {
    bool succeeded = true;
    size_t content_size = base::checked_cast<size_t>(blob->GetSize());
    // Get a buffer from the caller.
    if (base::span<uint8_t> content_buffer = buffer_provider(content_size);
        !content_buffer.empty()) {
      CHECK_EQ(content_buffer.size(), content_size);
      // Copy the content from the database directly into the caller's buffer.
      succeeded = blob->Read(/*offset=*/0, content_buffer);
    }
    if (succeeded) {
      return EntryMetadata{.input_signature = stm.ColumnInt64(1),
                           .write_timestamp = stm.ColumnInt64(2)};
    }
  }

  return base::unexpected(db_->GetErrorCode());
}

base::expected<void, int> SqliteBackendImpl::InsertImpl(
    std::string_view key,
    base::span<const uint8_t> content,
    EntryMetadata metadata) {
  // Use a transaction for insertions if the database may have multiple
  // connections so that the creation of the row and the writing of the data are
  // a single atomic operation. A transaction is not necessary if the database
  // is opened for a single connection, as it is not possible for another
  // connection to access or modify the database between the statements below.
  std::optional<sql::Transaction> transaction;
  if (!vfs_file_set_.is_single_connection() &&
      !transaction.emplace(&*db_).Begin()) {
    return base::unexpected(db_->GetErrorCode());
  }

  sql::Statement stm(db_->GetCachedStatement(
      SQL_FROM_HERE,
      "REPLACE INTO entries (key, content, input_signature, write_timestamp) "
      "VALUES (?, ?, ?, strftime(\'%s\', \'now\'))"));

  stm.BindString(0, key);
  stm.BindBlobForStreaming(1, content.size());
  stm.BindInt64(2, metadata.input_signature);

  DCHECK(stm.is_valid());
  if (!stm.Run()) {
    return base::unexpected(db_->GetErrorCode());
  }

  const auto row_id = db_->GetLastInsertRowId();
  if (auto blob_handle = db_->GetStreamingBlob("entries", "content", row_id,
                                               /*readonly=*/false);
      !blob_handle.has_value() || !blob_handle->Write(0, content)) {
    return base::unexpected(db_->GetErrorCode());
  }

  if (transaction && !transaction->Commit()) {
    return base::unexpected(db_->GetErrorCode());
  }

  return base::ok();
}

// static
TransactionError SqliteBackendImpl::TranslateError(int error_code) {
  switch (error_code) {
    case SQLITE_BUSY:
    case SQLITE_NOMEM:
      return TransactionError::kTransient;
    case SQLITE_CANTOPEN:
    case SQLITE_IOERR_LOCK:  // Lock abandonment.
      return TransactionError::kConnectionError;
    case SQLITE_ERROR:
    case SQLITE_CORRUPT:
    case SQLITE_FULL:
    case SQLITE_IOERR_FSTAT:
    case SQLITE_IOERR_FSYNC:
    case SQLITE_IOERR_READ:
    case SQLITE_IOERR_WRITE:
      return TransactionError::kPermanent;
  }

  // Remaining errors are treasted as transient.
  // `Sql.Database.Statement.Error.PersistentCache` should be monitored to
  // ensure that there are no surprising permanent errors wrongly handled here
  // as this will mean unusable databases that keep being used.
  return TransactionError::kTransient;
}

BackendType SqliteBackendImpl::GetType() const {
  return BackendType::kSqlite;
}

bool SqliteBackendImpl::IsReadOnly() const {
  return vfs_file_set_.read_only();
}

LockState SqliteBackendImpl::Abandon() {
  // Read only instances do not have the privilege of abandoning an instance.
  CHECK(!IsReadOnly());
  return vfs_file_set_.Abandon();
}

}  // namespace persistent_cache
