OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/dom_distiller/core/dom_distiller_store.h" | 5 #include "components/dom_distiller/core/dom_distiller_store.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "components/dom_distiller/core/article_entry.h" | 9 #include "components/dom_distiller/core/article_entry.h" |
10 #include "sync/api/sync_change.h" | 10 #include "sync/api/sync_change.h" |
11 #include "sync/protocol/article_specifics.pb.h" | 11 #include "sync/protocol/article_specifics.pb.h" |
12 #include "sync/protocol/sync.pb.h" | 12 #include "sync/protocol/sync.pb.h" |
13 | 13 |
| 14 using leveldb_proto::ProtoDatabase; |
14 using sync_pb::ArticleSpecifics; | 15 using sync_pb::ArticleSpecifics; |
15 using sync_pb::EntitySpecifics; | 16 using sync_pb::EntitySpecifics; |
16 using syncer::ModelType; | 17 using syncer::ModelType; |
17 using syncer::SyncChange; | 18 using syncer::SyncChange; |
18 using syncer::SyncChangeList; | 19 using syncer::SyncChangeList; |
19 using syncer::SyncData; | 20 using syncer::SyncData; |
20 using syncer::SyncDataList; | 21 using syncer::SyncDataList; |
21 using syncer::SyncError; | 22 using syncer::SyncError; |
22 using syncer::SyncMergeResult; | 23 using syncer::SyncMergeResult; |
23 | 24 |
24 namespace dom_distiller { | 25 namespace dom_distiller { |
25 | 26 |
26 DomDistillerStore::DomDistillerStore( | 27 DomDistillerStore::DomDistillerStore( |
27 scoped_ptr<DomDistillerDatabaseInterface> database, | 28 scoped_ptr<ProtoDatabase<ArticleEntry> > database, |
28 const base::FilePath& database_dir) | 29 const base::FilePath& database_dir) |
29 : database_(database.Pass()), | 30 : database_(database.Pass()), |
30 database_loaded_(false), | 31 database_loaded_(false), |
31 weak_ptr_factory_(this) { | 32 weak_ptr_factory_(this) { |
32 database_->Init(database_dir, | 33 database_->Init(database_dir, base::Bind(&DomDistillerStore::OnDatabaseInit, |
33 base::Bind(&DomDistillerStore::OnDatabaseInit, | 34 weak_ptr_factory_.GetWeakPtr())); |
34 weak_ptr_factory_.GetWeakPtr())); | |
35 } | 35 } |
36 | 36 |
37 DomDistillerStore::DomDistillerStore( | 37 DomDistillerStore::DomDistillerStore( |
38 scoped_ptr<DomDistillerDatabaseInterface> database, | 38 scoped_ptr<ProtoDatabase<ArticleEntry> > database, |
39 const std::vector<ArticleEntry>& initial_data, | 39 const std::vector<ArticleEntry>& initial_data, |
40 const base::FilePath& database_dir) | 40 const base::FilePath& database_dir) |
41 : database_(database.Pass()), | 41 : database_(database.Pass()), |
42 database_loaded_(false), | 42 database_loaded_(false), |
43 model_(initial_data), | 43 model_(initial_data), |
44 weak_ptr_factory_(this) { | 44 weak_ptr_factory_(this) { |
45 database_->Init(database_dir, | 45 database_->Init(database_dir, base::Bind(&DomDistillerStore::OnDatabaseInit, |
46 base::Bind(&DomDistillerStore::OnDatabaseInit, | 46 weak_ptr_factory_.GetWeakPtr())); |
47 weak_ptr_factory_.GetWeakPtr())); | |
48 } | 47 } |
49 | 48 |
50 DomDistillerStore::~DomDistillerStore() {} | 49 DomDistillerStore::~DomDistillerStore() {} |
51 | 50 |
52 // DomDistillerStoreInterface implementation. | 51 // DomDistillerStoreInterface implementation. |
53 syncer::SyncableService* DomDistillerStore::GetSyncableService() { | 52 syncer::SyncableService* DomDistillerStore::GetSyncableService() { |
54 return this; | 53 return this; |
55 } | 54 } |
56 | 55 |
57 bool DomDistillerStore::GetEntryById(const std::string& entry_id, | 56 bool DomDistillerStore::GetEntryById(const std::string& entry_id, |
58 ArticleEntry* entry) { | 57 ArticleEntry* entry) { |
59 return model_.GetEntryById(entry_id, entry); | 58 return model_.GetEntryById(entry_id, entry); |
60 } | 59 } |
61 | 60 |
62 bool DomDistillerStore::GetEntryByUrl(const GURL& url, | 61 bool DomDistillerStore::GetEntryByUrl(const GURL& url, ArticleEntry* entry) { |
63 ArticleEntry* entry) { | |
64 return model_.GetEntryByUrl(url, entry); | 62 return model_.GetEntryByUrl(url, entry); |
65 } | 63 } |
66 | 64 |
67 | |
68 bool DomDistillerStore::AddEntry(const ArticleEntry& entry) { | 65 bool DomDistillerStore::AddEntry(const ArticleEntry& entry) { |
69 if (!database_loaded_) { | 66 if (!database_loaded_) { |
70 return false; | 67 return false; |
71 } | 68 } |
72 | 69 |
73 if (model_.GetEntryById(entry.entry_id(), NULL)) { | 70 if (model_.GetEntryById(entry.entry_id(), NULL)) { |
74 DVLOG(1) << "Already have entry with id " << entry.entry_id() << "."; | 71 DVLOG(1) << "Already have entry with id " << entry.entry_id() << "."; |
75 return false; | 72 return false; |
76 } | 73 } |
77 | 74 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 void DomDistillerStore::RemoveObserver(DomDistillerObserver* observer) { | 155 void DomDistillerStore::RemoveObserver(DomDistillerObserver* observer) { |
159 observers_.RemoveObserver(observer); | 156 observers_.RemoveObserver(observer); |
160 } | 157 } |
161 | 158 |
162 std::vector<ArticleEntry> DomDistillerStore::GetEntries() const { | 159 std::vector<ArticleEntry> DomDistillerStore::GetEntries() const { |
163 return model_.GetEntries(); | 160 return model_.GetEntries(); |
164 } | 161 } |
165 | 162 |
166 // syncer::SyncableService implementation. | 163 // syncer::SyncableService implementation. |
167 SyncMergeResult DomDistillerStore::MergeDataAndStartSyncing( | 164 SyncMergeResult DomDistillerStore::MergeDataAndStartSyncing( |
168 ModelType type, | 165 ModelType type, const SyncDataList& initial_sync_data, |
169 const SyncDataList& initial_sync_data, | |
170 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, | 166 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, |
171 scoped_ptr<syncer::SyncErrorFactory> error_handler) { | 167 scoped_ptr<syncer::SyncErrorFactory> error_handler) { |
172 DCHECK_EQ(syncer::ARTICLES, type); | 168 DCHECK_EQ(syncer::ARTICLES, type); |
173 DCHECK(!sync_processor_); | 169 DCHECK(!sync_processor_); |
174 DCHECK(!error_factory_); | 170 DCHECK(!error_factory_); |
175 sync_processor_.reset(sync_processor.release()); | 171 sync_processor_.reset(sync_processor.release()); |
176 error_factory_.reset(error_handler.release()); | 172 error_factory_.reset(error_handler.release()); |
177 | 173 |
178 SyncChangeList database_changes; | 174 SyncChangeList database_changes; |
179 SyncChangeList sync_changes; | 175 SyncChangeList sync_changes; |
(...skipping 23 matching lines...) Expand all Loading... |
203 ApplyChangesToModel(change_list, &database_changes, &sync_changes); | 199 ApplyChangesToModel(change_list, &database_changes, &sync_changes); |
204 ApplyChangesToDatabase(database_changes); | 200 ApplyChangesToDatabase(database_changes); |
205 DCHECK_EQ(size_t(0), sync_changes.size()); | 201 DCHECK_EQ(size_t(0), sync_changes.size()); |
206 return SyncError(); | 202 return SyncError(); |
207 } | 203 } |
208 | 204 |
209 void DomDistillerStore::NotifyObservers(const syncer::SyncChangeList& changes) { | 205 void DomDistillerStore::NotifyObservers(const syncer::SyncChangeList& changes) { |
210 if (observers_.might_have_observers() && changes.size() > 0) { | 206 if (observers_.might_have_observers() && changes.size() > 0) { |
211 std::vector<DomDistillerObserver::ArticleUpdate> article_changes; | 207 std::vector<DomDistillerObserver::ArticleUpdate> article_changes; |
212 for (SyncChangeList::const_iterator it = changes.begin(); | 208 for (SyncChangeList::const_iterator it = changes.begin(); |
213 it != changes.end(); | 209 it != changes.end(); ++it) { |
214 ++it) { | |
215 DomDistillerObserver::ArticleUpdate article_update; | 210 DomDistillerObserver::ArticleUpdate article_update; |
216 switch (it->change_type()) { | 211 switch (it->change_type()) { |
217 case SyncChange::ACTION_ADD: | 212 case SyncChange::ACTION_ADD: |
218 article_update.update_type = DomDistillerObserver::ArticleUpdate::ADD; | 213 article_update.update_type = DomDistillerObserver::ArticleUpdate::ADD; |
219 break; | 214 break; |
220 case SyncChange::ACTION_UPDATE: | 215 case SyncChange::ACTION_UPDATE: |
221 article_update.update_type = | 216 article_update.update_type = |
222 DomDistillerObserver::ArticleUpdate::UPDATE; | 217 DomDistillerObserver::ArticleUpdate::UPDATE; |
223 break; | 218 break; |
224 case SyncChange::ACTION_DELETE: | 219 case SyncChange::ACTION_DELETE: |
225 article_update.update_type = | 220 article_update.update_type = |
226 DomDistillerObserver::ArticleUpdate::REMOVE; | 221 DomDistillerObserver::ArticleUpdate::REMOVE; |
227 break; | 222 break; |
228 case SyncChange::ACTION_INVALID: | 223 case SyncChange::ACTION_INVALID: |
229 NOTREACHED(); | 224 NOTREACHED(); |
230 break; | 225 break; |
231 } | 226 } |
232 const ArticleEntry& entry = GetEntryFromChange(*it); | 227 const ArticleEntry& entry = GetEntryFromChange(*it); |
233 article_update.entry_id = entry.entry_id(); | 228 article_update.entry_id = entry.entry_id(); |
234 article_changes.push_back(article_update); | 229 article_changes.push_back(article_update); |
235 } | 230 } |
236 FOR_EACH_OBSERVER(DomDistillerObserver, | 231 FOR_EACH_OBSERVER(DomDistillerObserver, observers_, |
237 observers_, | |
238 ArticleEntriesUpdated(article_changes)); | 232 ArticleEntriesUpdated(article_changes)); |
239 } | 233 } |
240 } | 234 } |
241 | 235 |
242 void DomDistillerStore::ApplyChangesToModel( | 236 void DomDistillerStore::ApplyChangesToModel(const SyncChangeList& changes, |
243 const SyncChangeList& changes, | 237 SyncChangeList* changes_applied, |
244 SyncChangeList* changes_applied, | 238 SyncChangeList* changes_missing) { |
245 SyncChangeList* changes_missing) { | |
246 model_.ApplyChangesToModel(changes, changes_applied, changes_missing); | 239 model_.ApplyChangesToModel(changes, changes_applied, changes_missing); |
247 NotifyObservers(*changes_applied); | 240 NotifyObservers(*changes_applied); |
248 } | 241 } |
249 | 242 |
250 void DomDistillerStore::OnDatabaseInit(bool success) { | 243 void DomDistillerStore::OnDatabaseInit(bool success) { |
251 if (!success) { | 244 if (!success) { |
252 DVLOG(1) << "DOM Distiller database init failed."; | 245 DVLOG(1) << "DOM Distiller database init failed."; |
253 database_.reset(); | 246 database_.reset(); |
254 return; | 247 return; |
255 } | 248 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 } | 299 } |
307 | 300 |
308 bool DomDistillerStore::ApplyChangesToDatabase( | 301 bool DomDistillerStore::ApplyChangesToDatabase( |
309 const SyncChangeList& change_list) { | 302 const SyncChangeList& change_list) { |
310 if (!database_loaded_) { | 303 if (!database_loaded_) { |
311 return false; | 304 return false; |
312 } | 305 } |
313 if (change_list.empty()) { | 306 if (change_list.empty()) { |
314 return true; | 307 return true; |
315 } | 308 } |
316 scoped_ptr<EntryVector> entries_to_save(new EntryVector()); | 309 scoped_ptr<ProtoDatabase<ArticleEntry>::KeyEntryVector> entries_to_save( |
317 scoped_ptr<EntryVector> entries_to_remove(new EntryVector()); | 310 new ProtoDatabase<ArticleEntry>::KeyEntryVector()); |
| 311 scoped_ptr<std::vector<std::string> > keys_to_remove( |
| 312 new std::vector<std::string>()); |
318 | 313 |
319 for (SyncChangeList::const_iterator it = change_list.begin(); | 314 for (SyncChangeList::const_iterator it = change_list.begin(); |
320 it != change_list.end(); | 315 it != change_list.end(); ++it) { |
321 ++it) { | 316 if (it->change_type() == SyncChange::ACTION_DELETE) { |
322 if (it->change_type() == SyncChange::ACTION_DELETE) | 317 ArticleEntry entry = GetEntryFromChange(*it); |
323 entries_to_remove->push_back(GetEntryFromChange(*it)); | 318 keys_to_remove->push_back(entry.entry_id()); |
324 else | 319 } else { |
325 entries_to_save->push_back(GetEntryFromChange(*it)); | 320 ArticleEntry entry = GetEntryFromChange(*it); |
| 321 entries_to_save->push_back(std::make_pair(entry.entry_id(), entry)); |
| 322 } |
326 } | 323 } |
327 database_->UpdateEntries(entries_to_save.Pass(), | 324 database_->UpdateEntries(entries_to_save.Pass(), keys_to_remove.Pass(), |
328 entries_to_remove.Pass(), | |
329 base::Bind(&DomDistillerStore::OnDatabaseSave, | 325 base::Bind(&DomDistillerStore::OnDatabaseSave, |
330 weak_ptr_factory_.GetWeakPtr())); | 326 weak_ptr_factory_.GetWeakPtr())); |
331 return true; | 327 return true; |
332 } | 328 } |
333 | 329 |
334 SyncMergeResult DomDistillerStore::MergeDataWithModel( | 330 SyncMergeResult DomDistillerStore::MergeDataWithModel( |
335 const SyncDataList& data, | 331 const SyncDataList& data, SyncChangeList* changes_applied, |
336 SyncChangeList* changes_applied, | |
337 SyncChangeList* changes_missing) { | 332 SyncChangeList* changes_missing) { |
338 DCHECK(changes_applied); | 333 DCHECK(changes_applied); |
339 DCHECK(changes_missing); | 334 DCHECK(changes_missing); |
340 | 335 |
341 SyncMergeResult result(syncer::ARTICLES); | 336 SyncMergeResult result(syncer::ARTICLES); |
342 result.set_num_items_before_association(model_.GetNumEntries()); | 337 result.set_num_items_before_association(model_.GetNumEntries()); |
343 | 338 |
344 SyncChangeList changes_to_apply; | 339 SyncChangeList changes_to_apply; |
345 model_.CalculateChangesForMerge(data, &changes_to_apply, changes_missing); | 340 model_.CalculateChangesForMerge(data, &changes_to_apply, changes_missing); |
346 SyncError error; | 341 SyncError error; |
347 ApplyChangesToModel(changes_to_apply, changes_applied, changes_missing); | 342 ApplyChangesToModel(changes_to_apply, changes_applied, changes_missing); |
348 | 343 |
349 int num_added = 0; | 344 int num_added = 0; |
350 int num_modified = 0; | 345 int num_modified = 0; |
351 for (SyncChangeList::const_iterator it = changes_applied->begin(); | 346 for (SyncChangeList::const_iterator it = changes_applied->begin(); |
352 it != changes_applied->end(); | 347 it != changes_applied->end(); ++it) { |
353 ++it) { | |
354 DCHECK(it->IsValid()); | 348 DCHECK(it->IsValid()); |
355 switch (it->change_type()) { | 349 switch (it->change_type()) { |
356 case SyncChange::ACTION_ADD: | 350 case SyncChange::ACTION_ADD: |
357 num_added++; | 351 num_added++; |
358 break; | 352 break; |
359 case SyncChange::ACTION_UPDATE: | 353 case SyncChange::ACTION_UPDATE: |
360 num_modified++; | 354 num_modified++; |
361 break; | 355 break; |
362 default: | 356 default: |
363 NOTREACHED(); | 357 NOTREACHED(); |
364 } | 358 } |
365 } | 359 } |
366 result.set_num_items_added(num_added); | 360 result.set_num_items_added(num_added); |
367 result.set_num_items_modified(num_modified); | 361 result.set_num_items_modified(num_modified); |
368 result.set_num_items_deleted(0); | 362 result.set_num_items_deleted(0); |
369 | 363 |
370 result.set_pre_association_version(0); | 364 result.set_pre_association_version(0); |
371 result.set_num_items_after_association(model_.GetNumEntries()); | 365 result.set_num_items_after_association(model_.GetNumEntries()); |
372 result.set_error(error); | 366 result.set_error(error); |
373 | 367 |
374 return result; | 368 return result; |
375 } | 369 } |
376 | 370 |
377 } // namespace dom_distiller | 371 } // namespace dom_distiller |
OLD | NEW |