File: sql_store_base.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 (190 lines) | stat: -rw-r--r-- 7,131 bytes parent folder | download | duplicates (5)
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
// 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 COMPONENTS_OFFLINE_PAGES_TASK_SQL_STORE_BASE_H_
#define COMPONENTS_OFFLINE_PAGES_TASK_SQL_STORE_BASE_H_

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "sql/database.h"

namespace offline_pages {

// Maintains an SQLite database and permits safe access.
// Opens the database only when queried. Automatically closes the database
// if it's not being used.
// This is a base class, and must be overridden to configure the database
// schema.
class SqlStoreBase {
 public:
  enum class InitializationStatus {
    kNotInitialized,
    kInProgress,
    kSuccess,
    kFailure,
  };

  // Definition of the callback that is going to run the core of the command in
  // the |Execute| method.
  template <typename T>
  using RunCallback = base::OnceCallback<T(sql::Database*)>;

  // Definition of the callback used to pass the result back to the caller of
  // |Execute| method.
  template <typename T>
  using ResultCallback = base::OnceCallback<void(T)>;

  // Defines inactivity time of DB after which it is going to be closed.
  // TODO(crbug.com/40614502): Derive appropriate value in a scientific way.
  static constexpr base::TimeDelta kClosingDelay = base::Seconds(20);

  // If |file_path| is empty, this constructs an in-memory database.
  SqlStoreBase(sql::Database::Tag histogram_tag,
               scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
               const base::FilePath& file_path);

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

  virtual ~SqlStoreBase();

  // Gets the initialization status of the store.
  InitializationStatus initialization_status_for_testing() const {
    return initialization_status_;
  }

  // Executes a |run_callback| on SQL store on the blocking sequence, and posts
  // its result back to calling thread through |result_callback|.
  // Calling |Execute| when store is kNotInitialized will cause the store
  // initialization to start.
  // Store initialization status needs to be kSuccess for run_callback to run.
  // If initialization fails, |result_callback| is invoked with |default_value|.
  template <typename T>
  void Execute(RunCallback<T> run_callback,
               ResultCallback<T> result_callback,
               T default_value) {
    ExecuteInternal(
        base::BindOnce(&SqlStoreBase::ExecuteAfterInitialized<T>,
                       weak_ptr_factory_.GetWeakPtr(), std::move(run_callback),
                       std::move(result_callback), std::move(default_value)));
  }

  void SetInitializationStatusForTesting(
      InitializationStatus initialization_status,
      bool reset_db);

 protected:
  // Returns a function that installs the latest schema to |db| (if necessary),
  // and returns whether the database was successfully verified to have the
  // current schema. |GetSchemaInitializationFunction| is called on the main
  // thread, but the returned function is executed on the blocking sequence.
  virtual base::OnceCallback<bool(sql::Database* db)>
  GetSchemaInitializationFunction() = 0;

  // Optional tracing methods. The derived class may implement tracing events
  // with these methods.

  // Called on attempt to open the database. |last_closing_time| is the time
  // since the last time the database was closed, or null if the database was
  // not previously opened since creation of this.
  virtual void OnOpenStart(base::TimeTicks last_closing_time) {}
  // Called when done attempting to open the database.
  virtual void OnOpenDone(bool success) {}
  // Called before a task is executed through |Execute()|.
  virtual void OnTaskBegin(bool is_initialized) {}
  // Called after calling the |run_callback| in |Execute()|.
  virtual void OnTaskRunComplete() {}
  // Called after calling the |result_callback| in |Execute()|.
  virtual void OnTaskReturnComplete() {}
  // Called when starting to close the database.
  virtual void OnCloseStart(InitializationStatus status_before_close) {}
  // Called after closing the database.
  virtual void OnCloseComplete() {}

 private:
  using DatabaseUniquePtr =
      std::unique_ptr<sql::Database, base::OnTaskRunnerDeleter>;

  void Initialize(base::OnceClosure pending_command);
  void InitializeDone(base::OnceClosure pending_command, bool success);

  void ExecuteInternal(base::OnceClosure command);
  sql::Database* ExecuteBegin();

  template <typename T>
  void ExecuteAfterInitialized(RunCallback<T> run_callback,
                               ResultCallback<T> result_callback,
                               T default_value) {
    DCHECK_NE(initialization_status_, InitializationStatus::kNotInitialized);
    DCHECK_NE(initialization_status_, InitializationStatus::kInProgress);
    sql::Database* db = ExecuteBegin();
    if (!db) {
      base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
          FROM_HERE,
          base::BindOnce(std::move(result_callback), std::move(default_value)));
      return;
    }
    background_task_runner_->PostTaskAndReplyWithResult(
        FROM_HERE, base::BindOnce(std::move(run_callback), db),
        base::BindOnce(&SqlStoreBase::RescheduleClosing<T>,
                       weak_ptr_factory_.GetWeakPtr(),
                       std::move(result_callback)));
  }

  // Reschedules the closing with a delay. Ensures that |result_callback| is
  // called.
  template <typename T>
  void RescheduleClosing(ResultCallback<T> result_callback, T result) {
    RescheduleClosingBefore();
    std::move(result_callback).Run(std::move(result));
    OnTaskReturnComplete();
  }

  void RescheduleClosingBefore();

  // Internal function initiating the closing.
  void CloseInternal();

  // Completes the closing. Main purpose is to destroy the db pointer.
  void CloseInternalDone(DatabaseUniquePtr db);

  // Background thread where all SQL access should be run.
  scoped_refptr<base::SequencedTaskRunner> background_task_runner_;

  // Histogram tag for the sqlite database.
  sql::Database::Tag histogram_tag_;

  // Path to the database on disk. If empty, the database is in memory only.
  base::FilePath db_file_path_;

  // Database connection.
  DatabaseUniquePtr db_;

  // Pending commands.
  std::vector<base::OnceClosure> pending_commands_;

  // State of initialization.
  InitializationStatus initialization_status_ =
      InitializationStatus::kNotInitialized;

  // Time of the last time the store was closed. Kept for metrics reporting.
  base::TimeTicks last_closing_time_;

  base::WeakPtrFactory<SqlStoreBase> weak_ptr_factory_{this};
  base::WeakPtrFactory<SqlStoreBase> closing_weak_ptr_factory_{this};
};

}  // namespace offline_pages

#endif  // COMPONENTS_OFFLINE_PAGES_TASK_SQL_STORE_BASE_H_