// 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 <map>
#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_map.h"
#include "base/containers/flat_set.h"
#include "base/containers/queue.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/backend_cleanup_tracker.h"
#include "net/disk_cache/cache_util.h"
#include "net/disk_cache/sql/shared_cache_client_remote.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 "net/disk_cache/sql/sql_shared_cache.h"
#include "net/disk_cache/sql/sql_shared_cache_manager.h"
#include "net/http/http_response_info.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) {
  // Only include the experiment group in the fake index if reset on group
  // change is enabled, preventing unintended cache wipes during rollout.
  base::FieldTrial* backend_field_trial =
      net::features::kDiskCacheBackendResetCacheOnGroupChange.Get()
          ? base::FeatureList::GetFieldTrial(
                net::features::kDiskCacheBackendExperiment)
          : nullptr;
  const std::string expected_contents = base::StrCat(
      {kSqlBackendFakeIndexPrefix,
       net::features::kSqlDiskCacheWalMode.Get() ? "Wal" : "Truncate",
       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`.
    auto db_handle =
        base::MakeRefCounted<EntryDbHandle>(entry_info.info.res_id);
    if (entry_info.info.shared_cache_resource_id.has_value()) {
      db_handle->set_shared_cache_resource_id(
          *entry_info.info.shared_cache_resource_id);
      // For faster entry iteration, we don't retrieve shared_cache_blob_handle.
    }
    scoped_refptr<SqlEntryImpl> new_entry = base::MakeRefCounted<SqlEntryImpl>(
        backend_, entry_info.key, std::move(db_handle),
        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,
    scoped_refptr<BackendCleanupTracker> cleanup_tracker)
    : Backend(cache_type),
      cleanup_tracker_(std::move(cleanup_tracker)),
      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_,
                                                  cleanup_tracker_)),
      optimistic_write_buffer_monitor_(
          net::features::kSqlDiskCacheOptimisticWriteBufferSize.Get()),
      write_buffer_monitor_(
          net::features::kSqlDiskCacheMaxWriteBufferTotalSize.Get()),
      reduce_uma_(net::features::kSqlDiskCacheReduceUma.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::OnEntryOperationFinished,
                                    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 the entry is not active, 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);
  ProcessSharedCacheEligibleEntries(
      base::ScopedClosureRunner(),
      /*on_entry_copied_callback=*/base::NullCallback());
}

bool SqlBackendImpl::SupportsSharedCache() const {
  return !!store_->GetSharedCacheManager();
}

void SqlBackendImpl::RegisterSharedCacheClientRemote(
    const net::NetworkIsolationKey& network_isolation_key,
    std::unique_ptr<SharedCacheClientRemote> client) {
  CHECK(SupportsSharedCache());
  if (network_isolation_key.IsTransient()) {
    return;
  }
  if (store_ && store_->GetSharedCacheManager()) {
    store_->GetSharedCacheManager()->RegisterClient(network_isolation_key,
                                                    std::move(client));
  }
}

void SqlBackendImpl::OnEntryEligibleForSharedCache(
    const std::string& key,
    const GURL& url,
    std::unique_ptr<net::HttpResponseInfo> response_info,
    const net::NetworkIsolationKey& nik) {
  CHECK(SupportsSharedCache());
  CHECK(response_info);
  CacheEntryKey entry_key(key);
  auto [it, inserted] = shared_cache_eligible_entries_.try_emplace(
      entry_key, entry_key, url, std::move(response_info), nik);
  // If an entry for `entry_key` was already registered, update it only if the
  // new `response_info` has a strictly newer `response_time`.
  if (!inserted &&
      response_info->response_time > it->second.response_info->response_time) {
    it->second = SqlPersistentStore::SharedCacheEligibleEntry(
        entry_key, url, std::move(response_info), nik);
  }
}

void SqlBackendImpl::ProcessAllSharedCacheEligibleEntriesForTest(
    base::ScopedClosureRunner scoped_closure_runner) {
  CHECK(SupportsSharedCache());
  ProcessAllSharedCacheEligibleEntriesWithCallbackForTest(  // IN-TEST
      std::move(scoped_closure_runner),
      /*on_entry_copied_callback=*/base::NullCallback());
}

size_t SqlBackendImpl::GetSharedCacheEligibleEntriesCountForTest()  // IN-TEST
    const {
  return shared_cache_eligible_entries_.size();
}

void SqlBackendImpl::ProcessSharedCacheEligibleEntriesForTest(  // IN-TEST
    base::ScopedClosureRunner scoped_closure_runner,
    base::RepeatingCallback<void(const CacheEntryKey&)>
        on_entry_copied_callback) {
  ProcessSharedCacheEligibleEntries(std::move(scoped_closure_runner),
                                    std::move(on_entry_copied_callback));
}

void SqlBackendImpl::
    ProcessAllSharedCacheEligibleEntriesWithCallbackForTest(  // IN-TEST
        base::ScopedClosureRunner scoped_closure_runner,
        base::RepeatingCallback<void(const CacheEntryKey&)>
            on_entry_copied_callback) {
  if (!SupportsSharedCache() || shared_cache_eligible_entries_.empty()) {
    return;
  }
  ProcessSharedCacheEligibleEntries(
      base::ScopedClosureRunner(
          // Post the next iteration asynchronously to avoid a synchronous
          // infinite loop when eligible entries are temporarily active.
          base::BindPostTaskToCurrentDefault(base::BindOnce(
              &SqlBackendImpl::
                  ProcessAllSharedCacheEligibleEntriesWithCallbackForTest,
              weak_factory_.GetWeakPtr(), std::move(scoped_closure_runner),
              on_entry_copied_callback))),
      on_entry_copied_callback);
}

void SqlBackendImpl::ProcessSharedCacheEligibleEntries(
    base::ScopedClosureRunner scoped_closure_runner,
    base::RepeatingCallback<void(const CacheEntryKey&)>
        on_entry_copied_callback) {
  if (!SupportsSharedCache()) {
    return;
  }
  exclusive_operation_coordinator_.PostOrRunExclusiveOperation(base::BindOnce(
      &SqlBackendImpl::HandleProcessSharedCacheEligibleEntries,
      weak_factory_.GetWeakPtr(), std::move(scoped_closure_runner),
      std::move(on_entry_copied_callback)));
}

void SqlBackendImpl::HandleProcessSharedCacheEligibleEntries(
    base::ScopedClosureRunner scoped_closure_runner,
    base::RepeatingCallback<void(const CacheEntryKey&)>
        on_entry_copied_callback,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
  // `std::map` is intentionally used here to ensure deterministic processing
  // order (via ordered iterators) and because the map is not guaranteed to be
  // small and could potentially grow large, making `base::flat_map` unsuitable.
  std::map<net::NetworkIsolationKey,
           base::queue<SqlPersistentStore::SharedCacheEligibleEntry>>
      entries_to_process;
  for (auto it = shared_cache_eligible_entries_.begin();
       it != shared_cache_eligible_entries_.end();) {
    if (active_entries_.find(it->first) == active_entries_.end()) {
      entries_to_process[it->second.nik].push(std::move(it->second));
      shared_cache_eligible_entries_.erase(it++);
    } else {
      ++it;
    }
  }

  if (entries_to_process.empty()) {
    return;
  }

  store_->GetSharedCacheManager()->ProcessSharedCacheEligibleEntries(
      std::move(entries_to_process),
      exclusive_operation_coordinator_.GetHasPendingTaskFlag(),
      base::BindOnce(
          &SqlBackendImpl::OnProcessSharedCacheEligibleEntriesComplete,
          weak_factory_.GetWeakPtr(), std::move(scoped_closure_runner),
          std::move(handle)),
      std::move(on_entry_copied_callback));
}

void SqlBackendImpl::OnProcessSharedCacheEligibleEntriesComplete(
    base::ScopedClosureRunner scoped_closure_runner,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle,
    std::vector<SqlPersistentStore::SharedCacheEligibleEntry>
        unprocessed_entries) {
  // Put back any entries that could not be processed into
  // `shared_cache_eligible_entries_`. If an entry for the same key was newly
  // registered while processing was in flight, update it only if the
  // unprocessed entry has a strictly newer response_time.
  for (auto& entry : unprocessed_entries) {
    auto [it, inserted] =
        shared_cache_eligible_entries_.try_emplace(entry.key, std::move(entry));
    if (!inserted && entry.response_info->response_time >
                         it->second.response_info->response_time) {
      it->second = std::move(entry);
    }
  }
}

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

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

  auto db_handle = base::MakeRefCounted<EntryDbHandle>(entry_info.res_id);
  if (entry_info.shared_cache_resource_id.has_value()) {
    CHECK(entry_info.shared_cache_handle);
    CHECK(entry_info.shared_cache_blob_handle);
    db_handle->set_shared_cache_resource_id(
        *entry_info.shared_cache_resource_id);
    db_handle->SetSharedCacheHandle(std::move(entry_info.shared_cache_handle));
    db_handle->SetSharedCacheBlobHandle(
        std::move(entry_info.shared_cache_blob_handle));
  }

  // Create a new SqlEntryImpl instance.
  scoped_refptr<SqlEntryImpl> new_entry = base::MakeRefCounted<SqlEntryImpl>(
      weak_factory_.GetWeakPtr(), key, std::move(db_handle),
      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(entry_info.opened
                              ? EntryResult::MakeOpened(new_entry.get())
                              : EntryResult::MakeCreated(new_entry.get()));

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

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);

  if (!reduce_uma_) {
    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(
                        [](bool reduce_uma,
                           SqlPersistentStore::ResIdOrError result) {
                          if (!reduce_uma) {
                            base::UmaHistogramEnumeration(
                                "Net.SqlDiskCache.OptimisticWrite.Result",
                                result.error_or(
                                    SqlPersistentStore::Error::kOk));
                          }
                        },
                        reduce_uma_))
                    .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;
  }
  if (!db_handle->shared_cache_resource_id().has_value()) {
    store_->ReadEntryData(
        key, *db_handle->GetResId(), offset, buffer, buf_len, body_end,
        sparse_reading,
        std::move(callback).Then(OnceClosureWithBoundArgs(std::move(handle))));
    return;
  }
  int bytes_to_read = std::max(
      int64_t{0}, std::min(static_cast<int64_t>(buf_len), body_end - offset));
  CHECK_GE(buffer->size(), bytes_to_read);
  if (buffer->size() != bytes_to_read) {
    buffer = base::MakeRefCounted<net::DrainableIOBuffer>(std::move(buffer),
                                                          bytes_to_read);
  }

  store_->GetSharedCacheManager()->GetCacheByDbId(
      db_handle->shared_cache_resource_id()->db_id,
      base::BindOnce(
          [](const CacheEntryKey& key, SqlSharedCacheRowId shared_cache_row_id,
             int64_t body_end, int64_t offset,
             scoped_refptr<net::IOBuffer> buffer,
             SqlPersistentStore::ReadResultOrErrorCallback callback,
             scoped_refptr<SqlSharedCacheHandle> shared_cache) {
            if (!shared_cache || !*shared_cache) {
              std::move(callback).Run(
                  base::unexpected(SqlPersistentStore::Error::kNotFound));
              return;
            }
            (*shared_cache)
                ->Read(key, shared_cache_row_id,
                       base::checked_cast<int>(body_end), offset, buffer,
                       std::move(callback).Then(base::OnceClosure(
                           base::DoNothingWithBoundArgs(shared_cache))));
          },
          key, db_handle->shared_cache_resource_id()->row_id, body_end, offset,
          std::move(buffer),
          std::move(callback).Then(
              OnceClosureWithBoundArgs(std::move(handle)))));
}

int SqlBackendImpl::CopySharedCacheToBlobTableAndWrite(
    const CacheEntryKey& key,
    const scoped_refptr<EntryDbHandle>& db_handle,
    int64_t offset,
    scoped_refptr<net::IOBuffer> buffer,
    int buf_len,
    int64_t old_body_end,
    bool truncate,
    base::Time last_used,
    bool sparse_write,
    size_t header_size,
    CompletionOnceCallback callback) {
  const int64_t end_offset = base::CheckAdd(offset, buf_len).ValueOrDie();
  const int64_t new_body_end =
      truncate ? end_offset : std::max(end_offset, old_body_end);
  auto sync_result_receiver =
      base::MakeRefCounted<SyncResultReceiver<int>>(std::move(callback));
  exclusive_operation_coordinator_.PostOrRunNormalOperation(
      key,
      base::BindOnce(
          &SqlBackendImpl::HandleCopySharedCacheToBlobTableOperation,
          weak_factory_.GetWeakPtr(), key, db_handle, offset, std::move(buffer),
          buf_len, old_body_end, truncate, last_used, sparse_write, header_size,
          PushInFlightEntryModification(
              key, InFlightEntryModification(db_handle, new_body_end)),
          WrapCallbackWithAbortError<int>(sync_result_receiver->GetCallback(),
                                          net::ERR_ABORTED)));

  auto sync_result = sync_result_receiver->FinishSyncCall();
  return sync_result ? std::move(*sync_result) : net::ERR_IO_PENDING;
}

void SqlBackendImpl::HandleCopySharedCacheToBlobTableOperation(
    const CacheEntryKey& key,
    const scoped_refptr<EntryDbHandle>& db_handle,
    int64_t offset,
    scoped_refptr<net::IOBuffer> buffer,
    int buf_len,
    int64_t old_body_end,
    bool truncate,
    base::Time last_used,
    bool sparse_write,
    size_t header_size,
    PopInFlightEntryModificationRunner pop_in_flight_entry_modification,
    CompletionOnceCallback callback,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
  CHECK(!db_handle->IsInitialState());
  if (db_handle->GetError().has_value()) {
    db_handle->SetSharedCacheBlobHandle(nullptr);
    db_handle->SetSharedCacheHandle(nullptr);
    std::move(callback).Run(net::ERR_FAILED);
    return;
  }
  auto copy_buffer = base::MakeRefCounted<net::IOBufferWithSize>(16 * 1024);
  DoCopySharedCacheToBlobTableStep(
      key, db_handle, offset, std::move(buffer), buf_len, old_body_end,
      truncate, last_used, sparse_write, header_size, /*copy_offset=*/0,
      copy_buffer, std::move(pop_in_flight_entry_modification),
      std::move(callback), std::move(handle));
}

void SqlBackendImpl::DoCopySharedCacheToBlobTableStep(
    const CacheEntryKey& key,
    const scoped_refptr<EntryDbHandle>& db_handle,
    int64_t offset,
    scoped_refptr<net::IOBuffer> buffer,
    int buf_len,
    int64_t old_body_end,
    bool truncate,
    base::Time last_used,
    bool sparse_write,
    size_t header_size,
    int64_t copy_offset,
    scoped_refptr<net::IOBuffer> copy_buffer,
    PopInFlightEntryModificationRunner pop_in_flight_entry_modification,
    CompletionOnceCallback callback,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle) {
  CHECK_LE(copy_offset, old_body_end);
  if (copy_offset == old_body_end) {
    // Done copying!
    auto shared_cache_resource_id = *db_handle->shared_cache_resource_id();
    db_handle->set_shared_cache_resource_id(std::nullopt);
    db_handle->SetSharedCacheBlobHandle(nullptr);
    db_handle->SetSharedCacheHandle(nullptr);

    auto* manager = GetSharedCacheManager();
    CHECK(manager);
    manager->DeleteResources({shared_cache_resource_id}, base::NullCallback());

    // Execute the final WriteData.
    HandleWriteEntryDataOperation(
        key, db_handle, old_body_end,
        EntryWriteBuffer(buffer.get(), buf_len, offset), truncate, last_used,
        sparse_write, header_size,
        WrapCallbackWithAbortError<SqlPersistentStore::ResIdOrError>(
            MakeUpdateDbHandleCallback(db_handle)
                .Then(MakeResIdOrErrorToIntCallback(buf_len))
                .Then(std::move(callback)),
            base::unexpected(SqlPersistentStore::Error::kAborted)),
        std::move(pop_in_flight_entry_modification), std::move(handle));
    return;
  }

  int bytes_to_read = std::min(static_cast<int64_t>(copy_buffer->size()),
                               old_body_end - copy_offset);
  CHECK(db_handle->shared_cache_resource_id());

  scoped_refptr<net::IOBuffer> read_buffer = copy_buffer;
  CHECK_GE(copy_buffer->size(), bytes_to_read);
  if (copy_buffer->size() != bytes_to_read) {
    read_buffer = base::MakeRefCounted<net::DrainableIOBuffer>(copy_buffer,
                                                               bytes_to_read);
  }

  HandleReadEntryDataOperation(
      key, db_handle, copy_offset, copy_buffer, bytes_to_read, old_body_end,
      sparse_write,
      base::BindOnce(&SqlBackendImpl::OnReadFromSharedCacheForCopy,
                     weak_factory_.GetWeakPtr(), key, db_handle, offset, buffer,
                     buf_len, old_body_end, truncate, last_used, sparse_write,
                     header_size, copy_offset, copy_buffer, bytes_to_read,
                     std::move(pop_in_flight_entry_modification),
                     std::move(callback), std::move(handle)),
      /*handle=*/nullptr);
}

void SqlBackendImpl::OnReadFromSharedCacheForCopy(
    const CacheEntryKey& key,
    const scoped_refptr<EntryDbHandle>& db_handle,
    int64_t offset,
    scoped_refptr<net::IOBuffer> buffer,
    int buf_len,
    int64_t old_body_end,
    bool truncate,
    base::Time last_used,
    bool sparse_write,
    size_t header_size,
    int64_t copy_offset,
    scoped_refptr<net::IOBuffer> copy_buffer,
    int bytes_to_read,
    PopInFlightEntryModificationRunner pop_in_flight_entry_modification,
    CompletionOnceCallback callback,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle,
    SqlPersistentStore::ReadResultOrError result) {
  if (!result.has_value() || result->read_bytes != bytes_to_read) {
    db_handle->MarkAsErrorOccurred(
        result.error_or(SqlPersistentStore::Error::kBodyEndMismatch));
    db_handle->SetSharedCacheBlobHandle(nullptr);
    db_handle->SetSharedCacheHandle(nullptr);
    std::move(callback).Run(net::ERR_FAILED);
    return;
  }
  CHECK(db_handle->GetResId().has_value());
  EntryWriteBuffer write_buffer(copy_buffer, bytes_to_read, copy_offset);
  if (result->cache_buffer) {
    write_buffer.buffers.push_back(result->cache_buffer);
    write_buffer.size += result->cache_buffer->size();
  }
  int total_bytes_written = write_buffer.size;
  store_->WriteEntryData(
      key, *db_handle->GetResId(), old_body_end, std::move(write_buffer),
      /*truncate=*/false, db_handle->doomed(), sparse_write, header_size,
      base::BindOnce(&SqlBackendImpl::OnWriteToBlobTableForCopy,
                     weak_factory_.GetWeakPtr(), key, db_handle, offset, buffer,
                     buf_len, old_body_end, truncate, last_used, sparse_write,
                     header_size, copy_offset, copy_buffer, total_bytes_written,
                     std::move(pop_in_flight_entry_modification),
                     std::move(callback), std::move(handle)));
}

void SqlBackendImpl::OnWriteToBlobTableForCopy(
    const CacheEntryKey& key,
    const scoped_refptr<EntryDbHandle>& db_handle,
    int64_t offset,
    scoped_refptr<net::IOBuffer> buffer,
    int buf_len,
    int64_t old_body_end,
    bool truncate,
    base::Time last_used,
    bool sparse_write,
    size_t header_size,
    int64_t copy_offset,
    scoped_refptr<net::IOBuffer> copy_buffer,
    int bytes_written,
    PopInFlightEntryModificationRunner pop_in_flight_entry_modification,
    CompletionOnceCallback callback,
    std::unique_ptr<ExclusiveOperationCoordinator::OperationHandle> handle,
    SqlPersistentStore::ResIdOrError result) {
  if (!result.has_value()) {
    db_handle->MarkAsErrorOccurred(result.error());
    db_handle->SetSharedCacheBlobHandle(nullptr);
    db_handle->SetSharedCacheHandle(nullptr);
    std::move(callback).Run(net::ERR_FAILED);
    return;
  }
  copy_offset += bytes_written;
  DoCopySharedCacheToBlobTableStep(
      key, db_handle, offset, buffer, buf_len, old_body_end, truncate,
      last_used, sparse_write, header_size, copy_offset, copy_buffer,
      std::move(pop_in_flight_entry_modification), std::move(callback),
      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
