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