sql_store_base.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef COMPONENTS_OFFLINE_PAGES_TASK_SQL_STORE_BASE_H_
  5. #define COMPONENTS_OFFLINE_PAGES_TASK_SQL_STORE_BASE_H_
  6. #include <memory>
  7. #include <string>
  8. #include <utility>
  9. #include <vector>
  10. #include "base/bind.h"
  11. #include "base/files/file_path.h"
  12. #include "base/location.h"
  13. #include "base/memory/weak_ptr.h"
  14. #include "base/task/task_runner_util.h"
  15. #include "base/threading/thread_task_runner_handle.h"
  16. #include "base/time/time.h"
  17. #include "sql/database.h"
  18. namespace offline_pages {
  19. // Maintains an SQLite database and permits safe access.
  20. // Opens the database only when queried. Automatically closes the database
  21. // if it's not being used.
  22. // This is a base class, and must be overridden to configure the database
  23. // schema.
  24. class SqlStoreBase {
  25. public:
  26. enum class InitializationStatus {
  27. kNotInitialized,
  28. kInProgress,
  29. kSuccess,
  30. kFailure,
  31. };
  32. // Definition of the callback that is going to run the core of the command in
  33. // the |Execute| method.
  34. template <typename T>
  35. using RunCallback = base::OnceCallback<T(sql::Database*)>;
  36. // Definition of the callback used to pass the result back to the caller of
  37. // |Execute| method.
  38. template <typename T>
  39. using ResultCallback = base::OnceCallback<void(T)>;
  40. // Defines inactivity time of DB after which it is going to be closed.
  41. // TODO(crbug.com/933369): Derive appropriate value in a scientific way.
  42. static constexpr base::TimeDelta kClosingDelay = base::Seconds(20);
  43. // If |file_path| is empty, this constructs an in-memory database.
  44. SqlStoreBase(const std::string& histogram_tag,
  45. scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
  46. const base::FilePath& file_path);
  47. SqlStoreBase(const SqlStoreBase&) = delete;
  48. SqlStoreBase& operator=(const SqlStoreBase&) = delete;
  49. virtual ~SqlStoreBase();
  50. // Gets the initialization status of the store.
  51. InitializationStatus initialization_status_for_testing() const {
  52. return initialization_status_;
  53. }
  54. // Executes a |run_callback| on SQL store on the blocking sequence, and posts
  55. // its result back to calling thread through |result_callback|.
  56. // Calling |Execute| when store is kNotInitialized will cause the store
  57. // initialization to start.
  58. // Store initialization status needs to be kSuccess for run_callback to run.
  59. // If initialization fails, |result_callback| is invoked with |default_value|.
  60. template <typename T>
  61. void Execute(RunCallback<T> run_callback,
  62. ResultCallback<T> result_callback,
  63. T default_value) {
  64. ExecuteInternal(
  65. base::BindOnce(&SqlStoreBase::ExecuteAfterInitialized<T>,
  66. weak_ptr_factory_.GetWeakPtr(), std::move(run_callback),
  67. std::move(result_callback), std::move(default_value)));
  68. }
  69. void SetInitializationStatusForTesting(
  70. InitializationStatus initialization_status,
  71. bool reset_db);
  72. protected:
  73. // Returns a function that installs the latest schema to |db| (if necessary),
  74. // and returns whether the database was successfully verified to have the
  75. // current schema. |GetSchemaInitializationFunction| is called on the main
  76. // thread, but the returned function is executed on the blocking sequence.
  77. virtual base::OnceCallback<bool(sql::Database* db)>
  78. GetSchemaInitializationFunction() = 0;
  79. // Optional tracing methods. The derived class may implement tracing events
  80. // with these methods.
  81. // Called on attempt to open the database. |last_closing_time| is the time
  82. // since the last time the database was closed, or null if the database was
  83. // not previously opened since creation of this.
  84. virtual void OnOpenStart(base::TimeTicks last_closing_time) {}
  85. // Called when done attempting to open the database.
  86. virtual void OnOpenDone(bool success) {}
  87. // Called before a task is executed through |Execute()|.
  88. virtual void OnTaskBegin(bool is_initialized) {}
  89. // Called after calling the |run_callback| in |Execute()|.
  90. virtual void OnTaskRunComplete() {}
  91. // Called after calling the |result_callback| in |Execute()|.
  92. virtual void OnTaskReturnComplete() {}
  93. // Called when starting to close the database.
  94. virtual void OnCloseStart(InitializationStatus status_before_close) {}
  95. // Called after closing the database.
  96. virtual void OnCloseComplete() {}
  97. private:
  98. using DatabaseUniquePtr =
  99. std::unique_ptr<sql::Database, base::OnTaskRunnerDeleter>;
  100. void Initialize(base::OnceClosure pending_command);
  101. void InitializeDone(base::OnceClosure pending_command, bool success);
  102. void ExecuteInternal(base::OnceClosure command);
  103. sql::Database* ExecuteBegin();
  104. template <typename T>
  105. void ExecuteAfterInitialized(RunCallback<T> run_callback,
  106. ResultCallback<T> result_callback,
  107. T default_value) {
  108. DCHECK_NE(initialization_status_, InitializationStatus::kNotInitialized);
  109. DCHECK_NE(initialization_status_, InitializationStatus::kInProgress);
  110. sql::Database* db = ExecuteBegin();
  111. if (!db) {
  112. base::ThreadTaskRunnerHandle::Get()->PostTask(
  113. FROM_HERE,
  114. base::BindOnce(std::move(result_callback), std::move(default_value)));
  115. return;
  116. }
  117. base::PostTaskAndReplyWithResult(
  118. background_task_runner_.get(), FROM_HERE,
  119. base::BindOnce(std::move(run_callback), db),
  120. base::BindOnce(&SqlStoreBase::RescheduleClosing<T>,
  121. weak_ptr_factory_.GetWeakPtr(),
  122. std::move(result_callback)));
  123. }
  124. // Reschedules the closing with a delay. Ensures that |result_callback| is
  125. // called.
  126. template <typename T>
  127. void RescheduleClosing(ResultCallback<T> result_callback, T result) {
  128. RescheduleClosingBefore();
  129. std::move(result_callback).Run(std::move(result));
  130. OnTaskReturnComplete();
  131. }
  132. void RescheduleClosingBefore();
  133. // Internal function initiating the closing.
  134. void CloseInternal();
  135. // Completes the closing. Main purpose is to destroy the db pointer.
  136. void CloseInternalDone(DatabaseUniquePtr db);
  137. // Background thread where all SQL access should be run.
  138. scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
  139. // Histogram tag for the sqlite database.
  140. std::string histogram_tag_;
  141. // Path to the database on disk. If empty, the database is in memory only.
  142. base::FilePath db_file_path_;
  143. // Database connection.
  144. DatabaseUniquePtr db_;
  145. // Pending commands.
  146. std::vector<base::OnceClosure> pending_commands_;
  147. // State of initialization.
  148. InitializationStatus initialization_status_ =
  149. InitializationStatus::kNotInitialized;
  150. // Time of the last time the store was closed. Kept for metrics reporting.
  151. base::TimeTicks last_closing_time_;
  152. base::WeakPtrFactory<SqlStoreBase> weak_ptr_factory_{this};
  153. base::WeakPtrFactory<SqlStoreBase> closing_weak_ptr_factory_{this};
  154. };
  155. } // namespace offline_pages
  156. #endif // COMPONENTS_OFFLINE_PAGES_TASK_SQL_STORE_BASE_H_