blob: b6a5746d0d36bf288c9d12a1e6546b2766f8bb4d [file]
// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_DISK_CACHE_SQL_ENTRY_DB_HANDLE_H_
#define NET_DISK_CACHE_SQL_ENTRY_DB_HANDLE_H_
#include <optional>
#include <variant>
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "net/base/net_export.h"
#include "net/disk_cache/sql/sql_persistent_store.h"
#include "net/disk_cache/sql/sql_shared_cache_blob_handle.h"
#include "net/disk_cache/sql/sql_shared_cache_handle.h"
namespace disk_cache {
// This class holds the resource ID (ResId) of a SQL cache entry.
// For speculatively created entries, the ResId might not be available
// initially. This class allows setting the ResId or an Error later.
// It is ref-counted so it can be shared between SqlEntryImpl and
// SqlBackendImpl operations.
class NET_EXPORT_PRIVATE EntryDbHandle
: public base::RefCounted<EntryDbHandle> {
public:
// SqlBackendImpl::OpenOrCreateEntry and CreateEntry perform speculative
// creation and synchronously return a SqlEntryImpl holding an EntryDbHandle
// in the kInitial state when the DB's in-memory index indicates that no
// entry with the corresponding key exists in the DB.
//
// The state changes to kCreating when writing to the DB becomes necessary
// (e.g., when the write buffering limit is exceeded), and then to kCreated
// upon completion. If the DB write fails, the state becomes kErrorOccurred.
//
// If an existing entry is opened, or if speculative creation is skipped
// (e.g., because the in-memory index is not yet loaded), a SqlEntryImpl
// holding an EntryDbHandle in the kCreated state is created after the DB
// read or write operation completes.
enum class State {
kInitial = 0,
kCreating,
kCreated,
kErrorOccurred,
};
EntryDbHandle();
explicit EntryDbHandle(SqlPersistentStore::ResId res_id);
void MarkAsCreating();
void MarkAsCreated(SqlPersistentStore::ResId res_id);
void MarkAsErrorOccurred(SqlPersistentStore::Error error);
void set_shared_cache_resource_id(
std::optional<SqlSharedCacheResourceId> shared_cache_resource_id);
const std::optional<SqlSharedCacheResourceId>& shared_cache_resource_id()
const;
// For entries whose body has been moved to the shared cache,
// `shared_cache_resource_id` is always set.
// However, while `shared_cache_handle` and `shared_cache_blob_handle` are
// set for explicitly opened entries, they are NOT set for entries retrieved
// via entry iteration. This is a deliberate optimization to keep iteration
// fast.
//
// `EntryDbHandle` holds a `shared_cache_handle` to open the corresponding
// shared cache DB as early as possible and keep it open for the lifetime of
// the entry in memory.
//
// Additionally, `EntryDbHandle` holds a `shared_cache_blob_handle` to keep
// the underlying `sql::StreamingBlobHandle` alive within the
// `SqlSharedCacheIsolatedDatabase`, avoiding the overhead of repeated DB
// lookups.
void SetSharedCacheHandle(
scoped_refptr<SqlSharedCacheHandle> shared_cache_handle);
void SetSharedCacheBlobHandle(
scoped_refptr<SqlSharedCacheBlobHandle> shared_cache_blob_handle);
std::optional<SqlPersistentStore::ResId> GetResId() const;
std::optional<SqlPersistentStore::Error> GetError() const;
bool IsInitialState() const { return state_ == State::kInitial; }
bool IsCreatingState() const { return state_ == State::kCreating; }
// Returns true if the ResId has been set or an error has occurred.
bool IsFinished() const;
// Marks the entry as doomed. This is called by the backend when an
// active entry is doomed.
void MarkAsDoomed();
bool doomed() const;
private:
friend class base::RefCounted<EntryDbHandle>;
~EntryDbHandle();
std::optional<
std::variant<SqlPersistentStore::ResId, SqlPersistentStore::Error>>
data_;
State state_;
std::optional<SqlSharedCacheResourceId> shared_cache_resource_id_;
scoped_refptr<SqlSharedCacheHandle> shared_cache_handle_;
scoped_refptr<SqlSharedCacheBlobHandle> shared_cache_blob_handle_;
// True if this entry has been marked for deletion.
bool doomed_ = false;
SEQUENCE_CHECKER(sequence_checker_);
};
} // namespace disk_cache
#endif // NET_DISK_CACHE_SQL_ENTRY_DB_HANDLE_H_