File: sqlite_persistent_store_backend_base.h

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 6,122,156 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (205 lines) | stat: -rw-r--r-- 7,916 bytes parent folder | download | duplicates (6)
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
// Copyright 2019 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_EXTRAS_SQLITE_SQLITE_PERSISTENT_STORE_BACKEND_BASE_H_
#define NET_EXTRAS_SQLITE_SQLITE_PERSISTENT_STORE_BACKEND_BASE_H_

#include <memory>
#include <optional>
#include <string>

#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/memory/ref_counted.h"
#include "base/thread_annotations.h"
#include "sql/database.h"
#include "sql/meta_table.h"

namespace base {
class Location;
class SequencedTaskRunner;
}  // namespace base

namespace sql {
class Database;
class Statement;
}  // namespace sql

namespace net {

// This class handles the initialization and closing of a SQLite database. It
// is designed to be shared between a client thread and a background task
// runner.
//
// Subclasses will want to have:
// - methods to load the data from the database, which should call
//   InitializeDatabase() from the background thread to ensure the database has
//   been initialized before attempting to load data,
// - overridden DoMigrateDatabaseSchema() and CreateDatabaseSchema(),
//   which will be called in the course of initializing the database,
// - optionally overridden DoInitializeDatabase() which performs any other
//   initialization tasks,
// - a way to keep track of pending operations in order to commit them
//   by invoking Commit() on the background thread, e.g. when a certain batch
//   size is reached or a certain amount of time has passed,
// - overridden DoCommit() to actually handle the logic of committing
//   pending operations to the database,
// - optionally overridden Record*() to record the appropriate metrics.
class SQLitePersistentStoreBackendBase
    : public base::RefCountedThreadSafe<SQLitePersistentStoreBackendBase> {
 public:
  SQLitePersistentStoreBackendBase(const SQLitePersistentStoreBackendBase&) =
      delete;
  SQLitePersistentStoreBackendBase& operator=(
      const SQLitePersistentStoreBackendBase&) = delete;

  // Posts a task to flush pending operations to the database in the background.
  // |callback| is run in the foreground when it is done.
  void Flush(base::OnceClosure callback);

  // Commit any pending operations and close the database. This must be called
  // before the object is destroyed.
  void Close();

  // Set the callback that will be run at the beginning of Commit.
  void SetBeforeCommitCallback(base::RepeatingClosure callback);

 protected:
  friend class base::RefCountedThreadSafe<SQLitePersistentStoreBackendBase>;

  // |current_version_number| and |compatible_version_number| must be greater
  // than 0, as per //sql/meta_table.h. |background_task_runner| should be
  // non-null. If |enable_exclusive_access| is true then the sqlite3 database
  // will be opened with exclusive flag.
  SQLitePersistentStoreBackendBase(
      const base::FilePath& path,
      sql::Database::Tag histogram_tag,
      const int current_version_number,
      const int compatible_version_number,
      scoped_refptr<base::SequencedTaskRunner> background_task_runner,
      scoped_refptr<base::SequencedTaskRunner> client_task_runner,
      bool enable_exclusive_access);

  virtual ~SQLitePersistentStoreBackendBase();

  // Initialize the database. Should be called on background thread. Call this
  // from a subclass' Load method(s) to ensure the database is initialized
  // before loading data from it.
  bool InitializeDatabase();

  // Record metrics on various errors/events that may occur during
  // initialization.
  virtual void RecordOpenDBProblem() {}
  virtual void RecordDBMigrationProblem() {}

  // Embedder-specific database upgrade statements. Returns the version number
  // that the database ends up at, or returns nullopt on error. This is called
  // during MigrateDatabaseSchema() which is called during InitializeDatabase(),
  // and returning |std::nullopt| will cause the initialization process to fail
  // and stop.
  virtual std::optional<int> DoMigrateDatabaseSchema() = 0;

  // Initializes the desired table(s) of the database, e.g. by creating them or
  // checking that they already exist. Returns whether the tables exist.
  // |db()| should not be null when this is called. This is called during
  // InitializeDatabase(), and returning false will cause the initialization
  // process to fail and stop.
  virtual bool CreateDatabaseSchema() = 0;

  // Embedder-specific database initialization tasks. Returns whether they were
  // successful. |db()| should not be null when this is called.
  // This is called during InitializeDatabase(), and returning false will cause
  // the initialization process to fail and stop. The default implementation
  // just returns true.
  virtual bool DoInitializeDatabase();

  // Raze and reset the metatable and database, e.g. if errors are encountered
  // in initialization.
  void Reset();

  // Commit pending operations to the database. First runs
  // |before_commit_callback_|. Should be called on the background thread.
  void Commit();

  // Embedder-specific logic to commit pending operations. (This base class has
  // no notion of pending operations or what to do with them.)
  virtual void DoCommit() = 0;

  // Post a task to the background task runner.
  void PostBackgroundTask(const base::Location& origin, base::OnceClosure task);

  // Post a task to the client task runner.
  void PostClientTask(const base::Location& origin, base::OnceClosure task);

  sql::Database* db() { return db_.get(); }
  sql::MetaTable* meta_table() { return &meta_table_; }

  base::SequencedTaskRunner* background_task_runner() {
    return background_task_runner_.get();
  }
  base::SequencedTaskRunner* client_task_runner() {
    return client_task_runner_.get();
  }

 private:
  // Ensures that the database is at the current version, upgrading if
  // necessary. Returns whether it was successful.
  bool MigrateDatabaseSchema();

  // Flushes (commits pending operations) on the background runner, and invokes
  // |callback| on the client thread when done.
  void FlushAndNotifyInBackground(base::OnceClosure callback);

  // Close the database on the background runner.
  void DoCloseInBackground();

  // Error-handling callback. On errors, the error number (and statement, if
  // available) will be passed to the callback.
  // Sets |corruption_detected_| and posts a task to the background runner to
  // kill the database.
  void DatabaseErrorCallback(int error, sql::Statement* stmt);

  // Kills the database in the case of a catastropic error.
  void KillDatabase();

  // The file path where the database is stored.
  const base::FilePath path_;

  std::unique_ptr<sql::Database> db_;
  sql::MetaTable meta_table_;

  // The identifying prefix for metrics.
  const sql::Database::Tag histogram_tag_;

  // Whether the database has been initialized.
  bool initialized_ = false;

  // Whether the KillDatabase callback has been scheduled.
  bool corruption_detected_ = false;

  // Current version number of the database. Must be greater than 0.
  const int current_version_number_;

  // The lowest version of the code that the database can be read by. Must be
  // greater than 0.
  const int compatible_version_number_;

  const scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
  const scoped_refptr<base::SequencedTaskRunner> client_task_runner_;

  // If true, then sqlite will be requested to open the file with exclusive
  // access.
  const bool enable_exclusive_access_;

  // Callback to be run before Commit.
  base::RepeatingClosure before_commit_callback_
      GUARDED_BY(before_commit_callback_lock_);
  // Guards |before_commit_callback_|.
  base::Lock before_commit_callback_lock_;
};

}  // namespace net

#endif  // NET_EXTRAS_SQLITE_SQLITE_PERSISTENT_STORE_BACKEND_BASE_H_