Index: chrome/browser/sync/engine/build_and_process_conflict_sets_command.cc |
diff --git a/chrome/browser/sync/engine/build_and_process_conflict_sets_command.cc b/chrome/browser/sync/engine/build_and_process_conflict_sets_command.cc |
deleted file mode 100644 |
index 3db89f0c6b8323a1d0ff9f11ea7c126a5af56ff8..0000000000000000000000000000000000000000 |
--- a/chrome/browser/sync/engine/build_and_process_conflict_sets_command.cc |
+++ /dev/null |
@@ -1,238 +0,0 @@ |
-// 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 "chrome/browser/sync/engine/build_and_process_conflict_sets_command.h" |
- |
-#include <set> |
-#include <string> |
-#include <sstream> |
-#include <vector> |
- |
-#include "base/basictypes.h" |
-#include "base/format_macros.h" |
-#include "base/location.h" |
-#include "chrome/browser/sync/engine/syncer_util.h" |
-#include "chrome/browser/sync/engine/update_applicator.h" |
-#include "chrome/browser/sync/sessions/sync_session.h" |
-#include "chrome/browser/sync/syncable/directory_manager.h" |
- |
-namespace browser_sync { |
- |
-using sessions::ConflictProgress; |
-using sessions::StatusController; |
-using sessions::SyncSession; |
-using sessions::UpdateProgress; |
-using std::set; |
-using std::string; |
-using std::vector; |
- |
-BuildAndProcessConflictSetsCommand::BuildAndProcessConflictSetsCommand() {} |
-BuildAndProcessConflictSetsCommand::~BuildAndProcessConflictSetsCommand() {} |
- |
-std::set<ModelSafeGroup> BuildAndProcessConflictSetsCommand::GetGroupsToChange( |
- const sessions::SyncSession& session) const { |
- return session.GetEnabledGroupsWithConflicts(); |
-} |
- |
-SyncerError BuildAndProcessConflictSetsCommand::ModelChangingExecuteImpl( |
- SyncSession* session) { |
- syncable::ScopedDirLookup dir(session->context()->directory_manager(), |
- session->context()->account_name()); |
- if (!dir.good()) |
- return DIRECTORY_LOOKUP_FAILED; |
- |
- syncable::WriteTransaction trans(FROM_HERE, syncable::SYNCER, dir); |
- BuildConflictSets(&trans, |
- session->mutable_status_controller()->mutable_conflict_progress()); |
- |
- return SYNCER_OK; |
-} |
- |
-void BuildAndProcessConflictSetsCommand::BuildConflictSets( |
- syncable::BaseTransaction* trans, |
- ConflictProgress* conflict_progress) { |
- conflict_progress->CleanupSets(); |
- set<syncable::Id>::const_iterator i = |
- conflict_progress->ConflictingItemsBegin(); |
- while (i != conflict_progress->ConflictingItemsEnd()) { |
- syncable::Entry entry(trans, syncable::GET_BY_ID, *i); |
- if (!entry.good() || |
- (!entry.Get(syncable::IS_UNSYNCED) && |
- !entry.Get(syncable::IS_UNAPPLIED_UPDATE))) { |
- // This can happen very rarely. It means we had a simply conflicting item |
- // that randomly committed; its ID could have changed during the commit. |
- // We drop the entry as it's no longer conflicting. |
- conflict_progress->EraseConflictingItemById(*(i++)); |
- continue; |
- } |
- if (entry.ExistsOnClientBecauseNameIsNonEmpty() && |
- (entry.Get(syncable::IS_DEL) || entry.Get(syncable::SERVER_IS_DEL))) { |
- // If we're deleted on client or server we can't be in a complex set. |
- ++i; |
- continue; |
- } |
- bool new_parent = |
- entry.Get(syncable::PARENT_ID) != entry.Get(syncable::SERVER_PARENT_ID); |
- if (new_parent) |
- MergeSetsForIntroducedLoops(trans, &entry, conflict_progress); |
- MergeSetsForNonEmptyDirectories(trans, &entry, conflict_progress); |
- ++i; |
- } |
-} |
- |
-void BuildAndProcessConflictSetsCommand::MergeSetsForIntroducedLoops( |
- syncable::BaseTransaction* trans, syncable::Entry* entry, |
- ConflictProgress* conflict_progress) { |
- // This code crawls up from the item in question until it gets to the root |
- // or itself. If it gets to the root it does nothing. If it finds a loop all |
- // moved unsynced entries in the list of crawled entries have their sets |
- // merged with the entry. |
- // TODO(sync): Build test cases to cover this function when the argument list |
- // has settled. |
- syncable::Id parent_id = entry->Get(syncable::SERVER_PARENT_ID); |
- syncable::Entry parent(trans, syncable::GET_BY_ID, parent_id); |
- if (!parent.good()) { |
- return; |
- } |
- // Don't check for loop if the server parent is deleted. |
- if (parent.Get(syncable::IS_DEL)) |
- return; |
- vector<syncable::Id> conflicting_entries; |
- while (!parent_id.IsRoot()) { |
- syncable::Entry parent(trans, syncable::GET_BY_ID, parent_id); |
- if (!parent.good()) { |
- DVLOG(1) << "Bad parent in loop check, skipping. Bad parent id: " |
- << parent_id << " entry: " << *entry; |
- return; |
- } |
- if (parent.Get(syncable::IS_UNSYNCED) && |
- entry->Get(syncable::PARENT_ID) != |
- entry->Get(syncable::SERVER_PARENT_ID)) |
- conflicting_entries.push_back(parent_id); |
- parent_id = parent.Get(syncable::PARENT_ID); |
- if (parent_id == entry->Get(syncable::ID)) |
- break; |
- } |
- if (parent_id.IsRoot()) |
- return; |
- for (size_t i = 0; i < conflicting_entries.size(); i++) { |
- conflict_progress->MergeSets(entry->Get(syncable::ID), |
- conflicting_entries[i]); |
- } |
-} |
- |
-namespace { |
- |
-class ServerDeletedPathChecker { |
- public: |
- static bool CausingConflict(const syncable::Entry& e, |
- const syncable::Entry& log_entry) { |
- CHECK(e.good()) << "Missing parent in path of: " << log_entry; |
- if (e.Get(syncable::IS_UNAPPLIED_UPDATE) && |
- e.Get(syncable::SERVER_IS_DEL)) { |
- CHECK(!e.Get(syncable::IS_DEL)) << " Inconsistency in local tree. " |
- "syncable::Entry: " << e << " Leaf: " << log_entry; |
- return true; |
- } else { |
- CHECK(!e.Get(syncable::IS_DEL)) << " Deleted entry has children. " |
- "syncable::Entry: " << e << " Leaf: " << log_entry; |
- return false; |
- } |
- } |
- |
- // returns 0 if we should stop investigating the path. |
- static syncable::Id GetAndExamineParent(syncable::BaseTransaction* trans, |
- const syncable::Id& id, |
- const syncable::Id& check_id, |
- const syncable::Entry& log_entry) { |
- syncable::Entry parent(trans, syncable::GET_BY_ID, id); |
- CHECK(parent.good()) << "Tree inconsitency, missing id" << id << " " |
- << log_entry; |
- syncable::Id parent_id = parent.Get(syncable::PARENT_ID); |
- CHECK(parent_id != check_id) << "Loop in dir tree! " |
- << log_entry << " " << parent; |
- return parent_id; |
- } |
-}; |
- |
-class LocallyDeletedPathChecker { |
- public: |
- static bool CausingConflict(const syncable::Entry& e, |
- const syncable::Entry& log_entry) { |
- return e.good() && e.Get(syncable::IS_DEL) && e.Get(syncable::IS_UNSYNCED); |
- } |
- |
- // returns 0 if we should stop investigating the path. |
- static syncable::Id GetAndExamineParent(syncable::BaseTransaction* trans, |
- const syncable::Id& id, |
- const syncable::Id& check_id, |
- const syncable::Entry& log_entry) { |
- syncable::Entry parent(trans, syncable::GET_BY_ID, id); |
- if (!parent.good()) |
- return syncable::GetNullId(); |
- syncable::Id parent_id = parent.Get(syncable::PARENT_ID); |
- if (parent_id == check_id) |
- return syncable::GetNullId(); |
- return parent_id; |
- } |
-}; |
- |
-template <typename Checker> |
-void CrawlDeletedTreeMergingSets(syncable::BaseTransaction* trans, |
- const syncable::Entry& entry, |
- ConflictProgress* conflict_progress, |
- Checker checker) { |
- syncable::Id parent_id = entry.Get(syncable::PARENT_ID); |
- syncable::Id double_step_parent_id = parent_id; |
- // This block builds sets where we've got an entry in a directory the server |
- // wants to delete. |
- // |
- // Here we're walking up the tree to find all entries that the pass checks |
- // deleted. We can be extremely strict here as anything unexpected means |
- // invariants in the local hierarchy have been broken. |
- while (!parent_id.IsRoot()) { |
- if (!double_step_parent_id.IsRoot()) { |
- // Checks to ensure we don't loop. |
- double_step_parent_id = checker.GetAndExamineParent( |
- trans, double_step_parent_id, parent_id, entry); |
- double_step_parent_id = checker.GetAndExamineParent( |
- trans, double_step_parent_id, parent_id, entry); |
- } |
- syncable::Entry parent(trans, syncable::GET_BY_ID, parent_id); |
- if (checker.CausingConflict(parent, entry)) { |
- conflict_progress->MergeSets(entry.Get(syncable::ID), |
- parent.Get(syncable::ID)); |
- } else { |
- break; |
- } |
- parent_id = parent.Get(syncable::PARENT_ID); |
- } |
-} |
- |
-} // namespace |
- |
-void BuildAndProcessConflictSetsCommand::MergeSetsForNonEmptyDirectories( |
- syncable::BaseTransaction* trans, syncable::Entry* entry, |
- ConflictProgress* conflict_progress) { |
- if (entry->Get(syncable::IS_UNSYNCED) && !entry->Get(syncable::IS_DEL)) { |
- ServerDeletedPathChecker checker; |
- CrawlDeletedTreeMergingSets(trans, *entry, conflict_progress, checker); |
- } |
- if (entry->Get(syncable::IS_UNAPPLIED_UPDATE) && |
- !entry->Get(syncable::SERVER_IS_DEL)) { |
- syncable::Entry parent(trans, syncable::GET_BY_ID, |
- entry->Get(syncable::SERVER_PARENT_ID)); |
- syncable::Id parent_id = entry->Get(syncable::SERVER_PARENT_ID); |
- if (!parent.good()) |
- return; |
- LocallyDeletedPathChecker checker; |
- if (!checker.CausingConflict(parent, *entry)) |
- return; |
- conflict_progress->MergeSets(entry->Get(syncable::ID), |
- parent.Get(syncable::ID)); |
- CrawlDeletedTreeMergingSets(trans, parent, conflict_progress, checker); |
- } |
-} |
- |
-} // namespace browser_sync |