Home | History | Annotate | Download | only in sessions
      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);
    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.
    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 
    231 struct 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.
    249 template <typename T>
    250 class 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.
    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