Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: sync/internal_api/model_type_store_impl.cc

Issue 2130453004: [Sync] Move //sync to //components/sync. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
5 #include "sync/internal_api/public/model_type_store_impl.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/location.h"
11 #include "base/logging.h"
12 #include "base/memory/ptr_util.h"
13 #include "base/sequenced_task_runner.h"
14 #include "base/task_runner_util.h"
15 #include "base/threading/thread_task_runner_handle.h"
16 #include "sync/internal_api/public/model_type_store_backend.h"
17 #include "third_party/leveldatabase/src/include/leveldb/env.h"
18 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
19
20 namespace syncer_v2 {
21
22 namespace {
23
24 // Key prefix for data/metadata records.
25 const char kDataPrefix[] = "-dt-";
26 const char kMetadataPrefix[] = "-md-";
27
28 // Key for global metadata record.
29 const char kGlobalMetadataKey[] = "GlobalMetadata";
30
31 void NoOpForBackendDtor(scoped_refptr<ModelTypeStoreBackend> backend) {
32 // This function was intentionally left blank.
33 }
34
35 } // namespace
36
37 // static
38 std::string ModelTypeStoreImpl::FormatDataPrefix(const syncer::ModelType type) {
39 return std::string(syncer::GetModelTypeRootTag(type)) + kDataPrefix;
40 }
41
42 // static
43 std::string ModelTypeStoreImpl::FormatMetaPrefix(const syncer::ModelType type) {
44 return std::string(syncer::GetModelTypeRootTag(type)) + kMetadataPrefix;
45 }
46
47 // static
48 leveldb::WriteBatch* ModelTypeStoreImpl::GetLeveldbWriteBatch(
49 WriteBatch* write_batch) {
50 return static_cast<WriteBatchImpl*>(write_batch)->leveldb_write_batch_.get();
51 }
52
53 std::string ModelTypeStoreImpl::FormatDataKey(const std::string& id) {
54 return data_prefix_ + id;
55 }
56
57 std::string ModelTypeStoreImpl::FormatMetadataKey(const std::string& id) {
58 return metadata_prefix_ + id;
59 }
60
61 ModelTypeStoreImpl::ModelTypeStoreImpl(
62 const syncer::ModelType type,
63 scoped_refptr<ModelTypeStoreBackend> backend,
64 scoped_refptr<base::SequencedTaskRunner> backend_task_runner)
65 : backend_(backend),
66 backend_task_runner_(backend_task_runner),
67 data_prefix_(FormatDataPrefix(type)),
68 metadata_prefix_(FormatMetaPrefix(type)),
69 weak_ptr_factory_(this) {
70 DCHECK(backend_);
71 DCHECK(backend_task_runner_);
72 }
73
74 ModelTypeStoreImpl::~ModelTypeStoreImpl() {
75 DCHECK(CalledOnValidThread());
76 backend_task_runner_->PostTask(
77 FROM_HERE, base::Bind(&NoOpForBackendDtor, base::Passed(&backend_)));
78 }
79
80 // static
81 void ModelTypeStoreImpl::CreateStore(
82 const syncer::ModelType type,
83 const std::string& path,
84 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
85 const InitCallback& callback) {
86 DCHECK(!callback.is_null());
87 std::unique_ptr<leveldb::Env> env;
88 std::unique_ptr<Result> result(new Result());
89 auto task = base::Bind(&ModelTypeStoreBackend::GetOrCreateBackend, path,
90 base::Passed(&env), result.get());
91 auto reply =
92 base::Bind(&ModelTypeStoreImpl::BackendInitDone, type,
93 base::Passed(&result), blocking_task_runner, callback);
94
95 base::PostTaskAndReplyWithResult(blocking_task_runner.get(), FROM_HERE, task,
96 reply);
97 }
98
99 // static
100 void ModelTypeStoreImpl::CreateInMemoryStoreForTest(
101 const InitCallback& callback) {
102 DCHECK(!callback.is_null());
103
104 std::unique_ptr<leveldb::Env> env =
105 ModelTypeStoreBackend::CreateInMemoryEnv();
106
107 std::string path;
108 env->GetTestDirectory(&path);
109 path += "/in-memory";
110
111 // In-memory store backend works on the same thread as test.
112 scoped_refptr<base::SequencedTaskRunner> task_runner =
113 base::ThreadTaskRunnerHandle::Get();
114
115 std::unique_ptr<Result> result(new Result());
116
117 auto task = base::Bind(&ModelTypeStoreBackend::GetOrCreateBackend, path,
118 base::Passed(&env), result.get());
119 auto reply =
120 base::Bind(&ModelTypeStoreImpl::BackendInitDone, syncer::UNSPECIFIED,
121 base::Passed(&result), task_runner, callback);
122
123 base::PostTaskAndReplyWithResult(task_runner.get(), FROM_HERE, task, reply);
124 }
125
126 // static
127 void ModelTypeStoreImpl::BackendInitDone(
128 const syncer::ModelType type,
129 std::unique_ptr<Result> result,
130 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
131 const InitCallback& callback,
132 scoped_refptr<ModelTypeStoreBackend> backend) {
133 std::unique_ptr<ModelTypeStoreImpl> store;
134 if (*result == Result::SUCCESS) {
135 store.reset(new ModelTypeStoreImpl(type, backend, blocking_task_runner));
136 }
137
138 callback.Run(*result, std::move(store));
139 }
140
141 // Note on pattern for communicating with backend:
142 // - API function (e.g. ReadData) allocates lists for output.
143 // - API function prepares two callbacks: task that will be posted on backend
144 // thread and reply which will be posted on model type thread once task
145 // finishes.
146 // - Task for backend thread takes raw pointers to output lists while reply
147 // takes ownership of those lists. This allows backend interface to be simple
148 // while ensuring proper objects' lifetime.
149 // - Function bound by reply calls consumer's callback and passes ownership of
150 // output lists to it.
151
152 void ModelTypeStoreImpl::ReadData(const IdList& id_list,
153 const ReadDataCallback& callback) {
154 DCHECK(CalledOnValidThread());
155 DCHECK(!callback.is_null());
156 std::unique_ptr<RecordList> record_list(new RecordList());
157 std::unique_ptr<IdList> missing_id_list(new IdList());
158
159 auto task = base::Bind(&ModelTypeStoreBackend::ReadRecordsWithPrefix,
160 base::Unretained(backend_.get()), data_prefix_,
161 id_list, base::Unretained(record_list.get()),
162 base::Unretained(missing_id_list.get()));
163 auto reply = base::Bind(
164 &ModelTypeStoreImpl::ReadDataDone, weak_ptr_factory_.GetWeakPtr(),
165 callback, base::Passed(&record_list), base::Passed(&missing_id_list));
166 base::PostTaskAndReplyWithResult(backend_task_runner_.get(), FROM_HERE, task,
167 reply);
168 }
169
170 void ModelTypeStoreImpl::ReadDataDone(const ReadDataCallback& callback,
171 std::unique_ptr<RecordList> record_list,
172 std::unique_ptr<IdList> missing_id_list,
173 Result result) {
174 DCHECK(CalledOnValidThread());
175 callback.Run(result, std::move(record_list), std::move(missing_id_list));
176 }
177
178 void ModelTypeStoreImpl::ReadAllData(const ReadAllDataCallback& callback) {
179 DCHECK(CalledOnValidThread());
180 DCHECK(!callback.is_null());
181 std::unique_ptr<RecordList> record_list(new RecordList());
182 auto task = base::Bind(&ModelTypeStoreBackend::ReadAllRecordsWithPrefix,
183 base::Unretained(backend_.get()), data_prefix_,
184 base::Unretained(record_list.get()));
185 auto reply = base::Bind(&ModelTypeStoreImpl::ReadAllDataDone,
186 weak_ptr_factory_.GetWeakPtr(), callback,
187 base::Passed(&record_list));
188 base::PostTaskAndReplyWithResult(backend_task_runner_.get(), FROM_HERE, task,
189 reply);
190 }
191
192 void ModelTypeStoreImpl::ReadAllDataDone(
193 const ReadAllDataCallback& callback,
194 std::unique_ptr<RecordList> record_list,
195 Result result) {
196 DCHECK(CalledOnValidThread());
197 callback.Run(result, std::move(record_list));
198 }
199
200 void ModelTypeStoreImpl::ReadAllMetadata(const ReadMetadataCallback& callback) {
201 DCHECK(CalledOnValidThread());
202 DCHECK(!callback.is_null());
203
204 // ReadAllMetadata performs two steps sequentially: read all metadata records
205 // and then read global metadata record. Start reading metadata records here.
206 // When this read operation is done ReadMetadataRecordsDone callback will
207 // issue read operation for global metadata record.
208 std::unique_ptr<RecordList> metadata_records(new RecordList());
209 auto task = base::Bind(&ModelTypeStoreBackend::ReadAllRecordsWithPrefix,
210 base::Unretained(backend_.get()), metadata_prefix_,
211 base::Unretained(metadata_records.get()));
212 auto reply = base::Bind(&ModelTypeStoreImpl::ReadMetadataRecordsDone,
213 weak_ptr_factory_.GetWeakPtr(), callback,
214 base::Passed(&metadata_records));
215 base::PostTaskAndReplyWithResult(backend_task_runner_.get(), FROM_HERE, task,
216 reply);
217 }
218
219 void ModelTypeStoreImpl::ReadMetadataRecordsDone(
220 const ReadMetadataCallback& callback,
221 std::unique_ptr<RecordList> metadata_records,
222 Result result) {
223 DCHECK(CalledOnValidThread());
224 if (result != Result::SUCCESS) {
225 callback.Run(result, std::move(metadata_records), std::string());
226 return;
227 }
228
229 IdList global_metadata_id;
230 global_metadata_id.push_back(kGlobalMetadataKey);
231 std::unique_ptr<RecordList> global_metadata_records(new RecordList());
232 std::unique_ptr<IdList> missing_id_list(new IdList());
233 auto task = base::Bind(&ModelTypeStoreBackend::ReadRecordsWithPrefix,
234 base::Unretained(backend_.get()), std::string(),
235 global_metadata_id,
236 base::Unretained(global_metadata_records.get()),
237 base::Unretained(missing_id_list.get()));
238 auto reply = base::Bind(
239 &ModelTypeStoreImpl::ReadAllMetadataDone, weak_ptr_factory_.GetWeakPtr(),
240 callback, base::Passed(&metadata_records),
241 base::Passed(&global_metadata_records), base::Passed(&missing_id_list));
242 base::PostTaskAndReplyWithResult(backend_task_runner_.get(), FROM_HERE, task,
243 reply);
244 }
245
246 void ModelTypeStoreImpl::ReadAllMetadataDone(
247 const ReadMetadataCallback& callback,
248 std::unique_ptr<RecordList> metadata_records,
249 std::unique_ptr<RecordList> global_metadata_records,
250 std::unique_ptr<IdList> missing_id_list,
251 Result result) {
252 DCHECK(CalledOnValidThread());
253 if (result != Result::SUCCESS) {
254 callback.Run(result, std::move(metadata_records), std::string());
255 return;
256 }
257
258 if (!missing_id_list->empty()) {
259 // Missing global metadata record is not an error. We shouild return empty
260 // string in this case.
261 DCHECK((*missing_id_list)[0] == kGlobalMetadataKey);
262 DCHECK(global_metadata_records->empty());
263 callback.Run(Result::SUCCESS, std::move(metadata_records), std::string());
264 return;
265 }
266 DCHECK(!global_metadata_records->empty());
267 DCHECK((*global_metadata_records)[0].id == kGlobalMetadataKey);
268 callback.Run(Result::SUCCESS, std::move(metadata_records),
269 (*global_metadata_records)[0].value);
270 }
271
272 std::unique_ptr<ModelTypeStore::WriteBatch>
273 ModelTypeStoreImpl::CreateWriteBatch() {
274 DCHECK(CalledOnValidThread());
275 return base::WrapUnique(new WriteBatchImpl());
276 }
277
278 void ModelTypeStoreImpl::CommitWriteBatch(
279 std::unique_ptr<WriteBatch> write_batch,
280 const CallbackWithResult& callback) {
281 DCHECK(CalledOnValidThread());
282 DCHECK(!callback.is_null());
283 WriteBatchImpl* write_batch_impl =
284 static_cast<WriteBatchImpl*>(write_batch.get());
285 auto task = base::Bind(&ModelTypeStoreBackend::WriteModifications,
286 base::Unretained(backend_.get()),
287 base::Passed(&write_batch_impl->leveldb_write_batch_));
288 auto reply = base::Bind(&ModelTypeStoreImpl::WriteModificationsDone,
289 weak_ptr_factory_.GetWeakPtr(), callback);
290 base::PostTaskAndReplyWithResult(backend_task_runner_.get(), FROM_HERE, task,
291 reply);
292 }
293
294 void ModelTypeStoreImpl::WriteModificationsDone(
295 const CallbackWithResult& callback,
296 Result result) {
297 DCHECK(CalledOnValidThread());
298 callback.Run(result);
299 }
300
301 void ModelTypeStoreImpl::WriteData(WriteBatch* write_batch,
302 const std::string& id,
303 const std::string& value) {
304 DCHECK(CalledOnValidThread());
305 GetLeveldbWriteBatch(write_batch)->Put(FormatDataKey(id), value);
306 }
307
308 void ModelTypeStoreImpl::WriteMetadata(WriteBatch* write_batch,
309 const std::string& id,
310 const std::string& value) {
311 DCHECK(CalledOnValidThread());
312 GetLeveldbWriteBatch(write_batch)->Put(FormatMetadataKey(id), value);
313 }
314
315 void ModelTypeStoreImpl::WriteGlobalMetadata(WriteBatch* write_batch,
316 const std::string& value) {
317 DCHECK(CalledOnValidThread());
318 GetLeveldbWriteBatch(write_batch)->Put(kGlobalMetadataKey, value);
319 }
320
321 void ModelTypeStoreImpl::DeleteData(WriteBatch* write_batch,
322 const std::string& id) {
323 DCHECK(CalledOnValidThread());
324 GetLeveldbWriteBatch(write_batch)->Delete(FormatDataKey(id));
325 }
326
327 void ModelTypeStoreImpl::DeleteMetadata(WriteBatch* write_batch,
328 const std::string& id) {
329 DCHECK(CalledOnValidThread());
330 GetLeveldbWriteBatch(write_batch)->Delete(FormatMetadataKey(id));
331 }
332
333 void ModelTypeStoreImpl::DeleteGlobalMetadata(WriteBatch* write_batch) {
334 DCHECK(CalledOnValidThread());
335 GetLeveldbWriteBatch(write_batch)->Delete(kGlobalMetadataKey);
336 }
337
338 ModelTypeStoreImpl::WriteBatchImpl::WriteBatchImpl() {
339 leveldb_write_batch_.reset(new leveldb::WriteBatch());
340 }
341
342 ModelTypeStoreImpl::WriteBatchImpl::~WriteBatchImpl() {}
343
344 } // namespace syncer_v2
OLDNEW
« no previous file with comments | « sync/internal_api/model_type_store_backend_unittest.cc ('k') | sync/internal_api/model_type_store_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698