1// Copyright (c) 2012 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 "sync/engine/all_status.h"
6
7#include <algorithm>
8
9#include "base/logging.h"
10#include "base/port.h"
11#include "sync/engine/net/server_connection_manager.h"
12#include "sync/engine/sync_cycle_event.h"
13#include "sync/internal_api/public/base/model_type.h"
14
15namespace syncer {
16
17AllStatus::AllStatus() {
18  status_.notifications_enabled = false;
19  status_.cryptographer_ready = false;
20  status_.crypto_has_pending_keys = false;
21}
22
23AllStatus::~AllStatus() {
24}
25
26SyncStatus AllStatus::CreateBlankStatus() const {
27  // Status is initialized with the previous status value.  Variables
28  // whose values accumulate (e.g. lifetime counters like updates_received)
29  // are not to be cleared here.
30  SyncStatus status = status_;
31  status.encryption_conflicts = 0;
32  status.hierarchy_conflicts = 0;
33  status.server_conflicts = 0;
34  status.committed_count = 0;
35  return status;
36}
37
38SyncStatus AllStatus::CalcSyncing(const SyncCycleEvent &event) const {
39  SyncStatus status = CreateBlankStatus();
40  const sessions::SyncSessionSnapshot& snapshot = event.snapshot;
41  status.encryption_conflicts = snapshot.num_encryption_conflicts();
42  status.hierarchy_conflicts = snapshot.num_hierarchy_conflicts();
43  status.server_conflicts = snapshot.num_server_conflicts();
44  status.committed_count =
45      snapshot.model_neutral_state().num_successful_commits;
46
47  if (event.what_happened == SyncCycleEvent::SYNC_CYCLE_BEGIN) {
48    status.syncing = true;
49  } else if (event.what_happened == SyncCycleEvent::SYNC_CYCLE_ENDED) {
50    status.syncing = false;
51  }
52
53  status.num_entries_by_type = snapshot.num_entries_by_type();
54  status.num_to_delete_entries_by_type =
55      snapshot.num_to_delete_entries_by_type();
56
57  // Accumulate update count only once per session to avoid double-counting.
58  if (event.what_happened == SyncCycleEvent::SYNC_CYCLE_ENDED) {
59    status.updates_received +=
60        snapshot.model_neutral_state().num_updates_downloaded_total;
61    status.tombstone_updates_received +=
62        snapshot.model_neutral_state().num_tombstone_updates_downloaded_total;
63    status.reflected_updates_received +=
64        snapshot.model_neutral_state().num_reflected_updates_downloaded_total;
65    status.num_commits_total +=
66        snapshot.model_neutral_state().num_successful_commits;
67    status.num_local_overwrites_total +=
68        snapshot.model_neutral_state().num_local_overwrites;
69    status.num_server_overwrites_total +=
70        snapshot.model_neutral_state().num_server_overwrites;
71  }
72  return status;
73}
74
75void AllStatus::OnSyncCycleEvent(const SyncCycleEvent& event) {
76  ScopedStatusLock lock(this);
77  switch (event.what_happened) {
78    case SyncCycleEvent::SYNC_CYCLE_BEGIN:
79    case SyncCycleEvent::STATUS_CHANGED:
80    case SyncCycleEvent::SYNC_CYCLE_ENDED:
81      status_ = CalcSyncing(event);
82      break;
83    default:
84      LOG(ERROR) << "Unrecognized Syncer Event: " << event.what_happened;
85      break;
86  }
87}
88
89void AllStatus::OnActionableError(
90    const SyncProtocolError& sync_protocol_error) {
91  ScopedStatusLock lock(this);
92  status_ = CreateBlankStatus();
93  status_.sync_protocol_error = sync_protocol_error;
94}
95
96void AllStatus::OnRetryTimeChanged(base::Time retry_time) {
97  ScopedStatusLock lock(this);
98  status_.retry_time = retry_time;
99}
100
101void AllStatus::OnThrottledTypesChanged(ModelTypeSet throttled_types) {
102  ScopedStatusLock lock(this);
103  status_.throttled_types = throttled_types;
104}
105
106void AllStatus::OnMigrationRequested(ModelTypeSet) {}
107
108void AllStatus::OnProtocolEvent(const ProtocolEvent&) {}
109
110SyncStatus AllStatus::status() const {
111  base::AutoLock lock(mutex_);
112  return status_;
113}
114
115void AllStatus::SetNotificationsEnabled(bool notifications_enabled) {
116  ScopedStatusLock lock(this);
117  status_.notifications_enabled = notifications_enabled;
118}
119
120void AllStatus::IncrementNotificationsReceived() {
121  ScopedStatusLock lock(this);
122  ++status_.notifications_received;
123}
124
125void AllStatus::SetEncryptedTypes(ModelTypeSet types) {
126  ScopedStatusLock lock(this);
127  status_.encrypted_types = types;
128}
129
130void AllStatus::SetCryptographerReady(bool ready) {
131  ScopedStatusLock lock(this);
132  status_.cryptographer_ready = ready;
133}
134
135void AllStatus::SetCryptoHasPendingKeys(bool has_pending_keys) {
136  ScopedStatusLock lock(this);
137  status_.crypto_has_pending_keys = has_pending_keys;
138}
139
140void AllStatus::SetPassphraseType(PassphraseType type) {
141  ScopedStatusLock lock(this);
142  status_.passphrase_type = type;
143}
144
145void AllStatus::SetHasKeystoreKey(bool has_keystore_key) {
146  ScopedStatusLock lock(this);
147  status_.has_keystore_key = has_keystore_key;
148}
149
150void AllStatus::SetKeystoreMigrationTime(const base::Time& migration_time) {
151  ScopedStatusLock lock(this);
152  status_.keystore_migration_time = migration_time;
153}
154
155void AllStatus::SetSyncId(const std::string& sync_id) {
156  ScopedStatusLock lock(this);
157  status_.sync_id = sync_id;
158}
159
160void AllStatus::SetInvalidatorClientId(
161    const std::string& invalidator_client_id) {
162  ScopedStatusLock lock(this);
163  status_.invalidator_client_id = invalidator_client_id;
164}
165
166void AllStatus::IncrementNudgeCounter(NudgeSource source) {
167  ScopedStatusLock lock(this);
168  switch(source) {
169    case NUDGE_SOURCE_LOCAL_REFRESH:
170      status_.nudge_source_local_refresh++;
171      return;
172    case NUDGE_SOURCE_LOCAL:
173      status_.nudge_source_local++;
174      return;
175    case NUDGE_SOURCE_NOTIFICATION:
176      status_.nudge_source_notification++;
177      return;
178    case NUDGE_SOURCE_UNKNOWN:
179      break;
180  }
181  // If we're here, the source is most likely
182  // NUDGE_SOURCE_UNKNOWN. That shouldn't happen.
183  NOTREACHED();
184}
185
186ScopedStatusLock::ScopedStatusLock(AllStatus* allstatus)
187    : allstatus_(allstatus) {
188  allstatus->mutex_.Acquire();
189}
190
191ScopedStatusLock::~ScopedStatusLock() {
192  allstatus_->mutex_.Release();
193}
194
195}  // namespace syncer
196