• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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