File: backing_store.h

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (253 lines) | stat: -rw-r--r-- 10,683 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
// 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.

#ifndef CONTENT_BROWSER_INDEXED_DB_INSTANCE_BACKING_STORE_H_
#define CONTENT_BROWSER_INDEXED_DB_INSTANCE_BACKING_STORE_H_

#include <list>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/types/expected.h"
#include "components/services/storage/indexed_db/locks/partitioned_lock.h"
#include "content/browser/indexed_db/indexed_db_external_object_storage.h"
#include "content/browser/indexed_db/status.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_key_range.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"

namespace base {
class WaitableEvent;
}

namespace content::indexed_db {

struct IndexedDBValue;

// NB: This interface is a WIP and is expected to experience heavy churn in the
// near future as additional interfaces are introduced to appropriately abstract
// the different database engines. See crbug.com/40273263.
//
// This interface abstracts the implementation of the data store for IDB data
// for a single bucket (which may contain many IDB databases). The current
// complete implementation uses LevelDB as its engine, along with a bespoke
// flat-file store for blobs, and is called level_db::BackingStore. In this
// system, each BackingStore corresponds to one LevelDB database.
//
// The SQLite version is a work in progress. There, each IDBDatabase correlates
// to a different database, so the BackingStore uses a collection of .sql
// files.
//
// Many of the methods here are likely to be moved to sibling interfaces that
// better encapsulate semantic objects. Eventually, all access to the
// BackingStore should be routed through this interface or its siblings rather
// than reaching directly into level_db::BackingStore.
class BackingStore {
 public:
  // Used to uniquely identify a record in the database. Can be treated as an
  // opaque token by consumers of the `BackingStore`.
  struct RecordIdentifier {
    // The meaning of these fields is backend-specific. Consumer code should
    // ignore them.
    // SQLite: a row id. LevelDB: a version.
    int64_t number;
    // SQLite: unused. LevelDB: the *encoded* primary key bytes.
    std::string data;
  };

  class Cursor;
  class Transaction;

  // Represents a database in the backing store. A single Database may be
  // associated with many connections and transactions.
  class Database {
   public:
    virtual ~Database() = default;

    // Memory-cached metadata for this database.
    virtual const blink::IndexedDBDatabaseMetadata& GetMetadata() = 0;

    // Generates a lock ID for the given object store.
    virtual PartitionedLockId GetLockId(int64_t object_store_id) const = 0;

    // Creates a transaction on this database.
    virtual std::unique_ptr<Transaction> CreateTransaction(
        blink::mojom::IDBTransactionDurability durability,
        blink::mojom::IDBTransactionMode mode) = 0;

    // Deletes the database from the backing store and resets metadata to a
    // mostly uninitialized state.
    [[nodiscard]] virtual Status DeleteDatabase(
        std::vector<PartitionedLock> locks,
        base::OnceClosure on_complete) = 0;
  };

  // This interface wraps state and actions executed on the backing store by the
  // store-agnostic `Transaction`, and is to be implemented by backends such as
  // LevelDB or SQLite.
  // Each transaction is associated with a single `Database`.
  class Transaction {
   public:
    virtual ~Transaction() = default;

    // For now, refer to comments in level_db::BackingStore::Transaction for
    // documentation.
    virtual void Begin(std::vector<PartitionedLock> locks) = 0;
    virtual Status CommitPhaseOne(BlobWriteCallback callback) = 0;
    virtual Status CommitPhaseTwo() = 0;
    virtual void Rollback() = 0;

    // Called after the transaction is aborted or completed.
    // TODO(crbug.com/40253999): can this be removed in favor of deleting the
    // object?
    virtual void Reset() = 0;

    // Changes the database version to |version|.
    [[nodiscard]] virtual Status SetDatabaseVersion(int64_t version) = 0;
    [[nodiscard]] virtual Status CreateObjectStore(
        int64_t object_store_id,
        const std::u16string& name,
        blink::IndexedDBKeyPath key_path,
        bool auto_increment) = 0;
    [[nodiscard]] virtual Status DeleteObjectStore(int64_t object_store_id) = 0;
    [[nodiscard]] virtual Status RenameObjectStore(
        int64_t object_store_id,
        const std::u16string& new_name) = 0;
    // Removes all data contained in the given object store but keeps the object
    // store.
    [[nodiscard]] virtual Status ClearObjectStore(int64_t object_store_id) = 0;

    // Creates a new index metadata and writes it to the transaction.
    [[nodiscard]] virtual Status CreateIndex(
        int64_t object_store_id,
        blink::IndexedDBIndexMetadata index) = 0;

