diff options
author | nick@chromium.org <nick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-10 06:05:27 +0000 |
---|---|---|
committer | nick@chromium.org <nick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-10 06:05:27 +0000 |
commit | 5852edc1b6eab234b9e048c41dd0d664ae7fc747 (patch) | |
tree | 9e5d8eb4833b76cdb11e66fc3607689e0f5e0122 /chrome/browser/sync/engine/conflict_resolver.h | |
parent | f6059e37f8b8ac335ce18a189a13e702974a1c7e (diff) | |
download | chromium_src-5852edc1b6eab234b9e048c41dd0d664ae7fc747.zip chromium_src-5852edc1b6eab234b9e048c41dd0d664ae7fc747.tar.gz chromium_src-5852edc1b6eab234b9e048c41dd0d664ae7fc747.tar.bz2 |
Initial commit of sync engine code to browser/sync.
The code is not built on any platform yet. That will arrive
as a subsequent checkin.
This is an implementation of the interface exposed earlier
through syncapi.h. It is the client side of a sync
protocol that lets users sync their browser data
(currently, just bookmarks) with their Google Account.
Table of contents:
browser/sync/
protocol - The protocol definition, and
other definitions necessary to connect to
the service.
syncable/ - defines a data model for syncable objects,
and provides a sqlite-based backing store
for this model.
engine/ - includes the core sync logic, including commiting
changes to the server, downloading changes from
the server, resolving conflicts, other parts of
the sync algorithm.
engine/net - parts of the sync engine focused on the
business of talking to the server. Some of
this is binds a generic "server connection"
interface to a concrete implementation
provided by Chromium.
notifier - the part of the syncer focused on the business
of sending and receiving xmpp notifications.
Notifications are used instead of polling to
achieve very low latency change propagation.
util - not necessarily sync specific utility code. Much
of this is scaffolding which should either be
replaced by, or merged with, the utility code
in base/.
BUG=none
TEST=this code includes its own suite of unit tests.
Review URL: http://codereview.chromium.org/194065
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25850 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/sync/engine/conflict_resolver.h')
-rw-r--r-- | chrome/browser/sync/engine/conflict_resolver.h | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/chrome/browser/sync/engine/conflict_resolver.h b/chrome/browser/sync/engine/conflict_resolver.h new file mode 100644 index 0000000..7959106 --- /dev/null +++ b/chrome/browser/sync/engine/conflict_resolver.h @@ -0,0 +1,129 @@ +// 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_ + +#include <list> +#include <vector> + +#include "base/basictypes.h" +#include "chrome/browser/sync/engine/conflict_resolution_view.h" +#include "chrome/browser/sync/engine/syncer_session.h" +#include "chrome/browser/sync/engine/syncer_status.h" +#include "chrome/browser/sync/engine/syncer_types.h" +#include "chrome/browser/sync/util/event_sys.h" +#include "testing/gtest/include/gtest/gtest_prod.h" // For FRIEND_TEST + +namespace syncable { +class BaseTransaction; +class Id; +class MutableEntry; +class ScopedDirLookup; +class WriteTransaction; +} // namespace syncable + +namespace browser_sync { + +class ConflictResolver { + friend class SyncerTest; + FRIEND_TEST(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, + ConflictResolutionView* view, + SyncerSession *session); + + // Called by ProcessServerClientNameClash. Returns true if it's merged the + // items, false otherwise. Does not re-check preconditions covered in + // ProcessServerClientNameClash (i.e. it assumes a name clash). + bool AttemptItemMerge(syncable::WriteTransaction* trans, + syncable::MutableEntry* local_entry, + syncable::MutableEntry* server_entry); + + 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. + }; + + enum ServerClientNameClashReturn { + NO_CLASH, + SOLUTION_DEFERRED, + SOLVED, + BOGUS_SET, + }; + + // Get a key for the given set. NB: 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, + syncable::Id id, + SyncerSession* session); + + bool ResolveSimpleConflicts(const syncable::ScopedDirLookup& dir, + ConflictResolutionView* view, + SyncerSession* session); + + bool ProcessConflictSet(syncable::WriteTransaction* trans, + ConflictSet* conflict_set, + int conflict_count, + SyncerSession* session); + + // Gives any unsynced entries in the given set new names if possible. + bool RenameUnsyncedEntries(syncable::WriteTransaction* trans, + ConflictSet* conflict_set); + + ServerClientNameClashReturn ProcessServerClientNameClash( + syncable::WriteTransaction* trans, + syncable::MutableEntry* locally_named, + syncable::MutableEntry* server_named, + SyncerSession* session); + ServerClientNameClashReturn ProcessNameClashesInSet( + syncable::WriteTransaction* trans, + ConflictSet* conflict_set, + SyncerSession* session); + + // Returns true if we're stuck + template <typename InputIt> + bool LogAndSignalIfConflictStuck(syncable::BaseTransaction* trans, + int attempt_count, + InputIt start, InputIt end, + ConflictResolutionView* view); + + 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_ |