OLD | NEW |
(Empty) | |
| 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 // |
| 6 // The sync process consists of a sequence of sync cycles, each of which |
| 7 // (hopefully) moves the client into closer synchronization with the server. |
| 8 // While SyncCycleState holds state that is pertinent to a single sync cycle, |
| 9 // this data structure holds state that must be passed from cycle to cycle. |
| 10 // |
| 11 // THIS CLASS PROVIDES NO SYNCHRONIZATION GUARANTEES. |
| 12 |
| 13 #ifndef CHROME_BROWSER_SYNC_ENGINE_SYNC_PROCESS_STATE_H_ |
| 14 #define CHROME_BROWSER_SYNC_ENGINE_SYNC_PROCESS_STATE_H_ |
| 15 |
| 16 #include <map> |
| 17 #include <set> |
| 18 #include <utility> // for pair<> |
| 19 |
| 20 #include "base/atomicops.h" |
| 21 #include "base/basictypes.h" |
| 22 #include "base/port.h" |
| 23 #include "chrome/browser/sync/engine/net/server_connection_manager.h" |
| 24 #include "chrome/browser/sync/engine/syncer_types.h" |
| 25 #include "chrome/browser/sync/syncable/syncable_id.h" |
| 26 #include "testing/gtest/include/gtest/gtest_prod.h" // For FRIEND_TEST |
| 27 |
| 28 namespace browser_sync { |
| 29 |
| 30 class ConflictResolver; |
| 31 class ModelSafeWorker; |
| 32 |
| 33 class SyncProcessState { |
| 34 FRIEND_TEST(SyncerSyncProcessState, MergeSetsTest); |
| 35 FRIEND_TEST(SyncerTest, CopySyncProcessState); |
| 36 public: |
| 37 ~SyncProcessState(); |
| 38 SyncProcessState( |
| 39 syncable::DirectoryManager* dirman, |
| 40 PathString account_name, |
| 41 ServerConnectionManager* connection_manager, |
| 42 ConflictResolver* const resolver, |
| 43 SyncerEventChannel* syncer_event_channel, |
| 44 ModelSafeWorker* model_safe_worker); |
| 45 |
| 46 // intentionally not 'explicit' b/c it's a copy ctor: |
| 47 SyncProcessState(const SyncProcessState& counts); |
| 48 SyncProcessState& operator=(const SyncProcessState& that); |
| 49 |
| 50 PathString account_name() const { return account_name_; } |
| 51 |
| 52 syncable::DirectoryManager* dirman() const { return dirman_; } |
| 53 |
| 54 ServerConnectionManager* connection_manager() |
| 55 const { |
| 56 return connection_manager_; |
| 57 } |
| 58 |
| 59 ConflictResolver* resolver() const { return resolver_; } |
| 60 |
| 61 ModelSafeWorker* model_safe_worker() { return model_safe_worker_; } |
| 62 |
| 63 SyncerEventChannel* syncer_event_channel() const { |
| 64 return syncer_event_channel_; |
| 65 } |
| 66 |
| 67 // Functions that deal with conflict set stuff |
| 68 IdToConflictSetMap::const_iterator IdToConflictSetFind( |
| 69 const syncable::Id& the_id) const { |
| 70 return id_to_conflict_set_.find(the_id); |
| 71 } |
| 72 |
| 73 IdToConflictSetMap::const_iterator IdToConflictSetBegin() const { |
| 74 return id_to_conflict_set_.begin(); |
| 75 } |
| 76 |
| 77 IdToConflictSetMap::const_iterator IdToConflictSetEnd() const { |
| 78 return id_to_conflict_set_.end(); |
| 79 } |
| 80 |
| 81 IdToConflictSetMap::size_type IdToConflictSetSize() const { |
| 82 return id_to_conflict_set_.size(); |
| 83 } |
| 84 |
| 85 const ConflictSet* IdToConflictSetGet(const syncable::Id& the_id) { |
| 86 return id_to_conflict_set_[the_id]; |
| 87 } |
| 88 |
| 89 std::set<ConflictSet*>::const_iterator ConflictSetsBegin() const { |
| 90 return conflict_sets_.begin(); |
| 91 } |
| 92 |
| 93 std::set<ConflictSet*>::const_iterator ConflictSetsEnd() const { |
| 94 return conflict_sets_.end(); |
| 95 } |
| 96 |
| 97 std::set<ConflictSet*>::size_type ConflictSetsSize() const { |
| 98 return conflict_sets_.size(); |
| 99 } |
| 100 |
| 101 void MergeSets(const syncable::Id& set1, const syncable::Id& set2); |
| 102 |
| 103 void CleanupSets(); |
| 104 // END conflict set functions |
| 105 |
| 106 // item id set manipulation functions |
| 107 bool HasConflictingItems() const { |
| 108 return !conflicting_item_ids_.empty(); |
| 109 } |
| 110 |
| 111 bool HasBlockedItems() const { |
| 112 return !blocked_item_ids_.empty(); |
| 113 } |
| 114 |
| 115 int ConflictingItemsSize() const { |
| 116 return conflicting_item_ids_.size(); |
| 117 } |
| 118 |
| 119 int BlockedItemsSize() const { |
| 120 return blocked_item_ids_.size(); |
| 121 } |
| 122 |
| 123 void AddConflictingItem(const syncable::Id& the_id) { |
| 124 std::pair<std::set<syncable::Id>::iterator, bool> ret = |
| 125 conflicting_item_ids_.insert(the_id); |
| 126 UpdateDirty(ret.second); |
| 127 } |
| 128 |
| 129 void AddBlockedItem(const syncable::Id& the_id) { |
| 130 std::pair<std::set<syncable::Id>::iterator, bool> ret = |
| 131 blocked_item_ids_.insert(the_id); |
| 132 UpdateDirty(ret.second); |
| 133 } |
| 134 |
| 135 void EraseConflictingItem(std::set<syncable::Id>::iterator it) { |
| 136 UpdateDirty(true); |
| 137 conflicting_item_ids_.erase(it); |
| 138 } |
| 139 |
| 140 void EraseBlockedItem(std::set<syncable::Id>::iterator it) { |
| 141 UpdateDirty(true); |
| 142 blocked_item_ids_.erase(it); |
| 143 } |
| 144 |
| 145 void EraseConflictingItem(const syncable::Id& the_id) { |
| 146 int items_erased = conflicting_item_ids_.erase(the_id); |
| 147 UpdateDirty(0 != items_erased); |
| 148 } |
| 149 |
| 150 void EraseBlockedItem(const syncable::Id& the_id) { |
| 151 int items_erased = blocked_item_ids_.erase(the_id); |
| 152 UpdateDirty(0 != items_erased); |
| 153 } |
| 154 |
| 155 std::set<syncable::Id>::iterator ConflictingItemsBegin() { |
| 156 return conflicting_item_ids_.begin(); |
| 157 } |
| 158 |
| 159 std::set<syncable::Id>::iterator BlockedItemsBegin() { |
| 160 return blocked_item_ids_.begin(); |
| 161 } |
| 162 |
| 163 std::set<syncable::Id>::iterator ConflictingItemsEnd() { |
| 164 return conflicting_item_ids_.end(); |
| 165 } |
| 166 |
| 167 std::set<syncable::Id>::iterator BlockedItemsEnd() { |
| 168 return blocked_item_ids_.end(); |
| 169 } |
| 170 |
| 171 void SetConflictingItems(const std::set<syncable::Id>& s) { |
| 172 UpdateDirty(true); |
| 173 conflicting_item_ids_ = s; |
| 174 } |
| 175 |
| 176 void SetBlockedItems(const std::set<syncable::Id>& s) { |
| 177 UpdateDirty(true); |
| 178 blocked_item_ids_ = s; |
| 179 } |
| 180 // END item id set manipulation functions |
| 181 |
| 182 // Assorted other state info |
| 183 int conflicting_updates() const { return conflicting_item_ids_.size(); } |
| 184 |
| 185 int num_sync_cycles_; |
| 186 |
| 187 // When we're over bandwidth quota, we don't update until past this time. |
| 188 time_t silenced_until_; |
| 189 |
| 190 // Info that is tracked purely for status reporting |
| 191 |
| 192 // During inital sync these two members can be used to measure sync progress. |
| 193 int64 current_sync_timestamp() const { return current_sync_timestamp_; } |
| 194 |
| 195 int64 servers_latest_timestamp() const { return servers_latest_timestamp_; } |
| 196 |
| 197 void set_current_sync_timestamp(const int64 val); |
| 198 |
| 199 void set_servers_latest_timestamp(const int64 val); |
| 200 |
| 201 bool invalid_store() const { return invalid_store_; } |
| 202 |
| 203 void set_invalid_store(const bool val); |
| 204 |
| 205 bool syncer_stuck() const { return syncer_stuck_; } |
| 206 |
| 207 void set_syncer_stuck(const bool val); |
| 208 |
| 209 bool syncing() const { return syncing_; } |
| 210 |
| 211 void set_syncing(const bool val); |
| 212 |
| 213 bool IsShareUsable() const; |
| 214 |
| 215 int error_commits() const { return error_commits_; } |
| 216 |
| 217 void set_error_commits(const int val); |
| 218 |
| 219 int conflicting_commits() const { return conflicting_commits_; } |
| 220 |
| 221 void set_conflicting_commits(const int val); |
| 222 |
| 223 int stalled_commits() const { return stalled_commits_; } |
| 224 |
| 225 void set_stalled_commits(const int val); |
| 226 |
| 227 // WEIRD COUNTER manipulation functions |
| 228 int consecutive_problem_get_updates() const { |
| 229 return consecutive_problem_get_updates_; |
| 230 } |
| 231 |
| 232 void increment_consecutive_problem_get_updates(); |
| 233 |
| 234 void zero_consecutive_problem_get_updates(); |
| 235 |
| 236 int consecutive_problem_commits() const { |
| 237 return consecutive_problem_commits_; |
| 238 } |
| 239 |
| 240 void increment_consecutive_problem_commits(); |
| 241 |
| 242 void zero_consecutive_problem_commits(); |
| 243 |
| 244 int consecutive_transient_error_commits() const { |
| 245 return consecutive_transient_error_commits_; |
| 246 } |
| 247 |
| 248 void increment_consecutive_transient_error_commits_by(int value); |
| 249 |
| 250 void zero_consecutive_transient_error_commits(); |
| 251 |
| 252 int consecutive_errors() const { return consecutive_errors_; } |
| 253 |
| 254 void increment_consecutive_errors_by(int value); |
| 255 |
| 256 void zero_consecutive_errors(); |
| 257 |
| 258 int successful_commits() const { return successful_commits_; } |
| 259 |
| 260 void increment_successful_commits(); |
| 261 |
| 262 void zero_successful_commits(); |
| 263 // end WEIRD COUNTER manipulation functions |
| 264 |
| 265 // Methods for managing error rate tracking |
| 266 void TallyNewError(); |
| 267 |
| 268 void TallyBigNewError(); |
| 269 |
| 270 void ForgetOldError(); |
| 271 |
| 272 void CheckErrorRateTooHigh(); |
| 273 |
| 274 // Methods for tracking authentication state |
| 275 void AuthFailed(); |
| 276 void AuthSucceeded(); |
| 277 |
| 278 // Returns true if this object has been modified since last SetClean() call |
| 279 bool IsDirty() const { return dirty_; } |
| 280 |
| 281 // Call to tell this status object that its new state has been seen |
| 282 void SetClean() { dirty_ = false; } |
| 283 |
| 284 // Returns true if auth status has been modified since last SetClean() call |
| 285 bool IsAuthDirty() const { return auth_dirty_; } |
| 286 |
| 287 // Call to tell this status object that its auth state has been seen |
| 288 void SetAuthClean() { auth_dirty_ = false; } |
| 289 |
| 290 private: |
| 291 // for testing |
| 292 SyncProcessState() |
| 293 : account_name_(PSTR("")), |
| 294 dirman_(NULL), |
| 295 syncer_event_channel_(NULL), |
| 296 connection_manager_(NULL), |
| 297 model_safe_worker_(NULL), |
| 298 resolver_(NULL), |
| 299 syncer_stuck_(false), |
| 300 num_sync_cycles_(0), |
| 301 silenced_until_(0), |
| 302 error_rate_(0), |
| 303 current_sync_timestamp_(0), |
| 304 servers_latest_timestamp_(0), |
| 305 error_commits_(0), |
| 306 stalled_commits_(0), |
| 307 conflicting_commits_(0), |
| 308 consecutive_problem_get_updates_(0), |
| 309 consecutive_problem_commits_(0), |
| 310 consecutive_transient_error_commits_(0), |
| 311 consecutive_errors_(0), |
| 312 successful_commits_(0), |
| 313 dirty_(false), |
| 314 auth_dirty_(false), |
| 315 auth_failed_(false), |
| 316 syncing_(false), |
| 317 invalid_store_(false) {} |
| 318 |
| 319 ServerConnectionManager *connection_manager_; |
| 320 const PathString account_name_; |
| 321 syncable::DirectoryManager* const dirman_; |
| 322 ConflictResolver* const resolver_; |
| 323 ModelSafeWorker* const model_safe_worker_; |
| 324 |
| 325 // For sending notifications from sync commands out to observers of the |
| 326 // Syncer. |
| 327 SyncerEventChannel* syncer_event_channel_; |
| 328 |
| 329 // TODO(sync): move away from sets if it makes more sense. |
| 330 std::set<syncable::Id> conflicting_item_ids_; |
| 331 std::set<syncable::Id> blocked_item_ids_; |
| 332 std::map<syncable::Id, ConflictSet*> id_to_conflict_set_; |
| 333 std::set<ConflictSet*> conflict_sets_; |
| 334 |
| 335 // Status information, as opposed to state info that may also be exposed for |
| 336 // status reporting purposes. |
| 337 static const int ERROR_THRESHOLD = 500; |
| 338 int error_rate_; // A EMA in the range [0,65536) |
| 339 int64 current_sync_timestamp_; // During inital sync these two members |
| 340 int64 servers_latest_timestamp_; // can be used to measure sync progress. |
| 341 |
| 342 // There remains sync state updating in: |
| 343 // CommitUnsyncedEntries |
| 344 bool syncing_; |
| 345 |
| 346 // True when we get such an INVALID_STORE error from the server. |
| 347 bool invalid_store_; |
| 348 // True iff we're stuck. User should contact support. |
| 349 bool syncer_stuck_; |
| 350 // counts of various commit return values. |
| 351 int error_commits_; |
| 352 int conflicting_commits_; |
| 353 int stalled_commits_; |
| 354 |
| 355 // WEIRD COUNTERS |
| 356 // Two variables that track the # on consecutive problem requests. |
| 357 // consecutive_problem_get_updates_ resets when we get any updates (not on |
| 358 // pings) and increments whenever the request fails. |
| 359 int consecutive_problem_get_updates_; |
| 360 // consecutive_problem_commits_ resets whenever we commit any number of |
| 361 // items and increments whenever all commits fail for any reason. |
| 362 int consecutive_problem_commits_; |
| 363 // number of commits hitting transient errors since the last successful |
| 364 // commit. |
| 365 int consecutive_transient_error_commits_; |
| 366 // Incremented when get_updates fails, commit fails, and when |
| 367 // hitting transient errors. When any of these succeed, this counter |
| 368 // is reset. |
| 369 // TODO(chron): Reduce number of weird counters we use. |
| 370 int consecutive_errors_; |
| 371 int successful_commits_; |
| 372 |
| 373 bool dirty_; |
| 374 bool auth_dirty_; |
| 375 bool auth_failed_; |
| 376 |
| 377 void UpdateDirty(bool new_info) { dirty_ |= new_info; } |
| 378 |
| 379 void UpdateAuthDirty(bool new_info) { auth_dirty_ |= new_info; } |
| 380 }; |
| 381 |
| 382 } // namespace browser_sync |
| 383 |
| 384 #endif // CHROME_BROWSER_SYNC_ENGINE_SYNC_PROCESS_STATE_H_ |
OLD | NEW |