| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/sync/driver/model_association_manager.h" | 5 #include "components/sync/driver/model_association_manager.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| 11 #include <functional> | 11 #include <functional> |
| 12 | 12 |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/macros.h" | 14 #include "base/macros.h" |
| 15 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
| 16 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
| 17 #include "base/trace_event/trace_event.h" | 17 #include "base/trace_event/trace_event.h" |
| 18 #include "components/sync/api/sync_merge_result.h" | 18 #include "components/sync/api/sync_merge_result.h" |
| 19 #include "components/sync/base/model_type.h" | 19 #include "components/sync/base/model_type.h" |
| 20 | 20 |
| 21 using syncer::ModelTypeSet; | 21 namespace syncer { |
| 22 | |
| 23 namespace sync_driver { | |
| 24 | 22 |
| 25 namespace { | 23 namespace { |
| 26 | 24 |
| 27 static const syncer::ModelType kStartOrder[] = { | 25 static const ModelType kStartOrder[] = { |
| 28 syncer::NIGORI, // Listed for completeness. | 26 NIGORI, // Listed for completeness. |
| 29 syncer::DEVICE_INFO, // Listed for completeness. | 27 DEVICE_INFO, // Listed for completeness. |
| 30 syncer::EXPERIMENTS, // Listed for completeness. | 28 EXPERIMENTS, // Listed for completeness. |
| 31 syncer::PROXY_TABS, // Listed for completeness. | 29 PROXY_TABS, // Listed for completeness. |
| 32 | 30 |
| 33 // Kick off the association of the non-UI types first so they can associate | 31 // Kick off the association of the non-UI types first so they can associate |
| 34 // in parallel with the UI types. | 32 // in parallel with the UI types. |
| 35 syncer::PASSWORDS, syncer::AUTOFILL, syncer::AUTOFILL_PROFILE, | 33 PASSWORDS, AUTOFILL, AUTOFILL_PROFILE, AUTOFILL_WALLET_DATA, |
| 36 syncer::AUTOFILL_WALLET_DATA, syncer::AUTOFILL_WALLET_METADATA, | 34 AUTOFILL_WALLET_METADATA, EXTENSION_SETTINGS, APP_SETTINGS, TYPED_URLS, |
| 37 syncer::EXTENSION_SETTINGS, syncer::APP_SETTINGS, syncer::TYPED_URLS, | 35 HISTORY_DELETE_DIRECTIVES, SYNCED_NOTIFICATIONS, |
| 38 syncer::HISTORY_DELETE_DIRECTIVES, syncer::SYNCED_NOTIFICATIONS, | 36 SYNCED_NOTIFICATION_APP_INFO, |
| 39 syncer::SYNCED_NOTIFICATION_APP_INFO, | |
| 40 | 37 |
| 41 // UI thread data types. | 38 // UI thread data types. |
| 42 syncer::BOOKMARKS, | 39 BOOKMARKS, |
| 43 syncer::SUPERVISED_USERS, // Syncing supervised users on initial login | 40 SUPERVISED_USERS, // Syncing supervised users on initial login |
| 44 // might block creating a new supervised user, | 41 // might block creating a new supervised user, |
| 45 // so we want to do it early. | 42 // so we want to do it early. |
| 46 syncer::PREFERENCES, syncer::PRIORITY_PREFERENCES, syncer::EXTENSIONS, | 43 PREFERENCES, PRIORITY_PREFERENCES, EXTENSIONS, APPS, APP_LIST, ARC_PACKAGE, |
| 47 syncer::APPS, syncer::APP_LIST, syncer::ARC_PACKAGE, syncer::READING_LIST, | 44 READING_LIST, THEMES, SEARCH_ENGINES, SESSIONS, APP_NOTIFICATIONS, |
| 48 syncer::THEMES, syncer::SEARCH_ENGINES, syncer::SESSIONS, | 45 DICTIONARY, FAVICON_IMAGES, FAVICON_TRACKING, PRINTERS, |
| 49 syncer::APP_NOTIFICATIONS, syncer::DICTIONARY, syncer::FAVICON_IMAGES, | 46 SUPERVISED_USER_SETTINGS, SUPERVISED_USER_SHARED_SETTINGS, |
| 50 syncer::FAVICON_TRACKING, syncer::PRINTERS, | 47 SUPERVISED_USER_WHITELISTS, ARTICLES, WIFI_CREDENTIALS, |
| 51 syncer::SUPERVISED_USER_SETTINGS, syncer::SUPERVISED_USER_SHARED_SETTINGS, | |
| 52 syncer::SUPERVISED_USER_WHITELISTS, syncer::ARTICLES, | |
| 53 syncer::WIFI_CREDENTIALS, | |
| 54 }; | 48 }; |
| 55 | 49 |
| 56 static_assert(arraysize(kStartOrder) == | 50 static_assert(arraysize(kStartOrder) == |
| 57 syncer::MODEL_TYPE_COUNT - syncer::FIRST_REAL_MODEL_TYPE, | 51 MODEL_TYPE_COUNT - FIRST_REAL_MODEL_TYPE, |
| 58 "kStartOrder must have MODEL_TYPE_COUNT - " | 52 "kStartOrder must have MODEL_TYPE_COUNT - " |
| 59 "FIRST_REAL_MODEL_TYPE elements"); | 53 "FIRST_REAL_MODEL_TYPE elements"); |
| 60 | 54 |
| 61 // The amount of time we wait for association to finish. If some types haven't | 55 // The amount of time we wait for association to finish. If some types haven't |
| 62 // finished association by the time, DataTypeManager is notified of the | 56 // finished association by the time, DataTypeManager is notified of the |
| 63 // unfinished types. | 57 // unfinished types. |
| 64 const int64_t kAssociationTimeOutInSeconds = 600; | 58 const int64_t kAssociationTimeOutInSeconds = 600; |
| 65 | 59 |
| 66 syncer::DataTypeAssociationStats BuildAssociationStatsFromMergeResults( | 60 DataTypeAssociationStats BuildAssociationStatsFromMergeResults( |
| 67 const syncer::SyncMergeResult& local_merge_result, | 61 const SyncMergeResult& local_merge_result, |
| 68 const syncer::SyncMergeResult& syncer_merge_result, | 62 const SyncMergeResult& syncer_merge_result, |
| 69 const base::TimeDelta& association_wait_time, | 63 const base::TimeDelta& association_wait_time, |
| 70 const base::TimeDelta& association_time) { | 64 const base::TimeDelta& association_time) { |
| 71 DCHECK_EQ(local_merge_result.model_type(), syncer_merge_result.model_type()); | 65 DCHECK_EQ(local_merge_result.model_type(), syncer_merge_result.model_type()); |
| 72 syncer::DataTypeAssociationStats stats; | 66 DataTypeAssociationStats stats; |
| 73 stats.had_error = | 67 stats.had_error = |
| 74 local_merge_result.error().IsSet() || syncer_merge_result.error().IsSet(); | 68 local_merge_result.error().IsSet() || syncer_merge_result.error().IsSet(); |
| 75 stats.num_local_items_before_association = | 69 stats.num_local_items_before_association = |
| 76 local_merge_result.num_items_before_association(); | 70 local_merge_result.num_items_before_association(); |
| 77 stats.num_sync_items_before_association = | 71 stats.num_sync_items_before_association = |
| 78 syncer_merge_result.num_items_before_association(); | 72 syncer_merge_result.num_items_before_association(); |
| 79 stats.num_local_items_after_association = | 73 stats.num_local_items_after_association = |
| 80 local_merge_result.num_items_after_association(); | 74 local_merge_result.num_items_after_association(); |
| 81 stats.num_sync_items_after_association = | 75 stats.num_sync_items_after_association = |
| 82 syncer_merge_result.num_items_after_association(); | 76 syncer_merge_result.num_items_after_association(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 108 weak_ptr_factory_(this) { | 102 weak_ptr_factory_(this) { |
| 109 // Ensure all data type controllers are stopped. | 103 // Ensure all data type controllers are stopped. |
| 110 for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); | 104 for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); |
| 111 it != controllers_->end(); ++it) { | 105 it != controllers_->end(); ++it) { |
| 112 DCHECK_EQ(DataTypeController::NOT_RUNNING, (*it).second->state()); | 106 DCHECK_EQ(DataTypeController::NOT_RUNNING, (*it).second->state()); |
| 113 } | 107 } |
| 114 } | 108 } |
| 115 | 109 |
| 116 ModelAssociationManager::~ModelAssociationManager() {} | 110 ModelAssociationManager::~ModelAssociationManager() {} |
| 117 | 111 |
| 118 void ModelAssociationManager::Initialize(syncer::ModelTypeSet desired_types) { | 112 void ModelAssociationManager::Initialize(ModelTypeSet desired_types) { |
| 119 // state_ can be INITIALIZED if types are reconfigured when | 113 // state_ can be INITIALIZED if types are reconfigured when |
| 120 // data is being downloaded, so StartAssociationAsync() is never called for | 114 // data is being downloaded, so StartAssociationAsync() is never called for |
| 121 // the first configuration. | 115 // the first configuration. |
| 122 DCHECK_NE(ASSOCIATING, state_); | 116 DCHECK_NE(ASSOCIATING, state_); |
| 123 | 117 |
| 124 // Only keep types that have controllers. | 118 // Only keep types that have controllers. |
| 125 desired_types_.Clear(); | 119 desired_types_.Clear(); |
| 126 for (syncer::ModelTypeSet::Iterator it = desired_types.First(); it.Good(); | 120 for (ModelTypeSet::Iterator it = desired_types.First(); it.Good(); it.Inc()) { |
| 127 it.Inc()) { | |
| 128 if (controllers_->find(it.Get()) != controllers_->end()) | 121 if (controllers_->find(it.Get()) != controllers_->end()) |
| 129 desired_types_.Put(it.Get()); | 122 desired_types_.Put(it.Get()); |
| 130 } | 123 } |
| 131 | 124 |
| 132 DVLOG(1) << "ModelAssociationManager: Initializing for " | 125 DVLOG(1) << "ModelAssociationManager: Initializing for " |
| 133 << syncer::ModelTypeSetToString(desired_types_); | 126 << ModelTypeSetToString(desired_types_); |
| 134 | 127 |
| 135 state_ = INITIALIZED; | 128 state_ = INITIALIZED; |
| 136 notified_about_ready_for_configure_ = false; | 129 notified_about_ready_for_configure_ = false; |
| 137 | 130 |
| 138 StopDisabledTypes(); | 131 StopDisabledTypes(); |
| 139 LoadEnabledTypes(); | 132 LoadEnabledTypes(); |
| 140 } | 133 } |
| 141 | 134 |
| 142 void ModelAssociationManager::StopDatatype(const syncer::SyncError& error, | 135 void ModelAssociationManager::StopDatatype(const SyncError& error, |
| 143 DataTypeController* dtc) { | 136 DataTypeController* dtc) { |
| 144 loaded_types_.Remove(dtc->type()); | 137 loaded_types_.Remove(dtc->type()); |
| 145 associated_types_.Remove(dtc->type()); | 138 associated_types_.Remove(dtc->type()); |
| 146 associating_types_.Remove(dtc->type()); | 139 associating_types_.Remove(dtc->type()); |
| 147 | 140 |
| 148 if (error.IsSet() || dtc->state() != DataTypeController::NOT_RUNNING) { | 141 if (error.IsSet() || dtc->state() != DataTypeController::NOT_RUNNING) { |
| 149 // If an error was set, the delegate must be informed of the error. | 142 // If an error was set, the delegate must be informed of the error. |
| 150 delegate_->OnSingleDataTypeWillStop(dtc->type(), error); | 143 delegate_->OnSingleDataTypeWillStop(dtc->type(), error); |
| 151 dtc->Stop(); | 144 dtc->Stop(); |
| 152 } | 145 } |
| 153 } | 146 } |
| 154 | 147 |
| 155 void ModelAssociationManager::StopDisabledTypes() { | 148 void ModelAssociationManager::StopDisabledTypes() { |
| 156 DVLOG(1) << "ModelAssociationManager: Stopping disabled types."; | 149 DVLOG(1) << "ModelAssociationManager: Stopping disabled types."; |
| 157 for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); | 150 for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); |
| 158 it != controllers_->end(); ++it) { | 151 it != controllers_->end(); ++it) { |
| 159 DataTypeController* dtc = (*it).second.get(); | 152 DataTypeController* dtc = (*it).second.get(); |
| 160 if (dtc->state() != DataTypeController::NOT_RUNNING && | 153 if (dtc->state() != DataTypeController::NOT_RUNNING && |
| 161 !desired_types_.Has(dtc->type())) { | 154 !desired_types_.Has(dtc->type())) { |
| 162 DVLOG(1) << "ModelAssociationManager: stop " << dtc->name(); | 155 DVLOG(1) << "ModelAssociationManager: stop " << dtc->name(); |
| 163 StopDatatype(syncer::SyncError(), dtc); | 156 StopDatatype(SyncError(), dtc); |
| 164 } | 157 } |
| 165 } | 158 } |
| 166 } | 159 } |
| 167 | 160 |
| 168 void ModelAssociationManager::LoadEnabledTypes() { | 161 void ModelAssociationManager::LoadEnabledTypes() { |
| 169 // Load in kStartOrder. | 162 // Load in kStartOrder. |
| 170 for (size_t i = 0; i < arraysize(kStartOrder); i++) { | 163 for (size_t i = 0; i < arraysize(kStartOrder); i++) { |
| 171 syncer::ModelType type = kStartOrder[i]; | 164 ModelType type = kStartOrder[i]; |
| 172 if (!desired_types_.Has(type)) | 165 if (!desired_types_.Has(type)) |
| 173 continue; | 166 continue; |
| 174 | 167 |
| 175 DCHECK(controllers_->find(type) != controllers_->end()); | 168 DCHECK(controllers_->find(type) != controllers_->end()); |
| 176 DataTypeController* dtc = controllers_->find(type)->second.get(); | 169 DataTypeController* dtc = controllers_->find(type)->second.get(); |
| 177 if (dtc->state() == DataTypeController::NOT_RUNNING) { | 170 if (dtc->state() == DataTypeController::NOT_RUNNING) { |
| 178 DCHECK(!loaded_types_.Has(dtc->type())); | 171 DCHECK(!loaded_types_.Has(dtc->type())); |
| 179 DCHECK(!associated_types_.Has(dtc->type())); | 172 DCHECK(!associated_types_.Has(dtc->type())); |
| 180 dtc->LoadModels(base::Bind(&ModelAssociationManager::ModelLoadCallback, | 173 dtc->LoadModels(base::Bind(&ModelAssociationManager::ModelLoadCallback, |
| 181 weak_ptr_factory_.GetWeakPtr())); | 174 weak_ptr_factory_.GetWeakPtr())); |
| 182 } | 175 } |
| 183 } | 176 } |
| 184 NotifyDelegateIfReadyForConfigure(); | 177 NotifyDelegateIfReadyForConfigure(); |
| 185 } | 178 } |
| 186 | 179 |
| 187 void ModelAssociationManager::StartAssociationAsync( | 180 void ModelAssociationManager::StartAssociationAsync( |
| 188 const syncer::ModelTypeSet& types_to_associate) { | 181 const ModelTypeSet& types_to_associate) { |
| 189 DCHECK_EQ(INITIALIZED, state_); | 182 DCHECK_EQ(INITIALIZED, state_); |
| 190 DVLOG(1) << "Starting association for " | 183 DVLOG(1) << "Starting association for " |
| 191 << syncer::ModelTypeSetToString(types_to_associate); | 184 << ModelTypeSetToString(types_to_associate); |
| 192 state_ = ASSOCIATING; | 185 state_ = ASSOCIATING; |
| 193 | 186 |
| 194 association_start_time_ = base::TimeTicks::Now(); | 187 association_start_time_ = base::TimeTicks::Now(); |
| 195 | 188 |
| 196 requested_types_ = types_to_associate; | 189 requested_types_ = types_to_associate; |
| 197 | 190 |
| 198 associating_types_ = types_to_associate; | 191 associating_types_ = types_to_associate; |
| 199 associating_types_.RetainAll(desired_types_); | 192 associating_types_.RetainAll(desired_types_); |
| 200 associating_types_.RemoveAll(associated_types_); | 193 associating_types_.RemoveAll(associated_types_); |
| 201 | 194 |
| 202 // Assume success. | 195 // Assume success. |
| 203 configure_status_ = DataTypeManager::OK; | 196 configure_status_ = DataTypeManager::OK; |
| 204 | 197 |
| 205 // Done if no types to associate. | 198 // Done if no types to associate. |
| 206 if (associating_types_.Empty()) { | 199 if (associating_types_.Empty()) { |
| 207 ModelAssociationDone(INITIALIZED); | 200 ModelAssociationDone(INITIALIZED); |
| 208 return; | 201 return; |
| 209 } | 202 } |
| 210 | 203 |
| 211 timer_.Start(FROM_HERE, | 204 timer_.Start(FROM_HERE, |
| 212 base::TimeDelta::FromSeconds(kAssociationTimeOutInSeconds), | 205 base::TimeDelta::FromSeconds(kAssociationTimeOutInSeconds), |
| 213 base::Bind(&ModelAssociationManager::ModelAssociationDone, | 206 base::Bind(&ModelAssociationManager::ModelAssociationDone, |
| 214 weak_ptr_factory_.GetWeakPtr(), INITIALIZED)); | 207 weak_ptr_factory_.GetWeakPtr(), INITIALIZED)); |
| 215 | 208 |
| 216 // Start association of types that are loaded in specified order. | 209 // Start association of types that are loaded in specified order. |
| 217 for (size_t i = 0; i < arraysize(kStartOrder); i++) { | 210 for (size_t i = 0; i < arraysize(kStartOrder); i++) { |
| 218 syncer::ModelType type = kStartOrder[i]; | 211 ModelType type = kStartOrder[i]; |
| 219 if (!associating_types_.Has(type) || !loaded_types_.Has(type)) | 212 if (!associating_types_.Has(type) || !loaded_types_.Has(type)) |
| 220 continue; | 213 continue; |
| 221 | 214 |
| 222 DataTypeController* dtc = controllers_->find(type)->second.get(); | 215 DataTypeController* dtc = controllers_->find(type)->second.get(); |
| 223 DCHECK(DataTypeController::MODEL_LOADED == dtc->state() || | 216 DCHECK(DataTypeController::MODEL_LOADED == dtc->state() || |
| 224 DataTypeController::ASSOCIATING == dtc->state()); | 217 DataTypeController::ASSOCIATING == dtc->state()); |
| 225 if (dtc->state() == DataTypeController::MODEL_LOADED) { | 218 if (dtc->state() == DataTypeController::MODEL_LOADED) { |
| 226 TRACE_EVENT_ASYNC_BEGIN1("sync", "ModelAssociation", dtc, "DataType", | 219 TRACE_EVENT_ASYNC_BEGIN1("sync", "ModelAssociation", dtc, "DataType", |
| 227 ModelTypeToString(type)); | 220 ModelTypeToString(type)); |
| 228 | 221 |
| 229 dtc->StartAssociating(base::Bind( | 222 dtc->StartAssociating(base::Bind( |
| 230 &ModelAssociationManager::TypeStartCallback, | 223 &ModelAssociationManager::TypeStartCallback, |
| 231 weak_ptr_factory_.GetWeakPtr(), type, base::TimeTicks::Now())); | 224 weak_ptr_factory_.GetWeakPtr(), type, base::TimeTicks::Now())); |
| 232 } | 225 } |
| 233 } | 226 } |
| 234 } | 227 } |
| 235 | 228 |
| 236 void ModelAssociationManager::Stop() { | 229 void ModelAssociationManager::Stop() { |
| 237 // Ignore callbacks from controllers. | 230 // Ignore callbacks from controllers. |
| 238 weak_ptr_factory_.InvalidateWeakPtrs(); | 231 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 239 | 232 |
| 240 // Stop started data types. | 233 // Stop started data types. |
| 241 for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); | 234 for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); |
| 242 it != controllers_->end(); ++it) { | 235 it != controllers_->end(); ++it) { |
| 243 DataTypeController* dtc = (*it).second.get(); | 236 DataTypeController* dtc = (*it).second.get(); |
| 244 if (dtc->state() != DataTypeController::NOT_RUNNING) { | 237 if (dtc->state() != DataTypeController::NOT_RUNNING) { |
| 245 StopDatatype(syncer::SyncError(), dtc); | 238 StopDatatype(SyncError(), dtc); |
| 246 DVLOG(1) << "ModelAssociationManager: Stopped " << dtc->name(); | 239 DVLOG(1) << "ModelAssociationManager: Stopped " << dtc->name(); |
| 247 } | 240 } |
| 248 } | 241 } |
| 249 | 242 |
| 250 desired_types_.Clear(); | 243 desired_types_.Clear(); |
| 251 loaded_types_.Clear(); | 244 loaded_types_.Clear(); |
| 252 associated_types_.Clear(); | 245 associated_types_.Clear(); |
| 253 | 246 |
| 254 if (state_ == ASSOCIATING) { | 247 if (state_ == ASSOCIATING) { |
| 255 if (configure_status_ == DataTypeManager::OK) | 248 if (configure_status_ == DataTypeManager::OK) |
| 256 configure_status_ = DataTypeManager::ABORTED; | 249 configure_status_ = DataTypeManager::ABORTED; |
| 257 DVLOG(1) << "ModelAssociationManager: Calling OnModelAssociationDone"; | 250 DVLOG(1) << "ModelAssociationManager: Calling OnModelAssociationDone"; |
| 258 ModelAssociationDone(IDLE); | 251 ModelAssociationDone(IDLE); |
| 259 } else { | 252 } else { |
| 260 DCHECK(associating_types_.Empty()); | 253 DCHECK(associating_types_.Empty()); |
| 261 DCHECK(requested_types_.Empty()); | 254 DCHECK(requested_types_.Empty()); |
| 262 state_ = IDLE; | 255 state_ = IDLE; |
| 263 } | 256 } |
| 264 } | 257 } |
| 265 | 258 |
| 266 void ModelAssociationManager::ModelLoadCallback( | 259 void ModelAssociationManager::ModelLoadCallback(ModelType type, |
| 267 syncer::ModelType type, | 260 const SyncError& error) { |
| 268 const syncer::SyncError& error) { | |
| 269 DVLOG(1) << "ModelAssociationManager: ModelLoadCallback for " | 261 DVLOG(1) << "ModelAssociationManager: ModelLoadCallback for " |
| 270 << syncer::ModelTypeToString(type); | 262 << ModelTypeToString(type); |
| 271 | 263 |
| 272 if (error.IsSet()) { | 264 if (error.IsSet()) { |
| 273 syncer::SyncMergeResult local_merge_result(type); | 265 SyncMergeResult local_merge_result(type); |
| 274 local_merge_result.set_error(error); | 266 local_merge_result.set_error(error); |
| 275 TypeStartCallback(type, base::TimeTicks::Now(), | 267 TypeStartCallback(type, base::TimeTicks::Now(), |
| 276 DataTypeController::ASSOCIATION_FAILED, | 268 DataTypeController::ASSOCIATION_FAILED, |
| 277 local_merge_result, syncer::SyncMergeResult(type)); | 269 local_merge_result, SyncMergeResult(type)); |
| 278 return; | 270 return; |
| 279 } | 271 } |
| 280 | 272 |
| 281 // This happens when slow loading type is disabled by new configuration. | 273 // This happens when slow loading type is disabled by new configuration. |
| 282 if (!desired_types_.Has(type)) | 274 if (!desired_types_.Has(type)) |
| 283 return; | 275 return; |
| 284 | 276 |
| 285 DCHECK(!loaded_types_.Has(type)); | 277 DCHECK(!loaded_types_.Has(type)); |
| 286 loaded_types_.Put(type); | 278 loaded_types_.Put(type); |
| 287 NotifyDelegateIfReadyForConfigure(); | 279 NotifyDelegateIfReadyForConfigure(); |
| 288 if (associating_types_.Has(type)) { | 280 if (associating_types_.Has(type)) { |
| 289 DataTypeController* dtc = controllers_->find(type)->second.get(); | 281 DataTypeController* dtc = controllers_->find(type)->second.get(); |
| 290 // If initial sync was done for this datatype then | 282 // If initial sync was done for this datatype then |
| 291 // NotifyDelegateIfReadyForConfigure possibly already triggered model | 283 // NotifyDelegateIfReadyForConfigure possibly already triggered model |
| 292 // association and StartAssociating was already called for this type. To | 284 // association and StartAssociating was already called for this type. To |
| 293 // ensure StartAssociating is called only once only make a call if state is | 285 // ensure StartAssociating is called only once only make a call if state is |
| 294 // MODEL_LOADED. | 286 // MODEL_LOADED. |
| 295 // TODO(pavely): Add test for this scenario in DataTypeManagerImpl | 287 // TODO(pavely): Add test for this scenario in DataTypeManagerImpl |
| 296 // unittests. | 288 // unittests. |
| 297 if (dtc->state() == DataTypeController::MODEL_LOADED) { | 289 if (dtc->state() == DataTypeController::MODEL_LOADED) { |
| 298 dtc->StartAssociating(base::Bind( | 290 dtc->StartAssociating(base::Bind( |
| 299 &ModelAssociationManager::TypeStartCallback, | 291 &ModelAssociationManager::TypeStartCallback, |
| 300 weak_ptr_factory_.GetWeakPtr(), type, base::TimeTicks::Now())); | 292 weak_ptr_factory_.GetWeakPtr(), type, base::TimeTicks::Now())); |
| 301 } | 293 } |
| 302 } | 294 } |
| 303 } | 295 } |
| 304 | 296 |
| 305 void ModelAssociationManager::TypeStartCallback( | 297 void ModelAssociationManager::TypeStartCallback( |
| 306 syncer::ModelType type, | 298 ModelType type, |
| 307 base::TimeTicks type_start_time, | 299 base::TimeTicks type_start_time, |
| 308 DataTypeController::ConfigureResult start_result, | 300 DataTypeController::ConfigureResult start_result, |
| 309 const syncer::SyncMergeResult& local_merge_result, | 301 const SyncMergeResult& local_merge_result, |
| 310 const syncer::SyncMergeResult& syncer_merge_result) { | 302 const SyncMergeResult& syncer_merge_result) { |
| 311 if (desired_types_.Has(type) && | 303 if (desired_types_.Has(type) && |
| 312 !DataTypeController::IsSuccessfulResult(start_result)) { | 304 !DataTypeController::IsSuccessfulResult(start_result)) { |
| 313 DVLOG(1) << "ModelAssociationManager: Type encountered an error."; | 305 DVLOG(1) << "ModelAssociationManager: Type encountered an error."; |
| 314 desired_types_.Remove(type); | 306 desired_types_.Remove(type); |
| 315 DataTypeController* dtc = controllers_->find(type)->second.get(); | 307 DataTypeController* dtc = controllers_->find(type)->second.get(); |
| 316 StopDatatype(local_merge_result.error(), dtc); | 308 StopDatatype(local_merge_result.error(), dtc); |
| 317 NotifyDelegateIfReadyForConfigure(); | 309 NotifyDelegateIfReadyForConfigure(); |
| 318 | 310 |
| 319 // Update configuration result. | 311 // Update configuration result. |
| 320 if (start_result == DataTypeController::UNRECOVERABLE_ERROR) | 312 if (start_result == DataTypeController::UNRECOVERABLE_ERROR) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 337 | 329 |
| 338 if (state_ != ASSOCIATING) | 330 if (state_ != ASSOCIATING) |
| 339 return; | 331 return; |
| 340 | 332 |
| 341 TRACE_EVENT_ASYNC_END1("sync", "ModelAssociation", | 333 TRACE_EVENT_ASYNC_END1("sync", "ModelAssociation", |
| 342 controllers_->find(type)->second.get(), "DataType", | 334 controllers_->find(type)->second.get(), "DataType", |
| 343 ModelTypeToString(type)); | 335 ModelTypeToString(type)); |
| 344 | 336 |
| 345 // Track the merge results if we succeeded or an association failure | 337 // Track the merge results if we succeeded or an association failure |
| 346 // occurred. | 338 // occurred. |
| 347 if (syncer::ProtocolTypes().Has(type)) { | 339 if (ProtocolTypes().Has(type)) { |
| 348 base::TimeDelta association_wait_time = | 340 base::TimeDelta association_wait_time = |
| 349 std::max(base::TimeDelta(), type_start_time - association_start_time_); | 341 std::max(base::TimeDelta(), type_start_time - association_start_time_); |
| 350 base::TimeDelta association_time = base::TimeTicks::Now() - type_start_time; | 342 base::TimeDelta association_time = base::TimeTicks::Now() - type_start_time; |
| 351 syncer::DataTypeAssociationStats stats = | 343 DataTypeAssociationStats stats = BuildAssociationStatsFromMergeResults( |
| 352 BuildAssociationStatsFromMergeResults( | 344 local_merge_result, syncer_merge_result, association_wait_time, |
| 353 local_merge_result, syncer_merge_result, association_wait_time, | 345 association_time); |
| 354 association_time); | |
| 355 delegate_->OnSingleDataTypeAssociationDone(type, stats); | 346 delegate_->OnSingleDataTypeAssociationDone(type, stats); |
| 356 } | 347 } |
| 357 | 348 |
| 358 associating_types_.Remove(type); | 349 associating_types_.Remove(type); |
| 359 | 350 |
| 360 if (associating_types_.Empty()) | 351 if (associating_types_.Empty()) |
| 361 ModelAssociationDone(INITIALIZED); | 352 ModelAssociationDone(INITIALIZED); |
| 362 } | 353 } |
| 363 | 354 |
| 364 void ModelAssociationManager::ModelAssociationDone(State new_state) { | 355 void ModelAssociationManager::ModelAssociationDone(State new_state) { |
| 365 DCHECK_NE(IDLE, state_); | 356 DCHECK_NE(IDLE, state_); |
| 366 | 357 |
| 367 if (state_ == INITIALIZED) { | 358 if (state_ == INITIALIZED) { |
| 368 // No associations are currently happening. Just reset the state. | 359 // No associations are currently happening. Just reset the state. |
| 369 state_ = new_state; | 360 state_ = new_state; |
| 370 return; | 361 return; |
| 371 } | 362 } |
| 372 | 363 |
| 373 DVLOG(1) << "Model association complete for " | 364 DVLOG(1) << "Model association complete for " |
| 374 << syncer::ModelTypeSetToString(requested_types_); | 365 << ModelTypeSetToString(requested_types_); |
| 375 | 366 |
| 376 timer_.Stop(); | 367 timer_.Stop(); |
| 377 | 368 |
| 378 // Treat any unfinished types as having errors. | 369 // Treat any unfinished types as having errors. |
| 379 desired_types_.RemoveAll(associating_types_); | 370 desired_types_.RemoveAll(associating_types_); |
| 380 for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); | 371 for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); |
| 381 it != controllers_->end(); ++it) { | 372 it != controllers_->end(); ++it) { |
| 382 DataTypeController* dtc = (*it).second.get(); | 373 DataTypeController* dtc = (*it).second.get(); |
| 383 if (associating_types_.Has(dtc->type()) && | 374 if (associating_types_.Has(dtc->type()) && |
| 384 dtc->state() != DataTypeController::NOT_RUNNING) { | 375 dtc->state() != DataTypeController::NOT_RUNNING) { |
| 385 UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureFailed", | 376 UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureFailed", |
| 386 ModelTypeToHistogramInt(dtc->type()), | 377 ModelTypeToHistogramInt(dtc->type()), |
| 387 syncer::MODEL_TYPE_COUNT); | 378 MODEL_TYPE_COUNT); |
| 388 StopDatatype( | 379 StopDatatype(SyncError(FROM_HERE, SyncError::DATATYPE_ERROR, |
| 389 syncer::SyncError(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | 380 "Association timed out.", dtc->type()), |
| 390 "Association timed out.", dtc->type()), | 381 dtc); |
| 391 dtc); | |
| 392 } | 382 } |
| 393 } | 383 } |
| 394 | 384 |
| 395 DataTypeManager::ConfigureResult result(configure_status_, requested_types_); | 385 DataTypeManager::ConfigureResult result(configure_status_, requested_types_); |
| 396 | 386 |
| 397 // Need to reset state before invoking delegate in order to avoid re-entrancy | 387 // Need to reset state before invoking delegate in order to avoid re-entrancy |
| 398 // issues (delegate may trigger a reconfiguration). | 388 // issues (delegate may trigger a reconfiguration). |
| 399 associating_types_.Clear(); | 389 associating_types_.Clear(); |
| 400 requested_types_.Clear(); | 390 requested_types_.Clear(); |
| 401 state_ = new_state; | 391 state_ = new_state; |
| 402 | 392 |
| 403 delegate_->OnModelAssociationDone(result); | 393 delegate_->OnModelAssociationDone(result); |
| 404 } | 394 } |
| 405 | 395 |
| 406 base::OneShotTimer* ModelAssociationManager::GetTimerForTesting() { | 396 base::OneShotTimer* ModelAssociationManager::GetTimerForTesting() { |
| 407 return &timer_; | 397 return &timer_; |
| 408 } | 398 } |
| 409 | 399 |
| 410 void ModelAssociationManager::NotifyDelegateIfReadyForConfigure() { | 400 void ModelAssociationManager::NotifyDelegateIfReadyForConfigure() { |
| 411 if (notified_about_ready_for_configure_) | 401 if (notified_about_ready_for_configure_) |
| 412 return; | 402 return; |
| 413 for (const auto& type_dtc_pair : *controllers_) { | 403 for (const auto& type_dtc_pair : *controllers_) { |
| 414 syncer::ModelType type = type_dtc_pair.first; | 404 ModelType type = type_dtc_pair.first; |
| 415 if (!desired_types_.Has(type)) | 405 if (!desired_types_.Has(type)) |
| 416 continue; | 406 continue; |
| 417 DataTypeController* dtc = type_dtc_pair.second.get(); | 407 DataTypeController* dtc = type_dtc_pair.second.get(); |
| 418 if (dtc->ShouldLoadModelBeforeConfigure() && !loaded_types_.Has(type)) { | 408 if (dtc->ShouldLoadModelBeforeConfigure() && !loaded_types_.Has(type)) { |
| 419 // At least one type is not ready. | 409 // At least one type is not ready. |
| 420 return; | 410 return; |
| 421 } | 411 } |
| 422 } | 412 } |
| 423 | 413 |
| 424 notified_about_ready_for_configure_ = true; | 414 notified_about_ready_for_configure_ = true; |
| 425 delegate_->OnAllDataTypesReadyForConfigure(); | 415 delegate_->OnAllDataTypesReadyForConfigure(); |
| 426 } | 416 } |
| 427 | 417 |
| 428 } // namespace sync_driver | 418 } // namespace syncer |
| OLD | NEW |