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 // THIS CLASS PROVIDES NO SYNCHRONIZATION GUARANTEES. |
| 7 |
| 8 #include "chrome/browser/sync/engine/sync_process_state.h" |
| 9 |
| 10 #include <map> |
| 11 #include <set> |
| 12 #include <vector> |
| 13 |
| 14 #include "base/basictypes.h" |
| 15 #include "chrome/browser/sync/syncable/directory_manager.h" |
| 16 #include "chrome/browser/sync/syncable/syncable.h" |
| 17 |
| 18 using std::map; |
| 19 using std::set; |
| 20 using std::vector; |
| 21 |
| 22 namespace browser_sync { |
| 23 |
| 24 SyncProcessState::SyncProcessState(const SyncProcessState& counts) |
| 25 : account_name_(counts.account_name_), |
| 26 dirman_(counts.dirman_), |
| 27 syncer_event_channel_(counts.syncer_event_channel_), |
| 28 connection_manager_(counts.connection_manager_), |
| 29 resolver_(counts.resolver_), |
| 30 model_safe_worker_(counts.model_safe_worker_) { |
| 31 *this = counts; |
| 32 } |
| 33 |
| 34 SyncProcessState::SyncProcessState(syncable::DirectoryManager* dirman, |
| 35 PathString account_name, |
| 36 ServerConnectionManager* connection_manager, |
| 37 ConflictResolver* const resolver, |
| 38 SyncerEventChannel* syncer_event_channel, |
| 39 ModelSafeWorker* model_safe_worker) |
| 40 : account_name_(account_name), |
| 41 dirman_(dirman), |
| 42 syncer_event_channel_(syncer_event_channel), |
| 43 connection_manager_(connection_manager), |
| 44 model_safe_worker_(model_safe_worker), |
| 45 resolver_(resolver), |
| 46 syncer_stuck_(false), |
| 47 num_sync_cycles_(0), |
| 48 silenced_until_(0), |
| 49 error_rate_(0), |
| 50 current_sync_timestamp_(0), |
| 51 servers_latest_timestamp_(0), |
| 52 error_commits_(0), |
| 53 stalled_commits_(0), |
| 54 conflicting_commits_(0), |
| 55 consecutive_problem_get_updates_(0), |
| 56 consecutive_problem_commits_(0), |
| 57 consecutive_transient_error_commits_(0), |
| 58 consecutive_errors_(0), |
| 59 successful_commits_(0), |
| 60 dirty_(false), |
| 61 auth_dirty_(false), |
| 62 auth_failed_(false), |
| 63 invalid_store_(false) { |
| 64 syncable::ScopedDirLookup dir(dirman_, account_name_); |
| 65 |
| 66 // The directory must be good here. |
| 67 LOG_IF(ERROR, !dir.good()); |
| 68 syncing_ = !dir->initial_sync_ended(); |
| 69 |
| 70 // If we have never synced then we are invalid until made otherwise. |
| 71 set_invalid_store((dir->last_sync_timestamp() <= 0)); |
| 72 } |
| 73 |
| 74 SyncProcessState& SyncProcessState::operator=(const SyncProcessState& counts) { |
| 75 if (this == &counts) { |
| 76 return *this; |
| 77 } |
| 78 CleanupSets(); |
| 79 num_sync_cycles_ = counts.num_sync_cycles_; |
| 80 silenced_until_ = counts.silenced_until_; |
| 81 error_rate_ = counts.error_rate_; |
| 82 current_sync_timestamp_ = counts.current_sync_timestamp_; |
| 83 servers_latest_timestamp_ = counts.servers_latest_timestamp_; |
| 84 error_commits_ = counts.error_commits_; |
| 85 stalled_commits_ = counts.stalled_commits_; |
| 86 conflicting_commits_ = counts.conflicting_commits_; |
| 87 consecutive_problem_get_updates_ = |
| 88 counts.consecutive_problem_get_updates_; |
| 89 consecutive_problem_commits_ = |
| 90 counts.consecutive_problem_commits_; |
| 91 consecutive_transient_error_commits_ = |
| 92 counts.consecutive_transient_error_commits_; |
| 93 consecutive_errors_ = counts.consecutive_errors_; |
| 94 conflicting_item_ids_ = counts.conflicting_item_ids_; |
| 95 blocked_item_ids_ = counts.blocked_item_ids_; |
| 96 successful_commits_ = counts.successful_commits_; |
| 97 syncer_stuck_ = counts.syncer_stuck_; |
| 98 |
| 99 // TODO(chron): Is it safe to set these? |
| 100 // |
| 101 // Pointers: |
| 102 // |
| 103 // connection_manager_ |
| 104 // account_name_ |
| 105 // dirman_ |
| 106 // model_safe_worker_ |
| 107 // syncer_event_channel_ |
| 108 // |
| 109 // Status members: |
| 110 // syncing_ |
| 111 // invalid_store_ |
| 112 // syncer_stuck_ |
| 113 // got_zero_updates_ |
| 114 // dirty_ |
| 115 // auth_dirty_ |
| 116 // auth_failed_ |
| 117 |
| 118 for (set<ConflictSet*>::const_iterator it = |
| 119 counts.ConflictSetsBegin(); |
| 120 counts.ConflictSetsEnd() != it; ++it) { |
| 121 const ConflictSet* old_set = *it; |
| 122 ConflictSet* const new_set = new ConflictSet(*old_set); |
| 123 conflict_sets_.insert(new_set); |
| 124 |
| 125 for (ConflictSet::const_iterator setit = new_set->begin(); |
| 126 new_set->end() != setit; ++setit) { |
| 127 id_to_conflict_set_[*setit] = new_set; |
| 128 } |
| 129 } |
| 130 return *this; |
| 131 } |
| 132 |
| 133 // status maintenance functions |
| 134 void SyncProcessState::set_invalid_store(const bool val) { |
| 135 UpdateDirty(val != invalid_store_); |
| 136 invalid_store_ = val; |
| 137 } |
| 138 |
| 139 void SyncProcessState::set_syncer_stuck(const bool val) { |
| 140 UpdateDirty(val != syncer_stuck_); |
| 141 syncer_stuck_ = val; |
| 142 } |
| 143 |
| 144 void SyncProcessState::set_syncing(const bool val) { |
| 145 UpdateDirty(val != syncing_); |
| 146 syncing_ = val; |
| 147 } |
| 148 |
| 149 // Returns true if got zero updates has been set on the directory. |
| 150 bool SyncProcessState::IsShareUsable() const { |
| 151 syncable::ScopedDirLookup dir(dirman(), account_name()); |
| 152 if (!dir.good()) { |
| 153 LOG(ERROR) << "Scoped dir lookup failed!"; |
| 154 return false; |
| 155 } |
| 156 return dir->initial_sync_ended(); |
| 157 } |
| 158 |
| 159 void SyncProcessState::set_current_sync_timestamp(const int64 val) { |
| 160 UpdateDirty(val != current_sync_timestamp_); |
| 161 current_sync_timestamp_ = val; |
| 162 } |
| 163 |
| 164 void SyncProcessState::set_servers_latest_timestamp(const int64 val) { |
| 165 UpdateDirty(val != servers_latest_timestamp_); |
| 166 servers_latest_timestamp_ = val; |
| 167 } |
| 168 |
| 169 void SyncProcessState::set_error_commits(const int val) { |
| 170 UpdateDirty(val != error_commits_); |
| 171 error_commits_ = val; |
| 172 } |
| 173 |
| 174 void SyncProcessState::set_stalled_commits(const int val) { |
| 175 UpdateDirty(val != conflicting_commits_); |
| 176 conflicting_commits_ = val; |
| 177 } |
| 178 |
| 179 void SyncProcessState::set_conflicting_commits(const int val) { |
| 180 UpdateDirty(val != stalled_commits_); |
| 181 stalled_commits_ = val; |
| 182 } |
| 183 |
| 184 // WEIRD COUNTER functions |
| 185 void SyncProcessState::increment_consecutive_problem_get_updates() { |
| 186 UpdateDirty(true); |
| 187 ++consecutive_problem_get_updates_; |
| 188 } |
| 189 |
| 190 void SyncProcessState::zero_consecutive_problem_get_updates() { |
| 191 UpdateDirty(0 != consecutive_problem_get_updates_); |
| 192 consecutive_problem_get_updates_ = 0; |
| 193 } |
| 194 |
| 195 void SyncProcessState::increment_consecutive_problem_commits() { |
| 196 UpdateDirty(true); |
| 197 ++consecutive_problem_commits_; |
| 198 } |
| 199 |
| 200 void SyncProcessState::zero_consecutive_problem_commits() { |
| 201 UpdateDirty(0 != consecutive_problem_commits_); |
| 202 consecutive_problem_commits_ = 0; |
| 203 } |
| 204 |
| 205 void SyncProcessState::increment_consecutive_transient_error_commits_by( |
| 206 int value) { |
| 207 UpdateDirty(0 != value); |
| 208 consecutive_transient_error_commits_ += value; |
| 209 } |
| 210 |
| 211 void SyncProcessState::zero_consecutive_transient_error_commits() { |
| 212 UpdateDirty(0 != consecutive_transient_error_commits_); |
| 213 consecutive_transient_error_commits_ = 0; |
| 214 } |
| 215 |
| 216 void SyncProcessState::increment_consecutive_errors_by(int value) { |
| 217 UpdateDirty(0 != value); |
| 218 consecutive_errors_ += value; |
| 219 } |
| 220 |
| 221 void SyncProcessState::zero_consecutive_errors() { |
| 222 UpdateDirty(0 != consecutive_errors_); |
| 223 consecutive_errors_ = 0; |
| 224 } |
| 225 |
| 226 void SyncProcessState::increment_successful_commits() { |
| 227 UpdateDirty(true); |
| 228 ++successful_commits_; |
| 229 } |
| 230 |
| 231 void SyncProcessState::zero_successful_commits() { |
| 232 UpdateDirty(0 != successful_commits_); |
| 233 successful_commits_ = 0; |
| 234 } |
| 235 |
| 236 // Methods for managing error rate tracking |
| 237 void SyncProcessState::TallyNewError() { |
| 238 UpdateDirty(true); |
| 239 error_rate_ += (65536 - error_rate_) >> 2; |
| 240 } |
| 241 |
| 242 void SyncProcessState::TallyBigNewError() { |
| 243 UpdateDirty(true); |
| 244 error_rate_ += (65536 - error_rate_) >> 2; |
| 245 } |
| 246 |
| 247 void SyncProcessState::ForgetOldError() { |
| 248 error_rate_ -= error_rate_ >> 2; |
| 249 } |
| 250 |
| 251 void SyncProcessState::CheckErrorRateTooHigh() { |
| 252 UpdateDirty(error_rate_ > ERROR_THRESHOLD); |
| 253 } |
| 254 |
| 255 |
| 256 void SyncProcessState::MergeSets(const syncable::Id& id1, |
| 257 const syncable::Id& id2) { |
| 258 // There are no single item sets, we just leave those entries == 0 |
| 259 vector<syncable::Id>* set1 = id_to_conflict_set_[id1]; |
| 260 vector<syncable::Id>* set2 = id_to_conflict_set_[id2]; |
| 261 vector<syncable::Id>* rv = 0; |
| 262 if (0 == set1 && 0 == set2) { |
| 263 // neither item currently has a set so we build one. |
| 264 rv = new vector<syncable::Id>(); |
| 265 rv->push_back(id1); |
| 266 if (id1 != id2) { |
| 267 rv->push_back(id2); |
| 268 } else { |
| 269 LOG(WARNING) << "[BUG] Attempting to merge two identical conflict ids."; |
| 270 } |
| 271 conflict_sets_.insert(rv); |
| 272 } else if (0 == set1) { |
| 273 // add the item to the existing set. |
| 274 rv = set2; |
| 275 rv->push_back(id1); |
| 276 } else if (0 == set2) { |
| 277 // add the item to the existing set. |
| 278 rv = set1; |
| 279 rv->push_back(id2); |
| 280 } else if (set1 == set2) { |
| 281 // It's the same set already |
| 282 return; |
| 283 } else { |
| 284 // merge the two sets. |
| 285 rv = set1; |
| 286 // point all the second sets id's back to the first. |
| 287 vector<syncable::Id>::iterator i; |
| 288 for (i = set2->begin() ; i != set2->end() ; ++i) { |
| 289 id_to_conflict_set_[*i] = rv; |
| 290 } |
| 291 // copy the second set to the first. |
| 292 rv->insert(rv->end(), set2->begin(), set2->end()); |
| 293 conflict_sets_.erase(set2); |
| 294 delete set2; |
| 295 } |
| 296 id_to_conflict_set_[id1] = id_to_conflict_set_[id2] = rv; |
| 297 } |
| 298 |
| 299 void SyncProcessState::CleanupSets() { |
| 300 // Clean up all the sets. |
| 301 set<ConflictSet*>::iterator i; |
| 302 for (i = conflict_sets_.begin(); i != conflict_sets_.end(); i++) { |
| 303 delete *i; |
| 304 } |
| 305 conflict_sets_.clear(); |
| 306 id_to_conflict_set_.clear(); |
| 307 } |
| 308 |
| 309 SyncProcessState::~SyncProcessState() { |
| 310 CleanupSets(); |
| 311 } |
| 312 |
| 313 void SyncProcessState::AuthFailed() { |
| 314 // dirty if the last one DIDN'T fail. |
| 315 UpdateAuthDirty(true != auth_failed_); |
| 316 auth_failed_ = true; |
| 317 } |
| 318 |
| 319 void SyncProcessState::AuthSucceeded() { |
| 320 // dirty if the last one DID fail. |
| 321 UpdateAuthDirty(false != auth_failed_); |
| 322 auth_failed_ = false; |
| 323 } |
| 324 |
| 325 } // namespace browser_sync |
OLD | NEW |