| 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 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 name_(name), | 185 name_(name), |
| 186 sync_loop_(MessageLoop::current()), | 186 sync_loop_(MessageLoop::current()), |
| 187 started_(false), | 187 started_(false), |
| 188 syncer_short_poll_interval_seconds_( | 188 syncer_short_poll_interval_seconds_( |
| 189 TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds)), | 189 TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds)), |
| 190 syncer_long_poll_interval_seconds_( | 190 syncer_long_poll_interval_seconds_( |
| 191 TimeDelta::FromSeconds(kDefaultLongPollIntervalSeconds)), | 191 TimeDelta::FromSeconds(kDefaultLongPollIntervalSeconds)), |
| 192 sessions_commit_delay_( | 192 sessions_commit_delay_( |
| 193 TimeDelta::FromSeconds(kDefaultSessionsCommitDelaySeconds)), | 193 TimeDelta::FromSeconds(kDefaultSessionsCommitDelaySeconds)), |
| 194 mode_(NORMAL_MODE), | 194 mode_(NORMAL_MODE), |
| 195 // Start with assuming everything is fine with the connection. | |
| 196 // At the end of the sync cycle we would have the correct status. | |
| 197 server_connection_ok_(true), | |
| 198 connection_code_(HttpResponse::SERVER_CONNECTION_OK), | |
| 199 delay_provider_(new DelayProvider()), | 195 delay_provider_(new DelayProvider()), |
| 200 syncer_(syncer), | 196 syncer_(syncer), |
| 201 session_context_(context) { | 197 session_context_(context) { |
| 202 DCHECK(sync_loop_); | 198 DCHECK(sync_loop_); |
| 203 } | 199 } |
| 204 | 200 |
| 205 SyncScheduler::~SyncScheduler() { | 201 SyncScheduler::~SyncScheduler() { |
| 206 DCHECK_EQ(MessageLoop::current(), sync_loop_); | 202 DCHECK_EQ(MessageLoop::current(), sync_loop_); |
| 207 StopImpl(base::Closure()); | 203 StopImpl(base::Closure()); |
| 208 } | 204 } |
| 209 | 205 |
| 210 void SyncScheduler::OnCredentialsUpdated() { | |
| 211 DCHECK_EQ(MessageLoop::current(), sync_loop_); | |
| 212 | |
| 213 // TODO(lipalani): crbug.com/106262. One issue here is that if after | |
| 214 // the auth error we happened to do gettime and it succeeded then | |
| 215 // the |connection_code_| would be briefly OK however it would revert | |
| 216 // back to SYNC_AUTH_ERROR at the end of the sync cycle. The | |
| 217 // referenced bug explores the option of removing gettime calls | |
| 218 // altogethere | |
| 219 if (HttpResponse::SYNC_AUTH_ERROR == connection_code_) { | |
| 220 OnServerConnectionErrorFixed(); | |
| 221 } | |
| 222 } | |
| 223 | |
| 224 void SyncScheduler::OnConnectionStatusChange() { | |
| 225 if (HttpResponse::CONNECTION_UNAVAILABLE == connection_code_) { | |
| 226 // Optimistically assume that the connection is fixed and try | |
| 227 // connecting. | |
| 228 OnServerConnectionErrorFixed(); | |
| 229 } | |
| 230 } | |
| 231 | |
| 232 void SyncScheduler::OnServerConnectionErrorFixed() { | 206 void SyncScheduler::OnServerConnectionErrorFixed() { |
| 233 DCHECK(!server_connection_ok_); | |
| 234 connection_code_ = HttpResponse::SERVER_CONNECTION_OK; | |
| 235 server_connection_ok_ = true; | |
| 236 PostTask(FROM_HERE, "DoCanaryJob", | 207 PostTask(FROM_HERE, "DoCanaryJob", |
| 237 base::Bind(&SyncScheduler::DoCanaryJob, | 208 base::Bind(&SyncScheduler::DoCanaryJob, |
| 238 weak_ptr_factory_.GetWeakPtr())); | 209 weak_ptr_factory_.GetWeakPtr())); |
| 239 | |
| 240 } | |
| 241 | |
| 242 void SyncScheduler::UpdateServerConnectionManagerStatus( | |
| 243 HttpResponse::ServerConnectionCode code) { | |
| 244 DCHECK_EQ(MessageLoop::current(), sync_loop_); | |
| 245 SDVLOG(2) << "New server connection code: " | |
| 246 << HttpResponse::GetServerConnectionCodeString(code); | |
| 247 bool old_server_connection_ok = server_connection_ok_; | |
| 248 | |
| 249 connection_code_ = code; | |
| 250 | |
| 251 // Note, be careful when adding cases here because if the SyncScheduler | |
| 252 // thinks there is no valid connection as determined by this method, it | |
| 253 // will drop out of *all* forward progress sync loops (it won't poll and it | |
| 254 // will queue up Talk notifications but not actually call SyncShare) until | |
| 255 // some external action causes a ServerConnectionManager to broadcast that | |
| 256 // a valid connection has been re-established | |
| 257 if (HttpResponse::CONNECTION_UNAVAILABLE == code || | |
| 258 HttpResponse::SYNC_AUTH_ERROR == code) { | |
| 259 server_connection_ok_ = false; | |
| 260 SDVLOG(2) << "Sync auth error or unavailable connection: " | |
| 261 << "server connection is down"; | |
| 262 } else if (HttpResponse::SERVER_CONNECTION_OK == code) { | |
| 263 server_connection_ok_ = true; | |
| 264 SDVLOG(2) << "Sync server connection is ok: " | |
| 265 << "server connection is up, doing canary job"; | |
| 266 } | |
| 267 | |
| 268 if (old_server_connection_ok != server_connection_ok_) { | |
| 269 const char* transition = | |
| 270 server_connection_ok_ ? "down -> up" : "up -> down"; | |
| 271 SDVLOG(2) << "Server connection changed: " << transition; | |
| 272 } | |
| 273 } | 210 } |
| 274 | 211 |
| 275 void SyncScheduler::Start(Mode mode, const base::Closure& callback) { | 212 void SyncScheduler::Start(Mode mode, const base::Closure& callback) { |
| 276 DCHECK_EQ(MessageLoop::current(), sync_loop_); | 213 DCHECK_EQ(MessageLoop::current(), sync_loop_); |
| 277 std::string thread_name = MessageLoop::current()->thread_name(); | 214 std::string thread_name = MessageLoop::current()->thread_name(); |
| 278 if (thread_name.empty()) | 215 if (thread_name.empty()) |
| 279 thread_name = "<Main thread>"; | 216 thread_name = "<Main thread>"; |
| 280 SDVLOG(2) << "Start called from thread " | 217 SDVLOG(2) << "Start called from thread " |
| 281 << thread_name << " with mode " << GetModeString(mode); | 218 << thread_name << " with mode " << GetModeString(mode); |
| 282 if (!started_) { | 219 if (!started_) { |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 // We are in normal mode. | 315 // We are in normal mode. |
| 379 DCHECK_EQ(mode_, NORMAL_MODE); | 316 DCHECK_EQ(mode_, NORMAL_MODE); |
| 380 DCHECK_NE(job.purpose, SyncSessionJob::CONFIGURATION); | 317 DCHECK_NE(job.purpose, SyncSessionJob::CONFIGURATION); |
| 381 | 318 |
| 382 // Freshness condition | 319 // Freshness condition |
| 383 if (job.scheduled_start < last_sync_session_end_time_) { | 320 if (job.scheduled_start < last_sync_session_end_time_) { |
| 384 SDVLOG(2) << "Dropping job because of freshness"; | 321 SDVLOG(2) << "Dropping job because of freshness"; |
| 385 return DROP; | 322 return DROP; |
| 386 } | 323 } |
| 387 | 324 |
| 388 if (server_connection_ok_) | 325 if (!session_context_->connection_manager()->HasInvalidAuthToken()) |
| 389 return CONTINUE; | 326 return CONTINUE; |
| 390 | 327 |
| 391 SDVLOG(2) << "Bad server connection. Using that to decide on job."; | 328 SDVLOG(2) << "We have no valid auth token. Using that to decide on job."; |
| 392 return job.purpose == SyncSessionJob::NUDGE ? SAVE : DROP; | 329 return job.purpose == SyncSessionJob::NUDGE ? SAVE : DROP; |
| 393 } | 330 } |
| 394 | 331 |
| 395 void SyncScheduler::InitOrCoalescePendingJob(const SyncSessionJob& job) { | 332 void SyncScheduler::InitOrCoalescePendingJob(const SyncSessionJob& job) { |
| 396 DCHECK_EQ(MessageLoop::current(), sync_loop_); | 333 DCHECK_EQ(MessageLoop::current(), sync_loop_); |
| 397 DCHECK(job.purpose != SyncSessionJob::CONFIGURATION); | 334 DCHECK(job.purpose != SyncSessionJob::CONFIGURATION); |
| 398 if (pending_nudge_.get() == NULL) { | 335 if (pending_nudge_.get() == NULL) { |
| 399 SDVLOG(2) << "Creating a pending nudge job"; | 336 SDVLOG(2) << "Creating a pending nudge job"; |
| 400 SyncSession* s = job.session.get(); | 337 SyncSession* s = job.session.get(); |
| 401 scoped_ptr<SyncSession> session(new SyncSession(s->context(), | 338 scoped_ptr<SyncSession> session(new SyncSession(s->context(), |
| (...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 845 ModelTypePayloadMap::const_iterator iter; | 782 ModelTypePayloadMap::const_iterator iter; |
| 846 for (iter = job.session->source().types.begin(); | 783 for (iter = job.session->source().types.begin(); |
| 847 iter != job.session->source().types.end(); | 784 iter != job.session->source().types.end(); |
| 848 ++iter) { | 785 ++iter) { |
| 849 syncable::PostTimeToTypeHistogram(iter->first, | 786 syncable::PostTimeToTypeHistogram(iter->first, |
| 850 now - last_sync_session_end_time_); | 787 now - last_sync_session_end_time_); |
| 851 } | 788 } |
| 852 } | 789 } |
| 853 last_sync_session_end_time_ = now; | 790 last_sync_session_end_time_ = now; |
| 854 | 791 |
| 855 // Now update the status of the connection from SCM. We need this | |
| 856 // to decide whether we need to save/run future jobs. The notifications | |
| 857 // from SCM are not reliable. | |
| 858 // TODO(rlarocque): crbug.com/110954 | |
| 859 // We should get rid of the notifications and | |
| 860 // it is probably not needed to maintain this status variable | |
| 861 // in 2 places. We should query it directly from SCM when needed. | |
| 862 // But that would need little more refactoring(including a method to | |
| 863 // query if the auth token is invalid) from SCM side. | |
| 864 ServerConnectionManager* scm = session_context_->connection_manager(); | 792 ServerConnectionManager* scm = session_context_->connection_manager(); |
| 865 UpdateServerConnectionManagerStatus(scm->server_status()); | 793 SDVLOG(2) << "New server connection code: " |
| 794 << HttpResponse::GetServerConnectionCodeString(scm->server_status()); |
| 866 | 795 |
| 867 UpdateCarryoverSessionState(job); | 796 UpdateCarryoverSessionState(job); |
| 868 if (IsSyncingCurrentlySilenced()) { | 797 if (IsSyncingCurrentlySilenced()) { |
| 869 SDVLOG(2) << "We are currently throttled; not scheduling the next sync."; | 798 SDVLOG(2) << "We are currently throttled; not scheduling the next sync."; |
| 870 // TODO(sync): Investigate whether we need to check job.purpose | 799 // TODO(sync): Investigate whether we need to check job.purpose |
| 871 // here; see DCHECKs in SaveJob(). (See http://crbug.com/90868.) | 800 // here; see DCHECKs in SaveJob(). (See http://crbug.com/90868.) |
| 872 SaveJob(job); | 801 SaveJob(job); |
| 873 return; // Nothing to do. | 802 return; // Nothing to do. |
| 874 } | 803 } |
| 875 | 804 |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1215 | 1144 |
| 1216 #undef SDVLOG_LOC | 1145 #undef SDVLOG_LOC |
| 1217 | 1146 |
| 1218 #undef SDVLOG | 1147 #undef SDVLOG |
| 1219 | 1148 |
| 1220 #undef SLOG | 1149 #undef SLOG |
| 1221 | 1150 |
| 1222 #undef ENUM_CASE | 1151 #undef ENUM_CASE |
| 1223 | 1152 |
| 1224 } // browser_sync | 1153 } // browser_sync |
| OLD | NEW |