// 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 "net/disk_cache/sql/sql_backend_impl.h"

#include <algorithm>
#include <type_traits>
#include <utility>
#include <vector>

#include "base/barrier_callback.h"
#include "base/barrier_closure.h"
#include "base/byte_size.h"
#include "base/containers/flat_set.h"
#include "base/containers/span.h"
#include "base/feature_list.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_functions.h"
#include "base/notimplemented.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/bind_post_task.h"
#include "base/task/task_runner.h"
#include "base/task/thread_pool.h"
#include "base/trace_event/trace_event.h"
#include "base/types/expected.h"
#include "components/performance_manager/scenario_api/performance_scenarios.h"
#include "net/base/features.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/disk_cache/cache_util.h"
#include "net/disk_cache/sql/sql_async_task_token.h"
#include "net/disk_cache/sql/sql_entry_impl.h"
#include "net/disk_cache/sql/sql_persistent_store.h"
#include "sql_backend_constants.h"

namespace disk_cache {
namespace {

using FakeIndexFileError = SqlBackendImpl::FakeIndexFileError;

size_t GetShardCount() {
  return std::max(std::min(net::features::kSqlDiskCacheShardCount.Get(), 255),
                  1);
}

// Checks the fake index file, creating it if it doesn't exist. Returns an
// error code if the file is corrupted or cannot be created.
FakeIndexFileError CheckFakeIndexFileInternal(const base::FilePath& path) {
  base::FieldTrial* backend_field_trial = base::FeatureList::GetFieldTrial(
      net::features::kDiskCacheBackendExperiment);
  const std::string expected_contents = base::StrCat(
      {kSqlBackendFakeIndexPrefix, base::NumberToString(GetShardCount()),
       backend_field_trial ? backend_field_trial->group_name() : ""});
  const base::FilePath file_path = path.Append(kSqlBackendFakeIndexFileName);
  const std::optional<int64_t> file_size = base::GetFileSize(file_path);
  if (file_size.has_value()) {
    if (file_size != expected_contents.size()) {
      return FakeIndexFileError::kWrongFileSize;
    }
    base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
    if (!file.IsValid()) {
      return FakeIndexFileError::kOpenFileFailed;
    }
    std::vector<uint8_t> contents(expected_contents.size());
    if (!file.ReadAndCheck(0, contents)) {
      return FakeIndexFileError::kReadFileFailed;
    }
    if (base::span(contents) != base::span(expected_contents)) {
      return FakeIndexFileError::kWrongMagicNumber;
    }
    return FakeIndexFileError::kOkExisting;
  }
  if (!base::DirectoryExists(path) && !base::CreateDirectory(path)) {
    return FakeIndexFileError::kFailedToCreateDirectory;
  }
  base::File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
  if (!file.IsValid()) {
    return FakeIndexFileError::kCreateFileFailed;
  }
  if (!file.WriteAndCheck(0, base::as_byte_span(expected_contents))) {
    return FakeIndexFileError::kWriteFileFailed;
  }
  return FakeIndexFileError::kOkNew;
}

// Checks the fake index file and records a histogram of the result.
bool CheckFakeIndexFile(const base::FilePath& path) {
  FakeIndexFileError error = CheckFakeIndexFileInternal(path);
  base::UmaHistogramEnumeration("Net.SqlDiskCache.FakeIndexFileError", error);
  return error == FakeIndexFileError::kOkNew ||
         error == FakeIndexFileError::kOkExisting;
}

// Checks if the browser is still idle. This is called within ShouldRunEviction.
// The purpose of this is to prevent operations from running if the browser is
// no longer idle in the time between SqlBackendImpl::OnBrowserIdle() being
// called and the actual processing.
bool IsBrowserIdle() {
  return performance_scenarios::CurrentScenariosMatch(
      performance_scenarios::ScenarioScope::kGlobal,
      performance_scenarios::kDefaultIdleScenarios);
}

// Determines whether cache eviction should run based on the urgency and timing.
// Eviction is triggered under three conditions:
// 1. Not needed: Eviction is skipped.
// 2. Idle time: Eviction runs only if it's an idle-time task and the browser
//    is currently idle.
// 3. Needed: Eviction runs immediately, regardless of browser state.
bool ShouldRunEviction(SqlPersistentStore::EvictionUrgency eviction_urgency,
                       bool is_idle_time_eviction) {
  switch (eviction_urgency) {
    case SqlPersistentStore::EvictionUrgency::kNotNeeded:
      return false;
    case SqlPersistentStore::EvictionUrgency::kIdleTime:
      return is_idle_time_eviction && IsBrowserIdle();
    case SqlPersistentStore::EvictionUrgency::kNeeded:
      return true;
  }
}

// Wraps a OnceCallback. If the returned callback is destroyed without being
// run, the original callback is run with `abort_result`.
// This ensures that the callback is always run, even if the operation is
// cancelled or the owner is destroyed.
template <typename ResultType>
base::OnceCallback<void(ResultType)> WrapCallbackWithAbortError(
    base::OnceCallback<void(ResultType)> callback,
    ResultType abort_result) {
  CHECK(callback);
  auto [success_cb, failure_cb] = base::SplitOnceCallback(std::move(callback));

  // The ScopedClosureRunner will run the `failure_cb` with `abort_result` if
  // it's destroyed before being released.
  auto runner = std::make_unique<base::ScopedClosureRunner>(
      base::BindPostTaskToCurrentDefault(
          base::BindOnce(std::move(failure_cb), abort_result)));

  // The returned callback represents the "success" path.
  return base::BindOnce(
      [](std::unique_ptr<base::ScopedClosureRunner> runner,
         base::OnceCallback<void(ResultType)> cb, ResultType result) {
        // Release the runner to prevent the failure callback from running on
        // destruction.
        std::ignore = runner->Release();
        // Run the success callback with the provided result.
        std::move(cb).Run(std::move(result));
      },
      std::move(runner), std::move(success_cb));
}

// A helper to handle methods that may complete synchronously.
//
// This allows a caller to dispatch an async operation and immediately check if
// it completed synchronously. If so, the result is returned directly. If not,
// a provided callback is invoked later.
template <typename T, typename R = std::decay_t<T>>
class SyncResultReceiver : public base::RefCounted<SyncResultReceiver<T>> {
 public:
  using ResultCallback = base::OnceCallback<void(T)>;

  explicit SyncResultReceiver(ResultCallback callback)
      : callback_(std::move(callback)) {}

  ~SyncResultReceiver() {
    // As a contract, FinishSyncCall() must be called. If it's not, it's a
    // bug in the calling code.
    CHECK(sync_call_finished_);
  }

  SyncResultReceiver(const SyncResultReceiver&) = delete;
  SyncResultReceiver& operator=(const SyncResultReceiver&) = delete;

  // Returns a callback to pass to the async operation.
  ResultCallback GetCallback() {
    return base::BindOnce(&SyncResultReceiver::OnResult, this);
  }

  // Checks for a synchronous result. If the operation already completed,
  // returns the result. Otherwise, returns nullopt and the original callback
  // will be run asynchronously.
  std::optional<R> FinishSyncCall() {
    sync_call_finished_ = true;
    if (result_) {
      callback_.Reset();
      return std::move(result_);
    }
    return std::nullopt;
  }

 private:
  // Receives the result from the async operation.
  void OnResult(T result) {
    if (sync_call_finished_) {
      // The caller is already waiting for the async result.
      if (callback_) {
        std::move(callback_).Run(std::move(result));
      }
    } else {
      // The result arrived synchronously. Store it for FinishSyncCall.
      result_ = std::move(result);
    }
  }

