Commit c7f0b95d authored by Troy Hildebrandt's avatar Troy Hildebrandt Committed by Commit Bot

Refactor ProtoDatabase(Impl) to allow DBs with multiple proto types.

Currently, ProtoDatabase<T> only allows us to have a LevelDB that stores
a single proto type.

In preparation for a single unified proto DB, ProtoDatabase and
ProtoDatabaseImpl have been refactored. Much of ProtoDatabaseImpl's
logic has been moved into ProtoLevelDBWrapper, which contains template
functions instead of being a template class.

ProtoDatabase<T> provides the interface we have today, and we now
have a UniqueProtoDatabase<T> as a thin layer above ProtoDatabase so
that it can manage the unique_ptr to its own LevelDB.
ProtoDatabaseImpl<T> is kept around as an alias for UniqueProtoDatabase
for compatibility, and as a result no ProtoDatabase(Impl) users are
negatively impacted by this change.

The addition of the ProtoLevelDBWrapper provides a convenient place to
record metrics for the various database clients.

Bug: 870813
Change-Id: I6175a3cbea5dd312f09c1d88d5ad80f1f4b26006
Reviewed-on: https://chromium-review.googlesource.com/c/1170093
Commit-Queue: Troy Hildebrandt <thildebr@chromium.org>
Reviewed-by: default avatarTommy Nyquist <nyquist@chromium.org>
Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Cr-Commit-Position: refs/heads/master@{#598782}
parent c377f0a4
...@@ -9,6 +9,9 @@ static_library("leveldb_proto") { ...@@ -9,6 +9,9 @@ static_library("leveldb_proto") {
"proto_database.cc", "proto_database.cc",
"proto_database.h", "proto_database.h",
"proto_database_impl.h", "proto_database_impl.h",
"proto_leveldb_wrapper.cc",
"proto_leveldb_wrapper.h",
"unique_proto_database.h",
] ]
public_deps = [ public_deps = [
...@@ -26,6 +29,7 @@ source_set("test_support") { ...@@ -26,6 +29,7 @@ source_set("test_support") {
public_deps = [ public_deps = [
":leveldb_proto", ":leveldb_proto",
"//base", "//base",
"//base/test:test_support",
"//components/leveldb_proto/testing/proto", "//components/leveldb_proto/testing/proto",
] ]
} }
...@@ -33,7 +37,7 @@ source_set("test_support") { ...@@ -33,7 +37,7 @@ source_set("test_support") {
source_set("unit_tests") { source_set("unit_tests") {
testonly = true testonly = true
sources = [ sources = [
"proto_database_impl_unittest.cc", "unique_proto_database_unittest.cc",
] ]
deps = [ deps = [
":test_support", ":test_support",
......
...@@ -10,10 +10,7 @@ ...@@ -10,10 +10,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
#include "base/threading/thread_collision_warner.h"
#include "third_party/leveldatabase/env_chromium.h" #include "third_party/leveldatabase/env_chromium.h"
namespace base { namespace base {
...@@ -25,7 +22,6 @@ namespace leveldb { ...@@ -25,7 +22,6 @@ namespace leveldb {
class Cache; class Cache;
class DB; class DB;
class Env; class Env;
class Status;
} // namespace leveldb } // namespace leveldb
namespace leveldb_proto { namespace leveldb_proto {
......
...@@ -6,18 +6,12 @@ ...@@ -6,18 +6,12 @@
#define COMPONENTS_LEVELDB_PROTO_PROTO_DATABASE_H_ #define COMPONENTS_LEVELDB_PROTO_PROTO_DATABASE_H_
#include <map> #include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector> #include <vector>
#include "base/callback.h" #include "base/sequenced_task_runner.h"
#include "base/threading/thread_checker.h"
#include "components/leveldb_proto/leveldb_database.h" #include "components/leveldb_proto/leveldb_database.h"
#include "third_party/leveldatabase/env_chromium.h" #include "components/leveldb_proto/proto_leveldb_wrapper.h"
namespace base {
class FilePath;
}
namespace leveldb_proto { namespace leveldb_proto {
...@@ -43,6 +37,9 @@ class ProtoDatabase { ...@@ -43,6 +37,9 @@ class ProtoDatabase {
// A list of key-value (string, T) tuples. // A list of key-value (string, T) tuples.
using KeyEntryVector = std::vector<std::pair<std::string, T>>; using KeyEntryVector = std::vector<std::pair<std::string, T>>;
explicit ProtoDatabase(
const scoped_refptr<base::SequencedTaskRunner>& task_runner)
: db_wrapper_(std::make_unique<ProtoLevelDBWrapper>(task_runner)) {}
virtual ~ProtoDatabase() {} virtual ~ProtoDatabase() {}
// Asynchronously initializes the object with the specified |options|. // Asynchronously initializes the object with the specified |options|.
...@@ -50,7 +47,15 @@ class ProtoDatabase { ...@@ -50,7 +47,15 @@ class ProtoDatabase {
virtual void Init(const char* client_name, virtual void Init(const char* client_name,
const base::FilePath& database_dir, const base::FilePath& database_dir,
const leveldb_env::Options& options, const leveldb_env::Options& options,
InitCallback callback) = 0; typename ProtoDatabase<T>::InitCallback callback) = 0;
virtual void InitWithDatabase(LevelDB* database,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
InitCallback callback) {
db_wrapper_->InitWithDatabase(database, database_dir, options,
std::move(callback));
}
// Asynchronously saves |entries_to_save| and deletes entries from // Asynchronously saves |entries_to_save| and deletes entries from
// |keys_to_remove| from the database. |callback| will be invoked on the // |keys_to_remove| from the database. |callback| will be invoked on the
...@@ -58,7 +63,11 @@ class ProtoDatabase { ...@@ -58,7 +63,11 @@ class ProtoDatabase {
virtual void UpdateEntries( virtual void UpdateEntries(
std::unique_ptr<KeyEntryVector> entries_to_save, std::unique_ptr<KeyEntryVector> entries_to_save,
std::unique_ptr<std::vector<std::string>> keys_to_remove, std::unique_ptr<std::vector<std::string>> keys_to_remove,
UpdateCallback callback) = 0; UpdateCallback callback) {
db_wrapper_->template UpdateEntries<T>(std::move(entries_to_save),
std::move(keys_to_remove),
std::move(callback));
}
// Asynchronously saves |entries_to_save| and deletes entries that satisfies // Asynchronously saves |entries_to_save| and deletes entries that satisfies
// the |delete_key_filter| from the database. |callback| will be invoked on // the |delete_key_filter| from the database. |callback| will be invoked on
...@@ -67,44 +76,76 @@ class ProtoDatabase { ...@@ -67,44 +76,76 @@ class ProtoDatabase {
virtual void UpdateEntriesWithRemoveFilter( virtual void UpdateEntriesWithRemoveFilter(
std::unique_ptr<KeyEntryVector> entries_to_save, std::unique_ptr<KeyEntryVector> entries_to_save,
const LevelDB::KeyFilter& delete_key_filter, const LevelDB::KeyFilter& delete_key_filter,
UpdateCallback callback) = 0; UpdateCallback callback) {
db_wrapper_->template UpdateEntriesWithRemoveFilter<T>(
std::move(entries_to_save), delete_key_filter, std::move(callback));
}
// Asynchronously loads all entries from the database and invokes |callback| // Asynchronously loads all entries from the database and invokes |callback|
// when complete. // when complete.
virtual void LoadEntries(LoadCallback callback) = 0; virtual void LoadEntries(LoadCallback callback) {
db_wrapper_->template LoadEntries<T>(std::move(callback));
}
// Asynchronously loads entries that satisfies the |filter| from the database // Asynchronously loads entries that satisfies the |filter| from the database
// and invokes |callback| when complete. The filter will be called on // and invokes |callback| when complete. The filter will be called on
// ProtoDatabase's taskrunner. // ProtoDatabase's taskrunner.
virtual void LoadEntriesWithFilter(const LevelDB::KeyFilter& filter, virtual void LoadEntriesWithFilter(const LevelDB::KeyFilter& filter,
LoadCallback callback) = 0; LoadCallback callback) {
virtual void LoadEntriesWithFilter(const LevelDB::KeyFilter& filter, db_wrapper_->template LoadEntriesWithFilter<T>(filter, std::move(callback));
}
virtual void LoadEntriesWithFilter(const LevelDB::KeyFilter& key_filter,
const leveldb::ReadOptions& options, const leveldb::ReadOptions& options,
const std::string& target_prefix, const std::string& target_prefix,
LoadCallback callback) = 0; LoadCallback callback) {
db_wrapper_->template LoadEntriesWithFilter<T>(
key_filter, options, target_prefix, std::move(callback));
}
virtual void LoadKeysAndEntries(LoadKeysAndEntriesCallback callback) {
db_wrapper_->template LoadKeysAndEntries<T>(std::move(callback));
}
virtual void LoadKeysAndEntries(
typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) = 0;
virtual void LoadKeysAndEntriesWithFilter( virtual void LoadKeysAndEntriesWithFilter(
const LevelDB::KeyFilter& filter, const LevelDB::KeyFilter& filter,
typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) = 0; typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) {
db_wrapper_->template LoadKeysAndEntriesWithFilter<T>(filter,
std::move(callback));
}
virtual void LoadKeysAndEntriesWithFilter( virtual void LoadKeysAndEntriesWithFilter(
const LevelDB::KeyFilter& filter, const LevelDB::KeyFilter& filter,
const leveldb::ReadOptions& options, const leveldb::ReadOptions& options,
const std::string& target_prefix, const std::string& target_prefix,
typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) = 0; typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) {
db_wrapper_->template LoadKeysAndEntriesWithFilter<T>(
filter, options, target_prefix, std::move(callback));
}
// Asynchronously loads all keys from the database and invokes |callback| with // Asynchronously loads all keys from the database and invokes |callback| with
// those keys when complete. // those keys when complete.
virtual void LoadKeys(LoadKeysCallback callback) = 0; virtual void LoadKeys(LoadKeysCallback callback) {
db_wrapper_->LoadKeys(std::move(callback));
}
// Asynchronously loads a single entry, identified by |key|, from the database // Asynchronously loads a single entry, identified by |key|, from the database
// and invokes |callback| when complete. If no entry with |key| is found, // and invokes |callback| when complete. If no entry with |key| is found,
// a nullptr is passed to the callback, but the success flag is still true. // a nullptr is passed to the callback, but the success flag is still true.
virtual void GetEntry(const std::string& key, GetCallback callback) = 0; virtual void GetEntry(const std::string& key, GetCallback callback) {
db_wrapper_->template GetEntry<T>(key, std::move(callback));
}
// Asynchronously destroys the database. // Asynchronously destroys the database.
virtual void Destroy(DestroyCallback callback) = 0; virtual void Destroy(DestroyCallback callback) {
db_wrapper_->Destroy(std::move(callback));
}
bool GetApproximateMemoryUse(uint64_t* approx_mem_use) {
return db_wrapper_->GetApproximateMemoryUse(approx_mem_use);
}
protected:
std::unique_ptr<ProtoLevelDBWrapper> db_wrapper_;
}; };
// Return a new instance of Options, but with two additions: // Return a new instance of Options, but with two additions:
......
...@@ -5,483 +5,16 @@ ...@@ -5,483 +5,16 @@
#ifndef COMPONENTS_LEVELDB_PROTO_PROTO_DATABASE_IMPL_H_ #ifndef COMPONENTS_LEVELDB_PROTO_PROTO_DATABASE_IMPL_H_
#define COMPONENTS_LEVELDB_PROTO_PROTO_DATABASE_IMPL_H_ #define COMPONENTS_LEVELDB_PROTO_PROTO_DATABASE_IMPL_H_
#include <memory> #include "components/leveldb_proto/unique_proto_database.h"
#include <string>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_checker.h"
#include "components/leveldb_proto/leveldb_database.h"
#include "components/leveldb_proto/proto_database.h"
namespace leveldb_proto { namespace leveldb_proto {
using KeyValueVector = base::StringPairs; // Part of an ongoing effort to refactor ProtoDatabase. New users of
using KeyVector = std::vector<std::string>; // ProtoDatabaseImpl should avoid using this in favor of including
// unique_proto_database.h and using UniqueProtoDatabase directly.
// When the ProtoDatabaseImpl instance is deleted, in-progress asynchronous // See https://crbug.com/870813.
// operations will be completed and the corresponding callbacks will be called.
// Construction/calls/destruction should all happen on the same thread.
template <typename T>
class ProtoDatabaseImpl : public ProtoDatabase<T> {
public:
// All blocking calls/disk access will happen on the provided |task_runner|.
explicit ProtoDatabaseImpl(
const scoped_refptr<base::SequencedTaskRunner>& task_runner);
~ProtoDatabaseImpl() override;
// ProtoDatabase implementation.
// TODO(cjhopman): Perhaps Init() shouldn't be exposed to users and not just
// part of the constructor
void Init(const char* client_name,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
typename ProtoDatabase<T>::InitCallback callback) override;
void UpdateEntries(
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector>
entries_to_save,
std::unique_ptr<KeyVector> keys_to_remove,
typename ProtoDatabase<T>::UpdateCallback callback) override;
void UpdateEntriesWithRemoveFilter(
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector>
entries_to_save,
const LevelDB::KeyFilter& delete_key_filter,
typename ProtoDatabase<T>::UpdateCallback callback) override;
void LoadEntries(typename ProtoDatabase<T>::LoadCallback callback) override;
void LoadEntriesWithFilter(
const LevelDB::KeyFilter& filter,
typename ProtoDatabase<T>::LoadCallback callback) override;
void LoadEntriesWithFilter(
const LevelDB::KeyFilter& filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
typename ProtoDatabase<T>::LoadCallback callback) override;
void LoadKeysAndEntries(
typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) override;
void LoadKeysAndEntriesWithFilter(
const LevelDB::KeyFilter& filter,
typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) override;
void LoadKeysAndEntriesWithFilter(
const LevelDB::KeyFilter& filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) override;
void LoadKeys(typename ProtoDatabase<T>::LoadKeysCallback callback) override;
void GetEntry(const std::string& key,
typename ProtoDatabase<T>::GetCallback callback) override;
void Destroy(typename ProtoDatabase<T>::DestroyCallback callback) override;
// Allow callers to provide their own Database implementation.
void InitWithDatabase(std::unique_ptr<LevelDB> database,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
typename ProtoDatabase<T>::InitCallback callback);
bool GetApproximateMemoryUse(uint64_t* approx_mem);
private:
base::ThreadChecker thread_checker_;
// Used to run blocking tasks in-order.
scoped_refptr<base::SequencedTaskRunner> task_runner_;
std::unique_ptr<LevelDB> db_;
DISALLOW_COPY_AND_ASSIGN(ProtoDatabaseImpl);
};
namespace {
template <typename T>
void RunInitCallback(typename ProtoDatabase<T>::InitCallback callback,
const bool* success) {
std::move(callback).Run(*success);
}
template <typename T>
void RunUpdateCallback(typename ProtoDatabase<T>::UpdateCallback callback,
const bool* success) {
std::move(callback).Run(*success);
}
template <typename T>
void RunLoadCallback(typename ProtoDatabase<T>::LoadCallback callback,
bool* success,
std::unique_ptr<std::vector<T>> entries) {
std::move(callback).Run(*success, std::move(entries));
}
template <typename T>
void RunLoadKeysAndEntriesCallback(
typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback,
bool* success,
std::unique_ptr<std::map<std::string, T>> keys_entries) {
std::move(callback).Run(*success, std::move(keys_entries));
}
template <typename T>
void RunLoadKeysCallback(typename ProtoDatabase<T>::LoadKeysCallback callback,
std::unique_ptr<bool> success,
std::unique_ptr<std::vector<std::string>> keys) {
std::move(callback).Run(*success, std::move(keys));
}
template <typename T>
void RunGetCallback(typename ProtoDatabase<T>::GetCallback callback,
const bool* success,
const bool* found,
std::unique_ptr<T> entry) {
std::move(callback).Run(*success, *found ? std::move(entry) : nullptr);
}
template <typename T>
void RunDestroyCallback(typename ProtoDatabase<T>::DestroyCallback callback,
const bool* success) {
std::move(callback).Run(*success);
}
inline void InitFromTaskRunner(LevelDB* database,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
bool* success) {
DCHECK(success);
// TODO(cjhopman): Histogram for database size.
*success = database->Init(database_dir, options);
}
inline void DestroyFromTaskRunner(std::unique_ptr<LevelDB> leveldb,
bool* success) {
CHECK(success);
*success = leveldb->Destroy();
}
template <typename T>
void UpdateEntriesFromTaskRunner(
LevelDB* database,
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save,
std::unique_ptr<KeyVector> keys_to_remove,
bool* success) {
DCHECK(success);
// Serialize the values from Proto to string before passing on to database.
KeyValueVector pairs_to_save;
for (const auto& pair : *entries_to_save) {
pairs_to_save.push_back(
std::make_pair(pair.first, pair.second.SerializeAsString()));
}
*success = database->Save(pairs_to_save, *keys_to_remove);
}
template <typename T>
void UpdateEntriesWithRemoveFilterFromTaskRunner(
LevelDB* database,
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save,
const LevelDB::KeyFilter& delete_key_filter,
bool* success) {
DCHECK(success);
// Serialize the values from Proto to string before passing on to database.
KeyValueVector pairs_to_save;
for (const auto& pair : *entries_to_save) {
pairs_to_save.push_back(
std::make_pair(pair.first, pair.second.SerializeAsString()));
}
*success = database->UpdateWithRemoveFilter(pairs_to_save, delete_key_filter);
}
template <typename T>
void LoadKeysAndEntriesFromTaskRunner(LevelDB* database,
const LevelDB::KeyFilter& filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
std::map<std::string, T>* keys_entries,
bool* success) {
DCHECK(success);
DCHECK(keys_entries);
keys_entries->clear();
std::map<std::string, std::string> loaded_entries;
*success = database->LoadKeysAndEntriesWithFilter(filter, &loaded_entries,
options, target_prefix);
for (const auto& pair : loaded_entries) {
T entry;
if (!entry.ParseFromString(pair.second)) {
DLOG(WARNING) << "Unable to parse leveldb_proto entry";
// TODO(cjhopman): Decide what to do about un-parseable entries.
}
keys_entries->insert(std::make_pair(pair.first, entry));
}
}
template <typename T>
void LoadEntriesFromTaskRunner(LevelDB* database,
const LevelDB::KeyFilter& filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
std::vector<T>* entries,
bool* success) {
entries->clear();
std::map<std::string, T> keys_entries;
LoadKeysAndEntriesFromTaskRunner<T>(database, filter, options, target_prefix,
&keys_entries, success);
for (const auto& pair : keys_entries)
entries->push_back(pair.second);
}
inline void LoadKeysFromTaskRunner(LevelDB* database,
std::vector<std::string>* keys,
bool* success) {
DCHECK(success);
DCHECK(keys);
keys->clear();
*success = database->LoadKeys(keys);
}
template <typename T>
void GetEntryFromTaskRunner(LevelDB* database,
const std::string& key,
T* entry,
bool* found,
bool* success) {
DCHECK(success);
DCHECK(found);
DCHECK(entry);
std::string serialized_entry;
*success = database->Get(key, found, &serialized_entry);
if (!*success) {
*found = false;
return;
}
if (!*found)
return;
if (!entry->ParseFromString(serialized_entry)) {
*found = false;
DLOG(WARNING) << "Unable to parse leveldb_proto entry";
// TODO(cjhopman): Decide what to do about un-parseable entries.
}
}
} // namespace
template <typename T>
ProtoDatabaseImpl<T>::ProtoDatabaseImpl(
const scoped_refptr<base::SequencedTaskRunner>& task_runner)
: task_runner_(task_runner) {}
template <typename T>
ProtoDatabaseImpl<T>::~ProtoDatabaseImpl() {
DCHECK(thread_checker_.CalledOnValidThread());
if (db_.get() && !task_runner_->DeleteSoon(FROM_HERE, db_.release()))
DLOG(WARNING) << "Proto database will not be deleted.";
}
template <typename T>
void ProtoDatabaseImpl<T>::Init(
const char* client_name,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
typename ProtoDatabase<T>::InitCallback callback) {
DCHECK(thread_checker_.CalledOnValidThread());
InitWithDatabase(base::WrapUnique(new LevelDB(client_name)), database_dir,
options, std::move(callback));
}
template <typename T>
void ProtoDatabaseImpl<T>::Destroy(
typename ProtoDatabase<T>::DestroyCallback callback) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(db_);
bool* success = new bool(false);
task_runner_->PostTaskAndReply(
FROM_HERE, base::BindOnce(DestroyFromTaskRunner, std::move(db_), success),
base::BindOnce(RunDestroyCallback<T>, std::move(callback),
base::Owned(success)));
}
template <typename T>
void ProtoDatabaseImpl<T>::InitWithDatabase(
std::unique_ptr<LevelDB> database,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
typename ProtoDatabase<T>::InitCallback callback) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!db_);
DCHECK(database);
db_ = std::move(database);
bool* success = new bool(false);
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(InitFromTaskRunner, base::Unretained(db_.get()),
database_dir, options, success),
base::BindOnce(RunInitCallback<T>, std::move(callback),
base::Owned(success)));
}
template <typename T>
void ProtoDatabaseImpl<T>::UpdateEntries(
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save,
std::unique_ptr<KeyVector> keys_to_remove,
typename ProtoDatabase<T>::UpdateCallback callback) {
DCHECK(thread_checker_.CalledOnValidThread());
bool* success = new bool(false);
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(UpdateEntriesFromTaskRunner<T>,
base::Unretained(db_.get()), std::move(entries_to_save),
std::move(keys_to_remove), success),
base::BindOnce(RunUpdateCallback<T>, std::move(callback),
base::Owned(success)));
}
template <typename T>
void ProtoDatabaseImpl<T>::UpdateEntriesWithRemoveFilter(
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save,
const LevelDB::KeyFilter& delete_key_filter,
typename ProtoDatabase<T>::UpdateCallback callback) {
DCHECK(thread_checker_.CalledOnValidThread());
bool* success = new bool(false);
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(UpdateEntriesWithRemoveFilterFromTaskRunner<T>,
base::Unretained(db_.get()), std::move(entries_to_save),
delete_key_filter, success),
base::BindOnce(RunUpdateCallback<T>, std::move(callback),
base::Owned(success)));
}
template <typename T>
void ProtoDatabaseImpl<T>::LoadEntries(
typename ProtoDatabase<T>::LoadCallback callback) {
LoadEntriesWithFilter(LevelDB::KeyFilter(), std::move(callback));
}
template <typename T>
void ProtoDatabaseImpl<T>::LoadEntriesWithFilter(
const LevelDB::KeyFilter& key_filter,
typename ProtoDatabase<T>::LoadCallback callback) {
LoadEntriesWithFilter(key_filter, leveldb::ReadOptions(), std::string(),
std::move(callback));
}
template <typename T>
void ProtoDatabaseImpl<T>::LoadEntriesWithFilter(
const LevelDB::KeyFilter& key_filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
typename ProtoDatabase<T>::LoadCallback callback) {
DCHECK(thread_checker_.CalledOnValidThread());
bool* success = new bool(false);
auto entries = std::make_unique<std::vector<T>>();
// Get this pointer before entries is std::move()'d so we can use it below.
std::vector<T>* entries_ptr = entries.get();
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(LoadEntriesFromTaskRunner<T>, base::Unretained(db_.get()),
key_filter, options, target_prefix, entries_ptr, success),
base::BindOnce(RunLoadCallback<T>, std::move(callback),
base::Owned(success), std::move(entries)));
}
template <typename T>
void ProtoDatabaseImpl<T>::LoadKeysAndEntries(
typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) {
LoadKeysAndEntriesWithFilter(LevelDB::KeyFilter(), std::move(callback));
}
template <typename T>
void ProtoDatabaseImpl<T>::LoadKeysAndEntriesWithFilter(
const LevelDB::KeyFilter& key_filter,
typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) {
LoadKeysAndEntriesWithFilter(key_filter, leveldb::ReadOptions(),
std::string(), std::move(callback));
}
template <typename T>
void ProtoDatabaseImpl<T>::LoadKeysAndEntriesWithFilter(
const LevelDB::KeyFilter& key_filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) {
DCHECK(thread_checker_.CalledOnValidThread());
bool* success = new bool(false);
auto keys_entries = std::make_unique<std::map<std::string, T>>();
// Get this pointer before entries is std::move()'d so we can use it below.
std::map<std::string, T>* keys_entries_ptr = keys_entries.get();
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(LoadKeysAndEntriesFromTaskRunner<T>,
base::Unretained(db_.get()), key_filter, options,
target_prefix, keys_entries_ptr, success),
base::BindOnce(RunLoadKeysAndEntriesCallback<T>, std::move(callback),
base::Owned(success), std::move(keys_entries)));
}
template <typename T>
void ProtoDatabaseImpl<T>::LoadKeys(
typename ProtoDatabase<T>::LoadKeysCallback callback) {
DCHECK(thread_checker_.CalledOnValidThread());
auto success = std::make_unique<bool>(false);
auto keys = std::make_unique<std::vector<std::string>>();
auto load_task =
base::Bind(LoadKeysFromTaskRunner, base::Unretained(db_.get()),
keys.get(), success.get());
task_runner_->PostTaskAndReply(
FROM_HERE, load_task,
base::BindOnce(RunLoadKeysCallback<T>, std::move(callback),
std::move(success), std::move(keys)));
}
template <typename T>
void ProtoDatabaseImpl<T>::GetEntry(
const std::string& key,
typename ProtoDatabase<T>::GetCallback callback) {
DCHECK(thread_checker_.CalledOnValidThread());
bool* success = new bool(false);
bool* found = new bool(false);
std::unique_ptr<T> entry(new T());
// Get this pointer before entry is std::move()'d so we can use it below.
T* entry_ptr = entry.get();
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(GetEntryFromTaskRunner<T>, base::Unretained(db_.get()),
key, entry_ptr, found, success),
base::BindOnce(RunGetCallback<T>, std::move(callback),
base::Owned(success), base::Owned(found),
std::move(entry)));
}
template <typename T> template <typename T>
bool ProtoDatabaseImpl<T>::GetApproximateMemoryUse(uint64_t* approx_mem) { using ProtoDatabaseImpl = UniqueProtoDatabase<T>;
return db_->GetApproximateMemoryUse(approx_mem);
}
} // namespace leveldb_proto } // namespace leveldb_proto
......
...@@ -24,8 +24,8 @@ ...@@ -24,8 +24,8 @@
#include "base/threading/thread.h" #include "base/threading/thread.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "components/leveldb_proto/leveldb_database.h" #include "components/leveldb_proto/leveldb_database.h"
#include "components/leveldb_proto/proto_database_impl.h"
#include "components/leveldb_proto/testing/proto/test_db.pb.h" #include "components/leveldb_proto/testing/proto/test_db.pb.h"
#include "components/leveldb_proto/unique_proto_database.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_test.h" #include "testing/perf/perf_test.h"
...@@ -85,7 +85,7 @@ class TestDatabase { ...@@ -85,7 +85,7 @@ class TestDatabase {
TestDatabase(const std::string& name, TestDatabase(const std::string& name,
scoped_refptr<base::SingleThreadTaskRunner> task_runner, scoped_refptr<base::SingleThreadTaskRunner> task_runner,
const base::FilePath& path) { const base::FilePath& path) {
db_.reset(new ProtoDatabaseImpl<TestProto>(task_runner)); db_.reset(new UniqueProtoDatabase<TestProto>(task_runner));
leveldb_env::Options options = leveldb_proto::CreateSimpleOptions(); leveldb_env::Options options = leveldb_proto::CreateSimpleOptions();
base::RunLoop run_init_db; base::RunLoop run_init_db;
...@@ -102,11 +102,11 @@ class TestDatabase { ...@@ -102,11 +102,11 @@ class TestDatabase {
} }
bool is_initialized() const { return is_initialized_; } bool is_initialized() const { return is_initialized_; }
ProtoDatabaseImpl<TestProto>* proto_db() const { return db_.get(); } UniqueProtoDatabase<TestProto>* proto_db() const { return db_.get(); }
private: private:
bool is_initialized_ = false; bool is_initialized_ = false;
std::unique_ptr<ProtoDatabaseImpl<TestProto>> db_; std::unique_ptr<UniqueProtoDatabase<TestProto>> db_;
}; };
} // namespace } // namespace
......
// 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/proto_leveldb_wrapper.h"
namespace leveldb_proto {
namespace {
void RunInitCallback(typename ProtoLevelDBWrapper::InitCallback callback,
const bool* success) {
std::move(callback).Run(*success);
}
inline void InitFromTaskRunner(LevelDB* database,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
bool* success) {
DCHECK(success);
// TODO(cjhopman): Histogram for database size.
*success = database->Init(database_dir, options);
}
void RunDestroyCallback(typename ProtoLevelDBWrapper::DestroyCallback callback,
const bool* success) {
std::move(callback).Run(*success);
}
inline void DestroyFromTaskRunner(LevelDB* database, bool* success) {
CHECK(success);
*success = database->Destroy();
}
void RunLoadKeysCallback(
typename ProtoLevelDBWrapper::LoadKeysCallback callback,
std::unique_ptr<bool> success,
std::unique_ptr<std::vector<std::string>> keys) {
std::move(callback).Run(*success, std::move(keys));
}
inline void LoadKeysFromTaskRunner(LevelDB* database,
std::vector<std::string>* keys,
bool* success) {
DCHECK(success);
DCHECK(keys);
keys->clear();
*success = database->LoadKeys(keys);
}
} // namespace
ProtoLevelDBWrapper::ProtoLevelDBWrapper(
const scoped_refptr<base::SequencedTaskRunner>& task_runner)
: task_runner_(task_runner) {}
ProtoLevelDBWrapper::~ProtoLevelDBWrapper() = default;
void ProtoLevelDBWrapper::InitWithDatabase(
LevelDB* database,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
typename ProtoLevelDBWrapper::InitCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!db_);
DCHECK(database);
db_ = database;
bool* success = new bool(false);
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(InitFromTaskRunner, base::Unretained(db_), database_dir,
options, success),
base::BindOnce(RunInitCallback, std::move(callback),
base::Owned(success)));
}
void ProtoLevelDBWrapper::Destroy(
typename ProtoLevelDBWrapper::DestroyCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(db_);
bool* success = new bool(false);
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(DestroyFromTaskRunner, base::Unretained(db_), success),
base::BindOnce(RunDestroyCallback, std::move(callback),
base::Owned(success)));
}
void ProtoLevelDBWrapper::LoadKeys(
typename ProtoLevelDBWrapper::LoadKeysCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
auto success = std::make_unique<bool>(false);
auto keys = std::make_unique<std::vector<std::string>>();
auto load_task = base::BindOnce(LoadKeysFromTaskRunner, base::Unretained(db_),
keys.get(), success.get());
task_runner_->PostTaskAndReply(
FROM_HERE, std::move(load_task),
base::BindOnce(RunLoadKeysCallback, std::move(callback),
std::move(success), std::move(keys)));
}
bool ProtoLevelDBWrapper::GetApproximateMemoryUse(uint64_t* approx_mem_use) {
return db_->GetApproximateMemoryUse(approx_mem_use);
}
const scoped_refptr<base::SequencedTaskRunner>&
ProtoLevelDBWrapper::task_runner() {
return task_runner_;
}
} // namespace leveldb_proto
\ No newline at end of file
// 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.
#ifndef COMPONENTS_LEVELDB_PROTO_PROTO_LEVELDB_WRAPPER_H_
#define COMPONENTS_LEVELDB_PROTO_PROTO_LEVELDB_WRAPPER_H_
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/callback.h"
#include "base/memory/ptr_util.h"
#include "base/sequenced_task_runner.h"
#include "base/threading/thread_checker.h"
#include "components/leveldb_proto/leveldb_database.h"
#include "third_party/leveldatabase/env_chromium.h"
namespace base {
class FilePath;
}
namespace leveldb_proto {
using KeyValueVector = base::StringPairs;
using KeyVector = std::vector<std::string>;
// When the ProtoDatabase instance is deleted, in-progress asynchronous
// operations will be completed and the corresponding callbacks will be called.
// Construction/calls/destruction should all happen on the same thread.
class ProtoLevelDBWrapper {
public:
using InitCallback = base::OnceCallback<void(bool success)>;
using UpdateCallback = base::OnceCallback<void(bool success)>;
using LoadKeysCallback =
base::OnceCallback<void(bool success,
std::unique_ptr<std::vector<std::string>>)>;
using DestroyCallback = base::OnceCallback<void(bool success)>;
using OnCreateCallback = base::OnceCallback<void(ProtoLevelDBWrapper*)>;
template <typename T>
class Internal {
public:
using LoadCallback =
base::OnceCallback<void(bool success, std::unique_ptr<std::vector<T>>)>;
using GetCallback =
base::OnceCallback<void(bool success, std::unique_ptr<T>)>;
using LoadKeysAndEntriesCallback =
base::OnceCallback<void(bool success,
std::unique_ptr<std::map<std::string, T>>)>;
// A list of key-value (string, T) tuples.
using KeyEntryVector = std::vector<std::pair<std::string, T>>;
};
// All blocking calls/disk access will happen on the provided |task_runner|.
ProtoLevelDBWrapper(
const scoped_refptr<base::SequencedTaskRunner>& task_runner);
virtual ~ProtoLevelDBWrapper();
template <typename T>
void UpdateEntries(
std::unique_ptr<typename ProtoLevelDBWrapper::Internal<T>::KeyEntryVector>
entries_to_save,
std::unique_ptr<KeyVector> keys_to_remove,
UpdateCallback callback);
template <typename T>
void UpdateEntriesWithRemoveFilter(
std::unique_ptr<typename ProtoLevelDBWrapper::Internal<T>::KeyEntryVector>
entries_to_save,
const LevelDB::KeyFilter& delete_key_filter,
UpdateCallback callback);
template <typename T>
void LoadEntries(
typename ProtoLevelDBWrapper::Internal<T>::LoadCallback callback);
template <typename T>
void LoadEntriesWithFilter(
const LevelDB::KeyFilter& key_filter,
typename ProtoLevelDBWrapper::Internal<T>::LoadCallback callback);
template <typename T>
void LoadEntriesWithFilter(
const LevelDB::KeyFilter& key_filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
typename ProtoLevelDBWrapper::Internal<T>::LoadCallback callback);
template <typename T>
void LoadKeysAndEntries(
typename ProtoLevelDBWrapper::Internal<T>::LoadKeysAndEntriesCallback
callback);
template <typename T>
void LoadKeysAndEntriesWithFilter(
const LevelDB::KeyFilter& filter,
typename ProtoLevelDBWrapper::Internal<T>::LoadKeysAndEntriesCallback
callback);
template <typename T>
void LoadKeysAndEntriesWithFilter(
const LevelDB::KeyFilter& filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
typename ProtoLevelDBWrapper::Internal<T>::LoadKeysAndEntriesCallback
callback);
void LoadKeys(LoadKeysCallback callback);
template <typename T>
void GetEntry(
const std::string& key,
typename ProtoLevelDBWrapper::Internal<T>::GetCallback callback);
void Destroy(DestroyCallback callback);
// Allow callers to provide their own Database implementation.
void InitWithDatabase(LevelDB* database,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
InitCallback callback);
bool GetApproximateMemoryUse(uint64_t* approx_mem_use);
const scoped_refptr<base::SequencedTaskRunner>& task_runner();
private:
THREAD_CHECKER(thread_checker_);
// Used to run blocking tasks in-order, must be the TaskRunner that |db_|
// relies on.
scoped_refptr<base::SequencedTaskRunner> task_runner_;
LevelDB* db_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(ProtoLevelDBWrapper);
};
namespace {
template <typename T>
void RunUpdateCallback(typename ProtoLevelDBWrapper::UpdateCallback callback,
const bool* success) {
std::move(callback).Run(*success);
}
template <typename T>
void RunLoadCallback(
typename ProtoLevelDBWrapper::Internal<T>::LoadCallback callback,
bool* success,
std::unique_ptr<std::vector<T>> entries) {
std::move(callback).Run(*success, std::move(entries));
}
template <typename T>
void RunLoadKeysAndEntriesCallback(
typename ProtoLevelDBWrapper::Internal<T>::LoadKeysAndEntriesCallback
callback,
bool* success,
std::unique_ptr<std::map<std::string, T>> keys_entries) {
std::move(callback).Run(*success, std::move(keys_entries));
}
template <typename T>
void RunGetCallback(
typename ProtoLevelDBWrapper::Internal<T>::GetCallback callback,
const bool* success,
const bool* found,
std::unique_ptr<T> entry) {
std::move(callback).Run(*success, *found ? std::move(entry) : nullptr);
}
template <typename T>
void UpdateEntriesFromTaskRunner(
LevelDB* database,
std::unique_ptr<typename ProtoLevelDBWrapper::Internal<T>::KeyEntryVector>
entries_to_save,
std::unique_ptr<KeyVector> keys_to_remove,
bool* success) {
DCHECK(success);
// Serialize the values from Proto to string before passing on to database.
KeyValueVector pairs_to_save;
for (const auto& pair : *entries_to_save) {
pairs_to_save.push_back(
std::make_pair(pair.first, pair.second.SerializeAsString()));
}
*success = database->Save(pairs_to_save, *keys_to_remove);
}
template <typename T>
void UpdateEntriesWithRemoveFilterFromTaskRunner(
LevelDB* database,
std::unique_ptr<typename ProtoLevelDBWrapper::Internal<T>::KeyEntryVector>
entries_to_save,
const LevelDB::KeyFilter& delete_key_filter,
bool* success) {
DCHECK(success);
// Serialize the values from Proto to string before passing on to database.
KeyValueVector pairs_to_save;
for (const auto& pair : *entries_to_save) {
pairs_to_save.push_back(
std::make_pair(pair.first, pair.second.SerializeAsString()));
}
*success = database->UpdateWithRemoveFilter(pairs_to_save, delete_key_filter);
}
template <typename T>
void LoadKeysAndEntriesFromTaskRunner(LevelDB* database,
const LevelDB::KeyFilter& filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
std::map<std::string, T>* keys_entries,
bool* success) {
DCHECK(success);
DCHECK(keys_entries);
keys_entries->clear();
std::map<std::string, std::string> loaded_entries;
*success = database->LoadKeysAndEntriesWithFilter(filter, &loaded_entries,
options, target_prefix);
for (const auto& pair : loaded_entries) {
T entry;
if (!entry.ParseFromString(pair.second)) {
DLOG(WARNING) << "Unable to parse leveldb_proto entry";
// TODO(cjhopman): Decide what to do about un-parseable entries.
}
keys_entries->insert(std::make_pair(pair.first, entry));
}
}
template <typename T>
void LoadEntriesFromTaskRunner(LevelDB* database,
const LevelDB::KeyFilter& filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
std::vector<T>* entries,
bool* success) {
DCHECK(success);
DCHECK(entries);
entries->clear();
std::vector<std::string> loaded_entries;
*success =
database->LoadWithFilter(filter, &loaded_entries, options, target_prefix);
for (const auto& serialized_entry : loaded_entries) {
T entry;
if (!entry.ParseFromString(serialized_entry)) {
DLOG(WARNING) << "Unable to parse leveldb_proto entry";
// TODO(cjhopman): Decide what to do about un-parseable entries.
}
entries->push_back(entry);
}
}
template <typename T>
void GetEntryFromTaskRunner(LevelDB* database,
const std::string& key,
T* entry,
bool* found,
bool* success) {
DCHECK(success);
DCHECK(found);
DCHECK(entry);
std::string serialized_entry;
*success = database->Get(key, found, &serialized_entry);
if (!*success) {
*found = false;
return;
}
if (!*found)
return;
if (!entry->ParseFromString(serialized_entry)) {
*found = false;
DLOG(WARNING) << "Unable to parse leveldb_proto entry";
// TODO(cjhopman): Decide what to do about un-parseable entries.
}
}
} // namespace
template <typename T>
void ProtoLevelDBWrapper::UpdateEntries(
std::unique_ptr<typename ProtoLevelDBWrapper::Internal<T>::KeyEntryVector>
entries_to_save,
std::unique_ptr<KeyVector> keys_to_remove,
typename ProtoLevelDBWrapper::UpdateCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
bool* success = new bool(false);
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(UpdateEntriesFromTaskRunner<T>, base::Unretained(db_),
std::move(entries_to_save), std::move(keys_to_remove),
success),
base::BindOnce(RunUpdateCallback<T>, std::move(callback),
base::Owned(success)));
}
template <typename T>
void ProtoLevelDBWrapper::UpdateEntriesWithRemoveFilter(
std::unique_ptr<typename ProtoLevelDBWrapper::Internal<T>::KeyEntryVector>
entries_to_save,
const LevelDB::KeyFilter& delete_key_filter,
typename ProtoLevelDBWrapper::UpdateCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
bool* success = new bool(false);
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(UpdateEntriesWithRemoveFilterFromTaskRunner<T>,
base::Unretained(db_), std::move(entries_to_save),
delete_key_filter, success),
base::BindOnce(RunUpdateCallback<T>, std::move(callback),
base::Owned(success)));
}
template <typename T>
void ProtoLevelDBWrapper::LoadEntries(
typename ProtoLevelDBWrapper::Internal<T>::LoadCallback callback) {
LoadEntriesWithFilter<T>(LevelDB::KeyFilter(), std::move(callback));
}
template <typename T>
void ProtoLevelDBWrapper::LoadEntriesWithFilter(
const LevelDB::KeyFilter& key_filter,
typename ProtoLevelDBWrapper::Internal<T>::LoadCallback callback) {
LoadEntriesWithFilter<T>(key_filter, leveldb::ReadOptions(), std::string(),
std::move(callback));
}
template <typename T>
void ProtoLevelDBWrapper::LoadEntriesWithFilter(
const LevelDB::KeyFilter& key_filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
typename ProtoLevelDBWrapper::Internal<T>::LoadCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
bool* success = new bool(false);
std::unique_ptr<std::vector<T>> entries(new std::vector<T>());
// Get this pointer before entries is std::move()'d so we can use it below.
std::vector<T>* entries_ptr = entries.get();
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(LoadEntriesFromTaskRunner<T>, base::Unretained(db_),
key_filter, options, target_prefix, entries_ptr, success),
base::BindOnce(RunLoadCallback<T>, std::move(callback),
base::Owned(success), std::move(entries)));
}
template <typename T>
void ProtoLevelDBWrapper::LoadKeysAndEntries(
typename ProtoLevelDBWrapper::Internal<T>::LoadKeysAndEntriesCallback
callback) {
LoadKeysAndEntriesWithFilter<T>(LevelDB::KeyFilter(), std::move(callback));
}
template <typename T>
void ProtoLevelDBWrapper::LoadKeysAndEntriesWithFilter(
const LevelDB::KeyFilter& key_filter,
typename ProtoLevelDBWrapper::Internal<T>::LoadKeysAndEntriesCallback
callback) {
LoadKeysAndEntriesWithFilter<T>(key_filter, leveldb::ReadOptions(),
std::string(), std::move(callback));
}
template <typename T>
void ProtoLevelDBWrapper::LoadKeysAndEntriesWithFilter(
const LevelDB::KeyFilter& key_filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
typename ProtoLevelDBWrapper::Internal<T>::LoadKeysAndEntriesCallback
callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
bool* success = new bool(false);
auto keys_entries = std::make_unique<std::map<std::string, T>>();
// Get this pointer before entries is std::move()'d so we can use it below.
std::map<std::string, T>* keys_entries_ptr = keys_entries.get();
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(LoadKeysAndEntriesFromTaskRunner<T>, base::Unretained(db_),
key_filter, options, target_prefix, keys_entries_ptr,
success),
base::BindOnce(RunLoadKeysAndEntriesCallback<T>, std::move(callback),
base::Owned(success), std::move(keys_entries)));
}
template <typename T>
void ProtoLevelDBWrapper::GetEntry(
const std::string& key,
typename ProtoLevelDBWrapper::Internal<T>::GetCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
bool* success = new bool(false);
bool* found = new bool(false);
std::unique_ptr<T> entry(new T());
// Get this pointer before entry is std::move()'d so we can use it below.
T* entry_ptr = entry.get();
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(GetEntryFromTaskRunner<T>, base::Unretained(db_), key,
entry_ptr, found, success),
base::BindOnce(RunGetCallback<T>, std::move(callback),
base::Owned(success), base::Owned(found),
std::move(entry)));
}
} // namespace leveldb_proto
#endif // COMPONENTS_LEVELDB_PROTO_PROTO_LEVELDB_WRAPPER_H_
\ No newline at end of file
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/task/post_task.h"
#include "base/test/test_simple_task_runner.h"
#include "components/leveldb_proto/proto_database.h" #include "components/leveldb_proto/proto_database.h"
namespace leveldb_proto { namespace leveldb_proto {
...@@ -34,6 +36,11 @@ class FakeDB : public ProtoDatabase<T> { ...@@ -34,6 +36,11 @@ class FakeDB : public ProtoDatabase<T> {
const base::FilePath& database_dir, const base::FilePath& database_dir,
const leveldb_env::Options& options, const leveldb_env::Options& options,
typename ProtoDatabase<T>::InitCallback callback) override; typename ProtoDatabase<T>::InitCallback callback) override;
void InitWithDatabase(
LevelDB* database,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
typename ProtoLevelDBWrapper::InitCallback callback) override;
void UpdateEntries( void UpdateEntries(
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector> std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector>
entries_to_save, entries_to_save,
...@@ -115,7 +122,9 @@ class FakeDB : public ProtoDatabase<T> { ...@@ -115,7 +122,9 @@ class FakeDB : public ProtoDatabase<T> {
template <typename T> template <typename T>
FakeDB<T>::FakeDB(EntryMap* db) FakeDB<T>::FakeDB(EntryMap* db)
: db_(db) {} : ProtoDatabase<T>(base::MakeRefCounted<base::TestSimpleTaskRunner>()) {
db_ = db;
}
template <typename T> template <typename T>
FakeDB<T>::~FakeDB() {} FakeDB<T>::~FakeDB() {}
...@@ -129,6 +138,15 @@ void FakeDB<T>::Init(const char* client_name, ...@@ -129,6 +138,15 @@ void FakeDB<T>::Init(const char* client_name,
init_callback_ = std::move(callback); init_callback_ = std::move(callback);
} }
template <typename T>
void FakeDB<T>::InitWithDatabase(
LevelDB* database,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
typename ProtoLevelDBWrapper::InitCallback callback) {
Init("", database_dir, options, std::move(callback));
}
template <typename T> template <typename T>
void FakeDB<T>::UpdateEntries( void FakeDB<T>::UpdateEntries(
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save, std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save,
......
// Copyright 2014 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.
#ifndef COMPONENTS_LEVELDB_PROTO_UNIQUE_PROTO_DATABASE_H_
#define COMPONENTS_LEVELDB_PROTO_UNIQUE_PROTO_DATABASE_H_
#include "base/sequenced_task_runner.h"
#include "base/threading/thread_checker.h"
#include "components/leveldb_proto/leveldb_database.h"
#include "components/leveldb_proto/proto_database.h"
#include "components/leveldb_proto/proto_leveldb_wrapper.h"
namespace leveldb_proto {
// An implementation of ProtoDatabase<T> that manages the lifecycle of a unique
// LevelDB instance.
template <typename T>
class UniqueProtoDatabase : public ProtoDatabase<T> {
public:
UniqueProtoDatabase(
const scoped_refptr<base::SequencedTaskRunner>& task_runner)
: ProtoDatabase<T>(task_runner) {}
virtual void Init(const char* client_name,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
typename ProtoDatabase<T>::InitCallback callback) override {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
db_ = std::make_unique<LevelDB>(client_name);
ProtoDatabase<T>::InitWithDatabase(db_.get(), database_dir, options,
std::move(callback));
}
virtual ~UniqueProtoDatabase() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (db_.get() &&
!this->db_wrapper_->task_runner()->DeleteSoon(FROM_HERE, db_.release()))
DLOG(WARNING) << "Proto database will not be deleted.";
}
private:
THREAD_CHECKER(thread_checker_);
scoped_refptr<base::SequencedTaskRunner> task_runner_;
std::unique_ptr<LevelDB> db_;
};
} // namespace leveldb_proto
#endif // COMPONENTS_LEVELDB_PROTO_UNIQUE_PROTO_DATABASE_H_
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "components/leveldb_proto/proto_database_impl.h" #include "components/leveldb_proto/unique_proto_database.h"
#include <stddef.h> #include <stddef.h>
...@@ -174,13 +174,13 @@ void ExpectEntryPointersEquals(EntryMap expected, ...@@ -174,13 +174,13 @@ void ExpectEntryPointersEquals(EntryMap expected,
} }
} }
class ProtoDatabaseImplTest : public testing::Test { class UniqueProtoDatabaseTest : public testing::Test {
public: public:
ProtoDatabaseImplTest() UniqueProtoDatabaseTest()
: options_(MakeMatcher(new OptionsEqMatcher(CreateSimpleOptions()))) {} : options_(MakeMatcher(new OptionsEqMatcher(CreateSimpleOptions()))) {}
void SetUp() override { void SetUp() override {
main_loop_.reset(new MessageLoop()); main_loop_.reset(new MessageLoop());
db_.reset(new ProtoDatabaseImpl<TestProto>(main_loop_->task_runner())); db_.reset(new UniqueProtoDatabase<TestProto>(main_loop_->task_runner()));
} }
void TearDown() override { void TearDown() override {
...@@ -190,32 +190,32 @@ class ProtoDatabaseImplTest : public testing::Test { ...@@ -190,32 +190,32 @@ class ProtoDatabaseImplTest : public testing::Test {
} }
const Matcher<const Options&> options_; const Matcher<const Options&> options_;
std::unique_ptr<ProtoDatabaseImpl<TestProto>> db_; std::unique_ptr<UniqueProtoDatabase<TestProto>> db_;
std::unique_ptr<MessageLoop> main_loop_; std::unique_ptr<MessageLoop> main_loop_;
}; };
// Test that ProtoDatabaseImpl calls Init on the underlying database and that // Test that UniqueProtoDatabase calls Init on the underlying database and that
// the caller's InitCallback is called with the correct value. // the caller's InitCallback is called with the correct value.
TEST_F(ProtoDatabaseImplTest, TestDBInitSuccess) { TEST_F(UniqueProtoDatabaseTest, TestDBInitSuccess) {
base::FilePath path(FILE_PATH_LITERAL("/fake/path")); base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
MockDB* mock_db = new MockDB(); auto mock_db = std::make_unique<MockDB>();
EXPECT_CALL(*mock_db, Init(path, options_)).WillOnce(Return(true)); EXPECT_CALL(*mock_db, Init(path, options_)).WillOnce(Return(true));
MockDatabaseCaller caller; MockDatabaseCaller caller;
EXPECT_CALL(caller, InitCallback(true)); EXPECT_CALL(caller, InitCallback(true));
db_->InitWithDatabase(base::WrapUnique(mock_db), path, CreateSimpleOptions(), db_->InitWithDatabase(mock_db.get(), path, CreateSimpleOptions(),
base::BindOnce(&MockDatabaseCaller::InitCallback, base::BindOnce(&MockDatabaseCaller::InitCallback,
base::Unretained(&caller))); base::Unretained(&caller)));
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
TEST_F(ProtoDatabaseImplTest, TestDBInitFailure) { TEST_F(UniqueProtoDatabaseTest, TestDBInitFailure) {
base::FilePath path(FILE_PATH_LITERAL("/fake/path")); base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
MockDB* mock_db = new MockDB(); auto mock_db = std::make_unique<MockDB>();
Options options; Options options;
options.create_if_missing = true; options.create_if_missing = true;
EXPECT_CALL(*mock_db, Init(path, OptionsEq(options))).WillOnce(Return(false)); EXPECT_CALL(*mock_db, Init(path, OptionsEq(options))).WillOnce(Return(false));
...@@ -223,23 +223,23 @@ TEST_F(ProtoDatabaseImplTest, TestDBInitFailure) { ...@@ -223,23 +223,23 @@ TEST_F(ProtoDatabaseImplTest, TestDBInitFailure) {
MockDatabaseCaller caller; MockDatabaseCaller caller;
EXPECT_CALL(caller, InitCallback(false)); EXPECT_CALL(caller, InitCallback(false));
db_->InitWithDatabase(base::WrapUnique(mock_db), path, options, db_->InitWithDatabase(mock_db.get(), path, options,
base::BindOnce(&MockDatabaseCaller::InitCallback, base::BindOnce(&MockDatabaseCaller::InitCallback,
base::Unretained(&caller))); base::Unretained(&caller)));
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
TEST_F(ProtoDatabaseImplTest, TestDBDestroySuccess) { TEST_F(UniqueProtoDatabaseTest, TestDBDestroySuccess) {
base::FilePath path(FILE_PATH_LITERAL("/fake/path")); base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
MockDB* mock_db = new MockDB(); auto mock_db = std::make_unique<MockDB>();
EXPECT_CALL(*mock_db, Init(path, options_)).WillOnce(Return(true)); EXPECT_CALL(*mock_db, Init(path, options_)).WillOnce(Return(true));
MockDatabaseCaller caller; MockDatabaseCaller caller;
EXPECT_CALL(caller, InitCallback(true)); EXPECT_CALL(caller, InitCallback(true));
db_->InitWithDatabase(base::WrapUnique(mock_db), path, CreateSimpleOptions(), db_->InitWithDatabase(mock_db.get(), path, CreateSimpleOptions(),
base::BindOnce(&MockDatabaseCaller::InitCallback, base::BindOnce(&MockDatabaseCaller::InitCallback,
base::Unretained(&caller))); base::Unretained(&caller)));
...@@ -251,16 +251,16 @@ TEST_F(ProtoDatabaseImplTest, TestDBDestroySuccess) { ...@@ -251,16 +251,16 @@ TEST_F(ProtoDatabaseImplTest, TestDBDestroySuccess) {
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
TEST_F(ProtoDatabaseImplTest, TestDBDestroyFailure) { TEST_F(UniqueProtoDatabaseTest, TestDBDestroyFailure) {
base::FilePath path(FILE_PATH_LITERAL("/fake/path")); base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
MockDB* mock_db = new MockDB(); auto mock_db = std::make_unique<MockDB>();
EXPECT_CALL(*mock_db, Init(path, options_)).WillOnce(Return(true)); EXPECT_CALL(*mock_db, Init(path, options_)).WillOnce(Return(true));
MockDatabaseCaller caller; MockDatabaseCaller caller;
EXPECT_CALL(caller, InitCallback(true)); EXPECT_CALL(caller, InitCallback(true));
db_->InitWithDatabase(base::WrapUnique(mock_db), path, CreateSimpleOptions(), db_->InitWithDatabase(mock_db.get(), path, CreateSimpleOptions(),
base::BindOnce(&MockDatabaseCaller::InitCallback, base::BindOnce(&MockDatabaseCaller::InitCallback,
base::Unretained(&caller))); base::Unretained(&caller)));
...@@ -301,47 +301,47 @@ ACTION_P(VerifyLoadKeysAndEntries, expected) { ...@@ -301,47 +301,47 @@ ACTION_P(VerifyLoadKeysAndEntries, expected) {
ExpectEntryPointersEquals(expected, actual); ExpectEntryPointersEquals(expected, actual);
} }
// Test that ProtoDatabaseImpl calls Load on the underlying database and that // Test that UniqueProtoDatabase calls Load on the underlying database and that
// the caller's LoadCallback is called with the correct success value. Also // the caller's LoadCallback is called with the correct success value. Also
// confirms that on success, the expected entries are passed to the caller's // confirms that on success, the expected entries are passed to the caller's
// LoadCallback. // LoadCallback.
TEST_F(ProtoDatabaseImplTest, TestDBLoadSuccess) { TEST_F(UniqueProtoDatabaseTest, TestDBLoadSuccess) {
base::FilePath path(FILE_PATH_LITERAL("/fake/path")); base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
MockDB* mock_db = new MockDB(); auto mock_db = std::make_unique<MockDB>();
MockDatabaseCaller caller; MockDatabaseCaller caller;
EntryMap model = GetSmallModel(); EntryMap model = GetSmallModel();
EXPECT_CALL(*mock_db, Init(_, options_)); EXPECT_CALL(*mock_db, Init(_, options_));
EXPECT_CALL(caller, InitCallback(_)); EXPECT_CALL(caller, InitCallback(_));
db_->InitWithDatabase(base::WrapUnique(mock_db), path, CreateSimpleOptions(), db_->InitWithDatabase(mock_db.get(), path, CreateSimpleOptions(),
base::BindOnce(&MockDatabaseCaller::InitCallback, base::BindOnce(&MockDatabaseCaller::InitCallback,
base::Unretained(&caller))); base::Unretained(&caller)));
EXPECT_CALL(*mock_db, LoadKeysAndEntriesWithFilter(_, _, _, _)) EXPECT_CALL(*mock_db, LoadKeysAndEntriesWithFilter(_, _, _, _))
.WillOnce(AppendLoadKeysAndEntries(model)); .WillOnce(AppendLoadKeysAndEntries(model));
EXPECT_CALL(caller, LoadCallback1(true, _)) EXPECT_CALL(caller, LoadKeysAndEntriesCallback1(true, _))
.WillOnce(VerifyLoadEntries(testing::ByRef(model))); .WillOnce(VerifyLoadKeysAndEntries(testing::ByRef(model)));
db_->LoadEntries(base::BindOnce(&MockDatabaseCaller::LoadCallback, db_->LoadKeysAndEntries(
base::BindOnce(&MockDatabaseCaller::LoadKeysAndEntriesCallback,
base::Unretained(&caller))); base::Unretained(&caller)));
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
TEST_F(ProtoDatabaseImplTest, TestDBLoadFailure) { TEST_F(UniqueProtoDatabaseTest, TestDBLoadFailure) {
base::FilePath path(FILE_PATH_LITERAL("/fake/path")); base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
MockDB* mock_db = new MockDB(); auto mock_db = std::make_unique<MockDB>();
MockDatabaseCaller caller; MockDatabaseCaller caller;
EXPECT_CALL(*mock_db, Init(_, options_)); EXPECT_CALL(*mock_db, Init(_, options_));
EXPECT_CALL(caller, InitCallback(_)); EXPECT_CALL(caller, InitCallback(_));
db_->InitWithDatabase(base::WrapUnique(mock_db), path, CreateSimpleOptions(), db_->InitWithDatabase(mock_db.get(), path, CreateSimpleOptions(),
base::BindOnce(&MockDatabaseCaller::InitCallback, base::BindOnce(&MockDatabaseCaller::InitCallback,
base::Unretained(&caller))); base::Unretained(&caller)));
EXPECT_CALL(*mock_db, LoadKeysAndEntriesWithFilter(_, _, _, _)) EXPECT_CALL(*mock_db, LoadWithFilter(_, _, _, _)).WillOnce(Return(false));
.WillOnce(Return(false));
EXPECT_CALL(caller, LoadCallback1(false, _)); EXPECT_CALL(caller, LoadCallback1(false, _));
db_->LoadEntries(base::BindOnce(&MockDatabaseCaller::LoadCallback, db_->LoadEntries(base::BindOnce(&MockDatabaseCaller::LoadCallback,
base::Unretained(&caller))); base::Unretained(&caller)));
...@@ -368,16 +368,16 @@ ACTION_P(VerifyGetEntry, expected) { ...@@ -368,16 +368,16 @@ ACTION_P(VerifyGetEntry, expected) {
EXPECT_EQ(expected.SerializeAsString(), actual->SerializeAsString()); EXPECT_EQ(expected.SerializeAsString(), actual->SerializeAsString());
} }
TEST_F(ProtoDatabaseImplTest, TestDBGetSuccess) { TEST_F(UniqueProtoDatabaseTest, TestDBGetSuccess) {
base::FilePath path(FILE_PATH_LITERAL("/fake/path")); base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
MockDB* mock_db = new MockDB(); auto mock_db = std::make_unique<MockDB>();
MockDatabaseCaller caller; MockDatabaseCaller caller;
EntryMap model = GetSmallModel(); EntryMap model = GetSmallModel();
EXPECT_CALL(*mock_db, Init(_, options_)); EXPECT_CALL(*mock_db, Init(_, options_));
EXPECT_CALL(caller, InitCallback(_)); EXPECT_CALL(caller, InitCallback(_));
db_->InitWithDatabase(base::WrapUnique(mock_db), path, CreateSimpleOptions(), db_->InitWithDatabase(mock_db.get(), path, CreateSimpleOptions(),
base::BindOnce(&MockDatabaseCaller::InitCallback, base::BindOnce(&MockDatabaseCaller::InitCallback,
base::Unretained(&caller))); base::Unretained(&caller)));
...@@ -392,7 +392,7 @@ TEST_F(ProtoDatabaseImplTest, TestDBGetSuccess) { ...@@ -392,7 +392,7 @@ TEST_F(ProtoDatabaseImplTest, TestDBGetSuccess) {
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
class ProtoDatabaseImplLevelDBTest : public testing::Test { class UniqueProtoDatabaseLevelDBTest : public testing::Test {
public: public:
void SetUp() override { main_loop_.reset(new MessageLoop()); } void SetUp() override { main_loop_.reset(new MessageLoop()); }
...@@ -405,24 +405,24 @@ class ProtoDatabaseImplLevelDBTest : public testing::Test { ...@@ -405,24 +405,24 @@ class ProtoDatabaseImplLevelDBTest : public testing::Test {
std::unique_ptr<MessageLoop> main_loop_; std::unique_ptr<MessageLoop> main_loop_;
}; };
TEST_F(ProtoDatabaseImplLevelDBTest, TestDBSaveAndLoadKeys) { TEST_F(UniqueProtoDatabaseLevelDBTest, TestDBSaveAndLoadKeys) {
ScopedTempDir temp_dir; ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::Thread db_thread("dbthread"); base::Thread db_thread("dbthread");
ASSERT_TRUE(db_thread.Start()); ASSERT_TRUE(db_thread.Start());
std::unique_ptr<ProtoDatabaseImpl<TestProto>> db( std::unique_ptr<UniqueProtoDatabase<TestProto>> db(
new ProtoDatabaseImpl<TestProto>(db_thread.task_runner())); new UniqueProtoDatabase<TestProto>(db_thread.task_runner()));
auto expect_init_success = auto expect_init_success =
base::Bind([](bool success) { EXPECT_TRUE(success); }); base::BindOnce([](bool success) { EXPECT_TRUE(success); });
db->Init(kTestLevelDBClientName, temp_dir.GetPath(), CreateSimpleOptions(), db->Init(kTestLevelDBClientName, temp_dir.GetPath(), CreateSimpleOptions(),
expect_init_success); std::move(expect_init_success));
base::RunLoop run_update_entries; base::RunLoop run_update_entries;
auto expect_update_success = base::Bind( auto expect_update_success = base::BindOnce(
[](base::Closure signal, bool success) { [](base::OnceClosure signal, bool success) {
EXPECT_TRUE(success); EXPECT_TRUE(success);
signal.Run(); std::move(signal).Run();
}, },
run_update_entries.QuitClosure()); run_update_entries.QuitClosure());
TestProto test_proto; TestProto test_proto;
...@@ -431,19 +431,20 @@ TEST_F(ProtoDatabaseImplLevelDBTest, TestDBSaveAndLoadKeys) { ...@@ -431,19 +431,20 @@ TEST_F(ProtoDatabaseImplLevelDBTest, TestDBSaveAndLoadKeys) {
{{"0", test_proto}, {"1", test_proto}, {"2", test_proto}}); {{"0", test_proto}, {"1", test_proto}, {"2", test_proto}});
db->UpdateEntries( db->UpdateEntries(
std::make_unique<ProtoDatabase<TestProto>::KeyEntryVector>(data_set), std::make_unique<ProtoDatabase<TestProto>::KeyEntryVector>(data_set),
std::make_unique<std::vector<std::string>>(), expect_update_success); std::make_unique<std::vector<std::string>>(),
std::move(expect_update_success));
run_update_entries.Run(); run_update_entries.Run();
base::RunLoop run_load_keys; base::RunLoop run_load_keys;
auto verify_loaded_keys = base::Bind( auto verify_loaded_keys = base::BindOnce(
[](base::Closure signal, bool success, [](base::OnceClosure signal, bool success,
std::unique_ptr<std::vector<std::string>> keys) { std::unique_ptr<std::vector<std::string>> keys) {
EXPECT_TRUE(success); EXPECT_TRUE(success);
EXPECT_THAT(*keys, UnorderedElementsAre("0", "1", "2")); EXPECT_THAT(*keys, UnorderedElementsAre("0", "1", "2"));
signal.Run(); std::move(signal).Run();
}, },
run_load_keys.QuitClosure()); run_load_keys.QuitClosure());
db->LoadKeys(verify_loaded_keys); db->LoadKeys(std::move(verify_loaded_keys));
run_load_keys.Run(); run_load_keys.Run();
// Shutdown database. // Shutdown database.
...@@ -454,16 +455,16 @@ TEST_F(ProtoDatabaseImplLevelDBTest, TestDBSaveAndLoadKeys) { ...@@ -454,16 +455,16 @@ TEST_F(ProtoDatabaseImplLevelDBTest, TestDBSaveAndLoadKeys) {
run_destruction.Run(); run_destruction.Run();
} }
TEST_F(ProtoDatabaseImplTest, TestDBGetNotFound) { TEST_F(UniqueProtoDatabaseTest, TestDBGetNotFound) {
base::FilePath path(FILE_PATH_LITERAL("/fake/path")); base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
MockDB* mock_db = new MockDB(); auto mock_db = std::make_unique<MockDB>();
MockDatabaseCaller caller; MockDatabaseCaller caller;
EntryMap model = GetSmallModel(); EntryMap model = GetSmallModel();
EXPECT_CALL(*mock_db, Init(_, options_)); EXPECT_CALL(*mock_db, Init(_, options_));
EXPECT_CALL(caller, InitCallback(_)); EXPECT_CALL(caller, InitCallback(_));
db_->InitWithDatabase(base::WrapUnique(mock_db), path, CreateSimpleOptions(), db_->InitWithDatabase(mock_db.get(), path, CreateSimpleOptions(),
base::BindOnce(&MockDatabaseCaller::InitCallback, base::BindOnce(&MockDatabaseCaller::InitCallback,
base::Unretained(&caller))); base::Unretained(&caller)));
...@@ -477,16 +478,16 @@ TEST_F(ProtoDatabaseImplTest, TestDBGetNotFound) { ...@@ -477,16 +478,16 @@ TEST_F(ProtoDatabaseImplTest, TestDBGetNotFound) {
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
TEST_F(ProtoDatabaseImplTest, TestDBGetFailure) { TEST_F(UniqueProtoDatabaseTest, TestDBGetFailure) {
base::FilePath path(FILE_PATH_LITERAL("/fake/path")); base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
MockDB* mock_db = new MockDB(); auto mock_db = std::make_unique<MockDB>();
MockDatabaseCaller caller; MockDatabaseCaller caller;
EntryMap model = GetSmallModel(); EntryMap model = GetSmallModel();
EXPECT_CALL(*mock_db, Init(_, options_)); EXPECT_CALL(*mock_db, Init(_, options_));
EXPECT_CALL(caller, InitCallback(_)); EXPECT_CALL(caller, InitCallback(_));
db_->InitWithDatabase(base::WrapUnique(mock_db), path, CreateSimpleOptions(), db_->InitWithDatabase(mock_db.get(), path, CreateSimpleOptions(),
base::BindOnce(&MockDatabaseCaller::InitCallback, base::BindOnce(&MockDatabaseCaller::InitCallback,
base::Unretained(&caller))); base::Unretained(&caller)));
...@@ -519,19 +520,19 @@ ACTION_P(VerifyUpdateEntries, expected) { ...@@ -519,19 +520,19 @@ ACTION_P(VerifyUpdateEntries, expected) {
return true; return true;
} }
// Test that ProtoDatabaseImpl calls Save on the underlying database with the // Test that UniqueProtoDatabase calls Save on the underlying database with the
// correct entries to save and that the caller's SaveCallback is called with the // correct entries to save and that the caller's SaveCallback is called with the
// correct success value. // correct success value.
TEST_F(ProtoDatabaseImplTest, TestDBSaveSuccess) { TEST_F(UniqueProtoDatabaseTest, TestDBSaveSuccess) {
base::FilePath path(FILE_PATH_LITERAL("/fake/path")); base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
MockDB* mock_db = new MockDB(); auto mock_db = std::make_unique<MockDB>();
MockDatabaseCaller caller; MockDatabaseCaller caller;
EntryMap model = GetSmallModel(); EntryMap model = GetSmallModel();
EXPECT_CALL(*mock_db, Init(_, options_)); EXPECT_CALL(*mock_db, Init(_, options_));
EXPECT_CALL(caller, InitCallback(_)); EXPECT_CALL(caller, InitCallback(_));
db_->InitWithDatabase(base::WrapUnique(mock_db), path, CreateSimpleOptions(), db_->InitWithDatabase(mock_db.get(), path, CreateSimpleOptions(),
base::BindOnce(&MockDatabaseCaller::InitCallback, base::BindOnce(&MockDatabaseCaller::InitCallback,
base::Unretained(&caller))); base::Unretained(&caller)));
...@@ -551,10 +552,10 @@ TEST_F(ProtoDatabaseImplTest, TestDBSaveSuccess) { ...@@ -551,10 +552,10 @@ TEST_F(ProtoDatabaseImplTest, TestDBSaveSuccess) {
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
TEST_F(ProtoDatabaseImplTest, TestDBSaveFailure) { TEST_F(UniqueProtoDatabaseTest, TestDBSaveFailure) {
base::FilePath path(FILE_PATH_LITERAL("/fake/path")); base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
MockDB* mock_db = new MockDB(); auto mock_db = std::make_unique<MockDB>();
MockDatabaseCaller caller; MockDatabaseCaller caller;
std::unique_ptr<ProtoDatabase<TestProto>::KeyEntryVector> entries( std::unique_ptr<ProtoDatabase<TestProto>::KeyEntryVector> entries(
new ProtoDatabase<TestProto>::KeyEntryVector()); new ProtoDatabase<TestProto>::KeyEntryVector());
...@@ -562,7 +563,7 @@ TEST_F(ProtoDatabaseImplTest, TestDBSaveFailure) { ...@@ -562,7 +563,7 @@ TEST_F(ProtoDatabaseImplTest, TestDBSaveFailure) {
EXPECT_CALL(*mock_db, Init(_, options_)); EXPECT_CALL(*mock_db, Init(_, options_));
EXPECT_CALL(caller, InitCallback(_)); EXPECT_CALL(caller, InitCallback(_));
db_->InitWithDatabase(base::WrapUnique(mock_db), path, CreateSimpleOptions(), db_->InitWithDatabase(mock_db.get(), path, CreateSimpleOptions(),
base::BindOnce(&MockDatabaseCaller::InitCallback, base::BindOnce(&MockDatabaseCaller::InitCallback,
base::Unretained(&caller))); base::Unretained(&caller)));
...@@ -575,19 +576,19 @@ TEST_F(ProtoDatabaseImplTest, TestDBSaveFailure) { ...@@ -575,19 +576,19 @@ TEST_F(ProtoDatabaseImplTest, TestDBSaveFailure) {
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
// Test that ProtoDatabaseImpl calls Save on the underlying database with the // Test that UniqueProtoDatabase calls Save on the underlying database with the
// correct entries to delete and that the caller's SaveCallback is called with // correct entries to delete and that the caller's SaveCallback is called with
// the correct success value. // the correct success value.
TEST_F(ProtoDatabaseImplTest, TestDBRemoveSuccess) { TEST_F(UniqueProtoDatabaseTest, TestDBRemoveSuccess) {
base::FilePath path(FILE_PATH_LITERAL("/fake/path")); base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
MockDB* mock_db = new MockDB(); auto mock_db = std::make_unique<MockDB>();
MockDatabaseCaller caller; MockDatabaseCaller caller;
EntryMap model = GetSmallModel(); EntryMap model = GetSmallModel();
EXPECT_CALL(*mock_db, Init(_, options_)); EXPECT_CALL(*mock_db, Init(_, options_));
EXPECT_CALL(caller, InitCallback(_)); EXPECT_CALL(caller, InitCallback(_));
db_->InitWithDatabase(base::WrapUnique(mock_db), path, CreateSimpleOptions(), db_->InitWithDatabase(mock_db.get(), path, CreateSimpleOptions(),
base::BindOnce(&MockDatabaseCaller::InitCallback, base::BindOnce(&MockDatabaseCaller::InitCallback,
base::Unretained(&caller))); base::Unretained(&caller)));
...@@ -607,10 +608,10 @@ TEST_F(ProtoDatabaseImplTest, TestDBRemoveSuccess) { ...@@ -607,10 +608,10 @@ TEST_F(ProtoDatabaseImplTest, TestDBRemoveSuccess) {
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
TEST_F(ProtoDatabaseImplTest, TestDBRemoveFailure) { TEST_F(UniqueProtoDatabaseTest, TestDBRemoveFailure) {
base::FilePath path(FILE_PATH_LITERAL("/fake/path")); base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
MockDB* mock_db = new MockDB(); auto mock_db = std::make_unique<MockDB>();
MockDatabaseCaller caller; MockDatabaseCaller caller;
std::unique_ptr<ProtoDatabase<TestProto>::KeyEntryVector> entries( std::unique_ptr<ProtoDatabase<TestProto>::KeyEntryVector> entries(
new ProtoDatabase<TestProto>::KeyEntryVector()); new ProtoDatabase<TestProto>::KeyEntryVector());
...@@ -618,7 +619,7 @@ TEST_F(ProtoDatabaseImplTest, TestDBRemoveFailure) { ...@@ -618,7 +619,7 @@ TEST_F(ProtoDatabaseImplTest, TestDBRemoveFailure) {
EXPECT_CALL(*mock_db, Init(_, options_)); EXPECT_CALL(*mock_db, Init(_, options_));
EXPECT_CALL(caller, InitCallback(_)); EXPECT_CALL(caller, InitCallback(_));
db_->InitWithDatabase(base::WrapUnique(mock_db), path, CreateSimpleOptions(), db_->InitWithDatabase(mock_db.get(), path, CreateSimpleOptions(),
base::BindOnce(&MockDatabaseCaller::InitCallback, base::BindOnce(&MockDatabaseCaller::InitCallback,
base::Unretained(&caller))); base::Unretained(&caller)));
...@@ -633,7 +634,7 @@ TEST_F(ProtoDatabaseImplTest, TestDBRemoveFailure) { ...@@ -633,7 +634,7 @@ TEST_F(ProtoDatabaseImplTest, TestDBRemoveFailure) {
// This tests that normal usage of the real database does not cause any // This tests that normal usage of the real database does not cause any
// threading violations. // threading violations.
TEST(ProtoDatabaseImplThreadingTest, TestDBDestruction) { TEST(UniqueProtoDatabaseThreadingTest, TestDBDestruction) {
base::MessageLoop main_loop; base::MessageLoop main_loop;
ScopedTempDir temp_dir; ScopedTempDir temp_dir;
...@@ -642,8 +643,8 @@ TEST(ProtoDatabaseImplThreadingTest, TestDBDestruction) { ...@@ -642,8 +643,8 @@ TEST(ProtoDatabaseImplThreadingTest, TestDBDestruction) {
base::Thread db_thread("dbthread"); base::Thread db_thread("dbthread");
ASSERT_TRUE(db_thread.Start()); ASSERT_TRUE(db_thread.Start());
std::unique_ptr<ProtoDatabaseImpl<TestProto>> db( std::unique_ptr<UniqueProtoDatabase<TestProto>> db(
new ProtoDatabaseImpl<TestProto>(db_thread.task_runner())); new UniqueProtoDatabase<TestProto>(db_thread.task_runner()));
MockDatabaseCaller caller; MockDatabaseCaller caller;
EXPECT_CALL(caller, InitCallback(_)); EXPECT_CALL(caller, InitCallback(_));
...@@ -661,7 +662,7 @@ TEST(ProtoDatabaseImplThreadingTest, TestDBDestruction) { ...@@ -661,7 +662,7 @@ TEST(ProtoDatabaseImplThreadingTest, TestDBDestruction) {
// This tests that normal usage of the real database does not cause any // This tests that normal usage of the real database does not cause any
// threading violations. // threading violations.
TEST(ProtoDatabaseImplThreadingTest, TestDBDestroy) { TEST(UniqueProtoDatabaseThreadingTest, TestDBDestroy) {
base::MessageLoop main_loop; base::MessageLoop main_loop;
ScopedTempDir temp_dir; ScopedTempDir temp_dir;
...@@ -670,8 +671,8 @@ TEST(ProtoDatabaseImplThreadingTest, TestDBDestroy) { ...@@ -670,8 +671,8 @@ TEST(ProtoDatabaseImplThreadingTest, TestDBDestroy) {
base::Thread db_thread("dbthread"); base::Thread db_thread("dbthread");
ASSERT_TRUE(db_thread.Start()); ASSERT_TRUE(db_thread.Start());
std::unique_ptr<ProtoDatabaseImpl<TestProto>> db( std::unique_ptr<UniqueProtoDatabase<TestProto>> db(
new ProtoDatabaseImpl<TestProto>(db_thread.task_runner())); new UniqueProtoDatabase<TestProto>(db_thread.task_runner()));
MockDatabaseCaller caller; MockDatabaseCaller caller;
EXPECT_CALL(caller, InitCallback(_)); EXPECT_CALL(caller, InitCallback(_));
...@@ -734,15 +735,15 @@ void TestLevelDBSaveAndLoad(bool close_after_save) { ...@@ -734,15 +735,15 @@ void TestLevelDBSaveAndLoad(bool close_after_save) {
ExpectEntryPointersEquals(model, loaded_protos); ExpectEntryPointersEquals(model, loaded_protos);
} }
TEST_F(ProtoDatabaseImplLevelDBTest, TestDBSaveAndLoad) { TEST_F(UniqueProtoDatabaseLevelDBTest, TestDBSaveAndLoad) {
TestLevelDBSaveAndLoad(false); TestLevelDBSaveAndLoad(false);
} }
TEST_F(ProtoDatabaseImplLevelDBTest, TestDBCloseAndReopen) { TEST_F(UniqueProtoDatabaseLevelDBTest, TestDBCloseAndReopen) {
TestLevelDBSaveAndLoad(true); TestLevelDBSaveAndLoad(true);
} }
TEST_F(ProtoDatabaseImplLevelDBTest, TestDBLoadWithFilter) { TEST_F(UniqueProtoDatabaseLevelDBTest, TestDBLoadWithFilter) {
ScopedTempDir temp_dir; ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
...@@ -770,7 +771,7 @@ TEST_F(ProtoDatabaseImplLevelDBTest, TestDBLoadWithFilter) { ...@@ -770,7 +771,7 @@ TEST_F(ProtoDatabaseImplLevelDBTest, TestDBLoadWithFilter) {
EXPECT_EQ(entry.SerializeAsString(), model["0"].SerializeAsString()); EXPECT_EQ(entry.SerializeAsString(), model["0"].SerializeAsString());
} }
TEST_F(ProtoDatabaseImplLevelDBTest, TestDBLoadKeysAndEntries) { TEST_F(UniqueProtoDatabaseLevelDBTest, TestDBLoadKeysAndEntries) {
ScopedTempDir temp_dir; ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
...@@ -799,7 +800,7 @@ TEST_F(ProtoDatabaseImplLevelDBTest, TestDBLoadKeysAndEntries) { ...@@ -799,7 +800,7 @@ TEST_F(ProtoDatabaseImplLevelDBTest, TestDBLoadKeysAndEntries) {
} }
} }
TEST_F(ProtoDatabaseImplLevelDBTest, TestDBInitFail) { TEST_F(UniqueProtoDatabaseLevelDBTest, TestDBInitFail) {
ScopedTempDir temp_dir; ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
...@@ -816,7 +817,7 @@ TEST_F(ProtoDatabaseImplLevelDBTest, TestDBInitFail) { ...@@ -816,7 +817,7 @@ TEST_F(ProtoDatabaseImplLevelDBTest, TestDBInitFail) {
EXPECT_FALSE(db->Save(save_entries, remove_keys)); EXPECT_FALSE(db->Save(save_entries, remove_keys));
} }
TEST_F(ProtoDatabaseImplLevelDBTest, TestMemoryDatabase) { TEST_F(UniqueProtoDatabaseLevelDBTest, TestMemoryDatabase) {
std::unique_ptr<LevelDB> db(new LevelDB(kTestLevelDBClientName)); std::unique_ptr<LevelDB> db(new LevelDB(kTestLevelDBClientName));
std::vector<std::string> load_entries; std::vector<std::string> load_entries;
...@@ -837,7 +838,7 @@ TEST_F(ProtoDatabaseImplLevelDBTest, TestMemoryDatabase) { ...@@ -837,7 +838,7 @@ TEST_F(ProtoDatabaseImplLevelDBTest, TestMemoryDatabase) {
EXPECT_EQ(1u, second_load_entries.size()); EXPECT_EQ(1u, second_load_entries.size());
} }
TEST_F(ProtoDatabaseImplLevelDBTest, TestCorruptDBReset) { TEST_F(UniqueProtoDatabaseLevelDBTest, TestCorruptDBReset) {
ScopedTempDir temp_dir; ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
...@@ -867,7 +868,7 @@ TEST_F(ProtoDatabaseImplLevelDBTest, TestCorruptDBReset) { ...@@ -867,7 +868,7 @@ TEST_F(ProtoDatabaseImplLevelDBTest, TestCorruptDBReset) {
ASSERT_FALSE(found); ASSERT_FALSE(found);
} }
TEST_F(ProtoDatabaseImplLevelDBTest, TestDBDeleteWithFilter) { TEST_F(UniqueProtoDatabaseLevelDBTest, TestDBDeleteWithFilter) {
ScopedTempDir temp_dir; ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment