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

Side by Side Diff: chrome/browser/sync/engine/syncer_thread.cc

Issue 3078022: Unplumb AllStatus from SyncerThread. (Closed)
Patch Set: parens Created 10 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
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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 #include "chrome/browser/sync/engine/syncer_thread.h" 4 #include "chrome/browser/sync/engine/syncer_thread.h"
5 5
6 #include "build/build_config.h" 6 #include "build/build_config.h"
7 7
8 #if defined(OS_MACOSX) 8 #if defined(OS_MACOSX)
9 #include <CoreFoundation/CFNumber.h> 9 #include <CoreFoundation/CFNumber.h>
10 #include <IOKit/IOTypes.h> 10 #include <IOKit/IOTypes.h>
11 #include <IOKit/IOKitLib.h> 11 #include <IOKit/IOKitLib.h>
12 #endif 12 #endif
13 13
14 #include <algorithm> 14 #include <algorithm>
15 #include <map> 15 #include <map>
16 #include <queue> 16 #include <queue>
17 17
18 #include "base/rand_util.h"
18 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" 19 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
19 #include "chrome/browser/sync/engine/auth_watcher.h" 20 #include "chrome/browser/sync/engine/auth_watcher.h"
20 #include "chrome/browser/sync/engine/model_safe_worker.h" 21 #include "chrome/browser/sync/engine/model_safe_worker.h"
21 #include "chrome/browser/sync/engine/net/server_connection_manager.h" 22 #include "chrome/browser/sync/engine/net/server_connection_manager.h"
22 #include "chrome/browser/sync/engine/syncer.h" 23 #include "chrome/browser/sync/engine/syncer.h"
24 #include "chrome/browser/sync/sessions/session_state.h"
23 #include "chrome/browser/sync/syncable/directory_manager.h" 25 #include "chrome/browser/sync/syncable/directory_manager.h"
24 #include "chrome/common/chrome_switches.h" 26 #include "chrome/common/chrome_switches.h"
25 #include "jingle/notifier/listener/notification_constants.h" 27 #include "jingle/notifier/listener/notification_constants.h"
26 28
27 using std::priority_queue; 29 using std::priority_queue;
28 using std::min; 30 using std::min;
29 using base::Time; 31 using base::Time;
30 using base::TimeDelta; 32 using base::TimeDelta;
31 using base::TimeTicks; 33 using base::TimeTicks;
32 34
35 namespace browser_sync {
33 36
34 namespace browser_sync { 37 using sessions::SyncSessionSnapshot;
35 38
36 // We use high values here to ensure that failure to receive poll updates from 39 // We use high values here to ensure that failure to receive poll updates from
37 // the server doesn't result in rapid-fire polling from the client due to low 40 // the server doesn't result in rapid-fire polling from the client due to low
38 // local limits. 41 // local limits.
39 const int SyncerThread::kDefaultShortPollIntervalSeconds = 3600 * 8; 42 const int SyncerThread::kDefaultShortPollIntervalSeconds = 3600 * 8;
40 const int SyncerThread::kDefaultLongPollIntervalSeconds = 3600 * 12; 43 const int SyncerThread::kDefaultLongPollIntervalSeconds = 3600 * 12;
41 44
42 // TODO(tim): This is used to regulate the short poll (when notifications are 45 // TODO(tim): This is used to regulate the short poll (when notifications are
43 // disabled) based on user idle time. If it is set to a smaller value than 46 // disabled) based on user idle time. If it is set to a smaller value than
44 // the short poll interval, it basically does nothing; for now, this is what 47 // the short poll interval, it basically does nothing; for now, this is what
45 // we want and allows stronger control over the poll rate from the server. We 48 // we want and allows stronger control over the poll rate from the server. We
46 // should probably re-visit this code later and figure out if user idle time 49 // should probably re-visit this code later and figure out if user idle time
47 // is really something we want and make sure it works, if it is. 50 // is really something we want and make sure it works, if it is.
48 const int SyncerThread::kDefaultMaxPollIntervalMs = 30 * 60 * 1000; 51 const int SyncerThread::kDefaultMaxPollIntervalMs = 30 * 60 * 1000;
49 52
53 // Backoff interval randomization factor.
54 static const int kBackoffRandomizationFactor = 2;
55
56 const int SyncerThread::kMaxBackoffSeconds = 60 * 60 * 4; // 4 hours.
57
50 void SyncerThread::NudgeSyncer(int milliseconds_from_now, NudgeSource source) { 58 void SyncerThread::NudgeSyncer(int milliseconds_from_now, NudgeSource source) {
51 AutoLock lock(lock_); 59 AutoLock lock(lock_);
52 if (vault_.syncer_ == NULL) { 60 if (vault_.syncer_ == NULL) {
53 return; 61 return;
54 } 62 }
55 63
56 NudgeSyncImpl(milliseconds_from_now, source); 64 NudgeSyncImpl(milliseconds_from_now, source);
57 } 65 }
58 66
59 SyncerThread::SyncerThread(sessions::SyncSessionContext* context, 67 SyncerThread::SyncerThread(sessions::SyncSessionContext* context)
60 AllStatus* all_status)
61 : thread_main_started_(false, false), 68 : thread_main_started_(false, false),
62 thread_("SyncEngine_SyncerThread"), 69 thread_("SyncEngine_SyncerThread"),
63 vault_field_changed_(&lock_), 70 vault_field_changed_(&lock_),
64 p2p_authenticated_(false), 71 p2p_authenticated_(false),
65 p2p_subscribed_(false), 72 p2p_subscribed_(false),
66 conn_mgr_hookup_(NULL), 73 conn_mgr_hookup_(NULL),
67 allstatus_(all_status),
68 syncer_short_poll_interval_seconds_(kDefaultShortPollIntervalSeconds), 74 syncer_short_poll_interval_seconds_(kDefaultShortPollIntervalSeconds),
69 syncer_long_poll_interval_seconds_(kDefaultLongPollIntervalSeconds), 75 syncer_long_poll_interval_seconds_(kDefaultLongPollIntervalSeconds),
70 syncer_polling_interval_(kDefaultShortPollIntervalSeconds), 76 syncer_polling_interval_(kDefaultShortPollIntervalSeconds),
71 syncer_max_interval_(kDefaultMaxPollIntervalMs), 77 syncer_max_interval_(kDefaultMaxPollIntervalMs),
72 directory_manager_hookup_(NULL), 78 directory_manager_hookup_(NULL),
73 syncer_events_(NULL), 79 syncer_events_(NULL),
74 session_context_(context), 80 session_context_(context),
75 disable_idle_detection_(false) { 81 disable_idle_detection_(false) {
76 DCHECK(context); 82 DCHECK(context);
77 syncer_event_relay_channel_.reset(new SyncerEventChannel()); 83 syncer_event_relay_channel_.reset(new SyncerEventChannel());
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 // event. This will also update the source of the following SyncMain call. 335 // event. This will also update the source of the following SyncMain call.
330 bool nudged = UpdateNudgeSource(throttled, continue_sync_cycle, 336 bool nudged = UpdateNudgeSource(throttled, continue_sync_cycle,
331 &initial_sync_for_thread); 337 &initial_sync_for_thread);
332 338
333 LOG(INFO) << "Calling Sync Main at time " << Time::Now().ToInternalValue(); 339 LOG(INFO) << "Calling Sync Main at time " << Time::Now().ToInternalValue();
334 SyncMain(vault_.syncer_); 340 SyncMain(vault_.syncer_);
335 last_sync_time = TimeTicks::Now(); 341 last_sync_time = TimeTicks::Now();
336 342
337 LOG(INFO) << "Updating the next polling time after SyncMain"; 343 LOG(INFO) << "Updating the next polling time after SyncMain";
338 vault_.current_wait_interval_ = CalculatePollingWaitTime( 344 vault_.current_wait_interval_ = CalculatePollingWaitTime(
339 allstatus_->status(),
340 static_cast<int>(vault_.current_wait_interval_.poll_delta.InSeconds()), 345 static_cast<int>(vault_.current_wait_interval_.poll_delta.InSeconds()),
341 &user_idle_milliseconds, &continue_sync_cycle, nudged); 346 &user_idle_milliseconds, &continue_sync_cycle, nudged);
342 } 347 }
343 #if defined(OS_LINUX) 348 #if defined(OS_LINUX)
344 idle_query_.reset(); 349 idle_query_.reset();
345 #endif 350 #endif
346 } 351 }
347 352
348 void SyncerThread::WaitUntilConnectedOrQuit() { 353 void SyncerThread::WaitUntilConnectedOrQuit() {
349 LOG(INFO) << "Syncer thread waiting for connection."; 354 LOG(INFO) << "Syncer thread waiting for connection.";
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 void SyncerThread::ExitPausedState() { 413 void SyncerThread::ExitPausedState() {
409 lock_.AssertAcquired(); 414 lock_.AssertAcquired();
410 vault_.paused_ = false; 415 vault_.paused_ = false;
411 vault_field_changed_.Broadcast(); 416 vault_field_changed_.Broadcast();
412 SyncerEvent event(SyncerEvent::RESUMED); 417 SyncerEvent event(SyncerEvent::RESUMED);
413 relay_channel()->Notify(event); 418 relay_channel()->Notify(event);
414 } 419 }
415 420
416 // We check how long the user's been idle and sync less often if the machine is 421 // We check how long the user's been idle and sync less often if the machine is
417 // not in use. The aim is to reduce server load. 422 // not in use. The aim is to reduce server load.
418 // TODO(timsteele): Should use Time(Delta).
419 SyncerThread::WaitInterval SyncerThread::CalculatePollingWaitTime( 423 SyncerThread::WaitInterval SyncerThread::CalculatePollingWaitTime(
420 const AllStatus::Status& status,
421 int last_poll_wait, // Time in seconds. 424 int last_poll_wait, // Time in seconds.
422 int* user_idle_milliseconds, 425 int* user_idle_milliseconds,
423 bool* continue_sync_cycle, 426 bool* continue_sync_cycle,
424 bool was_nudged) { 427 bool was_nudged) {
425 lock_.AssertAcquired(); // We access 'vault' in here, so we need the lock. 428 lock_.AssertAcquired(); // We access 'vault' in here, so we need the lock.
426 WaitInterval return_interval; 429 WaitInterval return_interval;
427 430
428 // Server initiated throttling trumps everything. 431 // Server initiated throttling trumps everything.
429 if (!silenced_until_.is_null()) { 432 if (!silenced_until_.is_null()) {
430 // We don't need to reset other state, it can continue where it left off. 433 // We don't need to reset other state, it can continue where it left off.
431 return_interval.mode = WaitInterval::THROTTLED; 434 return_interval.mode = WaitInterval::THROTTLED;
432 return_interval.poll_delta = silenced_until_ - TimeTicks::Now(); 435 return_interval.poll_delta = silenced_until_ - TimeTicks::Now();
433 return return_interval; 436 return return_interval;
434 } 437 }
435 438
436 bool is_continuing_sync_cyle = *continue_sync_cycle; 439 bool is_continuing_sync_cyle = *continue_sync_cycle;
437 *continue_sync_cycle = false; 440 *continue_sync_cycle = false;
438 441
439 // Determine if the syncer has unfinished work to do from allstatus_. 442 // Determine if the syncer has unfinished work to do.
440 const bool syncer_has_work_to_do = 443 SyncSessionSnapshot* snapshot = session_context_->previous_session_snapshot();
441 status.updates_available > status.updates_received 444 const bool syncer_has_work_to_do = snapshot &&
442 || status.unsynced_count > 0; 445 (snapshot->num_server_changes_remaining > snapshot->max_local_timestamp
446 || snapshot->unsynced_count > 0);
443 LOG(INFO) << "syncer_has_work_to_do is " << syncer_has_work_to_do; 447 LOG(INFO) << "syncer_has_work_to_do is " << syncer_has_work_to_do;
444 448
445 // First calculate the expected wait time, figuring in any backoff because of 449 // First calculate the expected wait time, figuring in any backoff because of
446 // user idle time. next_wait is in seconds 450 // user idle time. next_wait is in seconds
447 syncer_polling_interval_ = (!status.notifications_enabled) ? 451 syncer_polling_interval_ = (!session_context_->notifications_enabled()) ?
448 syncer_short_poll_interval_seconds_ : 452 syncer_short_poll_interval_seconds_ :
449 syncer_long_poll_interval_seconds_; 453 syncer_long_poll_interval_seconds_;
450 int default_next_wait = syncer_polling_interval_; 454 int default_next_wait = syncer_polling_interval_;
451 return_interval.poll_delta = TimeDelta::FromSeconds(default_next_wait); 455 return_interval.poll_delta = TimeDelta::FromSeconds(default_next_wait);
452 456
453 if (syncer_has_work_to_do) { 457 if (syncer_has_work_to_do) {
454 // Provide exponential backoff due to consecutive errors, else attempt to 458 // Provide exponential backoff due to consecutive errors, else attempt to
455 // complete the work as soon as possible. 459 // complete the work as soon as possible.
456 if (is_continuing_sync_cyle) { 460 if (is_continuing_sync_cyle) {
457 return_interval.mode = WaitInterval::EXPONENTIAL_BACKOFF; 461 return_interval.mode = WaitInterval::EXPONENTIAL_BACKOFF;
458 if (was_nudged && vault_.current_wait_interval_.mode == 462 if (was_nudged && vault_.current_wait_interval_.mode ==
459 WaitInterval::EXPONENTIAL_BACKOFF) { 463 WaitInterval::EXPONENTIAL_BACKOFF) {
460 // We were nudged, it failed, and we were already in backoff. 464 // We were nudged, it failed, and we were already in backoff.
461 return_interval.had_nudge_during_backoff = true; 465 return_interval.had_nudge_during_backoff = true;
462 // Keep exponent for exponential backoff the same in this case. 466 // Keep exponent for exponential backoff the same in this case.
463 return_interval.poll_delta = vault_.current_wait_interval_.poll_delta; 467 return_interval.poll_delta = vault_.current_wait_interval_.poll_delta;
464 } else { 468 } else {
465 // We weren't nudged, or we were in a NORMAL wait interval until now. 469 // We weren't nudged, or we were in a NORMAL wait interval until now.
466 return_interval.poll_delta = TimeDelta::FromSeconds( 470 return_interval.poll_delta = TimeDelta::FromSeconds(
467 AllStatus::GetRecommendedDelaySeconds(last_poll_wait)); 471 GetRecommendedDelaySeconds(last_poll_wait));
468 } 472 }
469 } else { 473 } else {
470 // No consecutive error. 474 // No consecutive error.
471 return_interval.poll_delta = TimeDelta::FromSeconds( 475 return_interval.poll_delta = TimeDelta::FromSeconds(
472 AllStatus::GetRecommendedDelaySeconds(0)); 476 GetRecommendedDelaySeconds(0));
473 } 477 }
474 *continue_sync_cycle = true; 478 *continue_sync_cycle = true;
475 } else if (!status.notifications_enabled) { 479 } else if (!session_context_->notifications_enabled()) {
476 // Ensure that we start exponential backoff from our base polling 480 // Ensure that we start exponential backoff from our base polling
477 // interval when we are not continuing a sync cycle. 481 // interval when we are not continuing a sync cycle.
478 last_poll_wait = std::max(last_poll_wait, syncer_polling_interval_); 482 last_poll_wait = std::max(last_poll_wait, syncer_polling_interval_);
479 483
480 // Did the user start interacting with the computer again? 484 // Did the user start interacting with the computer again?
481 // If so, revise our idle time (and probably next_sync_time) downwards 485 // If so, revise our idle time (and probably next_sync_time) downwards
482 int new_idle_time = disable_idle_detection_ ? 0 : UserIdleTime(); 486 int new_idle_time = disable_idle_detection_ ? 0 : UserIdleTime();
483 if (new_idle_time < *user_idle_milliseconds) { 487 if (new_idle_time < *user_idle_milliseconds) {
484 *user_idle_milliseconds = new_idle_time; 488 *user_idle_milliseconds = new_idle_time;
485 } 489 }
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
643 AutoLock lock(lock_); 647 AutoLock lock(lock_);
644 CheckConnected(&vault_.connected_, event.connection_code, 648 CheckConnected(&vault_.connected_, event.connection_code,
645 &vault_field_changed_); 649 &vault_field_changed_);
646 } 650 }
647 } 651 }
648 652
649 SyncerEventChannel* SyncerThread::relay_channel() { 653 SyncerEventChannel* SyncerThread::relay_channel() {
650 return syncer_event_relay_channel_.get(); 654 return syncer_event_relay_channel_.get();
651 } 655 }
652 656
657 int SyncerThread::GetRecommendedDelaySeconds(int base_delay_seconds) {
658 if (base_delay_seconds >= kMaxBackoffSeconds)
659 return kMaxBackoffSeconds;
660
661 // This calculates approx. base_delay_seconds * 2 +/- base_delay_seconds / 2
662 int backoff_s =
663 std::max(1, base_delay_seconds * kBackoffRandomizationFactor);
664
665 // Flip a coin to randomize backoff interval by +/- 50%.
666 int rand_sign = base::RandInt(0, 1) * 2 - 1;
667
668 // Truncation is adequate for rounding here.
669 backoff_s = backoff_s +
670 (rand_sign * (base_delay_seconds / kBackoffRandomizationFactor));
671
672 // Cap the backoff interval.
673 backoff_s = std::max(1, std::min(backoff_s, kMaxBackoffSeconds));
674
675 return backoff_s;
676 }
677
653 // Inputs and return value in milliseconds. 678 // Inputs and return value in milliseconds.
654 int SyncerThread::CalculateSyncWaitTime(int last_interval, int user_idle_ms) { 679 int SyncerThread::CalculateSyncWaitTime(int last_interval, int user_idle_ms) {
655 // syncer_polling_interval_ is in seconds 680 // syncer_polling_interval_ is in seconds
656 int syncer_polling_interval_ms = syncer_polling_interval_ * 1000; 681 int syncer_polling_interval_ms = syncer_polling_interval_ * 1000;
657 682
658 // This is our default and lower bound. 683 // This is our default and lower bound.
659 int next_wait = syncer_polling_interval_ms; 684 int next_wait = syncer_polling_interval_ms;
660 685
661 // Get idle time, bounded by max wait. 686 // Get idle time, bounded by max wait.
662 int idle = min(user_idle_ms, syncer_max_interval_); 687 int idle = min(user_idle_ms, syncer_max_interval_);
663 688
664 // If the user has been idle for a while, we'll start decreasing the poll 689 // If the user has been idle for a while, we'll start decreasing the poll
665 // rate. 690 // rate.
666 if (idle >= kPollBackoffThresholdMultiplier * syncer_polling_interval_ms) { 691 if (idle >= kPollBackoffThresholdMultiplier * syncer_polling_interval_ms) {
667 next_wait = std::min(AllStatus::GetRecommendedDelaySeconds( 692 next_wait = std::min(GetRecommendedDelaySeconds(
668 last_interval / 1000), syncer_max_interval_ / 1000) * 1000; 693 last_interval / 1000), syncer_max_interval_ / 1000) * 1000;
669 } 694 }
670 695
671 return next_wait; 696 return next_wait;
672 } 697 }
673 698
674 // Called with mutex_ already locked. 699 // Called with mutex_ already locked.
675 void SyncerThread::NudgeSyncImpl(int milliseconds_from_now, 700 void SyncerThread::NudgeSyncImpl(int milliseconds_from_now,
676 NudgeSource source) { 701 NudgeSource source) {
677 // TODO(sync): Add the option to reset the backoff state machine. 702 // TODO(sync): Add the option to reset the backoff state machine.
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 was_logged = true; 792 was_logged = true;
768 LOG(INFO) << "UserIdleTime unimplemented on this platform, " 793 LOG(INFO) << "UserIdleTime unimplemented on this platform, "
769 "synchronization will not throttle when user idle"; 794 "synchronization will not throttle when user idle";
770 } 795 }
771 #endif 796 #endif
772 797
773 return 0; 798 return 0;
774 } 799 }
775 800
776 } // namespace browser_sync 801 } // namespace browser_sync
OLDNEW
« no previous file with comments | « chrome/browser/sync/engine/syncer_thread.h ('k') | chrome/browser/sync/engine/syncer_thread_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698