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