    // Deletes the index metadata on the transaction (but not any index
    // entries).
    [[nodiscard]] virtual Status DeleteIndex(int64_t object_store_id,
                                             int64_t index_id) = 0;
    // Renames the given index and writes it to the transaction.
    [[nodiscard]] virtual Status RenameIndex(
        int64_t object_store_id,
        int64_t index_id,
        const std::u16string& new_name) = 0;
    [[nodiscard]] virtual Status GetRecord(int64_t object_store_id,
                                           const blink::IndexedDBKey& key,
                                           IndexedDBValue* record) = 0;
    // When successful, returns the identifier for the newly stored record.
    [[nodiscard]] virtual StatusOr<RecordIdentifier> PutRecord(
        int64_t object_store_id,
        const blink::IndexedDBKey& key,
        IndexedDBValue value) = 0;
    [[nodiscard]] virtual Status DeleteRange(
        int64_t object_store_id,
        const blink::IndexedDBKeyRange&) = 0;
    [[nodiscard]] virtual StatusOr<int64_t> GetKeyGeneratorCurrentNumber(
        int64_t object_store_id) = 0;
    [[nodiscard]] virtual Status MaybeUpdateKeyGeneratorCurrentNumber(
        int64_t object_store_id,
        int64_t new_state,
        bool check_current) = 0;
    // Returns the `RecordIdentifier` for the record if the primary key exists
    // in the given object store. Returns `Status` on error. Returns nullopt if
    // no record exists with the given key.
    [[nodiscard]] virtual StatusOr<std::optional<RecordIdentifier>>
    KeyExistsInObjectStore(int64_t object_store_id,
                           const blink::IndexedDBKey& key) = 0;
    [[nodiscard]] virtual Status PutIndexDataForRecord(
        int64_t object_store_id,
        int64_t index_id,
        const blink::IndexedDBKey& key,
        const RecordIdentifier& record) = 0;
    [[nodiscard]] virtual Status GetPrimaryKeyViaIndex(
        int64_t object_store_id,
        int64_t index_id,
        const blink::IndexedDBKey& key,
        std::unique_ptr<blink::IndexedDBKey>* primary_key) = 0;
    [[nodiscard]] virtual Status KeyExistsInIndex(
        int64_t object_store_id,
        int64_t index_id,
        const blink::IndexedDBKey& key,
        std::unique_ptr<blink::IndexedDBKey>* found_primary_key,
        bool* exists) = 0;
    virtual StatusOr<std::unique_ptr<Cursor>> OpenObjectStoreKeyCursor(
        int64_t object_store_id,
        const blink::IndexedDBKeyRange& key_range,
        blink::mojom::IDBCursorDirection) = 0;
    virtual StatusOr<std::unique_ptr<Cursor>> OpenObjectStoreCursor(
        int64_t object_store_id,
        const blink::IndexedDBKeyRange& key_range,
        blink::mojom::IDBCursorDirection) = 0;
    virtual StatusOr<std::unique_ptr<Cursor>> OpenIndexKeyCursor(
        int64_t object_store_id,
        int64_t index_id,
        const blink::IndexedDBKeyRange& key_range,
        blink::mojom::IDBCursorDirection) = 0;
    virtual StatusOr<std::unique_ptr<Cursor>> OpenIndexCursor(
        int64_t object_store_id,
        int64_t index_id,
        const blink::IndexedDBKeyRange& key_range,
        blink::mojom::IDBCursorDirection) = 0;
  };

  // Another interface to be implemented by a backend implementation.
  class Cursor {
   public:
    enum IteratorState { READY = 0, SEEK };

    virtual ~Cursor() = default;

    virtual const blink::IndexedDBKey& GetKey() const = 0;
    virtual const blink::IndexedDBKey& GetPrimaryKey() const = 0;
    virtual blink::IndexedDBKey TakeKey() && = 0;
    virtual IndexedDBValue& GetValue() = 0;

    virtual bool Continue(const blink::IndexedDBKey& key,
                          const blink::IndexedDBKey& primary_key,
                          IteratorState state,
                          Status*) = 0;
    virtual bool Advance(uint32_t count, Status*) = 0;
    // Clone may return a nullptr if cloning fails for any reason.
    virtual std::unique_ptr<Cursor> Clone() const = 0;

    bool Continue(Status* s) { return Continue({}, {}, SEEK, s); }
  };

  virtual ~BackingStore() = default;

  // Get tasks to be run after a BackingStore no longer has any connections.
  virtual void TearDown(base::WaitableEvent* signal_on_destruction) = 0;
  virtual void InvalidateBlobReferences() = 0;
  virtual void StartPreCloseTasks(base::OnceClosure on_done) = 0;
  virtual void StopPreCloseTasks() = 0;
  // Gets the total size of blobs and the database for in-memory backing
  // stores.
  virtual int64_t GetInMemorySize() const = 0;
  // Returns a list of names of existing databases, regardless of whether
  // they're currently open.
  [[nodiscard]] virtual StatusOr<std::vector<std::u16string>>
  GetDatabaseNames() = 0;
  // Returns a list of names of existing databases and their version numbers
  // (i.e. `IndexedDBDatabaseMetadata::version`), regardless of whether they're
  // currently open.
  [[nodiscard]]
  virtual StatusOr<std::vector<blink::mojom::IDBNameAndVersionPtr>>
  GetDatabaseNamesAndVersions() = 0;
  // Creates a new database in the backing store, or opens an existing one. If
  // pre-existing, the database's metadata will be populated from disk.
  // Otherwise the version will be initialized to NO_VERSION.
  [[nodiscard]] virtual StatusOr<std::unique_ptr<BackingStore::Database>>
  CreateOrOpenDatabase(const std::u16string& name) = 0;

  virtual uintptr_t GetIdentifierForMemoryDump() = 0;

  // Writes backing store files to disk in their long-term format, e.g. converts
  // a log to actual DB files.
  virtual void FlushForTesting() = 0;
};

}  // namespace content::indexed_db

#endif  // CONTENT_BROWSER_INDEXED_DB_INSTANCE_BACKING_STORE_H_