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