123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- // 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/sync/model/blocking_model_type_store_impl.h"
- #include <utility>
- #include "base/check_op.h"
- #include "base/location.h"
- #include "base/memory/ptr_util.h"
- #include "base/memory/raw_ptr.h"
- #include "components/sync/model/metadata_batch.h"
- #include "components/sync/model/model_error.h"
- #include "components/sync/model/model_type_store_backend.h"
- #include "components/sync/protocol/entity_metadata.pb.h"
- #include "components/sync/protocol/model_type_state.pb.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "third_party/leveldatabase/src/include/leveldb/env.h"
- #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
- namespace syncer {
- namespace {
- // Key prefix for data/metadata records.
- const char kDataPrefix[] = "-dt-";
- const char kMetadataPrefix[] = "-md-";
- // Key for global metadata record.
- const char kGlobalMetadataKey[] = "-GlobalMetadata";
- class LevelDbMetadataChangeList : public MetadataChangeList {
- public:
- LevelDbMetadataChangeList(ModelType type,
- leveldb::WriteBatch* leveldb_write_batch)
- : leveldb_write_batch_(leveldb_write_batch),
- metadata_prefix_(FormatMetaPrefix(type)),
- global_metadata_key_(FormatGlobalMetadataKey(type)) {
- DCHECK(leveldb_write_batch_);
- }
- // MetadataChangeList implementation.
- void UpdateModelTypeState(
- const sync_pb::ModelTypeState& model_type_state) override {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- leveldb_write_batch_->Put(global_metadata_key_,
- model_type_state.SerializeAsString());
- }
- void ClearModelTypeState() override {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- leveldb_write_batch_->Delete(global_metadata_key_);
- }
- void UpdateMetadata(const std::string& storage_key,
- const sync_pb::EntityMetadata& metadata) override {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- leveldb_write_batch_->Put(FormatMetadataKey(storage_key),
- metadata.SerializeAsString());
- }
- void ClearMetadata(const std::string& storage_key) override {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- leveldb_write_batch_->Delete(FormatMetadataKey(storage_key));
- }
- private:
- // Format key for metadata records with given id.
- std::string FormatMetadataKey(const std::string& id) const {
- return metadata_prefix_ + id;
- }
- const raw_ptr<leveldb::WriteBatch> leveldb_write_batch_;
- // Key for this type's metadata records.
- const std::string metadata_prefix_;
- const std::string global_metadata_key_;
- SEQUENCE_CHECKER(sequence_checker_);
- };
- class LevelDbWriteBatch : public BlockingModelTypeStoreImpl::WriteBatch {
- public:
- static std::unique_ptr<leveldb::WriteBatch> ToLevelDbWriteBatch(
- std::unique_ptr<LevelDbWriteBatch> batch) {
- return std::move(batch->leveldb_write_batch_);
- }
- explicit LevelDbWriteBatch(ModelType type)
- : type_(type),
- data_prefix_(FormatDataPrefix(type)),
- leveldb_write_batch_(std::make_unique<leveldb::WriteBatch>()),
- metadata_change_list_(type, leveldb_write_batch_.get()) {}
- ~LevelDbWriteBatch() override = default;
- ModelType GetModelType() const { return type_; }
- // WriteBatch implementation.
- void WriteData(const std::string& id, const std::string& value) override {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- leveldb_write_batch_->Put(FormatDataKey(id), value);
- }
- void DeleteData(const std::string& id) override {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- leveldb_write_batch_->Delete(FormatDataKey(id));
- }
- MetadataChangeList* GetMetadataChangeList() override {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return &metadata_change_list_;
- }
- private:
- // Format key for data records with given id.
- std::string FormatDataKey(const std::string& id) const {
- return data_prefix_ + id;
- }
- const ModelType type_;
- // Key prefix for data records of this model type.
- const std::string data_prefix_;
- std::unique_ptr<leveldb::WriteBatch> leveldb_write_batch_;
- LevelDbMetadataChangeList metadata_change_list_;
- SEQUENCE_CHECKER(sequence_checker_);
- };
- } // namespace
- // Formats key prefix for data records of |type|.
- std::string FormatDataPrefix(ModelType type) {
- return std::string(GetModelTypeRootTag(type)) + kDataPrefix;
- }
- // Formats key prefix for metadata records of |type|.
- std::string FormatMetaPrefix(ModelType type) {
- return std::string(GetModelTypeRootTag(type)) + kMetadataPrefix;
- }
- // Formats key for global metadata record of |type|.
- std::string FormatGlobalMetadataKey(ModelType type) {
- return std::string(GetModelTypeRootTag(type)) + kGlobalMetadataKey;
- }
- BlockingModelTypeStoreImpl::BlockingModelTypeStoreImpl(
- ModelType type,
- scoped_refptr<ModelTypeStoreBackend> backend)
- : type_(type),
- backend_(std::move(backend)),
- data_prefix_(FormatDataPrefix(type)),
- metadata_prefix_(FormatMetaPrefix(type)),
- global_metadata_key_(FormatGlobalMetadataKey(type)) {
- DCHECK(backend_);
- }
- BlockingModelTypeStoreImpl::~BlockingModelTypeStoreImpl() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- }
- absl::optional<ModelError> BlockingModelTypeStoreImpl::ReadData(
- const IdList& id_list,
- RecordList* data_records,
- IdList* missing_id_list) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(data_records);
- DCHECK(missing_id_list);
- return backend_->ReadRecordsWithPrefix(data_prefix_, id_list, data_records,
- missing_id_list);
- }
- absl::optional<ModelError> BlockingModelTypeStoreImpl::ReadAllData(
- RecordList* data_records) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(data_records);
- return backend_->ReadAllRecordsWithPrefix(data_prefix_, data_records);
- }
- absl::optional<ModelError> BlockingModelTypeStoreImpl::ReadAllMetadata(
- MetadataBatch* metadata_batch) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(metadata_batch);
- // Read global metadata.
- RecordList global_metadata_records;
- IdList missing_global_metadata_id;
- absl::optional<ModelError> error = backend_->ReadRecordsWithPrefix(
- /*prefix=*/std::string(), {global_metadata_key_},
- &global_metadata_records, &missing_global_metadata_id);
- if (error.has_value()) {
- return error;
- }
- // If global metadata is missing, no need to read further.
- if (!missing_global_metadata_id.empty()) {
- // Missing global metadata record is not an error; we can just return the
- // default instance.
- DCHECK_EQ(global_metadata_key_, missing_global_metadata_id[0]);
- DCHECK(global_metadata_records.empty());
- } else {
- sync_pb::ModelTypeState state;
- if (!state.ParseFromString(global_metadata_records[0].value)) {
- return ModelError(FROM_HERE, "Failed to deserialize model type state.");
- }
- metadata_batch->SetModelTypeState(state);
- }
- // Read individual metadata records.
- RecordList metadata_records;
- error =
- backend_->ReadAllRecordsWithPrefix(metadata_prefix_, &metadata_records);
- if (error.has_value()) {
- return error;
- }
- for (const Record& r : metadata_records) {
- auto entity_metadata = std::make_unique<sync_pb::EntityMetadata>();
- if (!entity_metadata->ParseFromString(r.value)) {
- return ModelError(FROM_HERE, "Failed to deserialize entity metadata.");
- }
- metadata_batch->AddMetadata(r.id, std::move(entity_metadata));
- }
- return absl::nullopt;
- }
- std::unique_ptr<BlockingModelTypeStoreImpl::WriteBatch>
- BlockingModelTypeStoreImpl::CreateWriteBatch() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return CreateWriteBatchForType(type_);
- }
- absl::optional<ModelError> BlockingModelTypeStoreImpl::CommitWriteBatch(
- std::unique_ptr<WriteBatch> write_batch) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(write_batch);
- std::unique_ptr<LevelDbWriteBatch> write_batch_impl(
- static_cast<LevelDbWriteBatch*>(write_batch.release()));
- DCHECK_EQ(write_batch_impl->GetModelType(), type_);
- return backend_->WriteModifications(
- LevelDbWriteBatch::ToLevelDbWriteBatch(std::move(write_batch_impl)));
- }
- absl::optional<ModelError>
- BlockingModelTypeStoreImpl::DeleteAllDataAndMetadata() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return backend_->DeleteDataAndMetadataForPrefix(GetModelTypeRootTag(type_));
- }
- // static
- std::unique_ptr<BlockingModelTypeStoreImpl::WriteBatch>
- BlockingModelTypeStoreImpl::CreateWriteBatchForType(ModelType type) {
- return std::make_unique<LevelDbWriteBatch>(type);
- }
- } // namespace syncer
|