| // Copyright (c) 2006-2009 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. |
| // |
| // A class that watches the syncer and attempts to resolve any conflicts that |
| // occur. |
| |
| #ifndef CHROME_BROWSER_SYNC_ENGINE_CONFLICT_RESOLVER_H_ |
| #define CHROME_BROWSER_SYNC_ENGINE_CONFLICT_RESOLVER_H_ |
| #pragma once |
| |
| #include <set> |
| #include <string> |
| |
| #include "base/basictypes.h" |
| #include "base/gtest_prod_util.h" |
| #include "chrome/browser/sync/engine/syncer_types.h" |
| #include "chrome/common/deprecated/event_sys.h" |
| |
| namespace syncable { |
| class BaseTransaction; |
| class Id; |
| class MutableEntry; |
| class ScopedDirLookup; |
| class WriteTransaction; |
| } // namespace syncable |
| |
| namespace browser_sync { |
| namespace sessions { |
| class StatusController; |
| } |
| |
| class ConflictResolver { |
| friend class SyncerTest; |
| FRIEND_TEST_ALL_PREFIXES(SyncerTest, |
| ConflictResolverMergeOverwritesLocalEntry); |
| public: |
| ConflictResolver(); |
| ~ConflictResolver(); |
| // Called by the syncer at the end of a update/commit cycle. |
| // Returns true if the syncer should try to apply its updates again. |
| bool ResolveConflicts(const syncable::ScopedDirLookup& dir, |
| sessions::StatusController* status); |
| |
| private: |
| // We keep a map to record how often we've seen each conflict set. We use this |
| // to screen out false positives caused by transient server or client states, |
| // and to allow us to try to make smaller changes to fix situations before |
| // moving onto more drastic solutions. |
| typedef std::string ConflictSetCountMapKey; |
| typedef std::map<ConflictSetCountMapKey, int> ConflictSetCountMap; |
| typedef std::map<syncable::Id, int> SimpleConflictCountMap; |
| |
| enum ProcessSimpleConflictResult { |
| NO_SYNC_PROGRESS, // No changes to advance syncing made. |
| SYNC_PROGRESS, // Progress made. |
| }; |
| |
| // Get a key for the given set. NOTE: May reorder set contents. The key is |
| // currently not very efficient, but will ease debugging. |
| ConflictSetCountMapKey GetSetKey(ConflictSet* conflict_set); |
| |
| void IgnoreLocalChanges(syncable::MutableEntry* entry); |
| void OverwriteServerChanges(syncable::WriteTransaction* trans, |
| syncable::MutableEntry* entry); |
| |
| ProcessSimpleConflictResult ProcessSimpleConflict( |
| syncable::WriteTransaction* trans, |
| const syncable::Id& id); |
| |
| bool ResolveSimpleConflicts(const syncable::ScopedDirLookup& dir, |
| sessions::StatusController* status); |
| |
| bool ProcessConflictSet(syncable::WriteTransaction* trans, |
| ConflictSet* conflict_set, |
| int conflict_count); |
| |
| // Returns true if we're stuck. |
| template <typename InputIt> |
| bool LogAndSignalIfConflictStuck(syncable::BaseTransaction* trans, |
| int attempt_count, |
| InputIt start, InputIt end, |
| sessions::StatusController* status); |
| |
| ConflictSetCountMap conflict_set_count_map_; |
| SimpleConflictCountMap simple_conflict_count_map_; |
| |
| // Contains the ids of uncommitted items that are children of entries merged |
| // in the previous cycle. This is used to speed up the merge resolution of |
| // deep trees. Used to happen in store refresh. |
| // TODO(chron): Can we get rid of this optimization? |
| std::set<syncable::Id> children_of_merged_dirs_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ConflictResolver); |
| }; |
| |
| } // namespace browser_sync |
| |
| #endif // CHROME_BROWSER_SYNC_ENGINE_CONFLICT_RESOLVER_H_ |