Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(539)

Side by Side Diff: chrome/browser/sync/glue/sync_backend_host.cc

Issue 7655055: [Sync] Make BackendMigrator not wait for full sync cycles (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix race condition Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 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 "build/build_config.h" 5 #include "build/build_config.h"
6 6
7 #include "chrome/browser/sync/glue/sync_backend_host.h" 7 #include "chrome/browser/sync/glue/sync_backend_host.h"
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <map> 10 #include <map>
11 11
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/compiler_specific.h" 14 #include "base/compiler_specific.h"
15 #include "base/file_util.h" 15 #include "base/file_util.h"
16 #include "base/task.h" 16 #include "base/task.h"
17 #include "base/threading/thread_restrictions.h" 17 #include "base/threading/thread_restrictions.h"
18 #include "base/tracked.h" 18 #include "base/tracked.h"
19 #include "base/utf_string_conversions.h" 19 #include "base/utf_string_conversions.h"
20 #include "chrome/browser/net/gaia/token_service.h" 20 #include "chrome/browser/net/gaia/token_service.h"
21 #include "chrome/browser/prefs/pref_service.h" 21 #include "chrome/browser/prefs/pref_service.h"
22 #include "chrome/browser/profiles/profile.h" 22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/sync/glue/change_processor.h" 23 #include "chrome/browser/sync/glue/change_processor.h"
24 #include "chrome/browser/sync/glue/http_bridge.h" 24 #include "chrome/browser/sync/glue/http_bridge.h"
25 #include "chrome/browser/sync/internal_api/base_transaction.h" 25 #include "chrome/browser/sync/internal_api/base_transaction.h"
26 #include "chrome/browser/sync/internal_api/read_transaction.h"
26 #include "chrome/browser/sync/internal_api/sync_manager.h" 27 #include "chrome/browser/sync/internal_api/sync_manager.h"
27 #include "chrome/browser/sync/glue/sync_backend_registrar.h" 28 #include "chrome/browser/sync/glue/sync_backend_registrar.h"
28 #include "chrome/browser/sync/notifier/sync_notifier.h" 29 #include "chrome/browser/sync/notifier/sync_notifier.h"
30 #include "chrome/browser/sync/protocol/sync.pb.h"
29 #include "chrome/browser/sync/sessions/session_state.h" 31 #include "chrome/browser/sync/sessions/session_state.h"
30 // TODO(tim): Remove this! We should have a syncapi pass-thru instead. 32 // TODO(tim): Remove this! We should have a syncapi pass-thru instead.
31 #include "chrome/browser/sync/syncable/directory_manager.h" // Cryptographer. 33 #include "chrome/browser/sync/syncable/directory_manager.h" // Cryptographer.
32 #include "chrome/common/chrome_notification_types.h" 34 #include "chrome/common/chrome_notification_types.h"
33 #include "chrome/common/chrome_version_info.h" 35 #include "chrome/common/chrome_version_info.h"
34 #include "chrome/common/net/gaia/gaia_constants.h" 36 #include "chrome/common/net/gaia/gaia_constants.h"
35 #include "chrome/common/pref_names.h" 37 #include "chrome/common/pref_names.h"
36 #include "content/browser/browser_thread.h" 38 #include "content/browser/browser_thread.h"
37 #include "content/common/notification_service.h" 39 #include "content/common/notification_service.h"
38 #include "webkit/glue/webkit_glue.h" 40 #include "webkit/glue/webkit_glue.h"
(...skipping 11 matching lines...) Expand all
50 using sessions::SyncSessionSnapshot; 52 using sessions::SyncSessionSnapshot;
51 using sync_api::SyncCredentials; 53 using sync_api::SyncCredentials;
52 54
53 SyncBackendHost::SyncBackendHost(Profile* profile) 55 SyncBackendHost::SyncBackendHost(Profile* profile)
54 : core_(new Core(profile, 56 : core_(new Core(profile,
55 ALLOW_THIS_IN_INITIALIZER_LIST(this))), 57 ALLOW_THIS_IN_INITIALIZER_LIST(this))),
56 initialization_state_(NOT_INITIALIZED), 58 initialization_state_(NOT_INITIALIZED),
57 sync_thread_("Chrome_SyncThread"), 59 sync_thread_("Chrome_SyncThread"),
58 frontend_loop_(MessageLoop::current()), 60 frontend_loop_(MessageLoop::current()),
59 profile_(profile), 61 profile_(profile),
62 name_(profile_->GetDebugName()),
60 sync_notifier_factory_(webkit_glue::GetUserAgent(GURL()), 63 sync_notifier_factory_(webkit_glue::GetUserAgent(GURL()),
61 profile_->GetRequestContext(), 64 profile_->GetRequestContext(),
62 *CommandLine::ForCurrentProcess()), 65 *CommandLine::ForCurrentProcess()),
63 frontend_(NULL), 66 frontend_(NULL),
64 sync_data_folder_path_( 67 sync_data_folder_path_(
65 profile_->GetPath().Append(kSyncDataFolderName)), 68 profile_->GetPath().Append(kSyncDataFolderName)),
66 last_auth_error_(AuthError::None()) { 69 last_auth_error_(AuthError::None()) {
67 } 70 }
68 71
69 SyncBackendHost::SyncBackendHost() 72 SyncBackendHost::SyncBackendHost()
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 DCHECK_GT(initialization_state_, NOT_INITIALIZED); 275 DCHECK_GT(initialization_state_, NOT_INITIALIZED);
273 276
274 pending_config_mode_state_.reset(new PendingConfigureDataTypesState()); 277 pending_config_mode_state_.reset(new PendingConfigureDataTypesState());
275 pending_config_mode_state_->ready_task = ready_task; 278 pending_config_mode_state_->ready_task = ready_task;
276 pending_config_mode_state_->types_to_add = types_to_add_with_nigori; 279 pending_config_mode_state_->types_to_add = types_to_add_with_nigori;
277 pending_config_mode_state_->added_types = 280 pending_config_mode_state_->added_types =
278 registrar_->ConfigureDataTypes(types_to_add_with_nigori, 281 registrar_->ConfigureDataTypes(types_to_add_with_nigori,
279 types_to_remove_with_nigori); 282 types_to_remove_with_nigori);
280 pending_config_mode_state_->reason = reason; 283 pending_config_mode_state_->reason = reason;
281 284
282 // Cleanup disabled types before starting configuration so that 285 StartConfiguration(!types_to_remove_with_nigori.empty());
283 // callers can assume that the data types are cleaned up once
284 // configuration is done.
285 if (!types_to_remove.empty()) {
286 sync_thread_.message_loop()->PostTask(
287 FROM_HERE,
288 NewRunnableMethod(
289 core_.get(),
290 &SyncBackendHost::Core::DoRequestCleanupDisabledTypes));
291 }
292
293 StartConfiguration(NewCallback(core_.get(),
294 &SyncBackendHost::Core::FinishConfigureDataTypes));
295 } 286 }
296 287
297 void SyncBackendHost::StartConfiguration(Callback0::Type* callback) { 288 void SyncBackendHost::StartConfiguration(bool cleanup_disabled_types) {
tim (not reviewing) 2011/08/26 12:41:40 I'll point out the bools vs enum style guide at ht
298 // Put syncer in the config mode. DTM will put us in normal mode once it is 289 sync_thread_.message_loop()->PostTask(
299 // done. This is to ensure we dont do a normal sync when we are doing model 290 FROM_HERE,
300 // association. 291 base::Bind(&SyncBackendHost::Core::DoStartConfiguration, core_.get(),
301 sync_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( 292 cleanup_disabled_types));
302 core_.get(), &SyncBackendHost::Core::DoStartConfiguration, callback));
303 } 293 }
304 294
305 void SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop() { 295 void SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop() {
306 DCHECK_EQ(MessageLoop::current(), frontend_loop_); 296 DCHECK_EQ(MessageLoop::current(), frontend_loop_);
307 // Nudge the syncer. This is necessary for both datatype addition/deletion. 297 // Nudge the syncer. This is necessary for both datatype addition/deletion.
308 // 298 //
309 // Deletions need a nudge in order to ensure the deletion occurs in a timely 299 // Deletions need a nudge in order to ensure the deletion occurs in a timely
310 // manner (see issue 56416). 300 // manner (see issue 56416).
311 // 301 //
312 // In the case of additions, on the next sync cycle, the syncer should 302 // In the case of additions, on the next sync cycle, the syncer should
313 // notice that the routing info has changed and start the process of 303 // notice that the routing info has changed and start the process of
314 // downloading updates for newly added data types. Once this is 304 // downloading updates for newly added data types. Once this is
315 // complete, the configure_state_.ready_task_ is run via an 305 // complete, the configure_state_.ready_task_ is run via an
316 // OnInitializationComplete notification. 306 // OnInitializationComplete notification.
317 307
318 VLOG(1) << "Syncer in config mode. SBH executing" 308 VLOG(1) << "Syncer in config mode. SBH executing "
319 << "FinishConfigureDataTypesOnFrontendLoop"; 309 << "FinishConfigureDataTypesOnFrontendLoop";
320 310
321 if (pending_config_mode_state_->added_types.empty() && 311 if (pending_config_mode_state_->added_types.empty() &&
322 !core_->sync_manager()->InitialSyncEndedForAllEnabledTypes()) { 312 !core_->sync_manager()->InitialSyncEndedForAllEnabledTypes()) {
323 LOG(WARNING) << "No new types, but initial sync not finished." 313 LOG(WARNING) << "No new types, but initial sync not finished."
324 << "Possible sync db corruption / removal."; 314 << "Possible sync db corruption / removal.";
325 // TODO(tim): Log / UMA / count this somehow? 315 // TODO(tim): Log / UMA / count this somehow?
326 // TODO(tim): If no added types, we could (should?) config only for 316 // TODO(tim): If no added types, we could (should?) config only for
327 // types that are needed... but this is a rare corruption edge case or 317 // types that are needed... but this is a rare corruption edge case or
328 // implies the user mucked around with their syncdb, so for now do all. 318 // implies the user mucked around with their syncdb, so for now do all.
329 pending_config_mode_state_->added_types = 319 pending_config_mode_state_->added_types =
330 pending_config_mode_state_->types_to_add; 320 pending_config_mode_state_->types_to_add;
331 } 321 }
332 322
333 // If we've added types, we always want to request a nudge/config (even if 323 // If we've added types, we always want to request a nudge/config (even if
334 // the initial sync is ended), in case we could not decrypt the data. 324 // the initial sync is ended), in case we could not decrypt the data.
335 if (pending_config_mode_state_->added_types.empty()) { 325 if (pending_config_mode_state_->added_types.empty()) {
336 VLOG(1) << "SyncBackendHost(" << this << "): No new types added. " 326 VLOG(1) << name_ << ": No new types added; calling ready_task directly";
337 << "Calling ready_task directly";
338 // No new types - just notify the caller that the types are available. 327 // No new types - just notify the caller that the types are available.
339 pending_config_mode_state_->ready_task.Run(true); 328 pending_config_mode_state_->ready_task.Run(true);
340 } else { 329 } else {
341 pending_download_state_.reset(pending_config_mode_state_.release()); 330 pending_download_state_.reset(pending_config_mode_state_.release());
342 331
343 // Always configure nigori if it's enabled. 332 // Always configure nigori if it's enabled.
344 syncable::ModelTypeSet types_to_config = 333 syncable::ModelTypeSet types_to_config =
345 pending_download_state_->added_types; 334 pending_download_state_->added_types;
346 if (IsNigoriEnabled()) { 335 if (IsNigoriEnabled()) {
347 types_to_config.insert(syncable::NIGORI); 336 types_to_config.insert(syncable::NIGORI);
348 } 337 }
349 VLOG(1) << "SyncBackendHost(" << this << "):New Types added. " 338 VLOG(1) << name_ << ": types " << ModelTypeSetToString(types_to_config)
350 << "Calling DoRequestConfig"; 339 << "added; calling DoRequestConfig";
351 sync_thread_.message_loop()->PostTask(FROM_HERE, 340 sync_thread_.message_loop()->PostTask(FROM_HERE,
352 NewRunnableMethod(core_.get(), 341 NewRunnableMethod(core_.get(),
353 &SyncBackendHost::Core::DoRequestConfig, 342 &SyncBackendHost::Core::DoRequestConfig,
354 syncable::ModelTypeBitSetFromSet(types_to_config), 343 syncable::ModelTypeBitSetFromSet(types_to_config),
355 pending_download_state_->reason)); 344 pending_download_state_->reason));
356 } 345 }
357 346
358 pending_config_mode_state_.reset(); 347 pending_config_mode_state_.reset();
359 348
360 // Notify the SyncManager about the new types. 349 // Notify the SyncManager about the new types.
361 sync_thread_.message_loop()->PostTask(FROM_HERE, 350 sync_thread_.message_loop()->PostTask(FROM_HERE,
362 NewRunnableMethod(core_.get(), 351 NewRunnableMethod(core_.get(),
363 &SyncBackendHost::Core::DoUpdateEnabledTypes)); 352 &SyncBackendHost::Core::DoUpdateEnabledTypes));
364 } 353 }
365 354
366 void SyncBackendHost::EncryptDataTypes( 355 void SyncBackendHost::EncryptDataTypes(
367 const syncable::ModelTypeSet& encrypted_types) { 356 const syncable::ModelTypeSet& encrypted_types) {
368 sync_thread_.message_loop()->PostTask(FROM_HERE, 357 sync_thread_.message_loop()->PostTask(FROM_HERE,
369 NewRunnableMethod(core_.get(), 358 NewRunnableMethod(core_.get(),
370 &SyncBackendHost::Core::DoEncryptDataTypes, 359 &SyncBackendHost::Core::DoEncryptDataTypes,
371 encrypted_types)); 360 encrypted_types));
372 } 361 }
373 362
374 syncable::ModelTypeSet SyncBackendHost::GetEncryptedDataTypes() const { 363 syncable::ModelTypeSet SyncBackendHost::GetEncryptedDataTypes() const {
375 DCHECK_GT(initialization_state_, NOT_INITIALIZED); 364 DCHECK_GT(initialization_state_, NOT_INITIALIZED);
376 return core_->sync_manager()->GetEncryptedDataTypes(); 365 return core_->sync_manager()->GetEncryptedDataTypes();
377 } 366 }
378 367
368 syncable::ModelTypeSet SyncBackendHost::GetPurgedDataTypes() const {
369 DCHECK_GT(initialization_state_, NOT_INITIALIZED);
370 sync_api::ReadTransaction trans(FROM_HERE, GetUserShare());
371 syncable::ModelTypeSet purged_data_types;
372 for (int i = syncable::FIRST_REAL_MODEL_TYPE;
373 i < syncable::MODEL_TYPE_COUNT; ++i) {
374 syncable::ModelType type = syncable::ModelTypeFromInt(i);
375 sync_pb::DataTypeProgressMarker progress_marker;
376 trans.GetLookup()->GetDownloadProgress(type, &progress_marker);
tim (not reviewing) 2011/08/26 12:41:40 I like the GetDownloadProgress approach, but want
377 if (progress_marker.token().empty()) {
378 purged_data_types.insert(type);
379 }
380 }
381 return purged_data_types;
382 }
383
379 void SyncBackendHost::ActivateDataType( 384 void SyncBackendHost::ActivateDataType(
380 syncable::ModelType type, ModelSafeGroup group, 385 syncable::ModelType type, ModelSafeGroup group,
381 ChangeProcessor* change_processor) { 386 ChangeProcessor* change_processor) {
382 registrar_->ActivateDataType(type, group, change_processor, GetUserShare()); 387 registrar_->ActivateDataType(type, group, change_processor, GetUserShare());
383 } 388 }
384 389
385 void SyncBackendHost::DeactivateDataType(syncable::ModelType type) { 390 void SyncBackendHost::DeactivateDataType(syncable::ModelType type) {
386 registrar_->DeactivateDataType(type); 391 registrar_->DeactivateDataType(type);
387 } 392 }
388 393
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
631 DCHECK(MessageLoop::current() == host_->sync_thread_.message_loop()); 636 DCHECK(MessageLoop::current() == host_->sync_thread_.message_loop());
632 sync_manager_->EncryptDataTypes(encrypted_types); 637 sync_manager_->EncryptDataTypes(encrypted_types);
633 } 638 }
634 639
635 void SyncBackendHost::Core::DoRequestConfig( 640 void SyncBackendHost::Core::DoRequestConfig(
636 const syncable::ModelTypeBitSet& types_to_config, 641 const syncable::ModelTypeBitSet& types_to_config,
637 sync_api::ConfigureReason reason) { 642 sync_api::ConfigureReason reason) {
638 sync_manager_->RequestConfig(types_to_config, reason); 643 sync_manager_->RequestConfig(types_to_config, reason);
639 } 644 }
640 645
641 void SyncBackendHost::Core::DoStartConfiguration(Callback0::Type* callback) { 646 void SyncBackendHost::Core::DoStartConfiguration(bool cleanup_disabled_types) {
642 sync_manager_->StartConfigurationMode(callback); 647 base::Closure done_callback =
648 base::Bind(&SyncBackendHost::Core::FinishConfigureDataTypes,this);
649 base::Closure on_config_done_callback =
650 cleanup_disabled_types ?
651 base::Bind(&SyncBackendHost::Core::DoRequestCleanupDisabledTypes,
652 this, done_callback) :
653 done_callback;
654 sync_manager_->StartConfigurationMode(on_config_done_callback);
643 } 655 }
644 656
645 void SyncBackendHost::Core::DoShutdown(bool sync_disabled) { 657 void SyncBackendHost::Core::DoShutdown(bool sync_disabled) {
646 DCHECK(MessageLoop::current() == host_->sync_thread_.message_loop()); 658 DCHECK(MessageLoop::current() == host_->sync_thread_.message_loop());
647 659
648 save_changes_timer_.Stop(); 660 save_changes_timer_.Stop();
649 sync_manager_->Shutdown(); // Stops the SyncerThread. 661 sync_manager_->Shutdown(); // Stops the SyncerThread.
650 sync_manager_->RemoveObserver(this); 662 sync_manager_->RemoveObserver(this);
651 sync_manager_.reset(); 663 sync_manager_.reset();
652 registrar_->OnSyncerShutdownComplete(); 664 registrar_->OnSyncerShutdownComplete();
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
720 732
721 // If we are waiting for a configuration change, check here to see 733 // If we are waiting for a configuration change, check here to see
722 // if this sync cycle has initialized all of the types we've been 734 // if this sync cycle has initialized all of the types we've been
723 // waiting for. 735 // waiting for.
724 if (host_->pending_download_state_.get()) { 736 if (host_->pending_download_state_.get()) {
725 scoped_ptr<PendingConfigureDataTypesState> state( 737 scoped_ptr<PendingConfigureDataTypesState> state(
726 host_->pending_download_state_.release()); 738 host_->pending_download_state_.release());
727 DCHECK( 739 DCHECK(
728 std::includes(state->types_to_add.begin(), state->types_to_add.end(), 740 std::includes(state->types_to_add.begin(), state->types_to_add.end(),
729 state->added_types.begin(), state->added_types.end())); 741 state->added_types.begin(), state->added_types.end()));
742 VLOG(1)
743 << "Added types: "
744 << syncable::ModelTypeSetToString(state->added_types)
745 << ", configured types: "
746 << syncable::ModelTypeBitSetToString(snapshot->initial_sync_ended);
730 syncable::ModelTypeBitSet added_types = 747 syncable::ModelTypeBitSet added_types =
731 syncable::ModelTypeBitSetFromSet(state->added_types); 748 syncable::ModelTypeBitSetFromSet(state->added_types);
732 bool found_all_added = 749 bool found_all_added =
733 (added_types & snapshot->initial_sync_ended) == added_types; 750 (added_types & snapshot->initial_sync_ended) == added_types;
734 state->ready_task.Run(found_all_added); 751 state->ready_task.Run(found_all_added);
735 if (!found_all_added) 752 if (!found_all_added)
736 return; 753 return;
737 } 754 }
738 755
739 if (host_->initialized()) 756 if (host_->initialized())
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
880 void SyncBackendHost::Core::StartSavingChanges() { 897 void SyncBackendHost::Core::StartSavingChanges() {
881 save_changes_timer_.Start( 898 save_changes_timer_.Start(
882 base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds), 899 base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds),
883 this, &Core::SaveChanges); 900 this, &Core::SaveChanges);
884 } 901 }
885 902
886 void SyncBackendHost::Core::DoRequestClearServerData() { 903 void SyncBackendHost::Core::DoRequestClearServerData() {
887 sync_manager_->RequestClearServerData(); 904 sync_manager_->RequestClearServerData();
888 } 905 }
889 906
890 void SyncBackendHost::Core::DoRequestCleanupDisabledTypes() { 907 void SyncBackendHost::Core::DoRequestCleanupDisabledTypes(
891 sync_manager_->RequestCleanupDisabledTypes(); 908 const base::Closure& callback) {
909 sync_manager_->RequestCleanupDisabledTypes(callback);
892 } 910 }
893 911
894 void SyncBackendHost::Core::SaveChanges() { 912 void SyncBackendHost::Core::SaveChanges() {
895 sync_manager_->SaveChanges(); 913 sync_manager_->SaveChanges();
896 } 914 }
897 915
898 void SyncBackendHost::Core::DeleteSyncDataFolder() { 916 void SyncBackendHost::Core::DeleteSyncDataFolder() {
899 if (file_util::DirectoryExists(host_->sync_data_folder_path())) { 917 if (file_util::DirectoryExists(host_->sync_data_folder_path())) {
900 if (!file_util::Delete(host_->sync_data_folder_path(), true)) 918 if (!file_util::Delete(host_->sync_data_folder_path(), true))
901 LOG(DFATAL) << "Could not delete the Sync Data folder."; 919 LOG(DFATAL) << "Could not delete the Sync Data folder.";
902 } 920 }
903 } 921 }
904 922
905 } // namespace browser_sync 923 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698