OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 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 entry. |
| 4 |
| 5 #ifndef CHROME_BROWSER_SYNC_ENGINE_SYNCER_H_ |
| 6 #define CHROME_BROWSER_SYNC_ENGINE_SYNCER_H_ |
| 7 |
| 8 #include <string> |
| 9 #include <utility> |
| 10 #include <vector> |
| 11 |
| 12 #include "base/basictypes.h" |
| 13 #include "base/scoped_ptr.h" |
| 14 #include "chrome/browser/sync/engine/client_command_channel.h" |
| 15 #include "chrome/browser/sync/engine/conflict_resolver.h" |
| 16 #include "chrome/browser/sync/engine/syncer_types.h" |
| 17 #include "chrome/browser/sync/engine/syncproto.h" |
| 18 #include "chrome/browser/sync/syncable/directory_event.h" |
| 19 #include "chrome/browser/sync/util/event_sys-inl.h" |
| 20 #include "chrome/browser/sync/util/event_sys.h" |
| 21 #include "chrome/browser/sync/util/pthread_helpers.h" |
| 22 #include "testing/gtest/include/gtest/gtest_prod.h" // For FRIEND_TEST |
| 23 |
| 24 namespace syncable { |
| 25 class Directory; |
| 26 class DirectoryManager; |
| 27 class Entry; |
| 28 class Id; |
| 29 class MutableEntry; |
| 30 class WriteTransaction; |
| 31 } // namespace syncable |
| 32 |
| 33 namespace browser_sync { |
| 34 |
| 35 class ModelSafeWorker; |
| 36 class ServerConnectionManager; |
| 37 class SyncProcessState; |
| 38 class SyncerSession; |
| 39 class URLFactory; |
| 40 struct HttpResponse; |
| 41 |
| 42 static const int kDefaultMaxCommitBatchSize = 25; |
| 43 |
| 44 enum SyncerStep { |
| 45 SYNCER_BEGIN, |
| 46 DOWNLOAD_UPDATES, |
| 47 PROCESS_CLIENT_COMMAND, |
| 48 VERIFY_UPDATES, |
| 49 PROCESS_UPDATES, |
| 50 APPLY_UPDATES, |
| 51 BUILD_COMMIT_REQUEST, |
| 52 POST_COMMIT_MESSAGE, |
| 53 PROCESS_COMMIT_RESPONSE, |
| 54 BUILD_AND_PROCESS_CONFLICT_SETS, |
| 55 RESOLVE_CONFLICTS, |
| 56 APPLY_UPDATES_TO_RESOLVE_CONFLICTS, |
| 57 SYNCER_END |
| 58 }; |
| 59 |
| 60 // A Syncer provides a control interface for driving the individual steps |
| 61 // of the sync cycle. Each cycle (hopefully) moves the client into closer |
| 62 // synchronization with the server. The individual steps are modeled |
| 63 // as SyncerCommands, and the ordering of the steps is expressed using |
| 64 // the SyncerStep enum. |
| 65 // |
| 66 // A Syncer instance expects to run on a dedicated thread. Calls |
| 67 // to SyncShare() may take an unbounded amount of time, as SyncerCommands |
| 68 // may block on network i/o, on lock contention, or on tasks posted to |
| 69 // other threads. |
| 70 class Syncer { |
| 71 public: |
| 72 typedef std::vector<int64> UnsyncedMetaHandles; |
| 73 typedef void (*TestCallbackFunction)(syncable::Directory* dir); |
| 74 |
| 75 // The constructor may be called from a thread that is not the Syncer's |
| 76 // dedicated thread, to allow some flexibility in the setup. |
| 77 Syncer( |
| 78 syncable::DirectoryManager* dirman, |
| 79 const PathString &account_name, |
| 80 ServerConnectionManager* connection_manager, |
| 81 ModelSafeWorker* model_safe_worker); |
| 82 |
| 83 ~Syncer(); |
| 84 |
| 85 // Called by other threads to tell the syncer to stop what it's doing |
| 86 // and return early from SyncShare, if possible. |
| 87 bool ExitRequested() { return early_exit_requested_; } |
| 88 void RequestEarlyExit() { early_exit_requested_ = true; } |
| 89 |
| 90 // SyncShare(...) variants cause one sync cycle to occur. The return value |
| 91 // indicates whether we should sync again. |
| 92 // The zero-argument version of SyncShare is provided for unit tests. |
| 93 // When |sync_process_state| is provided, it is used as the syncer state |
| 94 // for the sync cycle. It is treated as an input/output parameter. |
| 95 // When |first_step| and |last_step| are provided, this means to perform |
| 96 // a partial sync cycle, stopping after |last_step| is performed. |
| 97 bool SyncShare(); |
| 98 bool SyncShare(SyncProcessState *sync_process_state); |
| 99 bool SyncShare(SyncerStep first_step, SyncerStep last_step); |
| 100 |
| 101 // Limit the batch size of commit operations to a specified number of items. |
| 102 void set_max_commit_batch_size(int x) { max_commit_batch_size_ = x; } |
| 103 |
| 104 ConflictResolver* conflict_resolver() { return &resolver_; } |
| 105 |
| 106 PathString account_name() { return account_name_; } |
| 107 |
| 108 SyncerEventChannel* channel() const { return syncer_event_channel_.get(); } |
| 109 |
| 110 ShutdownChannel* shutdown_channel() const { return shutdown_channel_.get(); } |
| 111 |
| 112 ModelSafeWorker* model_safe_worker() { return model_safe_worker_; } |
| 113 |
| 114 // Syncer will take ownership of this channel and it will be destroyed along |
| 115 // with the Syncer instance. |
| 116 void set_shutdown_channel(ShutdownChannel* channel) { |
| 117 shutdown_channel_.reset(channel); |
| 118 } |
| 119 |
| 120 void set_command_channel(ClientCommandChannel* channel) { |
| 121 command_channel_ = channel; |
| 122 } |
| 123 |
| 124 // Volatile reader for the source member of the syncer session object. The |
| 125 // value is set to the SYNC_CYCLE_CONTINUATION value to signal that it has |
| 126 // been read. |
| 127 sync_pb::GetUpdatesCallerInfo::GET_UPDATES_SOURCE TestAndSetUpdatesSource() { |
| 128 sync_pb::GetUpdatesCallerInfo::GET_UPDATES_SOURCE old_source = |
| 129 updates_source_; |
| 130 set_updates_source(sync_pb::GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION); |
| 131 return old_source; |
| 132 } |
| 133 |
| 134 void set_updates_source( |
| 135 sync_pb::GetUpdatesCallerInfo::GET_UPDATES_SOURCE source) { |
| 136 updates_source_ = source; |
| 137 } |
| 138 |
| 139 bool notifications_enabled() const { |
| 140 return notifications_enabled_; |
| 141 } |
| 142 |
| 143 void set_notifications_enabled(bool state) { |
| 144 notifications_enabled_ = state; |
| 145 } |
| 146 |
| 147 private: |
| 148 void RequestNudge(int milliseconds); |
| 149 |
| 150 // Implements the PROCESS_CLIENT_COMMAND syncer step. |
| 151 void ProcessClientCommand(SyncerSession *session); |
| 152 |
| 153 void SyncShare(SyncerSession* session); |
| 154 void SyncShare(SyncerSession* session, |
| 155 SyncerStep first_step, |
| 156 SyncerStep last_step); |
| 157 |
| 158 PathString account_name_; |
| 159 bool early_exit_requested_; |
| 160 |
| 161 int32 max_commit_batch_size_; |
| 162 |
| 163 ServerConnectionManager* connection_manager_; |
| 164 |
| 165 ConflictResolver resolver_; |
| 166 syncable::DirectoryManager* const dirman_; |
| 167 |
| 168 // When we're over bandwidth quota, we don't update until past this time. |
| 169 time_t silenced_until_; |
| 170 |
| 171 scoped_ptr<SyncerEventChannel> syncer_event_channel_; |
| 172 scoped_ptr<ShutdownChannel> shutdown_channel_; |
| 173 ClientCommandChannel* command_channel_; |
| 174 |
| 175 // A worker capable of processing work closures on a thread that is |
| 176 // guaranteed to be safe for model modifications. This is created and owned |
| 177 // by the SyncerThread that created us. |
| 178 ModelSafeWorker* model_safe_worker_; |
| 179 |
| 180 // The source of the last nudge. |
| 181 sync_pb::GetUpdatesCallerInfo::GET_UPDATES_SOURCE updates_source_; |
| 182 |
| 183 // True only if the notification channel is authorized and open. |
| 184 bool notifications_enabled_; |
| 185 |
| 186 // A callback hook used in unittests to simulate changes between conflict set |
| 187 // building and conflict resolution. |
| 188 TestCallbackFunction pre_conflict_resolution_function_; |
| 189 |
| 190 FRIEND_TEST(SyncerTest, NewServerItemInAFolderHierarchyWeHaveDeleted3); |
| 191 FRIEND_TEST(SyncerTest, TestCommitListOrderingAndNewParent); |
| 192 FRIEND_TEST(SyncerTest, TestCommitListOrderingAndNewParentAndChild); |
| 193 FRIEND_TEST(SyncerTest, TestCommitListOrderingCounterexample); |
| 194 FRIEND_TEST(SyncerTest, TestCommitListOrderingWithNesting); |
| 195 FRIEND_TEST(SyncerTest, TestCommitListOrderingWithNewItems); |
| 196 FRIEND_TEST(SyncerTest, TestGetUnsyncedAndSimpleCommit); |
| 197 |
| 198 DISALLOW_COPY_AND_ASSIGN(Syncer); |
| 199 }; |
| 200 |
| 201 // Inline utility functions. |
| 202 |
| 203 // Given iterator ranges from two collections sorted according to a |
| 204 // common strict weak ordering, return true if the two ranges contain |
| 205 // any common items, and false if they do not. |
| 206 // This function is in this header so that it can be tested. |
| 207 template <class Iterator1, class Iterator2> |
| 208 bool SortedCollectionsIntersect(Iterator1 begin1, Iterator1 end1, |
| 209 Iterator2 begin2, Iterator2 end2) { |
| 210 Iterator1 i1 = begin1; |
| 211 Iterator2 i2 = begin2; |
| 212 while (i1 != end1 && i2 != end2) { |
| 213 if (*i1 == *i2) |
| 214 return true; |
| 215 if (*i1 > *i2) |
| 216 ++i2; |
| 217 else |
| 218 ++i1; |
| 219 } |
| 220 return false; |
| 221 } |
| 222 // Utility function declarations. |
| 223 void SplitServerInformationIntoNewEntry(syncable::WriteTransaction* trans, |
| 224 syncable::MutableEntry* entry); |
| 225 void CopyServerFields(syncable::Entry* src, syncable::MutableEntry* dest); |
| 226 void ClearServerData(syncable::MutableEntry* entry); |
| 227 |
| 228 // Get update contents as a string. Intended for logging, and intended |
| 229 // to have a smaller footprint than the protobuf's built-in pretty printer. |
| 230 std::string SyncEntityDebugString(const sync_pb::SyncEntity& entry); |
| 231 |
| 232 } // namespace browser_sync |
| 233 |
| 234 #endif // CHROME_BROWSER_SYNC_ENGINE_SYNCER_H_ |
OLD | NEW |