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

Add a ProtoDatabaseProvider as a keyed service.

Adds a ProtoDatabaseProvider(Factory) to provide ProtoDatabases with
the user directory, with ProtoDatabaseProvider as a
BrowserContextKeyedService.

Since ProtoDatabase is just an interface, and the underlying
implementation of it can vary from client to client, a
ProtoDatabaseWrapper that contains a pointer to a ProtoDatabase is
created, also built off ProtoDatabase.

Modifies the Feature Engagement Tracker to use the new provider for
its two databases.

Bug: 870813
Change-Id: I26376a14e8280605b7e3431862e5fe3ad6b9c8db
Reviewed-on: https://chromium-review.googlesource.com/c/1318053Reviewed-by: default avatarJochen Eisinger <jochen@chromium.org>
Reviewed-by: default avataredchin <edchin@chromium.org>
Reviewed-by: default avatarRohit Rao <rohitrao@chromium.org>
Reviewed-by: default avatarTommy Nyquist <nyquist@chromium.org>
Commit-Queue: Troy Hildebrandt <thildebr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#611878}
parent c4740eae
......@@ -1794,6 +1794,7 @@ jumbo_split_static_library("browser") {
"//components/keyed_service/content",
"//components/language/content/browser",
"//components/language/core/browser",
"//components/leveldb_proto/content:factory",
"//components/live_tab_count_metrics",
"//components/metrics:call_stack_profile_collector",
"//components/metrics:component_metrics",
......
......@@ -14,6 +14,7 @@
#include "chrome/common/chrome_constants.h"
#include "components/feature_engagement/public/tracker.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/leveldb_proto/content/proto_database_provider_factory.h"
#include "content/public/browser/browser_context.h"
namespace feature_engagement {
......@@ -33,7 +34,9 @@ feature_engagement::Tracker* TrackerFactory::GetForBrowserContext(
TrackerFactory::TrackerFactory()
: BrowserContextKeyedServiceFactory(
"feature_engagement::Tracker",
BrowserContextDependencyManager::GetInstance()) {}
BrowserContextDependencyManager::GetInstance()) {
DependsOn(leveldb_proto::ProtoDatabaseProviderFactory::GetInstance());
}
TrackerFactory::~TrackerFactory() = default;
......@@ -48,8 +51,11 @@ KeyedService* TrackerFactory::BuildServiceInstanceFor(
base::FilePath storage_dir = profile->GetPath().Append(
chrome::kFeatureEngagementTrackerStorageDirname);
return feature_engagement::Tracker::Create(storage_dir,
background_task_runner);
leveldb_proto::ProtoDatabaseProvider* db_provider =
leveldb_proto::ProtoDatabaseProviderFactory::GetInstance()
->GetForBrowserContext(context);
return feature_engagement::Tracker::Create(
storage_dir, background_task_runner, db_provider);
}
content::BrowserContext* TrackerFactory::GetBrowserContextToUse(
......
......@@ -146,8 +146,7 @@ void PersistentAvailabilityStore::LoadAndUpdateStore(
PersistentAvailabilityStore::OnLoadedCallback on_loaded_callback,
uint32_t current_day) {
auto* db_ptr = db.get();
db_ptr->Init(kDatabaseUMAName, storage_dir,
leveldb_proto::CreateSimpleOptions(),
db_ptr->Init(kDatabaseUMAName,
base::BindOnce(&OnDBInitComplete, std::move(db),
std::move(feature_filter),
std::move(on_loaded_callback), current_day));
......
......@@ -94,17 +94,6 @@ class PersistentAvailabilityStoreTest : public testing::Test {
} // namespace
TEST_F(PersistentAvailabilityStoreTest, StorageDirectory) {
PersistentAvailabilityStore::LoadAndUpdateStore(
storage_dir_, CreateDB(), FeatureVector(), std::move(load_callback_),
14u);
db_->InitCallback(true);
EXPECT_EQ(storage_dir_, db_->GetDirectory());
// Finish the pipeline to ensure the test does not leak anything.
db_->LoadCallback(false);
}
TEST_F(PersistentAvailabilityStoreTest, InitFail) {
PersistentAvailabilityStore::LoadAndUpdateStore(
storage_dir_, CreateDB(), FeatureVector(), std::move(load_callback_),
......
......@@ -25,19 +25,15 @@ void NoopUpdateCallback(bool success) {
} // namespace
PersistentEventStore::PersistentEventStore(
const base::FilePath& storage_dir,
std::unique_ptr<leveldb_proto::ProtoDatabase<Event>> db)
: storage_dir_(storage_dir),
db_(std::move(db)),
ready_(false),
weak_ptr_factory_(this) {}
: db_(std::move(db)), ready_(false), weak_ptr_factory_(this) {}
PersistentEventStore::~PersistentEventStore() = default;
void PersistentEventStore::Load(const OnLoadedCallback& callback) {
DCHECK(!ready_);
db_->Init(kDBUMAName, storage_dir_, leveldb_proto::CreateSimpleOptions(),
db_->Init(kDBUMAName,
base::BindOnce(&PersistentEventStore::OnInitComplete,
weak_ptr_factory_.GetWeakPtr(), callback));
}
......@@ -48,6 +44,7 @@ bool PersistentEventStore::IsReady() const {
void PersistentEventStore::WriteEvent(const Event& event) {
DCHECK(IsReady());
std::unique_ptr<KeyEventList> entries = std::make_unique<KeyEventList>();
entries->push_back(KeyEventPair(event.name(), event));
......
......@@ -23,10 +23,8 @@ namespace feature_engagement {
// to always save every write during shutdown.
class PersistentEventStore : public EventStore {
public:
// Builds a PersistentEventStore backed by the ProtoDatabase |db|. The
// database will be loaded and/or created at |storage_dir|.
PersistentEventStore(const base::FilePath& storage_dir,
std::unique_ptr<leveldb_proto::ProtoDatabase<Event>> db);
// Builds a PersistentEventStore backed by the ProtoDatabase |db|.
PersistentEventStore(std::unique_ptr<leveldb_proto::ProtoDatabase<Event>> db);
~PersistentEventStore() override;
// EventStore implementation.
......
......@@ -33,9 +33,7 @@ void VerifyEventsInListAndMap(const std::map<std::string, Event>& map,
class PersistentEventStoreTest : public ::testing::Test {
public:
PersistentEventStoreTest()
: db_(nullptr),
storage_dir_(FILE_PATH_LITERAL("/persistent/store/lalala")) {
PersistentEventStoreTest() : db_(nullptr) {
load_callback_ = base::Bind(&PersistentEventStoreTest::LoadCallback,
base::Unretained(this));
}
......@@ -53,7 +51,7 @@ class PersistentEventStoreTest : public ::testing::Test {
auto db = std::make_unique<leveldb_proto::test::FakeDB<Event>>(&db_events_);
db_ = db.get();
store_.reset(new PersistentEventStore(storage_dir_, std::move(db)));
store_.reset(new PersistentEventStore(std::move(db)));
}
void LoadCallback(bool success, std::unique_ptr<std::vector<Event>> events) {
......@@ -69,19 +67,10 @@ class PersistentEventStoreTest : public ::testing::Test {
std::map<std::string, Event> db_events_;
leveldb_proto::test::FakeDB<Event>* db_;
std::unique_ptr<EventStore> store_;
// Constant test data.
base::FilePath storage_dir_;
};
} // namespace
TEST_F(PersistentEventStoreTest, StorageDirectory) {
SetUpDB();
store_->Load(load_callback_);
EXPECT_EQ(storage_dir_, db_->GetDirectory());
}
TEST_F(PersistentEventStoreTest, SuccessfulInitAndLoadEmptyStore) {
SetUpDB();
......
......@@ -34,6 +34,7 @@
#include "components/feature_engagement/public/feature_constants.h"
#include "components/feature_engagement/public/feature_list.h"
#include "components/leveldb_proto/proto_database_impl.h"
#include "components/leveldb_proto/proto_database_provider.h"
namespace feature_engagement {
......@@ -91,18 +92,18 @@ std::unique_ptr<Tracker> CreateDemoModeTracker() {
// static
Tracker* Tracker::Create(
const base::FilePath& storage_dir,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner) {
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
leveldb_proto::ProtoDatabaseProvider* db_provider) {
DVLOG(2) << "Creating Tracker";
if (base::FeatureList::IsEnabled(kIPHDemoMode))
return CreateDemoModeTracker().release();
std::unique_ptr<leveldb_proto::ProtoDatabase<Event>> event_db =
std::make_unique<leveldb_proto::ProtoDatabaseImpl<Event>>(
background_task_runner);
base::FilePath event_storage_dir = storage_dir.Append(kEventDBStorageDir);
auto event_store = std::make_unique<PersistentEventStore>(
event_storage_dir, std::move(event_db));
auto event_db =
db_provider->GetDB<Event>(event_storage_dir, background_task_runner);
auto event_store =
std::make_unique<PersistentEventStore>(std::move(event_db));
auto configuration = std::make_unique<ChromeVariationsConfiguration>();
configuration->ParseFeatureConfigs(GetAllFeatures());
......@@ -122,9 +123,8 @@ Tracker* Tracker::Create(
base::FilePath availability_storage_dir =
storage_dir.Append(kAvailabilityDBStorageDir);
auto availability_db =
std::make_unique<leveldb_proto::ProtoDatabaseImpl<Availability>>(
background_task_runner);
auto availability_db = db_provider->GetDB<Availability>(
availability_storage_dir, background_task_runner);
auto availability_store_loader = base::BindOnce(
&PersistentAvailabilityStore::LoadAndUpdateStore,
availability_storage_dir, std::move(availability_db), GetAllFeatures());
......
......@@ -22,6 +22,10 @@
#include "base/android/jni_android.h"
#endif // defined(OS_ANDROID)
namespace leveldb_proto {
class ProtoDatabaseProvider;
}
namespace feature_engagement {
// A handle for the display lock. While this is unreleased, no in-product help
......@@ -71,7 +75,8 @@ class Tracker : public KeyedService {
// The |bakground_task_runner| will be used for all disk reads and writes.
static Tracker* Create(
const base::FilePath& storage_dir,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner);
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
leveldb_proto::ProtoDatabaseProvider* db_provider);
// Must be called whenever an event happens.
virtual void NotifyEvent(const std::string& event) = 0;
......
......@@ -9,6 +9,9 @@ static_library("leveldb_proto") {
"proto_database.cc",
"proto_database.h",
"proto_database_impl.h",
"proto_database_provider.cc",
"proto_database_provider.h",
"proto_database_wrapper.h",
"proto_leveldb_wrapper.cc",
"proto_leveldb_wrapper.h",
"proto_leveldb_wrapper_metrics.cc",
......@@ -18,6 +21,7 @@ static_library("leveldb_proto") {
public_deps = [
"//base",
"//components/keyed_service/core",
"//third_party/leveldatabase",
]
}
......
include_rules = [
"+components/keyed_service/core",
"+third_party/leveldatabase",
]
# 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.
source_set("factory") {
sources = [
"proto_database_provider_factory.cc",
"proto_database_provider_factory.h",
]
public_deps = [
"//base",
"//components/keyed_service/content",
]
deps = [
"//content/public/browser",
]
}
include_rules = [
"+components/keyed_service/content",
"+content/public/browser",
]
\ 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.
#include "components/leveldb_proto/content/proto_database_provider_factory.h"
#include "base/files/file_path.h"
#include "base/memory/singleton.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/leveldb_proto/proto_database_provider.h"
#include "content/public/browser/browser_context.h"
namespace leveldb_proto {
// static
ProtoDatabaseProviderFactory* ProtoDatabaseProviderFactory::GetInstance() {
return base::Singleton<ProtoDatabaseProviderFactory>::get();
}
// static
leveldb_proto::ProtoDatabaseProvider*
ProtoDatabaseProviderFactory::GetForBrowserContext(
content::BrowserContext* context) {
return static_cast<leveldb_proto::ProtoDatabaseProvider*>(
GetInstance()->GetServiceForBrowserContext(context, true));
}
ProtoDatabaseProviderFactory::ProtoDatabaseProviderFactory()
: BrowserContextKeyedServiceFactory(
"leveldb_proto::ProtoDatabaseProvider",
BrowserContextDependencyManager::GetInstance()) {}
ProtoDatabaseProviderFactory::~ProtoDatabaseProviderFactory() = default;
KeyedService* ProtoDatabaseProviderFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
base::FilePath profile_dir = context->GetPath();
return leveldb_proto::ProtoDatabaseProvider::Create(profile_dir);
}
} // namespace leveldb_proto
// 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_CONTENT_PROTO_DATABASE_PROVIDER_FACTORY_H_
#define COMPONENTS_LEVELDB_PROTO_CONTENT_PROTO_DATABASE_PROVIDER_FACTORY_H_
#include "base/macros.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
namespace base {
template <typename T>
struct DefaultSingletonTraits;
} // namespace base
namespace leveldb_proto {
class ProtoDatabaseProvider;
// A factory for ProtoDatabaseProvider, a class that provides proto databases
// stored in the appropriate directory for the current profile.
class ProtoDatabaseProviderFactory : public BrowserContextKeyedServiceFactory {
public:
// Returns singleton instance of ProtoDatabaseProviderFactory.
static ProtoDatabaseProviderFactory* GetInstance();
// Returns ProtoDatabaseProvider associated with |context|, so we can
// instantiate ProtoDatabases that use the appropriate profile directory.
static ProtoDatabaseProvider* GetForBrowserContext(
content::BrowserContext* context);
private:
friend struct base::DefaultSingletonTraits<ProtoDatabaseProviderFactory>;
ProtoDatabaseProviderFactory();
~ProtoDatabaseProviderFactory() override;
// BrowserContextKeyedServiceFactory overrides:
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override;
DISALLOW_COPY_AND_ASSIGN(ProtoDatabaseProviderFactory);
};
} // namespace leveldb_proto
#endif // COMPONENTS_LEVELDB_PROTO_CONTENT_PROTO_DATABASE_PROVIDER_FACTORY_H_
......@@ -138,6 +138,14 @@ bool LevelDB::Save(const base::StringPairs& entries_to_save,
bool LevelDB::UpdateWithRemoveFilter(const base::StringPairs& entries_to_save,
const KeyFilter& delete_key_filter,
leveldb::Status* status) {
return UpdateWithRemoveFilter(entries_to_save, delete_key_filter,
std::string(), status);
}
bool LevelDB::UpdateWithRemoveFilter(const base::StringPairs& entries_to_save,
const KeyFilter& delete_key_filter,
const std::string& target_prefix,
leveldb::Status* status) {
DCHECK(status);
DFAKE_SCOPED_LOCK(thread_checker_);
if (!db_)
......@@ -147,11 +155,13 @@ bool LevelDB::UpdateWithRemoveFilter(const base::StringPairs& entries_to_save,
for (const auto& pair : entries_to_save)
updates.Put(leveldb::Slice(pair.first), leveldb::Slice(pair.second));
leveldb::Slice target(target_prefix);
if (!delete_key_filter.is_null()) {
leveldb::ReadOptions read_options;
std::unique_ptr<leveldb::Iterator> db_iterator(
db_->NewIterator(read_options));
for (db_iterator->SeekToFirst(); db_iterator->Valid();
for (db_iterator->Seek(target);
db_iterator->Valid() && db_iterator->key().starts_with(target);
db_iterator->Next()) {
leveldb::Slice key_slice = db_iterator->key();
std::string key(key_slice.data(), key_slice.size());
......@@ -235,11 +245,16 @@ bool LevelDB::LoadKeysAndEntriesWithFilter(
}
bool LevelDB::LoadKeys(std::vector<std::string>* keys) {
return LoadKeys(std::string(), keys);
}
bool LevelDB::LoadKeys(const std::string& target_prefix,
std::vector<std::string>* keys) {
leveldb::ReadOptions options;
options.fill_cache = false;
std::map<std::string, std::string> keys_entries;
bool result = LoadKeysAndEntriesWithFilter(KeyFilter(), &keys_entries,
options, std::string());
options, target_prefix);
if (!result)
return false;
......
......@@ -51,9 +51,14 @@ class LevelDB {
virtual bool Save(const base::StringPairs& pairs_to_save,
const std::vector<std::string>& keys_to_remove,
leveldb::Status* status);
virtual bool UpdateWithRemoveFilter(const base::StringPairs& entries_to_save,
const KeyFilter& delete_key_filter,
leveldb::Status* status);
virtual bool UpdateWithRemoveFilter(const base::StringPairs& entries_to_save,
const KeyFilter& delete_key_filter,
const std::string& target_prefix,
leveldb::Status* status);
virtual bool Load(std::vector<std::string>* entries);
virtual bool LoadWithFilter(const KeyFilter& filter,
......@@ -75,6 +80,9 @@ class LevelDB {
const std::string& target_prefix);
virtual bool LoadKeys(std::vector<std::string>* keys);
virtual bool LoadKeys(const std::string& target_prefix,
std::vector<std::string>* keys);
virtual bool Get(const std::string& key,
bool* found,
std::string* entry,
......
......@@ -37,29 +37,22 @@ class ProtoDatabase {
// A list of key-value (string, T) tuples.
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() = default;
// Asynchronously initializes the object with the specified |options|.
// |callback| will be invoked on the calling thread when complete.
virtual void Init(const std::string& client_name,
typename ProtoDatabase<T>::InitCallback callback) = 0;
virtual void Init(const std::string& client_name, InitCallback callback) = 0;
// This version of Init is for compatibility, since many of the current
// proto database clients still use this.
virtual void Init(const char* client_name,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
typename ProtoDatabase<T>::InitCallback callback) = 0;
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));
}
InitCallback callback) = 0;
// Asynchronously saves |entries_to_save| and deletes entries from
// |keys_to_remove| from the database. |callback| will be invoked on the
......@@ -67,11 +60,7 @@ class ProtoDatabase {
virtual void UpdateEntries(
std::unique_ptr<KeyEntryVector> entries_to_save,
std::unique_ptr<std::vector<std::string>> keys_to_remove,
UpdateCallback callback) {
db_wrapper_->template UpdateEntries<T>(std::move(entries_to_save),
std::move(keys_to_remove),
std::move(callback));
}
UpdateCallback callback) = 0;
// Asynchronously saves |entries_to_save| and deletes entries that satisfies
// the |delete_key_filter| from the database. |callback| will be invoked on
......@@ -80,76 +69,54 @@ class ProtoDatabase {
virtual void UpdateEntriesWithRemoveFilter(
std::unique_ptr<KeyEntryVector> entries_to_save,
const LevelDB::KeyFilter& delete_key_filter,
UpdateCallback callback) {
db_wrapper_->template UpdateEntriesWithRemoveFilter<T>(
std::move(entries_to_save), delete_key_filter, std::move(callback));
}
UpdateCallback callback) = 0;
virtual void UpdateEntriesWithRemoveFilter(
std::unique_ptr<KeyEntryVector> entries_to_save,
const LevelDB::KeyFilter& delete_key_filter,
const std::string& target_prefix,
UpdateCallback callback) = 0;
// Asynchronously loads all entries from the database and invokes |callback|
// when complete.
virtual void LoadEntries(LoadCallback callback) {
db_wrapper_->template LoadEntries<T>(std::move(callback));
}
virtual void LoadEntries(LoadCallback callback) = 0;
// Asynchronously loads entries that satisfies the |filter| from the database
// and invokes |callback| when complete. The filter will be called on
// ProtoDatabase's taskrunner.
virtual void LoadEntriesWithFilter(const LevelDB::KeyFilter& filter,
LoadCallback callback) {
db_wrapper_->template LoadEntriesWithFilter<T>(filter, std::move(callback));
}
LoadCallback callback) = 0;
virtual void LoadEntriesWithFilter(const LevelDB::KeyFilter& key_filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
LoadCallback callback) {
db_wrapper_->template LoadEntriesWithFilter<T>(
key_filter, options, target_prefix, std::move(callback));
}
LoadCallback callback) = 0;
virtual void LoadKeysAndEntries(LoadKeysAndEntriesCallback callback) {
db_wrapper_->template LoadKeysAndEntries<T>(std::move(callback));
}
virtual void LoadKeysAndEntries(LoadKeysAndEntriesCallback callback) = 0;
virtual void LoadKeysAndEntriesWithFilter(
const LevelDB::KeyFilter& filter,
typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) {
db_wrapper_->template LoadKeysAndEntriesWithFilter<T>(filter,
std::move(callback));
}
LoadKeysAndEntriesCallback callback) = 0;
virtual void LoadKeysAndEntriesWithFilter(
const LevelDB::KeyFilter& filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) {
db_wrapper_->template LoadKeysAndEntriesWithFilter<T>(
filter, options, target_prefix, std::move(callback));
}
LoadKeysAndEntriesCallback callback) = 0;
// Asynchronously loads all keys from the database and invokes |callback| with
// those keys when complete.
virtual void LoadKeys(LoadKeysCallback callback) {
db_wrapper_->LoadKeys(std::move(callback));
}
virtual void LoadKeys(LoadKeysCallback callback) = 0;
virtual void LoadKeys(const std::string& target_prefix,
LoadKeysCallback callback) = 0;
// Asynchronously loads a single entry, identified by |key|, from the database
// 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.
virtual void GetEntry(const std::string& key, GetCallback callback) {
db_wrapper_->template GetEntry<T>(key, std::move(callback));
}
virtual void GetEntry(const std::string& key, GetCallback callback) = 0;
// Asynchronously destroys the database.
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);
}
virtual void Destroy(DestroyCallback callback) = 0;
protected:
std::unique_ptr<ProtoLevelDBWrapper> db_wrapper_;
ProtoDatabase() = default;
};
// Return a new instance of Options, but with two additions:
......
// 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_database_provider.h"
#include "base/files/file_path.h"
namespace leveldb_proto {
ProtoDatabaseProvider::ProtoDatabaseProvider(const base::FilePath& profile_dir)
: profile_dir_(profile_dir) {}
// static
ProtoDatabaseProvider* ProtoDatabaseProvider::Create(
const base::FilePath& profile_dir) {
return new ProtoDatabaseProvider(profile_dir);
}
} // namespace leveldb_proto
// 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_DATABASE_PROVIDER_H_
#define COMPONENTS_LEVELDB_PROTO_PROTO_DATABASE_PROVIDER_H_
#include "base/files/file_path.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/leveldb_proto/proto_database.h"
#include "components/leveldb_proto/proto_database_wrapper.h"
namespace leveldb_proto {
// A KeyedService that provides instances of ProtoDatabase tied to the current
// profile directory.
class ProtoDatabaseProvider : public KeyedService {
public:
static ProtoDatabaseProvider* Create(const base::FilePath& profile_dir);
// |unique_db_dir|: the subdirectory this database should live in within
// the profile directory.
// |task_runner|: the SequencedTaskRunner to run all database operations on.
template <typename T>
std::unique_ptr<ProtoDatabase<T>> GetDB(
const base::FilePath& unique_db_dir,
const scoped_refptr<base::SequencedTaskRunner>& task_runner);
~ProtoDatabaseProvider() override = default;
private:
ProtoDatabaseProvider(const base::FilePath& profile_dir);
base::FilePath profile_dir_;
};
template <typename T>
std::unique_ptr<ProtoDatabase<T>> ProtoDatabaseProvider::GetDB(
const base::FilePath& unique_db_dir,
const scoped_refptr<base::SequencedTaskRunner>& task_runner) {
return std::make_unique<ProtoDatabaseWrapper<T>>(unique_db_dir, task_runner);
}
} // namespace leveldb_proto
#endif // COMPONENTS_LEVELDB_PROTO_PROTO_DATABASE_PROVIDER_H_
\ 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_DATABASE_WRAPPER_H_
#define COMPONENTS_LEVELDB_PROTO_PROTO_DATABASE_WRAPPER_H_
#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "components/leveldb_proto/unique_proto_database.h"
namespace leveldb_proto {
// The ProtoDatabaseWrapper<T> owns a ProtoDatabase<T> instance, and allows the
// underlying ProtoDatabase<T> implementation to change without users of the
// wrapper needing to know.
template <typename T>
class ProtoDatabaseWrapper : public UniqueProtoDatabase<T> {
public:
using InitCallback = base::OnceCallback<void(bool success)>;
ProtoDatabaseWrapper(
const base::FilePath& db_dir,
const scoped_refptr<base::SequencedTaskRunner>& task_runner);
virtual ~ProtoDatabaseWrapper() {}
// This version of Init is for compatibility, since many of the current
// proto database still use this.
void Init(const char* client_name,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
typename ProtoDatabase<T>::InitCallback callback) override;
void Init(const std::string& client_name,
typename ProtoDatabase<T>::InitCallback callback) override;
void InitWithDatabase(
LevelDB* database,
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<std::vector<std::string>> 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 UpdateEntriesWithRemoveFilter(
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector>
entries_to_save,
const LevelDB::KeyFilter& delete_key_filter,
const std::string& target_prefix,
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& key_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 LoadKeys(const std::string& target_prefix,
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;
void RunCallbackOnCallingSequence(base::OnceClosure callback);
private:
void OnInitUniqueDB(std::unique_ptr<ProtoDatabase<T>> db,
InitCallback callback,
bool success);
base::FilePath db_dir_;
std::unique_ptr<ProtoDatabase<T>> db_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
std::unique_ptr<base::WeakPtrFactory<ProtoDatabaseWrapper<T>>>
weak_ptr_factory_;
};
template <typename T>
void ProtoDatabaseWrapper<T>::RunCallbackOnCallingSequence(
base::OnceClosure callback) {
DCHECK(base::SequencedTaskRunnerHandle::IsSet());
base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
std::move(callback));
}
template <typename T>
ProtoDatabaseWrapper<T>::ProtoDatabaseWrapper(
const base::FilePath& db_dir,
const scoped_refptr<base::SequencedTaskRunner>& task_runner)
: UniqueProtoDatabase<T>(task_runner) {
db_dir_ = db_dir;
db_ = nullptr;
task_runner_ = task_runner;
weak_ptr_factory_ =
std::make_unique<base::WeakPtrFactory<ProtoDatabaseWrapper<T>>>(this);
}
template <typename T>
void ProtoDatabaseWrapper<T>::Init(
const char* client_name,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
typename ProtoDatabase<T>::InitCallback callback) {
// We shouldn't be calling this on the wrapper. This function is purely for
// compatibility right now.
NOTREACHED();
}
template <typename T>
void ProtoDatabaseWrapper<T>::OnInitUniqueDB(
std::unique_ptr<ProtoDatabase<T>> db,
InitCallback callback,
bool success) {
if (success)
db_ = std::move(db);
RunCallbackOnCallingSequence(base::BindOnce(std::move(callback), success));
}
template <typename T>
void ProtoDatabaseWrapper<T>::Init(
const std::string& client_name,
typename ProtoDatabase<T>::InitCallback callback) {
auto unique_db = std::make_unique<UniqueProtoDatabase<T>>(
db_dir_, CreateSimpleOptions(), task_runner_);
unique_db->Init(client_name,
base::BindOnce(&ProtoDatabaseWrapper<T>::OnInitUniqueDB,
weak_ptr_factory_->GetWeakPtr(),
std::move(unique_db), std::move(callback)));
}
template <typename T>
void ProtoDatabaseWrapper<T>::InitWithDatabase(
LevelDB* database,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
typename ProtoDatabase<T>::InitCallback callback) {
if (!db_) {
RunCallbackOnCallingSequence(base::BindOnce(std::move(callback), false));
return;
}
db_->InitWithDatabase(database, database_dir, options, std::move(callback));
}
template <typename T>
void ProtoDatabaseWrapper<T>::UpdateEntries(
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save,
std::unique_ptr<std::vector<std::string>> keys_to_remove,
typename ProtoDatabase<T>::UpdateCallback callback) {
if (!db_) {
RunCallbackOnCallingSequence(base::BindOnce(std::move(callback), false));
return;
}
db_->UpdateEntries(std::move(entries_to_save), std::move(keys_to_remove),
std::move(callback));
}
template <typename T>
void ProtoDatabaseWrapper<T>::UpdateEntriesWithRemoveFilter(
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save,
const LevelDB::KeyFilter& delete_key_filter,
typename ProtoDatabase<T>::UpdateCallback callback) {
if (!db_) {
RunCallbackOnCallingSequence(base::BindOnce(std::move(callback), false));
return;
}
db_->UpdateEntriesWithRemoveFilter(std::move(entries_to_save),
delete_key_filter, std::move(callback));
}
template <typename T>
void ProtoDatabaseWrapper<T>::UpdateEntriesWithRemoveFilter(
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save,
const LevelDB::KeyFilter& delete_key_filter,
const std::string& target_prefix,
typename ProtoDatabase<T>::UpdateCallback callback) {
if (!db_) {
RunCallbackOnCallingSequence(base::BindOnce(std::move(callback), false));
return;
}
db_->UpdateEntriesWithRemoveFilter(std::move(entries_to_save),
delete_key_filter, target_prefix,
std::move(callback));
}
template <typename T>
void ProtoDatabaseWrapper<T>::LoadEntries(
typename ProtoDatabase<T>::LoadCallback callback) {
if (!db_) {
RunCallbackOnCallingSequence(base::BindOnce(
std::move(callback), false, std::make_unique<std::vector<T>>()));
return;
}
db_->LoadEntries(std::move(callback));
}
template <typename T>
void ProtoDatabaseWrapper<T>::LoadEntriesWithFilter(
const LevelDB::KeyFilter& filter,
typename ProtoDatabase<T>::LoadCallback callback) {
if (!db_) {
RunCallbackOnCallingSequence(base::BindOnce(
std::move(callback), false, std::make_unique<std::vector<T>>()));
return;
}
db_->LoadEntriesWithFilter(filter, std::move(callback));
}
template <typename T>
void ProtoDatabaseWrapper<T>::LoadEntriesWithFilter(
const LevelDB::KeyFilter& key_filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
typename ProtoDatabase<T>::LoadCallback callback) {
if (!db_) {
RunCallbackOnCallingSequence(base::BindOnce(
std::move(callback), false, std::make_unique<std::vector<T>>()));
return;
}
db_->LoadEntriesWithFilter(key_filter, options, target_prefix,
std::move(callback));
}
template <typename T>
void ProtoDatabaseWrapper<T>::LoadKeysAndEntries(
typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) {
if (!db_) {
RunCallbackOnCallingSequence(
base::BindOnce(std::move(callback), false,
std::make_unique<std::map<std::string, T>>()));
return;
}
db_->LoadKeysAndEntries(std::move(callback));
}
template <typename T>
void ProtoDatabaseWrapper<T>::LoadKeysAndEntriesWithFilter(
const LevelDB::KeyFilter& filter,
typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) {
if (!db_) {
RunCallbackOnCallingSequence(
base::BindOnce(std::move(callback), false,
std::make_unique<std::map<std::string, T>>()));
return;
}
db_->LoadKeysAndEntriesWithFilter(filter, std::move(callback));
}
template <typename T>
void ProtoDatabaseWrapper<T>::LoadKeysAndEntriesWithFilter(
const LevelDB::KeyFilter& filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) {
if (!db_) {
RunCallbackOnCallingSequence(
base::BindOnce(std::move(callback), false,
std::make_unique<std::map<std::string, T>>()));
return;
}
db_->LoadKeysAndEntriesWithFilter(filter, options, target_prefix,
std::move(callback));
}
template <typename T>
void ProtoDatabaseWrapper<T>::LoadKeys(
typename ProtoDatabase<T>::LoadKeysCallback callback) {
if (!db_) {
RunCallbackOnCallingSequence(
base::BindOnce(std::move(callback), false,
std::make_unique<std::vector<std::string>>()));
return;
}
db_->LoadKeys(std::move(callback));
}
template <typename T>
void ProtoDatabaseWrapper<T>::LoadKeys(
const std::string& target_prefix,
typename ProtoDatabase<T>::LoadKeysCallback callback) {
if (!db_) {
RunCallbackOnCallingSequence(
base::BindOnce(std::move(callback), false,
std::make_unique<std::vector<std::string>>()));
return;
}
db_->LoadKeys(target_prefix, std::move(callback));
}
template <typename T>
void ProtoDatabaseWrapper<T>::GetEntry(
const std::string& key,
typename ProtoDatabase<T>::GetCallback callback) {
if (!db_) {
RunCallbackOnCallingSequence(
base::BindOnce(std::move(callback), false, std::make_unique<T>()));
return;
}
db_->GetEntry(key, std::move(callback));
}
template <typename T>
void ProtoDatabaseWrapper<T>::Destroy(
typename ProtoDatabase<T>::DestroyCallback callback) {
if (!db_) {
RunCallbackOnCallingSequence(base::BindOnce(std::move(callback), false));
return;
}
db_->Destroy(std::move(callback));
}
} // namespace leveldb_proto
#endif // COMPONENTS_LEVELDB_PROTO_PROTO_DATABASE_WRAPPER_H_
\ No newline at end of file
......@@ -51,6 +51,7 @@ void RunLoadKeysCallback(
}
inline void LoadKeysFromTaskRunner(LevelDB* database,
const std::string& target_prefix,
std::vector<std::string>* keys,
bool* success,
const std::string& client_id) {
......@@ -67,25 +68,28 @@ ProtoLevelDBWrapper::ProtoLevelDBWrapper(
const scoped_refptr<base::SequencedTaskRunner>& task_runner)
: task_runner_(task_runner) {}
ProtoLevelDBWrapper::ProtoLevelDBWrapper(
const scoped_refptr<base::SequencedTaskRunner>& task_runner,
LevelDB* db)
: task_runner_(task_runner), db_(db) {}
ProtoLevelDBWrapper::~ProtoLevelDBWrapper() = default;
void ProtoLevelDBWrapper::InitWithDatabase(
LevelDB* database,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
bool destroy_on_corruption,
typename ProtoLevelDBWrapper::InitCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!db_);
DCHECK(database);
db_ = database;
leveldb::Status* status = new leveldb::Status();
// Sets |destroy_on_corruption| to true to mimic the original behaviour for
// now.
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(InitFromTaskRunner, base::Unretained(db_), database_dir,
options, true /* destroy_on_corruption */, status,
metrics_id_),
options, destroy_on_corruption, status, metrics_id_),
base::BindOnce(RunInitCallback, std::move(callback),
base::Owned(status)));
}
......@@ -106,13 +110,22 @@ void ProtoLevelDBWrapper::Destroy(
void ProtoLevelDBWrapper::LoadKeys(
typename ProtoLevelDBWrapper::LoadKeysCallback callback) {
LoadKeys(std::string(), std::move(callback));
}
void ProtoLevelDBWrapper::LoadKeys(
const std::string& target_prefix,
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(), metrics_id_);
bool* success_ptr = success.get();
std::vector<std::string>* keys_ptr = keys.get();
task_runner_->PostTaskAndReply(
FROM_HERE, std::move(load_task),
FROM_HERE,
base::BindOnce(LoadKeysFromTaskRunner, base::Unretained(db_),
target_prefix, base::Unretained(keys_ptr),
base::Unretained(success_ptr), metrics_id_),
base::BindOnce(RunLoadKeysCallback, std::move(callback),
std::move(success), std::move(keys)));
}
......
......@@ -60,6 +60,10 @@ class ProtoLevelDBWrapper {
ProtoLevelDBWrapper(
const scoped_refptr<base::SequencedTaskRunner>& task_runner);
ProtoLevelDBWrapper(
const scoped_refptr<base::SequencedTaskRunner>& task_runner,
LevelDB* db);
virtual ~ProtoLevelDBWrapper();
template <typename T>
......@@ -76,6 +80,14 @@ class ProtoLevelDBWrapper {
const LevelDB::KeyFilter& delete_key_filter,
UpdateCallback callback);
template <typename T>
void UpdateEntriesWithRemoveFilter(
std::unique_ptr<typename ProtoLevelDBWrapper::Internal<T>::KeyEntryVector>
entries_to_save,
const LevelDB::KeyFilter& delete_key_filter,
const std::string& target_prefix,
UpdateCallback callback);
template <typename T>
void LoadEntries(
typename ProtoLevelDBWrapper::Internal<T>::LoadCallback callback);
......@@ -112,6 +124,7 @@ class ProtoLevelDBWrapper {
callback);
void LoadKeys(LoadKeysCallback callback);
void LoadKeys(const std::string& target_prefix, LoadKeysCallback callback);
template <typename T>
void GetEntry(
......@@ -124,6 +137,7 @@ class ProtoLevelDBWrapper {
void InitWithDatabase(LevelDB* database,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
bool destroy_on_corruption,
InitCallback callback);
void SetMetricsId(const std::string& id);
......@@ -334,6 +348,18 @@ void ProtoLevelDBWrapper::UpdateEntriesWithRemoveFilter(
entries_to_save,
const LevelDB::KeyFilter& delete_key_filter,
typename ProtoLevelDBWrapper::UpdateCallback callback) {
UpdateEntriesWithRemoveFilter<T>(std::move(entries_to_save),
delete_key_filter, std::string(),
std::move(callback));
}
template <typename T>
void ProtoLevelDBWrapper::UpdateEntriesWithRemoveFilter(
std::unique_ptr<typename ProtoLevelDBWrapper::Internal<T>::KeyEntryVector>
entries_to_save,
const LevelDB::KeyFilter& delete_key_filter,
const std::string& target_prefix,
typename ProtoLevelDBWrapper::UpdateCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
bool* success = new bool(false);
task_runner_->PostTaskAndReply(
......
......@@ -29,9 +29,10 @@ class FakeDB : public UniqueProtoDatabase<T> {
using EntryMap = std::map<std::string, T>;
explicit FakeDB(EntryMap* db);
~FakeDB() override;
// ProtoDatabase implementation.
void Init(const std::string& client_name,
typename ProtoDatabase<T>::InitCallback callback) override;
void Init(const char* client_name,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
......@@ -128,7 +129,11 @@ FakeDB<T>::FakeDB(EntryMap* db)
}
template <typename T>
FakeDB<T>::~FakeDB() {}
void FakeDB<T>::Init(const std::string& client_name,
typename ProtoDatabase<T>::InitCallback callback) {
Init(client_name.c_str(), base::FilePath(FILE_PATH_LITERAL("db_dir")),
leveldb_proto::CreateSimpleOptions(), std::move(callback));
}
template <typename T>
void FakeDB<T>::Init(const char* client_name,
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// 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.
......@@ -18,8 +18,10 @@ namespace leveldb_proto {
template <typename T>
class UniqueProtoDatabase : public ProtoDatabase<T> {
public:
UniqueProtoDatabase(
explicit UniqueProtoDatabase(
const scoped_refptr<base::SequencedTaskRunner>& task_runner);
explicit UniqueProtoDatabase(std::unique_ptr<ProtoLevelDBWrapper>);
virtual ~UniqueProtoDatabase();
UniqueProtoDatabase(
const base::FilePath& database_dir,
......@@ -28,37 +30,97 @@ class UniqueProtoDatabase : public ProtoDatabase<T> {
// This version of Init is for compatibility, since many of the current
// proto database still use this.
virtual void Init(const char* client_name,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
typename ProtoDatabase<T>::InitCallback callback) override;
void Init(const char* client_name,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
typename ProtoDatabase<T>::InitCallback callback) override;
virtual void Init(const std::string& client_name,
typename ProtoDatabase<T>::InitCallback callback) override;
void Init(const std::string& client_name,
typename ProtoDatabase<T>::InitCallback callback) override;
virtual ~UniqueProtoDatabase();
void InitWithDatabase(
LevelDB* database,
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<std::vector<std::string>> 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 UpdateEntriesWithRemoveFilter(
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector>
entries_to_save,
const LevelDB::KeyFilter& delete_key_filter,
const std::string& target_prefix,
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& key_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 LoadKeys(const std::string& target_prefix,
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;
bool GetApproximateMemoryUse(uint64_t* approx_mem_use);
private:
THREAD_CHECKER(thread_checker_);
base::FilePath database_dir_;
leveldb_env::Options options_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
std::unique_ptr<ProtoLevelDBWrapper> db_wrapper_;
std::unique_ptr<LevelDB> db_;
};
template <typename T>
UniqueProtoDatabase<T>::UniqueProtoDatabase(
const scoped_refptr<base::SequencedTaskRunner>& task_runner)
: ProtoDatabase<T>(task_runner) {}
: db_wrapper_(std::make_unique<ProtoLevelDBWrapper>(task_runner)) {}
template <typename T>
UniqueProtoDatabase<T>::UniqueProtoDatabase(
std::unique_ptr<ProtoLevelDBWrapper> db_wrapper)
: db_wrapper_(std::move(db_wrapper)) {}
template <typename T>
UniqueProtoDatabase<T>::UniqueProtoDatabase(
const base::FilePath& database_dir,
const leveldb_env::Options& options,
const scoped_refptr<base::SequencedTaskRunner>& task_runner)
: ProtoDatabase<T>(task_runner) {
: UniqueProtoDatabase<T>(task_runner) {
database_dir_ = database_dir;
options_ = options;
}
......@@ -67,7 +129,7 @@ template <typename T>
UniqueProtoDatabase<T>::~UniqueProtoDatabase() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (db_.get() &&
!this->db_wrapper_->task_runner()->DeleteSoon(FROM_HERE, db_.release()))
!db_wrapper_->task_runner()->DeleteSoon(FROM_HERE, db_.release()))
DLOG(WARNING) << "Proto database will not be deleted.";
}
......@@ -77,8 +139,8 @@ void UniqueProtoDatabase<T>::Init(
typename ProtoDatabase<T>::InitCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
db_ = std::make_unique<LevelDB>(client_name.c_str());
ProtoDatabase<T>::InitWithDatabase(db_.get(), database_dir_, options_,
std::move(callback));
db_wrapper_->SetMetricsId(client_name);
InitWithDatabase(db_.get(), database_dir_, options_, std::move(callback));
}
template <typename T>
......@@ -89,9 +151,131 @@ void UniqueProtoDatabase<T>::Init(
typename ProtoDatabase<T>::InitCallback callback) {
database_dir_ = database_dir;
options_ = options;
db_wrapper_->SetMetricsId(client_name);
Init(std::string(client_name), std::move(callback));
}
template <typename T>
void UniqueProtoDatabase<T>::InitWithDatabase(
LevelDB* database,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
typename ProtoDatabase<T>::InitCallback callback) {
// We set |destroy_on_corruption| to true to preserve the original behaviour
// where database corruption led to automatic destruction.
db_wrapper_->InitWithDatabase(database, database_dir, options,
true /* destroy_on_corruption */,
std::move(callback));
}
template <typename T>
void UniqueProtoDatabase<T>::UpdateEntries(
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save,
std::unique_ptr<std::vector<std::string>> keys_to_remove,
typename ProtoDatabase<T>::UpdateCallback callback) {
db_wrapper_->template UpdateEntries<T>(std::move(entries_to_save),
std::move(keys_to_remove),
std::move(callback));
}
template <typename T>
void UniqueProtoDatabase<T>::UpdateEntriesWithRemoveFilter(
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save,
const LevelDB::KeyFilter& delete_key_filter,
typename ProtoDatabase<T>::UpdateCallback callback) {
db_wrapper_->template UpdateEntriesWithRemoveFilter<T>(
std::move(entries_to_save), delete_key_filter, std::move(callback));
}
template <typename T>
void UniqueProtoDatabase<T>::UpdateEntriesWithRemoveFilter(
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save,
const LevelDB::KeyFilter& delete_key_filter,
const std::string& target_prefix,
typename ProtoDatabase<T>::UpdateCallback callback) {
db_wrapper_->template UpdateEntriesWithRemoveFilter<T>(
std::move(entries_to_save), delete_key_filter, target_prefix,
std::move(callback));
}
template <typename T>
void UniqueProtoDatabase<T>::LoadEntries(
typename ProtoDatabase<T>::LoadCallback callback) {
db_wrapper_->template LoadEntries<T>(std::move(callback));
}
template <typename T>
void UniqueProtoDatabase<T>::LoadEntriesWithFilter(
const LevelDB::KeyFilter& filter,
typename ProtoDatabase<T>::LoadCallback callback) {
db_wrapper_->template LoadEntriesWithFilter<T>(filter, std::move(callback));
}
template <typename T>
void UniqueProtoDatabase<T>::LoadEntriesWithFilter(
const LevelDB::KeyFilter& key_filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
typename ProtoDatabase<T>::LoadCallback callback) {
db_wrapper_->template LoadEntriesWithFilter<T>(
key_filter, options, target_prefix, std::move(callback));
}
template <typename T>
void UniqueProtoDatabase<T>::LoadKeysAndEntries(
typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) {
db_wrapper_->template LoadKeysAndEntries<T>(std::move(callback));
}
template <typename T>
void UniqueProtoDatabase<T>::LoadKeysAndEntriesWithFilter(
const LevelDB::KeyFilter& filter,
typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) {
db_wrapper_->template LoadKeysAndEntriesWithFilter<T>(filter,
std::move(callback));
}
template <typename T>
void UniqueProtoDatabase<T>::LoadKeysAndEntriesWithFilter(
const LevelDB::KeyFilter& filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) {
db_wrapper_->template LoadKeysAndEntriesWithFilter<T>(
filter, options, target_prefix, std::move(callback));
}
template <typename T>
void UniqueProtoDatabase<T>::LoadKeys(
typename ProtoDatabase<T>::LoadKeysCallback callback) {
db_wrapper_->LoadKeys(std::move(callback));
}
template <typename T>
void UniqueProtoDatabase<T>::LoadKeys(
const std::string& target_prefix,
typename ProtoDatabase<T>::LoadKeysCallback callback) {
db_wrapper_->LoadKeys(target_prefix, std::move(callback));
}
template <typename T>
void UniqueProtoDatabase<T>::GetEntry(
const std::string& key,
typename ProtoDatabase<T>::GetCallback callback) {
db_wrapper_->template GetEntry<T>(key, std::move(callback));
}
template <typename T>
void UniqueProtoDatabase<T>::Destroy(
typename ProtoDatabase<T>::DestroyCallback callback) {
db_wrapper_->Destroy(std::move(callback));
}
template <typename T>
bool UniqueProtoDatabase<T>::GetApproximateMemoryUse(uint64_t* approx_mem_use) {
return db_wrapper_->GetApproximateMemoryUse(approx_mem_use);
}
} // namespace leveldb_proto
#endif // COMPONENTS_LEVELDB_PROTO_UNIQUE_PROTO_DATABASE_H_
......@@ -19,8 +19,10 @@ source_set("feature_engagement") {
"//components/feature_engagement",
"//components/keyed_service/core",
"//components/keyed_service/ios",
"//components/leveldb_proto",
"//ios/chrome/browser",
"//ios/chrome/browser/browser_state",
"//ios/chrome/browser/leveldb_proto:factory",
"//ios/chrome/browser/ui/commands",
"//ios/web/public",
]
......
......@@ -11,6 +11,7 @@
#include "components/feature_engagement/public/tracker.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#include "ios/chrome/browser/chrome_constants.h"
#include "ios/chrome/browser/leveldb_proto/proto_database_provider_factory.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
......@@ -38,8 +39,12 @@ std::unique_ptr<KeyedService> CreateFeatureEngagementTracker(
base::FilePath storage_dir = browser_state->GetStatePath().Append(
kIOSFeatureEngagementTrackerStorageDirname);
return base::WrapUnique(
feature_engagement::Tracker::Create(storage_dir, background_task_runner));
leveldb_proto::ProtoDatabaseProvider* db_provider =
leveldb_proto::ProtoDatabaseProviderFactory::GetForBrowserState(
browser_state);
return base::WrapUnique(feature_engagement::Tracker::Create(
storage_dir, background_task_runner, db_provider));
}
} // namespace feature_engagement
# 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.
source_set("factory") {
sources = [
"proto_database_provider_factory.h",
"proto_database_provider_factory.mm",
]
configs += [ "//build/config/compiler:enable_arc" ]
deps = [
"//base",
"//components/keyed_service/core",
"//components/keyed_service/ios",
"//components/leveldb_proto",
"//ios/chrome/browser",
"//ios/chrome/browser/browser_state",
]
}
// 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 IOS_CHROME_BROWSER_LEVELDB_PROTO_PROTO_DATABASE_PROVIDER_FACTORY_H_
#define IOS_CHROME_BROWSER_LEVELDB_PROTO_PROTO_DATABASE_PROVIDER_FACTORY_H_
#include "base/macros.h"
#include "components/keyed_service/ios/browser_state_keyed_service_factory.h"
namespace base {
template <typename T>
struct DefaultSingletonTraits;
} // namespace base
namespace ios {
class ChromeBrowserState;
} // namespace ios
namespace leveldb_proto {
class ProtoDatabaseProvider;
// A factory for ProtoDatabaseProvider, a class that provides proto databases
// stored in the appropriate directory given an ios::ChromeBrowserState object.
class ProtoDatabaseProviderFactory : public BrowserStateKeyedServiceFactory {
public:
// Returns singleton instance of ProtoDatabaseProviderFactory.
static ProtoDatabaseProviderFactory* GetInstance();
// Returns ProtoDatabaseProvider associated with |context|, so we can
// instantiate ProtoDatabases that use the appropriate profile directory.
static ProtoDatabaseProvider* GetForBrowserState(
ios::ChromeBrowserState* browser_state);
protected:
// BrowserStateKeyedServiceFactory implementation.
std::unique_ptr<KeyedService> BuildServiceInstanceFor(
web::BrowserState* context) const override;
private:
friend struct base::DefaultSingletonTraits<ProtoDatabaseProviderFactory>;
ProtoDatabaseProviderFactory();
~ProtoDatabaseProviderFactory() override;
DISALLOW_COPY_AND_ASSIGN(ProtoDatabaseProviderFactory);
};
} // namespace leveldb_proto
#endif // IOS_CHROME_BROWSER_LEVELDB_PROTO_PROTO_DATABASE_PROVIDER_FACTORY_H_
\ 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.
#include "ios/chrome/browser/leveldb_proto/proto_database_provider_factory.h"
#include "base/memory/singleton.h"
#include "components/keyed_service/ios/browser_state_dependency_manager.h"
#include "components/leveldb_proto/proto_database_provider.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace leveldb_proto {
// static
ProtoDatabaseProviderFactory* ProtoDatabaseProviderFactory::GetInstance() {
return base::Singleton<ProtoDatabaseProviderFactory>::get();
}
// static
leveldb_proto::ProtoDatabaseProvider*
ProtoDatabaseProviderFactory::GetForBrowserState(
ios::ChromeBrowserState* browser_state) {
return static_cast<leveldb_proto::ProtoDatabaseProvider*>(
GetInstance()->GetServiceForBrowserState(browser_state, true));
}
ProtoDatabaseProviderFactory::ProtoDatabaseProviderFactory()
: BrowserStateKeyedServiceFactory(
"leveldb_proto::ProtoDatabaseProvider",
BrowserStateDependencyManager::GetInstance()) {}
ProtoDatabaseProviderFactory::~ProtoDatabaseProviderFactory() = default;
std::unique_ptr<KeyedService>
ProtoDatabaseProviderFactory::BuildServiceInstanceFor(
web::BrowserState* context) const {
base::FilePath profile_dir = context->GetStatePath();
return base::WrapUnique(
leveldb_proto::ProtoDatabaseProvider::Create(profile_dir));
}
} // namespace leveldb_proto
\ No newline at end of file
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