1 // Copyright (c) 2011 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 // The 'sessions' namespace comprises all the pieces of state that are 6 // combined to form a SyncSession instance. In that way, it can be thought of 7 // as an extension of the SyncSession type itself. Session scoping gives 8 // context to things like "conflict progress", "update progress", etc, and the 9 // separation this file provides allows clients to only include the parts they 10 // need rather than the entire session stack. 11 12 #ifndef CHROME_BROWSER_SYNC_SESSIONS_SESSION_STATE_H_ 13 #define CHROME_BROWSER_SYNC_SESSIONS_SESSION_STATE_H_ 14 #pragma once 15 16 #include <map> 17 #include <set> 18 #include <string> 19 #include <utility> 20 #include <vector> 21 22 #include "base/basictypes.h" 23 #include "chrome/browser/sync/engine/syncer_types.h" 24 #include "chrome/browser/sync/engine/syncproto.h" 25 #include "chrome/browser/sync/sessions/ordered_commit_set.h" 26 #include "chrome/browser/sync/syncable/model_type.h" 27 #include "chrome/browser/sync/syncable/model_type_payload_map.h" 28 #include "chrome/browser/sync/syncable/syncable.h" 29 30 class DictionaryValue; 31 32 namespace syncable { 33 class DirectoryManager; 34 } 35 36 namespace browser_sync { 37 namespace sessions { 38 39 class UpdateProgress; 40 41 // A container for the source of a sync session. This includes the update 42 // source, the datatypes triggering the sync session, and possible session 43 // specific payloads which should be sent to the server. 44 struct SyncSourceInfo { 45 SyncSourceInfo(); 46 explicit SyncSourceInfo(const syncable::ModelTypePayloadMap& t); 47 SyncSourceInfo( 48 const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource& u, 49 const syncable::ModelTypePayloadMap& t); 50 ~SyncSourceInfo(); 51 52 // Caller takes ownership of the returned dictionary. 53 DictionaryValue* ToValue() const; 54 55 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource updates_source; 56 syncable::ModelTypePayloadMap types; 57 }; 58 59 // Data pertaining to the status of an active Syncer object. 60 struct SyncerStatus { 61 SyncerStatus(); 62 ~SyncerStatus(); 63 64 // Caller takes ownership of the returned dictionary. 65 DictionaryValue* ToValue() const; 66 67 // True when we get such an INVALID_STORE error from the server. 68 bool invalid_store; 69 // True iff we're stuck. 70 bool syncer_stuck; 71 bool syncing; 72 int num_successful_commits; 73 // This is needed for monitoring extensions activity. 74 int num_successful_bookmark_commits; 75 76 // Download event counters. 77 int num_updates_downloaded_total; 78 int num_tombstone_updates_downloaded_total; 79 80 // If the syncer encountered a MIGRATION_DONE code, these are the types that 81 // the client must now "migrate", by purging and re-downloading all updates. 82 syncable::ModelTypeSet types_needing_local_migration; 83 }; 84 85 // Counters for various errors that can occur repeatedly during a sync session. 86 struct ErrorCounters { 87 ErrorCounters(); 88 89 // Caller takes ownership of the returned dictionary. 90 DictionaryValue* ToValue() const; 91 92 int num_conflicting_commits; 93 94 // Number of commits hitting transient errors since the last successful 95 // commit. 96 int consecutive_transient_error_commits; 97 98 // Incremented when get_updates fails, commit fails, and when hitting 99 // transient errors. When any of these succeed, this counter is reset. 100 // TODO(chron): Reduce number of weird counters we use. 101 int consecutive_errors; 102 }; 103 104 // Caller takes ownership of the returned dictionary. 105 DictionaryValue* DownloadProgressMarkersToValue( 106 const std::string 107 (&download_progress_markers)[syncable::MODEL_TYPE_COUNT]); 108 109 // An immutable snapshot of state from a SyncSession. Convenient to use as 110 // part of notifications as it is inherently thread-safe. 111 struct SyncSessionSnapshot { 112 SyncSessionSnapshot( 113 const SyncerStatus& syncer_status, 114 const ErrorCounters& errors, 115 int64 num_server_changes_remaining, 116 bool is_share_usable, 117 const syncable::ModelTypeBitSet& initial_sync_ended, 118 const std::string 119 (&download_progress_markers)[syncable::MODEL_TYPE_COUNT], 120 bool more_to_sync, 121 bool is_silenced, 122 int64 unsynced_count, 123 int num_conflicting_updates, 124 bool did_commit_items, 125 const SyncSourceInfo& source); 126 ~SyncSessionSnapshot(); 127 128 // Caller takes ownership of the returned dictionary. 129 DictionaryValue* ToValue() const; 130 131 const SyncerStatus syncer_status; 132 const ErrorCounters errors; 133 const int64 num_server_changes_remaining; 134 const bool is_share_usable; 135 const syncable::ModelTypeBitSet initial_sync_ended; 136 const std::string download_progress_markers[syncable::MODEL_TYPE_COUNT]; 137 const bool has_more_to_sync; 138 const bool is_silenced; 139 const int64 unsynced_count; 140 const int num_conflicting_updates; 141 const bool did_commit_items; 142 const SyncSourceInfo source; 143 }; 144 145 // Tracks progress of conflicts and their resolution using conflict sets. 146 class ConflictProgress { 147 public: 148 explicit ConflictProgress(bool* dirty_flag); 149 ~ConflictProgress(); 150 // Various iterators, size, and retrieval functions for conflict sets. 151 IdToConflictSetMap::const_iterator IdToConflictSetBegin() const; 152 IdToConflictSetMap::const_iterator IdToConflictSetEnd() const; 153 IdToConflictSetMap::size_type IdToConflictSetSize() const; 154 IdToConflictSetMap::const_iterator IdToConflictSetFind( 155 const syncable::Id& the_id) const; 156 const ConflictSet* IdToConflictSetGet(const syncable::Id& the_id); 157 std::set<ConflictSet*>::const_iterator ConflictSetsBegin() const; 158 std::set<ConflictSet*>::const_iterator ConflictSetsEnd() const; 159 std::set<ConflictSet*>::size_type ConflictSetsSize() const; 160 161 // Various mutators for tracking commit conflicts. 162 void AddConflictingItemById(const syncable::Id& the_id); 163 void EraseConflictingItemById(const syncable::Id& the_id); ConflictingItemsSize()164 int ConflictingItemsSize() const { return conflicting_item_ids_.size(); } 165 std::set<syncable::Id>::iterator ConflictingItemsBegin(); 166 std::set<syncable::Id>::const_iterator ConflictingItemsBeginConst() const; 167 std::set<syncable::Id>::const_iterator ConflictingItemsEnd() const; 168 169 void MergeSets(const syncable::Id& set1, const syncable::Id& set2); 170 void CleanupSets(); 171 172 private: 173 // TODO(sync): move away from sets if it makes more sense. 174 std::set<syncable::Id> conflicting_item_ids_; 175 std::map<syncable::Id, ConflictSet*> id_to_conflict_set_; 176 std::set<ConflictSet*> conflict_sets_; 177 178 // Whether a conflicting item was added or removed since 179 // the last call to reset_progress_changed(), if any. In practice this 180 // points to StatusController::is_dirty_. 181 bool* dirty_; 182 }; 183 184 typedef std::pair<VerifyResult, sync_pb::SyncEntity> VerifiedUpdate; 185 typedef std::pair<UpdateAttemptResponse, syncable::Id> AppliedUpdate; 186 187 // Tracks update application and verification. 188 class UpdateProgress { 189 public: 190 UpdateProgress(); 191 ~UpdateProgress(); 192 193 void AddVerifyResult(const VerifyResult& verify_result, 194 const sync_pb::SyncEntity& entity); 195 196 // Log a successful or failing update attempt. 197 void AddAppliedUpdate(const UpdateAttemptResponse& response, 198 const syncable::Id& id); 199 200 // Various iterators. 201 std::vector<AppliedUpdate>::iterator AppliedUpdatesBegin(); 202 std::vector<VerifiedUpdate>::const_iterator VerifiedUpdatesBegin() const; 203 std::vector<AppliedUpdate>::const_iterator AppliedUpdatesEnd() const; 204 std::vector<VerifiedUpdate>::const_iterator VerifiedUpdatesEnd() const; 205 206 // Returns the number of update application attempts. This includes both 207 // failures and successes. AppliedUpdatesSize()208 int AppliedUpdatesSize() const { return applied_updates_.size(); } VerifiedUpdatesSize()209 int VerifiedUpdatesSize() const { return verified_updates_.size(); } HasVerifiedUpdates()210 bool HasVerifiedUpdates() const { return !verified_updates_.empty(); } HasAppliedUpdates()211 bool HasAppliedUpdates() const { return !applied_updates_.empty(); } 212 213 // Count the number of successful update applications that have happend this 214 // cycle. Note that if an item is successfully applied twice, it will be 215 // double counted here. 216 int SuccessfullyAppliedUpdateCount() const; 217 218 // Returns true if at least one update application failed due to a conflict 219 // during this sync cycle. 220 bool HasConflictingUpdates() const; 221 222 private: 223 // Container for updates that passed verification. 224 std::vector<VerifiedUpdate> verified_updates_; 225 226 // Stores the result of the various ApplyUpdate attempts we've made. 227 // May contain duplicate entries. 228 std::vector<AppliedUpdate> applied_updates_; 229 }; 230 231 struct SyncCycleControlParameters { SyncCycleControlParametersSyncCycleControlParameters232 SyncCycleControlParameters() : conflict_sets_built(false), 233 conflicts_resolved(false), 234 items_committed(false) {} 235 // Set to true by BuildAndProcessConflictSetsCommand if the RESOLVE_CONFLICTS 236 // step is needed. 237 bool conflict_sets_built; 238 239 // Set to true by ResolveConflictsCommand if any forward progress was made. 240 bool conflicts_resolved; 241 242 // Set to true by PostCommitMessageCommand if any commits were successful. 243 bool items_committed; 244 }; 245 246 // DirtyOnWrite wraps a value such that any write operation will update a 247 // specified dirty bit, which can be used to determine if a notification should 248 // be sent due to state change. 249 template <typename T> 250 class DirtyOnWrite { 251 public: DirtyOnWrite(bool * dirty)252 explicit DirtyOnWrite(bool* dirty) : dirty_(dirty) {} DirtyOnWrite(bool * dirty,const T & t)253 DirtyOnWrite(bool* dirty, const T& t) : t_(t), dirty_(dirty) {} mutate()254 T* mutate() { 255 *dirty_ = true; 256 return &t_; 257 } value()258 const T& value() const { return t_; } 259 private: 260 T t_; 261 bool* dirty_; 262 }; 263 264 // The next 3 structures declare how all the state involved in running a sync 265 // cycle is divided between global scope (applies to all model types), 266 // ModelSafeGroup scope (applies to all data types in a group), and single 267 // model type scope. Within this breakdown, each struct declares which bits 268 // of state are dirty-on-write and should incur dirty bit updates if changed. 269 270 // Grouping of all state that applies to all model types. Note that some 271 // components of the global grouping can internally implement finer grained 272 // scope control (such as OrderedCommitSet), but the top level entity is still 273 // a singleton with respect to model types. 274 struct AllModelTypeState { 275 explicit AllModelTypeState(bool* dirty_flag); 276 ~AllModelTypeState(); 277 278 // Commits for all model types are bundled together into a single message. 279 ClientToServerMessage commit_message; 280 ClientToServerResponse commit_response; 281 // We GetUpdates for some combination of types at once. 282 // requested_update_types stores the set of types which were requested. 283 syncable::ModelTypeBitSet updates_request_types; 284 ClientToServerResponse updates_response; 285 // Used to build the shared commit message. 286 DirtyOnWrite<std::vector<int64> > unsynced_handles; 287 DirtyOnWrite<SyncerStatus> syncer_status; 288 DirtyOnWrite<ErrorCounters> error_counters; 289 SyncCycleControlParameters control_params; 290 DirtyOnWrite<int64> num_server_changes_remaining; 291 OrderedCommitSet commit_set; 292 }; 293 294 // Grouping of all state that applies to a single ModelSafeGroup. 295 struct PerModelSafeGroupState { 296 explicit PerModelSafeGroupState(bool* dirty_flag); 297 ~PerModelSafeGroupState(); 298 299 UpdateProgress update_progress; 300 ConflictProgress conflict_progress; 301 }; 302 303 } // namespace sessions 304 } // namespace browser_sync 305 306 #endif // CHROME_BROWSER_SYNC_SESSIONS_SESSION_STATE_H_ 307