proto_database_selector.cc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  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. #include "components/leveldb_proto/internal/proto_database_selector.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/check_op.h"
  8. #include "base/metrics/histogram_macros.h"
  9. #include "base/notreached.h"
  10. #include "components/leveldb_proto/internal/migration_delegate.h"
  11. #include "components/leveldb_proto/internal/shared_proto_database.h"
  12. #include "components/leveldb_proto/internal/shared_proto_database_provider.h"
  13. #include "components/leveldb_proto/internal/unique_proto_database.h"
  14. namespace leveldb_proto {
  15. namespace {
  16. void RunInitCallbackOnTaskRunner(
  17. Callbacks::InitStatusCallback callback,
  18. scoped_refptr<base::SequencedTaskRunner> task_runner,
  19. Enums::InitStatus status) {
  20. task_runner->PostTask(FROM_HERE, base::BindOnce(std::move(callback), status));
  21. }
  22. } // namespace
  23. // static
  24. void ProtoDatabaseSelector::RecordInitState(
  25. ProtoDatabaseSelector::ProtoDatabaseInitState state) {
  26. UMA_HISTOGRAM_ENUMERATION("ProtoDB.SharedDbInitStatus", state);
  27. }
  28. ProtoDatabaseSelector::ProtoDatabaseSelector(
  29. ProtoDbType db_type,
  30. scoped_refptr<base::SequencedTaskRunner> task_runner,
  31. std::unique_ptr<SharedProtoDatabaseProvider> db_provider)
  32. : db_type_(db_type),
  33. task_runner_(task_runner),
  34. db_provider_(std::move(db_provider)),
  35. migration_delegate_(std::make_unique<MigrationDelegate>()) {
  36. DETACH_FROM_SEQUENCE(sequence_checker_);
  37. }
  38. ProtoDatabaseSelector::~ProtoDatabaseSelector() {
  39. if (db_)
  40. task_runner_->DeleteSoon(FROM_HERE, std::move(db_));
  41. }
  42. void ProtoDatabaseSelector::InitWithDatabase(
  43. LevelDB* database,
  44. const base::FilePath& database_dir,
  45. const leveldb_env::Options& options,
  46. scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
  47. Callbacks::InitStatusCallback callback) {
  48. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  49. if (!db_)
  50. db_ = std::make_unique<UniqueProtoDatabase>(task_runner_);
  51. unique_database_dir_ = database_dir;
  52. db_->InitWithDatabase(
  53. database, database_dir, options, false,
  54. base::BindOnce(&RunInitCallbackOnTaskRunner, std::move(callback),
  55. callback_task_runner));
  56. OnInitDone(ProtoDatabaseInitState::kLegacyInitCalled);
  57. }
  58. void ProtoDatabaseSelector::InitUniqueOrShared(
  59. const std::string& client_name,
  60. base::FilePath db_dir,
  61. const leveldb_env::Options& unique_db_options,
  62. bool use_shared_db,
  63. scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
  64. Callbacks::InitStatusCallback callback) {
  65. RecordInitState(ProtoDatabaseInitState::kSharedDbInitAttempted);
  66. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  67. init_status_ = InitStatus::IN_PROGRESS;
  68. unique_database_dir_ = db_dir;
  69. client_name_ = client_name;
  70. if (unique_database_dir_.empty()) {
  71. DCHECK(!use_shared_db) << "Opening in memory shared db is not supported";
  72. // In case we set up field trials by mistake, ignore the use shared flag and
  73. // return unique db.
  74. use_shared_db = false;
  75. }
  76. auto unique_options = unique_db_options;
  77. // There are two Init methods, one that receives Options for its unique DB and
  78. // another that uses CreateSimpleOptions() to open the unique DB. In case a
  79. // shared DB needs to be used then we don't need to create a new unique DB if
  80. // it doesn't exist. In case a unique DB needs to be used then we don't change
  81. // the create_if_missing parameter, because it may have been set by a client.
  82. if (use_shared_db) {
  83. unique_options.create_if_missing = false;
  84. }
  85. auto unique_db = std::make_unique<UniqueProtoDatabase>(db_dir, unique_options,
  86. task_runner_);
  87. auto* unique_db_ptr = unique_db.get();
  88. unique_db_ptr->Init(
  89. client_name, base::BindOnce(&ProtoDatabaseSelector::OnInitUniqueDB, this,
  90. std::move(unique_db), use_shared_db,
  91. base::BindOnce(&RunInitCallbackOnTaskRunner,
  92. std::move(callback),
  93. callback_task_runner)));
  94. }
  95. void ProtoDatabaseSelector::OnInitUniqueDB(
  96. std::unique_ptr<UniqueProtoDatabase> unique_db,
  97. bool use_shared_db,
  98. Callbacks::InitStatusCallback callback,
  99. Enums::InitStatus status) {
  100. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  101. // If the unique DB is corrupt, just return it early with the corruption
  102. // status to avoid silently migrating a corrupt database and giving no errors
  103. // back.
  104. if (status == Enums::InitStatus::kCorrupt) {
  105. db_ = std::move(unique_db);
  106. std::move(callback).Run(Enums::InitStatus::kCorrupt);
  107. OnInitDone(ProtoDatabaseInitState::kFailureUniqueDbCorrupted);
  108. return;
  109. }
  110. // Clear out the unique_db before sending an unusable DB into InitSharedDB,
  111. // a nullptr indicates opening a unique DB failed.
  112. if (status != Enums::InitStatus::kOK)
  113. unique_db.reset();
  114. // If no SharedProtoDatabaseProvider is set then we use the unique DB (if it
  115. // opened correctly). If in memory db is requested then do not try to migrate
  116. // data from shared db, which was the behavior when only unique db existed.
  117. if (!db_provider_ || unique_database_dir_.empty()) {
  118. db_ = std::move(unique_db);
  119. std::move(callback).Run(status);
  120. OnInitDone(
  121. status == Enums::kOK
  122. ? ProtoDatabaseInitState::kSuccessNoSharedDBProviderUniqueSucceeded
  123. : ProtoDatabaseInitState::kFailureNoSharedDBProviderUniqueFailed);
  124. return;
  125. }
  126. // Get the current task runner to ensure the callback is run on the same
  127. // callback as the rest, and the WeakPtr checks out on the right sequence.
  128. DCHECK(task_runner_->RunsTasksInCurrentSequence());
  129. db_provider_->GetDBInstance(
  130. base::BindOnce(&ProtoDatabaseSelector::OnInitSharedDB, this,
  131. std::move(unique_db), status, use_shared_db,
  132. std::move(callback)),
  133. task_runner_);
  134. }
  135. void ProtoDatabaseSelector::OnInitSharedDB(
  136. std::unique_ptr<UniqueProtoDatabase> unique_db,
  137. Enums::InitStatus unique_db_status,
  138. bool use_shared_db,
  139. Callbacks::InitStatusCallback callback,
  140. scoped_refptr<SharedProtoDatabase> shared_db) {
  141. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  142. if (shared_db) {
  143. // If we have a reference to the shared database, try to get a client.
  144. shared_db->GetClientAsync(
  145. db_type_, use_shared_db,
  146. base::BindOnce(&ProtoDatabaseSelector::OnGetSharedDBClient, this,
  147. std::move(unique_db), unique_db_status, use_shared_db,
  148. std::move(callback)));
  149. return;
  150. }
  151. // Otherwise, we just call the OnGetSharedDBClient function with a nullptr
  152. // client.
  153. OnGetSharedDBClient(std::move(unique_db), unique_db_status, use_shared_db,
  154. std::move(callback), nullptr, Enums::InitStatus::kError);
  155. }
  156. void ProtoDatabaseSelector::OnGetSharedDBClient(
  157. std::unique_ptr<UniqueProtoDatabase> unique_db,
  158. Enums::InitStatus unique_db_status,
  159. bool use_shared_db,
  160. Callbacks::InitStatusCallback callback,
  161. std::unique_ptr<SharedProtoDatabaseClient> client,
  162. Enums::InitStatus shared_db_status) {
  163. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  164. if (!unique_db && !client) {
  165. std::move(callback).Run(Enums::InitStatus::kError);
  166. OnInitDone(ProtoDatabaseInitState::kBothUniqueAndSharedFailedOpen);
  167. return;
  168. }
  169. if (!client) {
  170. if (use_shared_db) {
  171. // If there's no shared client and one is requested we return an error,
  172. // because it should be created if missing.
  173. std::move(callback).Run(Enums::InitStatus::kError);
  174. OnInitDone(ProtoDatabaseInitState::kSharedDbClientMissingInitFailed);
  175. return;
  176. } else {
  177. // ProtoLevelDBWrapper::InitWithDatabase() returns kInvalidOperation when
  178. // a database doesn't exist and create_if_missing is false.
  179. if (shared_db_status == Enums::InitStatus::kInvalidOperation) {
  180. // If the shared DB doesn't exist and a unique DB is requested then we
  181. // return the unique DB.
  182. db_ = std::move(unique_db);
  183. std::move(callback).Run(Enums::InitStatus::kOK);
  184. OnInitDone(
  185. ProtoDatabaseInitState::kSharedDbClientMissingUniqueReturned);
  186. return;
  187. } else {
  188. // If the shared DB failed to open and a unique DB is requested then we
  189. // throw an error, as the shared DB may contain unmigrated data.
  190. std::move(callback).Run(Enums::InitStatus::kError);
  191. OnInitDone(ProtoDatabaseInitState::kSharedDbOpenFailed);
  192. return;
  193. }
  194. }
  195. }
  196. if (!unique_db) {
  197. switch (client->migration_status()) {
  198. case SharedDBMetadataProto::MIGRATION_NOT_ATTEMPTED:
  199. // ProtoLevelDBWrapper::InitWithDatabase() returns kInvalidOperation
  200. // when a database doesn't exist and create_if_missing is false.
  201. if (unique_db_status == Enums::kInvalidOperation) {
  202. // If the unique DB doesn't exist and the migration status is not
  203. // attempted then we set the status to migrated to shared and return
  204. // the shared DB. We don't check use_shared_db because we should only
  205. // get here when use_shared_db is true, otherwise the unique_db is
  206. // opened using create_if_missing
  207. client->UpdateClientInitMetadata(
  208. SharedDBMetadataProto::MIGRATE_TO_SHARED_SUCCESSFUL);
  209. db_ = std::move(client);
  210. std::move(callback).Run(Enums::InitStatus::kOK);
  211. OnInitDone(ProtoDatabaseInitState::kUniqueDbMissingSharedReturned);
  212. return;
  213. }
  214. // If the unique DB failed to open and the migration status is not
  215. // attempted then we return an error, as we don't know if the unique
  216. // DB contains any data.
  217. std::move(callback).Run(Enums::InitStatus::kError);
  218. OnInitDone(ProtoDatabaseInitState::kUniqueDbOpenFailed);
  219. return;
  220. case SharedDBMetadataProto::MIGRATE_TO_SHARED_SUCCESSFUL:
  221. case SharedDBMetadataProto::MIGRATE_TO_SHARED_UNIQUE_TO_BE_DELETED:
  222. // If the unique DB failed to open, but the data is located in shared
  223. // then we use the shared DB. We do the same when the unique DB is
  224. // marked for deletion because there's no way to delete it.
  225. // use_shared_db is ignored because we know the data is in shared DB,
  226. // and there's no way to migrate.
  227. db_ = std::move(client);
  228. std::move(callback).Run(Enums::InitStatus::kOK);
  229. OnInitDone(ProtoDatabaseInitState::kMigratedSharedDbOpened);
  230. return;
  231. case SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SUCCESSFUL:
  232. case SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SHARED_TO_BE_DELETED:
  233. if (unique_db_status == Enums::kInvalidOperation) {
  234. // If unique db does not exist and migration state expects it, reset
  235. // the migration state since this is not recoverable, and return the
  236. // shared db. Clear the shared db since it might contain stale data.
  237. SharedProtoDatabaseClient* client_ptr = client.get();
  238. client_ptr->UpdateEntriesWithRemoveFilter(
  239. std::make_unique<KeyValueVector>(),
  240. base::BindRepeating([](const std::string& key) { return true; }),
  241. base::BindOnce(&ProtoDatabaseSelector::
  242. InvokeInitUniqueDbMissingSharedCleared,
  243. this, std::move(client), std::move(callback)));
  244. return;
  245. }
  246. // If the unique DB failed to open, and the data is located on it then
  247. // we throw an error.
  248. std::move(callback).Run(Enums::InitStatus::kError);
  249. OnInitDone(ProtoDatabaseInitState::kUniqueDbOpenFailed);
  250. return;
  251. }
  252. }
  253. // Both databases opened correctly. Migrate data and delete old DB if needed.
  254. if (use_shared_db) {
  255. switch (client->migration_status()) {
  256. case SharedDBMetadataProto::MIGRATION_NOT_ATTEMPTED:
  257. case SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SUCCESSFUL: {
  258. // Migrate from unique to shared.
  259. UniqueProtoDatabase* from = unique_db.get();
  260. UniqueProtoDatabase* to = client.get();
  261. RecordInitState(ProtoDatabaseInitState::kMigrateToSharedAttempted);
  262. migration_delegate_->DoMigration(
  263. from, to,
  264. base::BindOnce(&ProtoDatabaseSelector::OnMigrationTransferComplete,
  265. this, std::move(unique_db), std::move(client),
  266. use_shared_db, std::move(callback)));
  267. return;
  268. }
  269. case SharedDBMetadataProto::MIGRATE_TO_SHARED_SUCCESSFUL:
  270. // Unique db was deleted in previous migration, so nothing to do here.
  271. return OnMigrationCleanupComplete(std::move(unique_db),
  272. std::move(client), use_shared_db,
  273. std::move(callback), true);
  274. case SharedDBMetadataProto::MIGRATE_TO_SHARED_UNIQUE_TO_BE_DELETED:
  275. // Migration transfer was completed, so just try deleting the unique db.
  276. return OnMigrationTransferComplete(std::move(unique_db),
  277. std::move(client), use_shared_db,
  278. std::move(callback), true);
  279. case SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SHARED_TO_BE_DELETED:
  280. // Shared db was not deleted in last migration and we want to use shared
  281. // db. So, delete stale data, and attempt migration.
  282. return DeleteOldDataAndMigrate(std::move(unique_db), std::move(client),
  283. use_shared_db, std::move(callback));
  284. }
  285. } else {
  286. switch (client->migration_status()) {
  287. case SharedDBMetadataProto::MIGRATION_NOT_ATTEMPTED:
  288. case SharedDBMetadataProto::MIGRATE_TO_SHARED_SUCCESSFUL: {
  289. // Migrate from shared to unique.
  290. UniqueProtoDatabase* from = client.get();
  291. UniqueProtoDatabase* to = unique_db.get();
  292. RecordInitState(ProtoDatabaseInitState::kMigrateToUniqueAttempted);
  293. migration_delegate_->DoMigration(
  294. from, to,
  295. base::BindOnce(&ProtoDatabaseSelector::OnMigrationTransferComplete,
  296. this, std::move(unique_db), std::move(client),
  297. use_shared_db, std::move(callback)));
  298. return;
  299. }
  300. case SharedDBMetadataProto::MIGRATE_TO_SHARED_UNIQUE_TO_BE_DELETED:
  301. // Unique db was not deleted in last migration and we want to use unique
  302. // db. So, delete stale data, and attempt migration.
  303. return DeleteOldDataAndMigrate(std::move(unique_db), std::move(client),
  304. use_shared_db, std::move(callback));
  305. case SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SUCCESSFUL:
  306. // Shared db was deleted in previous migration, so nothing to do here.
  307. return OnMigrationCleanupComplete(std::move(unique_db),
  308. std::move(client), use_shared_db,
  309. std::move(callback), true);
  310. case SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SHARED_TO_BE_DELETED:
  311. // Migration transfer was completed, so just try deleting the shared db.
  312. return OnMigrationTransferComplete(std::move(unique_db),
  313. std::move(client), use_shared_db,
  314. std::move(callback), true);
  315. }
  316. }
  317. }
  318. void ProtoDatabaseSelector::DeleteOldDataAndMigrate(
  319. std::unique_ptr<UniqueProtoDatabase> unique_db,
  320. std::unique_ptr<SharedProtoDatabaseClient> client,
  321. bool use_shared_db,
  322. Callbacks::InitStatusCallback callback) {
  323. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  324. UniqueProtoDatabase* to_remove_old_data =
  325. use_shared_db ? client.get() : unique_db.get();
  326. auto maybe_do_migration =
  327. base::BindOnce(&ProtoDatabaseSelector::MaybeDoMigrationOnDeletingOld,
  328. this, std::move(unique_db), std::move(client),
  329. std::move(callback), use_shared_db);
  330. to_remove_old_data->UpdateEntriesWithRemoveFilter(
  331. std::make_unique<KeyValueVector>(),
  332. base::BindRepeating([](const std::string& key) { return true; }),
  333. std::move(maybe_do_migration));
  334. }
  335. void ProtoDatabaseSelector::MaybeDoMigrationOnDeletingOld(
  336. std::unique_ptr<UniqueProtoDatabase> unique_db,
  337. std::unique_ptr<SharedProtoDatabaseClient> client,
  338. Callbacks::InitStatusCallback callback,
  339. bool use_shared_db,
  340. bool delete_success) {
  341. if (!delete_success) {
  342. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  343. // Old data has not been removed from the database we want to use. We also
  344. // know that previous attempt of migration failed for same reason. Give up
  345. // on this database and use the other.
  346. // This update is not necessary since this was the old value. But update to
  347. // be clear.
  348. client->UpdateClientInitMetadata(
  349. use_shared_db
  350. ? SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SHARED_TO_BE_DELETED
  351. : SharedDBMetadataProto::MIGRATE_TO_SHARED_UNIQUE_TO_BE_DELETED);
  352. db_ = use_shared_db ? std::move(unique_db) : std::move(client);
  353. std::move(callback).Run(Enums::InitStatus::kOK);
  354. OnInitDone(ProtoDatabaseInitState::kDeletionOfOldDataFailed);
  355. return;
  356. }
  357. auto* from = use_shared_db ? unique_db.get() : client.get();
  358. auto* to = use_shared_db ? client.get() : unique_db.get();
  359. RecordInitState(use_shared_db
  360. ? ProtoDatabaseInitState::kMigrateToSharedAttempted
  361. : ProtoDatabaseInitState::kMigrateToUniqueAttempted);
  362. migration_delegate_->DoMigration(
  363. from, to,
  364. base::BindOnce(&ProtoDatabaseSelector::OnMigrationTransferComplete, this,
  365. std::move(unique_db), std::move(client), use_shared_db,
  366. std::move(callback)));
  367. }
  368. void ProtoDatabaseSelector::OnMigrationTransferComplete(
  369. std::unique_ptr<UniqueProtoDatabase> unique_db,
  370. std::unique_ptr<SharedProtoDatabaseClient> client,
  371. bool use_shared_db,
  372. Callbacks::InitStatusCallback callback,
  373. bool success) {
  374. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  375. if (success) {
  376. // Call Destroy on the DB we no longer want to use.
  377. auto* db_destroy_ptr = use_shared_db ? unique_db.get() : client.get();
  378. db_destroy_ptr->Destroy(
  379. base::BindOnce(&ProtoDatabaseSelector::OnMigrationCleanupComplete, this,
  380. std::move(unique_db), std::move(client), use_shared_db,
  381. std::move(callback)));
  382. return;
  383. }
  384. // Failing to transfer the old data means that the requested database to be
  385. // used could have some bad data. So, mark them to be deleted before use in
  386. // the next runs.
  387. client->UpdateClientInitMetadata(
  388. use_shared_db
  389. ? SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SHARED_TO_BE_DELETED
  390. : SharedDBMetadataProto::MIGRATE_TO_SHARED_UNIQUE_TO_BE_DELETED);
  391. db_ = use_shared_db ? std::move(unique_db) : std::move(client);
  392. std::move(callback).Run(Enums::InitStatus::kOK);
  393. OnInitDone(use_shared_db ? ProtoDatabaseInitState::kMigrateToSharedFailed
  394. : ProtoDatabaseInitState::kMigrateToUniqueFailed);
  395. }
  396. void ProtoDatabaseSelector::OnMigrationCleanupComplete(
  397. std::unique_ptr<UniqueProtoDatabase> unique_db,
  398. std::unique_ptr<SharedProtoDatabaseClient> client,
  399. bool use_shared_db,
  400. Callbacks::InitStatusCallback callback,
  401. bool success) {
  402. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  403. // We still return true in our callback below because we do have a database as
  404. // far as the original caller is concerned. As long as |db_| is assigned, we
  405. // return true.
  406. ProtoDatabaseInitState state;
  407. if (success) {
  408. client->UpdateClientInitMetadata(
  409. use_shared_db ? SharedDBMetadataProto::MIGRATE_TO_SHARED_SUCCESSFUL
  410. : SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SUCCESSFUL);
  411. state = use_shared_db ? ProtoDatabaseInitState::kMigrateToSharedSuccess
  412. : ProtoDatabaseInitState::kMigrateToUniqueSuccess;
  413. } else {
  414. client->UpdateClientInitMetadata(
  415. use_shared_db
  416. ? SharedDBMetadataProto::MIGRATE_TO_SHARED_UNIQUE_TO_BE_DELETED
  417. : SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SHARED_TO_BE_DELETED);
  418. state =
  419. use_shared_db
  420. ? ProtoDatabaseInitState::kMigrateToUniqueCompleteDeletionFailed
  421. : ProtoDatabaseInitState::kMigrateToSharedCompleteDeletionFailed;
  422. }
  423. // Migration transfer was complete. So, we should use the requested database.
  424. db_ = use_shared_db ? std::move(client) : std::move(unique_db);
  425. std::move(callback).Run(Enums::InitStatus::kOK);
  426. OnInitDone(state);
  427. }
  428. void ProtoDatabaseSelector::AddTransaction(base::OnceClosure task) {
  429. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  430. switch (init_status_) {
  431. case InitStatus::IN_PROGRESS:
  432. if (pending_tasks_.size() > 10) {
  433. std::move(pending_tasks_.front()).Run();
  434. pending_tasks_.pop();
  435. }
  436. pending_tasks_.push(std::move(task));
  437. break;
  438. case InitStatus::NOT_STARTED:
  439. NOTREACHED();
  440. [[fallthrough]];
  441. case InitStatus::DONE:
  442. std::move(task).Run();
  443. break;
  444. }
  445. }
  446. void ProtoDatabaseSelector::UpdateEntries(
  447. std::unique_ptr<KeyValueVector> entries_to_save,
  448. std::unique_ptr<KeyVector> keys_to_remove,
  449. Callbacks::UpdateCallback callback) {
  450. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  451. DCHECK_EQ(init_status_, InitStatus::DONE);
  452. if (!db_) {
  453. std::move(callback).Run(false);
  454. return;
  455. }
  456. db_->UpdateEntries(std::move(entries_to_save), std::move(keys_to_remove),
  457. std::move(callback));
  458. }
  459. void ProtoDatabaseSelector::UpdateEntriesWithRemoveFilter(
  460. std::unique_ptr<KeyValueVector> entries_to_save,
  461. const KeyFilter& delete_key_filter,
  462. Callbacks::UpdateCallback callback) {
  463. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  464. if (!db_) {
  465. std::move(callback).Run(false);
  466. return;
  467. }
  468. db_->UpdateEntriesWithRemoveFilter(std::move(entries_to_save),
  469. delete_key_filter, std::move(callback));
  470. }
  471. void ProtoDatabaseSelector::LoadEntries(
  472. typename Callbacks::LoadCallback callback) {
  473. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  474. if (!db_) {
  475. std::move(callback).Run(false, nullptr);
  476. return;
  477. }
  478. db_->LoadEntries(std::move(callback));
  479. }
  480. void ProtoDatabaseSelector::LoadEntriesWithFilter(
  481. const KeyFilter& key_filter,
  482. const leveldb::ReadOptions& options,
  483. const std::string& target_prefix,
  484. typename Callbacks::LoadCallback callback) {
  485. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  486. if (!db_) {
  487. std::move(callback).Run(false, nullptr);
  488. return;
  489. }
  490. db_->LoadEntriesWithFilter(key_filter, options, target_prefix,
  491. std::move(callback));
  492. }
  493. void ProtoDatabaseSelector::LoadKeysAndEntries(
  494. typename Callbacks::LoadKeysAndEntriesCallback callback) {
  495. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  496. if (!db_) {
  497. std::move(callback).Run(false, nullptr);
  498. return;
  499. }
  500. db_->LoadKeysAndEntries(std::move(callback));
  501. }
  502. void ProtoDatabaseSelector::LoadKeysAndEntriesWithFilter(
  503. const KeyFilter& filter,
  504. const leveldb::ReadOptions& options,
  505. const std::string& target_prefix,
  506. typename Callbacks::LoadKeysAndEntriesCallback callback) {
  507. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  508. if (!db_) {
  509. std::move(callback).Run(false, nullptr);
  510. return;
  511. }
  512. db_->LoadKeysAndEntriesWithFilter(filter, options, target_prefix,
  513. std::move(callback));
  514. }
  515. void ProtoDatabaseSelector::LoadKeysAndEntriesInRange(
  516. const std::string& start,
  517. const std::string& end,
  518. typename Callbacks::LoadKeysAndEntriesCallback callback) {
  519. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  520. if (!db_) {
  521. std::move(callback).Run(false, nullptr);
  522. return;
  523. }
  524. db_->LoadKeysAndEntriesInRange(start, end, std::move(callback));
  525. }
  526. void ProtoDatabaseSelector::LoadKeysAndEntriesWhile(
  527. const std::string& start,
  528. const KeyIteratorController& controller,
  529. typename Callbacks::LoadKeysAndEntriesCallback callback) {
  530. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  531. if (!db_) {
  532. std::move(callback).Run(false, nullptr);
  533. return;
  534. }
  535. db_->LoadKeysAndEntriesWhile(start, controller, std::move(callback));
  536. }
  537. void ProtoDatabaseSelector::LoadKeys(Callbacks::LoadKeysCallback callback) {
  538. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  539. if (!db_) {
  540. std::move(callback).Run(false, nullptr);
  541. return;
  542. }
  543. db_->LoadKeys(std::move(callback));
  544. }
  545. void ProtoDatabaseSelector::GetEntry(const std::string& key,
  546. typename Callbacks::GetCallback callback) {
  547. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  548. if (!db_) {
  549. std::move(callback).Run(false, nullptr);
  550. return;
  551. }
  552. db_->GetEntry(key, std::move(callback));
  553. }
  554. void ProtoDatabaseSelector::Destroy(Callbacks::DestroyCallback callback) {
  555. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  556. if (!db_) {
  557. if (!unique_database_dir_.empty()) {
  558. ProtoLevelDBWrapper::Destroy(unique_database_dir_, client_name_,
  559. task_runner_, std::move(callback));
  560. return;
  561. }
  562. std::move(callback).Run(false);
  563. return;
  564. }
  565. db_->Destroy(std::move(callback));
  566. }
  567. void ProtoDatabaseSelector::RemoveKeysForTesting(
  568. const KeyFilter& key_filter,
  569. const std::string& target_prefix,
  570. Callbacks::UpdateCallback callback) {
  571. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  572. if (!db_) {
  573. std::move(callback).Run(false);
  574. return;
  575. }
  576. db_->RemoveKeysForTesting(key_filter, target_prefix, std::move(callback));
  577. }
  578. void ProtoDatabaseSelector::InvokeInitUniqueDbMissingSharedCleared(
  579. std::unique_ptr<SharedProtoDatabaseClient> client,
  580. Callbacks::InitStatusCallback callback,
  581. bool shared_cleared) {
  582. if (!shared_cleared) {
  583. OnInitDone(
  584. ProtoDatabaseInitState::kFailureUniqueDbMissingClearSharedFailed);
  585. std::move(callback).Run(Enums::InitStatus::kError);
  586. return;
  587. }
  588. // Reset state to migrated to shared since unique db is missing.
  589. client->UpdateClientInitMetadata(
  590. SharedDBMetadataProto::MIGRATE_TO_SHARED_SUCCESSFUL);
  591. db_ = std::move(client);
  592. OnInitDone(ProtoDatabaseInitState::kUniqueDbMissingSharedReturned);
  593. std::move(callback).Run(Enums::InitStatus::kOK);
  594. }
  595. void ProtoDatabaseSelector::OnInitDone(
  596. ProtoDatabaseSelector::ProtoDatabaseInitState state) {
  597. RecordInitState(state);
  598. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  599. init_status_ = InitStatus::DONE;
  600. while (!pending_tasks_.empty()) {
  601. task_runner_->PostTask(FROM_HERE, std::move(pending_tasks_.front()));
  602. pending_tasks_.pop();
  603. }
  604. }
  605. } // namespace leveldb_proto