summaryrefslogtreecommitdiffstats
path: root/components/sync_driver/data_type_manager_impl.h
blob: fd9a5bc6fc600bcf7fae862a7d55fe3df19e1af9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_SYNC_DRIVER_DATA_TYPE_MANAGER_IMPL_H__
#define COMPONENTS_SYNC_DRIVER_DATA_TYPE_MANAGER_IMPL_H__

#include "components/sync_driver/data_type_manager.h"

#include <map>
#include <queue>
#include <vector>

#include "base/basictypes.h"
#include "base/callback_forward.h"
#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "components/sync_driver/backend_data_type_configurer.h"
#include "components/sync_driver/model_association_manager.h"

namespace syncer {
struct DataTypeConfigurationStats;
class DataTypeDebugInfoListener;
template <typename T> class WeakHandle;
}

namespace sync_driver {

class DataTypeController;
class DataTypeEncryptionHandler;
class DataTypeManagerObserver;

// List of data types grouped by priority and ordered from high priority to
// low priority.
typedef std::queue<syncer::ModelTypeSet> TypeSetPriorityList;

class DataTypeManagerImpl : public DataTypeManager,
                            public ModelAssociationManagerDelegate {
 public:
  DataTypeManagerImpl(
      const base::Closure& unrecoverable_error_method,
      const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
          debug_info_listener,
      const DataTypeController::TypeMap* controllers,
      const DataTypeEncryptionHandler* encryption_handler,
      BackendDataTypeConfigurer* configurer,
      DataTypeManagerObserver* observer);
  ~DataTypeManagerImpl() override;

  // DataTypeManager interface.
  void Configure(syncer::ModelTypeSet desired_types,
                 syncer::ConfigureReason reason) override;
  void ReenableType(syncer::ModelType type) override;
  void ResetDataTypeErrors() override;

  // Needed only for backend migration.
  void PurgeForMigration(syncer::ModelTypeSet undesired_types,
                         syncer::ConfigureReason reason) override;

  void Stop() override;
  State state() const override;

  // |ModelAssociationManagerDelegate| implementation.
  void OnSingleDataTypeAssociationDone(
      syncer::ModelType type,
      const syncer::DataTypeAssociationStats& association_stats) override;
  void OnModelAssociationDone(
      const DataTypeManager::ConfigureResult& result) override;
  void OnSingleDataTypeWillStop(syncer::ModelType type,
                                const syncer::SyncError& error) override;

  // Used by unit tests. TODO(sync) : This would go away if we made
  // this class be able to do Dependency injection. crbug.com/129212.
  ModelAssociationManager* GetModelAssociationManagerForTesting() {
    return &model_association_manager_;
  }

 private:
  // Helper enum for identifying which types within a priority group to
  // associate.
  enum AssociationGroup {
    // Those types that were already downloaded and didn't have an error at
    // configuration time. Corresponds with AssociationTypesInfo's
    // |ready_types|. These types can start associating as soon as the
    // ModelAssociationManager is not busy.
    READY_AT_CONFIG,
    // All other types, including first time sync types and those that have
    // encountered an error. These types must wait until the syncer has done
    // any db changes and/or downloads before associating.
    UNREADY_AT_CONFIG,
  };

  friend class TestDataTypeManager;

  // Abort configuration and stop all data types due to configuration errors.
  void Abort(ConfigureStatus status);

  // Returns the priority types (control + priority user types).
  // Virtual for overriding during tests.
  virtual syncer::ModelTypeSet GetPriorityTypes() const;

  // Divide |types| into sets by their priorities and return the sets from
  // high priority to low priority.
  TypeSetPriorityList PrioritizeTypes(const syncer::ModelTypeSet& types);

  // Post a task to reconfigure when no downloading or association are running.
  void ProcessReconfigure();

  void Restart(syncer::ConfigureReason reason);
  void DownloadReady(syncer::ModelTypeSet types_to_download,
                     syncer::ModelTypeSet first_sync_types,
                     syncer::ModelTypeSet failed_configuration_types);

  // Notification from the SBH that download failed due to a transient
  // error and it will be retried.
  void OnDownloadRetry();
  void NotifyStart();
  void NotifyDone(const ConfigureResult& result);

  // Add to |configure_time_delta_| the time since we last called
  // Restart().
  void AddToConfigureTime();

  void ConfigureImpl(syncer::ModelTypeSet desired_types,
                     syncer::ConfigureReason reason);

  BackendDataTypeConfigurer::DataTypeConfigStateMap
  BuildDataTypeConfigStateMap(
      const syncer::ModelTypeSet& types_being_configured) const;

  // Start download of next set of types in |download_types_queue_| (if
  // any exist, does nothing otherwise).
  // Will kick off association of any new ready types.
  void StartNextDownload(syncer::ModelTypeSet high_priority_types_before);

  // Start association of next batch of data types after association of
  // previous batch finishes. |group| controls which set of types within
  // an AssociationTypesInfo to associate. Does nothing if model associator
  // is busy performing association.
  void StartNextAssociation(AssociationGroup group);

  void StopImpl();

  BackendDataTypeConfigurer* configurer_;
  // Map of all data type controllers that are available for sync.
  // This list is determined at startup by various command line flags.
  const DataTypeController::TypeMap* controllers_;
  State state_;
  std::map<syncer::ModelType, int> start_order_;
  syncer::ModelTypeSet last_requested_types_;

  // Whether an attempt to reconfigure was made while we were busy configuring.
  // The |last_requested_types_| will reflect the newest set of requested types.
  bool needs_reconfigure_;

  // The reason for the last reconfigure attempt. Note: this will be set to a
  // valid value only when |needs_reconfigure_| is set.
  syncer::ConfigureReason last_configure_reason_;

  // The last time Restart() was called.
  base::Time last_restart_time_;

  // The accumulated time spent between calls to Restart() and going
  // to the DONE state.
  base::TimeDelta configure_time_delta_;

  // Sync's datatype debug info listener, which we pass model association
  // statistics to.
  const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>
      debug_info_listener_;

  // The manager that handles the model association of the individual types.
  ModelAssociationManager model_association_manager_;

  // DataTypeManager must have only one observer -- the ProfileSyncService that
  // created it and manages its lifetime.
  DataTypeManagerObserver* const observer_;

  // For querying failed data types (having unrecoverable error) when
  // configuring backend.
  DataTypeStatusTable data_type_status_table_;

  // Types waiting to be downloaded.
  TypeSetPriorityList download_types_queue_;

  // Types waiting for association and related time tracking info.
  struct AssociationTypesInfo {
    AssociationTypesInfo();
    ~AssociationTypesInfo();

    // Types to associate.
    syncer::ModelTypeSet types;
    // Types that have just been downloaded and are being associated for the
    // first time. This includes types that had previously encountered an error
    // and had to be purged/unapplied from the sync db.
    // This is a subset of |types|.
    syncer::ModelTypeSet first_sync_types;
    // Types that were already ready for association at configuration time.
    syncer::ModelTypeSet ready_types;
    // Time at which |types| began downloading.
    base::Time download_start_time;
    // Time at which |types| finished downloading.
    base::Time download_ready_time;
    // Time at which the association for |read_types| began.
    base::Time ready_association_request_time;
    // Time at which the association for |types| began (not relevant to
    // |ready_types|.
    base::Time full_association_request_time;
    // The set of types that are higher priority (and were therefore blocking)
    // the association of |types|.
    syncer::ModelTypeSet high_priority_types_before;
    // The subset of |types| that were successfully configured.
    syncer::ModelTypeSet configured_types;
  };
  std::queue<AssociationTypesInfo> association_types_queue_;

  // The encryption handler lets the DataTypeManager know the state of sync
  // datatype encryption.
  const DataTypeEncryptionHandler* encryption_handler_;

  // Association and time stats of data type configuration.
  std::vector<syncer::DataTypeConfigurationStats> configuration_stats_;

  base::Closure unrecoverable_error_method_;

  // True iff we are in the process of catching up datatypes.
  bool catch_up_in_progress_;

  base::WeakPtrFactory<DataTypeManagerImpl> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(DataTypeManagerImpl);
};

}  // namespace sync_driver

#endif  // COMPONENTS_SYNC_DRIVER_DATA_TYPE_MANAGER_IMPL_H__