| Index: sync/internal_api/sync_manager.cc
|
| diff --git a/sync/internal_api/sync_manager.cc b/sync/internal_api/sync_manager.cc
|
| index b0d9ebb660a8ecb1a0007cc8b8967691c17340f3..e8ba9dd45dcadeb6335191a7f8cb8a61723361e8 100644
|
| --- a/sync/internal_api/sync_manager.cc
|
| +++ b/sync/internal_api/sync_manager.cc
|
| @@ -197,6 +197,11 @@ class SyncManager::SyncInternal
|
| // went wrong.
|
| bool SignIn(const SyncCredentials& credentials);
|
|
|
| + // Purge from the directory those types with non-empty progress markers
|
| + // but without initial synced ended set.
|
| + // Returns false if an error occurred, true otherwise.
|
| + bool PurgePartiallySyncedTypes();
|
| +
|
| // Update tokens that we're using in Sync. Email must stay the same.
|
| void UpdateCredentials(const SyncCredentials& credentials);
|
|
|
| @@ -357,6 +362,21 @@ class SyncManager::SyncInternal
|
| // Called only by our NetworkChangeNotifier.
|
| virtual void OnIPAddressChanged() OVERRIDE;
|
|
|
| + ModelTypeSet GetTypesWithEmptyProgressMarkerToken(ModelTypeSet types) {
|
| + DCHECK(initialized_);
|
| + syncer::ModelTypeSet result;
|
| + for (syncer::ModelTypeSet::Iterator i = types.First();
|
| + i.Good(); i.Inc()) {
|
| + sync_pb::DataTypeProgressMarker marker;
|
| + directory()->GetDownloadProgress(i.Get(), &marker);
|
| +
|
| + if (marker.token().empty())
|
| + result.Put(i.Get());
|
| +
|
| + }
|
| + return result;
|
| + }
|
| +
|
| syncer::ModelTypeSet InitialSyncEndedTypes() {
|
| DCHECK(initialized_);
|
| return directory()->initial_sync_ended_types();
|
| @@ -751,6 +771,15 @@ syncer::ModelTypeSet SyncManager::InitialSyncEndedTypes() {
|
| return data_->InitialSyncEndedTypes();
|
| }
|
|
|
| +syncer::ModelTypeSet SyncManager::GetTypesWithEmptyProgressMarkerToken(
|
| + syncer::ModelTypeSet types) {
|
| + return data_->GetTypesWithEmptyProgressMarkerToken(types);
|
| +}
|
| +
|
| +bool SyncManager::PurgePartiallySyncedTypes() {
|
| + return data_->PurgePartiallySyncedTypes();
|
| +}
|
| +
|
| void SyncManager::StartSyncingNormally(
|
| const syncer::ModelSafeRoutingInfo& routing_info) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| @@ -924,15 +953,29 @@ bool SyncManager::SyncInternal::Init(
|
| scheduler_.reset(new SyncScheduler(name_, session_context(), new Syncer()));
|
| }
|
|
|
| - bool signed_in = SignIn(credentials);
|
| + bool success = SignIn(credentials);
|
|
|
| - if (signed_in) {
|
| + if (success) {
|
| if (scheduler()) {
|
| scheduler()->Start(syncer::SyncScheduler::CONFIGURATION_MODE);
|
| }
|
|
|
| initialized_ = true;
|
|
|
| + // Unapplied datatypes (those that do not have initial sync ended set) get
|
| + // re-downloaded during any configuration. But, it's possible for a datatype
|
| + // to have a progress marker but not have initial sync ended yet, making
|
| + // it a candidate for migration. This is a problem, as the DataTypeManager
|
| + // does not support a migration while it's already in the middle of a
|
| + // configuration. As a result, any partially synced datatype can stall the
|
| + // DTM, waiting for the configuration to complete, which it never will due
|
| + // to the migration error. In addition, a partially synced nigori will
|
| + // trigger the migration logic before the backend is initialized, resulting
|
| + // in crashes. We therefore detect and purge any partially synced types as
|
| + // part of initialization.
|
| + if (!PurgePartiallySyncedTypes())
|
| + success = false;
|
| +
|
| // Cryptographer should only be accessed while holding a
|
| // transaction. Grabbing the user share for the transaction
|
| // checks the initialization state, so this must come after
|
| @@ -950,14 +993,14 @@ bool SyncManager::SyncInternal::Init(
|
| FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
|
| OnInitializationComplete(
|
| MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()),
|
| - signed_in));
|
| + success));
|
|
|
| - if (!signed_in && testing_mode_ == NON_TEST)
|
| + if (!success && testing_mode_ == NON_TEST)
|
| return false;
|
|
|
| sync_notifier_->AddObserver(this);
|
|
|
| - return signed_in;
|
| + return success;
|
| }
|
|
|
| void SyncManager::SyncInternal::UpdateCryptographerAndNigori(
|
| @@ -1162,6 +1205,20 @@ bool SyncManager::SyncInternal::SignIn(const SyncCredentials& credentials) {
|
| return true;
|
| }
|
|
|
| +bool SyncManager::SyncInternal::PurgePartiallySyncedTypes() {
|
| + syncer::ModelTypeSet partially_synced_types =
|
| + syncer::ModelTypeSet::All();
|
| + partially_synced_types.RemoveAll(InitialSyncEndedTypes());
|
| + partially_synced_types.RemoveAll(GetTypesWithEmptyProgressMarkerToken(
|
| + syncer::ModelTypeSet::All()));
|
| +
|
| + UMA_HISTOGRAM_COUNTS("Sync.PartiallySyncedTypes",
|
| + partially_synced_types.Size());
|
| + if (partially_synced_types.Empty())
|
| + return true;
|
| + return directory()->PurgeEntriesWithTypeIn(partially_synced_types);
|
| +}
|
| +
|
| void SyncManager::SyncInternal::UpdateCredentials(
|
| const SyncCredentials& credentials) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| @@ -2472,20 +2529,4 @@ bool InitialSyncEndedForTypes(syncer::ModelTypeSet types,
|
| return true;
|
| }
|
|
|
| -syncer::ModelTypeSet GetTypesWithEmptyProgressMarkerToken(
|
| - syncer::ModelTypeSet types,
|
| - syncer::UserShare* share) {
|
| - syncer::ModelTypeSet result;
|
| - for (syncer::ModelTypeSet::Iterator i = types.First();
|
| - i.Good(); i.Inc()) {
|
| - sync_pb::DataTypeProgressMarker marker;
|
| - share->directory->GetDownloadProgress(i.Get(), &marker);
|
| -
|
| - if (marker.token().empty())
|
| - result.Put(i.Get());
|
| -
|
| - }
|
| - return result;
|
| -}
|
| -
|
| } // namespace syncer
|
|
|