  // The original callback, to be run on async completion.
  ResultCallback callback_;
  // Holds the result if it arrives synchronously.
  std::optional<R> result_;
  // Set to true when FinishSyncCall is called.
  bool sync_call_finished_ = false;
};

// Creates a `base::OnceClosure` that takes ownership of `args`. When the
// closure is run, the `args` are destroyed. This is typically used with
// `base::OnceCallback::Then()` to ensure the handle is released only after the
// primary callback has finished.
template <typename... Args>
base::OnceClosure OnceClosureWithBoundArgs(Args&&... args) {
  return base::OnceClosure(
      base::DoNothingWithBoundArgs(std::forward<Args>(args)...));
}

std::vector<scoped_refptr<base::SequencedTaskRunner>> CreateTaskRunners() {
  const size_t shard_count = GetShardCount();
  std::vector<scoped_refptr<base::SequencedTaskRunner>> runners;
  runners.reserve(shard_count);
  for (size_t i = 0; i < shard_count; ++i) {
    runners.push_back(base::ThreadPool::CreateSequencedTaskRunner(
        {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
         base::TaskShutdownBehavior::BLOCK_SHUTDOWN}));
  }
  return runners;
}

// Creates a callback to update `db_handle`.
base::OnceCallback<
    SqlPersistentStore::ResIdOrError(SqlPersistentStore::ResIdOrError)>
MakeUpdateDbHandleCallback(const scoped_refptr<EntryDbHandle>& db_handle) {
  return base::BindOnce(
      [](const scoped_refptr<EntryDbHandle>& db_handle,
         SqlPersistentStore::ResIdOrError result) {
        if (result.has_value()) {
          if (!db_handle->IsFinished()) {
            db_handle->MarkAsCreated(*result);
          }
        } else {
          db_handle->MarkAsErrorOccurred(result.error());
        }
        return result;
      },
      db_handle);
}

// Creates a utility callback to convert ResIdOrError to an int net error.
// `ok_result` is used when the passed ResIdOrError contains a ResId.
base::OnceCallback<int(SqlPersistentStore::ResIdOrError)>
MakeResIdOrErrorToIntCallback(int ok_result) {
  return base::BindOnce(
      [](int ok_result, SqlPersistentStore::ResIdOrError result) -> int {
        return result.has_value() ? ok_result : net::ERR_FAILED;
      },
      ok_result);
}

}  // namespace

// IteratorImpl provides an implementation of Backend::Iterator for the
// SqlBackendImpl. It allows iterating through cache entries stored in the
// SQLite database. Iteration is performed in reverse `res_id` order (from
// newest to oldest entry in the database).
class SqlBackendImpl::IteratorImpl : public Backend::Iterator {
 public:
  explicit IteratorImpl(base::WeakPtr<SqlBackendImpl> backend)
      : backend_(backend) {}
  ~IteratorImpl() override = default;
  EntryResult OpenNextEntry(EntryResultCallback callback) override {
    CHECK(!callback_);
    if (!backend_) {
      return EntryResult::MakeError(net::ERR_FAILED);
    }
    callback_ = std::move(callback);
    // Schedule `DoOpenNextEntry` as an exclusive operation to ensure that
    // iteration does not conflict with other backend-wide operations (e.g.,
    // mass deletion).
    backend_->exclusive_operation_coordinator_.PostOrRunExclusiveOperation(
        base::BindOnce(&IteratorImpl::DoOpenNextEntry,
                       weak_factory_.GetWeakPtr()));
    return EntryResult::MakeError(net::ERR_IO_PENDING);
  }

 private:
  // Performs the actual logic for opening the next entry. This method is
  // executed when it's its turn in the exclusive operation queue.
  void DoOpenNextEntry(
      std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
    if (!backend_) {
      std::move(callback_).Run(EntryResult::MakeError(net::ERR_FAILED));
      // `handle` is destroyed here, but `backend_` is null, so it's a no-op.
      return;
    }
    // Request the next entry from the persistent store. `entry_iterator_` keeps
    // track of the last entry returned, allowing the store to fetch the next
    // entry.
    // `handle` will be destroyed after executing`OnOpenNextEntryFinished()`,
    // may be triggering queued operations.
    backend_->store_->OpenNextEntry(
        entry_iterator_,
        base::BindOnce(&IteratorImpl::OnOpenNextEntryFinished,
                       weak_factory_.GetWeakPtr())
            .Then(OnceClosureWithBoundArgs(std::move(handle))));
  }

  // Callback for `SqlPersistentStore::OpenNextEntry`.
  void OnOpenNextEntryFinished(
      SqlPersistentStore::OptionalEntryInfoWithKeyAndIterator result) {
    CHECK(callback_);
    if (!backend_) {
      std::move(callback_).Run(EntryResult::MakeError(net::ERR_FAILED));
      return;
    }
    // If no more entries are found or an error occurred in the store.
    if (!result.has_value()) {
      std::move(callback_).Run(EntryResult::MakeError(net::ERR_FAILED));
      return;
    }
    SqlPersistentStore::EntryInfoWithKeyAndIterator& entry_info = *result;

    // Update the `entry_iterator_` to the `iterator` of the result, so the next
    // call to `OpenNextEntry` starts from here.
    entry_iterator_ = entry_info.iterator;

    // Check if the entry is already active in `active_entries_`. If so,
    // reuse the existing `SqlEntryImpl` instance.
    if (SqlEntryImpl* entry = backend_->GetActiveEntry(entry_info.key)) {
      entry->AddRef();
      std::move(callback_).Run(EntryResult::MakeOpened(entry));
      return;
    }

    // This DCHECK ensures that an entry returned by the store for iteration
    // is not already in the `doomed_entries_` set. This invariant is
    // maintained because iterator operations are "exclusive" and dooming
    // operations are "normal", and the `ExclusiveOperationCoordinator`
    // ensures they do not run concurrently. If a doom operation runs first,
    // the entry is marked as doomed in the database and `OpenNextEntry` will
    // not return it. If the iterator operation runs first, any subsequent doom
    // operation will be queued until the iteration step is complete.
    DCHECK(std::none_of(backend_->doomed_entries_.begin(),
                        backend_->doomed_entries_.end(),
                        [&](const raw_ref<const SqlEntryImpl>& doomed_entry) {
                          const auto optional_res_id =
                              doomed_entry.get().db_handle()->GetResId();
                          return optional_res_id.has_value() &&
                                 backend_->store_->GetShardIdForHash(
                                     doomed_entry.get().cache_key().hash()) ==
                                     backend_->store_->GetShardIdForHash(
                                         entry_info.key.hash()) &&
                                 *optional_res_id == entry_info.info.res_id;
                        }));

    // Apply any in-flight modifications (e.g., last_used time updates, header
    // changes) that were queued for this entry while it was not active.
    backend_->ApplyInFlightEntryModifications(entry_info.key, entry_info.info);

    // If the entry is not active, create a new `SqlEntryImpl`.
    scoped_refptr<SqlEntryImpl> new_entry = base::MakeRefCounted<SqlEntryImpl>(
        backend_, entry_info.key,
        base::MakeRefCounted<EntryDbHandle>(entry_info.info.res_id),
        entry_info.info.last_used, entry_info.info.body_end,
        entry_info.info.head);
    new_entry->AddRef();
    CHECK(backend_->active_entries_
              .insert(std::make_pair(entry_info.key,
                                     raw_ref<SqlEntryImpl>(*new_entry.get())))
              .second);

    // Return the newly opened entry.
    std::move(callback_).Run(EntryResult::MakeOpened(new_entry.get()));
  }

