shared_proto_database.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. // Copyright 2018 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_LEVELDB_PROTO_INTERNAL_SHARED_PROTO_DATABASE_H_
  5. #define COMPONENTS_LEVELDB_PROTO_INTERNAL_SHARED_PROTO_DATABASE_H_
  6. #include <memory>
  7. #include <string>
  8. #include "base/bind.h"
  9. #include "base/callback_helpers.h"
  10. #include "base/cancelable_callback.h"
  11. #include "base/component_export.h"
  12. #include "base/containers/queue.h"
  13. #include "base/gtest_prod_util.h"
  14. #include "base/memory/ref_counted.h"
  15. #include "base/sequence_checker.h"
  16. #include "base/synchronization/lock.h"
  17. #include "base/time/time.h"
  18. #include "components/leveldb_proto/internal/proto/shared_db_metadata.pb.h"
  19. #include "components/leveldb_proto/internal/shared_proto_database_client.h"
  20. #include "components/leveldb_proto/public/proto_database.h"
  21. namespace leveldb_proto {
  22. // Controls a single LevelDB database to be used by many clients, and provides
  23. // a way to get SharedProtoDatabaseClients that allow shared access to the
  24. // underlying single database.
  25. class COMPONENT_EXPORT(LEVELDB_PROTO) SharedProtoDatabase
  26. : public base::RefCountedThreadSafe<SharedProtoDatabase> {
  27. public:
  28. using SharedClientInitCallback =
  29. base::OnceCallback<void(Enums::InitStatus,
  30. SharedDBMetadataProto::MigrationStatus)>;
  31. SharedProtoDatabase(const SharedProtoDatabase&) = delete;
  32. SharedProtoDatabase& operator=(const SharedProtoDatabase&) = delete;
  33. // Always returns a SharedProtoDatabaseClient pointer, but that should ONLY
  34. // be used if the callback returns success.
  35. std::unique_ptr<SharedProtoDatabaseClient> GetClientForTesting(
  36. ProtoDbType db_type,
  37. bool create_if_missing,
  38. SharedClientInitCallback callback);
  39. // A version of GetClient that returns the client in a callback instead of
  40. // giving back a client instance immediately.
  41. void GetClientAsync(
  42. ProtoDbType db_type,
  43. bool create_if_missing,
  44. base::OnceCallback<void(std::unique_ptr<SharedProtoDatabaseClient>,
  45. Enums::InitStatus)> callback);
  46. void GetDatabaseInitStatusAsync(const std::string& client_db_id,
  47. Callbacks::InitStatusCallback callback);
  48. void UpdateClientMetadataAsync(
  49. const std::string& client_db_id,
  50. SharedDBMetadataProto::MigrationStatus migration_status,
  51. Callbacks::UpdateCallback callback);
  52. protected:
  53. SharedProtoDatabase(const std::string& client_db_id,
  54. const base::FilePath& db_dir);
  55. virtual ~SharedProtoDatabase();
  56. private:
  57. friend class base::RefCountedThreadSafe<SharedProtoDatabase>;
  58. friend class ProtoDatabaseProvider;
  59. template <typename T>
  60. friend class ProtoDatabaseImplTest;
  61. friend class SharedProtoDatabaseTest;
  62. friend class SharedProtoDatabaseClientTest;
  63. friend class TestSharedProtoDatabase;
  64. friend class TestSharedProtoDatabaseClient;
  65. FRIEND_TEST_ALL_PREFIXES(SharedProtoDatabaseTest,
  66. CancelDeleteObsoleteClients);
  67. FRIEND_TEST_ALL_PREFIXES(SharedProtoDatabaseTest, DeleteObsoleteClients);
  68. enum InitState {
  69. // Initialization hasn't been attempted.
  70. kNotAttempted,
  71. // Initialization is in progress, new requests will be enqueued.
  72. kInProgress,
  73. // Initialization successful, new requests will return existing DB.
  74. kSuccess,
  75. // Initialization failed, new requests will return InitStatus::kError.
  76. kFailure,
  77. // Shared database doesn't exist, new requests with create_if_missing ==
  78. // true will attempt to create it, if create_if_missing == false then will
  79. // return InitStatus::kInvalidOperation.
  80. kNotFound,
  81. };
  82. struct InitRequest {
  83. InitRequest(SharedClientInitCallback callback,
  84. const scoped_refptr<base::SequencedTaskRunner>& task_runner,
  85. const std::string& client_db_id);
  86. ~InitRequest();
  87. SharedClientInitCallback callback;
  88. scoped_refptr<base::SequencedTaskRunner> task_runner;
  89. std::string client_db_id;
  90. };
  91. // Make sure to give enough time after startup so that we have less chance of
  92. // affecting startup or navigations.
  93. static const base::TimeDelta kDelayToClearObsoleteDatabase;
  94. void Shutdown();
  95. void ProcessInitRequests(Enums::InitStatus status);
  96. std::unique_ptr<SharedProtoDatabaseClient> GetClientInternal(
  97. ProtoDbType db_type);
  98. void OnGetClientMetadata(
  99. const std::string& client_db_id,
  100. SharedClientInitCallback callback,
  101. scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
  102. bool success,
  103. std::unique_ptr<SharedDBMetadataProto> proto);
  104. // |callback_task_runner| should be the same sequence that Init was called
  105. // from.
  106. virtual void Init(
  107. bool create_if_missing,
  108. const std::string& client_db_id,
  109. SharedClientInitCallback callback,
  110. scoped_refptr<base::SequencedTaskRunner> callback_task_runner);
  111. void InitMetadataDatabase(int attempt, bool corruption);
  112. void OnMetadataInitComplete(int attempt,
  113. bool corruption,
  114. leveldb_proto::Enums::InitStatus status);
  115. void OnGetGlobalMetadata(bool corruption,
  116. bool success,
  117. std::unique_ptr<SharedDBMetadataProto> proto);
  118. void OnWriteMetadataAtInit(bool success);
  119. void OnDestroySharedDatabase(bool success);
  120. void InitDatabase();
  121. void OnDatabaseInit(bool create_if_missing, Enums::InitStatus status);
  122. void CheckCorruptionAndRunInitCallback(
  123. const std::string& client_db_id,
  124. SharedClientInitCallback callback,
  125. scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
  126. Enums::InitStatus status);
  127. void GetClientMetadataAsync(
  128. const std::string& client_db_id,
  129. SharedClientInitCallback callback,
  130. scoped_refptr<base::SequencedTaskRunner> callback_task_runner);
  131. void OnUpdateCorruptionCountAtInit(bool success);
  132. void CommitUpdatedGlobalMetadata(Callbacks::UpdateCallback callback);
  133. void RunInitCallback(
  134. Callbacks::InitStatusCallback callback,
  135. scoped_refptr<base::SequencedTaskRunner> callback_task_runner);
  136. // |done| will be called on |task_runner|.
  137. virtual void DestroyObsoleteSharedProtoDatabaseClients(
  138. Callbacks::UpdateCallback done);
  139. LevelDB* GetLevelDBForTesting() const;
  140. void SetDeleteObsoleteDelayForTesting(base::TimeDelta delay);
  141. scoped_refptr<base::SequencedTaskRunner> database_task_runner_for_testing()
  142. const {
  143. return task_runner_;
  144. }
  145. SEQUENCE_CHECKER(on_task_runner_);
  146. InitState init_state_ = InitState::kNotAttempted;
  147. // This TaskRunner is used to properly sequence Init calls and checks for the
  148. // current init state. When clients request the current InitState as part of
  149. // their call to their Init function, the request is put into this TaskRunner.
  150. scoped_refptr<base::SequencedTaskRunner> task_runner_;
  151. base::FilePath db_dir_;
  152. std::unique_ptr<LevelDB> db_;
  153. std::unique_ptr<ProtoLevelDBWrapper> db_wrapper_;
  154. std::unique_ptr<ProtoDatabase<SharedDBMetadataProto>> metadata_db_wrapper_;
  155. std::unique_ptr<SharedDBMetadataProto> metadata_;
  156. // Used to return to the Init callback in the case of an error, so we can
  157. // report corruptions.
  158. Enums::InitStatus init_status_ = Enums::InitStatus::kNotInitialized;
  159. base::queue<std::unique_ptr<InitRequest>> outstanding_init_requests_;
  160. bool create_if_missing_ = false;
  161. base::TimeDelta delete_obsolete_delay_ = base::Seconds(120);
  162. base::Lock delete_obsolete_delay_lock_;
  163. base::CancelableOnceClosure delete_obsolete_task_;
  164. };
  165. } // namespace leveldb_proto
  166. #endif // COMPONENTS_LEVELDB_PROTO_INTERNAL_SHARED_PROTO_DATABASE_H_