| Index: components/sync/model_impl/model_type_store_backend.cc
|
| diff --git a/components/sync/model_impl/model_type_store_backend.cc b/components/sync/model_impl/model_type_store_backend.cc
|
| index afc6fe8f3d7c7f0c37eb2e3ff2ce29b38625a2f9..a277b82f8cc0918bceae1263691540fafa80bded 100644
|
| --- a/components/sync/model_impl/model_type_store_backend.cc
|
| +++ b/components/sync/model_impl/model_type_store_backend.cc
|
| @@ -7,8 +7,10 @@
|
| #include <utility>
|
|
|
| #include "base/files/file_path.h"
|
| +#include "base/lazy_instance.h"
|
| #include "base/memory/ptr_util.h"
|
| #include "base/metrics/histogram_macros.h"
|
| +#include "base/synchronization/lock.h"
|
| #include "components/sync/protocol/model_type_store_schema_descriptor.pb.h"
|
| #include "third_party/leveldatabase/env_chromium.h"
|
| #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
|
| @@ -31,10 +33,6 @@ const char ModelTypeStoreBackend::kDBSchemaDescriptorRecordId[] =
|
| const char ModelTypeStoreBackend::kStoreInitResultHistogramName[] =
|
| "Sync.ModelTypeStoreInitResult";
|
|
|
| -// static
|
| -base::LazyInstance<ModelTypeStoreBackend::BackendMap>::DestructorAtExit
|
| - ModelTypeStoreBackend::backend_map_ = LAZY_INSTANCE_INITIALIZER;
|
| -
|
| namespace {
|
|
|
| StoreInitResultForHistogram LevelDbStatusToStoreInitResult(
|
| @@ -54,13 +52,59 @@ StoreInitResultForHistogram LevelDbStatusToStoreInitResult(
|
| return STORE_INIT_RESULT_UNKNOWN;
|
| }
|
|
|
| +// BackendMap tracks created ModelTypeStoreBackends ensuring at most one backend
|
| +// exists for a given path. BackendMap keeps non-owning pointer to backend
|
| +// allowing backend lifetime to be controlled by consumers. Since backends can
|
| +// run concurrently on different threads all map operations are guarded by lock.
|
| +class BackendMap {
|
| + public:
|
| + BackendMap() = default;
|
| +
|
| + // Returns backend reference or nullptr if backend for |path| is not in the
|
| + // map.
|
| + scoped_refptr<ModelTypeStoreBackend> GetBackend(
|
| + const std::string& path) const;
|
| + // Adds backend into the map ensuring it wasn't added before.
|
| + void SetBackend(const std::string& path, ModelTypeStoreBackend* backend);
|
| + void EraseBackend(const std::string& path);
|
| +
|
| + private:
|
| + mutable base::Lock lock_;
|
| +
|
| + std::unordered_map<std::string, ModelTypeStoreBackend*> backends_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(BackendMap);
|
| +};
|
| +
|
| +base::LazyInstance<BackendMap>::DestructorAtExit backend_map =
|
| + LAZY_INSTANCE_INITIALIZER;
|
| +
|
| +scoped_refptr<ModelTypeStoreBackend> BackendMap::GetBackend(
|
| + const std::string& path) const {
|
| + base::AutoLock scoped_lock(lock_);
|
| + auto it = backends_.find(path);
|
| + return (it == backends_.end()) ? nullptr : it->second;
|
| +}
|
| +
|
| +void BackendMap::SetBackend(const std::string& path,
|
| + ModelTypeStoreBackend* backend) {
|
| + base::AutoLock scoped_lock(lock_);
|
| + DCHECK(backends_.find(path) == backends_.end());
|
| + backends_[path] = backend;
|
| +}
|
| +
|
| +void BackendMap::EraseBackend(const std::string& path) {
|
| + base::AutoLock scoped_lock(lock_);
|
| + backends_.erase(path);
|
| +}
|
| +
|
| } // namespace
|
|
|
| ModelTypeStoreBackend::ModelTypeStoreBackend(const std::string& path)
|
| : path_(path) {}
|
|
|
| ModelTypeStoreBackend::~ModelTypeStoreBackend() {
|
| - backend_map_.Get().erase(path_);
|
| + backend_map.Get().EraseBackend(path_);
|
| }
|
|
|
| std::unique_ptr<leveldb::Env> ModelTypeStoreBackend::CreateInMemoryEnv() {
|
| @@ -72,18 +116,19 @@ scoped_refptr<ModelTypeStoreBackend> ModelTypeStoreBackend::GetOrCreateBackend(
|
| const std::string& path,
|
| std::unique_ptr<leveldb::Env> env,
|
| ModelTypeStore::Result* result) {
|
| - if (backend_map_.Get().find(path) != backend_map_.Get().end()) {
|
| + scoped_refptr<ModelTypeStoreBackend> backend =
|
| + backend_map.Get().GetBackend(path);
|
| + if (backend) {
|
| *result = ModelTypeStore::Result::SUCCESS;
|
| - return make_scoped_refptr(backend_map_.Get()[path]);
|
| + return backend;
|
| }
|
|
|
| - scoped_refptr<ModelTypeStoreBackend> backend =
|
| - new ModelTypeStoreBackend(path);
|
| + backend = new ModelTypeStoreBackend(path);
|
|
|
| *result = backend->Init(path, std::move(env));
|
|
|
| if (*result == ModelTypeStore::Result::SUCCESS) {
|
| - backend_map_.Get()[path] = backend.get();
|
| + backend_map.Get().SetBackend(path, backend.get());
|
| } else {
|
| backend = nullptr;
|
| }
|
| @@ -94,7 +139,7 @@ scoped_refptr<ModelTypeStoreBackend> ModelTypeStoreBackend::GetOrCreateBackend(
|
| ModelTypeStore::Result ModelTypeStoreBackend::Init(
|
| const std::string& path,
|
| std::unique_ptr<leveldb::Env> env) {
|
| - DFAKE_SCOPED_LOCK(push_pop_);
|
| + DCHECK(sequence_checker_.CalledOnValidSequence());
|
|
|
| env_ = std::move(env);
|
|
|
| @@ -162,7 +207,7 @@ ModelTypeStore::Result ModelTypeStoreBackend::ReadRecordsWithPrefix(
|
| const ModelTypeStore::IdList& id_list,
|
| ModelTypeStore::RecordList* record_list,
|
| ModelTypeStore::IdList* missing_id_list) {
|
| - DFAKE_SCOPED_LOCK(push_pop_);
|
| + DCHECK(sequence_checker_.CalledOnValidSequence());
|
| DCHECK(db_);
|
| record_list->reserve(id_list.size());
|
| leveldb::ReadOptions read_options;
|
| @@ -186,7 +231,7 @@ ModelTypeStore::Result ModelTypeStoreBackend::ReadRecordsWithPrefix(
|
| ModelTypeStore::Result ModelTypeStoreBackend::ReadAllRecordsWithPrefix(
|
| const std::string& prefix,
|
| ModelTypeStore::RecordList* record_list) {
|
| - DFAKE_SCOPED_LOCK(push_pop_);
|
| + DCHECK(sequence_checker_.CalledOnValidSequence());
|
| DCHECK(db_);
|
| leveldb::ReadOptions read_options;
|
| read_options.verify_checksums = true;
|
| @@ -205,7 +250,7 @@ ModelTypeStore::Result ModelTypeStoreBackend::ReadAllRecordsWithPrefix(
|
|
|
| ModelTypeStore::Result ModelTypeStoreBackend::WriteModifications(
|
| std::unique_ptr<leveldb::WriteBatch> write_batch) {
|
| - DFAKE_SCOPED_LOCK(push_pop_);
|
| + DCHECK(sequence_checker_.CalledOnValidSequence());
|
| DCHECK(db_);
|
| leveldb::Status status =
|
| db_->Write(leveldb::WriteOptions(), write_batch.get());
|
| @@ -263,4 +308,9 @@ void ModelTypeStoreBackend::RecordStoreInitResultHistogram(
|
| STORE_INIT_RESULT_COUNT);
|
| }
|
|
|
| +// static
|
| +bool ModelTypeStoreBackend::BackendExistsForTest(const std::string& path) {
|
| + return backend_map.Get().GetBackend(path) != nullptr;
|
| +}
|
| +
|
| } // namespace syncer
|
|
|