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

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

Powered by Google App Engine
This is Rietveld 408576698