value_store_frontend.cc 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // Copyright 2014 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/value_store/value_store_frontend.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/files/file_path.h"
  8. #include "base/logging.h"
  9. #include "base/memory/scoped_refptr.h"
  10. #include "base/task/sequenced_task_runner.h"
  11. #include "base/trace_event/trace_event.h"
  12. #include "components/value_store/leveldb_value_store.h"
  13. #include "components/value_store/value_store.h"
  14. #include "components/value_store/value_store_factory.h"
  15. namespace value_store {
  16. class ValueStoreFrontend::Backend : public base::RefCountedThreadSafe<Backend> {
  17. public:
  18. Backend(const scoped_refptr<ValueStoreFactory>& store_factory,
  19. const base::FilePath& directory,
  20. const std::string& uma_client_name,
  21. const scoped_refptr<base::SequencedTaskRunner>& origin_task_runner,
  22. const scoped_refptr<base::SequencedTaskRunner>& file_task_runner)
  23. : store_factory_(store_factory),
  24. directory_(directory),
  25. uma_client_name_(uma_client_name),
  26. origin_task_runner_(origin_task_runner),
  27. file_task_runner_(file_task_runner) {}
  28. Backend(const Backend&) = delete;
  29. Backend& operator=(const Backend&) = delete;
  30. void Get(const std::string& key, ValueStoreFrontend::ReadCallback callback) {
  31. DCHECK(file_task_runner_->RunsTasksInCurrentSequence());
  32. LazyInit();
  33. ValueStore::ReadResult result = storage_->Get(key);
  34. // Extract the value from the ReadResult and pass ownership of it to the
  35. // callback.
  36. absl::optional<base::Value> value;
  37. if (result.status().ok()) {
  38. value = result.settings().Extract(key);
  39. } else {
  40. LOG(WARNING) << "Reading " << key << " from " << db_path_.value()
  41. << " failed: " << result.status().message;
  42. }
  43. origin_task_runner_->PostTask(
  44. FROM_HERE,
  45. base::BindOnce(&ValueStoreFrontend::Backend::RunCallback, this,
  46. std::move(callback),
  47. value.has_value()
  48. ? base::Value::ToUniquePtrValue(std::move(*value))
  49. : nullptr));
  50. }
  51. void Set(const std::string& key, std::unique_ptr<base::Value> value) {
  52. DCHECK(file_task_runner_->RunsTasksInCurrentSequence());
  53. LazyInit();
  54. // We don't need the old value, so skip generating changes.
  55. ValueStore::WriteResult result = storage_->Set(
  56. ValueStore::IGNORE_QUOTA | ValueStore::NO_GENERATE_CHANGES, key,
  57. *value);
  58. LOG_IF(ERROR, !result.status().ok())
  59. << "Error while writing " << key << " to " << db_path_.value();
  60. }
  61. void Remove(const std::string& key) {
  62. DCHECK(file_task_runner_->RunsTasksInCurrentSequence());
  63. LazyInit();
  64. storage_->Remove(key);
  65. }
  66. private:
  67. friend class base::RefCountedThreadSafe<Backend>;
  68. virtual ~Backend() {
  69. if (storage_ && !file_task_runner_->RunsTasksInCurrentSequence())
  70. file_task_runner_->DeleteSoon(FROM_HERE, storage_.release());
  71. }
  72. void LazyInit() {
  73. DCHECK(file_task_runner_->RunsTasksInCurrentSequence());
  74. if (storage_)
  75. return;
  76. TRACE_EVENT0("ValueStoreFrontend::Backend", "LazyInit");
  77. storage_ = store_factory_->CreateValueStore(directory_, uma_client_name_);
  78. }
  79. void RunCallback(ValueStoreFrontend::ReadCallback callback,
  80. std::unique_ptr<base::Value> value) {
  81. DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
  82. std::move(callback).Run(std::move(value));
  83. }
  84. // The factory which will be used to lazily create the ValueStore when needed.
  85. // Used exclusively on the backend sequence.
  86. scoped_refptr<ValueStoreFactory> store_factory_;
  87. const base::FilePath directory_;
  88. const std::string uma_client_name_;
  89. scoped_refptr<base::SequencedTaskRunner> origin_task_runner_;
  90. scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
  91. // The actual ValueStore that handles persisting the data to disk. Used
  92. // exclusively on the backend sequence.
  93. std::unique_ptr<ValueStore> storage_;
  94. base::FilePath db_path_;
  95. };
  96. ValueStoreFrontend::ValueStoreFrontend(
  97. const scoped_refptr<ValueStoreFactory>& store_factory,
  98. const base::FilePath& directory,
  99. const std::string& uma_client_name,
  100. const scoped_refptr<base::SequencedTaskRunner>& origin_task_runner,
  101. const scoped_refptr<base::SequencedTaskRunner>& file_task_runner)
  102. : backend_(base::MakeRefCounted<Backend>(store_factory,
  103. directory,
  104. uma_client_name,
  105. origin_task_runner,
  106. file_task_runner)),
  107. origin_task_runner_(origin_task_runner),
  108. file_task_runner_(file_task_runner) {
  109. DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
  110. }
  111. ValueStoreFrontend::~ValueStoreFrontend() {
  112. DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
  113. }
  114. void ValueStoreFrontend::Get(const std::string& key, ReadCallback callback) {
  115. DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
  116. file_task_runner_->PostTask(
  117. FROM_HERE, base::BindOnce(&ValueStoreFrontend::Backend::Get, backend_,
  118. key, std::move(callback)));
  119. }
  120. void ValueStoreFrontend::Set(const std::string& key,
  121. std::unique_ptr<base::Value> value) {
  122. DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
  123. file_task_runner_->PostTask(
  124. FROM_HERE, base::BindOnce(&ValueStoreFrontend::Backend::Set, backend_,
  125. key, std::move(value)));
  126. }
  127. void ValueStoreFrontend::Remove(const std::string& key) {
  128. DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
  129. file_task_runner_->PostTask(
  130. FROM_HERE,
  131. base::BindOnce(&ValueStoreFrontend::Backend::Remove, backend_, key));
  132. }
  133. } // namespace value_store