Automated Commit: Committing new LKGM version 6953.0.0 for chromeos.
[chromium-blink-merge.git] / components / leveldb_proto / proto_database_impl.h
blobcc5622122c3b29e76d88e5d53bd13b97985135ae
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.
5 #ifndef COMPONENTS_LEVELDB_PROTO_PROTO_DATABASE_IMPL_H_
6 #define COMPONENTS_LEVELDB_PROTO_PROTO_DATABASE_IMPL_H_
8 #include <string>
9 #include <vector>
11 #include "base/bind.h"
12 #include "base/files/file_path.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/sequenced_task_runner.h"
16 #include "base/strings/string_util.h"
17 #include "base/threading/sequenced_worker_pool.h"
18 #include "base/threading/thread_checker.h"
19 #include "base/strings/string_split.h"
20 #include "components/leveldb_proto/leveldb_database.h"
21 #include "components/leveldb_proto/proto_database.h"
23 namespace leveldb_proto {
25 typedef base::StringPairs KeyValueVector;
26 typedef std::vector<std::string> KeyVector;
28 // When the ProtoDatabaseImpl instance is deleted, in-progress asynchronous
29 // operations will be completed and the corresponding callbacks will be called.
30 // Construction/calls/destruction should all happen on the same thread.
31 template <typename T>
32 class ProtoDatabaseImpl : public ProtoDatabase<T> {
33 public:
34 // All blocking calls/disk access will happen on the provided |task_runner|.
35 explicit ProtoDatabaseImpl(
36 scoped_refptr<base::SequencedTaskRunner> task_runner);
38 virtual ~ProtoDatabaseImpl();
40 // ProtoDatabase implementation.
41 // TODO(cjhopman): Perhaps Init() shouldn't be exposed to users and not just
42 // part of the constructor
43 virtual void Init(const base::FilePath& database_dir,
44 typename ProtoDatabase<T>::InitCallback callback) override;
45 virtual void UpdateEntries(
46 scoped_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save,
47 scoped_ptr<KeyVector> keys_to_remove,
48 typename ProtoDatabase<T>::UpdateCallback callback) override;
49 virtual void LoadEntries(
50 typename ProtoDatabase<T>::LoadCallback callback) override;
52 // Allow callers to provide their own Database implementation.
53 void InitWithDatabase(scoped_ptr<LevelDB> database,
54 const base::FilePath& database_dir,
55 typename ProtoDatabase<T>::InitCallback callback);
57 private:
58 base::ThreadChecker thread_checker_;
60 // Used to run blocking tasks in-order.
61 scoped_refptr<base::SequencedTaskRunner> task_runner_;
63 scoped_ptr<LevelDB> db_;
65 DISALLOW_COPY_AND_ASSIGN(ProtoDatabaseImpl);
68 namespace {
70 template <typename T>
71 void RunInitCallback(typename ProtoDatabase<T>::InitCallback callback,
72 const bool* success) {
73 callback.Run(*success);
76 template <typename T>
77 void RunUpdateCallback(typename ProtoDatabase<T>::UpdateCallback callback,
78 const bool* success) {
79 callback.Run(*success);
82 template <typename T>
83 void RunLoadCallback(typename ProtoDatabase<T>::LoadCallback callback,
84 const bool* success, scoped_ptr<std::vector<T> > entries) {
85 callback.Run(*success, entries.Pass());
88 void InitFromTaskRunner(LevelDB* database, const base::FilePath& database_dir,
89 bool* success) {
90 DCHECK(success);
92 // TODO(cjhopman): Histogram for database size.
93 *success = database->Init(database_dir);
96 template <typename T>
97 void UpdateEntriesFromTaskRunner(
98 LevelDB* database,
99 scoped_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save,
100 scoped_ptr<KeyVector> keys_to_remove, bool* success) {
101 DCHECK(success);
102 // Serialize the values from Proto to string before passing on to database.
103 KeyValueVector pairs_to_save;
104 for (typename ProtoDatabase<T>::KeyEntryVector::iterator it =
105 entries_to_save->begin();
106 it != entries_to_save->end(); ++it) {
107 pairs_to_save.push_back(
108 std::make_pair(it->first, it->second.SerializeAsString()));
110 *success = database->Save(pairs_to_save, *keys_to_remove);
113 template <typename T>
114 void LoadEntriesFromTaskRunner(LevelDB* database, std::vector<T>* entries,
115 bool* success) {
116 DCHECK(success);
117 DCHECK(entries);
119 entries->clear();
120 std::vector<std::string> loaded_entries;
121 *success = database->Load(&loaded_entries);
122 for (std::vector<std::string>::iterator it = loaded_entries.begin();
123 it != loaded_entries.end(); ++it) {
124 T entry;
125 if (!entry.ParseFromString(*it)) {
126 DLOG(WARNING) << "Unable to parse leveldb_proto entry " << *it;
127 // TODO(cjhopman): Decide what to do about un-parseable entries.
129 entries->push_back(entry);
133 } // namespace
135 template <typename T>
136 ProtoDatabaseImpl<T>::ProtoDatabaseImpl(
137 scoped_refptr<base::SequencedTaskRunner> task_runner)
138 : task_runner_(task_runner) {}
140 template <typename T>
141 ProtoDatabaseImpl<T>::~ProtoDatabaseImpl() {
142 DCHECK(thread_checker_.CalledOnValidThread());
143 if (!task_runner_->DeleteSoon(FROM_HERE, db_.release())) {
144 DLOG(WARNING) << "DOM distiller database will not be deleted.";
148 template <typename T>
149 void ProtoDatabaseImpl<T>::Init(
150 const base::FilePath& database_dir,
151 typename ProtoDatabase<T>::InitCallback callback) {
152 DCHECK(thread_checker_.CalledOnValidThread());
153 InitWithDatabase(scoped_ptr<LevelDB>(new LevelDB()), database_dir, callback);
156 template <typename T>
157 void ProtoDatabaseImpl<T>::InitWithDatabase(
158 scoped_ptr<LevelDB> database, const base::FilePath& database_dir,
159 typename ProtoDatabase<T>::InitCallback callback) {
160 DCHECK(thread_checker_.CalledOnValidThread());
161 DCHECK(!db_);
162 DCHECK(database);
163 db_.reset(database.release());
164 bool* success = new bool(false);
165 task_runner_->PostTaskAndReply(
166 FROM_HERE, base::Bind(InitFromTaskRunner, base::Unretained(db_.get()),
167 database_dir, success),
168 base::Bind(RunInitCallback<T>, callback, base::Owned(success)));
171 template <typename T>
172 void ProtoDatabaseImpl<T>::UpdateEntries(
173 scoped_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save,
174 scoped_ptr<KeyVector> keys_to_remove,
175 typename ProtoDatabase<T>::UpdateCallback callback) {
176 DCHECK(thread_checker_.CalledOnValidThread());
177 bool* success = new bool(false);
178 task_runner_->PostTaskAndReply(
179 FROM_HERE,
180 base::Bind(UpdateEntriesFromTaskRunner<T>, base::Unretained(db_.get()),
181 base::Passed(&entries_to_save), base::Passed(&keys_to_remove),
182 success),
183 base::Bind(RunUpdateCallback<T>, callback, base::Owned(success)));
186 template <typename T>
187 void ProtoDatabaseImpl<T>::LoadEntries(
188 typename ProtoDatabase<T>::LoadCallback callback) {
189 DCHECK(thread_checker_.CalledOnValidThread());
190 bool* success = new bool(false);
192 scoped_ptr<std::vector<T> > entries(new std::vector<T>());
193 // Get this pointer before entries is base::Passed() so we can use it below.
194 std::vector<T>* entries_ptr = entries.get();
196 task_runner_->PostTaskAndReply(
197 FROM_HERE, base::Bind(LoadEntriesFromTaskRunner<T>,
198 base::Unretained(db_.get()), entries_ptr, success),
199 base::Bind(RunLoadCallback<T>, callback, base::Owned(success),
200 base::Passed(&entries)));
203 } // namespace leveldb_proto
205 #endif // COMPONENTS_LEVELDB_PROTO_PROTO_DATABASE_IMPL_H_