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 "chrome/browser/sync/engine/sync_scheduler.h" | 5 #include "chrome/browser/sync/engine/sync_scheduler.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cstring> | 8 #include <cstring> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 name_(name), | 183 name_(name), |
184 sync_loop_(MessageLoop::current()), | 184 sync_loop_(MessageLoop::current()), |
185 started_(false), | 185 started_(false), |
186 syncer_short_poll_interval_seconds_( | 186 syncer_short_poll_interval_seconds_( |
187 TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds)), | 187 TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds)), |
188 syncer_long_poll_interval_seconds_( | 188 syncer_long_poll_interval_seconds_( |
189 TimeDelta::FromSeconds(kDefaultLongPollIntervalSeconds)), | 189 TimeDelta::FromSeconds(kDefaultLongPollIntervalSeconds)), |
190 sessions_commit_delay_( | 190 sessions_commit_delay_( |
191 TimeDelta::FromSeconds(kDefaultSessionsCommitDelaySeconds)), | 191 TimeDelta::FromSeconds(kDefaultSessionsCommitDelaySeconds)), |
192 mode_(NORMAL_MODE), | 192 mode_(NORMAL_MODE), |
193 server_connection_ok_(false), | |
194 delay_provider_(new DelayProvider()), | 193 delay_provider_(new DelayProvider()), |
195 syncer_(syncer), | 194 syncer_(syncer), |
196 session_context_(context) { | 195 session_context_(context) { |
197 DCHECK(sync_loop_); | 196 DCHECK(sync_loop_); |
198 } | 197 } |
199 | 198 |
200 SyncScheduler::~SyncScheduler() { | 199 SyncScheduler::~SyncScheduler() { |
201 DCHECK_EQ(MessageLoop::current(), sync_loop_); | 200 DCHECK_EQ(MessageLoop::current(), sync_loop_); |
202 StopImpl(base::Closure()); | 201 StopImpl(base::Closure()); |
203 } | 202 } |
204 | 203 |
205 void SyncScheduler::CheckServerConnectionManagerStatus( | |
206 HttpResponse::ServerConnectionCode code) { | |
207 DCHECK_EQ(MessageLoop::current(), sync_loop_); | |
208 SDVLOG(2) << "New server connection code: " | |
209 << HttpResponse::GetServerConnectionCodeString(code); | |
210 bool old_server_connection_ok = server_connection_ok_; | |
211 | |
212 // Note, be careful when adding cases here because if the SyncScheduler | |
213 // thinks there is no valid connection as determined by this method, it | |
214 // will drop out of *all* forward progress sync loops (it won't poll and it | |
215 // will queue up Talk notifications but not actually call SyncShare) until | |
216 // some external action causes a ServerConnectionManager to broadcast that | |
217 // a valid connection has been re-established. | |
218 if (HttpResponse::CONNECTION_UNAVAILABLE == code || | |
219 HttpResponse::SYNC_AUTH_ERROR == code) { | |
220 server_connection_ok_ = false; | |
221 SDVLOG(2) << "Sync auth error or unavailable connection: " | |
222 << "server connection is down"; | |
223 } else if (HttpResponse::SERVER_CONNECTION_OK == code) { | |
224 server_connection_ok_ = true; | |
225 SDVLOG(2) << "Sync server connection is ok: " | |
226 << "server connection is up, doing canary job"; | |
227 DoCanaryJob(); | |
228 } | |
229 | |
230 if (old_server_connection_ok != server_connection_ok_) { | |
231 const char* transition = | |
232 server_connection_ok_ ? "down -> up" : "up -> down"; | |
233 SDVLOG(2) << "Server connection changed: " << transition; | |
234 } | |
235 } | |
236 | |
237 void SyncScheduler::Start(Mode mode, const base::Closure& callback) { | 204 void SyncScheduler::Start(Mode mode, const base::Closure& callback) { |
238 DCHECK_EQ(MessageLoop::current(), sync_loop_); | 205 DCHECK_EQ(MessageLoop::current(), sync_loop_); |
239 std::string thread_name = MessageLoop::current()->thread_name(); | 206 std::string thread_name = MessageLoop::current()->thread_name(); |
240 if (thread_name.empty()) | 207 if (thread_name.empty()) |
241 thread_name = "<Main thread>"; | 208 thread_name = "<Main thread>"; |
242 SDVLOG(2) << "Start called from thread " | 209 SDVLOG(2) << "Start called from thread " |
243 << thread_name << " with mode " << GetModeString(mode); | 210 << thread_name << " with mode " << GetModeString(mode); |
244 if (!started_) { | 211 if (!started_) { |
245 started_ = true; | 212 started_ = true; |
246 WatchConnectionManager(); | |
247 PostTask(FROM_HERE, "SendInitialSnapshot", | 213 PostTask(FROM_HERE, "SendInitialSnapshot", |
248 base::Bind(&SyncScheduler::SendInitialSnapshot, | 214 base::Bind(&SyncScheduler::SendInitialSnapshot, |
249 weak_ptr_factory_.GetWeakPtr())); | 215 weak_ptr_factory_.GetWeakPtr())); |
250 } | 216 } |
251 PostTask(FROM_HERE, "StartImpl", | 217 PostTask(FROM_HERE, "StartImpl", |
252 base::Bind(&SyncScheduler::StartImpl, | 218 base::Bind(&SyncScheduler::StartImpl, |
253 weak_ptr_factory_.GetWeakPtr(), mode, callback)); | 219 weak_ptr_factory_.GetWeakPtr(), mode, callback)); |
254 } | 220 } |
255 | 221 |
256 void SyncScheduler::SendInitialSnapshot() { | 222 void SyncScheduler::SendInitialSnapshot() { |
257 DCHECK_EQ(MessageLoop::current(), sync_loop_); | 223 DCHECK_EQ(MessageLoop::current(), sync_loop_); |
258 scoped_ptr<SyncSession> dummy(new SyncSession(session_context_.get(), this, | 224 scoped_ptr<SyncSession> dummy(new SyncSession(session_context_.get(), this, |
259 SyncSourceInfo(), ModelSafeRoutingInfo(), | 225 SyncSourceInfo(), ModelSafeRoutingInfo(), |
260 std::vector<ModelSafeWorker*>())); | 226 std::vector<ModelSafeWorker*>())); |
261 SyncEngineEvent event(SyncEngineEvent::STATUS_CHANGED); | 227 SyncEngineEvent event(SyncEngineEvent::STATUS_CHANGED); |
262 sessions::SyncSessionSnapshot snapshot(dummy->TakeSnapshot()); | 228 sessions::SyncSessionSnapshot snapshot(dummy->TakeSnapshot()); |
263 event.snapshot = &snapshot; | 229 event.snapshot = &snapshot; |
264 session_context_->NotifyListeners(event); | 230 session_context_->NotifyListeners(event); |
265 } | 231 } |
266 | 232 |
267 void SyncScheduler::WatchConnectionManager() { | |
268 DCHECK_EQ(MessageLoop::current(), sync_loop_); | |
269 ServerConnectionManager* scm = session_context_->connection_manager(); | |
270 PostTask(FROM_HERE, "CheckServerConnectionManagerStatus", | |
271 base::Bind(&SyncScheduler::CheckServerConnectionManagerStatus, | |
272 weak_ptr_factory_.GetWeakPtr(), | |
273 scm->server_status())); | |
274 scm->AddListener(this); | |
275 } | |
276 | |
277 void SyncScheduler::StartImpl(Mode mode, const base::Closure& callback) { | 233 void SyncScheduler::StartImpl(Mode mode, const base::Closure& callback) { |
278 DCHECK_EQ(MessageLoop::current(), sync_loop_); | 234 DCHECK_EQ(MessageLoop::current(), sync_loop_); |
279 SDVLOG(2) << "In StartImpl with mode " << GetModeString(mode); | 235 SDVLOG(2) << "In StartImpl with mode " << GetModeString(mode); |
280 | 236 |
281 DCHECK_EQ(MessageLoop::current(), sync_loop_); | 237 DCHECK_EQ(MessageLoop::current(), sync_loop_); |
282 DCHECK(!session_context_->account_name().empty()); | 238 DCHECK(!session_context_->account_name().empty()); |
283 DCHECK(syncer_.get()); | 239 DCHECK(syncer_.get()); |
284 Mode old_mode = mode_; | 240 Mode old_mode = mode_; |
285 mode_ = mode; | 241 mode_ = mode; |
286 AdjustPolling(NULL); // Will kick start poll timer if needed. | 242 AdjustPolling(NULL); // Will kick start poll timer if needed. |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 // We are in normal mode. | 307 // We are in normal mode. |
352 DCHECK_EQ(mode_, NORMAL_MODE); | 308 DCHECK_EQ(mode_, NORMAL_MODE); |
353 DCHECK_NE(job.purpose, SyncSessionJob::CONFIGURATION); | 309 DCHECK_NE(job.purpose, SyncSessionJob::CONFIGURATION); |
354 | 310 |
355 // Freshness condition | 311 // Freshness condition |
356 if (job.scheduled_start < last_sync_session_end_time_) { | 312 if (job.scheduled_start < last_sync_session_end_time_) { |
357 SDVLOG(2) << "Dropping job because of freshness"; | 313 SDVLOG(2) << "Dropping job because of freshness"; |
358 return DROP; | 314 return DROP; |
359 } | 315 } |
360 | 316 |
361 if (server_connection_ok_) | 317 if (!session_context_->connection_manager()->HasInvalidAuthToken()) |
362 return CONTINUE; | 318 return CONTINUE; |
363 | 319 |
364 SDVLOG(2) << "Bad server connection. Using that to decide on job."; | 320 SDVLOG(2) << "We have no valid auth token. Using that to decide on job."; |
365 return job.purpose == SyncSessionJob::NUDGE ? SAVE : DROP; | 321 return job.purpose == SyncSessionJob::NUDGE ? SAVE : DROP; |
366 } | 322 } |
367 | 323 |
368 void SyncScheduler::InitOrCoalescePendingJob(const SyncSessionJob& job) { | 324 void SyncScheduler::InitOrCoalescePendingJob(const SyncSessionJob& job) { |
369 DCHECK_EQ(MessageLoop::current(), sync_loop_); | 325 DCHECK_EQ(MessageLoop::current(), sync_loop_); |
370 DCHECK(job.purpose != SyncSessionJob::CONFIGURATION); | 326 DCHECK(job.purpose != SyncSessionJob::CONFIGURATION); |
371 if (pending_nudge_.get() == NULL) { | 327 if (pending_nudge_.get() == NULL) { |
372 SDVLOG(2) << "Creating a pending nudge job"; | 328 SDVLOG(2) << "Creating a pending nudge job"; |
373 SyncSession* s = job.session.get(); | 329 SyncSession* s = job.session.get(); |
374 scoped_ptr<SyncSession> session(new SyncSession(s->context(), | 330 scoped_ptr<SyncSession> session(new SyncSession(s->context(), |
(...skipping 634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1009 | 965 |
1010 void SyncScheduler::StopImpl(const base::Closure& callback) { | 966 void SyncScheduler::StopImpl(const base::Closure& callback) { |
1011 DCHECK_EQ(MessageLoop::current(), sync_loop_); | 967 DCHECK_EQ(MessageLoop::current(), sync_loop_); |
1012 SDVLOG(2) << "StopImpl called"; | 968 SDVLOG(2) << "StopImpl called"; |
1013 | 969 |
1014 // Kill any in-flight method calls. | 970 // Kill any in-flight method calls. |
1015 weak_ptr_factory_.InvalidateWeakPtrs(); | 971 weak_ptr_factory_.InvalidateWeakPtrs(); |
1016 wait_interval_.reset(); | 972 wait_interval_.reset(); |
1017 poll_timer_.Stop(); | 973 poll_timer_.Stop(); |
1018 if (started_) { | 974 if (started_) { |
1019 session_context_->connection_manager()->RemoveListener(this); | |
1020 started_ = false; | 975 started_ = false; |
1021 } | 976 } |
1022 if (!callback.is_null()) | 977 if (!callback.is_null()) |
1023 callback.Run(); | 978 callback.Run(); |
1024 } | 979 } |
1025 | 980 |
1026 void SyncScheduler::DoCanaryJob() { | 981 void SyncScheduler::DoCanaryJob() { |
1027 DCHECK_EQ(MessageLoop::current(), sync_loop_); | 982 DCHECK_EQ(MessageLoop::current(), sync_loop_); |
1028 SDVLOG(2) << "Do canary job"; | 983 SDVLOG(2) << "Do canary job"; |
1029 DoPendingJobIfPossible(true); | 984 DoPendingJobIfPossible(true); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1165 const sessions::SyncSessionSnapshot& snapshot) { | 1120 const sessions::SyncSessionSnapshot& snapshot) { |
1166 DCHECK_EQ(MessageLoop::current(), sync_loop_); | 1121 DCHECK_EQ(MessageLoop::current(), sync_loop_); |
1167 if (ShouldRequestEarlyExit(snapshot.errors.sync_protocol_error)) { | 1122 if (ShouldRequestEarlyExit(snapshot.errors.sync_protocol_error)) { |
1168 SDVLOG(2) << "Sync Scheduler requesting early exit."; | 1123 SDVLOG(2) << "Sync Scheduler requesting early exit."; |
1169 syncer_->RequestEarlyExit(); // Thread-safe. | 1124 syncer_->RequestEarlyExit(); // Thread-safe. |
1170 } | 1125 } |
1171 if (IsActionableError(snapshot.errors.sync_protocol_error)) | 1126 if (IsActionableError(snapshot.errors.sync_protocol_error)) |
1172 OnActionableError(snapshot); | 1127 OnActionableError(snapshot); |
1173 } | 1128 } |
1174 | 1129 |
| 1130 void SyncScheduler::TryToConnect() { |
| 1131 if (wait_interval_.get() && wait_interval_->mode == WaitInterval::THROTTLED) |
| 1132 return; |
1175 | 1133 |
1176 void SyncScheduler::OnServerConnectionEvent( | 1134 DoCanaryJob(); |
1177 const ServerConnectionEvent& event) { | |
1178 DCHECK_EQ(MessageLoop::current(), sync_loop_); | |
1179 PostTask(FROM_HERE, "CheckServerConnectionManagerStatus", | |
1180 base::Bind(&SyncScheduler::CheckServerConnectionManagerStatus, | |
1181 weak_ptr_factory_.GetWeakPtr(), | |
1182 event.connection_code)); | |
1183 } | 1135 } |
1184 | 1136 |
1185 void SyncScheduler::set_notifications_enabled(bool notifications_enabled) { | 1137 void SyncScheduler::set_notifications_enabled(bool notifications_enabled) { |
1186 DCHECK_EQ(MessageLoop::current(), sync_loop_); | 1138 DCHECK_EQ(MessageLoop::current(), sync_loop_); |
1187 session_context_->set_notifications_enabled(notifications_enabled); | 1139 session_context_->set_notifications_enabled(notifications_enabled); |
1188 } | 1140 } |
1189 | 1141 |
1190 base::TimeDelta SyncScheduler::sessions_commit_delay() const { | 1142 base::TimeDelta SyncScheduler::sessions_commit_delay() const { |
1191 DCHECK_EQ(MessageLoop::current(), sync_loop_); | 1143 DCHECK_EQ(MessageLoop::current(), sync_loop_); |
1192 return sessions_commit_delay_; | 1144 return sessions_commit_delay_; |
1193 } | 1145 } |
1194 | 1146 |
1195 #undef SDVLOG_LOC | 1147 #undef SDVLOG_LOC |
1196 | 1148 |
1197 #undef SDVLOG | 1149 #undef SDVLOG |
1198 | 1150 |
1199 #undef SLOG | 1151 #undef SLOG |
1200 | 1152 |
1201 #undef ENUM_CASE | 1153 #undef ENUM_CASE |
1202 | 1154 |
1203 } // browser_sync | 1155 } // browser_sync |
OLD | NEW |