Home | History | Annotate | Download | only in sessions
      1 // Copyright 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 // StatusController handles all counter and status related number crunching and
      6 // state tracking on behalf of a SyncSession.
      7 //
      8 // The most important feature of StatusController is the
      9 // ScopedModelSafeGroupRestriction.  Some of its functions expose per-thread
     10 // state, and can be called only when the restriction is in effect.  For
     11 // example, if GROUP_UI is set then the value returned from
     12 // commit_id_projection() will be useful for iterating over the commit IDs of
     13 // items that live on the UI thread.
     14 //
     15 // Other parts of its state are global, and do not require the restriction.
     16 //
     17 // NOTE: There is no concurrent access protection provided by this class. It
     18 // assumes one single thread is accessing this class for each unique
     19 // ModelSafeGroup, and also only one single thread (in practice, the
     20 // SyncerThread) responsible for all "shared" access when no restriction is in
     21 // place. Thus, every bit of data is to be accessed mutually exclusively with
     22 // respect to threads.
     23 //
     24 // StatusController can also track if changes occur to certain parts of state
     25 // so that various parts of the sync engine can avoid broadcasting
     26 // notifications if no changes occurred.
     27 
     28 #ifndef SYNC_SESSIONS_STATUS_CONTROLLER_H_
     29 #define SYNC_SESSIONS_STATUS_CONTROLLER_H_
     30 
     31 #include <map>
     32 #include <vector>
     33 
     34 #include "base/logging.h"
     35 #include "base/stl_util.h"
     36 #include "base/time/time.h"
     37 #include "sync/base/sync_export.h"
     38 #include "sync/internal_api/public/sessions/model_neutral_state.h"
     39 #include "sync/sessions/ordered_commit_set.h"
     40 
     41 namespace syncer {
     42 namespace sessions {
     43 
     44 class SYNC_EXPORT_PRIVATE StatusController {
     45  public:
     46   explicit StatusController();
     47   ~StatusController();
     48 
     49   // ClientToServer messages.
     50   const ModelTypeSet updates_request_types() const {
     51     return model_neutral_.updates_request_types;
     52   }
     53   void set_updates_request_types(ModelTypeSet value) {
     54     model_neutral_.updates_request_types = value;
     55   }
     56   const ModelTypeSet commit_request_types() const {
     57     return model_neutral_.commit_request_types;
     58   }
     59   void set_commit_request_types(ModelTypeSet value) {
     60     model_neutral_.commit_request_types = value;
     61   }
     62   const sync_pb::ClientToServerResponse& updates_response() const {
     63     return model_neutral_.updates_response;
     64   }
     65   sync_pb::ClientToServerResponse* mutable_updates_response() {
     66     return &model_neutral_.updates_response;
     67   }
     68 
     69   // Changelog related state.
     70   int64 num_server_changes_remaining() const {
     71     return model_neutral_.num_server_changes_remaining;
     72   }
     73 
     74   const OrderedCommitSet::Projection& commit_id_projection(
     75       const sessions::OrderedCommitSet &commit_set) {
     76     DCHECK(group_restriction_in_effect_)
     77         << "No group restriction for projection.";
     78     return commit_set.GetCommitIdProjection(group_restriction_);
     79   }
     80 
     81   // Various conflict counters.
     82   int num_encryption_conflicts() const;
     83   int num_hierarchy_conflicts() const;
     84   int num_server_conflicts() const;
     85 
     86   // Aggregate sum of all conflicting items over all conflict types.
     87   int TotalNumConflictingItems() const;
     88 
     89   // Number of successfully applied updates.
     90   int num_updates_applied() const;
     91 
     92   int num_server_overwrites() const;
     93 
     94   // Returns the number of updates received from the sync server.
     95   int64 CountUpdates() const;
     96 
     97   // Returns true if the last download_updates_command received a valid
     98   // server response.
     99   bool download_updates_succeeded() const {
    100     return model_neutral_.last_download_updates_result
    101         == SYNCER_OK;
    102   }
    103 
    104   // Returns true if the last updates response indicated that we were fully
    105   // up to date.  This is subtle: if it's false, it could either mean that
    106   // the server said there WAS more to download, or it could mean that we
    107   // were unable to reach the server.  If we didn't request every enabled
    108   // datatype, then we can't say for sure that there's nothing left to
    109   // download: in that case, this also returns false.
    110   bool ServerSaysNothingMoreToDownload() const;
    111 
    112   ModelSafeGroup group_restriction() const {
    113     return group_restriction_;
    114   }
    115 
    116   base::Time sync_start_time() const {
    117     // The time at which we sent the first GetUpdates command for this sync.
    118     return sync_start_time_;
    119   }
    120 
    121   const ModelNeutralState& model_neutral_state() const {
    122     return model_neutral_;
    123   }
    124 
    125   SyncerError last_get_key_result() const;
    126 
    127   // Download counters.
    128   void set_num_server_changes_remaining(int64 changes_remaining);
    129   void increment_num_updates_downloaded_by(int value);
    130   void increment_num_tombstone_updates_downloaded_by(int value);
    131   void increment_num_reflected_updates_downloaded_by(int value);
    132 
    133   // Update application and conflict resolution counters.
    134   void increment_num_updates_applied_by(int value);
    135   void increment_num_encryption_conflicts_by(int value);
    136   void increment_num_hierarchy_conflicts_by(int value);
    137   void increment_num_server_conflicts();
    138   void increment_num_local_overwrites();
    139   void increment_num_server_overwrites();
    140 
    141   // Commit counters.
    142   void increment_num_successful_commits();
    143   void increment_num_successful_bookmark_commits();
    144   void set_num_successful_bookmark_commits(int value);
    145 
    146   // Server communication status tracking.
    147   void set_sync_protocol_error(const SyncProtocolError& error);
    148   void set_last_get_key_result(const SyncerError result);
    149   void set_last_download_updates_result(const SyncerError result);
    150   void set_commit_result(const SyncerError result);
    151 
    152   // A very important flag used to inform frontend of need to migrate.
    153   void set_types_needing_local_migration(ModelTypeSet types);
    154 
    155   void UpdateStartTime();
    156 
    157   void set_debug_info_sent();
    158 
    159   bool debug_info_sent() const;
    160 
    161  private:
    162   friend class ScopedModelSafeGroupRestriction;
    163 
    164   ModelNeutralState model_neutral_;
    165 
    166   // Used to fail read/write operations on state that don't obey the current
    167   // active ModelSafeWorker contract.
    168   bool group_restriction_in_effect_;
    169   ModelSafeGroup group_restriction_;
    170 
    171   base::Time sync_start_time_;
    172 
    173   DISALLOW_COPY_AND_ASSIGN(StatusController);
    174 };
    175 
    176 // A utility to restrict access to only those parts of the given
    177 // StatusController that pertain to the specified ModelSafeGroup.
    178 class ScopedModelSafeGroupRestriction {
    179  public:
    180   ScopedModelSafeGroupRestriction(StatusController* to_restrict,
    181                                   ModelSafeGroup restriction)
    182       : status_(to_restrict) {
    183     DCHECK(!status_->group_restriction_in_effect_);
    184     status_->group_restriction_ = restriction;
    185     status_->group_restriction_in_effect_ = true;
    186   }
    187   ~ScopedModelSafeGroupRestriction() {
    188     DCHECK(status_->group_restriction_in_effect_);
    189     status_->group_restriction_in_effect_ = false;
    190   }
    191  private:
    192   StatusController* status_;
    193   DISALLOW_COPY_AND_ASSIGN(ScopedModelSafeGroupRestriction);
    194 };
    195 
    196 }  // namespace sessions
    197 }  // namespace syncer
    198 
    199 #endif  // SYNC_SESSIONS_STATUS_CONTROLLER_H_
    200