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
5 #ifndef COMPONENTS_LEVELDB_PROTO_INTERNAL_SHARED_PROTO_DATABASE_CLIENT_H_
6 #define COMPONENTS_LEVELDB_PROTO_INTERNAL_SHARED_PROTO_DATABASE_CLIENT_H_
7
8 #include <memory>
9 #include <string>
10
11 #include "base/bind.h"
12 #include "base/component_export.h"
13 #include "base/sequence_checker.h"
14 #include "components/leveldb_proto/internal/leveldb_database.h"
15 #include "components/leveldb_proto/internal/proto/shared_db_metadata.pb.h"
16 #include "components/leveldb_proto/internal/unique_proto_database.h"
17 #include "components/leveldb_proto/public/shared_proto_database_client_list.h"
18
19 namespace leveldb_proto {
20
21 class SharedProtoDatabase;
22
23 // TODO: Move all these as static or member functions in the class.
24 using ClientCorruptCallback = base::OnceCallback<void(bool)>;
25 using SharedClientInitCallback =
26 base::OnceCallback<void(Enums::InitStatus,
27 SharedDBMetadataProto::MigrationStatus)>;
28
29 // An implementation of ProtoDatabase<T> that uses a shared LevelDB and task
30 // runner.
31 // Should be created, destroyed, and used on the same sequenced task runner.
COMPONENT_EXPORT(LEVELDB_PROTO)32 class COMPONENT_EXPORT(LEVELDB_PROTO) SharedProtoDatabaseClient
33 : public UniqueProtoDatabase {
34 public:
35 static std::string PrefixForDatabase(ProtoDbType db_type);
36
37 static std::string StripPrefix(const std::string& key,
38 const std::string& prefix);
39
40 static std::unique_ptr<KeyVector> PrefixStrings(
41 std::unique_ptr<KeyVector> strings,
42 const std::string& prefix);
43
44 static bool KeyFilterStripPrefix(const KeyFilter& key_filter,
45 const std::string& prefix,
46 const std::string& key);
47
48 static void GetSharedDatabaseInitStatusAsync(
49 const std::string& client_db_id,
50 const scoped_refptr<SharedProtoDatabase>& db,
51 Callbacks::InitStatusCallback callback);
52
53 static void UpdateClientMetadataAsync(
54 const scoped_refptr<SharedProtoDatabase>& db,
55 const std::string& client_db_id,
56 SharedDBMetadataProto::MigrationStatus migration_status,
57 ClientCorruptCallback callback);
58
59 // Destroys all the data from obsolete clients, for the given |db_wrapper|
60 // instance. |callback| is called once all the obsolete clients data are
61 // removed, with failure status if one or more of the update fails.
62 static void DestroyObsoleteSharedProtoDatabaseClients(
63 std::unique_ptr<ProtoLevelDBWrapper> db_wrapper,
64 Callbacks::UpdateCallback callback);
65
66 // Sets list of client names that are obsolete and will be cleared by next
67 // call to DestroyObsoleteSharedProtoDatabaseClients(). |list| is list of dbs
68 // with a |LAST| to mark the end of list.
69 static void SetObsoleteClientListForTesting(const ProtoDbType* list);
70
71 ~SharedProtoDatabaseClient() override;
72
73 void Init(const std::string& client_uma_name,
74 Callbacks::InitStatusCallback callback) override;
75
76 void InitWithDatabase(LevelDB* database,
77 const base::FilePath& database_dir,
78 const leveldb_env::Options& options,
79 bool destroy_on_corruption,
80 Callbacks::InitStatusCallback callback) override;
81
82 // Overrides for prepending namespace and type prefix to all operations on the
83 // shared database.
84 void UpdateEntries(std::unique_ptr<KeyValueVector> entries_to_save,
85 std::unique_ptr<KeyVector> keys_to_remove,
86 Callbacks::UpdateCallback callback) override;
87 void UpdateEntriesWithRemoveFilter(
88 std::unique_ptr<KeyValueVector> entries_to_save,
89 const KeyFilter& delete_key_filter,
90 Callbacks::UpdateCallback callback) override;
91 void UpdateEntriesWithRemoveFilter(
92 std::unique_ptr<KeyValueVector> entries_to_save,
93 const KeyFilter& delete_key_filter,
94 const std::string& target_prefix,
95 Callbacks::UpdateCallback callback) override;
96
97 void LoadEntries(Callbacks::LoadCallback callback) override;
98 void LoadEntriesWithFilter(const KeyFilter& filter,
99 Callbacks::LoadCallback callback) override;
100 void LoadEntriesWithFilter(const KeyFilter& key_filter,
101 const leveldb::ReadOptions& options,
102 const std::string& target_prefix,
103 Callbacks::LoadCallback callback) override;
104
105 void LoadKeys(Callbacks::LoadKeysCallback callback) override;
106 void LoadKeys(const std::string& target_prefix,
107 Callbacks::LoadKeysCallback callback) override;
108
109 void LoadKeysAndEntries(
110 Callbacks::LoadKeysAndEntriesCallback callback) override;
111 void LoadKeysAndEntriesWithFilter(
112 const KeyFilter& filter,
113 Callbacks::LoadKeysAndEntriesCallback callback) override;
114 void LoadKeysAndEntriesWithFilter(
115 const KeyFilter& filter,
116 const leveldb::ReadOptions& options,
117 const std::string& target_prefix,
118 Callbacks::LoadKeysAndEntriesCallback callback) override;
119 void LoadKeysAndEntriesInRange(
120 const std::string& start,
121 const std::string& end,
122 Callbacks::LoadKeysAndEntriesCallback callback) override;
123
124 void GetEntry(const std::string& key,
125 Callbacks::GetCallback callback) override;
126
127 void Destroy(Callbacks::DestroyCallback callback) override;
128
129 Callbacks::InitCallback GetInitCallback() const;
130
131 const std::string& client_db_id() const { return prefix_; }
132
133 void set_migration_status(
134 SharedDBMetadataProto::MigrationStatus migration_status) {
135 migration_status_ = migration_status;
136 }
137
138 virtual void UpdateClientInitMetadata(SharedDBMetadataProto::MigrationStatus);
139
140 SharedDBMetadataProto::MigrationStatus migration_status() const {
141 return migration_status_;
142 }
143
144 private:
145 friend class SharedProtoDatabase;
146 friend class SharedProtoDatabaseTest;
147 friend class SharedProtoDatabaseClientTest;
148 friend class TestSharedProtoDatabaseClient;
149
150 // Hide this so clients can only be created by the SharedProtoDatabase.
151 SharedProtoDatabaseClient(
152 std::unique_ptr<ProtoLevelDBWrapper> db_wrapper,
153 ProtoDbType db_type,
154 const scoped_refptr<SharedProtoDatabase>& parent_db);
155
156 static void StripPrefixLoadKeysCallback(
157 Callbacks::LoadKeysCallback callback,
158 const std::string& prefix,
159 bool success,
160 std::unique_ptr<leveldb_proto::KeyVector> keys);
161 static void StripPrefixLoadKeysAndEntriesCallback(
162 Callbacks::LoadKeysAndEntriesCallback callback,
163 const std::string& prefix,
164 bool success,
165 std::unique_ptr<KeyValueMap> keys_entries);
166
167 static std::unique_ptr<KeyValueVector> PrefixKeyEntryVector(
168 std::unique_ptr<KeyValueVector> kev,
169 const std::string& prefix);
170
171 SEQUENCE_CHECKER(sequence_checker_);
172
173 // |is_corrupt_| should be set by the SharedProtoDatabase that creates this
174 // when a client is created that doesn't know about a previous shared
175 // database corruption.
176 bool is_corrupt_ = false;
177 SharedDBMetadataProto::MigrationStatus migration_status_ =
178 SharedDBMetadataProto::MIGRATION_NOT_ATTEMPTED;
179
180 const std::string prefix_;
181
182 scoped_refptr<SharedProtoDatabase> parent_db_;
183
184 base::WeakPtrFactory<SharedProtoDatabaseClient> weak_ptr_factory_{this};
185
186 DISALLOW_COPY_AND_ASSIGN(SharedProtoDatabaseClient);
187 };
188
189 } // namespace leveldb_proto
190
191 #endif // COMPONENTS_LEVELDB_PROTO_INTERNAL_SHARED_PROTO_DATABASE_CLIENT_H_
192