// 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 <stdint.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/ref_counted_memory.h"
#include "base/memory/scoped_refptr.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_number_conversions.h"
#include "base/strings/string_view_util.h"
#include "base/time/time.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/client.h"
#include "components/persistent_cache/metrics_util.h"
#include "components/persistent_cache/sqlite/vfs_util.h"
#include "components/persistent_cache/transaction_error.h"
#include "components/sqlite_vfs/client.h"
#include "components/sqlite_vfs/lock_state.h"
#include "components/sqlite_vfs/pending_file_set.h"
#include "components/sqlite_vfs/sandboxed_file.h"
#include "components/sqlite_vfs/sqlite_sandboxed_vfs.h"
#include "components/sqlite_vfs/vfs_utils.h"
#include "sql/database.h"
#include "sql/statement.h"
#include "sql/streaming_blob_handle.h"
#include "sql/transaction.h"

namespace persistent_cache {

namespace {

sql::Database::Tag TagFromClient(Client client) {
  switch (client) {
    case Client::kCodeCache:
      return sql::Database::Tag("CodeCache");
    case Client::kShaderCache:
      return sql::Database::Tag("ShaderCache");
    case Client::kTest:
      return sql::Database::Tag("Test");
  }
}

}  // namespace

// static
base::expected<std::unique_ptr<Backend>, TransactionError>
SqliteBackendImpl::Bind(PendingBackend pending_backend, Client client) {
  const auto access_rights =
      pending_backend.pending_file_set.read_write
          ? sqlite_vfs::SandboxedFile::AccessRights::kReadWrite
          : sqlite_vfs::SandboxedFile::AccessRights::kReadOnly;

  auto file_set = sqlite_vfs::SqliteVfsFileSet::Bind(
      VfsClientFromClient(client), std::move(pending_backend.pending_file_set));
  if (!file_set.has_value()) {
    // `pending_backend.pending_file_set` was consumed, but failed to produce a
    // SqliteVfsFileSet. This is typically a failure to map the shared locks
    // into this process's address space. There is no need to delete the files.
    return base::unexpected(TransactionError::kConnectionError);
  }
  auto instance =
      base::WrapUnique(new SqliteBackendImpl(*std::move(file_set), client));

  base::ElapsedTimer timer;
  RETURN_IF_ERROR(instance->Initialize());

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

SqliteBackendImpl::SqliteBackendImpl(sqlite_vfs::SqliteVfsFileSet vfs_file_set,
                                     Client client)
    : database_path_(vfs_file_set.GetDbVirtualFilePath()),
      vfs_file_set_(std::move(vfs_file_set)),
      unregister_runner_(sqlite_vfs::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 as indicated.
              .set_wal_mode(vfs_file_set_.wal_mode())
              .set_vfs_name_discouraged(
                  sqlite_vfs::SqliteSandboxedVfsDelegate::kSqliteVfsName)
              // Prevent SQLite from trying to use mmap, as SandboxedVfs does
              // not currently support this.
              .set_mmap_enabled(false),
          TagFromClient(client)) {}

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

base::expected<void, TransactionError> SqliteBackendImpl::Initialize() {
  TRACE_EVENT("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);

  RETURN_IF_ERROR(InitializeImpl(),
                  [](int error_code) { return TranslateError(error_code); });

  return base::ok();
}

base::expected<void, int> SqliteBackendImpl::InitializeImpl() {
  if (!db_->Open(database_path_)) {
    return base::unexpected(db_->GetErrorCode());
  }

  // Check the user-version (https://sqlite.org/pragma.html#pragma_user_version)
  // to see if there has been a schema change since the last time this database
  // was modified.
  int detected_user_version;
  if (sql::Statement get_user_version_stm(
          db_->GetUniqueStatement("PRAGMA user_version"));
      get_user_version_stm.is_valid() && get_user_version_stm.Step()) {
    detected_user_version = get_user_version_stm.ColumnInt(0);
  } else {
    return base::unexpected(db_->GetErrorCode());
  }

  if (detected_user_version == kCurrentUserVersion) {
    return base::ok();
  }

  // A read only connection cannot do anything to recover from a mismatched
  // user version.
  if (IsReadOnly()) {
    return base::unexpected(SQLITE_READONLY);
  }

  // This is either a new database (user-version has never been set) or was last
  // written with an old schema. Recreate the table with the current schema and
  // update the user-version.

  // Begin an explicit transaction so that creating the table and
  // setting the associated user version is done atomically.
  sql::Transaction transaction(&*db_);
  if (!transaction.Begin()) {
    return base::unexpected(db_->GetErrorCode());
  }

  if (!db_->Execute("DROP TABLE IF EXISTS entries")) {
    return base::unexpected(db_->GetErrorCode());
  }

  // IMPORTANT: Revise the DROP TABLE statement above if more than the one
  // "entries" table is created here.
  if (!db_->Execute("CREATE TABLE entries(key BLOB PRIMARY KEY "
                    "UNIQUE NOT NULL, content BLOB NOT NULL,"
                    " input_signature INTEGER, write_timestamp INTEGER)")) {
    return base::unexpected(db_->GetErrorCode());
  }

  if (!db_->Execute(
          base::StrCat({"PRAGMA user_version=",
                        base::NumberToString(kCurrentUserVersion)}))) {
    return base::unexpected(db_->GetErrorCode());
  }

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

  return base::ok();
}

base::expected<std::optional<EntryMetadata>, TransactionError>
SqliteBackendImpl::Find(base::span<const uint8_t> key,
                        BufferProvider buffer_provider) {
  base::AutoLock lock(lock_, base::subtle::LockTracking::kEnabled);
  CHECK_GT(key.size(), 0ull);
  TRACE_EVENT("persistent_cache", "Find");

  ASSIGN_OR_RETURN(auto metadata, FindImpl(key, buffer_provider),
                   [](int error_code) {
                     return TranslateError(error_code);
                   });
  return metadata;
}

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

  CHECK_GT(key.size(), 0ull);
  TRACE_EVENT("persistent_cache", "Insert");

  // The caller should not specify a write timestamp.
  CHECK_EQ(metadata.write_timestamp, 0);

  RETURN_IF_ERROR(InsertImpl(key, content, metadata.input_signature),
                  [](int 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(
    base::span<const uint8_t> 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(
      db_->GetCachedStatement(SQL_FROM_HERE,
                              "SELECT rowid, input_signature, write_timestamp "
                              "FROM entries WHERE key = ?"));
  if (!stm.is_valid()) {
    return base::unexpected(db_->GetErrorCode());
  }

  stm.BindBlob(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.ColumnTime(2).ToDeltaSinceWindowsEpoch().InMicroseconds()};
    }
  }

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

base::expected<void, int> SqliteBackendImpl::InsertImpl(
    base::span<const uint8_t> key,
    base::span<const uint8_t> content,
    int64_t input_signature) {
  if (sql::Statement stm(db_->GetCachedStatement(
          SQL_FROM_HERE,
          "REPLACE INTO entries (key, content, input_signature, "
          "write_timestamp) VALUES (?, ?, ?, ?)"));
      stm.is_valid()) {
    stm.BindBlob(0, key);
    // SAFETY: SQLite reads from `content` while in scope. Internally,
    // sql::Statement clears its bindings upon destruction, guaranteeing it
    // cannot hold a dangling reference once this block ends.
    stm.BindBlob(1,
                 base::MakeRefCounted<base::RefCountedStaticMemory>(content));
    stm.BindInt64(2, input_signature);
    stm.BindTime(3, base::Time::Now());
    if (stm.Run()) {
      return base::ok();
    }
  }
  return base::unexpected(db_->GetErrorCode());
}

// static
TransactionError SqliteBackendImpl::TranslateError(int error_code) {
  // Handle extended result codes directly.
  if (error_code == SQLITE_IOERR_LOCK) {
    // Lock abandonment.
    return TransactionError::kConnectionError;
  }

  // Narrow the error down to its primary result code.
  switch (error_code & 0xFF) {
    case SQLITE_BUSY:
    case SQLITE_FULL:
    case SQLITE_INTERRUPT:
    case SQLITE_NOMEM:
      return TransactionError::kTransient;

    case SQLITE_CANTOPEN:
    case SQLITE_READONLY:  // Cannot modify a read-only database.
      // This also includes SQLITE_READONLY_ROLLBACK, which can happen if a
      // read-only connection is the first to discover that a hot journal needs
      // to be rolled back.
      return TransactionError::kConnectionError;

    case SQLITE_ERROR:
    case SQLITE_CORRUPT:
    case SQLITE_IOERR:
    case SQLITE_NOTADB:
      // The underlying file cannot be trusted. The best course of action is for
      // the owner to close the connection and delete the underlying files.
      return TransactionError::kPermanent;
  }

  // Remaining errors are considered transient. The Sql.Database.Statement.Error
  // metrics 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());
  switch (vfs_file_set_.Abandon()) {
    case sqlite_vfs::LockState::kNotHeld:
      return LockState::kNotHeld;
    case sqlite_vfs::LockState::kReading:
      return LockState::kReading;
    case sqlite_vfs::LockState::kWriting:
      return LockState::kWriting;
  }
}

}  // namespace persistent_cache
