OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "sync/engine/sync_scheduler_impl.h" | 5 #include "sync/engine/sync_scheduler_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cstring> | 8 #include <cstring> |
9 | 9 |
10 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 } | 227 } |
228 | 228 |
229 DCHECK(!session_context_->account_name().empty()); | 229 DCHECK(!session_context_->account_name().empty()); |
230 DCHECK(syncer_.get()); | 230 DCHECK(syncer_.get()); |
231 Mode old_mode = mode_; | 231 Mode old_mode = mode_; |
232 mode_ = mode; | 232 mode_ = mode; |
233 AdjustPolling(UPDATE_INTERVAL); // Will kick start poll timer if needed. | 233 AdjustPolling(UPDATE_INTERVAL); // Will kick start poll timer if needed. |
234 | 234 |
235 if (old_mode != mode_ && | 235 if (old_mode != mode_ && |
236 mode_ == NORMAL_MODE && | 236 mode_ == NORMAL_MODE && |
237 (nudge_tracker_.IsSyncRequired() || | 237 nudge_tracker_.IsSyncRequired() && |
238 nudge_tracker_.IsRetryRequired(base::TimeTicks::Now())) && | |
239 CanRunNudgeJobNow(NORMAL_PRIORITY)) { | 238 CanRunNudgeJobNow(NORMAL_PRIORITY)) { |
240 // We just got back to normal mode. Let's try to run the work that was | 239 // We just got back to normal mode. Let's try to run the work that was |
241 // queued up while we were configuring. | 240 // queued up while we were configuring. |
242 TrySyncSessionJob(); | 241 TrySyncSessionJob(); |
243 } | 242 } |
244 } | 243 } |
245 | 244 |
246 ModelTypeSet SyncSchedulerImpl::GetEnabledAndUnthrottledTypes() { | 245 ModelTypeSet SyncSchedulerImpl::GetEnabledAndUnthrottledTypes() { |
247 ModelTypeSet enabled_types = session_context_->enabled_types(); | 246 ModelTypeSet enabled_types = session_context_->enabled_types(); |
248 ModelTypeSet throttled_types = nudge_tracker_.GetThrottledTypes(); | 247 ModelTypeSet throttled_types = nudge_tracker_.GetThrottledTypes(); |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 // Don't run poll job till the next time poll timer fires. | 462 // Don't run poll job till the next time poll timer fires. |
464 do_poll_after_credentials_updated_ = false; | 463 do_poll_after_credentials_updated_ = false; |
465 | 464 |
466 bool success = !premature_exit | 465 bool success = !premature_exit |
467 && !sessions::HasSyncerError( | 466 && !sessions::HasSyncerError( |
468 session->status_controller().model_neutral_state()); | 467 session->status_controller().model_neutral_state()); |
469 | 468 |
470 if (success) { | 469 if (success) { |
471 // That cycle took care of any outstanding work we had. | 470 // That cycle took care of any outstanding work we had. |
472 SDVLOG(2) << "Nudge succeeded."; | 471 SDVLOG(2) << "Nudge succeeded."; |
473 nudge_tracker_.RecordSuccessfulSyncCycle(base::TimeTicks::Now()); | 472 nudge_tracker_.RecordSuccessfulSyncCycle(); |
474 scheduled_nudge_time_ = base::TimeTicks(); | 473 scheduled_nudge_time_ = base::TimeTicks(); |
475 | 474 |
476 // If we're here, then we successfully reached the server. End all backoff. | 475 // If we're here, then we successfully reached the server. End all backoff. |
477 wait_interval_.reset(); | 476 wait_interval_.reset(); |
478 NotifyRetryTime(base::Time()); | 477 NotifyRetryTime(base::Time()); |
479 return; | 478 return; |
480 } else { | 479 } else { |
481 HandleFailure(session->status_controller().model_neutral_state()); | 480 HandleFailure(session->status_controller().model_neutral_state()); |
482 } | 481 } |
483 } | 482 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 new WaitInterval(WaitInterval::EXPONENTIAL_BACKOFF, length)); | 542 new WaitInterval(WaitInterval::EXPONENTIAL_BACKOFF, length)); |
544 SDVLOG(2) << "Sync cycle failed. Will back off for " | 543 SDVLOG(2) << "Sync cycle failed. Will back off for " |
545 << wait_interval_->length.InMilliseconds() << "ms."; | 544 << wait_interval_->length.InMilliseconds() << "ms."; |
546 RestartWaiting(); | 545 RestartWaiting(); |
547 } | 546 } |
548 } | 547 } |
549 | 548 |
550 void SyncSchedulerImpl::DoPollSyncSessionJob() { | 549 void SyncSchedulerImpl::DoPollSyncSessionJob() { |
551 base::AutoReset<bool> protector(&no_scheduling_allowed_, true); | 550 base::AutoReset<bool> protector(&no_scheduling_allowed_, true); |
552 | 551 |
| 552 if (!CanRunJobNow(NORMAL_PRIORITY)) { |
| 553 SDVLOG(2) << "Unable to run a poll job right now."; |
| 554 return; |
| 555 } |
| 556 |
| 557 if (mode_ != NORMAL_MODE) { |
| 558 SDVLOG(2) << "Not running poll job in configure mode."; |
| 559 return; |
| 560 } |
| 561 |
553 SDVLOG(2) << "Polling with types " | 562 SDVLOG(2) << "Polling with types " |
554 << ModelTypeSetToString(GetEnabledAndUnthrottledTypes()); | 563 << ModelTypeSetToString(session_context_->enabled_types()); |
555 scoped_ptr<SyncSession> session(SyncSession::Build(session_context_, this)); | 564 scoped_ptr<SyncSession> session(SyncSession::Build(session_context_, this)); |
556 syncer_->PollSyncShare( | 565 syncer_->PollSyncShare( |
557 GetEnabledAndUnthrottledTypes(), | 566 GetEnabledAndUnthrottledTypes(), |
558 session.get()); | 567 session.get()); |
559 | 568 |
560 AdjustPolling(FORCE_RESET); | 569 AdjustPolling(FORCE_RESET); |
561 | 570 |
562 if (IsCurrentlyThrottled()) { | 571 if (IsCurrentlyThrottled()) { |
563 SDVLOG(2) << "Poll request got us throttled."; | 572 SDVLOG(2) << "Poll request got us throttled."; |
564 // The OnSilencedUntil() call set up the WaitInterval for us. All we need | 573 // The OnSilencedUntil() call set up the WaitInterval for us. All we need |
565 // to do is start the timer. | 574 // to do is start the timer. |
566 RestartWaiting(); | 575 RestartWaiting(); |
567 } | 576 } |
568 } | 577 } |
569 | 578 |
570 void SyncSchedulerImpl::DoRetrySyncSessionJob() { | |
571 DCHECK(CalledOnValidThread()); | |
572 DCHECK_EQ(mode_, NORMAL_MODE); | |
573 | |
574 base::AutoReset<bool> protector(&no_scheduling_allowed_, true); | |
575 | |
576 SDVLOG(2) << "Retrying with types " | |
577 << ModelTypeSetToString(GetEnabledAndUnthrottledTypes()); | |
578 scoped_ptr<SyncSession> session(SyncSession::Build(session_context_, this)); | |
579 if (syncer_->RetrySyncShare(GetEnabledAndUnthrottledTypes(), | |
580 session.get()) && | |
581 !sessions::HasSyncerError( | |
582 session->status_controller().model_neutral_state())) { | |
583 nudge_tracker_.RecordSuccessfulSyncCycle(base::TimeTicks::Now()); | |
584 } else { | |
585 HandleFailure(session->status_controller().model_neutral_state()); | |
586 } | |
587 } | |
588 | |
589 void SyncSchedulerImpl::UpdateNudgeTimeRecords(ModelTypeSet types) { | 579 void SyncSchedulerImpl::UpdateNudgeTimeRecords(ModelTypeSet types) { |
590 DCHECK(CalledOnValidThread()); | 580 DCHECK(CalledOnValidThread()); |
591 base::TimeTicks now = TimeTicks::Now(); | 581 base::TimeTicks now = TimeTicks::Now(); |
592 // Update timing information for how often datatypes are triggering nudges. | 582 // Update timing information for how often datatypes are triggering nudges. |
593 for (ModelTypeSet::Iterator iter = types.First(); iter.Good(); iter.Inc()) { | 583 for (ModelTypeSet::Iterator iter = types.First(); iter.Good(); iter.Inc()) { |
594 base::TimeTicks previous = last_local_nudges_by_model_type_[iter.Get()]; | 584 base::TimeTicks previous = last_local_nudges_by_model_type_[iter.Get()]; |
595 last_local_nudges_by_model_type_[iter.Get()] = now; | 585 last_local_nudges_by_model_type_[iter.Get()] = now; |
596 if (previous.is_null()) | 586 if (previous.is_null()) |
597 continue; | 587 continue; |
598 | 588 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
686 void SyncSchedulerImpl::TrySyncSessionJobImpl() { | 676 void SyncSchedulerImpl::TrySyncSessionJobImpl() { |
687 JobPriority priority = next_sync_session_job_priority_; | 677 JobPriority priority = next_sync_session_job_priority_; |
688 next_sync_session_job_priority_ = NORMAL_PRIORITY; | 678 next_sync_session_job_priority_ = NORMAL_PRIORITY; |
689 | 679 |
690 DCHECK(CalledOnValidThread()); | 680 DCHECK(CalledOnValidThread()); |
691 if (mode_ == CONFIGURATION_MODE) { | 681 if (mode_ == CONFIGURATION_MODE) { |
692 if (pending_configure_params_) { | 682 if (pending_configure_params_) { |
693 SDVLOG(2) << "Found pending configure job"; | 683 SDVLOG(2) << "Found pending configure job"; |
694 DoConfigurationSyncSessionJob(priority); | 684 DoConfigurationSyncSessionJob(priority); |
695 } | 685 } |
696 } else if (CanRunNudgeJobNow(priority)) { | 686 } else { |
697 if (nudge_tracker_.IsSyncRequired()) { | 687 DCHECK(mode_ == NORMAL_MODE); |
| 688 if (nudge_tracker_.IsSyncRequired() && CanRunNudgeJobNow(priority)) { |
698 SDVLOG(2) << "Found pending nudge job"; | 689 SDVLOG(2) << "Found pending nudge job"; |
699 DoNudgeSyncSessionJob(priority); | 690 DoNudgeSyncSessionJob(priority); |
700 } else if (nudge_tracker_.IsRetryRequired(base::TimeTicks::Now())) { | |
701 DoRetrySyncSessionJob(); | |
702 } else if (do_poll_after_credentials_updated_ || | 691 } else if (do_poll_after_credentials_updated_ || |
703 ((base::TimeTicks::Now() - last_poll_reset_) >= GetPollInterval())) { | 692 ((base::TimeTicks::Now() - last_poll_reset_) >= GetPollInterval())) { |
704 DoPollSyncSessionJob(); | 693 DoPollSyncSessionJob(); |
705 // Poll timer fires infrequently. Usually by this time access token is | 694 // Poll timer fires infrequently. Usually by this time access token is |
706 // already expired and poll job will fail with auth error. Set flag to | 695 // already expired and poll job will fail with auth error. Set flag to |
707 // retry poll once ProfileSyncService gets new access token, TryCanaryJob | 696 // retry poll once ProfileSyncService gets new access token, TryCanaryJob |
708 // will be called after access token is retrieved. | 697 // will be called after access token is retrieved. |
709 if (HttpResponse::SYNC_AUTH_ERROR == | 698 if (HttpResponse::SYNC_AUTH_ERROR == |
710 session_context_->connection_manager()->server_status()) { | 699 session_context_->connection_manager()->server_status()) { |
711 do_poll_after_credentials_updated_ = true; | 700 do_poll_after_credentials_updated_ = true; |
(...skipping 29 matching lines...) Expand all Loading... |
741 // timer. If we find that no_scheduling_allowed_ is set here, then | 730 // timer. If we find that no_scheduling_allowed_ is set here, then |
742 // something is very wrong. Maybe someone mistakenly called us directly, or | 731 // something is very wrong. Maybe someone mistakenly called us directly, or |
743 // mishandled the book-keeping for no_scheduling_allowed_. | 732 // mishandled the book-keeping for no_scheduling_allowed_. |
744 NOTREACHED() << "Illegal to schedule job while session in progress."; | 733 NOTREACHED() << "Illegal to schedule job while session in progress."; |
745 return; | 734 return; |
746 } | 735 } |
747 | 736 |
748 TrySyncSessionJob(); | 737 TrySyncSessionJob(); |
749 } | 738 } |
750 | 739 |
751 void SyncSchedulerImpl::RetryTimerCallback() { | |
752 TrySyncSessionJob(); | |
753 } | |
754 | |
755 void SyncSchedulerImpl::Unthrottle() { | 740 void SyncSchedulerImpl::Unthrottle() { |
756 DCHECK(CalledOnValidThread()); | 741 DCHECK(CalledOnValidThread()); |
757 DCHECK_EQ(WaitInterval::THROTTLED, wait_interval_->mode); | 742 DCHECK_EQ(WaitInterval::THROTTLED, wait_interval_->mode); |
758 | 743 |
759 // We're no longer throttled, so clear the wait interval. | 744 // We're no longer throttled, so clear the wait interval. |
760 wait_interval_.reset(); | 745 wait_interval_.reset(); |
761 NotifyRetryTime(base::Time()); | 746 NotifyRetryTime(base::Time()); |
762 | 747 |
763 // We treat this as a 'canary' in the sense that it was originally scheduled | 748 // We treat this as a 'canary' in the sense that it was originally scheduled |
764 // to run some time ago, failed, and we now want to retry, versus a job that | 749 // to run some time ago, failed, and we now want to retry, versus a job that |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
898 DCHECK(CalledOnValidThread()); | 883 DCHECK(CalledOnValidThread()); |
899 if (ShouldRequestEarlyExit( | 884 if (ShouldRequestEarlyExit( |
900 snapshot.model_neutral_state().sync_protocol_error)) { | 885 snapshot.model_neutral_state().sync_protocol_error)) { |
901 SDVLOG(2) << "Sync Scheduler requesting early exit."; | 886 SDVLOG(2) << "Sync Scheduler requesting early exit."; |
902 Stop(); | 887 Stop(); |
903 } | 888 } |
904 if (IsActionableError(snapshot.model_neutral_state().sync_protocol_error)) | 889 if (IsActionableError(snapshot.model_neutral_state().sync_protocol_error)) |
905 OnActionableError(snapshot); | 890 OnActionableError(snapshot); |
906 } | 891 } |
907 | 892 |
908 void SyncSchedulerImpl::OnReceivedGuRetryDelay(const base::TimeDelta& delay) { | |
909 nudge_tracker_.set_next_retry_time(base::TimeTicks::Now() + delay); | |
910 retry_timer_.Start(FROM_HERE, delay, this, | |
911 &SyncSchedulerImpl::RetryTimerCallback); | |
912 } | |
913 | |
914 void SyncSchedulerImpl::SetNotificationsEnabled(bool notifications_enabled) { | 893 void SyncSchedulerImpl::SetNotificationsEnabled(bool notifications_enabled) { |
915 DCHECK(CalledOnValidThread()); | 894 DCHECK(CalledOnValidThread()); |
916 session_context_->set_notifications_enabled(notifications_enabled); | 895 session_context_->set_notifications_enabled(notifications_enabled); |
917 if (notifications_enabled) | 896 if (notifications_enabled) |
918 nudge_tracker_.OnInvalidationsEnabled(); | 897 nudge_tracker_.OnInvalidationsEnabled(); |
919 else | 898 else |
920 nudge_tracker_.OnInvalidationsDisabled(); | 899 nudge_tracker_.OnInvalidationsDisabled(); |
921 } | 900 } |
922 | 901 |
923 base::TimeDelta SyncSchedulerImpl::GetSessionsCommitDelay() const { | 902 base::TimeDelta SyncSchedulerImpl::GetSessionsCommitDelay() const { |
924 DCHECK(CalledOnValidThread()); | 903 DCHECK(CalledOnValidThread()); |
925 return sessions_commit_delay_; | 904 return sessions_commit_delay_; |
926 } | 905 } |
927 | 906 |
928 #undef SDVLOG_LOC | 907 #undef SDVLOG_LOC |
929 | 908 |
930 #undef SDVLOG | 909 #undef SDVLOG |
931 | 910 |
932 #undef SLOG | 911 #undef SLOG |
933 | 912 |
934 #undef ENUM_CASE | 913 #undef ENUM_CASE |
935 | 914 |
936 } // namespace syncer | 915 } // namespace syncer |
OLD | NEW |