diff options
Diffstat (limited to 'chrome/browser/sync/engine/sync_process_state.cc')
-rw-r--r-- | chrome/browser/sync/engine/sync_process_state.cc | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/chrome/browser/sync/engine/sync_process_state.cc b/chrome/browser/sync/engine/sync_process_state.cc new file mode 100644 index 0000000..6f76eee --- /dev/null +++ b/chrome/browser/sync/engine/sync_process_state.cc @@ -0,0 +1,325 @@ +// 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. + +// +// THIS CLASS PROVIDES NO SYNCHRONIZATION GUARANTEES. + +#include "chrome/browser/sync/engine/sync_process_state.h" + +#include <map> +#include <set> +#include <vector> + +#include "base/basictypes.h" +#include "chrome/browser/sync/syncable/directory_manager.h" +#include "chrome/browser/sync/syncable/syncable.h" + +using std::map; +using std::set; +using std::vector; + +namespace browser_sync { + +SyncProcessState::SyncProcessState(const SyncProcessState& counts) + : account_name_(counts.account_name_), + dirman_(counts.dirman_), + syncer_event_channel_(counts.syncer_event_channel_), + connection_manager_(counts.connection_manager_), + resolver_(counts.resolver_), + model_safe_worker_(counts.model_safe_worker_) { + *this = counts; +} + +SyncProcessState::SyncProcessState(syncable::DirectoryManager* dirman, + PathString account_name, + ServerConnectionManager* connection_manager, + ConflictResolver* const resolver, + SyncerEventChannel* syncer_event_channel, + ModelSafeWorker* model_safe_worker) + : account_name_(account_name), + dirman_(dirman), + syncer_event_channel_(syncer_event_channel), + connection_manager_(connection_manager), + model_safe_worker_(model_safe_worker), + resolver_(resolver), + syncer_stuck_(false), + num_sync_cycles_(0), + silenced_until_(0), + error_rate_(0), + current_sync_timestamp_(0), + servers_latest_timestamp_(0), + error_commits_(0), + stalled_commits_(0), + conflicting_commits_(0), + consecutive_problem_get_updates_(0), + consecutive_problem_commits_(0), + consecutive_transient_error_commits_(0), + consecutive_errors_(0), + successful_commits_(0), + dirty_(false), + auth_dirty_(false), + auth_failed_(false), + invalid_store_(false) { + syncable::ScopedDirLookup dir(dirman_, account_name_); + + // The directory must be good here. + LOG_IF(ERROR, !dir.good()); + syncing_ = !dir->initial_sync_ended(); + + // If we have never synced then we are invalid until made otherwise. + set_invalid_store((dir->last_sync_timestamp() <= 0)); +} + +SyncProcessState& SyncProcessState::operator=(const SyncProcessState& counts) { + if (this == &counts) { + return *this; + } + CleanupSets(); + num_sync_cycles_ = counts.num_sync_cycles_; + silenced_until_ = counts.silenced_until_; + error_rate_ = counts.error_rate_; + current_sync_timestamp_ = counts.current_sync_timestamp_; + servers_latest_timestamp_ = counts.servers_latest_timestamp_; + error_commits_ = counts.error_commits_; + stalled_commits_ = counts.stalled_commits_; + conflicting_commits_ = counts.conflicting_commits_; + consecutive_problem_get_updates_ = + counts.consecutive_problem_get_updates_; + consecutive_problem_commits_ = + counts.consecutive_problem_commits_; + consecutive_transient_error_commits_ = + counts.consecutive_transient_error_commits_; + consecutive_errors_ = counts.consecutive_errors_; + conflicting_item_ids_ = counts.conflicting_item_ids_; + blocked_item_ids_ = counts.blocked_item_ids_; + successful_commits_ = counts.successful_commits_; + syncer_stuck_ = counts.syncer_stuck_; + + // TODO(chron): Is it safe to set these? + // + // Pointers: + // + // connection_manager_ + // account_name_ + // dirman_ + // model_safe_worker_ + // syncer_event_channel_ + // + // Status members: + // syncing_ + // invalid_store_ + // syncer_stuck_ + // got_zero_updates_ + // dirty_ + // auth_dirty_ + // auth_failed_ + + for (set<ConflictSet*>::const_iterator it = + counts.ConflictSetsBegin(); + counts.ConflictSetsEnd() != it; ++it) { + const ConflictSet* old_set = *it; + ConflictSet* const new_set = new ConflictSet(*old_set); + conflict_sets_.insert(new_set); + + for (ConflictSet::const_iterator setit = new_set->begin(); + new_set->end() != setit; ++setit) { + id_to_conflict_set_[*setit] = new_set; + } + } + return *this; +} + +// status maintenance functions +void SyncProcessState::set_invalid_store(const bool val) { + UpdateDirty(val != invalid_store_); + invalid_store_ = val; +} + +void SyncProcessState::set_syncer_stuck(const bool val) { + UpdateDirty(val != syncer_stuck_); + syncer_stuck_ = val; +} + +void SyncProcessState::set_syncing(const bool val) { + UpdateDirty(val != syncing_); + syncing_ = val; +} + +// Returns true if got zero updates has been set on the directory. +bool SyncProcessState::IsShareUsable() const { + syncable::ScopedDirLookup dir(dirman(), account_name()); + if (!dir.good()) { + LOG(ERROR) << "Scoped dir lookup failed!"; + return false; + } + return dir->initial_sync_ended(); +} + +void SyncProcessState::set_current_sync_timestamp(const int64 val) { + UpdateDirty(val != current_sync_timestamp_); + current_sync_timestamp_ = val; +} + +void SyncProcessState::set_servers_latest_timestamp(const int64 val) { + UpdateDirty(val != servers_latest_timestamp_); + servers_latest_timestamp_ = val; +} + +void SyncProcessState::set_error_commits(const int val) { + UpdateDirty(val != error_commits_); + error_commits_ = val; +} + +void SyncProcessState::set_stalled_commits(const int val) { + UpdateDirty(val != conflicting_commits_); + conflicting_commits_ = val; +} + +void SyncProcessState::set_conflicting_commits(const int val) { + UpdateDirty(val != stalled_commits_); + stalled_commits_ = val; +} + +// WEIRD COUNTER functions +void SyncProcessState::increment_consecutive_problem_get_updates() { + UpdateDirty(true); + ++consecutive_problem_get_updates_; +} + +void SyncProcessState::zero_consecutive_problem_get_updates() { + UpdateDirty(0 != consecutive_problem_get_updates_); + consecutive_problem_get_updates_ = 0; +} + +void SyncProcessState::increment_consecutive_problem_commits() { + UpdateDirty(true); + ++consecutive_problem_commits_; +} + +void SyncProcessState::zero_consecutive_problem_commits() { + UpdateDirty(0 != consecutive_problem_commits_); + consecutive_problem_commits_ = 0; +} + +void SyncProcessState::increment_consecutive_transient_error_commits_by( + int value) { + UpdateDirty(0 != value); + consecutive_transient_error_commits_ += value; +} + +void SyncProcessState::zero_consecutive_transient_error_commits() { + UpdateDirty(0 != consecutive_transient_error_commits_); + consecutive_transient_error_commits_ = 0; +} + +void SyncProcessState::increment_consecutive_errors_by(int value) { + UpdateDirty(0 != value); + consecutive_errors_ += value; +} + +void SyncProcessState::zero_consecutive_errors() { + UpdateDirty(0 != consecutive_errors_); + consecutive_errors_ = 0; +} + +void SyncProcessState::increment_successful_commits() { + UpdateDirty(true); + ++successful_commits_; +} + +void SyncProcessState::zero_successful_commits() { + UpdateDirty(0 != successful_commits_); + successful_commits_ = 0; +} + +// Methods for managing error rate tracking +void SyncProcessState::TallyNewError() { + UpdateDirty(true); + error_rate_ += (65536 - error_rate_) >> 2; +} + +void SyncProcessState::TallyBigNewError() { + UpdateDirty(true); + error_rate_ += (65536 - error_rate_) >> 2; +} + +void SyncProcessState::ForgetOldError() { + error_rate_ -= error_rate_ >> 2; +} + +void SyncProcessState::CheckErrorRateTooHigh() { + UpdateDirty(error_rate_ > ERROR_THRESHOLD); +} + + +void SyncProcessState::MergeSets(const syncable::Id& id1, + const syncable::Id& id2) { + // There are no single item sets, we just leave those entries == 0 + vector<syncable::Id>* set1 = id_to_conflict_set_[id1]; + vector<syncable::Id>* set2 = id_to_conflict_set_[id2]; + vector<syncable::Id>* rv = 0; + if (0 == set1 && 0 == set2) { + // neither item currently has a set so we build one. + rv = new vector<syncable::Id>(); + rv->push_back(id1); + if (id1 != id2) { + rv->push_back(id2); + } else { + LOG(WARNING) << "[BUG] Attempting to merge two identical conflict ids."; + } + conflict_sets_.insert(rv); + } else if (0 == set1) { + // add the item to the existing set. + rv = set2; + rv->push_back(id1); + } else if (0 == set2) { + // add the item to the existing set. + rv = set1; + rv->push_back(id2); + } else if (set1 == set2) { + // It's the same set already + return; + } else { + // merge the two sets. + rv = set1; + // point all the second sets id's back to the first. + vector<syncable::Id>::iterator i; + for (i = set2->begin() ; i != set2->end() ; ++i) { + id_to_conflict_set_[*i] = rv; + } + // copy the second set to the first. + rv->insert(rv->end(), set2->begin(), set2->end()); + conflict_sets_.erase(set2); + delete set2; + } + id_to_conflict_set_[id1] = id_to_conflict_set_[id2] = rv; +} + +void SyncProcessState::CleanupSets() { + // Clean up all the sets. + set<ConflictSet*>::iterator i; + for (i = conflict_sets_.begin(); i != conflict_sets_.end(); i++) { + delete *i; + } + conflict_sets_.clear(); + id_to_conflict_set_.clear(); +} + +SyncProcessState::~SyncProcessState() { + CleanupSets(); +} + +void SyncProcessState::AuthFailed() { + // dirty if the last one DIDN'T fail. + UpdateAuthDirty(true != auth_failed_); + auth_failed_ = true; +} + +void SyncProcessState::AuthSucceeded() { + // dirty if the last one DID fail. + UpdateAuthDirty(false != auth_failed_); + auth_failed_ = false; +} + +} // namespace browser_sync |