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

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

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

Powered by Google App Engine
This is Rietveld 408576698