Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / sync_file_system / sync_process_runner.cc
blob2f42d790d64254291a70ee8a7fb4d2a271a662c1
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 {
13 namespace {
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
19 // is running).
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;
43 } // namespace
45 SyncProcessRunner::SyncProcessRunner(
46 const std::string& name,
47 SyncFileSystemService* sync_service)
48 : name_(name),
49 sync_service_(sync_service),
50 current_delay_(0),
51 last_delay_(0),
52 pending_changes_(0),
53 running_(false),
54 factory_(this) {}
56 SyncProcessRunner::~SyncProcessRunner() {}
58 void SyncProcessRunner::Schedule() {
59 int64 delay = kSyncDelayInMilliseconds;
60 if (pending_changes_ == 0) {
61 ScheduleInternal(kSyncDelayMaxInMilliseconds);
62 return;
64 switch (GetServiceState()) {
65 case SYNC_SERVICE_RUNNING:
66 if (pending_changes_ > kPendingChangeThresholdForFastSync)
67 delay = kSyncDelayFastInMilliseconds;
68 else
69 delay = kSyncDelayInMilliseconds;
70 break;
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;
78 break;
80 case SYNC_SERVICE_AUTHENTICATION_REQUIRED:
81 case SYNC_SERVICE_DISABLED:
82 delay = kSyncDelayMaxInMilliseconds;
83 break;
85 ScheduleInternal(delay);
88 void SyncProcessRunner::ScheduleIfNotRunning() {
89 if (!timer_.IsRunning())
90 Schedule();
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);
105 Schedule();
108 SyncServiceState SyncProcessRunner::GetServiceState() {
109 return sync_service()->GetSyncServiceState();
112 void SyncProcessRunner::Finished(SyncStatusCode status) {
113 DCHECK(running_);
114 running_ = false;
115 util::Log(logging::LOG_VERBOSE, FROM_HERE,
116 "[%s] * Finished (elapsed: %" PRId64 " sec)",
117 name_.c_str(),
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);
125 else
126 Schedule();
129 void SyncProcessRunner::Run() {
130 if (running_)
131 return;
132 running_ = true;
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());
139 StartSync(
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)
148 return;
150 base::TimeDelta elapsed = base::Time::Now() - last_scheduled_;
151 if (elapsed < time_to_next) {
152 time_to_next = time_to_next - elapsed;
153 } else {
154 time_to_next = base::TimeDelta::FromMilliseconds(
155 kSyncDelayFastInMilliseconds);
157 timer_.Stop();
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