blocking_model_type_store_impl.cc 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/sync/model/blocking_model_type_store_impl.h"
  5. #include <utility>
  6. #include "base/check_op.h"
  7. #include "base/location.h"
  8. #include "base/memory/ptr_util.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "components/sync/model/metadata_batch.h"
  11. #include "components/sync/model/model_error.h"
  12. #include "components/sync/model/model_type_store_backend.h"
  13. #include "components/sync/protocol/entity_metadata.pb.h"
  14. #include "components/sync/protocol/model_type_state.pb.h"
  15. #include "third_party/abseil-cpp/absl/types/optional.h"
  16. #include "third_party/leveldatabase/src/include/leveldb/env.h"
  17. #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
  18. namespace syncer {
  19. namespace {
  20. // Key prefix for data/metadata records.
  21. const char kDataPrefix[] = "-dt-";
  22. const char kMetadataPrefix[] = "-md-";
  23. // Key for global metadata record.
  24. const char kGlobalMetadataKey[] = "-GlobalMetadata";
  25. class LevelDbMetadataChangeList : public MetadataChangeList {
  26. public:
  27. LevelDbMetadataChangeList(ModelType type,
  28. leveldb::WriteBatch* leveldb_write_batch)
  29. : leveldb_write_batch_(leveldb_write_batch),
  30. metadata_prefix_(FormatMetaPrefix(type)),
  31. global_metadata_key_(FormatGlobalMetadataKey(type)) {
  32. DCHECK(leveldb_write_batch_);
  33. }
  34. // MetadataChangeList implementation.
  35. void UpdateModelTypeState(
  36. const sync_pb::ModelTypeState& model_type_state) override {
  37. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  38. leveldb_write_batch_->Put(global_metadata_key_,
  39. model_type_state.SerializeAsString());
  40. }
  41. void ClearModelTypeState() override {
  42. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  43. leveldb_write_batch_->Delete(global_metadata_key_);
  44. }
  45. void UpdateMetadata(const std::string& storage_key,
  46. const sync_pb::EntityMetadata& metadata) override {
  47. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  48. leveldb_write_batch_->Put(FormatMetadataKey(storage_key),
  49. metadata.SerializeAsString());
  50. }
  51. void ClearMetadata(const std::string& storage_key) override {
  52. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  53. leveldb_write_batch_->Delete(FormatMetadataKey(storage_key));
  54. }
  55. private:
  56. // Format key for metadata records with given id.
  57. std::string FormatMetadataKey(const std::string& id) const {
  58. return metadata_prefix_ + id;
  59. }
  60. const raw_ptr<leveldb::WriteBatch> leveldb_write_batch_;
  61. // Key for this type's metadata records.
  62. const std::string metadata_prefix_;
  63. const std::string global_metadata_key_;
  64. SEQUENCE_CHECKER(sequence_checker_);
  65. };
  66. class LevelDbWriteBatch : public BlockingModelTypeStoreImpl::WriteBatch {
  67. public:
  68. static std::unique_ptr<leveldb::WriteBatch> ToLevelDbWriteBatch(
  69. std::unique_ptr<LevelDbWriteBatch> batch) {
  70. return std::move(batch->leveldb_write_batch_);
  71. }
  72. explicit LevelDbWriteBatch(ModelType type)
  73. : type_(type),
  74. data_prefix_(FormatDataPrefix(type)),
  75. leveldb_write_batch_(std::make_unique<leveldb::WriteBatch>()),
  76. metadata_change_list_(type, leveldb_write_batch_.get()) {}
  77. ~LevelDbWriteBatch() override = default;
  78. ModelType GetModelType() const { return type_; }
  79. // WriteBatch implementation.
  80. void WriteData(const std::string& id, const std::string& value) override {
  81. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  82. leveldb_write_batch_->Put(FormatDataKey(id), value);
  83. }
  84. void DeleteData(const std::string& id) override {
  85. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  86. leveldb_write_batch_->Delete(FormatDataKey(id));
  87. }
  88. MetadataChangeList* GetMetadataChangeList() override {
  89. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  90. return &metadata_change_list_;
  91. }
  92. private:
  93. // Format key for data records with given id.
  94. std::string FormatDataKey(const std::string& id) const {
  95. return data_prefix_ + id;
  96. }
  97. const ModelType type_;
  98. // Key prefix for data records of this model type.
  99. const std::string data_prefix_;
  100. std::unique_ptr<leveldb::WriteBatch> leveldb_write_batch_;
  101. LevelDbMetadataChangeList metadata_change_list_;
  102. SEQUENCE_CHECKER(sequence_checker_);
  103. };
  104. } // namespace
  105. // Formats key prefix for data records of |type|.
  106. std::string FormatDataPrefix(ModelType type) {
  107. return std::string(GetModelTypeRootTag(type)) + kDataPrefix;
  108. }
  109. // Formats key prefix for metadata records of |type|.
  110. std::string FormatMetaPrefix(ModelType type) {
  111. return std::string(GetModelTypeRootTag(type)) + kMetadataPrefix;
  112. }
  113. // Formats key for global metadata record of |type|.
  114. std::string FormatGlobalMetadataKey(ModelType type) {
  115. return std::string(GetModelTypeRootTag(type)) + kGlobalMetadataKey;
  116. }
  117. BlockingModelTypeStoreImpl::BlockingModelTypeStoreImpl(
  118. ModelType type,
  119. scoped_refptr<ModelTypeStoreBackend> backend)
  120. : type_(type),
  121. backend_(std::move(backend)),
  122. data_prefix_(FormatDataPrefix(type)),
  123. metadata_prefix_(FormatMetaPrefix(type)),
  124. global_metadata_key_(FormatGlobalMetadataKey(type)) {
  125. DCHECK(backend_);
  126. }
  127. BlockingModelTypeStoreImpl::~BlockingModelTypeStoreImpl() {
  128. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  129. }
  130. absl::optional<ModelError> BlockingModelTypeStoreImpl::ReadData(
  131. const IdList& id_list,
  132. RecordList* data_records,
  133. IdList* missing_id_list) {
  134. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  135. DCHECK(data_records);
  136. DCHECK(missing_id_list);
  137. return backend_->ReadRecordsWithPrefix(data_prefix_, id_list, data_records,
  138. missing_id_list);
  139. }
  140. absl::optional<ModelError> BlockingModelTypeStoreImpl::ReadAllData(
  141. RecordList* data_records) {
  142. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  143. DCHECK(data_records);
  144. return backend_->ReadAllRecordsWithPrefix(data_prefix_, data_records);
  145. }
  146. absl::optional<ModelError> BlockingModelTypeStoreImpl::ReadAllMetadata(
  147. MetadataBatch* metadata_batch) {
  148. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  149. DCHECK(metadata_batch);
  150. // Read global metadata.
  151. RecordList global_metadata_records;
  152. IdList missing_global_metadata_id;
  153. absl::optional<ModelError> error = backend_->ReadRecordsWithPrefix(
  154. /*prefix=*/std::string(), {global_metadata_key_},
  155. &global_metadata_records, &missing_global_metadata_id);
  156. if (error.has_value()) {
  157. return error;
  158. }
  159. // If global metadata is missing, no need to read further.
  160. if (!missing_global_metadata_id.empty()) {
  161. // Missing global metadata record is not an error; we can just return the
  162. // default instance.
  163. DCHECK_EQ(global_metadata_key_, missing_global_metadata_id[0]);
  164. DCHECK(global_metadata_records.empty());
  165. } else {
  166. sync_pb::ModelTypeState state;
  167. if (!state.ParseFromString(global_metadata_records[0].value)) {
  168. return ModelError(FROM_HERE, "Failed to deserialize model type state.");
  169. }
  170. metadata_batch->SetModelTypeState(state);
  171. }
  172. // Read individual metadata records.
  173. RecordList metadata_records;
  174. error =
  175. backend_->ReadAllRecordsWithPrefix(metadata_prefix_, &metadata_records);
  176. if (error.has_value()) {
  177. return error;
  178. }
  179. for (const Record& r : metadata_records) {
  180. auto entity_metadata = std::make_unique<sync_pb::EntityMetadata>();
  181. if (!entity_metadata->ParseFromString(r.value)) {
  182. return ModelError(FROM_HERE, "Failed to deserialize entity metadata.");
  183. }
  184. metadata_batch->AddMetadata(r.id, std::move(entity_metadata));
  185. }
  186. return absl::nullopt;
  187. }
  188. std::unique_ptr<BlockingModelTypeStoreImpl::WriteBatch>
  189. BlockingModelTypeStoreImpl::CreateWriteBatch() {
  190. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  191. return CreateWriteBatchForType(type_);
  192. }
  193. absl::optional<ModelError> BlockingModelTypeStoreImpl::CommitWriteBatch(
  194. std::unique_ptr<WriteBatch> write_batch) {
  195. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  196. DCHECK(write_batch);
  197. std::unique_ptr<LevelDbWriteBatch> write_batch_impl(
  198. static_cast<LevelDbWriteBatch*>(write_batch.release()));
  199. DCHECK_EQ(write_batch_impl->GetModelType(), type_);
  200. return backend_->WriteModifications(
  201. LevelDbWriteBatch::ToLevelDbWriteBatch(std::move(write_batch_impl)));
  202. }
  203. absl::optional<ModelError>
  204. BlockingModelTypeStoreImpl::DeleteAllDataAndMetadata() {
  205. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  206. return backend_->DeleteDataAndMetadataForPrefix(GetModelTypeRootTag(type_));
  207. }
  208. // static
  209. std::unique_ptr<BlockingModelTypeStoreImpl::WriteBatch>
  210. BlockingModelTypeStoreImpl::CreateWriteBatchForType(ModelType type) {
  211. return std::make_unique<LevelDbWriteBatch>(type);
  212. }
  213. } // namespace syncer