Index: sync/syncable/delete_journal.cc |
diff --git a/sync/syncable/delete_journal.cc b/sync/syncable/delete_journal.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..94506709d2df7b515d534fa3d4c2bbc717e8360b |
--- /dev/null |
+++ b/sync/syncable/delete_journal.cc |
@@ -0,0 +1,144 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "sync/syncable/delete_journal.h" |
+ |
+#include "base/stl_util.h" |
+#include "sync/internal_api/public/base/model_type.h" |
+ |
+namespace syncer { |
+namespace syncable { |
+ |
+DeleteJournal::DeleteJournal(JournalIndex* initial_journal) { |
+ CHECK(initial_journal); |
+ delete_journals_.swap(*initial_journal); |
+} |
+ |
+DeleteJournal::~DeleteJournal() { |
+ STLDeleteElements(&delete_journals_); |
+} |
+ |
+size_t DeleteJournal::GetDeleteJournalSize(BaseTransaction* trans) const { |
+ DCHECK(trans); |
+ return delete_journals_.size(); |
+} |
+ |
+void DeleteJournal::UpdateDeleteJournalForServerDelete( |
+ BaseTransaction* trans, bool was_deleted, const EntryKernel& entry) { |
+ DCHECK(trans); |
+ |
+ // Should be sufficient to check server type only but check for local |
+ // type too because of incomplete test setup. |
+ if (!(IsDeleteJournalEnabled(entry.GetServerModelType()) || |
+ IsDeleteJournalEnabled( |
+ GetModelTypeFromSpecifics(entry.ref(SPECIFICS))))) { |
+ return; |
+ } |
+ |
+ JournalIndex::iterator it = delete_journals_.find(&entry); |
+ |
+ if (entry.ref(SERVER_IS_DEL)) { |
+ if (it == delete_journals_.end()) { |
+ // New delete. |
+ EntryKernel* t = new EntryKernel(entry); |
+ delete_journals_.insert(t); |
+ delete_journals_to_purge_.erase(t->ref(META_HANDLE)); |
+ } |
+ } else { |
+ // Undelete. This could happen in two cases: |
+ // * An entry was deleted then undeleted, i.e. server delete was |
+ // overwritten because of entry has unsynced data locally. |
+ // * A data type was broken, i.e. encountered unrecoverable error, in last |
+ // sync session and all its entries were duplicated in delete journals. |
+ // On restart, entries are recreated from downloads and recreation calls |
+ // UpdateDeleteJournals() to remove live entries from delete journals, |
+ // thus only deleted entries remain in journals. |
+ if (it != delete_journals_.end()) { |
+ delete_journals_to_purge_.insert((*it)->ref(META_HANDLE)); |
+ delete *it; |
+ delete_journals_.erase(it); |
+ } else if (was_deleted) { |
+ delete_journals_to_purge_.insert(entry.ref(META_HANDLE)); |
+ } |
+ } |
+} |
+ |
+void DeleteJournal::GetDeleteJournals(BaseTransaction* trans, |
+ ModelType type, |
+ EntryKernelSet* deleted_entries) { |
+ DCHECK(trans); |
+ DCHECK(!passive_delete_journal_types_.Has(type)); |
+ for (JournalIndex::const_iterator it = delete_journals_.begin(); |
+ it != delete_journals_.end(); ++it) { |
+ if ((*it)->GetServerModelType() == type || |
+ GetModelTypeFromSpecifics((*it)->ref(SPECIFICS)) == type) { |
+ deleted_entries->insert(*it); |
+ } |
+ } |
+ passive_delete_journal_types_.Put(type); |
+} |
+ |
+void DeleteJournal::PurgeDeleteJournals(BaseTransaction* trans, |
+ const MetahandleSet& to_purge) { |
+ DCHECK(trans); |
+ JournalIndex::iterator it = delete_journals_.begin(); |
+ while (it != delete_journals_.end()) { |
+ int64 handle = (*it)->ref(META_HANDLE); |
+ if (to_purge.count(handle)) { |
+ delete *it; |
+ delete_journals_.erase(it++); |
+ } else { |
+ ++it; |
+ } |
+ } |
+ delete_journals_to_purge_.insert(to_purge.begin(), to_purge.end()); |
+} |
+ |
+void DeleteJournal::TakeSnapshotAndClear(BaseTransaction* trans, |
+ EntryKernelSet* journal_entries, |
+ MetahandleSet* journals_to_purge) { |
+ DCHECK(trans); |
+ // Move passive delete journals to snapshot. Will copy back if snapshot fails |
+ // to save. |
+ JournalIndex::iterator it = delete_journals_.begin(); |
+ while (it != delete_journals_.end()) { |
+ if (passive_delete_journal_types_.Has((*it)->GetServerModelType()) || |
+ passive_delete_journal_types_.Has(GetModelTypeFromSpecifics( |
+ (*it)->ref(SPECIFICS)))) { |
+ journal_entries->insert(*it); |
+ delete_journals_.erase(it++); |
+ } else { |
+ ++it; |
+ } |
+ } |
+ *journals_to_purge = delete_journals_to_purge_; |
+ delete_journals_to_purge_.clear(); |
+} |
+ |
+void DeleteJournal::AddJournalBatch(BaseTransaction* trans, |
+ const EntryKernelSet& entries) { |
+ DCHECK(trans); |
+ EntryKernel needle; |
+ for (EntryKernelSet::const_iterator i = entries.begin(); |
+ i != entries.end(); ++i) { |
+ needle.put(ID, (*i)->ref(ID)); |
+ if (delete_journals_.find(&needle) == delete_journals_.end()) { |
+ delete_journals_.insert(new EntryKernel(**i)); |
+ } |
+ delete_journals_to_purge_.erase((*i)->ref(META_HANDLE)); |
+ } |
+} |
+ |
+/* static */ |
+bool DeleteJournal::IsDeleteJournalEnabled(ModelType type) { |
+ switch (type) { |
+ case BOOKMARKS: |
+ return true; |
+ default: |
+ return false; |
+ } |
+} |
+ |
+} // namespace syncable |
+} // namespace syncer |