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