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 10 namespace browser_sync { 11 namespace sessions { 12 13 using syncable::FIRST_REAL_MODEL_TYPE; 14 using syncable::MODEL_TYPE_COUNT; 15 16 StatusController::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 25 StatusController::~StatusController() {} 26 27 bool StatusController::TestAndClearIsDirty() { 28 bool is_dirty = is_dirty_; 29 is_dirty_ = false; 30 return is_dirty; 31 } 32 33 PerModelSafeGroupState* 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 44 void 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 50 void StatusController::increment_num_updates_downloaded_by(int value) { 51 shared_.syncer_status.mutate()->num_updates_downloaded_total += value; 52 } 53 54 void StatusController::set_types_needing_local_migration( 55 const syncable::ModelTypeSet& types) { 56 shared_.syncer_status.mutate()->types_needing_local_migration = types; 57 } 58 59 void StatusController::increment_num_tombstone_updates_downloaded_by( 60 int value) { 61 shared_.syncer_status.mutate()->num_tombstone_updates_downloaded_total += 62 value; 63 } 64 65 void 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 70 void 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 78 void 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 85 void 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 90 void 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 96 void 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 101 void 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 106 void StatusController::set_syncing(bool syncing) { 107 if (shared_.syncer_status.value().syncing != syncing) 108 shared_.syncer_status.mutate()->syncing = syncing; 109 } 110 111 void 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 116 void 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 123 void StatusController::increment_num_consecutive_errors() { 124 set_num_consecutive_errors( 125 shared_.error_counters.value().consecutive_errors + 1); 126 } 127 128 void StatusController::increment_num_consecutive_errors_by(int value) { 129 set_num_consecutive_errors( 130 shared_.error_counters.value().consecutive_errors + value); 131 } 132 133 void StatusController::increment_num_successful_bookmark_commits() { 134 set_num_successful_bookmark_commits( 135 shared_.syncer_status.value().num_successful_bookmark_commits + 1); 136 } 137 138 void StatusController::increment_num_successful_commits() { 139 shared_.syncer_status.mutate()->num_successful_commits++; 140 } 141 142 void StatusController::set_commit_set(const OrderedCommitSet& commit_set) { 143 DCHECK(!group_restriction_in_effect_); 144 shared_.commit_set = commit_set; 145 } 146 147 void StatusController::update_conflict_sets_built(bool built) { 148 shared_.control_params.conflict_sets_built |= built; 149 } 150 void StatusController::update_conflicts_resolved(bool resolved) { 151 shared_.control_params.conflict_sets_built |= resolved; 152 } 153 void StatusController::reset_conflicts_resolved() { 154 shared_.control_params.conflicts_resolved = false; 155 } 156 void StatusController::set_items_committed() { 157 shared_.control_params.items_committed = true; 158 } 159 160 // Returns the number of updates received from the sync server. 161 int64 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 170 bool 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 176 bool 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 188 int 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 200 bool 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