blob: e1c3960f41110ec98acb777d57adf5e52c11e13c [file] [log] [blame]
// 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_INTERNAL_SHARED_PROTO_DATABASE_CLIENT_H_
#define COMPONENTS_LEVELDB_PROTO_INTERNAL_SHARED_PROTO_DATABASE_CLIENT_H_
#include <memory>
#include <string>
#include "base/bind.h"
#include "base/component_export.h"
#include "base/sequence_checker.h"
#include "components/leveldb_proto/internal/leveldb_database.h"
#include "components/leveldb_proto/internal/proto/shared_db_metadata.pb.h"
#include "components/leveldb_proto/internal/unique_proto_database.h"
#include "components/leveldb_proto/public/shared_proto_database_client_list.h"
namespace leveldb_proto {
class SharedProtoDatabase;
// TODO: Move all these as static or member functions in the class.
using ClientCorruptCallback = base::OnceCallback<void(bool)>;
using SharedClientInitCallback =
base::OnceCallback<void(Enums::InitStatus,
SharedDBMetadataProto::MigrationStatus)>;
// An implementation of ProtoDatabase<T> that uses a shared LevelDB and task
// runner.
// Should be created, destroyed, and used on the same sequenced task runner.
class COMPONENT_EXPORT(LEVELDB_PROTO) SharedProtoDatabaseClient
: public UniqueProtoDatabase {
public:
static std::string PrefixForDatabase(ProtoDbType db_type);
static std::string StripPrefix(const std::string& key,
const std::string& prefix);
static std::unique_ptr<KeyVector> PrefixStrings(
std::unique_ptr<KeyVector> strings,
const std::string& prefix);
static bool KeyFilterStripPrefix(const KeyFilter& key_filter,
const std::string& prefix,
const std::string& key);
static void GetSharedDatabaseInitStatusAsync(
const std::string& client_db_id,
const scoped_refptr<SharedProtoDatabase>& db,
Callbacks::InitStatusCallback callback);
static void UpdateClientMetadataAsync(
const scoped_refptr<SharedProtoDatabase>& db,
const std::string& client_db_id,
SharedDBMetadataProto::MigrationStatus migration_status,
ClientCorruptCallback callback);
// Destroys all the data from obsolete clients, for the given |db_wrapper|
// instance. |callback| is called once all the obsolete clients data are
// removed, with failure status if one or more of the update fails.
static void DestroyObsoleteSharedProtoDatabaseClients(
std::unique_ptr<ProtoLevelDBWrapper> db_wrapper,
Callbacks::UpdateCallback callback);
// Sets list of client names that are obsolete and will be cleared by next
// call to DestroyObsoleteSharedProtoDatabaseClients(). |list| is list of dbs
// with a |LAST| to mark the end of list.
static void SetObsoleteClientListForTesting(const ProtoDbType* list);
~SharedProtoDatabaseClient() override;
void Init(const std::string& client_uma_name,
Callbacks::InitStatusCallback callback) override;
void InitWithDatabase(LevelDB* database,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
bool destroy_on_corruption,
Callbacks::InitStatusCallback callback) override;
// Overrides for prepending namespace and type prefix to all operations on the
// shared database.
void UpdateEntries(std::unique_ptr<KeyValueVector> entries_to_save,
std::unique_ptr<KeyVector> keys_to_remove,
Callbacks::UpdateCallback callback) override;
void UpdateEntriesWithRemoveFilter(
std::unique_ptr<KeyValueVector> entries_to_save,
const KeyFilter& delete_key_filter,
Callbacks::UpdateCallback callback) override;
void UpdateEntriesWithRemoveFilter(
std::unique_ptr<KeyValueVector> entries_to_save,
const KeyFilter& delete_key_filter,
const std::string& target_prefix,
Callbacks::UpdateCallback callback) override;
void LoadEntries(Callbacks::LoadCallback callback) override;
void LoadEntriesWithFilter(const KeyFilter& filter,
Callbacks::LoadCallback callback) override;
void LoadEntriesWithFilter(const KeyFilter& key_filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
Callbacks::LoadCallback callback) override;
void LoadKeys(Callbacks::LoadKeysCallback callback) override;
void LoadKeys(const std::string& target_prefix,
Callbacks::LoadKeysCallback callback) override;
void LoadKeysAndEntries(
Callbacks::LoadKeysAndEntriesCallback callback) override;
void LoadKeysAndEntriesWithFilter(
const KeyFilter& filter,
Callbacks::LoadKeysAndEntriesCallback callback) override;
void LoadKeysAndEntriesWithFilter(
const KeyFilter& filter,
const leveldb::ReadOptions& options,
const std::string& target_prefix,
Callbacks::LoadKeysAndEntriesCallback callback) override;
void LoadKeysAndEntriesInRange(
const std::string& start,
const std::string& end,
Callbacks::LoadKeysAndEntriesCallback callback) override;
void GetEntry(const std::string& key,
Callbacks::GetCallback callback) override;
void Destroy(Callbacks::DestroyCallback callback) override;
Callbacks::InitCallback GetInitCallback() const;
const std::string& client_db_id() const { return prefix_; }
void set_migration_status(
SharedDBMetadataProto::MigrationStatus migration_status) {
migration_status_ = migration_status;
}
virtual void UpdateClientInitMetadata(SharedDBMetadataProto::MigrationStatus);
SharedDBMetadataProto::MigrationStatus migration_status() const {
return migration_status_;
}
private:
friend class SharedProtoDatabase;
friend class SharedProtoDatabaseTest;
friend class SharedProtoDatabaseClientTest;
friend class TestSharedProtoDatabaseClient;
// Hide this so clients can only be created by the SharedProtoDatabase.
SharedProtoDatabaseClient(
std::unique_ptr<ProtoLevelDBWrapper> db_wrapper,
ProtoDbType db_type,
const scoped_refptr<SharedProtoDatabase>& parent_db);
static void StripPrefixLoadKeysCallback(
Callbacks::LoadKeysCallback callback,
const std::string& prefix,
bool success,
std::unique_ptr<leveldb_proto::KeyVector> keys);
static void StripPrefixLoadKeysAndEntriesCallback(
Callbacks::LoadKeysAndEntriesCallback callback,
const std::string& prefix,
bool success,
std::unique_ptr<KeyValueMap> keys_entries);
static std::unique_ptr<KeyValueVector> PrefixKeyEntryVector(
std::unique_ptr<KeyValueVector> kev,
const std::string& prefix);
SEQUENCE_CHECKER(sequence_checker_);
// |is_corrupt_| should be set by the SharedProtoDatabase that creates this
// when a client is created that doesn't know about a previous shared
// database corruption.
bool is_corrupt_ = false;
SharedDBMetadataProto::MigrationStatus migration_status_ =
SharedDBMetadataProto::MIGRATION_NOT_ATTEMPTED;
const std::string prefix_;
scoped_refptr<SharedProtoDatabase> parent_db_;
base::WeakPtrFactory<SharedProtoDatabaseClient> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(SharedProtoDatabaseClient);
};
} // namespace leveldb_proto
#endif // COMPONENTS_LEVELDB_PROTO_INTERNAL_SHARED_PROTO_DATABASE_CLIENT_H_