| 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 |