model_type_store_backend.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // Copyright 2015 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. #ifndef COMPONENTS_SYNC_MODEL_MODEL_TYPE_STORE_BACKEND_H_
  5. #define COMPONENTS_SYNC_MODEL_MODEL_TYPE_STORE_BACKEND_H_
  6. #include <memory>
  7. #include <string>
  8. #include "base/files/file_path.h"
  9. #include "base/memory/ref_counted.h"
  10. #include "base/memory/scoped_refptr.h"
  11. #include "base/sequence_checker.h"
  12. #include "base/task/sequenced_task_runner.h"
  13. #include "components/sync/model/model_type_store.h"
  14. #include "third_party/abseil-cpp/absl/types/optional.h"
  15. #include "third_party/leveldatabase/src/include/leveldb/status.h"
  16. namespace leveldb {
  17. class DB;
  18. class Env;
  19. class WriteBatch;
  20. } // namespace leveldb
  21. namespace syncer {
  22. // ModelTypeStoreBackend handles operations with leveldb. It is oblivious of the
  23. // fact that it is called from separate thread (with the exception of ctor),
  24. // meaning it shouldn't deal with callbacks and task_runners.
  25. //
  26. // Created and destroyed on any sequence, but otherwise initialized and used on
  27. // a single sequence (attached during Init()).
  28. class ModelTypeStoreBackend
  29. : public base::RefCountedThreadSafe<ModelTypeStoreBackend> {
  30. public:
  31. static scoped_refptr<ModelTypeStoreBackend> CreateInMemoryForTest();
  32. // Create a new and uninitialized instance of ModelTypeStoreBackend. Init()
  33. // must be called afterwards, which binds the instance to a certain sequence.
  34. static scoped_refptr<ModelTypeStoreBackend> CreateUninitialized();
  35. ModelTypeStoreBackend(const ModelTypeStoreBackend&) = delete;
  36. ModelTypeStoreBackend& operator=(const ModelTypeStoreBackend&) = delete;
  37. // Init opens database at |path|. If database doesn't exist it creates one.
  38. // It can be called from a sequence that is different to the constructing one,
  39. // but from this point on the backend is bound to the current sequence, and
  40. // must be used on it. May be destructed on any sequence.
  41. absl::optional<ModelError> Init(const base::FilePath& path);
  42. // Can be called from any sequence.
  43. bool IsInitialized() const;
  44. // Reads records with keys formed by prepending ids from |id_list| with
  45. // |prefix|. If the record is found its id (without prefix) and value is
  46. // appended to record_list. If record is not found its id is appended to
  47. // |missing_id_list|. It is not an error that records for ids are not found so
  48. // function will still return success in this case.
  49. absl::optional<ModelError> ReadRecordsWithPrefix(
  50. const std::string& prefix,
  51. const ModelTypeStore::IdList& id_list,
  52. ModelTypeStore::RecordList* record_list,
  53. ModelTypeStore::IdList* missing_id_list);
  54. // Reads all records with keys starting with |prefix|. Prefix is removed from
  55. // key before it is added to |record_list|.
  56. absl::optional<ModelError> ReadAllRecordsWithPrefix(
  57. const std::string& prefix,
  58. ModelTypeStore::RecordList* record_list);
  59. // Writes modifications accumulated in |write_batch| to database.
  60. absl::optional<ModelError> WriteModifications(
  61. std::unique_ptr<leveldb::WriteBatch> write_batch);
  62. absl::optional<ModelError> DeleteDataAndMetadataForPrefix(
  63. const std::string& prefix);
  64. // Migrate the db schema from |current_version| to |desired_version|.
  65. absl::optional<ModelError> MigrateForTest(int64_t current_version,
  66. int64_t desired_version);
  67. // Attempts to read and return the database's version.
  68. int64_t GetStoreVersionForTest();
  69. // Some constants exposed for testing.
  70. static const int64_t kLatestSchemaVersion;
  71. static const char kDBSchemaDescriptorRecordId[];
  72. private:
  73. friend class base::RefCountedThreadSafe<ModelTypeStoreBackend>;
  74. // This is a slightly adapted version of base::OnTaskRunnerDeleter: The one
  75. // difference is that if the destruction request already happens on the target
  76. // sequence, then this avoids posting a task, and instead deletes the given
  77. // object immediately. This is convenient for unit-tests that don't run all
  78. // posted tasks, to avoid leaking memory.
  79. struct CustomOnTaskRunnerDeleter {
  80. explicit CustomOnTaskRunnerDeleter(
  81. scoped_refptr<base::SequencedTaskRunner> task_runner);
  82. CustomOnTaskRunnerDeleter(CustomOnTaskRunnerDeleter&&);
  83. CustomOnTaskRunnerDeleter& operator=(CustomOnTaskRunnerDeleter&&);
  84. ~CustomOnTaskRunnerDeleter();
  85. // For compatibility with std:: deleters.
  86. template <typename T>
  87. void operator()(const T* ptr) {
  88. if (!ptr)
  89. return;
  90. if (task_runner_->RunsTasksInCurrentSequence()) {
  91. delete ptr;
  92. } else {
  93. task_runner_->DeleteSoon(FROM_HERE, ptr);
  94. }
  95. }
  96. scoped_refptr<base::SequencedTaskRunner> task_runner_;
  97. };
  98. // Normally |env| should be nullptr, this causes leveldb to use default disk
  99. // based environment from leveldb::Env::Default().
  100. // Providing |env| allows to override environment used by leveldb for tests
  101. // with in-memory or faulty environment.
  102. explicit ModelTypeStoreBackend(std::unique_ptr<leveldb::Env> env);
  103. ~ModelTypeStoreBackend();
  104. // Opens leveldb database passing correct options. On success sets |db_| and
  105. // returns ok status. On failure |db_| is nullptr and returned status reflects
  106. // failure type.
  107. leveldb::Status OpenDatabase(const std::string& path, leveldb::Env* env);
  108. // Destroys leveldb database. Used for recovering after database corruption.
  109. leveldb::Status DestroyDatabase(const std::string& path, leveldb::Env* env);
  110. // Attempts to read and return the database's version.
  111. // If there is not a schema descriptor present, the value returned is 0.
  112. // If an error occurs, the value returned is kInvalidSchemaVersion(-1).
  113. int64_t GetStoreVersion();
  114. // Migrate the db schema from |current_version| to |desired_version|,
  115. // returning nullopt on success.
  116. absl::optional<ModelError> Migrate(int64_t current_version,
  117. int64_t desired_version);
  118. // Migrates from no version record at all (version 0) to version 1 of
  119. // the schema, returning true on success.
  120. bool Migrate0To1();
  121. // In some scenarios ModelTypeStoreBackend holds ownership of env. Typical
  122. // example is when test creates in memory environment with CreateInMemoryEnv
  123. // and wants it to be destroyed along with backend. This is achieved by
  124. // passing ownership of env to TakeEnvOwnership function.
  125. //
  126. // env_ declaration should appear before declaration of db_ because
  127. // environment object should still be valid when db_'s destructor is called.
  128. //
  129. // Note that no custom deleter is used for |env_| because it is non-null for
  130. // callers of CreateInMemoryForTest(), which initializes |db_| synchronously
  131. // and hence |db_| also gets deleted without involving task-posting (i.e.
  132. // |db_| cannot outlive |env_|).
  133. const std::unique_ptr<leveldb::Env> env_;
  134. // Destruction of |leveldb::DB| may incur blocking calls, and this class may
  135. // be destructed on any sequence, so let's avoid worst-case blocking the UI
  136. // thread by destroying leveldb::DB on the sequence where Init() was called.
  137. std::unique_ptr<leveldb::DB, CustomOnTaskRunnerDeleter> db_;
  138. // Ensures that operations with backend are performed seqentially, not
  139. // concurrently.
  140. SEQUENCE_CHECKER(sequence_checker_);
  141. };
  142. } // namespace syncer
  143. #endif // COMPONENTS_SYNC_MODEL_MODEL_TYPE_STORE_BACKEND_H_