shared_proto_database_client.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  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. #include "components/leveldb_proto/internal/shared_proto_database_client.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/check.h"
  8. #include "base/check_op.h"
  9. #include "base/notreached.h"
  10. #include "base/strings/strcat.h"
  11. #include "base/strings/stringprintf.h"
  12. #include "components/leveldb_proto/internal/proto_leveldb_wrapper.h"
  13. #include "components/leveldb_proto/internal/shared_proto_database.h"
  14. #include "components/leveldb_proto/public/proto_database.h"
  15. #include "components/leveldb_proto/public/shared_proto_database_client_list.h"
  16. namespace leveldb_proto {
  17. namespace {
  18. const ProtoDbType* g_obsolete_client_list_for_testing = nullptr;
  19. // Holds the db wrapper alive and callback is called at destruction. This class
  20. // is used to post multiple update tasks on |db_wrapper| and keep the instance
  21. // alive till all the callbacks are returned.
  22. class ObsoleteClientsDbHolder
  23. : public base::RefCounted<ObsoleteClientsDbHolder> {
  24. public:
  25. ObsoleteClientsDbHolder(std::unique_ptr<ProtoLevelDBWrapper> db_wrapper,
  26. Callbacks::UpdateCallback callback)
  27. : success_(true),
  28. owned_db_wrapper_(std::move(db_wrapper)),
  29. callback_(std::move(callback)) {}
  30. void set_success(bool success) { success_ &= success; }
  31. private:
  32. friend class base::RefCounted<ObsoleteClientsDbHolder>;
  33. ~ObsoleteClientsDbHolder() { std::move(callback_).Run(success_); }
  34. bool success_;
  35. std::unique_ptr<ProtoLevelDBWrapper> owned_db_wrapper_;
  36. Callbacks::UpdateCallback callback_;
  37. };
  38. PhysicalKey MakePhysicalKey(const KeyPrefix& prefix, const LogicalKey& key) {
  39. return PhysicalKey(base::StrCat({prefix.value(), key.value()}));
  40. }
  41. } // namespace
  42. // static
  43. bool SharedProtoDatabaseClient::HasPrefix(const PhysicalKey& key,
  44. const KeyPrefix& prefix) {
  45. return base::StartsWith(key.value(), prefix.value(),
  46. base::CompareCase::SENSITIVE);
  47. }
  48. // static
  49. absl::optional<LogicalKey> SharedProtoDatabaseClient::StripPrefix(
  50. const PhysicalKey& key,
  51. const KeyPrefix& prefix) {
  52. if (!HasPrefix(key, prefix))
  53. return absl::nullopt;
  54. return LogicalKey(key.value().substr(prefix.value().length()));
  55. }
  56. // static
  57. std::unique_ptr<KeyVector> SharedProtoDatabaseClient::PrefixStrings(
  58. std::unique_ptr<KeyVector> strings,
  59. const KeyPrefix& prefix) {
  60. for (auto& str : *strings)
  61. str.assign(MakePhysicalKey(prefix, LogicalKey(str)).value());
  62. return strings;
  63. }
  64. // static
  65. bool SharedProtoDatabaseClient::KeyFilterStripPrefix(
  66. const KeyFilter& key_filter,
  67. const KeyPrefix& prefix,
  68. const PhysicalKey& key) {
  69. if (key_filter.is_null())
  70. return true;
  71. absl::optional<LogicalKey> stripped = StripPrefix(key, prefix);
  72. if (!stripped)
  73. return false;
  74. return key_filter.Run(stripped->value());
  75. }
  76. // static
  77. bool SharedProtoDatabaseClient::KeyStringFilterStripPrefix(
  78. const KeyFilter& key_filter,
  79. const KeyPrefix& prefix,
  80. const std::string& key) {
  81. return KeyFilterStripPrefix(key_filter, prefix, PhysicalKey(key));
  82. }
  83. // static
  84. Enums::KeyIteratorAction
  85. SharedProtoDatabaseClient::KeyIteratorControllerStripPrefix(
  86. const KeyIteratorController& controller,
  87. const KeyPrefix& prefix,
  88. const PhysicalKey& key) {
  89. DCHECK(!controller.is_null());
  90. absl::optional<LogicalKey> stripped = StripPrefix(key, prefix);
  91. if (!stripped)
  92. return Enums::kSkipAndStop;
  93. return controller.Run(stripped->value());
  94. }
  95. // static
  96. Enums::KeyIteratorAction
  97. SharedProtoDatabaseClient::KeyStringIteratorControllerStripPrefix(
  98. const KeyIteratorController& controller,
  99. const KeyPrefix& prefix,
  100. const std::string& key) {
  101. return KeyIteratorControllerStripPrefix(controller, prefix, PhysicalKey(key));
  102. }
  103. // static
  104. void SharedProtoDatabaseClient::GetSharedDatabaseInitStatusAsync(
  105. const std::string& client_db_id,
  106. const scoped_refptr<SharedProtoDatabase>& shared_db,
  107. Callbacks::InitStatusCallback callback) {
  108. shared_db->GetDatabaseInitStatusAsync(client_db_id, std::move(callback));
  109. }
  110. // static
  111. void SharedProtoDatabaseClient::UpdateClientMetadataAsync(
  112. const scoped_refptr<SharedProtoDatabase>& shared_db,
  113. const std::string& client_db_id,
  114. SharedDBMetadataProto::MigrationStatus migration_status,
  115. ClientCorruptCallback callback) {
  116. shared_db->UpdateClientMetadataAsync(client_db_id, migration_status,
  117. std::move(callback));
  118. }
  119. // static
  120. void SharedProtoDatabaseClient::DestroyObsoleteSharedProtoDatabaseClients(
  121. std::unique_ptr<ProtoLevelDBWrapper> db_wrapper,
  122. Callbacks::UpdateCallback callback) {
  123. ProtoLevelDBWrapper* db_wrapper_ptr = db_wrapper.get();
  124. scoped_refptr<ObsoleteClientsDbHolder> db_holder =
  125. new ObsoleteClientsDbHolder(std::move(db_wrapper), std::move(callback));
  126. const ProtoDbType* list = g_obsolete_client_list_for_testing
  127. ? g_obsolete_client_list_for_testing
  128. : kObsoleteSharedProtoDbTypeClients;
  129. for (size_t i = 0; list[i] != ProtoDbType::LAST; ++i) {
  130. // Callback keeps a ref pointer to db_holder alive till the changes are
  131. // done. |db_holder| will be destroyed once all the RemoveKeys() calls
  132. // return.
  133. Callbacks::UpdateCallback callback_wrapper =
  134. base::BindOnce([](scoped_refptr<ObsoleteClientsDbHolder> db_holder,
  135. bool success) { db_holder->set_success(success); },
  136. db_holder);
  137. // Remove all type prefixes for the client.
  138. // TODO(ssid): Support cleanup of namespaces for clients. This code assumes
  139. // the prefix contains the client namespace at the beginning.
  140. db_wrapper_ptr->RemoveKeys(
  141. base::BindRepeating([](const std::string& key) { return true; }),
  142. SharedProtoDatabaseClient::PrefixForDatabase(list[i]).value(),
  143. std::move(callback_wrapper));
  144. }
  145. }
  146. // static
  147. void SharedProtoDatabaseClient::SetObsoleteClientListForTesting(
  148. const ProtoDbType* list) {
  149. g_obsolete_client_list_for_testing = list;
  150. }
  151. // static
  152. KeyPrefix SharedProtoDatabaseClient::PrefixForDatabase(ProtoDbType db_type) {
  153. return KeyPrefix(base::StringPrintf("%d_", static_cast<int>(db_type)));
  154. }
  155. SharedProtoDatabaseClient::SharedProtoDatabaseClient(
  156. std::unique_ptr<ProtoLevelDBWrapper> db_wrapper,
  157. ProtoDbType db_type,
  158. const scoped_refptr<SharedProtoDatabase>& parent_db)
  159. : UniqueProtoDatabase(std::move(db_wrapper)),
  160. prefix_(PrefixForDatabase(db_type)),
  161. parent_db_(parent_db) {
  162. DETACH_FROM_SEQUENCE(sequence_checker_);
  163. }
  164. SharedProtoDatabaseClient::~SharedProtoDatabaseClient() {
  165. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  166. }
  167. void SharedProtoDatabaseClient::Init(const std::string& client_uma_name,
  168. Callbacks::InitStatusCallback callback) {
  169. SetMetricsId(client_uma_name);
  170. GetSharedDatabaseInitStatusAsync(client_db_id(), parent_db_,
  171. std::move(callback));
  172. }
  173. void SharedProtoDatabaseClient::InitWithDatabase(
  174. LevelDB* database,
  175. const base::FilePath& database_dir,
  176. const leveldb_env::Options& options,
  177. bool destroy_on_corruption,
  178. Callbacks::InitStatusCallback callback) {
  179. NOTREACHED();
  180. }
  181. void SharedProtoDatabaseClient::UpdateEntries(
  182. std::unique_ptr<KeyValueVector> entries_to_save,
  183. std::unique_ptr<KeyVector> keys_to_remove,
  184. Callbacks::UpdateCallback callback) {
  185. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  186. UniqueProtoDatabase::UpdateEntries(
  187. PrefixKeyEntryVector(std::move(entries_to_save), prefix_),
  188. PrefixStrings(std::move(keys_to_remove), prefix_), std::move(callback));
  189. }
  190. void SharedProtoDatabaseClient::UpdateEntriesWithRemoveFilter(
  191. std::unique_ptr<KeyValueVector> entries_to_save,
  192. const KeyFilter& delete_key_filter,
  193. Callbacks::UpdateCallback callback) {
  194. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  195. UpdateEntriesWithRemoveFilter(std::move(entries_to_save), delete_key_filter,
  196. std::string(), std::move(callback));
  197. }
  198. void SharedProtoDatabaseClient::UpdateEntriesWithRemoveFilter(
  199. std::unique_ptr<KeyValueVector> entries_to_save,
  200. const KeyFilter& delete_key_filter,
  201. const std::string& target_prefix,
  202. Callbacks::UpdateCallback callback) {
  203. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  204. UniqueProtoDatabase::UpdateEntriesWithRemoveFilter(
  205. PrefixKeyEntryVector(std::move(entries_to_save), prefix_),
  206. base::BindRepeating(&KeyStringFilterStripPrefix, delete_key_filter,
  207. prefix_),
  208. MakePhysicalKey(prefix_, LogicalKey(target_prefix)).value(),
  209. std::move(callback));
  210. }
  211. void SharedProtoDatabaseClient::LoadEntries(Callbacks::LoadCallback callback) {
  212. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  213. LoadEntriesWithFilter(KeyFilter(), std::move(callback));
  214. }
  215. void SharedProtoDatabaseClient::LoadEntriesWithFilter(
  216. const KeyFilter& filter,
  217. Callbacks::LoadCallback callback) {
  218. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  219. LoadEntriesWithFilter(filter, leveldb::ReadOptions(), std::string(),
  220. std::move(callback));
  221. }
  222. void SharedProtoDatabaseClient::LoadEntriesWithFilter(
  223. const KeyFilter& filter,
  224. const leveldb::ReadOptions& options,
  225. const std::string& target_prefix,
  226. Callbacks::LoadCallback callback) {
  227. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  228. UniqueProtoDatabase::LoadEntriesWithFilter(
  229. base::BindRepeating(&KeyStringFilterStripPrefix, filter, prefix_),
  230. options, MakePhysicalKey(prefix_, LogicalKey(target_prefix)).value(),
  231. std::move(callback));
  232. }
  233. void SharedProtoDatabaseClient::LoadKeys(Callbacks::LoadKeysCallback callback) {
  234. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  235. LoadKeys(std::string(), std::move(callback));
  236. }
  237. void SharedProtoDatabaseClient::LoadKeys(const std::string& target_prefix,
  238. Callbacks::LoadKeysCallback callback) {
  239. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  240. UniqueProtoDatabase::LoadKeys(
  241. MakePhysicalKey(prefix_, LogicalKey(target_prefix)).value(),
  242. base::BindOnce(&SharedProtoDatabaseClient::StripPrefixLoadKeysCallback,
  243. std::move(callback), prefix_));
  244. }
  245. void SharedProtoDatabaseClient::LoadKeysAndEntries(
  246. Callbacks::LoadKeysAndEntriesCallback callback) {
  247. LoadKeysAndEntriesWithFilter(KeyFilter(), std::move(callback));
  248. }
  249. void SharedProtoDatabaseClient::LoadKeysAndEntriesWithFilter(
  250. const KeyFilter& filter,
  251. Callbacks::LoadKeysAndEntriesCallback callback) {
  252. LoadKeysAndEntriesWithFilter(filter, leveldb::ReadOptions(), std::string(),
  253. std::move(callback));
  254. }
  255. void SharedProtoDatabaseClient::LoadKeysAndEntriesWithFilter(
  256. const KeyFilter& filter,
  257. const leveldb::ReadOptions& options,
  258. const std::string& target_prefix,
  259. Callbacks::LoadKeysAndEntriesCallback callback) {
  260. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  261. UniqueProtoDatabase::LoadKeysAndEntriesWithFilter(
  262. base::BindRepeating(&KeyStringFilterStripPrefix, filter, prefix_),
  263. options, MakePhysicalKey(prefix_, LogicalKey(target_prefix)).value(),
  264. base::BindOnce(
  265. &SharedProtoDatabaseClient::StripPrefixLoadKeysAndEntriesCallback,
  266. std::move(callback), prefix_));
  267. }
  268. void SharedProtoDatabaseClient::LoadKeysAndEntriesInRange(
  269. const std::string& start,
  270. const std::string& end,
  271. Callbacks::LoadKeysAndEntriesCallback callback) {
  272. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  273. UniqueProtoDatabase::LoadKeysAndEntriesInRange(
  274. MakePhysicalKey(prefix_, LogicalKey(start)).value(),
  275. MakePhysicalKey(prefix_, LogicalKey(end)).value(),
  276. base::BindOnce(
  277. &SharedProtoDatabaseClient::StripPrefixLoadKeysAndEntriesCallback,
  278. std::move(callback), prefix_));
  279. }
  280. void SharedProtoDatabaseClient::LoadKeysAndEntriesWhile(
  281. const std::string& start,
  282. const leveldb_proto::KeyIteratorController& controller,
  283. Callbacks::LoadKeysAndEntriesCallback callback) {
  284. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  285. UniqueProtoDatabase::LoadKeysAndEntriesWhile(
  286. MakePhysicalKey(prefix_, LogicalKey(start)).value(),
  287. base::BindRepeating(&KeyStringIteratorControllerStripPrefix, controller,
  288. prefix_),
  289. base::BindOnce(
  290. &SharedProtoDatabaseClient::StripPrefixLoadKeysAndEntriesCallback,
  291. std::move(callback), prefix_));
  292. }
  293. void SharedProtoDatabaseClient::GetEntry(const std::string& key,
  294. Callbacks::GetCallback callback) {
  295. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  296. UniqueProtoDatabase::GetEntry(
  297. MakePhysicalKey(prefix_, LogicalKey(key)).value(), std::move(callback));
  298. }
  299. void SharedProtoDatabaseClient::Destroy(Callbacks::DestroyCallback callback) {
  300. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  301. UpdateEntriesWithRemoveFilter(
  302. std::make_unique<KeyValueVector>(),
  303. base::BindRepeating([](const std::string& key) { return true; }),
  304. base::BindOnce([](Callbacks::DestroyCallback callback,
  305. bool success) { std::move(callback).Run(success); },
  306. std::move(callback)));
  307. }
  308. void SharedProtoDatabaseClient::UpdateClientInitMetadata(
  309. SharedDBMetadataProto::MigrationStatus migration_status) {
  310. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  311. migration_status_ = migration_status;
  312. // Tell the SharedProtoDatabase that we've seen the corruption state so it's
  313. // safe to update its records for this client.
  314. UpdateClientMetadataAsync(parent_db_, client_db_id(), migration_status_,
  315. base::BindOnce([](bool success) {
  316. // TODO(thildebr): Should we do anything special
  317. // here? If the shared DB can't update the
  318. // client's corruption counter to match its own,
  319. // then the client will think it's corrupt on the
  320. // next Init as well.
  321. }));
  322. }
  323. // static
  324. void SharedProtoDatabaseClient::StripPrefixLoadKeysCallback(
  325. Callbacks::LoadKeysCallback callback,
  326. const KeyPrefix& prefix,
  327. bool success,
  328. std::unique_ptr<leveldb_proto::KeyVector> keys) {
  329. auto stripped_keys = std::make_unique<leveldb_proto::KeyVector>();
  330. for (auto& key : *keys) {
  331. absl::optional<LogicalKey> stripped = StripPrefix(PhysicalKey(key), prefix);
  332. if (!stripped)
  333. continue;
  334. stripped_keys->emplace_back(stripped->value());
  335. }
  336. std::move(callback).Run(success, std::move(stripped_keys));
  337. }
  338. // static
  339. void SharedProtoDatabaseClient::StripPrefixLoadKeysAndEntriesCallback(
  340. Callbacks::LoadKeysAndEntriesCallback callback,
  341. const KeyPrefix& prefix,
  342. bool success,
  343. std::unique_ptr<KeyValueMap> keys_entries) {
  344. auto stripped_keys_map = std::make_unique<KeyValueMap>();
  345. for (auto& key_entry : *keys_entries) {
  346. absl::optional<LogicalKey> stripped_key =
  347. StripPrefix(PhysicalKey(key_entry.first), prefix);
  348. if (!stripped_key)
  349. continue;
  350. stripped_keys_map->insert(
  351. std::make_pair(stripped_key->value(), key_entry.second));
  352. }
  353. std::move(callback).Run(success, std::move(stripped_keys_map));
  354. }
  355. // static
  356. std::unique_ptr<KeyValueVector> SharedProtoDatabaseClient::PrefixKeyEntryVector(
  357. std::unique_ptr<KeyValueVector> kev,
  358. const KeyPrefix& prefix) {
  359. for (auto& key_entry_pair : *kev) {
  360. key_entry_pair.first =
  361. MakePhysicalKey(prefix, LogicalKey(key_entry_pair.first)).value();
  362. }
  363. return kev;
  364. }
  365. } // namespace leveldb_proto