status_controller.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
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 file. 4 5#include "chrome/browser/sync/sessions/status_controller.h" 6 7#include "base/basictypes.h" 8#include "chrome/browser/sync/syncable/model_type.h" 9 10namespace browser_sync { 11namespace sessions { 12 13using syncable::FIRST_REAL_MODEL_TYPE; 14using syncable::MODEL_TYPE_COUNT; 15 16StatusController::StatusController(const ModelSafeRoutingInfo& routes) 17 : shared_(&is_dirty_), 18 per_model_group_deleter_(&per_model_group_), 19 per_model_type_deleter_(&per_model_type_), 20 is_dirty_(false), 21 group_restriction_in_effect_(false), 22 group_restriction_(GROUP_PASSIVE), 23 routing_info_(routes) { 24} 25 26bool StatusController::TestAndClearIsDirty() { 27 bool is_dirty = is_dirty_; 28 is_dirty_ = false; 29 return is_dirty; 30} 31 32PerModelSafeGroupState* StatusController::GetOrCreateModelSafeGroupState( 33 bool restrict, ModelSafeGroup group) { 34 DCHECK(restrict == group_restriction_in_effect_) << "Group violation!"; 35 if (per_model_group_.find(group) == per_model_group_.end()) { 36 PerModelSafeGroupState* state = new PerModelSafeGroupState(&is_dirty_); 37 per_model_group_[group] = state; 38 return state; 39 } 40 return per_model_group_[group]; 41} 42 43PerModelTypeState* StatusController::GetOrCreateModelTypeState( 44 bool restrict, syncable::ModelType model) { 45 if (restrict) { 46 DCHECK(group_restriction_in_effect_) << "No group restriction in effect!"; 47 DCHECK_EQ(group_restriction_, GetGroupForModelType(model, routing_info_)); 48 } 49 if (per_model_type_.find(model) == per_model_type_.end()) { 50 PerModelTypeState* state = new PerModelTypeState(&is_dirty_); 51 per_model_type_[model] = state; 52 return state; 53 } 54 return per_model_type_[model]; 55} 56 57void StatusController::increment_num_conflicting_commits_by(int value) { 58 if (value == 0) 59 return; 60 shared_.error_counters.mutate()->num_conflicting_commits += value; 61} 62 63void StatusController::reset_num_conflicting_commits() { 64 if (shared_.error_counters.value().num_conflicting_commits != 0) 65 shared_.error_counters.mutate()->num_conflicting_commits = 0; 66} 67 68void StatusController::set_num_consecutive_transient_error_commits(int value) { 69 if (shared_.error_counters.value().consecutive_transient_error_commits != 70 value) { 71 shared_.error_counters.mutate()->consecutive_transient_error_commits = 72 value; 73 } 74} 75 76void StatusController::increment_num_consecutive_transient_error_commits_by( 77 int value) { 78 set_num_consecutive_transient_error_commits( 79 shared_.error_counters.value().consecutive_transient_error_commits + 80 value); 81} 82 83void StatusController::set_num_consecutive_errors(int value) { 84 if (shared_.error_counters.value().consecutive_errors != value) 85 shared_.error_counters.mutate()->consecutive_errors = value; 86} 87 88void StatusController::set_current_download_timestamp( 89 syncable::ModelType model, 90 int64 current_timestamp) { 91 PerModelTypeState* state = GetOrCreateModelTypeState(false, model); 92 if (current_timestamp > state->current_download_timestamp.value()) 93 *(state->current_download_timestamp.mutate()) = current_timestamp; 94} 95 96void StatusController::set_num_server_changes_remaining( 97 int64 changes_remaining) { 98 if (shared_.num_server_changes_remaining.value() != changes_remaining) 99 *(shared_.num_server_changes_remaining.mutate()) = changes_remaining; 100} 101 102void StatusController::set_over_quota(bool over_quota) { 103 if (shared_.syncer_status.value().over_quota != over_quota) 104 shared_.syncer_status.mutate()->over_quota = over_quota; 105} 106 107void StatusController::set_invalid_store(bool invalid_store) { 108 if (shared_.syncer_status.value().invalid_store != invalid_store) 109 shared_.syncer_status.mutate()->invalid_store = invalid_store; 110} 111 112void StatusController::set_syncer_stuck(bool syncer_stuck) { 113 if (shared_.syncer_status.value().syncer_stuck != syncer_stuck) 114 shared_.syncer_status.mutate()->syncer_stuck = syncer_stuck; 115} 116 117void StatusController::set_syncing(bool syncing) { 118 if (shared_.syncer_status.value().syncing != syncing) 119 shared_.syncer_status.mutate()->syncing = syncing; 120} 121 122void StatusController::set_num_successful_bookmark_commits(int value) { 123 if (shared_.syncer_status.value().num_successful_bookmark_commits != value) 124 shared_.syncer_status.mutate()->num_successful_bookmark_commits = value; 125} 126 127void StatusController::set_unsynced_handles( 128 const std::vector<int64>& unsynced_handles) { 129 if (!operator==(unsynced_handles, shared_.unsynced_handles.value())) { 130 *(shared_.unsynced_handles.mutate()) = unsynced_handles; 131 } 132} 133 134void StatusController::increment_num_consecutive_errors() { 135 set_num_consecutive_errors( 136 shared_.error_counters.value().consecutive_errors + 1); 137} 138 139void StatusController::increment_num_consecutive_errors_by(int value) { 140 set_num_consecutive_errors( 141 shared_.error_counters.value().consecutive_errors + value); 142} 143 144void StatusController::increment_num_successful_bookmark_commits() { 145 set_num_successful_bookmark_commits( 146 shared_.syncer_status.value().num_successful_bookmark_commits + 1); 147} 148 149void StatusController::increment_num_successful_commits() { 150 shared_.syncer_status.mutate()->num_successful_commits++; 151} 152 153void StatusController::set_commit_set(const OrderedCommitSet& commit_set) { 154 DCHECK(!group_restriction_in_effect_); 155 shared_.commit_set = commit_set; 156} 157 158void StatusController::update_conflict_sets_built(bool built) { 159 shared_.control_params.conflict_sets_built |= built; 160} 161void StatusController::update_conflicts_resolved(bool resolved) { 162 shared_.control_params.conflict_sets_built |= resolved; 163} 164void StatusController::reset_conflicts_resolved() { 165 shared_.control_params.conflicts_resolved = false; 166} 167void StatusController::set_items_committed() { 168 shared_.control_params.items_committed = true; 169} 170 171// Returns the number of updates received from the sync server. 172int64 StatusController::CountUpdates() const { 173 const ClientToServerResponse& updates = shared_.updates_response; 174 if (updates.has_get_updates()) { 175 return updates.get_updates().entries().size(); 176 } else { 177 return 0; 178 } 179} 180 181bool StatusController::CurrentCommitIdProjectionHasIndex(size_t index) { 182 OrderedCommitSet::Projection proj = 183 shared_.commit_set.GetCommitIdProjection(group_restriction_); 184 return std::binary_search(proj.begin(), proj.end(), index); 185} 186 187int64 StatusController::ComputeMaxLocalTimestamp() const { 188 std::map<syncable::ModelType, PerModelTypeState*>::const_iterator it = 189 per_model_type_.begin(); 190 int64 max_timestamp = 0; 191 for (; it != per_model_type_.end(); ++it) { 192 if (it->second->current_download_timestamp.value() > max_timestamp) 193 max_timestamp = it->second->current_download_timestamp.value(); 194 } 195 return max_timestamp; 196} 197 198bool StatusController::HasConflictingUpdates() const { 199 DCHECK(!group_restriction_in_effect_) 200 << "HasConflictingUpdates applies to all ModelSafeGroups"; 201 std::map<ModelSafeGroup, PerModelSafeGroupState*>::const_iterator it = 202 per_model_group_.begin(); 203 for (; it != per_model_group_.end(); ++it) { 204 if (it->second->update_progress.HasConflictingUpdates()) 205 return true; 206 } 207 return false; 208} 209 210int StatusController::TotalNumConflictingItems() const { 211 DCHECK(!group_restriction_in_effect_) 212 << "TotalNumConflictingItems applies to all ModelSafeGroups"; 213 std::map<ModelSafeGroup, PerModelSafeGroupState*>::const_iterator it = 214 per_model_group_.begin(); 215 int sum = 0; 216 for (; it != per_model_group_.end(); ++it) { 217 sum += it->second->conflict_progress.ConflictingItemsSize(); 218 } 219 return sum; 220} 221 222bool StatusController::ServerSaysNothingMoreToDownload() const { 223 if (!download_updates_succeeded()) 224 return false; 225 // If we didn't request every enabled datatype, then we can't say for 226 // sure that there's nothing left to download. 227 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { 228 if (!updates_request_parameters().data_types[i] && 229 routing_info_.count(syncable::ModelTypeFromInt(i)) != 0) { 230 return false; 231 } 232 } 233 // The server indicates "you're up to date" by not sending a new 234 // timestamp. 235 return !updates_response().get_updates().has_new_timestamp(); 236} 237 238} // namespace sessions 239} // namespace browser_sync 240