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