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 
5 #ifndef COMPONENTS_LEVELDB_PROTO_INTERNAL_PROTO_DATABASE_SELECTOR_H_
6 #define COMPONENTS_LEVELDB_PROTO_INTERNAL_PROTO_DATABASE_SELECTOR_H_
7 
8 #include <memory>
9 #include <string>
10 
11 #include "base/component_export.h"
12 #include "base/containers/queue.h"
13 #include "base/files/file_path.h"
14 #include "base/sequenced_task_runner.h"
15 #include "components/leveldb_proto/internal/proto_leveldb_wrapper.h"
16 #include "components/leveldb_proto/public/shared_proto_database_client_list.h"
17 
18 namespace leveldb_proto {
19 
20 class MigrationDelegate;
21 class SharedProtoDatabase;
22 class SharedProtoDatabaseClient;
23 class SharedProtoDatabaseProvider;
24 class UniqueProtoDatabase;
25 
26 // A wrapper around unique and shared database client. Handles initialization of
27 // underlying database as unique or shared as requested.
28 // TODO: Discuss the init flow/migration path for unique/shared DB here.
COMPONENT_EXPORT(LEVELDB_PROTO)29 class COMPONENT_EXPORT(LEVELDB_PROTO) ProtoDatabaseSelector
30     : public base::RefCountedThreadSafe<ProtoDatabaseSelector> {
31  public:
32   // These values are logged to UMA. Entries should not be renumbered and
33   // numeric values should never be reused. Please keep in sync with
34   // "ProtoDatabaseInitState" in src/tools/metrics/histograms/enums.xml.
35   enum class ProtoDatabaseInitState {
36     kSharedDbInitAttempted = 0,
37     kFailureUniqueDbCorrupted = 1,
38     kFailureNoDatabaseProvider = 2,  // Deprecated.
39     kBothUniqueAndSharedFailedOpen = 3,
40     kSharedDbClientMissingInitFailed = 4,
41     kSharedDbClientMissingUniqueReturned = 5,
42     kSharedDbOpenFailed = 6,
43     kUniqueDbMissingSharedReturned = 7,
44     kUniqueDbOpenFailed = 8,
45     kMigrateToSharedAttempted = 9,
46     kMigrateToUniqueAttempted = 10,
47     kMigratedSharedDbOpened = 11,
48     kDeletionOfOldDataFailed = 12,
49     kMigrateToSharedFailed = 13,
50     kMigrateToUniqueFailed = 14,
51     kMigrateToSharedCompleteDeletionFailed = 15,
52     kMigrateToUniqueCompleteDeletionFailed = 16,
53     kMigrateToSharedSuccess = 17,
54     kMigrateToUniqueSuccess = 18,
55     kLegacyInitCalled = 19,
56     kSharedDbMetadataLoadFailed = 20,
57     kSharedDbMetadataWriteFailed = 21,
58     kSharedDbClientCorrupt = 22,
59     kSharedDbClientSuccess = 23,
60     kSharedLevelDbInitFailure = 24,
61     kSharedDbClientMissing = 25,
62     kFailureNoSharedDBProviderUniqueFailed = 26,
63     kSuccessNoSharedDBProviderUniqueSucceeded = 27,
64     kMaxValue = kSuccessNoSharedDBProviderUniqueSucceeded,
65   };
66 
67   static void RecordInitState(ProtoDatabaseInitState state);
68 
69   ProtoDatabaseSelector(
70       ProtoDbType db_type,
71       scoped_refptr<base::SequencedTaskRunner> task_runner,
72       std::unique_ptr<SharedProtoDatabaseProvider> db_provider);
73 
74   void InitWithDatabase(
75       LevelDB* database,
76       const base::FilePath& database_dir,
77       const leveldb_env::Options& options,
78       scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
79       Callbacks::InitStatusCallback callback);
80 
81   void InitUniqueOrShared(
82       const std::string& client_name,
83       base::FilePath db_dir,
84       const leveldb_env::Options& unique_db_options,
85       bool use_shared_db,
86       scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
87       Callbacks::InitStatusCallback callback);
88 
89   void AddTransaction(base::OnceClosure task);
90 
91   // DO NOT USE any of the functions below directly. They should be posted as
92   // transaction tasks using AddTransaction().
93   void UpdateEntries(std::unique_ptr<KeyValueVector> entries_to_save,
94                      std::unique_ptr<KeyVector> keys_to_remove,
95                      Callbacks::UpdateCallback callback);
96 
97   void UpdateEntriesWithRemoveFilter(
98       std::unique_ptr<KeyValueVector> entries_to_save,
99       const KeyFilter& delete_key_filter,
100       Callbacks::UpdateCallback callback);
101 
102   void LoadEntries(typename Callbacks::LoadCallback callback);
103 
104   void LoadEntriesWithFilter(const KeyFilter& key_filter,
105                              const leveldb::ReadOptions& options,
106                              const std::string& target_prefix,
107                              typename Callbacks::LoadCallback callback);
108 
109   void LoadKeysAndEntries(
110       typename Callbacks::LoadKeysAndEntriesCallback callback);
111 
112   void LoadKeysAndEntriesWithFilter(
113       const KeyFilter& filter,
114       const leveldb::ReadOptions& options,
115       const std::string& target_prefix,
116       typename Callbacks::LoadKeysAndEntriesCallback callback);
117   void LoadKeysAndEntriesInRange(
118       const std::string& start,
119       const std::string& end,
120       typename Callbacks::LoadKeysAndEntriesCallback callback);
121 
122   void LoadKeys(Callbacks::LoadKeysCallback callback);
123 
124   void GetEntry(const std::string& key,
125                 typename Callbacks::GetCallback callback);
126 
127   void Destroy(Callbacks::DestroyCallback callback);
128 
129   void RemoveKeysForTesting(const KeyFilter& key_filter,
130                             const std::string& target_prefix,
131                             Callbacks::UpdateCallback callback);
132 
133   UniqueProtoDatabase* db_for_testing() { return db_.get(); }
134 
135  private:
136   friend class base::RefCountedThreadSafe<ProtoDatabaseSelector>;
137   template <typename T>
138   friend class ProtoDatabaseImplTest;
139 
140   enum class InitStatus {
141     NOT_STARTED,
142     IN_PROGRESS,
143     DONE  // success or failure.
144   };
145 
146   ~ProtoDatabaseSelector();
147 
148   void OnInitUniqueDB(std::unique_ptr<UniqueProtoDatabase> db,
149                       bool use_shared_db,
150                       Callbacks::InitStatusCallback callback,
151                       Enums::InitStatus status);
152 
153   void OnInitSharedDB(std::unique_ptr<UniqueProtoDatabase> unique_db,
154                       Enums::InitStatus unique_db_status,
155                       bool use_shared_db,
156                       Callbacks::InitStatusCallback callback,
157                       scoped_refptr<SharedProtoDatabase> shared_db);
158   void OnGetSharedDBClient(std::unique_ptr<UniqueProtoDatabase> unique_db,
159                            Enums::InitStatus unique_db_status,
160                            bool use_shared_db,
161                            Callbacks::InitStatusCallback callback,
162                            std::unique_ptr<SharedProtoDatabaseClient> client,
163                            Enums::InitStatus shared_db_status);
164   void DeleteOldDataAndMigrate(
165       std::unique_ptr<UniqueProtoDatabase> unique_db,
166       std::unique_ptr<SharedProtoDatabaseClient> client,
167       bool use_shared_db,
168       Callbacks::InitStatusCallback callback);
169   void MaybeDoMigrationOnDeletingOld(
170       std::unique_ptr<UniqueProtoDatabase> unique_db,
171       std::unique_ptr<SharedProtoDatabaseClient> client,
172       Callbacks::InitStatusCallback init_callback,
173       bool use_shared_db,
174       bool delete_success);
175   void OnMigrationTransferComplete(
176       std::unique_ptr<UniqueProtoDatabase> unique_db,
177       std::unique_ptr<SharedProtoDatabaseClient> client,
178       bool use_shared_db,
179       Callbacks::InitStatusCallback callback,
180       bool success);
181   void OnMigrationCleanupComplete(
182       std::unique_ptr<UniqueProtoDatabase> unique_db,
183       std::unique_ptr<SharedProtoDatabaseClient> client,
184       bool use_shared_db,
185       Callbacks::InitStatusCallback callback,
186       bool success);
187   void OnInitDone(ProtoDatabaseInitState state);
188 
189   ProtoDbType db_type_;
190   const scoped_refptr<base::SequencedTaskRunner> task_runner_;
191   const std::unique_ptr<SharedProtoDatabaseProvider> db_provider_;
192   const std::unique_ptr<MigrationDelegate> migration_delegate_;
193 
194   InitStatus init_status_ = InitStatus::NOT_STARTED;
195   base::queue<base::OnceClosure> pending_tasks_;
196   std::unique_ptr<UniqueProtoDatabase> db_;
197   base::FilePath unique_database_dir_;
198   std::string client_name_;
199 
200   SEQUENCE_CHECKER(sequence_checker_);
201 };
202 
203 }  // namespace leveldb_proto
204 
205 #endif  // COMPONENTS_LEVELDB_PROTO_INTERNAL_PROTO_DATABASE_SELECTOR_H_
206