Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1024)

Side by Side Diff: chrome/browser/sync/engine/syncer_thread2.cc

Issue 6286067: sync: add a SyncSessionJobPurpose for clearing sync user data. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/chrome
Patch Set: Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/syncer_thread2.h" 5 #include "chrome/browser/sync/engine/syncer_thread2.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/rand_util.h" 9 #include "base/rand_util.h"
10 #include "chrome/browser/sync/engine/syncer.h" 10 #include "chrome/browser/sync/engine/syncer.h"
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 mode_ = mode; 95 mode_ = mode;
96 AdjustPolling(NULL); // Will kick start poll timer if needed. 96 AdjustPolling(NULL); // Will kick start poll timer if needed.
97 } 97 }
98 98
99 bool SyncerThread::ShouldRunJob(SyncSessionJobPurpose purpose, 99 bool SyncerThread::ShouldRunJob(SyncSessionJobPurpose purpose,
100 const TimeTicks& scheduled_start) { 100 const TimeTicks& scheduled_start) {
101 DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); 101 DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
102 102
103 // Check wait interval. 103 // Check wait interval.
104 if (wait_interval_.get()) { 104 if (wait_interval_.get()) {
105 // TODO(tim): Consider different handling for CLEAR_USER_DATA (i.e. permit
106 // when throttled).
105 if (wait_interval_->mode == WaitInterval::THROTTLED) 107 if (wait_interval_->mode == WaitInterval::THROTTLED)
106 return false; 108 return false;
107 109
108 DCHECK_EQ(wait_interval_->mode, WaitInterval::EXPONENTIAL_BACKOFF); 110 DCHECK_EQ(wait_interval_->mode, WaitInterval::EXPONENTIAL_BACKOFF);
109 DCHECK(purpose == POLL || 111 DCHECK(purpose == POLL ||
110 purpose == NUDGE); 112 purpose == NUDGE);
111 if ((purpose != NUDGE) || wait_interval_->had_nudge) 113 if ((purpose != NUDGE) || wait_interval_->had_nudge)
112 return false; 114 return false;
113 } 115 }
114 116
115 // Mode / purpose contract (See 'Mode' enum in header). Don't run jobs that 117 // Mode / purpose contract (See 'Mode' enum in header). Don't run jobs that
116 // were intended for a normal sync if we are in configuration mode, and vice 118 // were intended for a normal sync if we are in configuration mode, and vice
117 // versa. 119 // versa.
118 switch (mode_) { 120 switch (mode_) {
119 case CONFIGURATION_MODE: 121 case CONFIGURATION_MODE:
120 if (purpose != CONFIGURATION) 122 if (purpose != CONFIGURATION)
121 return false; 123 return false;
122 break; 124 break;
123 case NORMAL_MODE: 125 case NORMAL_MODE:
124 if (purpose != POLL && purpose != NUDGE) 126 if (purpose != POLL && purpose != NUDGE && purpose != CLEAR_USER_DATA)
Nicolas Zea 2011/02/03 00:39:07 if (purpose == CONFIGURATION)?
tim (not reviewing) 2011/02/03 00:56:15 Done.
125 return false; 127 return false;
126 break; 128 break;
127 default: 129 default:
128 NOTREACHED() << "Unknown SyncerThread Mode: " << mode_; 130 NOTREACHED() << "Unknown SyncerThread Mode: " << mode_;
129 return false; 131 return false;
130 } 132 }
131 133
132 // Continuation NUDGE tasks have priority over POLLs because they are the 134 // Continuation NUDGE tasks have priority over POLLs because they are the
133 // only tasks that trigger exponential backoff, so this prevents them from 135 // only tasks that trigger exponential backoff, so this prevents them from
134 // being starved from running (e.g. due to a very, very low poll interval, 136 // being starved from running (e.g. due to a very, very low poll interval,
(...skipping 16 matching lines...) Expand all
151 namespace { 153 namespace {
152 GetUpdatesCallerInfo::GetUpdatesSource GetUpdatesFromNudgeSource( 154 GetUpdatesCallerInfo::GetUpdatesSource GetUpdatesFromNudgeSource(
153 NudgeSource source) { 155 NudgeSource source) {
154 switch (source) { 156 switch (source) {
155 case NUDGE_SOURCE_NOTIFICATION: 157 case NUDGE_SOURCE_NOTIFICATION:
156 return GetUpdatesCallerInfo::NOTIFICATION; 158 return GetUpdatesCallerInfo::NOTIFICATION;
157 case NUDGE_SOURCE_LOCAL: 159 case NUDGE_SOURCE_LOCAL:
158 return GetUpdatesCallerInfo::LOCAL; 160 return GetUpdatesCallerInfo::LOCAL;
159 case NUDGE_SOURCE_CONTINUATION: 161 case NUDGE_SOURCE_CONTINUATION:
160 return GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION; 162 return GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION;
161 case NUDGE_SOURCE_CLEAR_PRIVATE_DATA:
162 return GetUpdatesCallerInfo::CLEAR_PRIVATE_DATA;
163 case NUDGE_SOURCE_UNKNOWN: 163 case NUDGE_SOURCE_UNKNOWN:
164 default: 164 default:
165 NOTREACHED();
165 return GetUpdatesCallerInfo::UNKNOWN; 166 return GetUpdatesCallerInfo::UNKNOWN;
166 } 167 }
167 } 168 }
168 169
169 // Functor for std::find_if to search by ModelSafeGroup. 170 // Functor for std::find_if to search by ModelSafeGroup.
170 struct WorkerGroupIs { 171 struct WorkerGroupIs {
171 explicit WorkerGroupIs(ModelSafeGroup group) : group(group) {} 172 explicit WorkerGroupIs(ModelSafeGroup group) : group(group) {}
172 bool operator()(ModelSafeWorker* w) { 173 bool operator()(ModelSafeWorker* w) {
173 return group == w->GetModelSafeGroup(); 174 return group == w->GetModelSafeGroup();
174 } 175 }
175 ModelSafeGroup group; 176 ModelSafeGroup group;
176 }; 177 };
177 } // namespace 178 } // namespace
178 179
180 void SyncerThread::ScheduleClearUserData() {
181 if (!thread_.IsRunning()) {
182 NOTREACHED();
183 return;
184 }
185 thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
186 this, &SyncerThread::ScheduleClearUserDataImpl));
187 }
188
179 void SyncerThread::ScheduleNudge(const TimeDelta& delay, 189 void SyncerThread::ScheduleNudge(const TimeDelta& delay,
180 NudgeSource source, const ModelTypeBitSet& types) { 190 NudgeSource source, const ModelTypeBitSet& types) {
181 if (!thread_.IsRunning()) { 191 if (!thread_.IsRunning()) {
182 NOTREACHED(); 192 NOTREACHED();
183 return; 193 return;
184 } 194 }
185 195
186 TypePayloadMap types_with_payloads = 196 TypePayloadMap types_with_payloads =
187 sessions::MakeTypePayloadMapFromBitSet(types, std::string()); 197 sessions::MakeTypePayloadMapFromBitSet(types, std::string());
188 thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( 198 thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
189 this, &SyncerThread::ScheduleNudgeImpl, delay, source, 199 this, &SyncerThread::ScheduleNudgeImpl, delay, source,
190 types_with_payloads)); 200 types_with_payloads));
191 } 201 }
192 202
193 void SyncerThread::ScheduleNudgeWithPayloads(const TimeDelta& delay, 203 void SyncerThread::ScheduleNudgeWithPayloads(const TimeDelta& delay,
194 NudgeSource source, const TypePayloadMap& types_with_payloads) { 204 NudgeSource source, const TypePayloadMap& types_with_payloads) {
195 if (!thread_.IsRunning()) { 205 if (!thread_.IsRunning()) {
196 NOTREACHED(); 206 NOTREACHED();
197 return; 207 return;
198 } 208 }
199 209
200 thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( 210 thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
201 this, &SyncerThread::ScheduleNudgeImpl, delay, source, 211 this, &SyncerThread::ScheduleNudgeImpl, delay, source,
202 types_with_payloads)); 212 types_with_payloads));
203 } 213 }
204 214
215 void SyncerThread::ScheduleClearUserDataImpl() {
216 DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
217 SyncSession* session = new SyncSession(session_context_.get(), this,
218 SyncSourceInfo(), ModelSafeRoutingInfo(),
219 std::vector<ModelSafeWorker*>());
220 ScheduleSyncSessionJob(TimeDelta::FromSeconds(0), CLEAR_USER_DATA, session);
221 }
222
205 void SyncerThread::ScheduleNudgeImpl(const TimeDelta& delay, 223 void SyncerThread::ScheduleNudgeImpl(const TimeDelta& delay,
206 NudgeSource source, const TypePayloadMap& types_with_payloads) { 224 NudgeSource source, const TypePayloadMap& types_with_payloads) {
207 DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); 225 DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
208 TimeTicks rough_start = TimeTicks::Now() + delay; 226 TimeTicks rough_start = TimeTicks::Now() + delay;
209 if (!ShouldRunJob(NUDGE, rough_start))
210 return;
211 227
212 // Note we currently nudge for all types regardless of the ones incurring 228 // Note we currently nudge for all types regardless of the ones incurring
213 // the nudge. Doing different would throw off some syncer commands like 229 // the nudge. Doing different would throw off some syncer commands like
214 // CleanupDisabledTypes. We may want to change this in the future. 230 // CleanupDisabledTypes. We may want to change this in the future.
215 ModelSafeRoutingInfo routes; 231 ModelSafeRoutingInfo routes;
216 std::vector<ModelSafeWorker*> workers; 232 std::vector<ModelSafeWorker*> workers;
217 session_context_->registrar()->GetModelSafeRoutingInfo(&routes); 233 session_context_->registrar()->GetModelSafeRoutingInfo(&routes);
218 session_context_->registrar()->GetWorkers(&workers); 234 session_context_->registrar()->GetWorkers(&workers);
219 SyncSourceInfo info(GetUpdatesFromNudgeSource(source), 235 SyncSourceInfo info(GetUpdatesFromNudgeSource(source),
220 types_with_payloads); 236 types_with_payloads);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 SyncSessionJob job = {purpose, TimeTicks::Now() + delay, 317 SyncSessionJob job = {purpose, TimeTicks::Now() + delay,
302 make_linked_ptr(session)}; 318 make_linked_ptr(session)};
303 if (purpose == NUDGE) { 319 if (purpose == NUDGE) {
304 DCHECK(!pending_nudge_.get() || pending_nudge_->session.get() == session); 320 DCHECK(!pending_nudge_.get() || pending_nudge_->session.get() == session);
305 pending_nudge_.reset(new SyncSessionJob(job)); 321 pending_nudge_.reset(new SyncSessionJob(job));
306 } 322 }
307 MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod(this, 323 MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod(this,
308 &SyncerThread::DoSyncSessionJob, job), delay.InMilliseconds()); 324 &SyncerThread::DoSyncSessionJob, job), delay.InMilliseconds());
309 } 325 }
310 326
327 void SyncerThread::SetSyncerStepsForPurpose(SyncSessionJobPurpose purpose,
328 SyncerStep* start, SyncerStep* end) {
329 *start = SYNCER_BEGIN;
330 *end = SYNCER_END;
331 switch (purpose) {
332 case CONFIGURATION:
333 *start = DOWNLOAD_UPDATES;
334 *end = APPLY_UPDATES;
335 return;
336 case CLEAR_USER_DATA:
337 *start = CLEAR_PRIVATE_DATA;
338 return;
339 }
340 }
341
311 void SyncerThread::DoSyncSessionJob(const SyncSessionJob& job) { 342 void SyncerThread::DoSyncSessionJob(const SyncSessionJob& job) {
312 DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); 343 DCHECK_EQ(MessageLoop::current(), thread_.message_loop());
313 344
314 if (job.purpose == NUDGE) { 345 if (job.purpose == NUDGE) {
315 DCHECK(pending_nudge_.get()); 346 DCHECK(pending_nudge_.get());
316 if (pending_nudge_->session != job.session) 347 if (pending_nudge_->session != job.session)
317 return; // Another nudge must have been scheduled in in the meantime. 348 return; // Another nudge must have been scheduled in in the meantime.
318 pending_nudge_.reset(); 349 pending_nudge_.reset();
319 } else if (job.purpose == CONFIGURATION) {
320 NOTIMPLEMENTED() << "TODO(tim): SyncShare [DOWNLOAD_UPDATES,APPLY_UPDATES]";
321 } 350 }
322 351
352 SyncerStep begin(SYNCER_BEGIN);
353 SyncerStep end(SYNCER_END);
354 SetSyncerStepsForPurpose(job.purpose, &begin, &end);
355
323 bool has_more_to_sync = true; 356 bool has_more_to_sync = true;
324 bool did_job = false; 357 bool did_job = false;
325 while (ShouldRunJob(job.purpose, job.scheduled_start) && has_more_to_sync) { 358 while (ShouldRunJob(job.purpose, job.scheduled_start) && has_more_to_sync) {
326 VLOG(1) << "SyncerThread: Calling SyncShare."; 359 VLOG(1) << "SyncerThread: Calling SyncShare.";
327 did_job = true; 360 did_job = true;
328 // Synchronously perform the sync session from this thread. 361 // Synchronously perform the sync session from this thread.
329 syncer_->SyncShare(job.session.get()); 362 syncer_->SyncShare(job.session.get(), begin, end);
330 has_more_to_sync = job.session->HasMoreToSync(); 363 has_more_to_sync = job.session->HasMoreToSync();
331 if (has_more_to_sync) 364 if (has_more_to_sync)
332 job.session->ResetTransientState(); 365 job.session->ResetTransientState();
333 } 366 }
334 VLOG(1) << "SyncerThread: Done SyncShare looping."; 367 VLOG(1) << "SyncerThread: Done SyncShare looping.";
335 if (did_job) 368 if (did_job)
336 FinishSyncSessionJob(job); 369 FinishSyncSessionJob(job);
337 } 370 }
338 371
339 void SyncerThread::FinishSyncSessionJob(const SyncSessionJob& job) { 372 void SyncerThread::FinishSyncSessionJob(const SyncSessionJob& job) {
(...skipping 28 matching lines...) Expand all
368 // 500, is likely to have occurred during commit). 401 // 500, is likely to have occurred during commit).
369 const bool work_to_do = 402 const bool work_to_do =
370 old_job.session->status_controller()->num_server_changes_remaining() > 0 403 old_job.session->status_controller()->num_server_changes_remaining() > 0
371 || old_job.session->status_controller()->unsynced_handles().size() > 0; 404 || old_job.session->status_controller()->unsynced_handles().size() > 0;
372 VLOG(1) << "syncer has work to do: " << work_to_do; 405 VLOG(1) << "syncer has work to do: " << work_to_do;
373 406
374 AdjustPolling(&old_job); 407 AdjustPolling(&old_job);
375 408
376 // TODO(tim): Old impl had special code if notifications disabled. Needed? 409 // TODO(tim): Old impl had special code if notifications disabled. Needed?
377 if (!work_to_do) { 410 if (!work_to_do) {
378 wait_interval_.reset(); // Success implies backoff relief. 411 // Success implies backoff relief. Note that if this was a "one-off" job
412 // (i.e. purpose == CLEAR_USER_DATA), if there was work_to_do before it
413 // ran this wont have changed, as jobs like this don't run a full sync
414 // cycle. So we don't need special code here.
415 wait_interval_.reset();
379 return; 416 return;
380 } 417 }
381 418
382 if (old_job.session->source().updates_source == 419 if (old_job.session->source().updates_source ==
383 GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION) { 420 GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION) {
384 // We don't seem to have made forward progress. Start or extend backoff. 421 // We don't seem to have made forward progress. Start or extend backoff.
385 HandleConsecutiveContinuationError(old_job); 422 HandleConsecutiveContinuationError(old_job);
386 } else if (IsBackingOff()) { 423 } else if (IsBackingOff()) {
387 // We weren't continuing but we're in backoff; must have been a nudge. 424 // We weren't continuing but we're in backoff; must have been a nudge.
388 DCHECK_EQ(NUDGE, old_job.purpose); 425 DCHECK_EQ(NUDGE, old_job.purpose);
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 const ServerConnectionEvent& event) { 572 const ServerConnectionEvent& event) {
536 NOTIMPLEMENTED(); 573 NOTIMPLEMENTED();
537 } 574 }
538 575
539 void SyncerThread::set_notifications_enabled(bool notifications_enabled) { 576 void SyncerThread::set_notifications_enabled(bool notifications_enabled) {
540 session_context_->set_notifications_enabled(notifications_enabled); 577 session_context_->set_notifications_enabled(notifications_enabled);
541 } 578 }
542 579
543 } // s3 580 } // s3
544 } // browser_sync 581 } // browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698