1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/sync_file_system/sync_process_runner.h"
7 #include "base/format_macros.h"
8 #include "chrome/browser/sync_file_system/logger.h"
9 #include "chrome/browser/sync_file_system/sync_file_system_service.h"
11 namespace sync_file_system
{
15 // Default delay when more changes are available.
16 const int64 kSyncDelayInMilliseconds
= 1 * base::Time::kMillisecondsPerSecond
;
18 // Default delay when the previous change has had an error (but remote service
20 const int64 kSyncDelayWithSyncError
= 3 * base::Time::kMillisecondsPerSecond
;
22 // Default delay when there're more than 10 pending changes.
23 const int64 kSyncDelayFastInMilliseconds
= 100;
24 const int kPendingChangeThresholdForFastSync
= 10;
26 // Default delay when remote service is temporarily unavailable.
27 const int64 kSyncDelaySlowInMilliseconds
=
28 30 * base::Time::kMillisecondsPerSecond
; // Start with 30 sec + exp backoff
30 // Default delay when there're no changes.
31 const int64 kSyncDelayMaxInMilliseconds
=
32 30 * 60 * base::Time::kMillisecondsPerSecond
; // 30 min
34 bool WasSuccessfulSync(SyncStatusCode status
) {
35 return status
== SYNC_STATUS_OK
||
36 status
== SYNC_STATUS_HAS_CONFLICT
||
37 status
== SYNC_STATUS_NO_CONFLICT
||
38 status
== SYNC_STATUS_NO_CHANGE_TO_SYNC
||
39 status
== SYNC_STATUS_UNKNOWN_ORIGIN
||
40 status
== SYNC_STATUS_RETRY
;
45 SyncProcessRunner::SyncProcessRunner(
46 const std::string
& name
,
47 SyncFileSystemService
* sync_service
)
49 sync_service_(sync_service
),
56 SyncProcessRunner::~SyncProcessRunner() {}
58 void SyncProcessRunner::Schedule() {
59 int64 delay
= kSyncDelayInMilliseconds
;
60 if (pending_changes_
== 0) {
61 ScheduleInternal(kSyncDelayMaxInMilliseconds
);
64 switch (GetServiceState()) {
65 case SYNC_SERVICE_RUNNING
:
66 if (pending_changes_
> kPendingChangeThresholdForFastSync
)
67 delay
= kSyncDelayFastInMilliseconds
;
69 delay
= kSyncDelayInMilliseconds
;
72 case SYNC_SERVICE_TEMPORARY_UNAVAILABLE
:
73 delay
= kSyncDelaySlowInMilliseconds
;
74 if (last_delay_
>= kSyncDelaySlowInMilliseconds
)
75 delay
= last_delay_
* 2;
76 if (delay
>= kSyncDelayMaxInMilliseconds
)
77 delay
= kSyncDelayMaxInMilliseconds
;
80 case SYNC_SERVICE_AUTHENTICATION_REQUIRED
:
81 case SYNC_SERVICE_DISABLED
:
82 delay
= kSyncDelayMaxInMilliseconds
;
85 ScheduleInternal(delay
);
88 void SyncProcessRunner::ScheduleIfNotRunning() {
89 if (!timer_
.IsRunning())
93 void SyncProcessRunner::OnChangesUpdated(
94 int64 pending_changes
) {
95 DCHECK_GE(pending_changes
, 0);
96 int64 old_pending_changes
= pending_changes_
;
97 pending_changes_
= pending_changes
;
98 if (old_pending_changes
!= pending_changes
) {
99 if (pending_changes
== 0)
100 sync_service()->OnSyncIdle();
101 util::Log(logging::LOG_VERBOSE
, FROM_HERE
,
102 "[%s] pending_changes updated: %" PRId64
,
103 name_
.c_str(), pending_changes
);
108 SyncServiceState
SyncProcessRunner::GetServiceState() {
109 return sync_service()->GetSyncServiceState();
112 void SyncProcessRunner::Finished(SyncStatusCode status
) {
115 util::Log(logging::LOG_VERBOSE
, FROM_HERE
,
116 "[%s] * Finished (elapsed: %" PRId64
" sec)",
118 (base::Time::Now() - last_scheduled_
).InSeconds());
119 if (status
== SYNC_STATUS_NO_CHANGE_TO_SYNC
||
120 status
== SYNC_STATUS_FILE_BUSY
)
121 ScheduleInternal(kSyncDelayMaxInMilliseconds
);
122 else if (!WasSuccessfulSync(status
) &&
123 GetServiceState() == SYNC_SERVICE_RUNNING
)
124 ScheduleInternal(kSyncDelayWithSyncError
);
129 void SyncProcessRunner::Run() {
133 last_scheduled_
= base::Time::Now();
134 last_delay_
= current_delay_
;
136 util::Log(logging::LOG_VERBOSE
, FROM_HERE
,
137 "[%s] * Started", name_
.c_str());
140 base::Bind(&SyncProcessRunner::Finished
, factory_
.GetWeakPtr()));
143 void SyncProcessRunner::ScheduleInternal(int64 delay
) {
144 base::TimeDelta time_to_next
= base::TimeDelta::FromMilliseconds(delay
);
146 if (timer_
.IsRunning()) {
147 if (current_delay_
== delay
)
150 base::TimeDelta elapsed
= base::Time::Now() - last_scheduled_
;
151 if (elapsed
< time_to_next
) {
152 time_to_next
= time_to_next
- elapsed
;
154 time_to_next
= base::TimeDelta::FromMilliseconds(
155 kSyncDelayFastInMilliseconds
);
160 if (current_delay_
!= delay
) {
161 util::Log(logging::LOG_VERBOSE
, FROM_HERE
,
162 "[%s] Scheduling task in %" PRId64
" secs",
163 name_
.c_str(), time_to_next
.InSeconds());
165 current_delay_
= delay
;
167 timer_
.Start(FROM_HERE
, time_to_next
, this, &SyncProcessRunner::Run
);
170 } // namespace sync_file_system