blob: ec70f2c8fc48a6733fd7c695ecf57f62f070cb78 [file] [log] [blame]
// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// StatusController handles all counter and status related number crunching and
// state tracking on behalf of a SyncSession.
// The most important feature of StatusController is the
// ScopedModelSafeGroupRestriction. Some of its functions expose per-thread
// state, and can be called only when the restriction is in effect. For
// example, if GROUP_UI is set then the value returned from
// commit_id_projection() will be useful for iterating over the commit IDs of
// items that live on the UI thread.
// Other parts of its state are global, and do not require the restriction.
// NOTE: There is no concurrent access protection provided by this class. It
// assumes one single thread is accessing this class for each unique
// ModelSafeGroup, and also only one single thread (in practice, the
// SyncerThread) responsible for all "shared" access when no restriction is in
// place. Thus, every bit of data is to be accessed mutually exclusively with
// respect to threads.
// StatusController can also track if changes occur to certain parts of state
// so that various parts of the sync engine can avoid broadcasting
// notifications if no changes occurred.
#include <map>
#include <vector>
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/time/time.h"
#include "sync/base/sync_export.h"
#include "sync/internal_api/public/sessions/model_neutral_state.h"
#include "sync/sessions/ordered_commit_set.h"
namespace syncer {
namespace sessions {
class SYNC_EXPORT_PRIVATE StatusController {
explicit StatusController();
// ClientToServer messages.
const ModelTypeSet updates_request_types() const {
return model_neutral_.updates_request_types;
void set_updates_request_types(ModelTypeSet value) {
model_neutral_.updates_request_types = value;
const sync_pb::ClientToServerResponse& updates_response() const {
return model_neutral_.updates_response;
sync_pb::ClientToServerResponse* mutable_updates_response() {
return &model_neutral_.updates_response;
// Changelog related state.
int64 num_server_changes_remaining() const {
return model_neutral_.num_server_changes_remaining;
const OrderedCommitSet::Projection& commit_id_projection(
const sessions::OrderedCommitSet &commit_set) {
<< "No group restriction for projection.";
return commit_set.GetCommitIdProjection(group_restriction_);
// Various conflict counters.
int num_encryption_conflicts() const;
int num_hierarchy_conflicts() const;
int num_server_conflicts() const;
// Aggregate sum of all conflicting items over all conflict types.
int TotalNumConflictingItems() const;
// Number of successfully applied updates.
int num_updates_applied() const;
int num_server_overwrites() const;
// Returns the number of updates received from the sync server.
int64 CountUpdates() const;
// Returns true if the last download_updates_command received a valid
// server response.
bool download_updates_succeeded() const {
return model_neutral_.last_download_updates_result
// Returns true if the last updates response indicated that we were fully
// up to date. This is subtle: if it's false, it could either mean that
// the server said there WAS more to download, or it could mean that we
// were unable to reach the server. If we didn't request every enabled
// datatype, then we can't say for sure that there's nothing left to
// download: in that case, this also returns false.
bool ServerSaysNothingMoreToDownload() const;
ModelSafeGroup group_restriction() const {
return group_restriction_;
base::Time sync_start_time() const {
// The time at which we sent the first GetUpdates command for this sync.
return sync_start_time_;
const ModelNeutralState& model_neutral_state() const {
return model_neutral_;
SyncerError last_get_key_result() const;
// Download counters.
void set_num_server_changes_remaining(int64 changes_remaining);
void increment_num_updates_downloaded_by(int value);
void increment_num_tombstone_updates_downloaded_by(int value);
void increment_num_reflected_updates_downloaded_by(int value);
// Update application and conflict resolution counters.
void increment_num_updates_applied_by(int value);
void increment_num_encryption_conflicts_by(int value);
void increment_num_hierarchy_conflicts_by(int value);
void increment_num_server_conflicts();
void increment_num_local_overwrites();
void increment_num_server_overwrites();
// Commit counters.
void increment_num_successful_commits();
void increment_num_successful_bookmark_commits();
void set_num_successful_bookmark_commits(int value);
// Server communication status tracking.
void set_sync_protocol_error(const SyncProtocolError& error);
void set_last_get_key_result(const SyncerError result);
void set_last_download_updates_result(const SyncerError result);
void set_commit_result(const SyncerError result);
// A very important flag used to inform frontend of need to migrate.
void set_types_needing_local_migration(ModelTypeSet types);
void UpdateStartTime();
void set_debug_info_sent();
bool debug_info_sent() const;
friend class ScopedModelSafeGroupRestriction;
ModelNeutralState model_neutral_;
// Used to fail read/write operations on state that don't obey the current
// active ModelSafeWorker contract.
bool group_restriction_in_effect_;
ModelSafeGroup group_restriction_;
base::Time sync_start_time_;
// A utility to restrict access to only those parts of the given
// StatusController that pertain to the specified ModelSafeGroup.
class ScopedModelSafeGroupRestriction {
ScopedModelSafeGroupRestriction(StatusController* to_restrict,
ModelSafeGroup restriction)
: status_(to_restrict) {
status_->group_restriction_ = restriction;
status_->group_restriction_in_effect_ = true;
~ScopedModelSafeGroupRestriction() {
status_->group_restriction_in_effect_ = false;
StatusController* status_;
} // namespace sessions
} // namespace syncer