  base::WeakPtr<SqlBackendImpl> backend_;
  // The `entry_iterator` of the last entry returned by the iterator. Used to
  // fetch the next entry in subsequent calls.
  SqlPersistentStore::EntryIterator entry_iterator_;
  EntryResultCallback callback_;
  base::WeakPtrFactory<IteratorImpl> weak_factory_{this};
};

SqlBackendImpl::SqlBackendImpl(const base::FilePath& path,
                               int64_t max_bytes,
                               net::CacheType cache_type)
    : Backend(cache_type),
      path_(path),
      background_task_runners_(CreateTaskRunners()),
      store_(std::make_unique<SqlPersistentStore>(path,
                                                  max_bytes > 0 ? max_bytes : 0,
                                                  GetCacheType(),
                                                  background_task_runners_,
                                                  async_task_manager_)),
      optimistic_write_buffer_monitor_(
          net::features::kSqlDiskCacheOptimisticWriteBufferSize.Get()),
      write_buffer_monitor_(
          net::features::kSqlDiskCacheMaxWriteBufferTotalSize.Get()) {
  DVLOG(1) << "SqlBackendImpl::SqlBackendImpl " << path;
}

SqlBackendImpl::~SqlBackendImpl() = default;

void SqlBackendImpl::Init(CompletionOnceCallback callback) {
  if (net::features::kSqlDiskCacheSerialInitialize.Get()) {
    base::ThreadPool::PostTaskAndReplyWithResult(
        FROM_HERE,
        {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
         base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
        base::BindOnce(&CheckFakeIndexFile, path_),
        base::BindOnce(&SqlBackendImpl::OnCheckFakeIndexFileFinished,
                       weak_factory_.GetWeakPtr(),
                       std::move(callback).Then(OnceClosureWithBoundArgs(
                           async_task_manager_.StartTask())),
                       base::ElapsedTimer()));
    return;
  }
  auto barrier_callback = base::BarrierCallback<bool>(
      2,
      base::BindOnce(&SqlBackendImpl::OnInitialized, weak_factory_.GetWeakPtr(),
                     std::move(callback), base::ElapsedTimer()));

  store_->Initialize(base::BindOnce([](SqlPersistentStore::Error result) {
                       return result == SqlPersistentStore::Error::kOk;
                     }).Then(barrier_callback));

  base::ThreadPool::PostTaskAndReplyWithResult(
      FROM_HERE,
      {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
       base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
      base::BindOnce(&CheckFakeIndexFile, path_),
      base::OnceCallback<void(bool)>(barrier_callback)
          .Then(OnceClosureWithBoundArgs(async_task_manager_.StartTask())));
}

void SqlBackendImpl::OnCheckFakeIndexFileFinished(
    CompletionOnceCallback callback,
    base::ElapsedTimer init_start_time,
    bool success) {
  if (!success) {
    OnInitialized(std::move(callback), init_start_time, {false});
    return;
  }
  store_->Initialize(base::BindOnce(&SqlBackendImpl::OnStoreInitialized,
                                    weak_factory_.GetWeakPtr(),
                                    std::move(callback), init_start_time));
}

void SqlBackendImpl::OnStoreInitialized(CompletionOnceCallback callback,
                                        base::ElapsedTimer init_start_time,
                                        SqlPersistentStore::Error error) {
  OnInitialized(std::move(callback), init_start_time,
                {error == SqlPersistentStore::Error::kOk});
}

void SqlBackendImpl::OnInitialized(CompletionOnceCallback callback,
                                   base::ElapsedTimer init_start_time,
                                   const std::vector<bool>& results) {
  CHECK_EQ(results.size(),
           net::features::kSqlDiskCacheSerialInitialize.Get() ? 1u : 2u);
  const bool success = std::all_of(results.begin(), results.end(),
                                   [](bool result) { return result; });
  base::UmaHistogramMicrosecondsTimes(
      base::StrCat(
          {"Net.SqlDiskCache.Init.", success ? "Success" : "Failure", "Time"}),
      init_start_time.Elapsed());

  if (success) {
    // Schedule a one-time task to load in-memory index and clean up doomed
    // entries from previous sessions. This runs after a delay to avoid
    // impacting startup performance. This is especially important for Android
    // WebView where Performance Scenario Detection doesn't work. See
    // https://crbug.com/456009994 for more details.
    // Note: Intentionally do not pass a SqlAsyncTaskToken to this
    // PostDelayedTask. This allows tests (e.g.
    // SqlBackendImplTest.DelayedPostInitializationTasks) to verify that the
    // index is not loaded until this task runs when
    // SqlDiskCacheLoadIndexOnInit is false.
    base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&SqlBackendImpl::RunDelayedPostInitializationTasks,
                       weak_factory_.GetWeakPtr()),
        kSqlBackendPostInitializationTasksDelay);
  }
  std::move(callback).Run(success ? net::OK : net::ERR_FAILED);
}

void SqlBackendImpl::RunDelayedPostInitializationTasks() {
  store_->MaybeLoadInMemoryIndex(base::BindOnce(
      [](base::WeakPtr<SqlBackendImpl> self, SqlPersistentStore::Error result) {
        if (self && result == SqlPersistentStore::Error::kOk) {
          self->store_->MaybeRunCleanupDoomedEntries(base::DoNothing());
        }
      },
      weak_factory_.GetWeakPtr()));
}

int64_t SqlBackendImpl::MaxFileSize() const {
  // Delegates to the persistent store to get the max file size.
  return store_->MaxFileSize();
}

base::expected<int32_t, net::Error> SqlBackendImpl::GetEntryCount(
    GetEntryCountCallback callback) const {
  // Flush buffers so that the GetEntryCountAsync call can see entries not yet
  // written to the DB.
  FlushActiveEntriesBuffers();
  // The entry count must be retrieved asynchronously to ensure that all
  // pending database operations are reflected in the result.
  store_->GetEntryCountAsync(std::move(callback));
  return base::unexpected(net::ERR_IO_PENDING);
}

void SqlBackendImpl::SetMaxBytes(base::ByteSize max_bytes) {
  store_->SetMaxSize(base::checked_cast<int64_t>(max_bytes.InBytes()));
  MaybeTriggerEviction(/*is_idle_time_eviction=*/false);
}

base::ByteSize SqlBackendImpl::GetMaxBytesForTesting() const {
  return base::ByteSize(base::checked_cast<uint64_t>(store_->MaxSize()));
}

EntryResult SqlBackendImpl::OpenOrCreateEntry(const std::string& key,
                                              net::RequestPriority priority,
                                              EntryResultCallback callback) {
  return OpenOrCreateEntryInternal(
      OpenOrCreateEntryOperationType::kOpenOrCreateEntry, key,
      std::move(callback));
}

EntryResult SqlBackendImpl::OpenEntry(const std::string& key,
                                      net::RequestPriority priority,
                                      EntryResultCallback callback) {
  return OpenOrCreateEntryInternal(OpenOrCreateEntryOperationType::kOpenEntry,
                                   key, std::move(callback));
}

EntryResult SqlBackendImpl::CreateEntry(const std::string& key,
                                        net::RequestPriority priority,
                                        EntryResultCallback callback) {
  return OpenOrCreateEntryInternal(OpenOrCreateEntryOperationType::kCreateEntry,
                                   key, std::move(callback));
}

EntryResult SqlBackendImpl::OpenOrCreateEntryInternal(
    OpenOrCreateEntryOperationType type,
    const std::string& key,
    EntryResultCallback callback) {
  const CacheEntryKey entry_key(key);
  auto sync_result_receiver =
      base::MakeRefCounted<SyncResultReceiver<EntryResult>>(
          std::move(callback));
  exclusive_operation_coordinator_.PostOrRunNormalOperation(
      entry_key,
      base::BindOnce(&SqlBackendImpl::HandleOpenOrCreateEntryOperation,
                     weak_factory_.GetWeakPtr(), type, entry_key,
                     sync_result_receiver->GetCallback()));
  auto sync_result = sync_result_receiver->FinishSyncCall();
  return sync_result ? std::move(*sync_result)
                     : EntryResult::MakeError(net::ERR_IO_PENDING);
}

void SqlBackendImpl::HandleOpenOrCreateEntryOperation(
    OpenOrCreateEntryOperationType type,
    const CacheEntryKey& entry_key,
    EntryResultCallback callback,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
  if (SqlEntryImpl* entry = GetActiveEntry(entry_key)) {
    if (type == OpenOrCreateEntryOperationType::kCreateEntry) {
      std::move(callback).Run(EntryResult::MakeError(net::ERR_FAILED));
    } else {
      entry->AddRef();
      std::move(callback).Run(EntryResult::MakeOpened(entry));
    }
    return;
  }

  if (store_->GetIndexStateForHash(entry_key.hash()) ==
      SqlPersistentStore::IndexState::kHashNotFound) {
    if (type == OpenOrCreateEntryOperationType::kOpenEntry) {
      std::move(callback).Run(EntryResult::MakeError(net::ERR_FAILED));
      return;
    }
    std::move(callback).Run(
        SpeculativeCreateEntry(entry_key, std::move(handle)));
    return;
  }

  switch (type) {
    case OpenOrCreateEntryOperationType::kOpenOrCreateEntry:
      store_->OpenOrCreateEntry(
          entry_key, base::BindOnce(&SqlBackendImpl::OnEntryOperationFinished,
                                    base::Unretained(this), entry_key,
                                    std::move(callback), std::move(handle)));
      break;
    case OpenOrCreateEntryOperationType::kOpenEntry:
      store_->OpenEntry(
          entry_key,
          base::BindOnce(&SqlBackendImpl::OnOptionalEntryOperationFinished,
                         base::Unretained(this), entry_key, std::move(callback),
                         std::move(handle)));
      break;
    case OpenOrCreateEntryOperationType::kCreateEntry:
      store_->CreateEntry(
          entry_key, base::Time::Now(),
          base::BindOnce(&SqlBackendImpl::OnEntryOperationFinished,
                         base::Unretained(this), entry_key, std::move(callback),
                         std::move(handle)));
      break;
  }
}

SqlEntryImpl* SqlBackendImpl::GetActiveEntry(const CacheEntryKey& key) {
  if (auto it = active_entries_.find(key); it != active_entries_.end()) {
    // Return a pointer to the SqlEntryImpl if found.
    return &it->second.get();
  }
  return nullptr;
}

void SqlBackendImpl::FlushActiveEntriesBuffers() const {
  for (const auto& it : active_entries_) {
    it.second->FlushBuffer(/*force_flush_for_creation=*/true);
  }
}

void SqlBackendImpl::DoomActiveEntry(SqlEntryImpl& entry) {
  exclusive_operation_coordinator_.PostOrRunNormalOperation(
      entry.cache_key(),
      base::BindOnce(&SqlBackendImpl::HandleDoomActiveEntryOperation,
                     weak_factory_.GetWeakPtr(),
                     scoped_refptr<SqlEntryImpl>(&entry)));
}

void SqlBackendImpl::HandleDoomActiveEntryOperation(
    scoped_refptr<SqlEntryImpl> entry,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
  if (entry->doomed()) {
    return;
  }
  DoomActiveEntryInternal(*entry,
                          base::DoNothingWithBoundArgs(std::move(handle)));
}

void SqlBackendImpl::DoomActiveEntryInternal(SqlEntryImpl& entry,
                                             CompletionOnceCallback callback) {
  const auto& db_handle = entry.db_handle();

  // Mark the entry as doomed internally.
  db_handle->MarkAsDoomed();
  // Move it from the active_entries_ map to the doomed_entries_ set.
  ReleaseActiveEntry(entry);
  doomed_entries_.emplace(entry);

  if (db_handle->IsInitialState() || db_handle->IsCreatingState()) {
    // If the entry hasn't been written to the DB (IsInitialState()), no further
    // processing is needed.
    // If the entry is being created (IsCreatingState()) by
    // WriteEntryDataAndMetadata() or WriteEntryData(), a new entry will be
    // written to the DB with doomed=true.
    std::move(callback).Run(net::OK);
    return;
  }

  if (db_handle->GetError().has_value()) {
    // Fail the operation for entries that previously failed a speculative
    // creation or optimistic write.
    std::move(callback).Run(net::ERR_FAILED);
    return;
  }
  // Ask the store to mark the entry as doomed in the database.
  store_->DoomEntry(
      entry.cache_key(), *db_handle->GetResId(),
      /*accept_index_mismatch=*/false,
      base::BindOnce(
          [](base::WeakPtr<SqlBackendImpl> weak_ptr,
             CompletionOnceCallback callback, SqlPersistentStore::Error error) {
            // Do not call the `callback` if the backend has been destroyed.
            // This is safe for both backend-initiated and entry-initiated
            // dooms:
            // - For backend operations (e.g., `DoomEntry`), the provided
            //   callback should be cancelled if the backend is gone.
            // - For entry operations (`SqlEntryImpl::Doom`), the callback is a
            //   `base::DoNothing()`, so cancelling it has no effect.
            if (weak_ptr) {
              // Return net::OK even if the entry is not found. This matches
              // the behavior of SimpleCache. This is tested by
              // BackendFailedOpenThenMultipleDoomsNonExistentEntry in
              // DiskCacheGenericBackendTest.
              std::move(callback).Run(net::OK);
            }
          },
          weak_factory_.GetWeakPtr(), std::move(callback)));
}

net::Error SqlBackendImpl::DoomEntry(const std::string& key,
                                     net::RequestPriority priority,
                                     CompletionOnceCallback callback) {
  const CacheEntryKey entry_key(key);

  auto sync_result_receiver =
      base::MakeRefCounted<SyncResultReceiver<int>>(std::move(callback));
  exclusive_operation_coordinator_.PostOrRunNormalOperation(
      entry_key, base::BindOnce(&SqlBackendImpl::HandleDoomEntryOperation,
                                weak_factory_.GetWeakPtr(), entry_key, priority,
                                sync_result_receiver->GetCallback()));
  auto sync_result = sync_result_receiver->FinishSyncCall();
  return sync_result ? static_cast<net::Error>(std::move(*sync_result))
                     : net::ERR_IO_PENDING;
}

void SqlBackendImpl::HandleDoomEntryOperation(
    const CacheEntryKey& key,
    net::RequestPriority priority,
    CompletionOnceCallback callback,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
  // If the entry is currently active, doom it directly.
  if (auto* active_entry = GetActiveEntry(key)) {
    DoomActiveEntryInternal(*active_entry, std::move(callback));
    // The handle for this operation is released upon returning, allowing the
    // next queued operation to run.
    return;
  }

  // Convert store error to net error. kNotFound is considered a success for
  // dooming (idempotency).
  auto store_callback = base::BindOnce(
      [](CompletionOnceCallback callback, SqlPersistentStore::Error result) {
        std::move(callback).Run((result == SqlPersistentStore::Error::kOk ||
                                 result == SqlPersistentStore::Error::kNotFound)
                                    ? net::OK
                                    : net::ERR_FAILED);
      },
      std::move(callback));

  // If there is a unique entry in the in-memory index, call DoomEntry using its
  // res_id.
  if (auto res_id = store_->TryGetSingleResIdFromInMemoryIndex(key.hash())) {
    store_->DoomEntry(key, *res_id, /*accept_index_mismatch=*/false,
                      std::move(store_callback));
    // The handle for this operation is released upon returning, allowing the
    // next queued operation to run.
    return;
  }

  // If the entry is not active and a single entry could not be found in the
  // in-memory index, we can directly ask the store to delete the "live" (not
  // yet doomed) entry from the database.
  store_->DeleteLiveEntry(
      key, std::move(store_callback)
               .Then(OnceClosureWithBoundArgs(std::move(handle))));
}

net::Error SqlBackendImpl::DoomAllEntries(CompletionOnceCallback callback) {
  // DoomAllEntries is a special case of DoomEntriesBetween with an unbounded
  // time range.
  return DoomEntriesBetween(base::Time::Min(), base::Time::Max(),
                            std::move(callback));
}

net::Error SqlBackendImpl::DoomEntriesBetween(base::Time initial_time,
                                              base::Time end_time,
                                              CompletionOnceCallback callback) {
  exclusive_operation_coordinator_.PostOrRunExclusiveOperation(base::BindOnce(
      &SqlBackendImpl::HandleDoomEntriesBetweenOperation,
      weak_factory_.GetWeakPtr(), initial_time, end_time, std::move(callback)));
  return net::ERR_IO_PENDING;
}

void SqlBackendImpl::HandleDoomEntriesBetweenOperation(
    base::Time initial_time,
    base::Time end_time,
    CompletionOnceCallback callback,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
  if (initial_time.is_null()) {
    // If initial_time is null, use the minimum possible time.
    initial_time = base::Time::Min();
  }
  if (end_time.is_null()) {
    // If end_time is null, use the maximum possible time.
    end_time = base::Time::Max();
  }

  // Optimization: If dooming all entries (min to max time) and there are no
  // active, doomed, or pending entries, we can directly ask the store to
  // delete all entries, which is more efficient.
  if (initial_time.is_min() && end_time.is_max() && active_entries_.empty() &&
      doomed_entries_.empty()) {
    // Ask the store to delete all entries from the database.
    store_->DeleteAllEntries(
        base::BindOnce(
            [](CompletionOnceCallback callback,
               SqlPersistentStore::Error result) {
              std::move(callback).Run(result == SqlPersistentStore::Error::kOk
                                          ? net::OK
                                          : net::ERR_FAILED);
            },
            std::move(callback))
            .Then(OnceClosureWithBoundArgs(std::move(handle))));
    return;
  }

  // Collect Ids of active entries to exclude them from the store's
  // DeleteLiveEntriesBetween operation, as they will be handled by dooming them
  // directly within this method.
  std::vector<SqlPersistentStore::ResIdAndShardId> excluded_list;
  excluded_list.reserve(active_entries_.size());
  std::vector<SqlEntryImpl*> active_entries_to_be_doomed;
  for (auto& it : active_entries_) {
    const auto optional_res_id = it.second->db_handle()->GetResId();
    if (optional_res_id.has_value()) {
      excluded_list.emplace_back(*optional_res_id,
                                 store_->GetShardIdForHash(it.first.hash()));
    }
    // Check if the active entry falls within the specified time range.
    const base::Time last_used_time = it.second->GetLastUsed();
    if (last_used_time >= initial_time && last_used_time < end_time) {
      active_entries_to_be_doomed.push_back(&it.second.get());
    }
  }

  auto barrier_callback = base::BarrierCallback<int>(
      active_entries_to_be_doomed.size() +  // For active entries being doomed
          1,  // For store's DeleteLiveEntriesBetween
      base::BindOnce(
          // This final callback is run after all individual doom operations
          // complete.
          [](base::WeakPtr<SqlBackendImpl> weak_ptr,
             CompletionOnceCallback callback, const std::vector<int>& result) {
            if (weak_ptr) {
              std::move(callback).Run(net::OK);
            }
          },
          weak_factory_.GetWeakPtr(), std::move(callback))
          .Then(OnceClosureWithBoundArgs(std::move(handle))));

  // Doom active entries that fall within the time range.
  for (auto* entry : active_entries_to_be_doomed) {
    DoomActiveEntryInternal(*entry, barrier_callback);
  }


  // Ask the store to delete all other "live" (not doomed, not active, not
  // pending) entries within the specified time range, excluding those already
  // handled.
  store_->DeleteLiveEntriesBetween(
      initial_time, end_time, std::move(excluded_list),
      base::BindOnce(
          [](CompletionOnceCallback callback,
             SqlPersistentStore::Error result) {
            std::move(callback).Run(result == SqlPersistentStore::Error::kOk
                                        ? net::OK
                                        : net::ERR_FAILED);
          },
          std::move(barrier_callback)));
}

net::Error SqlBackendImpl::DoomEntriesSince(base::Time initial_time,
                                            CompletionOnceCallback callback) {
  // DoomEntriesSince is a special case of DoomEntriesBetween with end_time set
  // to the maximum possible time.
  return DoomEntriesBetween(initial_time, base::Time::Max(),
                            std::move(callback));
}

int64_t SqlBackendImpl::CalculateSizeOfAllEntries(
    Int64CompletionOnceCallback callback) {
  return CalculateSizeOfEntriesBetween(base::Time::Min(), base::Time::Max(),
                                       std::move(callback));
}

int64_t SqlBackendImpl::CalculateSizeOfEntriesBetween(
    base::Time initial_time,
    base::Time end_time,
    Int64CompletionOnceCallback callback) {
  // Flush buffers so that the CalculateSizeOfEntriesBetween call can see
  // entries not yet written to the DB.
  FlushActiveEntriesBuffers();

  exclusive_operation_coordinator_.PostOrRunExclusiveOperation(base::BindOnce(
      &SqlBackendImpl::HandleCalculateSizeOfEntriesBetweenOperation,
      weak_factory_.GetWeakPtr(), initial_time, end_time, std::move(callback)));
  return net::ERR_IO_PENDING;
}

void SqlBackendImpl::HandleCalculateSizeOfEntriesBetweenOperation(
    base::Time initial_time,
    base::Time end_time,
    Int64CompletionOnceCallback callback,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
  store_->CalculateSizeOfEntriesBetween(
      initial_time, end_time,
      base::BindOnce(
          [](base::WeakPtr<SqlBackendImpl> weak_ptr,
             Int64CompletionOnceCallback callback,
             std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle>
                 handle,
             SqlPersistentStore::Int64OrError result) {
            if (weak_ptr) {
              std::move(callback).Run(result.has_value() ? result.value()
                                                         : net::ERR_FAILED);
            }
          },
          weak_factory_.GetWeakPtr(), std::move(callback), std::move(handle)));
}

std::unique_ptr<Backend::Iterator> SqlBackendImpl::CreateIterator() {
  // Flush buffers so that the Iterator can see entries not yet written to the
  // DB.
  FlushActiveEntriesBuffers();
  return std::make_unique<IteratorImpl>(weak_factory_.GetWeakPtr());
}

void SqlBackendImpl::GetStats(base::StringPairs* stats) {
  stats->emplace_back(std::make_pair("Cache type", "SQL Cache"));
  // TODO(crbug.com/422065015): Write more stats.
}

void SqlBackendImpl::OnExternalCacheHit(const std::string& key) {
  const CacheEntryKey entry_key(key);
  if (auto it = active_entries_.find(entry_key); it != active_entries_.end()) {
    it->second->UpdateLastUsed();
    return;
  }
  const base::Time now = base::Time::Now();
  exclusive_operation_coordinator_.PostOrRunNormalOperation(
      entry_key,
      base::BindOnce(&SqlBackendImpl::HandleOnExternalCacheHitOperation,
                     weak_factory_.GetWeakPtr(), entry_key, now,
                     PushInFlightEntryModification(
                         entry_key, InFlightEntryModification(nullptr, now))));
}

void SqlBackendImpl::HandleOnExternalCacheHitOperation(
    const CacheEntryKey& key,
    base::Time now,
    PopInFlightEntryModificationRunner pop_in_flight_entry_modification,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
  store_->UpdateEntryLastUsedByKey(
      key, now,
      base::BindOnce([](SqlPersistentStore::Error error) {})
          .Then(OnceClosureWithBoundArgs(
              std::move(pop_in_flight_entry_modification)))
          .Then(OnceClosureWithBoundArgs(std::move(handle))));
}

uint8_t SqlBackendImpl::GetEntryInMemoryData(const std::string& key) {
  const auto cache_key = CacheEntryKey(key);
  // Since hint information for speculatively created entries not yet written to
  // the DB is not saved in `store_`, check the hint information of the
  // corresponding active entry first.
  if (auto* entry = GetActiveEntry(cache_key)) {
    if (auto new_hints = entry->new_hints()) {
      return new_hints->value();
    }
  }

  // If GetEntryInMemoryData is called immediately after a speculatively created
  // entry with hints is doomed, the information is not yet in the `store_`'s
  // in-memory index, so check `in_flight_entry_modifications_`.
  std::optional<MemoryEntryDataHints> hints;
  if (auto it = in_flight_entry_modifications_.find(cache_key);
      it != in_flight_entry_modifications_.end()) {
    for (const auto& modification : it->second) {
      if (modification.hints.has_value()) {
        hints = modification.hints;
      }
    }
  }
  if (hints) {
    return hints->value();
  }
  return store_->GetInMemoryEntryDataHints(cache_key.hash())
      .value_or(MemoryEntryDataHints(0))
      .value();
}

void SqlBackendImpl::OnBrowserIdle() {
  store_->MaybeLoadInMemoryIndex(base::DoNothing());
  store_->MaybeRunCleanupDoomedEntries(base::DoNothing());
  store_->MaybeRunCheckpoint(base::DoNothing());
  store_->MaybeRunIncrementalVacuum(
      exclusive_operation_coordinator_.GetHasPendingTaskFlag(),
      base::DoNothing());
  MaybeTriggerEviction(/*is_idle_time_eviction=*/true);
}

void SqlBackendImpl::OnOptionalEntryOperationFinished(
    const CacheEntryKey& key,
    EntryResultCallback callback,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle,
    SqlPersistentStore::OptionalEntryInfoOrError result) {
  // If the store operation failed or the entry was not found (for OpenEntry).
  if (!result.has_value() || !result->has_value()) {
    std::move(callback).Run(EntryResult::MakeError(net::ERR_FAILED));
    return;
  }

  SqlPersistentStore::EntryInfo& entry_info = *(*result);
  ApplyInFlightEntryModifications(key, entry_info);

  // Create a new SqlEntryImpl instance.
  scoped_refptr<SqlEntryImpl> new_entry = base::MakeRefCounted<SqlEntryImpl>(
      weak_factory_.GetWeakPtr(), key,
      base::MakeRefCounted<EntryDbHandle>(entry_info.res_id),
      entry_info.last_used, entry_info.body_end, entry_info.head);

  // Add a reference for passing to the `callback`.
  new_entry->AddRef();
  // Add the new entry to the active_entries_ map.
  auto insert_result = active_entries_.insert(
      std::make_pair(key, raw_ref<SqlEntryImpl>(*new_entry.get())));
  CHECK(insert_result.second);

  // Run the original callback with the newly created/opened entry.
  std::move(callback).Run((*result)->opened
                              ? EntryResult::MakeOpened(new_entry.get())
                              : EntryResult::MakeCreated(new_entry.get()));

  MaybeTriggerEviction(/*is_idle_time_eviction=*/false);
}

void SqlBackendImpl::OnEntryOperationFinished(
    const CacheEntryKey& key,
    EntryResultCallback callback,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle,
    SqlPersistentStore::EntryInfoOrError result) {
  // This is a helper to adapt EntryInfoOrError to
  // OnOptionalEntryOperationFinished which expects OptionalEntryInfoOrError.
  if (result.has_value()) {
    OnOptionalEntryOperationFinished(key, std::move(callback),
                                     std::move(handle), std::move(*result));
  } else {
    OnOptionalEntryOperationFinished(key, std::move(callback),
                                     std::move(handle),
                                     base::unexpected(result.error()));
  }
}

EntryResult SqlBackendImpl::SpeculativeCreateEntry(
    const CacheEntryKey& entry_key,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
  auto db_handle = base::MakeRefCounted<EntryDbHandle>();
  const auto creation_time = base::Time::Now();

  // Create a new SqlEntryImpl instance.
  scoped_refptr<SqlEntryImpl> new_entry = base::MakeRefCounted<SqlEntryImpl>(
      weak_factory_.GetWeakPtr(), entry_key, std::move(db_handle),
      creation_time, /*body_end=*/0,
      /*head=*/nullptr);

  // Add a reference for passing to the `callback`.
  new_entry->AddRef();
  // Add the new entry to the active_entries_ map.
  auto insert_result = active_entries_.insert(
      std::make_pair(entry_key, raw_ref<SqlEntryImpl>(*new_entry.get())));
  CHECK(insert_result.second);

  return EntryResult::MakeCreated(new_entry.get());
}

void SqlBackendImpl::ReleaseActiveEntry(SqlEntryImpl& entry) {
  auto it = active_entries_.find(entry.cache_key());
  // The entry must exist in the active_entries_ map.
  CHECK(it != active_entries_.end());
  CHECK_EQ(&it->second.get(), &entry);
  active_entries_.erase(it);
}

void SqlBackendImpl::ReleaseDoomedEntry(SqlEntryImpl& entry) {
  auto it = doomed_entries_.find(entry);
  // The entry must exist in the doomed_entries_ set.
  CHECK(it != doomed_entries_.end());
  doomed_entries_.erase(it);
  exclusive_operation_coordinator_.PostOrRunNormalOperation(
      entry.cache_key(),
      base::BindOnce(&SqlBackendImpl::HandleDeleteDoomedEntry,
                     weak_factory_.GetWeakPtr(), entry.cache_key(),
                     entry.db_handle()));
}

void SqlBackendImpl::HandleDeleteDoomedEntry(
    const CacheEntryKey& key,
    const scoped_refptr<EntryDbHandle>& db_handle,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
  if (db_handle->IsInitialState()) {
    // If the entry hasn't been written to the DB, no further processing is
    // needed.
    return;
  }
  CHECK(db_handle->IsFinished());
  if (db_handle->GetError().has_value()) {
    // Fail the operation for entries that previously failed a speculative
    // creation or optimistic write.
    return;
  }
  store_->DeleteDoomedEntry(
      key, *db_handle->GetResId(),
      base::BindOnce(
          [](std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle>
                 handle,
             SqlPersistentStore::Error error) {},
          std::move(handle)));
}

void SqlBackendImpl::WriteEntryDataAndMetadata(
    const CacheEntryKey& key,
    const scoped_refptr<EntryDbHandle>& db_handle,
    std::optional<int64_t> old_body_end,
    int64_t body_end,
    EntryWriteBuffer buffer,
    base::Time last_used,
    const std::optional<MemoryEntryDataHints>& new_hints,
    scoped_refptr<net::GrowableIOBuffer> head_buffer,
    int64_t header_size_delta,
    CompletionOnceCallback callback) {
  if (db_handle->IsInitialState()) {
    db_handle->MarkAsCreating();
  }
  exclusive_operation_coordinator_.PostOrRunNormalOperation(
      key,
      base::BindOnce(
          &SqlBackendImpl::HandleWriteEntryDataAndMetadataOperation,
          weak_factory_.GetWeakPtr(), key, db_handle, old_body_end,
          std::move(buffer), last_used, new_hints, std::move(head_buffer),
          header_size_delta,
          PushInFlightEntryModification(
              key, InFlightEntryModification(db_handle, last_used, new_hints,
                                             head_buffer, body_end)),
          WrapCallbackWithAbortError<SqlPersistentStore::ResIdOrError>(
              MakeUpdateDbHandleCallback(db_handle)
                  .Then(MakeResIdOrErrorToIntCallback(net::OK))
                  .Then(std::move(callback)),
              base::unexpected(SqlPersistentStore::Error::kAborted))));
}

void SqlBackendImpl::HandleWriteEntryDataAndMetadataOperation(
    const CacheEntryKey& key,
    const scoped_refptr<EntryDbHandle>& db_handle,
    std::optional<int64_t> old_body_end,
    EntryWriteBuffer buffer,
    base::Time last_used,
    const std::optional<MemoryEntryDataHints>& new_hints,
    scoped_refptr<net::GrowableIOBuffer> head_buffer,
    int64_t header_size_delta,
    PopInFlightEntryModificationRunner pop_in_flight_entry_modification,
    SqlPersistentStore::ResIdOrErrorCallback callback,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
  CHECK(!db_handle->IsInitialState());
  if (db_handle->GetError().has_value()) {
    // Fail the operation for entries that previously failed a speculative
    // creation or optimistic write.
    std::move(callback).Run(base::unexpected(*db_handle->GetError()));
    return;
  }
  const auto optional_res_id = db_handle->GetResId();
  store_->WriteEntryDataAndMetadata(
      key, optional_res_id, old_body_end, std::move(buffer), last_used,
      new_hints, std::move(head_buffer), header_size_delta, db_handle->doomed(),
      std::move(callback)
          .Then(OnceClosureWithBoundArgs(
              std::move(pop_in_flight_entry_modification)))
          // Execute MaybeTriggerEviction after completion because the cache
          // size might have increased.
          .Then(base::BindOnce(&SqlBackendImpl::MaybeTriggerEviction,
                               weak_factory_.GetWeakPtr(),
                               /*is_idle_time_eviction=*/false))
          .Then(OnceClosureWithBoundArgs(std::move(handle))));
}

int SqlBackendImpl::WriteEntryData(
    const CacheEntryKey& key,
    const scoped_refptr<EntryDbHandle>& db_handle,
    int64_t old_body_end,
    int64_t body_end,
    EntryWriteBuffer buffer,
    bool truncate,
    base::Time last_used,
    bool sparse_write,
    int64_t header_size,
    bool copy_buffer_for_optimistic_write,
    CompletionOnceCallback callback) {
  if (db_handle->GetError().has_value()) {
    // Fail the operation for entries that previously failed a speculative
    // creation or optimistic write.
    return net::ERR_FAILED;
  }
  if (db_handle->IsInitialState()) {
    db_handle->MarkAsCreating();
  }

  const int buf_len = buffer.size;

  SqlWriteBufferMemoryMonitor::ScopedReservation optimistic_buffer_reservation;
  // Perform optimistic writes as long as `optimistic_write_buffer_monitor_`
  // allows it.
  const bool can_execute_optimistic_write =
      optimistic_write_buffer_monitor_.Allocate(buf_len,
                                                optimistic_buffer_reservation);

  base::UmaHistogramBoolean("Net.SqlDiskCache.Write.IsOptimistic",
                            can_execute_optimistic_write);
  if (can_execute_optimistic_write) {
    if (copy_buffer_for_optimistic_write) {
      CHECK_LE(buffer.buffers.size(), 1u);
      if (buffer.buffers.size() == 1) {
        CHECK(buffer.buffers[0]);
        buffer.buffers[0] = base::MakeRefCounted<net::VectorIOBuffer>(
            buffer.buffers[0]->first(static_cast<size_t>(buf_len)));
      }
    }
    exclusive_operation_coordinator_.PostOrRunNormalOperation(
        key,
        base::BindOnce(
            &SqlBackendImpl::HandleOptimisticWriteEntryDataOperation,
            weak_factory_.GetWeakPtr(), key, db_handle, old_body_end,
            std::move(buffer), truncate, last_used, sparse_write, header_size,
            WrapCallbackWithAbortError<SqlPersistentStore::ResIdOrError>(
                MakeUpdateDbHandleCallback(db_handle)
                    .Then(base::BindOnce(
                        [](SqlPersistentStore::ResIdOrError result) {
                          base::UmaHistogramEnumeration(
                              "Net.SqlDiskCache.OptimisticWrite.Result",
                              result.error_or(SqlPersistentStore::Error::kOk));
                        }))
                    .Then(OnceClosureWithBoundArgs(
                        std::move(optimistic_buffer_reservation))),
                base::unexpected(SqlPersistentStore::Error::kAborted)),
            PushInFlightEntryModification(
                key, InFlightEntryModification(db_handle, body_end))));
    return buf_len;
  }
  auto sync_result_receiver =
      base::MakeRefCounted<SyncResultReceiver<int>>(std::move(callback));
  exclusive_operation_coordinator_.PostOrRunNormalOperation(
      key,
      base::BindOnce(
          &SqlBackendImpl::HandleWriteEntryDataOperation,
          weak_factory_.GetWeakPtr(), key, db_handle, old_body_end,
          std::move(buffer), truncate, last_used, sparse_write, header_size,
          WrapCallbackWithAbortError<SqlPersistentStore::ResIdOrError>(
              MakeUpdateDbHandleCallback(db_handle)
                  .Then(MakeResIdOrErrorToIntCallback(buf_len))
                  .Then(sync_result_receiver->GetCallback()),
              base::unexpected(SqlPersistentStore::Error::kAborted)),
          PushInFlightEntryModification(
              key, InFlightEntryModification(db_handle, body_end))));
  auto sync_result = sync_result_receiver->FinishSyncCall();
  return sync_result ? std::move(*sync_result) : net::ERR_IO_PENDING;
}

void SqlBackendImpl::HandleWriteEntryDataOperation(
    const CacheEntryKey& key,
    const scoped_refptr<EntryDbHandle>& db_handle,
    int64_t old_body_end,
    EntryWriteBuffer buffer,
    bool truncate,
    base::Time last_used,
    bool sparse_write,
    int64_t header_size,
    SqlPersistentStore::ResIdOrErrorCallback callback,
    PopInFlightEntryModificationRunner pop_in_flight_entry_modification,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
  CHECK(!db_handle->IsInitialState());
  if (db_handle->GetError().has_value()) {
    // Fail the operation for entries that previously failed a speculative
    // creation or optimistic write.
    std::move(callback).Run(base::unexpected(*db_handle->GetError()));
    return;
  }
  store_->WriteEntryData(
      key,
      db_handle->GetResId().has_value()
          ? SqlPersistentStore::ResIdOrTime(*db_handle->GetResId())
          : SqlPersistentStore::ResIdOrTime(last_used),
      old_body_end, std::move(buffer), truncate, db_handle->doomed(),
      sparse_write, header_size,
      std::move(callback)
          .Then(OnceClosureWithBoundArgs(
              std::move(pop_in_flight_entry_modification)))
          // Execute MaybeTriggerEviction after completion because the cache
          // size might have increased.
          .Then(base::BindOnce(&SqlBackendImpl::MaybeTriggerEviction,
                               weak_factory_.GetWeakPtr(),
                               /*is_idle_time_eviction=*/false))
          .Then(OnceClosureWithBoundArgs(std::move(handle))));
}

void SqlBackendImpl::HandleOptimisticWriteEntryDataOperation(
    const CacheEntryKey& key,
    const scoped_refptr<EntryDbHandle>& db_handle,
    int64_t old_body_end,
    EntryWriteBuffer buffer,
    bool truncate,
    base::Time last_used,
    bool sparse_write,
    int64_t header_size,
    SqlPersistentStore::ResIdOrErrorCallback callback,
    PopInFlightEntryModificationRunner pop_in_flight_entry_modification,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
  CHECK(!db_handle->IsInitialState());
  if (db_handle->GetError().has_value()) {
    // Fail the operation for entries that previously failed a speculative
    // creation or optimistic write.
    // Need to call `callback` here, otherwise `db_handle` will be set to
    // SqlPersistentStore::Error::kAborted.
    std::move(callback).Run(base::unexpected(*db_handle->GetError()));
    return;
  }
  const auto optional_res_id = db_handle->GetResId();
  store_->WriteEntryData(
      key,
      optional_res_id.has_value()
          ? SqlPersistentStore::ResIdOrTime(*optional_res_id)
          : SqlPersistentStore::ResIdOrTime(last_used),
      old_body_end, std::move(buffer), truncate, db_handle->doomed(),
      sparse_write, header_size,
      base::BindOnce(
          &SqlBackendImpl::OnOptimisticWriteFinished,
          weak_factory_.GetWeakPtr(), key, optional_res_id, std::move(callback),
          std::move(pop_in_flight_entry_modification), std::move(handle)));
}

void SqlBackendImpl::OnOptimisticWriteFinished(
    const CacheEntryKey& key,
    std::optional<SqlPersistentStore::ResId> res_id,
    SqlPersistentStore::ResIdOrErrorCallback callback,
    PopInFlightEntryModificationRunner pop_in_flight_entry_modification,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle,
    SqlPersistentStore::ResIdOrError result) {
  std::move(callback).Run(result);

  // Execute MaybeTriggerEviction because the cache size might have increased.
  MaybeTriggerEviction(/*is_idle_time_eviction=*/false);

  if (result.has_value()) {
    return;
  }
  if (!res_id) {
    // If res_id was nullopt, it means we tried to create the entry lazily.
    // If that failed, there is no entry to doom.
    return;
  }
  // If an optimistic write fails, `maybe_update_db_handle_callback` has
  // set an error value in the entry's `db_handle`. This ensures that all
  // subsequent operations on this entry will also fail.
  // Since the user of the Sql backend can no longer delete the entry from
  // storage, SqlBackendImpl takes responsibility for deleting it.
  // `accept_index_mismatch` is set to true because the entry might have been
  // doomed by a concurrent operation (e.g., if the user called Doom() followed
  // by WriteData() immediately, the Doom operation might execute first). In
  // that case, the entry is already removed from the in-memory index.
  store_->DoomEntry(key, *res_id, /*accept_index_mismatch=*/true,
                    base::DoNothing());
  store_->DeleteDoomedEntry(key, *res_id,
                            base::DoNothingWithBoundArgs(std::move(handle)));
}

int SqlBackendImpl::ReadEntryData(
    const CacheEntryKey& key,
    const scoped_refptr<EntryDbHandle>& db_handle,
    int64_t offset,
    scoped_refptr<net::IOBuffer> buffer,
    int buf_len,
    int64_t body_end,
    bool sparse_reading,
    SqlPersistentStore::ReadResultOrErrorCallback callback) {
  auto sync_result_receiver = base::MakeRefCounted<
      SyncResultReceiver<SqlPersistentStore::ReadResultOrError>>(
      std::move(callback));
  exclusive_operation_coordinator_.PostOrRunNormalOperation(
      key,
      base::BindOnce(
          &SqlBackendImpl::HandleReadEntryDataOperation,
          weak_factory_.GetWeakPtr(), key, db_handle, offset, std::move(buffer),
          buf_len, body_end, sparse_reading,
          WrapCallbackWithAbortError<SqlPersistentStore::ReadResultOrError>(
              sync_result_receiver->GetCallback(),
              base::unexpected(SqlPersistentStore::Error::kAborted))));

  auto sync_result = sync_result_receiver->FinishSyncCall();
  if (sync_result) {
    return sync_result->has_value() ? (*sync_result)->read_bytes
                                    : net::ERR_FAILED;
  }
  return net::ERR_IO_PENDING;
}

void SqlBackendImpl::HandleReadEntryDataOperation(
    const CacheEntryKey& key,
    const scoped_refptr<EntryDbHandle>& db_handle,
    int64_t offset,
    scoped_refptr<net::IOBuffer> buffer,
    int buf_len,
    int64_t body_end,
    bool sparse_reading,
    SqlPersistentStore::ReadResultOrErrorCallback callback,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
  CHECK(db_handle->IsFinished());
  if (db_handle->GetError().has_value()) {
    std::move(callback).Run(base::unexpected(*db_handle->GetError()));
    return;
  }
  store_->ReadEntryData(
      key, *db_handle->GetResId(), offset, buffer, buf_len, body_end,
      sparse_reading,
      std::move(callback).Then(OnceClosureWithBoundArgs(std::move(handle))));
}

RangeResult SqlBackendImpl::GetEntryAvailableRange(
    const CacheEntryKey& key,
    const scoped_refptr<EntryDbHandle>& db_handle,
    int64_t offset,
    int len,
    RangeResultCallback callback) {
  CHECK(!db_handle->IsInitialState());
  auto sync_result_receiver =
      base::MakeRefCounted<SyncResultReceiver<const RangeResult&>>(
          std::move(callback));
  exclusive_operation_coordinator_.PostOrRunNormalOperation(
      key,
      base::BindOnce(&SqlBackendImpl::HandleGetEntryAvailableRangeOperation,
                     weak_factory_.GetWeakPtr(), key, db_handle, offset, len,
                     WrapCallbackWithAbortError<const RangeResult&>(
                         sync_result_receiver->GetCallback(),
                         RangeResult(net::ERR_ABORTED))));
  auto sync_result = sync_result_receiver->FinishSyncCall();
  return sync_result ? std::move(*sync_result)
                     : RangeResult(net::ERR_IO_PENDING);
}

void SqlBackendImpl::HandleGetEntryAvailableRangeOperation(
    const CacheEntryKey& key,
    const scoped_refptr<EntryDbHandle>& db_handle,
    int64_t offset,
    int len,
    RangeResultCallback callback,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
  CHECK(db_handle->IsFinished());
  if (db_handle->GetError().has_value()) {
    // Fail the operation for entries that previously failed a speculative
    // creation or optimistic write.
    std::move(callback).Run(RangeResult(net::ERR_FAILED));
    return;
  }
  store_->GetEntryAvailableRange(key, *db_handle->GetResId(), offset, len,
                                 std::move(callback));
}

void SqlBackendImpl::SetEntryDataHints(
    const CacheEntryKey& key,
    const scoped_refptr<EntryDbHandle>& db_handle,
    MemoryEntryDataHints hints) {
  exclusive_operation_coordinator_.PostOrRunNormalOperation(
      key, base::BindOnce(&SqlBackendImpl::HandleSetEntryDataHintsOperation,
                          weak_factory_.GetWeakPtr(), key, db_handle, hints));
}

void SqlBackendImpl::HandleSetEntryDataHintsOperation(
    const CacheEntryKey& key,
    const scoped_refptr<EntryDbHandle>& db_handle,
    MemoryEntryDataHints hints,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
  const auto optional_res_id = db_handle->GetResId();
  if (!optional_res_id) {
    // Do nothing if the entry previously failed a speculative creation or
    // optimistic write, or if the entry has not yet been created in the DB.
    // In the latter case, the index will be updated when the entry creation
    // in the DB completes.
    return;
  }
  store_->SetInMemoryEntryDataHints(key.hash(), *optional_res_id, hints);
}

SqlBackendImpl::PopInFlightEntryModificationRunner
SqlBackendImpl::PushInFlightEntryModification(
    const CacheEntryKey& entry_key,
    InFlightEntryModification in_flight_entry_modification) {
  in_flight_entry_modifications_[entry_key].emplace_back(
      std::move(in_flight_entry_modification));
  return PopInFlightEntryModificationRunner(base::ScopedClosureRunner(
      base::BindOnce(&SqlBackendImpl::PopInFlightEntryModification,
                     weak_factory_.GetWeakPtr(), entry_key)));
}

void SqlBackendImpl::PopInFlightEntryModification(
    const CacheEntryKey& entry_key) {
  // The in-flight modifications for a given key are queued and removed in FIFO
  // order. This is safe because `exclusive_operation_coordinator_` serializes
  // all normal operations for the same key. This guarantees that modifications
  // are enqueued and the corresponding store operations are executed in the
  // same order.
  auto it = in_flight_entry_modifications_.find(entry_key);
  CHECK(it != in_flight_entry_modifications_.end());
  CHECK(!it->second.empty());
  it->second.pop_front();
  if (it->second.empty()) {
    in_flight_entry_modifications_.erase(it);
  }
}

void SqlBackendImpl::ApplyInFlightEntryModifications(
    const CacheEntryKey& key,
    SqlPersistentStore::EntryInfo& entry_info) {
  auto it = in_flight_entry_modifications_.find(key);
  if (it == in_flight_entry_modifications_.end()) {
    return;
  }
  for (const auto& modification : it->second) {
    std::optional<SqlPersistentStore::ResId> optional_res_id =
        modification.db_handle ? modification.db_handle->GetResId()
                               : std::nullopt;
    if (!modification.db_handle || (optional_res_id.has_value() &&
                                    *optional_res_id == entry_info.res_id)) {
      if (modification.last_used.has_value()) {
        entry_info.last_used = *modification.last_used;
      }
      if (modification.head.has_value()) {
        entry_info.head = *modification.head;
      }
      if (modification.body_end.has_value()) {
        entry_info.body_end = *modification.body_end;
      }
    }
  }
}

void SqlBackendImpl::RunUntilAllTasksCompleteForTest() {
  async_task_manager_.RunUntilAllTasksCompleteForTest();  // IN-TEST
}

void SqlBackendImpl::MaybeTriggerEviction(bool is_idle_time_eviction) {
  if (eviction_operation_queued_ ||
      !ShouldRunEviction(store_->GetEvictionUrgency(), is_idle_time_eviction)) {
    return;
  }
  eviction_operation_queued_ = true;
  exclusive_operation_coordinator_.PostOrRunExclusiveOperation(
      base::BindOnce(&SqlBackendImpl::HandleTriggerEvictionOperation,
                     weak_factory_.GetWeakPtr(), is_idle_time_eviction));
}

void SqlBackendImpl::HandleTriggerEvictionOperation(
    bool is_idle_time_eviction,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
  eviction_operation_queued_ = false;
  if (!ShouldRunEviction(store_->GetEvictionUrgency(), is_idle_time_eviction)) {
    return;
  }
  std::vector<SqlPersistentStore::ResIdAndShardId> excluded_list;
  excluded_list.reserve(active_entries_.size());
  for (const auto& it : active_entries_) {
    const auto optional_res_id = it.second->db_handle()->GetResId();
    if (optional_res_id.has_value()) {
      excluded_list.emplace_back(*optional_res_id,
                                 store_->GetShardIdForHash(it.first.hash()));
    }
  }
  store_->StartEviction(
      std::move(excluded_list), is_idle_time_eviction,
      exclusive_operation_coordinator_.GetHasPendingTaskFlag(),
      base::BindOnce([](SqlPersistentStore::Error result) {
      }).Then(OnceClosureWithBoundArgs(std::move(handle))));
}

void SqlBackendImpl::EnableStrictCorruptionCheckForTesting() {
  store_->EnableStrictCorruptionCheckForTesting();  // IN-TEST
}

base::WeakPtr<SqlBackendImpl> SqlBackendImpl::GetWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

SqlBackendImpl::InFlightEntryModification::InFlightEntryModification(
    const scoped_refptr<EntryDbHandle>& db_handle,
    base::Time last_used)
    : db_handle(db_handle), last_used(last_used) {}
SqlBackendImpl::InFlightEntryModification::InFlightEntryModification(
    const scoped_refptr<EntryDbHandle>& db_handle,
    base::Time last_used,
    scoped_refptr<net::GrowableIOBuffer> head)
    : db_handle(db_handle), last_used(last_used), head(std::move(head)) {}
SqlBackendImpl::InFlightEntryModification::InFlightEntryModification(
    const scoped_refptr<EntryDbHandle>& db_handle,
    base::Time last_used,
    const std::optional<MemoryEntryDataHints>& hints,
    scoped_refptr<net::GrowableIOBuffer> head,
    int64_t body_end)
    : db_handle(db_handle),
      last_used(last_used),
      hints(hints),
      head(std::move(head)),
      body_end(body_end) {}
SqlBackendImpl::InFlightEntryModification::InFlightEntryModification(
    const scoped_refptr<EntryDbHandle>& db_handle,
    int64_t body_end)
    : db_handle(db_handle), body_end(body_end) {}
SqlBackendImpl::InFlightEntryModification::~InFlightEntryModification() =
    default;
SqlBackendImpl::InFlightEntryModification::InFlightEntryModification(
    InFlightEntryModification&&) = default;

}  // namespace disk_cache
