Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / components / leveldb_proto / proto_database_impl.h
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
5 #ifndef COMPONENTS_LEVELDB_PROTO_PROTO_DATABASE_IMPL_H_
6 #define COMPONENTS_LEVELDB_PROTO_PROTO_DATABASE_IMPL_H_
7
8 #include <string>
9 #include <vector>
10
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"
22
23 namespace leveldb_proto {
24
25 typedef base::StringPairs KeyValueVector;
26 typedef std::vector<std::string> KeyVector;
27
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);
37
38   virtual ~ProtoDatabaseImpl();
39
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;
51
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);
56
57  private:
58   base::ThreadChecker thread_checker_;
59
60   // Used to run blocking tasks in-order.
61   scoped_refptr<base::SequencedTaskRunner> task_runner_;
62
63   scoped_ptr<LevelDB> db_;
64
65   DISALLOW_COPY_AND_ASSIGN(ProtoDatabaseImpl);
66 };
67
68 namespace {
69
70 template <typename T>
71 void RunInitCallback(typename ProtoDatabase<T>::InitCallback callback,
72                      const bool* success) {
73   callback.Run(*success);
74 }
75
76 template <typename T>
77 void RunUpdateCallback(typename ProtoDatabase<T>::UpdateCallback callback,
78                        const bool* success) {
79   callback.Run(*success);
80 }
81
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());
86 }
87
88 void InitFromTaskRunner(LevelDB* database, const base::FilePath& database_dir,
89                         bool* success) {
90   DCHECK(success);
91
92   // TODO(cjhopman): Histogram for database size.
93   *success = database->Init(database_dir);
94 }
95
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()));
109   }
110   *success = database->Save(pairs_to_save, *keys_to_remove);
111 }
112
113 template <typename T>
114 void LoadEntriesFromTaskRunner(LevelDB* database, std::vector<T>* entries,
115                                bool* success) {
116   DCHECK(success);
117   DCHECK(entries);
118
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.
128     }
129     entries->push_back(entry);
130   }
131 }
132
133 }  // namespace
134
135 template <typename T>
136 ProtoDatabaseImpl<T>::ProtoDatabaseImpl(
137     scoped_refptr<base::SequencedTaskRunner> task_runner)
138     : task_runner_(task_runner) {}
139
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.";
145   }
146 }
147
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);
154 }
155
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)));
169 }
170
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)));
184 }
185
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);
191
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();
195
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)));
201 }
202
203 }  // namespace leveldb_proto
204
205 #endif  // COMPONENTS_LEVELDB_PROTO_PROTO_DATABASE_IMPL_H_