summaryrefslogtreecommitdiffstats
path: root/chrome/browser/sync/engine/syncer.h
blob: 89f1307b86fa3a1c0a3105febb3597f9756863ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
// Copyright (c) 2010 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.

#ifndef CHROME_BROWSER_SYNC_ENGINE_SYNCER_H_
#define CHROME_BROWSER_SYNC_ENGINE_SYNCER_H_
#pragma once

#include <utility>
#include <vector>

#include "base/basictypes.h"
#include "base/callback.h"
#include "base/gtest_prod_util.h"
#include "base/scoped_ptr.h"
#include "base/synchronization/lock.h"
#include "chrome/browser/sync/engine/conflict_resolver.h"
#include "chrome/browser/sync/engine/syncer_types.h"
#include "chrome/browser/sync/engine/syncproto.h"
#include "chrome/browser/sync/sessions/sync_session.h"
#include "chrome/browser/sync/syncable/directory_event.h"
#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/browser/sync/util/extensions_activity_monitor.h"
#include "chrome/common/deprecated/event_sys.h"
#include "chrome/common/deprecated/event_sys-inl.h"

namespace syncable {
class Directory;
class DirectoryManager;
class Entry;
class Id;
class MutableEntry;
class WriteTransaction;
}  // namespace syncable

namespace browser_sync {

class ModelSafeWorker;
class ServerConnectionManager;
class SyncProcessState;
class URLFactory;
struct HttpResponse;

static const int kDefaultMaxCommitBatchSize = 25;

enum SyncerStep {
  SYNCER_BEGIN,
  CLEANUP_DISABLED_TYPES,
  DOWNLOAD_UPDATES,
  PROCESS_CLIENT_COMMAND,
  VERIFY_UPDATES,
  PROCESS_UPDATES,
  STORE_TIMESTAMPS,
  APPLY_UPDATES,
  BUILD_COMMIT_REQUEST,
  POST_COMMIT_MESSAGE,
  PROCESS_COMMIT_RESPONSE,
  BUILD_AND_PROCESS_CONFLICT_SETS,
  RESOLVE_CONFLICTS,
  APPLY_UPDATES_TO_RESOLVE_CONFLICTS,
  CLEAR_PRIVATE_DATA,
  SYNCER_END
};

// A Syncer provides a control interface for driving the individual steps
// of the sync cycle.  Each cycle (hopefully) moves the client into closer
// synchronization with the server.  The individual steps are modeled
// as SyncerCommands, and the ordering of the steps is expressed using
// the SyncerStep enum.
//
// A Syncer instance expects to run on a dedicated thread.  Calls
// to SyncShare() may take an unbounded amount of time, as SyncerCommands
// may block on network i/o, on lock contention, or on tasks posted to
// other threads.
class Syncer {
 public:
  typedef std::vector<int64> UnsyncedMetaHandles;

  // The constructor may be called from a thread that is not the Syncer's
  // dedicated thread, to allow some flexibility in the setup.
  Syncer();
  ~Syncer();

  // Called by other threads to tell the syncer to stop what it's doing
  // and return early from SyncShare, if possible.
  bool ExitRequested();
  void RequestEarlyExit();

  // Cause one sync cycle to occur.  Like a good parent, it is the caller's
  // responsibility to clean up after the syncer when it finishes a sync share
  // operation and honor server mandated throttles.
  void SyncShare(sessions::SyncSession* session);

  // Limit the batch size of commit operations to a specified number of items.
  void set_max_commit_batch_size(int x) { max_commit_batch_size_ = x; }

 private:
  void RequestNudge(int milliseconds);

  // Implements the PROCESS_CLIENT_COMMAND syncer step.
  void ProcessClientCommand(sessions::SyncSession *session);

  // This is the bottom-most SyncShare variant, and does not cause transient
  // state to be reset in session.
  // Like SyncShare(), but |first_step| and |last_step| are provided to perform
  // a partial sync cycle, stopping after |last_step| is performed.
  void SyncShare(sessions::SyncSession* session,
                 SyncerStep first_step,
                 SyncerStep last_step);

  bool early_exit_requested_;
  base::Lock early_exit_requested_lock_;

  int32 max_commit_batch_size_;

  ConflictResolver resolver_;

  // A callback hook used in unittests to simulate changes between conflict set
  // building and conflict resolution.
  Callback0::Type* pre_conflict_resolution_closure_;

  friend class SyncerTest;
  FRIEND_TEST_ALL_PREFIXES(SyncerTest, NameClashWithResolver);
  FRIEND_TEST_ALL_PREFIXES(SyncerTest, IllegalAndLegalUpdates);
  FRIEND_TEST_ALL_PREFIXES(SusanDeletingTest,
                           NewServerItemInAFolderHierarchyWeHaveDeleted3);
  FRIEND_TEST_ALL_PREFIXES(SyncerTest, TestCommitListOrderingAndNewParent);
  FRIEND_TEST_ALL_PREFIXES(SyncerTest,
                           TestCommitListOrderingAndNewParentAndChild);
  FRIEND_TEST_ALL_PREFIXES(SyncerTest, TestCommitListOrderingCounterexample);
  FRIEND_TEST_ALL_PREFIXES(SyncerTest, TestCommitListOrderingWithNesting);
  FRIEND_TEST_ALL_PREFIXES(SyncerTest, TestCommitListOrderingWithNewItems);
  FRIEND_TEST_ALL_PREFIXES(SyncerTest, TestGetUnsyncedAndSimpleCommit);
  FRIEND_TEST_ALL_PREFIXES(SyncerTest, TestPurgeWhileUnsynced);
  FRIEND_TEST_ALL_PREFIXES(SyncerTest, TestPurgeWhileUnapplied);
  FRIEND_TEST_ALL_PREFIXES(SyncerTest, UnappliedUpdateDuringCommit);
  FRIEND_TEST_ALL_PREFIXES(SyncerTest, DeletingEntryInFolder);
  FRIEND_TEST_ALL_PREFIXES(SyncerTest,
                           LongChangelistCreatesFakeOrphanedEntries);
  FRIEND_TEST_ALL_PREFIXES(SyncerTest, QuicklyMergeDualCreatedHierarchy);
  FRIEND_TEST_ALL_PREFIXES(SyncerTest, LongChangelistWithApplicationConflict);
  FRIEND_TEST_ALL_PREFIXES(SyncerTest, DeletingEntryWithLocalEdits);
  FRIEND_TEST_ALL_PREFIXES(EntryCreatedInNewFolderTest,
                           EntryCreatedInNewFolderMidSync);

  DISALLOW_COPY_AND_ASSIGN(Syncer);
};

// Inline utility functions.

// Given iterator ranges from two collections sorted according to a common
// strict weak ordering, return true if the two ranges contain any common
// items, and false if they do not. This function is in this header so that it
// can be tested.
template <class Iterator1, class Iterator2>
bool SortedCollectionsIntersect(Iterator1 begin1, Iterator1 end1,
                                Iterator2 begin2, Iterator2 end2) {
  Iterator1 i1 = begin1;
  Iterator2 i2 = begin2;
  while (i1 != end1 && i2 != end2) {
    if (*i1 == *i2)
      return true;
    if (*i1 > *i2)
      ++i2;
    else
      ++i1;
  }
  return false;
}
// Utility function declarations.
void CopyServerFields(syncable::Entry* src, syncable::MutableEntry* dest);
void ClearServerData(syncable::MutableEntry* entry);

}  // namespace browser_sync

#endif  // CHROME_BROWSER_SYNC_ENGINE_SYNCER_H_