1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/sync/engine/syncer_thread.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/rand_util.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/syncer.h" 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeDelta; 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeTicks; 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace browser_sync { 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 17201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochusing sessions::SyncSession; 183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickusing sessions::SyncSessionSnapshot; 19201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochusing sessions::SyncSourceInfo; 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing syncable::ModelTypePayloadMap; 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing syncable::ModelTypeBitSet; 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing sync_pb::GetUpdatesCallerInfo; 2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSyncerThread::DelayProvider::DelayProvider() {} 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSyncerThread::DelayProvider::~DelayProvider() {} 2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSyncerThread::WaitInterval::WaitInterval() {} 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSyncerThread::WaitInterval::~WaitInterval() {} 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSyncerThread::SyncSessionJob::SyncSessionJob() {} 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSyncerThread::SyncSessionJob::~SyncSessionJob() {} 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSyncerThread::SyncSessionJob::SyncSessionJob(SyncSessionJobPurpose purpose, 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::TimeTicks start, 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen linked_ptr<sessions::SyncSession> session, bool is_canary_job, 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const tracked_objects::Location& nudge_location) : purpose(purpose), 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scheduled_start(start), 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen session(session), 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen is_canary_job(is_canary_job), 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen nudge_location(nudge_location) { 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTimeDelta SyncerThread::DelayProvider::GetDelay( 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const base::TimeDelta& last_delay) { 45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return SyncerThread::GetRecommendedDelay(last_delay); 464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenGetUpdatesCallerInfo::GetUpdatesSource GetUpdatesFromNudgeSource( 494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch NudgeSource source) { 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen switch (source) { 51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case NUDGE_SOURCE_NOTIFICATION: 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return GetUpdatesCallerInfo::NOTIFICATION; 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case NUDGE_SOURCE_LOCAL: 54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return GetUpdatesCallerInfo::LOCAL; 55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case NUDGE_SOURCE_CONTINUATION: 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION; 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case NUDGE_SOURCE_UNKNOWN: 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return GetUpdatesCallerInfo::UNKNOWN; 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen default: 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED(); 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return GetUpdatesCallerInfo::UNKNOWN; 624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSyncerThread::WaitInterval::WaitInterval(Mode mode, TimeDelta length) 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : mode(mode), had_nudge(false), length(length) { } 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSyncerThread::SyncerThread(sessions::SyncSessionContext* context, 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Syncer* syncer) 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : thread_("SyncEngine_SyncerThread"), 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncer_short_poll_interval_seconds_( 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds)), 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncer_long_poll_interval_seconds_( 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimeDelta::FromSeconds(kDefaultLongPollIntervalSeconds)), 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen mode_(NORMAL_MODE), 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen server_connection_ok_(false), 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delay_provider_(new DelayProvider()), 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncer_(syncer), 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen session_context_(context) { 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSyncerThread::~SyncerThread() { 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!thread_.IsRunning()); 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::CheckServerConnectionManagerStatus( 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen HttpResponse::ServerConnectionCode code) { 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Server connection changed." 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << "Old mode: " << server_connection_ok_ << " Code: " << code; 91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Note, be careful when adding cases here because if the SyncerThread 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // thinks there is no valid connection as determined by this method, it 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // will drop out of *all* forward progress sync loops (it won't poll and it 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // will queue up Talk notifications but not actually call SyncShare) until 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // some external action causes a ServerConnectionManager to broadcast that 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // a valid connection has been re-established. 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (HttpResponse::CONNECTION_UNAVAILABLE == code || 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen HttpResponse::SYNC_AUTH_ERROR == code) { 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen server_connection_ok_ = false; 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Server connection changed." 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " new mode:" << server_connection_ok_; 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (HttpResponse::SERVER_CONNECTION_OK == code) { 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen server_connection_ok_ = true; 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Server connection changed." 105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " new mode:" << server_connection_ok_; 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DoCanaryJob(); 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::Start(Mode mode, ModeChangeCallback* callback) { 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Start called from thread " 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << MessageLoop::current()->thread_name(); 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!thread_.IsRunning()) { 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Starting thread with mode " 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << mode; 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!thread_.Start()) { 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED() << "Unable to start SyncerThread."; 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WatchConnectionManager(); 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this, &SyncerThread::SendInitialSnapshot)); 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Entering start with mode = " 126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << mode; 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( 129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this, &SyncerThread::StartImpl, mode, callback)); 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::SendInitialSnapshot() { 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<SyncSession> dummy(new SyncSession(session_context_.get(), this, 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSourceInfo(), ModelSafeRoutingInfo(), 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<ModelSafeWorker*>())); 137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncEngineEvent event(SyncEngineEvent::STATUS_CHANGED); 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sessions::SyncSessionSnapshot snapshot(dummy->TakeSnapshot()); 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen event.snapshot = &snapshot; 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen session_context_->NotifyListeners(event); 141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::WatchConnectionManager() { 144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ServerConnectionManager* scm = session_context_->connection_manager(); 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CheckServerConnectionManagerStatus(scm->server_status()); 146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scm->AddListener(this); 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::StartImpl(Mode mode, ModeChangeCallback* callback) { 150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Doing StartImpl with mode " 151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << mode; 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(lipalani): This will leak if startimpl is never run. Fix it using a 154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // ThreadSafeRefcounted object. 155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<ModeChangeCallback> scoped_callback(callback); 156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); 157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!session_context_->account_name().empty()); 158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(syncer_.get()); 159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen mode_ = mode; 160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen AdjustPolling(NULL); // Will kick start poll timer if needed. 161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (scoped_callback.get()) 162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_callback->Run(); 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We just changed our mode. See if there are any pending jobs that we could 165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // execute in the new mode. 166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DoPendingJobIfPossible(false); 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSyncerThread::JobProcessDecision SyncerThread::DecideWhileInWaitInterval( 170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const SyncSessionJob& job) { 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(wait_interval_.get()); 173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_NE(job.purpose, SyncSessionJob::CLEAR_USER_DATA); 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Wait interval mode : " 176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << wait_interval_->mode << "Wait interval had nudge : " 177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << wait_interval_->had_nudge << "is canary job : " 178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << job.is_canary_job; 179731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (job.purpose == SyncSessionJob::POLL) 181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return DROP; 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(job.purpose == SyncSessionJob::NUDGE || 184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen job.purpose == SyncSessionJob::CONFIGURATION); 185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (wait_interval_->mode == WaitInterval::THROTTLED) 186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return SAVE; 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(wait_interval_->mode, WaitInterval::EXPONENTIAL_BACKOFF); 189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (job.purpose == SyncSessionJob::NUDGE) { 190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (mode_ == CONFIGURATION_MODE) 191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return SAVE; 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If we already had one nudge then just drop this nudge. We will retry 194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // later when the timer runs out. 195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return wait_interval_->had_nudge ? DROP : CONTINUE; 196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // This is a config job. 198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return job.is_canary_job ? CONTINUE : SAVE; 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSyncerThread::JobProcessDecision SyncerThread::DecideOnJob( 202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const SyncSessionJob& job) { 203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (job.purpose == SyncSessionJob::CLEAR_USER_DATA) 204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return CONTINUE; 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (wait_interval_.get()) 207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return DecideWhileInWaitInterval(job); 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (mode_ == CONFIGURATION_MODE) { 210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (job.purpose == SyncSessionJob::NUDGE) 211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return SAVE; 212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen else if (job.purpose == SyncSessionJob::CONFIGURATION) 213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return CONTINUE; 214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen else 215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return DROP; 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We are in normal mode. 219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(mode_, NORMAL_MODE); 220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_NE(job.purpose, SyncSessionJob::CONFIGURATION); 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Freshness condition 223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (job.scheduled_start < last_sync_session_end_time_) { 224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" 225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " Dropping job because of freshness"; 226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return DROP; 227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (server_connection_ok_) 230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return CONTINUE; 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " Bad server connection. Using that to decide on job."; 234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return job.purpose == SyncSessionJob::NUDGE ? SAVE : DROP; 235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::InitOrCoalescePendingJob(const SyncSessionJob& job) { 238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(job.purpose != SyncSessionJob::CONFIGURATION); 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (pending_nudge_.get() == NULL) { 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" 241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " Creating a pending nudge job"; 242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSession* s = job.session.get(); 243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<SyncSession> session(new SyncSession(s->context(), 244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen s->delegate(), s->source(), s->routing_info(), s->workers())); 2454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSessionJob new_job(SyncSessionJob::NUDGE, job.scheduled_start, 247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_linked_ptr(session.release()), false, job.nudge_location); 248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_nudge_.reset(new SyncSessionJob(new_job)); 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Coalescing a pending nudge"; 254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_nudge_->session->Coalesce(*(job.session.get())); 255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_nudge_->scheduled_start = job.scheduled_start; 25621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Unfortunately the nudge location cannot be modified. So it stores the 258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // location of the first caller. 25921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 26021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool SyncerThread::ShouldRunJob(const SyncSessionJob& job) { 262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen JobProcessDecision decision = DecideOnJob(job); 263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Should run job, decision: " 264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << decision << " Job purpose " << job.purpose << "mode " << mode_; 265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (decision != SAVE) 266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return decision == CONTINUE; 26721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(job.purpose == SyncSessionJob::NUDGE || job.purpose == 269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSessionJob::CONFIGURATION); 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SaveJob(job); 272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::SaveJob(const SyncSessionJob& job) { 276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(job.purpose != SyncSessionJob::CLEAR_USER_DATA); 277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (job.purpose == SyncSessionJob::NUDGE) { 278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Saving a nudge job"; 279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen InitOrCoalescePendingJob(job); 280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (job.purpose == SyncSessionJob::CONFIGURATION){ 281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Saving a configuration job"; 282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(wait_interval_.get()); 283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(mode_ == CONFIGURATION_MODE); 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSession* old = job.session.get(); 286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSession* s(new SyncSession(session_context_.get(), this, 287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen old->source(), old->routing_info(), old->workers())); 288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSessionJob new_job(job.purpose, TimeTicks::Now(), 289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_linked_ptr(s), false, job.nudge_location); 290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen wait_interval_->pending_configure_job.reset(new SyncSessionJob(new_job)); 291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } // drop the rest. 292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Functor for std::find_if to search by ModelSafeGroup. 295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstruct ModelSafeWorkerGroupIs { 296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen explicit ModelSafeWorkerGroupIs(ModelSafeGroup group) : group(group) {} 297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool operator()(ModelSafeWorker* w) { 298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return group == w->GetModelSafeGroup(); 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelSafeGroup group; 301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::ScheduleClearUserData() { 304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!thread_.IsRunning()) { 305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED(); 306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( 309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this, &SyncerThread::ScheduleClearUserDataImpl)); 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::ScheduleNudge(const TimeDelta& delay, 313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NudgeSource source, const ModelTypeBitSet& types, 314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const tracked_objects::Location& nudge_location) { 315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!thread_.IsRunning()) { 316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED(); 317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Nudge scheduled"; 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelTypePayloadMap types_with_payloads = 323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::ModelTypePayloadMapFromBitSet(types, std::string()); 324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( 325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this, &SyncerThread::ScheduleNudgeImpl, delay, 326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetUpdatesFromNudgeSource(source), types_with_payloads, false, 327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen nudge_location)); 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::ScheduleNudgeWithPayloads(const TimeDelta& delay, 331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NudgeSource source, const ModelTypePayloadMap& types_with_payloads, 332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const tracked_objects::Location& nudge_location) { 333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!thread_.IsRunning()) { 334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED(); 335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Nudge scheduled with payloads"; 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( 341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this, &SyncerThread::ScheduleNudgeImpl, delay, 342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetUpdatesFromNudgeSource(source), types_with_payloads, false, 343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen nudge_location)); 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::ScheduleClearUserDataImpl() { 347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); 348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSession* session = new SyncSession(session_context_.get(), this, 349ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSourceInfo(), ModelSafeRoutingInfo(), 350ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<ModelSafeWorker*>()); 351ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ScheduleSyncSessionJob(TimeDelta::FromSeconds(0), 352ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSessionJob::CLEAR_USER_DATA, session, FROM_HERE); 35321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 35421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::ScheduleNudgeImpl(const TimeDelta& delay, 356ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetUpdatesCallerInfo::GetUpdatesSource source, 357ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const ModelTypePayloadMap& types_with_payloads, 358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool is_canary_job, const tracked_objects::Location& nudge_location) { 359ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 361ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Running Schedule nudge impl"; 362ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Note we currently nudge for all types regardless of the ones incurring 363ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // the nudge. Doing different would throw off some syncer commands like 364ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // CleanupDisabledTypes. We may want to change this in the future. 365ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSourceInfo info(source, types_with_payloads); 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 367ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSession* session(CreateSyncSession(info)); 368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSessionJob job(SyncSessionJob::NUDGE, TimeTicks::Now() + delay, 369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_linked_ptr(session), is_canary_job, 370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen nudge_location); 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen session = NULL; 373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!ShouldRunJob(job)) 374ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 376ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (pending_nudge_.get()) { 377ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsBackingOff() && delay > TimeDelta::FromSeconds(1)) { 378ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Dropping the nudge because" 379ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << "we are in backoff"; 380ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 382ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 383ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Coalescing pending nudge"; 384ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_nudge_->session->Coalesce(*(job.session.get())); 385ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 386ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!IsBackingOff()) { 387ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Dropping a nudge because" 388ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " we are not in backoff and the job was coalesced"; 389ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 390ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 391ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" 392ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " Rescheduling pending nudge"; 393ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSession* s = pending_nudge_->session.get(); 394ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen job.session.reset(new SyncSession(s->context(), s->delegate(), 395ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen s->source(), s->routing_info(), s->workers())); 396ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_nudge_.reset(); 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 400ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(lipalani) - pass the job itself to ScheduleSyncSessionJob. 401ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ScheduleSyncSessionJob(delay, SyncSessionJob::NUDGE, job.session.release(), 402ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen nudge_location); 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 405ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Helper to extract the routing info and workers corresponding to types in 406ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// |types| from |registrar|. 407ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid GetModelSafeParamsForTypes(const ModelTypeBitSet& types, 408ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelSafeWorkerRegistrar* registrar, ModelSafeRoutingInfo* routes, 409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<ModelSafeWorker*>* workers) { 410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelSafeRoutingInfo r_tmp; 411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<ModelSafeWorker*> w_tmp; 412ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen registrar->GetModelSafeRoutingInfo(&r_tmp); 413ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen registrar->GetWorkers(&w_tmp); 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 415ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool passive_group_added = false; 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen typedef std::vector<ModelSafeWorker*>::const_iterator iter; 418ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = syncable::FIRST_REAL_MODEL_TYPE; i < types.size(); ++i) { 419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!types.test(i)) 420ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen continue; 421ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::ModelType t = syncable::ModelTypeFromInt(i); 422ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(1U, r_tmp.count(t)); 423ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (*routes)[t] = r_tmp[t]; 424ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen iter it = std::find_if(w_tmp.begin(), w_tmp.end(), 425ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelSafeWorkerGroupIs(r_tmp[t])); 426ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (it != w_tmp.end()) { 427ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen iter it2 = std::find_if(workers->begin(), workers->end(), 428ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelSafeWorkerGroupIs(r_tmp[t])); 429ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (it2 == workers->end()) 430ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen workers->push_back(*it); 431ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 432ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (r_tmp[t] == GROUP_PASSIVE) 433ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen passive_group_added = true; 434ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 435ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED(); 436ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 437ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 438ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 439ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Always add group passive. 440ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (passive_group_added == false) { 441ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen iter it = std::find_if(w_tmp.begin(), w_tmp.end(), 442ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelSafeWorkerGroupIs(GROUP_PASSIVE)); 443ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (it != w_tmp.end()) 444ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen workers->push_back(*it); 445ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen else 446ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED(); 447ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 448ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 449ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 450ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::ScheduleConfig(const ModelTypeBitSet& types) { 451ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!thread_.IsRunning()) { 452ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED(); 453ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 454ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 456ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Scheduling a config"; 457201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ModelSafeRoutingInfo routes; 458201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch std::vector<ModelSafeWorker*> workers; 459ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetModelSafeParamsForTypes(types, session_context_->registrar(), 460ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &routes, &workers); 461ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 462ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( 463ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this, &SyncerThread::ScheduleConfigImpl, routes, workers, 464ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetUpdatesCallerInfo::FIRST_UPDATE)); 465ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 467ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::ScheduleConfigImpl(const ModelSafeRoutingInfo& routing_info, 468ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::vector<ModelSafeWorker*>& workers, 469ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source) { 470ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); 471ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 472ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " ScheduleConfigImpl..."; 473ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(tim): config-specific GetUpdatesCallerInfo value? 474ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSession* session = new SyncSession(session_context_.get(), this, 475ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSourceInfo(source, 476ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::ModelTypePayloadMapFromRoutingInfo( 477ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen routing_info, std::string())), 478ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen routing_info, workers); 479ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ScheduleSyncSessionJob(TimeDelta::FromSeconds(0), 480ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSessionJob::CONFIGURATION, session, FROM_HERE); 481ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 482ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 483ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::ScheduleSyncSessionJob(const base::TimeDelta& delay, 484ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSessionJob::SyncSessionJobPurpose purpose, 485ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sessions::SyncSession* session, 486ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const tracked_objects::Location& nudge_location) { 487ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); 488ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 489ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSessionJob job(purpose, TimeTicks::Now() + delay, 490ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_linked_ptr(session), false, nudge_location); 491ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (purpose == SyncSessionJob::NUDGE) { 492ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Resetting pending_nudge in" 493ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " ScheduleSyncSessionJob"; 494ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!pending_nudge_.get() || pending_nudge_->session.get() == session); 495ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_nudge_.reset(new SyncSessionJob(job)); 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 497ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" 498ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " Posting job to execute in DoSyncSessionJob. Job purpose " 499ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << job.purpose; 500ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod(this, 501ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &SyncerThread::DoSyncSessionJob, job), 502ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delay.InMilliseconds()); 503ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 504ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 505ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::SetSyncerStepsForPurpose( 506ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSessionJob::SyncSessionJobPurpose purpose, 507ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncerStep* start, SyncerStep* end) { 508ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *end = SYNCER_END; 509ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen switch (purpose) { 510ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SyncSessionJob::CONFIGURATION: 511ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *start = DOWNLOAD_UPDATES; 512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *end = APPLY_UPDATES; 513ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 514ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SyncSessionJob::CLEAR_USER_DATA: 515ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *start = CLEAR_PRIVATE_DATA; 516ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 517ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SyncSessionJob::NUDGE: 518ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SyncSessionJob::POLL: 519ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *start = SYNCER_BEGIN; 520ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 521ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen default: 522ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED(); 523ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 524ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 525201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 526ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::DoSyncSessionJob(const SyncSessionJob& job) { 527ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); 528ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!ShouldRunJob(job)) { 529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(WARNING) << "Dropping nudge at DoSyncSessionJob, source = " 530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << job.session->source().updates_source; 531ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 53372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 534ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (job.purpose == SyncSessionJob::NUDGE) { 535ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (pending_nudge_.get() == NULL || pending_nudge_->session != job.session) 536ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; // Another nudge must have been scheduled in in the meantime. 537ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_nudge_.reset(); 538ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 539ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " DoSyncSessionJob. job purpose " 540ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << job.purpose; 541ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 542ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncerStep begin(SYNCER_BEGIN); 543ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncerStep end(SYNCER_END); 544ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetSyncerStepsForPurpose(job.purpose, &begin, &end); 545ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 546ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool has_more_to_sync = true; 547ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen while (ShouldRunJob(job) && has_more_to_sync) { 548ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" 549ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " SyncerThread: Calling SyncShare."; 550ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Synchronously perform the sync session from this thread. 551ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncer_->SyncShare(job.session.get(), begin, end); 552ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen has_more_to_sync = job.session->HasMoreToSync(); 553ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (has_more_to_sync) 554ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen job.session->ResetTransientState(); 555ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 556ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" 557ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " SyncerThread: Done SyncShare looping."; 558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FinishSyncSessionJob(job); 559ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 560ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 561ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::UpdateCarryoverSessionState(const SyncSessionJob& old_job) { 562ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (old_job.purpose == SyncSessionJob::CONFIGURATION) { 563ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Whatever types were part of a configuration task will have had updates 564ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // downloaded. For that reason, we make sure they get recorded in the 565ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // event that they get disabled at a later time. 566ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelSafeRoutingInfo r(session_context_->previous_session_routing_info()); 567ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!r.empty()) { 568ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelSafeRoutingInfo temp_r; 569ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelSafeRoutingInfo old_info(old_job.session->routing_info()); 570ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::set_union(r.begin(), r.end(), old_info.begin(), old_info.end(), 571ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::insert_iterator<ModelSafeRoutingInfo>(temp_r, temp_r.begin())); 572ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen session_context_->set_previous_session_routing_info(temp_r); 573ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 57472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 575ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen session_context_->set_previous_session_routing_info( 576ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen old_job.session->routing_info()); 57772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 578ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 57972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 580ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::FinishSyncSessionJob(const SyncSessionJob& job) { 581ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); 582ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Update timing information for how often datatypes are triggering nudges. 583ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::TimeTicks now = TimeTicks::Now(); 584ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!last_sync_session_end_time_.is_null()) { 585ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelTypePayloadMap::const_iterator iter; 586ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (iter = job.session->source().types.begin(); 587ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen iter != job.session->source().types.end(); 588ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ++iter) { 589ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::PostTimeToTypeHistogram(iter->first, 590ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen now - last_sync_session_end_time_); 591201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 592ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 593ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen last_sync_session_end_time_ = now; 594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UpdateCarryoverSessionState(job); 595ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsSyncingCurrentlySilenced()) { 596ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" 597ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " We are currently throttled. So not scheduling the next sync."; 598ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SaveJob(job); 599ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; // Nothing to do. 600ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 601ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 602ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" 603ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " Updating the next polling time after SyncMain"; 604ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ScheduleNextSync(job); 605ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 606ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 607ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::ScheduleNextSync(const SyncSessionJob& old_job) { 608ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); 609ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!old_job.session->HasMoreToSync()); 610ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Note: |num_server_changes_remaining| > 0 here implies that we received a 611ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // broken response while trying to download all updates, because the Syncer 612ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // will loop until this value is exhausted. Also, if unsynced_handles exist 613ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // but HasMoreToSync is false, this implies that the Syncer determined no 614ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // forward progress was possible at this time (an error, such as an HTTP 615ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // 500, is likely to have occurred during commit). 616ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const bool work_to_do = 617ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen old_job.session->status_controller()->num_server_changes_remaining() > 0 618ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen || old_job.session->status_controller()->unsynced_handles().size() > 0; 619ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " syncer has work to do: " 620ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << work_to_do; 621ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 622ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen AdjustPolling(&old_job); 623ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 624ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(tim): Old impl had special code if notifications disabled. Needed? 625ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!work_to_do) { 626ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Success implies backoff relief. Note that if this was a "one-off" job 627ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // (i.e. purpose == SyncSessionJob::CLEAR_USER_DATA), if there was 628ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // work_to_do before it ran this wont have changed, as jobs like this don't 629ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // run a full sync cycle. So we don't need special code here. 630ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen wait_interval_.reset(); 631ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" 632ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " Job suceeded so not scheduling more jobs"; 633ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 634ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 635ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 636ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (old_job.session->source().updates_source == 637ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION) { 638ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" 639ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " Job failed with source continuation"; 640ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We don't seem to have made forward progress. Start or extend backoff. 641ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen HandleConsecutiveContinuationError(old_job); 642ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (IsBackingOff()) { 643ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" 644ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " A nudge during backoff failed"; 645ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We weren't continuing but we're in backoff; must have been a nudge. 646ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(SyncSessionJob::NUDGE, old_job.purpose); 647ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!wait_interval_->had_nudge); 648ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen wait_interval_->had_nudge = true; 649ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen wait_interval_->timer.Reset(); 650201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } else { 651ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" 652ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " Failed. Schedule a job with continuation as source"; 653ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We weren't continuing and we aren't in backoff. Schedule a normal 654ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // continuation. 655ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (old_job.purpose == SyncSessionJob::CONFIGURATION) { 656ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ScheduleConfigImpl(old_job.session->routing_info(), 657ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen old_job.session->workers(), 658ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetUpdatesFromNudgeSource(NUDGE_SOURCE_CONTINUATION)); 659ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 660ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // For all other purposes(nudge and poll) we schedule a retry nudge. 661ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ScheduleNudgeImpl(TimeDelta::FromSeconds(0), 662ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetUpdatesFromNudgeSource(NUDGE_SOURCE_CONTINUATION), 663ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen old_job.session->source().types, false, FROM_HERE); 664201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 665201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 666201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 667201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 668ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::AdjustPolling(const SyncSessionJob* old_job) { 669ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(thread_.IsRunning()); 670ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); 671ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 672ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimeDelta poll = (!session_context_->notifications_enabled()) ? 673ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncer_short_poll_interval_seconds_ : 674ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncer_long_poll_interval_seconds_; 675ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool rate_changed = !poll_timer_.IsRunning() || 676ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen poll != poll_timer_.GetCurrentDelay(); 677ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 678ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (old_job && old_job->purpose != SyncSessionJob::POLL && !rate_changed) 679ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen poll_timer_.Reset(); 680ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 681ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!rate_changed) 682ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 683ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 684ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Adjust poll rate. 685ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen poll_timer_.Stop(); 686ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen poll_timer_.Start(poll, this, &SyncerThread::PollTimerCallback); 687201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 688201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 689ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::HandleConsecutiveContinuationError( 690ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const SyncSessionJob& old_job) { 691ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); 692ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // This if conditions should be compiled out in retail builds. 693ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsBackingOff()) { 694ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(wait_interval_->timer.IsRunning() || old_job.is_canary_job); 695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 696ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSession* old = old_job.session.get(); 697ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSession* s(new SyncSession(session_context_.get(), this, 698ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen old->source(), old->routing_info(), old->workers())); 699ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimeDelta length = delay_provider_->GetDelay( 700ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IsBackingOff() ? wait_interval_->length : TimeDelta::FromSeconds(1)); 701ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 702ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" 703ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " In handle continuation error. Old job purpose is " 704ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << old_job.purpose; 705ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" 706ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " In Handle continuation error. The time delta(ms) is: " 707ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << length.InMilliseconds(); 708ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 709ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // This will reset the had_nudge variable as well. 710ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen wait_interval_.reset(new WaitInterval(WaitInterval::EXPONENTIAL_BACKOFF, 711ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen length)); 712ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (old_job.purpose == SyncSessionJob::CONFIGURATION) { 713ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSessionJob job(old_job.purpose, TimeTicks::Now() + length, 714ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_linked_ptr(s), false, FROM_HERE); 715ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen wait_interval_->pending_configure_job.reset(new SyncSessionJob(job)); 716ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 717ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We are not in configuration mode. So wait_interval's pending job 718ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // should be null. 719ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(wait_interval_->pending_configure_job.get() == NULL); 720ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 721ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(lipalani) - handle clear user data. 722ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen InitOrCoalescePendingJob(old_job); 723ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 724ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen wait_interval_->timer.Start(length, this, &SyncerThread::DoCanaryJob); 725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 727ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static 728ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTimeDelta SyncerThread::GetRecommendedDelay(const TimeDelta& last_delay) { 729ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (last_delay.InSeconds() >= kMaxBackoffSeconds) 730ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return TimeDelta::FromSeconds(kMaxBackoffSeconds); 7313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 7323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // This calculates approx. base_delay_seconds * 2 +/- base_delay_seconds / 2 733ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 backoff_s = 734ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::max(static_cast<int64>(1), 735ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen last_delay.InSeconds() * kBackoffRandomizationFactor); 7363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 7373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Flip a coin to randomize backoff interval by +/- 50%. 7383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int rand_sign = base::RandInt(0, 1) * 2 - 1; 7393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 7403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Truncation is adequate for rounding here. 7413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick backoff_s = backoff_s + 742ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (rand_sign * (last_delay.InSeconds() / kBackoffRandomizationFactor)); 7433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 7443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Cap the backoff interval. 745ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen backoff_s = std::max(static_cast<int64>(1), 746ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::min(backoff_s, kMaxBackoffSeconds)); 7473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 748ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return TimeDelta::FromSeconds(backoff_s); 7493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 7503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 751ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::Stop() { 752ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " stop called"; 753ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncer_->RequestEarlyExit(); // Safe to call from any thread. 754ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen session_context_->connection_manager()->RemoveListener(this); 755ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thread_.Stop(); 756ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 758ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::DoCanaryJob() { 759ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Do canary job"; 760ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DoPendingJobIfPossible(true); 761ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 762ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 763ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::DoPendingJobIfPossible(bool is_canary_job) { 764ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSessionJob* job_to_execute = NULL; 765ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (mode_ == CONFIGURATION_MODE && wait_interval_.get() 766ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen && wait_interval_->pending_configure_job.get()) { 767ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Found pending configure job"; 768ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen job_to_execute = wait_interval_->pending_configure_job.get(); 769ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (mode_ == NORMAL_MODE && pending_nudge_.get()) { 770ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Found pending nudge job"; 771ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Pending jobs mostly have time from the past. Reset it so this job 772ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // will get executed. 773ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (pending_nudge_->scheduled_start < TimeTicks::Now()) 774ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_nudge_->scheduled_start = TimeTicks::Now(); 775ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 776ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<SyncSession> session(CreateSyncSession( 777ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_nudge_->session->source())); 778ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 779ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Also the routing info might have been changed since we cached the 780ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // pending nudge. Update it by coalescing to the latest. 781ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pending_nudge_->session->Coalesce(*(session.get())); 782ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The pending nudge would be cleared in the DoSyncSessionJob function. 783ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen job_to_execute = pending_nudge_.get(); 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 786ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (job_to_execute != NULL) { 787ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Executing pending job"; 788ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSessionJob copy = *job_to_execute; 789ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen copy.is_canary_job = is_canary_job; 790ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DoSyncSessionJob(copy); 791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 792ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 794ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSyncSession* SyncerThread::CreateSyncSession(const SyncSourceInfo& source) { 795ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelSafeRoutingInfo routes; 796ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<ModelSafeWorker*> workers; 797ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen session_context_->registrar()->GetModelSafeRoutingInfo(&routes); 798ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen session_context_->registrar()->GetWorkers(&workers); 799ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSourceInfo info(source); 8003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 801ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSession* session(new SyncSession(session_context_.get(), this, info, 802ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen routes, workers)); 803201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 804ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return session; 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 807ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::PollTimerCallback() { 808ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); 809ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelSafeRoutingInfo r; 810ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelTypePayloadMap types_with_payloads = 811ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::ModelTypePayloadMapFromRoutingInfo(r, std::string()); 812ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSourceInfo info(GetUpdatesCallerInfo::PERIODIC, types_with_payloads); 813ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncSession* s = CreateSyncSession(info); 814ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ScheduleSyncSessionJob(TimeDelta::FromSeconds(0), SyncSessionJob::POLL, s, 815ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FROM_HERE); 816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 818ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::Unthrottle() { 819ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(WaitInterval::THROTTLED, wait_interval_->mode); 820ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" << " Unthrottled.."; 821ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DoCanaryJob(); 822ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen wait_interval_.reset(); 823ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 825ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::Notify(SyncEngineEvent::EventCause cause) { 826ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); 827ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen session_context_->NotifyListeners(SyncEngineEvent(cause)); 828ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 830ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool SyncerThread::IsBackingOff() const { 831ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return wait_interval_.get() && wait_interval_->mode == 832ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WaitInterval::EXPONENTIAL_BACKOFF; 833ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 835ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::OnSilencedUntil(const base::TimeTicks& silenced_until) { 836ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen wait_interval_.reset(new WaitInterval(WaitInterval::THROTTLED, 837ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen silenced_until - TimeTicks::Now())); 838ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen wait_interval_->timer.Start(wait_interval_->length, this, 839ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &SyncerThread::Unthrottle); 840ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 842ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool SyncerThread::IsSyncingCurrentlySilenced() { 843ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return wait_interval_.get() && wait_interval_->mode == 844ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WaitInterval::THROTTLED; 845ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 847ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::OnReceivedShortPollIntervalUpdate( 848ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const base::TimeDelta& new_interval) { 849ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); 850ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncer_short_poll_interval_seconds_ = new_interval; 851ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 852ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 853ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::OnReceivedLongPollIntervalUpdate( 854ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const base::TimeDelta& new_interval) { 855ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); 856ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncer_long_poll_interval_seconds_ = new_interval; 857ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 858ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 859ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::OnShouldStopSyncingPermanently() { 860ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "SyncerThread(" << this << ")" 861ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << " OnShouldStopSyncingPermanently"; 862ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncer_->RequestEarlyExit(); // Thread-safe. 863ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Notify(SyncEngineEvent::STOP_SYNCING_PERMANENTLY); 864ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 865ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 866ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::OnServerConnectionEvent( 867ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const ServerConnectionEvent2& event) { 868ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, 869ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &SyncerThread::CheckServerConnectionManagerStatus, 870ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen event.connection_code)); 871ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 872ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 873ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncerThread::set_notifications_enabled(bool notifications_enabled) { 874ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen session_context_->set_notifications_enabled(notifications_enabled); 875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 877ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // browser_sync 878