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 is_dirty_(false), 20 group_restriction_in_effect_(false), 21 group_restriction_(GROUP_PASSIVE), 22 routing_info_(routes) { 23} 24 25StatusController::~StatusController() {} 26 27bool StatusController::TestAndClearIsDirty() { 28 bool is_dirty = is_dirty_; 29 is_dirty_ = false; 30 return is_dirty; 31} 32 33PerModelSafeGroupState* StatusController::GetOrCreateModelSafeGroupState( 34 bool restrict, ModelSafeGroup group) { 35 DCHECK(restrict == group_restriction_in_effect_) << "Group violation!"; 36 if (per_model_group_.find(group) == per_model_group_.end()) { 37 PerModelSafeGroupState* state = new PerModelSafeGroupState(&is_dirty_); 38 per_model_group_[group] = state; 39 return state; 40 } 41 return per_model_group_[group]; 42} 43 44void StatusController::increment_num_conflicting_commits_by(int value) { 45 if (value == 0) 46 return; 47 shared_.error_counters.mutate()->num_conflicting_commits += value; 48} 49 50void StatusController::increment_num_updates_downloaded_by(int value) { 51 shared_.syncer_status.mutate()->num_updates_downloaded_total += value; 52} 53 54void StatusController::set_types_needing_local_migration( 55 const syncable::ModelTypeSet& types) { 56 shared_.syncer_status.mutate()->types_needing_local_migration = types; 57} 58 59void StatusController::increment_num_tombstone_updates_downloaded_by( 60 int value) { 61 shared_.syncer_status.mutate()->num_tombstone_updates_downloaded_total += 62 value; 63} 64 65void StatusController::reset_num_conflicting_commits() { 66 if (shared_.error_counters.value().num_conflicting_commits != 0) 67 shared_.error_counters.mutate()->num_conflicting_commits = 0; 68} 69 70void StatusController::set_num_consecutive_transient_error_commits(int value) { 71 if (shared_.error_counters.value().consecutive_transient_error_commits != 72 value) { 73 shared_.error_counters.mutate()->consecutive_transient_error_commits = 74 value; 75 } 76} 77 78void StatusController::increment_num_consecutive_transient_error_commits_by( 79 int value) { 80 set_num_consecutive_transient_error_commits( 81 shared_.error_counters.value().consecutive_transient_error_commits + 82 value); 83} 84 85void StatusController::set_num_consecutive_errors(int value) { 86 if (shared_.error_counters.value().consecutive_errors != value) 87 shared_.error_counters.mutate()->consecutive_errors = value; 88} 89 90void StatusController::set_num_server_changes_remaining( 91 int64 changes_remaining) { 92 if (shared_.num_server_changes_remaining.value() != changes_remaining) 93 *(shared_.num_server_changes_remaining.mutate()) = changes_remaining; 94} 95 96void StatusController::set_invalid_store(bool invalid_store) { 97 if (shared_.syncer_status.value().invalid_store != invalid_store) 98 shared_.syncer_status.mutate()->invalid_store = invalid_store; 99} 100 101void StatusController::set_syncer_stuck(bool syncer_stuck) { 102 if (shared_.syncer_status.value().syncer_stuck != syncer_stuck) 103 shared_.syncer_status.mutate()->syncer_stuck = syncer_stuck; 104} 105 106void StatusController::set_syncing(bool syncing) { 107 if (shared_.syncer_status.value().syncing != syncing) 108 shared_.syncer_status.mutate()->syncing = syncing; 109} 110 111void StatusController::set_num_successful_bookmark_commits(int value) { 112 if (shared_.syncer_status.value().num_successful_bookmark_commits != value) 113 shared_.syncer_status.mutate()->num_successful_bookmark_commits = value; 114} 115 116void StatusController::set_unsynced_handles( 117 const std::vector<int64>& unsynced_handles) { 118 if (!operator==(unsynced_handles, shared_.unsynced_handles.value())) { 119 *(shared_.unsynced_handles.mutate()) = unsynced_handles; 120 } 121} 122 123void StatusController::increment_num_consecutive_errors() { 124 set_num_consecutive_errors( 125 shared_.error_counters.value().consecutive_errors + 1); 126} 127 128void StatusController::increment_num_consecutive_errors_by(int value) { 129 set_num_consecutive_errors( 130 shared_.error_counters.value().consecutive_errors + value); 131} 132 133void StatusController::increment_num_successful_bookmark_commits() { 134 set_num_successful_bookmark_commits( 135 shared_.syncer_status.value().num_successful_bookmark_commits + 1); 136} 137 138void StatusController::increment_num_successful_commits() { 139 shared_.syncer_status.mutate()->num_successful_commits++; 140} 141 142void StatusController::set_commit_set(const OrderedCommitSet& commit_set) { 143 DCHECK(!group_restriction_in_effect_); 144 shared_.commit_set = commit_set; 145} 146 147void StatusController::update_conflict_sets_built(bool built) { 148 shared_.control_params.conflict_sets_built |= built; 149} 150void StatusController::update_conflicts_resolved(bool resolved) { 151 shared_.control_params.conflict_sets_built |= resolved; 152} 153void StatusController::reset_conflicts_resolved() { 154 shared_.control_params.conflicts_resolved = false; 155} 156void StatusController::set_items_committed() { 157 shared_.control_params.items_committed = true; 158} 159 160// Returns the number of updates received from the sync server. 161int64 StatusController::CountUpdates() const { 162 const ClientToServerResponse& updates = shared_.updates_response; 163 if (updates.has_get_updates()) { 164 return updates.get_updates().entries().size(); 165 } else { 166 return 0; 167 } 168} 169 170bool StatusController::CurrentCommitIdProjectionHasIndex(size_t index) { 171 OrderedCommitSet::Projection proj = 172 shared_.commit_set.GetCommitIdProjection(group_restriction_); 173 return std::binary_search(proj.begin(), proj.end(), index); 174} 175 176bool StatusController::HasConflictingUpdates() const { 177 DCHECK(!group_restriction_in_effect_) 178 << "HasConflictingUpdates applies to all ModelSafeGroups"; 179 std::map<ModelSafeGroup, PerModelSafeGroupState*>::const_iterator it = 180 per_model_group_.begin(); 181 for (; it != per_model_group_.end(); ++it) { 182 if (it->second->update_progress.HasConflictingUpdates()) 183 return true; 184 } 185 return false; 186} 187 188int StatusController::TotalNumConflictingItems() const { 189 DCHECK(!group_restriction_in_effect_) 190 << "TotalNumConflictingItems applies to all ModelSafeGroups"; 191 std::map<ModelSafeGroup, PerModelSafeGroupState*>::const_iterator it = 192 per_model_group_.begin(); 193 int sum = 0; 194 for (; it != per_model_group_.end(); ++it) { 195 sum += it->second->conflict_progress.ConflictingItemsSize(); 196 } 197 return sum; 198} 199 200bool StatusController::ServerSaysNothingMoreToDownload() const { 201 if (!download_updates_succeeded()) 202 return false; 203 204 if (!updates_response().get_updates().has_changes_remaining()) { 205 NOTREACHED(); // Server should always send changes remaining. 206 return false; // Avoid looping forever. 207 } 208 // Changes remaining is an estimate, but if it's estimated to be 209 // zero, that's firm and we don't have to ask again. 210 return updates_response().get_updates().changes_remaining() == 0; 211} 212 213} // namespace sessions 214} // namespace browser_sync 215