• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "sync/syncable/syncable_delete_journal.h"
6 
7 #include "base/stl_util.h"
8 #include "sync/internal_api/public/base/model_type.h"
9 
10 namespace syncer {
11 namespace syncable {
12 
DeleteJournal(JournalIndex * initial_journal)13 DeleteJournal::DeleteJournal(JournalIndex* initial_journal) {
14   CHECK(initial_journal);
15   delete_journals_.swap(*initial_journal);
16 }
17 
~DeleteJournal()18 DeleteJournal::~DeleteJournal() {
19   STLDeleteElements(&delete_journals_);
20 }
21 
GetDeleteJournalSize(BaseTransaction * trans) const22 size_t DeleteJournal::GetDeleteJournalSize(BaseTransaction* trans) const {
23   DCHECK(trans);
24   return delete_journals_.size();
25 }
26 
UpdateDeleteJournalForServerDelete(BaseTransaction * trans,bool was_deleted,const EntryKernel & entry)27 void DeleteJournal::UpdateDeleteJournalForServerDelete(
28     BaseTransaction* trans, bool was_deleted, const EntryKernel& entry) {
29   DCHECK(trans);
30 
31   // Should be sufficient to check server type only but check for local
32   // type too because of incomplete test setup.
33   if (!(IsDeleteJournalEnabled(entry.GetServerModelType()) ||
34       IsDeleteJournalEnabled(
35           GetModelTypeFromSpecifics(entry.ref(SPECIFICS))))) {
36     return;
37   }
38 
39   JournalIndex::iterator it = delete_journals_.find(&entry);
40 
41   if (entry.ref(SERVER_IS_DEL)) {
42     if (it == delete_journals_.end()) {
43       // New delete.
44       EntryKernel* t = new EntryKernel(entry);
45       delete_journals_.insert(t);
46       delete_journals_to_purge_.erase(t->ref(META_HANDLE));
47     }
48   } else {
49     // Undelete. This could happen in two cases:
50     // * An entry was deleted then undeleted, i.e. server delete was
51     //   overwritten because of entry has unsynced data locally.
52     // * A data type was broken, i.e. encountered unrecoverable error, in last
53     //   sync session and all its entries were duplicated in delete journals.
54     //   On restart, entries are recreated from downloads and recreation calls
55     //   UpdateDeleteJournals() to remove live entries from delete journals,
56     //   thus only deleted entries remain in journals.
57     if (it != delete_journals_.end()) {
58       delete_journals_to_purge_.insert((*it)->ref(META_HANDLE));
59       delete *it;
60       delete_journals_.erase(it);
61     } else if (was_deleted) {
62       delete_journals_to_purge_.insert(entry.ref(META_HANDLE));
63     }
64   }
65 }
66 
GetDeleteJournals(BaseTransaction * trans,ModelType type,EntryKernelSet * deleted_entries)67 void DeleteJournal::GetDeleteJournals(BaseTransaction* trans,
68                                       ModelType type,
69                                       EntryKernelSet* deleted_entries) {
70   DCHECK(trans);
71   for (JournalIndex::const_iterator it = delete_journals_.begin();
72       it != delete_journals_.end(); ++it) {
73     if ((*it)->GetServerModelType() == type ||
74         GetModelTypeFromSpecifics((*it)->ref(SPECIFICS)) == type) {
75       deleted_entries->insert(*it);
76     }
77   }
78   passive_delete_journal_types_.Put(type);
79 }
80 
PurgeDeleteJournals(BaseTransaction * trans,const MetahandleSet & to_purge)81 void DeleteJournal::PurgeDeleteJournals(BaseTransaction* trans,
82                                         const MetahandleSet& to_purge) {
83   DCHECK(trans);
84   JournalIndex::iterator it = delete_journals_.begin();
85   while (it != delete_journals_.end()) {
86     int64 handle = (*it)->ref(META_HANDLE);
87     if (to_purge.count(handle)) {
88       delete *it;
89       delete_journals_.erase(it++);
90     } else {
91       ++it;
92     }
93   }
94   delete_journals_to_purge_.insert(to_purge.begin(), to_purge.end());
95 }
96 
TakeSnapshotAndClear(BaseTransaction * trans,EntryKernelSet * journal_entries,MetahandleSet * journals_to_purge)97 void DeleteJournal::TakeSnapshotAndClear(BaseTransaction* trans,
98                                          EntryKernelSet* journal_entries,
99                                          MetahandleSet* journals_to_purge) {
100   DCHECK(trans);
101   // Move passive delete journals to snapshot. Will copy back if snapshot fails
102   // to save.
103   JournalIndex::iterator it = delete_journals_.begin();
104   while (it != delete_journals_.end()) {
105     if (passive_delete_journal_types_.Has((*it)->GetServerModelType()) ||
106         passive_delete_journal_types_.Has(GetModelTypeFromSpecifics(
107             (*it)->ref(SPECIFICS)))) {
108       journal_entries->insert(*it);
109       delete_journals_.erase(it++);
110     } else {
111       ++it;
112     }
113   }
114   *journals_to_purge = delete_journals_to_purge_;
115   delete_journals_to_purge_.clear();
116 }
117 
AddJournalBatch(BaseTransaction * trans,const EntryKernelSet & entries)118 void DeleteJournal::AddJournalBatch(BaseTransaction* trans,
119                                     const EntryKernelSet& entries) {
120   DCHECK(trans);
121   EntryKernel needle;
122   for (EntryKernelSet::const_iterator i = entries.begin();
123        i != entries.end(); ++i) {
124     needle.put(ID, (*i)->ref(ID));
125     if (delete_journals_.find(&needle) == delete_journals_.end()) {
126       delete_journals_.insert(new EntryKernel(**i));
127     }
128     delete_journals_to_purge_.erase((*i)->ref(META_HANDLE));
129   }
130 }
131 
132 /* static */
IsDeleteJournalEnabled(ModelType type)133 bool DeleteJournal::IsDeleteJournalEnabled(ModelType type) {
134   switch (type) {
135     case BOOKMARKS:
136       return true;
137     default:
138       return false;
139   }
140 }
141 
142 }  // namespace syncable
143 }  // namespace syncer
144