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 |