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

Side by Side Diff: sync/engine/get_commit_ids_command.cc

Issue 10210009: sync: Loop committing items without downloading updates (v2) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase, remove class, modify loop exit Created 8 years, 7 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "sync/engine/get_commit_ids_command.h" 5 #include "sync/engine/get_commit_ids_command.h"
6 6
7 #include <set> 7 #include <set>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
11 #include "sync/engine/nigori_util.h" 11 #include "sync/engine/nigori_util.h"
12 #include "sync/engine/syncer_util.h" 12 #include "sync/engine/syncer_util.h"
13 #include "sync/syncable/syncable.h" 13 #include "sync/syncable/syncable.h"
14 #include "sync/util/cryptographer.h" 14 #include "sync/util/cryptographer.h"
15 15
16 using std::set; 16 using std::set;
17 using std::vector; 17 using std::vector;
18 18
19 namespace browser_sync { 19 namespace browser_sync {
20 20
21 using sessions::OrderedCommitSet; 21 using sessions::OrderedCommitSet;
22 using sessions::SyncSession; 22 using sessions::SyncSession;
23 using sessions::StatusController; 23 using sessions::StatusController;
24 24
25 GetCommitIdsCommand::GetCommitIdsCommand(int commit_batch_size) 25 GetCommitIdsCommand::GetCommitIdsCommand(
26 : requested_commit_batch_size_(commit_batch_size) {} 26 size_t commit_batch_size,
27 sessions::OrderedCommitSet* commit_set,
28 size_t* unsynced_item_count)
29 : requested_commit_batch_size_(commit_batch_size),
tim (not reviewing) 2012/05/11 18:42:16 indent of : is off.
rlarocque 2012/05/14 23:10:43 Done.
30 commit_set_(commit_set),
31 unsynced_item_count_(unsynced_item_count) {
32 }
27 33
28 GetCommitIdsCommand::~GetCommitIdsCommand() {} 34 GetCommitIdsCommand::~GetCommitIdsCommand() {}
29 35
30 SyncerError GetCommitIdsCommand::ExecuteImpl(SyncSession* session) { 36 SyncerError GetCommitIdsCommand::ExecuteImpl(SyncSession* session) {
31 // Gather the full set of unsynced items and store it in the session. They 37 // Gather the full set of unsynced items and store it in the session. They
32 // are not in the correct order for commit. 38 // are not in the correct order for commit.
33 std::set<int64> ready_unsynced_set; 39 std::set<int64> ready_unsynced_set;
34 syncable::Directory::UnsyncedMetaHandles all_unsynced_handles; 40 syncable::Directory::UnsyncedMetaHandles all_unsynced_handles;
35 SyncerUtil::GetUnsyncedEntries(session->write_transaction(), 41 SyncerUtil::GetUnsyncedEntries(session->write_transaction(),
36 &all_unsynced_handles); 42 &all_unsynced_handles);
(...skipping 13 matching lines...) Expand all
50 // We filter out all unready entries from the set of unsynced handles. This 56 // We filter out all unready entries from the set of unsynced handles. This
51 // new set of ready and unsynced items (which excludes throttled items as 57 // new set of ready and unsynced items (which excludes throttled items as
52 // well) is then what we use to determine what is a candidate for commit. 58 // well) is then what we use to determine what is a candidate for commit.
53 FilterUnreadyEntries(session->write_transaction(), 59 FilterUnreadyEntries(session->write_transaction(),
54 throttled_types, 60 throttled_types,
55 encrypted_types, 61 encrypted_types,
56 passphrase_missing, 62 passphrase_missing,
57 all_unsynced_handles, 63 all_unsynced_handles,
58 &ready_unsynced_set); 64 &ready_unsynced_set);
59 65
66 *unsynced_item_count_ = ready_unsynced_set.size();
67
60 BuildCommitIds(session->write_transaction(), 68 BuildCommitIds(session->write_transaction(),
61 session->routing_info(), 69 session->routing_info(),
62 ready_unsynced_set); 70 ready_unsynced_set);
63 71
64 StatusController* status = session->mutable_status_controller();
65 syncable::Directory::UnsyncedMetaHandles ready_unsynced_vector(
66 ready_unsynced_set.begin(), ready_unsynced_set.end());
67 status->set_unsynced_handles(ready_unsynced_vector);
68 const vector<syncable::Id>& verified_commit_ids = 72 const vector<syncable::Id>& verified_commit_ids =
69 ordered_commit_set_->GetAllCommitIds(); 73 commit_set_->GetAllCommitIds();
70 74
71 for (size_t i = 0; i < verified_commit_ids.size(); i++) 75 for (size_t i = 0; i < verified_commit_ids.size(); i++)
72 DVLOG(1) << "Debug commit batch result:" << verified_commit_ids[i]; 76 DVLOG(1) << "Debug commit batch result:" << verified_commit_ids[i];
73 77
74 status->set_commit_set(*ordered_commit_set_.get());
75 return SYNCER_OK; 78 return SYNCER_OK;
76 } 79 }
77 80
78 namespace { 81 namespace {
79 82
80 bool IsEntryInConflict(const syncable::Entry& entry) { 83 bool IsEntryInConflict(const syncable::Entry& entry) {
81 if (entry.Get(syncable::IS_UNSYNCED) && 84 if (entry.Get(syncable::IS_UNSYNCED) &&
82 entry.Get(syncable::SERVER_VERSION) > 0 && 85 entry.Get(syncable::SERVER_VERSION) > 0 &&
83 (entry.Get(syncable::SERVER_VERSION) > 86 (entry.Get(syncable::SERVER_VERSION) >
84 entry.Get(syncable::BASE_VERSION))) { 87 entry.Get(syncable::BASE_VERSION))) {
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 const syncable::Entry& item, 184 const syncable::Entry& item,
182 sessions::OrderedCommitSet* result) const { 185 sessions::OrderedCommitSet* result) const {
183 OrderedCommitSet item_dependencies(routes); 186 OrderedCommitSet item_dependencies(routes);
184 syncable::Id parent_id = item.Get(syncable::PARENT_ID); 187 syncable::Id parent_id = item.Get(syncable::PARENT_ID);
185 188
186 // Climb the tree adding entries leaf -> root. 189 // Climb the tree adding entries leaf -> root.
187 while (!parent_id.ServerKnows()) { 190 while (!parent_id.ServerKnows()) {
188 syncable::Entry parent(trans, syncable::GET_BY_ID, parent_id); 191 syncable::Entry parent(trans, syncable::GET_BY_ID, parent_id);
189 CHECK(parent.good()) << "Bad user-only parent in item path."; 192 CHECK(parent.good()) << "Bad user-only parent in item path.";
190 int64 handle = parent.Get(syncable::META_HANDLE); 193 int64 handle = parent.Get(syncable::META_HANDLE);
191 if (ordered_commit_set_->HaveCommitItem(handle)) { 194 if (commit_set_->HaveCommitItem(handle)) {
192 // We've already added this parent (and therefore all of its parents). 195 // We've already added this parent (and therefore all of its parents).
193 // We can return early. 196 // We can return early.
194 break; 197 break;
195 } 198 }
196 if (!AddItemThenPredecessors(trans, ready_unsynced_set, parent, 199 if (!AddItemThenPredecessors(trans, ready_unsynced_set, parent,
197 &item_dependencies)) { 200 &item_dependencies)) {
198 // There was a parent/predecessor in conflict. We return without adding 201 // There was a parent/predecessor in conflict. We return without adding
199 // anything to |ordered_commit_set_|. 202 // anything to |commit_set|.
200 DVLOG(1) << "Parent or parent's predecessor was in conflict, omitting " 203 DVLOG(1) << "Parent or parent's predecessor was in conflict, omitting "
201 << item; 204 << item;
202 return false; 205 return false;
203 } 206 }
204 parent_id = parent.Get(syncable::PARENT_ID); 207 parent_id = parent.Get(syncable::PARENT_ID);
205 } 208 }
206 209
207 // Reverse what we added to get the correct order. 210 // Reverse what we added to get the correct order.
208 result->AppendReverse(item_dependencies); 211 result->AppendReverse(item_dependencies);
209 return true; 212 return true;
(...skipping 17 matching lines...) Expand all
227 item.GetModelType()); 230 item.GetModelType());
228 return true; 231 return true;
229 } 232 }
230 233
231 bool GetCommitIdsCommand::AddItemThenPredecessors( 234 bool GetCommitIdsCommand::AddItemThenPredecessors(
232 syncable::BaseTransaction* trans, 235 syncable::BaseTransaction* trans,
233 const std::set<int64>& ready_unsynced_set, 236 const std::set<int64>& ready_unsynced_set,
234 const syncable::Entry& item, 237 const syncable::Entry& item,
235 OrderedCommitSet* result) const { 238 OrderedCommitSet* result) const {
236 int64 item_handle = item.Get(syncable::META_HANDLE); 239 int64 item_handle = item.Get(syncable::META_HANDLE);
237 if (ordered_commit_set_->HaveCommitItem(item_handle)) { 240 if (commit_set_->HaveCommitItem(item_handle)) {
238 // We've already added this item to the commit set, and so must have 241 // We've already added this item to the commit set, and so must have
239 // already added the predecessors as well. 242 // already added the predecessors as well.
240 return true; 243 return true;
241 } 244 }
242 if (!AddItem(ready_unsynced_set, item, result)) 245 if (!AddItem(ready_unsynced_set, item, result))
243 return false; // Item is in conflict. 246 return false; // Item is in conflict.
244 if (item.Get(syncable::IS_DEL)) 247 if (item.Get(syncable::IS_DEL))
245 return true; // Deleted items have no predecessors. 248 return true; // Deleted items have no predecessors.
246 249
247 syncable::Id prev_id = item.Get(syncable::PREV_ID); 250 syncable::Id prev_id = item.Get(syncable::PREV_ID);
248 while (!prev_id.IsRoot()) { 251 while (!prev_id.IsRoot()) {
249 syncable::Entry prev(trans, syncable::GET_BY_ID, prev_id); 252 syncable::Entry prev(trans, syncable::GET_BY_ID, prev_id);
250 CHECK(prev.good()) << "Bad id when walking predecessors."; 253 CHECK(prev.good()) << "Bad id when walking predecessors.";
251 if (!prev.Get(syncable::IS_UNSYNCED)) 254 if (!prev.Get(syncable::IS_UNSYNCED))
252 break; 255 break;
253 int64 handle = prev.Get(syncable::META_HANDLE); 256 int64 handle = prev.Get(syncable::META_HANDLE);
254 if (ordered_commit_set_->HaveCommitItem(handle)) { 257 if (commit_set_->HaveCommitItem(handle)) {
255 // We've already added this item to the commit set, and so must have 258 // We've already added this item to the commit set, and so must have
256 // already added the predecessors as well. 259 // already added the predecessors as well.
257 return true; 260 return true;
258 } 261 }
259 if (!AddItem(ready_unsynced_set, prev, result)) 262 if (!AddItem(ready_unsynced_set, prev, result))
260 return false; // Item is in conflict. 263 return false; // Item is in conflict.
261 prev_id = prev.Get(syncable::PREV_ID); 264 prev_id = prev.Get(syncable::PREV_ID);
262 } 265 }
263 return true; 266 return true;
264 } 267 }
(...skipping 12 matching lines...) Expand all
277 DVLOG(1) << "Predecessor was in conflict, omitting " << item; 280 DVLOG(1) << "Predecessor was in conflict, omitting " << item;
278 return false; 281 return false;
279 } 282 }
280 283
281 // Reverse what we added to get the correct order. 284 // Reverse what we added to get the correct order.
282 result->AppendReverse(item_dependencies); 285 result->AppendReverse(item_dependencies);
283 return true; 286 return true;
284 } 287 }
285 288
286 bool GetCommitIdsCommand::IsCommitBatchFull() const { 289 bool GetCommitIdsCommand::IsCommitBatchFull() const {
287 return ordered_commit_set_->Size() >= requested_commit_batch_size_; 290 return commit_set_->Size() >= requested_commit_batch_size_;
288 } 291 }
289 292
290 void GetCommitIdsCommand::AddCreatesAndMoves( 293 void GetCommitIdsCommand::AddCreatesAndMoves(
291 syncable::WriteTransaction* write_transaction, 294 syncable::WriteTransaction* write_transaction,
292 const ModelSafeRoutingInfo& routes, 295 const ModelSafeRoutingInfo& routes,
293 const std::set<int64>& ready_unsynced_set) { 296 const std::set<int64>& ready_unsynced_set) {
294 // Add moves and creates, and prepend their uncommitted parents. 297 // Add moves and creates, and prepend their uncommitted parents.
295 for (std::set<int64>::const_iterator iter = ready_unsynced_set.begin(); 298 for (std::set<int64>::const_iterator iter = ready_unsynced_set.begin();
296 !IsCommitBatchFull() && iter != ready_unsynced_set.end(); ++iter) { 299 !IsCommitBatchFull() && iter != ready_unsynced_set.end(); ++iter) {
297 int64 metahandle = *iter; 300 int64 metahandle = *iter;
298 if (ordered_commit_set_->HaveCommitItem(metahandle)) 301 if (commit_set_->HaveCommitItem(metahandle))
299 continue; 302 continue;
300 303
301 syncable::Entry entry(write_transaction, 304 syncable::Entry entry(write_transaction,
302 syncable::GET_BY_HANDLE, 305 syncable::GET_BY_HANDLE,
303 metahandle); 306 metahandle);
304 if (!entry.Get(syncable::IS_DEL)) { 307 if (!entry.Get(syncable::IS_DEL)) {
305 // We only commit an item + its dependencies if it and all its 308 // We only commit an item + its dependencies if it and all its
306 // dependencies are not in conflict. 309 // dependencies are not in conflict.
307 OrderedCommitSet item_dependencies(routes); 310 OrderedCommitSet item_dependencies(routes);
308 if (AddUncommittedParentsAndTheirPredecessors( 311 if (AddUncommittedParentsAndTheirPredecessors(
309 write_transaction, 312 write_transaction,
310 routes, 313 routes,
311 ready_unsynced_set, 314 ready_unsynced_set,
312 entry, 315 entry,
313 &item_dependencies) && 316 &item_dependencies) &&
314 AddPredecessorsThenItem(write_transaction, 317 AddPredecessorsThenItem(write_transaction,
315 routes, 318 routes,
316 ready_unsynced_set, 319 ready_unsynced_set,
317 entry, 320 entry,
318 &item_dependencies)) { 321 &item_dependencies)) {
319 ordered_commit_set_->Append(item_dependencies); 322 commit_set_->Append(item_dependencies);
320 } 323 }
321 } 324 }
322 } 325 }
323 326
324 // It's possible that we overcommitted while trying to expand dependent 327 // It's possible that we overcommitted while trying to expand dependent
325 // items. If so, truncate the set down to the allowed size. 328 // items. If so, truncate the set down to the allowed size.
326 ordered_commit_set_->Truncate(requested_commit_batch_size_); 329 commit_set_->Truncate(requested_commit_batch_size_);
327 } 330 }
328 331
329 void GetCommitIdsCommand::AddDeletes( 332 void GetCommitIdsCommand::AddDeletes(
330 syncable::WriteTransaction* write_transaction, 333 syncable::WriteTransaction* write_transaction,
331 const std::set<int64>& ready_unsynced_set) { 334 const std::set<int64>& ready_unsynced_set) {
332 set<syncable::Id> legal_delete_parents; 335 set<syncable::Id> legal_delete_parents;
333 336
334 for (std::set<int64>::const_iterator iter = ready_unsynced_set.begin(); 337 for (std::set<int64>::const_iterator iter = ready_unsynced_set.begin();
335 !IsCommitBatchFull() && iter != ready_unsynced_set.end(); ++iter) { 338 !IsCommitBatchFull() && iter != ready_unsynced_set.end(); ++iter) {
336 int64 metahandle = *iter; 339 int64 metahandle = *iter;
337 if (ordered_commit_set_->HaveCommitItem(metahandle)) 340 if (commit_set_->HaveCommitItem(metahandle))
338 continue; 341 continue;
339 342
340 syncable::Entry entry(write_transaction, syncable::GET_BY_HANDLE, 343 syncable::Entry entry(write_transaction, syncable::GET_BY_HANDLE,
341 metahandle); 344 metahandle);
342 345
343 if (entry.Get(syncable::IS_DEL)) { 346 if (entry.Get(syncable::IS_DEL)) {
344 syncable::Entry parent(write_transaction, syncable::GET_BY_ID, 347 syncable::Entry parent(write_transaction, syncable::GET_BY_ID,
345 entry.Get(syncable::PARENT_ID)); 348 entry.Get(syncable::PARENT_ID));
346 // If the parent is deleted and unsynced, then any children of that 349 // If the parent is deleted and unsynced, then any children of that
347 // parent don't need to be added to the delete queue. 350 // parent don't need to be added to the delete queue.
(...skipping 10 matching lines...) Expand all
358 // then we'll miss it in the roll up. We have to add it in manually. 361 // then we'll miss it in the roll up. We have to add it in manually.
359 // TODO(chron): Unit test for move / delete cases: 362 // TODO(chron): Unit test for move / delete cases:
360 // Case 1: Locally moved, then parent deleted 363 // Case 1: Locally moved, then parent deleted
361 // Case 2: Server moved, then locally issue recursive delete. 364 // Case 2: Server moved, then locally issue recursive delete.
362 if (entry.Get(syncable::ID).ServerKnows() && 365 if (entry.Get(syncable::ID).ServerKnows() &&
363 entry.Get(syncable::PARENT_ID) != 366 entry.Get(syncable::PARENT_ID) !=
364 entry.Get(syncable::SERVER_PARENT_ID)) { 367 entry.Get(syncable::SERVER_PARENT_ID)) {
365 DVLOG(1) << "Inserting moved and deleted entry, will be missed by " 368 DVLOG(1) << "Inserting moved and deleted entry, will be missed by "
366 << "delete roll." << entry.Get(syncable::ID); 369 << "delete roll." << entry.Get(syncable::ID);
367 370
368 ordered_commit_set_->AddCommitItem(metahandle, 371 commit_set_->AddCommitItem(metahandle,
369 entry.Get(syncable::ID), 372 entry.Get(syncable::ID),
370 entry.GetModelType()); 373 entry.GetModelType());
371 } 374 }
372 375
373 // Skip this entry since it's a child of a parent that will be 376 // Skip this entry since it's a child of a parent that will be
374 // deleted. The server will unroll the delete and delete the 377 // deleted. The server will unroll the delete and delete the
375 // child as well. 378 // child as well.
376 continue; 379 continue;
377 } 380 }
378 381
(...skipping 10 matching lines...) Expand all
389 // entry, then check if the parent is in legal_delete_parents. 392 // entry, then check if the parent is in legal_delete_parents.
390 // 393 //
391 // Parent being in legal_delete_parents means for the child: 394 // Parent being in legal_delete_parents means for the child:
392 // a recursive delete is not currently happening (no recent deletes in same 395 // a recursive delete is not currently happening (no recent deletes in same
393 // folder) 396 // folder)
394 // parent did expect at least one old deleted child 397 // parent did expect at least one old deleted child
395 // parent was not deleted 398 // parent was not deleted
396 for (std::set<int64>::const_iterator iter = ready_unsynced_set.begin(); 399 for (std::set<int64>::const_iterator iter = ready_unsynced_set.begin();
397 !IsCommitBatchFull() && iter != ready_unsynced_set.end(); ++iter) { 400 !IsCommitBatchFull() && iter != ready_unsynced_set.end(); ++iter) {
398 int64 metahandle = *iter; 401 int64 metahandle = *iter;
399 if (ordered_commit_set_->HaveCommitItem(metahandle)) 402 if (commit_set_->HaveCommitItem(metahandle))
400 continue; 403 continue;
401 syncable::MutableEntry entry(write_transaction, syncable::GET_BY_HANDLE, 404 syncable::MutableEntry entry(write_transaction, syncable::GET_BY_HANDLE,
402 metahandle); 405 metahandle);
403 if (entry.Get(syncable::IS_DEL)) { 406 if (entry.Get(syncable::IS_DEL)) {
404 syncable::Id parent_id = entry.Get(syncable::PARENT_ID); 407 syncable::Id parent_id = entry.Get(syncable::PARENT_ID);
405 if (legal_delete_parents.count(parent_id)) { 408 if (legal_delete_parents.count(parent_id)) {
406 ordered_commit_set_->AddCommitItem(metahandle, entry.Get(syncable::ID), 409 commit_set_->AddCommitItem(metahandle, entry.Get(syncable::ID),
407 entry.GetModelType()); 410 entry.GetModelType());
408 } 411 }
409 } 412 }
410 } 413 }
411 } 414 }
412 415
413 void GetCommitIdsCommand::BuildCommitIds( 416 void GetCommitIdsCommand::BuildCommitIds(
414 syncable::WriteTransaction* write_transaction, 417 syncable::WriteTransaction* write_transaction,
415 const ModelSafeRoutingInfo& routes, 418 const ModelSafeRoutingInfo& routes,
416 const std::set<int64>& ready_unsynced_set) { 419 const std::set<int64>& ready_unsynced_set) {
417 ordered_commit_set_.reset(new OrderedCommitSet(routes));
418 // Commits follow these rules: 420 // Commits follow these rules:
419 // 1. Moves or creates are preceded by needed folder creates, from 421 // 1. Moves or creates are preceded by needed folder creates, from
420 // root to leaf. For folders whose contents are ordered, moves 422 // root to leaf. For folders whose contents are ordered, moves
421 // and creates appear in order. 423 // and creates appear in order.
422 // 2. Moves/Creates before deletes. 424 // 2. Moves/Creates before deletes.
423 // 3. Deletes, collapsed. 425 // 3. Deletes, collapsed.
424 // We commit deleted moves under deleted items as moves when collapsing 426 // We commit deleted moves under deleted items as moves when collapsing
425 // delete trees. 427 // delete trees.
426 428
427 // Add moves and creates, and prepend their uncommitted parents. 429 // Add moves and creates, and prepend their uncommitted parents.
428 AddCreatesAndMoves(write_transaction, routes, ready_unsynced_set); 430 AddCreatesAndMoves(write_transaction, routes, ready_unsynced_set);
429 431
430 // Add all deletes. 432 // Add all deletes.
431 AddDeletes(write_transaction, ready_unsynced_set); 433 AddDeletes(write_transaction, ready_unsynced_set);
432 } 434 }
433 435
434 } // namespace browser_sync 436 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698