123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439 |
- // Copyright 2018 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/leveldb_proto/internal/proto_leveldb_wrapper.h"
- #include <string>
- #include "base/bind.h"
- #include "base/callback_forward.h"
- #include "base/task/sequenced_task_runner.h"
- #include "base/task/task_traits.h"
- #include "base/threading/sequenced_task_runner_handle.h"
- #include "components/leveldb_proto/internal/leveldb_database.h"
- #include "components/leveldb_proto/internal/proto_leveldb_wrapper_metrics.h"
- #include "components/leveldb_proto/public/proto_database.h"
- namespace leveldb_proto {
- namespace {
- Enums::InitStatus InitFromTaskRunner(LevelDB* database,
- const base::FilePath& database_dir,
- const leveldb_env::Options& options,
- bool destroy_on_corruption,
- const std::string& client_id) {
- // TODO(cjhopman): Histogram for database size.
- auto status = database->Init(database_dir, options, destroy_on_corruption);
- ProtoLevelDBWrapperMetrics::RecordInit(client_id, status);
- if (status.ok())
- return Enums::InitStatus::kOK;
- if (status.IsCorruption())
- return Enums::InitStatus::kCorrupt;
- if (status.IsNotSupportedError() || status.IsInvalidArgument())
- return Enums::InitStatus::kInvalidOperation;
- return Enums::InitStatus::kError;
- }
- bool DestroyFromTaskRunner(LevelDB* database, const std::string& client_id) {
- auto status = database->Destroy();
- bool success = status.ok();
- ProtoLevelDBWrapperMetrics::RecordDestroy(client_id, success);
- return success;
- }
- bool DestroyWithDirectoryFromTaskRunner(const base::FilePath& db_dir,
- const std::string& client_id) {
- leveldb::Status result = leveldb::DestroyDB(
- db_dir.AsUTF8Unsafe(), leveldb_proto::CreateSimpleOptions());
- bool success = result.ok();
- if (!client_id.empty())
- ProtoLevelDBWrapperMetrics::RecordDestroy(client_id, success);
- return success;
- }
- void LoadKeysFromTaskRunner(
- LevelDB* database,
- const std::string& target_prefix,
- const std::string& client_id,
- Callbacks::LoadKeysCallback callback,
- scoped_refptr<base::SequencedTaskRunner> callback_task_runner) {
- auto keys = std::make_unique<KeyVector>();
- bool success = database->LoadKeys(target_prefix, keys.get());
- ProtoLevelDBWrapperMetrics::RecordLoadKeys(client_id, success);
- callback_task_runner->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), success, std::move(keys)));
- }
- void RemoveKeysFromTaskRunner(
- LevelDB* database,
- const std::string& target_prefix,
- const KeyFilter& filter,
- const std::string& client_id,
- Callbacks::UpdateCallback callback,
- scoped_refptr<base::SequencedTaskRunner> callback_task_runner) {
- leveldb::Status status;
- bool success = database->UpdateWithRemoveFilter(base::StringPairs(), filter,
- target_prefix, &status);
- ProtoLevelDBWrapperMetrics::RecordUpdate(client_id, success, status);
- callback_task_runner->PostTask(FROM_HERE,
- base::BindOnce(std::move(callback), success));
- }
- void RunLoadCallback(Callbacks::LoadCallback callback,
- bool* success,
- std::unique_ptr<ValueVector> entries) {
- std::move(callback).Run(*success, std::move(entries));
- }
- void RunLoadKeysAndEntriesCallback(
- Callbacks::LoadKeysAndEntriesCallback callback,
- bool* success,
- std::unique_ptr<KeyValueMap> keys_entries) {
- std::move(callback).Run(*success, std::move(keys_entries));
- }
- void RunGetCallback(Callbacks::GetCallback callback,
- const bool* success,
- const bool* found,
- std::unique_ptr<std::string> entry) {
- std::move(callback).Run(*success, *found ? std::move(entry) : nullptr);
- }
- bool UpdateEntriesFromTaskRunner(
- LevelDB* database,
- std::unique_ptr<KeyValueVector> entries_to_save,
- std::unique_ptr<KeyVector> keys_to_remove,
- const std::string& client_id) {
- DCHECK(entries_to_save);
- DCHECK(keys_to_remove);
- leveldb::Status status;
- bool success = database->Save(*entries_to_save, *keys_to_remove, &status);
- ProtoLevelDBWrapperMetrics::RecordUpdate(client_id, success, status);
- return success;
- }
- bool UpdateEntriesWithRemoveFilterFromTaskRunner(
- LevelDB* database,
- std::unique_ptr<KeyValueVector> entries_to_save,
- const KeyFilter& delete_key_filter,
- const std::string& target_prefix,
- const std::string& client_id) {
- DCHECK(entries_to_save);
- leveldb::Status status;
- bool success = database->UpdateWithRemoveFilter(
- *entries_to_save, delete_key_filter, target_prefix, &status);
- ProtoLevelDBWrapperMetrics::RecordUpdate(client_id, success, status);
- return success;
- }
- void LoadKeysAndEntriesFromTaskRunner(LevelDB* database,
- const KeyIteratorController& controller,
- const leveldb::ReadOptions& options,
- const std::string& start_key,
- const std::string& client_id,
- bool* success,
- KeyValueMap* keys_entries) {
- DCHECK(success);
- DCHECK(keys_entries);
- keys_entries->clear();
- *success = database->LoadKeysAndEntriesWhile(keys_entries, options, start_key,
- controller);
- ProtoLevelDBWrapperMetrics::RecordLoadKeysAndEntries(client_id, success);
- }
- void LoadEntriesFromTaskRunner(LevelDB* database,
- const KeyFilter& filter,
- const leveldb::ReadOptions& options,
- const std::string& target_prefix,
- const std::string& client_id,
- bool* success,
- ValueVector* entries) {
- *success = database->LoadWithFilter(filter, entries, options, target_prefix);
- ProtoLevelDBWrapperMetrics::RecordLoadEntries(client_id, success);
- }
- void GetEntryFromTaskRunner(LevelDB* database,
- const std::string& key,
- const std::string& client_id,
- bool* success,
- bool* found,
- std::string* entry) {
- leveldb::Status status;
- *success = database->Get(key, found, entry, &status);
- ProtoLevelDBWrapperMetrics::RecordGet(client_id, *success, *found, status);
- }
- } // namespace
- ProtoLevelDBWrapper::ProtoLevelDBWrapper(
- const scoped_refptr<base::SequencedTaskRunner>& task_runner)
- : task_runner_(task_runner) {
- DETACH_FROM_SEQUENCE(sequence_checker_);
- }
- ProtoLevelDBWrapper::ProtoLevelDBWrapper(
- const scoped_refptr<base::SequencedTaskRunner>& task_runner,
- LevelDB* db)
- : task_runner_(task_runner), db_(db) {
- DETACH_FROM_SEQUENCE(sequence_checker_);
- }
- ProtoLevelDBWrapper::~ProtoLevelDBWrapper() = default;
- void ProtoLevelDBWrapper::RunInitCallback(Callbacks::InitCallback callback,
- const leveldb::Status* status) {
- std::move(callback).Run(status->ok());
- }
- void ProtoLevelDBWrapper::InitWithDatabase(
- LevelDB* database,
- const base::FilePath& database_dir,
- const leveldb_env::Options& options,
- bool destroy_on_corruption,
- Callbacks::InitStatusCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(database);
- db_ = database;
- base::PostTaskAndReplyWithResult(
- task_runner_.get(), FROM_HERE,
- base::BindOnce(InitFromTaskRunner, base::Unretained(db_), database_dir,
- options, destroy_on_corruption, metrics_id_),
- std::move(callback));
- }
- void ProtoLevelDBWrapper::UpdateEntries(
- std::unique_ptr<KeyValueVector> entries_to_save,
- std::unique_ptr<KeyVector> keys_to_remove,
- typename Callbacks::UpdateCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- base::PostTaskAndReplyWithResult(
- task_runner_.get(), FROM_HERE,
- base::BindOnce(UpdateEntriesFromTaskRunner, base::Unretained(db_),
- std::move(entries_to_save), std::move(keys_to_remove),
- metrics_id_),
- std::move(callback));
- }
- void ProtoLevelDBWrapper::UpdateEntriesWithRemoveFilter(
- std::unique_ptr<KeyValueVector> entries_to_save,
- const KeyFilter& delete_key_filter,
- Callbacks::UpdateCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- UpdateEntriesWithRemoveFilter(std::move(entries_to_save), delete_key_filter,
- std::string(), std::move(callback));
- }
- void ProtoLevelDBWrapper::UpdateEntriesWithRemoveFilter(
- std::unique_ptr<KeyValueVector> entries_to_save,
- const KeyFilter& delete_key_filter,
- const std::string& target_prefix,
- Callbacks::UpdateCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- base::PostTaskAndReplyWithResult(
- task_runner_.get(), FROM_HERE,
- base::BindOnce(UpdateEntriesWithRemoveFilterFromTaskRunner,
- base::Unretained(db_), std::move(entries_to_save),
- delete_key_filter, target_prefix, metrics_id_),
- std::move(callback));
- }
- void ProtoLevelDBWrapper::LoadEntries(Callbacks::LoadCallback callback) {
- LoadEntriesWithFilter(KeyFilter(), std::move(callback));
- }
- void ProtoLevelDBWrapper::LoadEntriesWithFilter(
- const KeyFilter& key_filter,
- Callbacks::LoadCallback callback) {
- LoadEntriesWithFilter(key_filter, leveldb::ReadOptions(), std::string(),
- std::move(callback));
- }
- void ProtoLevelDBWrapper::LoadEntriesWithFilter(
- const KeyFilter& key_filter,
- const leveldb::ReadOptions& options,
- const std::string& target_prefix,
- Callbacks::LoadCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- bool* success = new bool(false);
- auto entries = std::make_unique<ValueVector>();
- // Get this pointer before |entries| is std::move()'d so we can use it below.
- auto* entries_ptr = entries.get();
- task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::BindOnce(LoadEntriesFromTaskRunner, base::Unretained(db_),
- key_filter, options, target_prefix, metrics_id_, success,
- entries_ptr),
- base::BindOnce(RunLoadCallback, std::move(callback), base::Owned(success),
- std::move(entries)));
- }
- void ProtoLevelDBWrapper::LoadKeysAndEntries(
- Callbacks::LoadKeysAndEntriesCallback callback) {
- LoadKeysAndEntriesWithFilter(KeyFilter(), std::move(callback));
- }
- void ProtoLevelDBWrapper::LoadKeysAndEntriesWithFilter(
- const KeyFilter& key_filter,
- Callbacks::LoadKeysAndEntriesCallback callback) {
- LoadKeysAndEntriesWithFilter(key_filter, leveldb::ReadOptions(),
- std::string(), std::move(callback));
- }
- void ProtoLevelDBWrapper::LoadKeysAndEntriesWithFilter(
- const KeyFilter& key_filter,
- const leveldb::ReadOptions& options,
- const std::string& target_prefix,
- Callbacks::LoadKeysAndEntriesCallback callback) {
- LoadKeysAndEntriesWhile(
- base::BindRepeating(
- [](const std::string& prefix, const std::string& key) {
- return base::StartsWith(key, prefix, base::CompareCase::SENSITIVE);
- },
- target_prefix),
- key_filter, options, target_prefix, std::move(callback));
- }
- void ProtoLevelDBWrapper::LoadKeysAndEntriesInRange(
- const std::string& start,
- const std::string& end,
- Callbacks::LoadKeysAndEntriesCallback callback) {
- LoadKeysAndEntriesWhile(
- base::BindRepeating(
- [](const std::string& range_end, const std::string& key) {
- return key.compare(range_end) <= 0;
- },
- end),
- KeyFilter(), leveldb::ReadOptions(), start, std::move(callback));
- }
- void ProtoLevelDBWrapper::LoadKeysAndEntriesWhile(
- const std::string& start_key,
- const KeyIteratorController& controller,
- Callbacks::LoadKeysAndEntriesCallback callback) {
- LoadKeysAndEntriesWhile(controller, leveldb::ReadOptions(), start_key,
- std::move(callback));
- }
- void ProtoLevelDBWrapper::LoadKeysAndEntriesWhile(
- const KeyFilter& while_callback,
- const KeyFilter& filter,
- const leveldb::ReadOptions& options,
- const std::string& start_key,
- Callbacks::LoadKeysAndEntriesCallback callback) {
- LoadKeysAndEntriesWhile(base::BindRepeating(LevelDB::ComputeIteratorAction,
- while_callback, filter),
- options, start_key, std::move(callback));
- }
- void ProtoLevelDBWrapper::LoadKeysAndEntriesWhile(
- const KeyIteratorController& controller,
- const leveldb::ReadOptions& options,
- const std::string& start_key,
- Callbacks::LoadKeysAndEntriesCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- bool* success = new bool(false);
- auto keys_entries = std::make_unique<KeyValueMap>();
- // Get this pointer before |keys_entries| is std::move()'d so we can use it
- // below.
- auto* keys_entries_ptr = keys_entries.get();
- task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::BindOnce(LoadKeysAndEntriesFromTaskRunner, base::Unretained(db_),
- controller, options, start_key, metrics_id_, success,
- keys_entries_ptr),
- base::BindOnce(RunLoadKeysAndEntriesCallback, std::move(callback),
- base::Owned(success), std::move(keys_entries)));
- }
- void ProtoLevelDBWrapper::GetEntry(const std::string& key,
- Callbacks::GetCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- bool* success = new bool(false);
- bool* found = new bool(false);
- auto entry = std::make_unique<std::string>();
- // Get this pointer before |entry| is std::move()'d so we can use it below.
- auto* entry_ptr = entry.get();
- task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::BindOnce(GetEntryFromTaskRunner, base::Unretained(db_), key,
- metrics_id_, success, found, entry_ptr),
- base::BindOnce(RunGetCallback, std::move(callback), base::Owned(success),
- base::Owned(found), std::move(entry)));
- }
- void ProtoLevelDBWrapper::LoadKeys(
- typename Callbacks::LoadKeysCallback callback) {
- LoadKeys(std::string(), std::move(callback));
- }
- void ProtoLevelDBWrapper::LoadKeys(
- const std::string& target_prefix,
- typename Callbacks::LoadKeysCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- task_runner_->PostTask(
- FROM_HERE, base::BindOnce(LoadKeysFromTaskRunner, base::Unretained(db_),
- target_prefix, metrics_id_, std::move(callback),
- base::SequencedTaskRunnerHandle::Get()));
- }
- void ProtoLevelDBWrapper::RemoveKeys(const KeyFilter& filter,
- const std::string& target_prefix,
- Callbacks::UpdateCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(RemoveKeysFromTaskRunner, base::Unretained(db_),
- target_prefix, filter, metrics_id_, std::move(callback),
- base::SequencedTaskRunnerHandle::Get()));
- }
- void ProtoLevelDBWrapper::Destroy(Callbacks::DestroyCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(db_);
- base::PostTaskAndReplyWithResult(
- task_runner_.get(), FROM_HERE,
- base::BindOnce(DestroyFromTaskRunner, base::Unretained(db_), metrics_id_),
- std::move(callback));
- }
- void ProtoLevelDBWrapper::Destroy(
- const base::FilePath& db_dir,
- const std::string& client_id,
- const scoped_refptr<base::SequencedTaskRunner>& task_runner,
- Callbacks::DestroyCallback callback) {
- base::PostTaskAndReplyWithResult(
- task_runner.get(), FROM_HERE,
- base::BindOnce(DestroyWithDirectoryFromTaskRunner, db_dir, client_id),
- std::move(callback));
- }
- void ProtoLevelDBWrapper::SetMetricsId(const std::string& id) {
- metrics_id_ = id;
- }
- bool ProtoLevelDBWrapper::GetApproximateMemoryUse(uint64_t* approx_mem_use) {
- if (!db_)
- return false;
- return db_->GetApproximateMemoryUse(approx_mem_use);
- }
- const scoped_refptr<base::SequencedTaskRunner>&
- ProtoLevelDBWrapper::task_runner() {
- return task_runner_;
- }
- } // namespace leveldb_proto
|