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
30class DictionaryValue;
31
32namespace syncable {
33class DirectoryManager;
34}
35
36namespace browser_sync {
37namespace sessions {
38
39class 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.
44struct 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.
60struct 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.
86struct 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.
105DictionaryValue* 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.
111struct 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.
146class 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);
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
184typedef std::pair<VerifyResult, sync_pb::SyncEntity> VerifiedUpdate;
185typedef std::pair<UpdateAttemptResponse, syncable::Id> AppliedUpdate;
186
187// Tracks update application and verification.
188class 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.
208  int AppliedUpdatesSize() const { return applied_updates_.size(); }
209  int VerifiedUpdatesSize() const { return verified_updates_.size(); }
210  bool HasVerifiedUpdates() const { return !verified_updates_.empty(); }
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
231struct SyncCycleControlParameters {
232  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.
249template <typename T>
250class DirtyOnWrite {
251 public:
252  explicit DirtyOnWrite(bool* dirty) : dirty_(dirty) {}
253  DirtyOnWrite(bool* dirty, const T& t) : t_(t), dirty_(dirty) {}
254  T* mutate() {
255    *dirty_ = true;
256    return &t_;
257  }
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.
274struct 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.
295struct 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