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
StatusController(const ModelSafeRoutingInfo & routes)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
~StatusController()25 StatusController::~StatusController() {}
26
TestAndClearIsDirty()27 bool StatusController::TestAndClearIsDirty() {
28 bool is_dirty = is_dirty_;
29 is_dirty_ = false;
30 return is_dirty;
31 }
32
GetOrCreateModelSafeGroupState(bool restrict,ModelSafeGroup group)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
increment_num_conflicting_commits_by(int value)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
increment_num_updates_downloaded_by(int value)50 void StatusController::increment_num_updates_downloaded_by(int value) {
51 shared_.syncer_status.mutate()->num_updates_downloaded_total += value;
52 }
53
set_types_needing_local_migration(const syncable::ModelTypeSet & types)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
increment_num_tombstone_updates_downloaded_by(int value)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
reset_num_conflicting_commits()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
set_num_consecutive_transient_error_commits(int value)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
increment_num_consecutive_transient_error_commits_by(int value)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
set_num_consecutive_errors(int value)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
set_num_server_changes_remaining(int64 changes_remaining)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
set_invalid_store(bool invalid_store)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
set_syncer_stuck(bool syncer_stuck)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
set_syncing(bool syncing)106 void StatusController::set_syncing(bool syncing) {
107 if (shared_.syncer_status.value().syncing != syncing)
108 shared_.syncer_status.mutate()->syncing = syncing;
109 }
110
set_num_successful_bookmark_commits(int value)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
set_unsynced_handles(const std::vector<int64> & unsynced_handles)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
increment_num_consecutive_errors()123 void StatusController::increment_num_consecutive_errors() {
124 set_num_consecutive_errors(
125 shared_.error_counters.value().consecutive_errors + 1);
126 }
127
increment_num_consecutive_errors_by(int value)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
increment_num_successful_bookmark_commits()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
increment_num_successful_commits()138 void StatusController::increment_num_successful_commits() {
139 shared_.syncer_status.mutate()->num_successful_commits++;
140 }
141
set_commit_set(const OrderedCommitSet & commit_set)142 void StatusController::set_commit_set(const OrderedCommitSet& commit_set) {
143 DCHECK(!group_restriction_in_effect_);
144 shared_.commit_set = commit_set;
145 }
146
update_conflict_sets_built(bool built)147 void StatusController::update_conflict_sets_built(bool built) {
148 shared_.control_params.conflict_sets_built |= built;
149 }
update_conflicts_resolved(bool resolved)150 void StatusController::update_conflicts_resolved(bool resolved) {
151 shared_.control_params.conflict_sets_built |= resolved;
152 }
reset_conflicts_resolved()153 void StatusController::reset_conflicts_resolved() {
154 shared_.control_params.conflicts_resolved = false;
155 }
set_items_committed()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.
CountUpdates() const161 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
CurrentCommitIdProjectionHasIndex(size_t index)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
HasConflictingUpdates() const176 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
TotalNumConflictingItems() const188 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
ServerSaysNothingMoreToDownload() const200 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