conflict_resolver.h revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2006-2009 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// A class that watches the syncer and attempts to resolve any conflicts that
6// occur.
7
8#ifndef CHROME_BROWSER_SYNC_ENGINE_CONFLICT_RESOLVER_H_
9#define CHROME_BROWSER_SYNC_ENGINE_CONFLICT_RESOLVER_H_
10#pragma once
11
12#include <set>
13#include <string>
14
15#include "base/basictypes.h"
16#include "base/gtest_prod_util.h"
17#include "chrome/browser/sync/engine/syncer_types.h"
18#include "chrome/common/deprecated/event_sys.h"
19
20namespace syncable {
21class BaseTransaction;
22class Id;
23class MutableEntry;
24class ScopedDirLookup;
25class WriteTransaction;
26}  // namespace syncable
27
28namespace browser_sync {
29namespace sessions {
30class StatusController;
31}
32
33class ConflictResolver {
34  friend class SyncerTest;
35  FRIEND_TEST_ALL_PREFIXES(SyncerTest,
36                           ConflictResolverMergeOverwritesLocalEntry);
37 public:
38  ConflictResolver();
39  ~ConflictResolver();
40  // Called by the syncer at the end of a update/commit cycle.
41  // Returns true if the syncer should try to apply its updates again.
42  bool ResolveConflicts(const syncable::ScopedDirLookup& dir,
43                        sessions::StatusController* status);
44
45 private:
46  // We keep a map to record how often we've seen each conflict set. We use this
47  // to screen out false positives caused by transient server or client states,
48  // and to allow us to try to make smaller changes to fix situations before
49  // moving onto more drastic solutions.
50  typedef std::string ConflictSetCountMapKey;
51  typedef std::map<ConflictSetCountMapKey, int> ConflictSetCountMap;
52  typedef std::map<syncable::Id, int> SimpleConflictCountMap;
53
54  enum ProcessSimpleConflictResult {
55    NO_SYNC_PROGRESS,  // No changes to advance syncing made.
56    SYNC_PROGRESS,     // Progress made.
57  };
58
59  // Get a key for the given set. NOTE: May reorder set contents. The key is
60  // currently not very efficient, but will ease debugging.
61  ConflictSetCountMapKey GetSetKey(ConflictSet* conflict_set);
62
63  void IgnoreLocalChanges(syncable::MutableEntry* entry);
64  void OverwriteServerChanges(syncable::WriteTransaction* trans,
65                              syncable::MutableEntry* entry);
66
67  ProcessSimpleConflictResult ProcessSimpleConflict(
68      syncable::WriteTransaction* trans,
69      const syncable::Id& id);
70
71  bool ResolveSimpleConflicts(const syncable::ScopedDirLookup& dir,
72                              sessions::StatusController* status);
73
74  bool ProcessConflictSet(syncable::WriteTransaction* trans,
75                          ConflictSet* conflict_set,
76                          int conflict_count);
77
78  // Returns true if we're stuck.
79  template <typename InputIt>
80  bool LogAndSignalIfConflictStuck(syncable::BaseTransaction* trans,
81                                   int attempt_count,
82                                   InputIt start, InputIt end,
83                                   sessions::StatusController* status);
84
85  ConflictSetCountMap conflict_set_count_map_;
86  SimpleConflictCountMap simple_conflict_count_map_;
87
88  // Contains the ids of uncommitted items that are children of entries merged
89  // in the previous cycle. This is used to speed up the merge resolution of
90  // deep trees. Used to happen in store refresh.
91  // TODO(chron): Can we get rid of this optimization?
92  std::set<syncable::Id> children_of_merged_dirs_;
93
94  DISALLOW_COPY_AND_ASSIGN(ConflictResolver);
95};
96
97}  // namespace browser_sync
98
99#endif  // CHROME_BROWSER_SYNC_ENGINE_CONFLICT_RESOLVER_H_
100