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

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

Issue 1548843002: Fix GetCommitIds local deletion case resulting in orphaning of directory entries (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Use int64_t Created 4 years, 11 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
« no previous file with comments | « no previous file | sync/engine/syncer_unittest.cc » ('j') | sync/engine/syncer_unittest.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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.h" 5 #include "sync/engine/get_commit_ids.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <set> 10 #include <set>
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 bool HasAttachmentNotOnServer(const syncable::Entry& entry) { 112 bool HasAttachmentNotOnServer(const syncable::Entry& entry) {
113 const sync_pb::AttachmentMetadata& metadata = entry.GetAttachmentMetadata(); 113 const sync_pb::AttachmentMetadata& metadata = entry.GetAttachmentMetadata();
114 for (int i = 0; i < metadata.record_size(); ++i) { 114 for (int i = 0; i < metadata.record_size(); ++i) {
115 if (!metadata.record(i).is_on_server()) { 115 if (!metadata.record(i).is_on_server()) {
116 return true; 116 return true;
117 } 117 }
118 } 118 }
119 return false; 119 return false;
120 } 120 }
121 121
122 // An entry is not considered ready for commit if any are true: 122 // An entry may not commit if any are true:
123 // 1. It's in conflict. 123 // 1. It requires encryption (either the type is encrypted but a passphrase
124 // 2. It requires encryption (either the type is encrypted but a passphrase
125 // is missing from the cryptographer, or the entry itself wasn't properly 124 // is missing from the cryptographer, or the entry itself wasn't properly
126 // encrypted). 125 // encrypted).
127 // 3. It's type is currently throttled. 126 // 2. It's type is currently throttled.
128 // 4. It's a delete but has not been committed. 127 // 3. It's a delete but has not been committed.
129 bool IsEntryReadyForCommit(ModelTypeSet requested_types, 128 bool MayEntryCommit(ModelTypeSet requested_types,
130 ModelTypeSet encrypted_types, 129 ModelTypeSet encrypted_types,
131 bool passphrase_missing, 130 bool passphrase_missing,
132 const syncable::Entry& entry) { 131 const syncable::Entry& entry) {
133 DCHECK(entry.GetIsUnsynced()); 132 DCHECK(entry.GetIsUnsynced());
134 if (IsEntryInConflict(entry))
135 return false;
136 133
137 const ModelType type = entry.GetModelType(); 134 const ModelType type = entry.GetModelType();
138 // We special case the nigori node because even though it is considered an 135 // We special case the nigori node because even though it is considered an
139 // "encrypted type", not all nigori node changes require valid encryption 136 // "encrypted type", not all nigori node changes require valid encryption
140 // (ex: sync_tabs). 137 // (ex: sync_tabs).
141 if ((type != NIGORI) && encrypted_types.Has(type) && 138 if ((type != NIGORI) && encrypted_types.Has(type) &&
142 (passphrase_missing || 139 (passphrase_missing ||
143 syncable::EntryNeedsEncryption(encrypted_types, entry))) { 140 syncable::EntryNeedsEncryption(encrypted_types, entry))) {
144 // This entry requires encryption but is not properly encrypted (possibly 141 // This entry requires encryption but is not properly encrypted (possibly
145 // due to the cryptographer not being initialized or the user hasn't 142 // due to the cryptographer not being initialized or the user hasn't
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 // This entry is not ready to be sent to the server because it has one or 176 // This entry is not ready to be sent to the server because it has one or
180 // more attachments that have not yet been uploaded to the server. The idea 177 // more attachments that have not yet been uploaded to the server. The idea
181 // here is avoid propagating an entry with dangling attachment references. 178 // here is avoid propagating an entry with dangling attachment references.
182 return false; 179 return false;
183 } 180 }
184 181
185 DVLOG(2) << "Entry is ready for commit: " << entry; 182 DVLOG(2) << "Entry is ready for commit: " << entry;
186 return true; 183 return true;
187 } 184 }
188 185
186 bool SupportsHierarchy(const syncable::Entry& item) {
187 // Types with explicit server supported hierarchy only.
188 return IsTypeWithServerGeneratedRoot(item.GetModelType());
189 }
190
191 // Excludes ancestors of deleted conflicted items from
192 // |ready_unsynced_set|.
193 void ExcludeDeletedAncestors(
194 syncable::BaseTransaction* trans,
195 const std::vector<int64_t>& deleted_conflicted_items,
196 std::set<int64_t>* ready_unsynced_set) {
197 for (std::vector<int64_t>::const_iterator iter =
Nicolas Zea 2015/12/31 02:12:02 nit: use auto? (here and elsewhere)
stanisc 2016/01/04 22:00:48 Done.
198 deleted_conflicted_items.begin();
199 iter != deleted_conflicted_items.end(); ++iter) {
200 syncable::Entry item(trans, syncable::GET_BY_HANDLE, *iter);
201 syncable::Id parent_id = item.GetParentId();
202 DCHECK(!parent_id.IsNull());
203
204 while (!parent_id.IsRoot()) {
205 syncable::Entry parent(trans, syncable::GET_BY_ID, parent_id);
206 CHECK(parent.good()) << "Bad user-only parent in item path.";
207 int64_t handle = parent.GetMetahandle();
208
209 if (!parent.GetIsDel())
210 break;
211
212 std::set<int64_t>::iterator ready_iter = ready_unsynced_set->find(handle);
213 if (ready_iter == ready_unsynced_set->end())
214 break;
215
216 // Remove this entry from |ready_unsynced_set|.
217 ready_unsynced_set->erase(ready_iter);
218 parent_id = parent.GetParentId();
219 }
220 }
221 }
222
223 // Excludes children of items from |conflicted_items| list.
Nicolas Zea 2015/12/31 02:12:02 Mention excluded_items output as well?
stanisc 2016/01/04 22:00:48 Done.
224 void ExcludeChildren(syncable::BaseTransaction* trans,
225 const std::vector<int64_t>& conflicted_items,
226 std::vector<int64_t>* excluded_items,
227 std::set<int64_t>* ready_unsynced_set) {
228 for (std::vector<int64_t>::const_iterator iter = conflicted_items.begin();
229 iter != conflicted_items.end(); ++iter) {
230 syncable::Entry entry(trans, syncable::GET_BY_HANDLE, *iter);
231
232 if (!entry.GetIsDir() || entry.GetIsDel())
233 continue;
234
235 std::vector<int64_t> children;
236 entry.GetChildHandles(&children);
237
238 for (std::vector<int64_t>::const_iterator child_iter = children.begin();
239 child_iter != children.end(); ++child_iter) {
240 // Collect all child handles that are in |ready_unsynced_set|.
241 int64_t child_handle = *child_iter;
242 std::set<int64_t>::iterator ready_iter =
243 ready_unsynced_set->find(child_handle);
244 if (ready_iter != ready_unsynced_set->end()) {
245 // Remove this entry from |ready_unsynced_set| and add it
246 // to |excluded_items|.
247 ready_unsynced_set->erase(ready_iter);
248 excluded_items->push_back(child_handle);
249 }
250 }
251 }
252 }
253
189 // Filters |unsynced_handles| to remove all entries that do not belong to the 254 // Filters |unsynced_handles| to remove all entries that do not belong to the
190 // specified |requested_types|, or are not eligible for a commit at this time. 255 // specified |requested_types|, or are not eligible for a commit at this time.
191 void FilterUnreadyEntries( 256 void FilterUnreadyEntries(
192 syncable::BaseTransaction* trans, 257 syncable::BaseTransaction* trans,
193 ModelTypeSet requested_types, 258 ModelTypeSet requested_types,
194 ModelTypeSet encrypted_types, 259 ModelTypeSet encrypted_types,
195 bool passphrase_missing, 260 bool passphrase_missing,
196 const syncable::Directory::Metahandles& unsynced_handles, 261 const syncable::Directory::Metahandles& unsynced_handles,
197 std::set<int64_t>* ready_unsynced_set) { 262 std::set<int64_t>* ready_unsynced_set) {
263 std::vector<int64_t> deleted_conflicted_items;
264 std::vector<int64_t> conflicted_items;
265
266 // Go over all unsynced handles, filter the ones that might be committed based
267 // on type / encryption, then based on whether they are in conflict add them
268 // to either |ready_unsynced_set| or one of the conflicted lists.
198 for (syncable::Directory::Metahandles::const_iterator iter = 269 for (syncable::Directory::Metahandles::const_iterator iter =
199 unsynced_handles.begin(); iter != unsynced_handles.end(); ++iter) { 270 unsynced_handles.begin(); iter != unsynced_handles.end(); ++iter) {
200 syncable::Entry entry(trans, syncable::GET_BY_HANDLE, *iter); 271 syncable::Entry entry(trans, syncable::GET_BY_HANDLE, *iter);
201 // TODO(maniscalco): While we check if entry is ready to be committed, we 272 // TODO(maniscalco): While we check if entry is ready to be committed, we
202 // also need to check that all of its ancestors (parents, transitive) are 273 // also need to check that all of its ancestors (parents, transitive) are
203 // ready to be committed. Once attachments can prevent an entry from being 274 // ready to be committed. Once attachments can prevent an entry from being
204 // committable, this method must ensure all ancestors are ready for commit 275 // committable, this method must ensure all ancestors are ready for commit
205 // (bug 356273). 276 // (bug 356273).
206 if (IsEntryReadyForCommit(requested_types, 277 if (MayEntryCommit(requested_types, encrypted_types, passphrase_missing,
207 encrypted_types, 278 entry)) {
208 passphrase_missing, 279 if (IsEntryInConflict(entry)) {
209 entry)) { 280 // Conflicting hierarchical entries might prevent their ancestors or
210 ready_unsynced_set->insert(*iter); 281 // descendants from being committed.
282 if (SupportsHierarchy(entry)) {
283 if (entry.GetIsDel()) {
284 deleted_conflicted_items.push_back(*iter);
285 } else if (entry.GetIsDir()) {
286 // Populate the initial version of |conflicted_items| with folder
287 // items that are in conflict.
288 conflicted_items.push_back(*iter);
289 }
290 }
291 } else {
292 ready_unsynced_set->insert(*iter);
293 }
211 } 294 }
212 } 295 }
296
297 // If there are any deleted conflicted entries, remote their deleted ancestors
Nicolas Zea 2015/12/31 02:12:03 nit: remote -> remove
stanisc 2016/01/04 22:00:48 Done.
298 // as well.
299 ExcludeDeletedAncestors(trans, deleted_conflicted_items, ready_unsynced_set);
300
301 // Starting with conflicted_items containing conflicted folders go down and
302 // exclude all descendants from |ready_unsynced_set|.
303 while (!conflicted_items.empty()) {
304 std::vector<int64_t> new_list;
305 ExcludeChildren(trans, conflicted_items, &new_list, ready_unsynced_set);
306 conflicted_items.swap(new_list);
307 }
213 } 308 }
214 309
215 // This class helps to implement OrderCommitIds(). Its members track the 310 // This class helps to implement OrderCommitIds(). Its members track the
216 // progress of a traversal while its methods extend it. It can return early if 311 // progress of a traversal while its methods extend it. It can return early if
217 // the traversal reaches the desired size before the full traversal is complete. 312 // the traversal reaches the desired size before the full traversal is complete.
218 class Traversal { 313 class Traversal {
219 public: 314 public:
220 Traversal(syncable::BaseTransaction* trans, 315 Traversal(syncable::BaseTransaction* trans,
221 int64_t max_entries, 316 int64_t max_entries,
222 syncable::Directory::Metahandles* out); 317 syncable::Directory::Metahandles* out);
223 ~Traversal(); 318 ~Traversal();
224 319
225 // First step of traversal building. Adds non-deleted items in order. 320 // First step of traversal building. Adds non-deleted items in order.
226 void AddCreatesAndMoves(const std::set<int64_t>& ready_unsynced_set); 321 void AddCreatesAndMoves(const std::set<int64_t>& ready_unsynced_set);
227 322
228 // Second step of traverals building. Appends deleted items. 323 // Second step of traverals building. Appends deleted items.
229 void AddDeletes(const std::set<int64_t>& ready_unsynced_set); 324 void AddDeletes(const std::set<int64_t>& ready_unsynced_set);
230 325
231 private: 326 private:
232 // The following functions do not modify the traversal directly. They return 327 // The following functions do not modify the traversal directly. They return
233 // their results in the |result| vector instead. 328 // their results in the |result| vector instead.
234 bool AddUncommittedParents(const std::set<int64_t>& ready_unsynced_set, 329 void AddUncommittedParents(const std::set<int64_t>& ready_unsynced_set,
235 const syncable::Entry& item, 330 const syncable::Entry& item,
236 syncable::Directory::Metahandles* result) const; 331 syncable::Directory::Metahandles* result) const;
237 332
238 void TryAddItem(const std::set<int64_t>& ready_unsynced_set, 333 bool TryAddItem(const std::set<int64_t>& ready_unsynced_set,
239 const syncable::Entry& item, 334 const syncable::Entry& item,
240 syncable::Directory::Metahandles* result) const; 335 syncable::Directory::Metahandles* result) const;
241 336
242 bool AddDeletedParents(const std::set<int64_t>& ready_unsynced_set, 337 void AddDeletedParents(const std::set<int64_t>& ready_unsynced_set,
243 const syncable::Entry& item, 338 const syncable::Entry& item,
244 const syncable::Directory::Metahandles& traversed, 339 const syncable::Directory::Metahandles& traversed,
245 syncable::Directory::Metahandles* result) const; 340 syncable::Directory::Metahandles* result) const;
246 341
247 bool SupportsHierarchy(const syncable::Entry& item) const;
248
249 // Returns true if we've collected enough items. 342 // Returns true if we've collected enough items.
250 bool IsFull() const; 343 bool IsFull() const;
251 344
252 // Returns true if the specified handle is already in the traversal. 345 // Returns true if the specified handle is already in the traversal.
253 bool HaveItem(int64_t handle) const; 346 bool HaveItem(int64_t handle) const;
254 347
255 // Adds the specified handles to the traversal. 348 // Adds the specified handles to the traversal.
256 void AppendManyToTraversal(const syncable::Directory::Metahandles& handles); 349 void AppendManyToTraversal(const syncable::Directory::Metahandles& handles);
257 350
258 // Adds the specifed handle to the traversal. 351 // Adds the specifed handle to the traversal.
259 void AppendToTraversal(int64_t handle); 352 void AppendToTraversal(int64_t handle);
260 353
261 syncable::Directory::Metahandles* out_; 354 syncable::Directory::Metahandles* out_;
262 std::set<int64_t> added_handles_; 355 std::set<int64_t> added_handles_;
263 const size_t max_entries_; 356 const size_t max_entries_;
264 syncable::BaseTransaction* trans_; 357 syncable::BaseTransaction* trans_;
265 358
266 DISALLOW_COPY_AND_ASSIGN(Traversal); 359 DISALLOW_COPY_AND_ASSIGN(Traversal);
267 }; 360 };
268 361
269 Traversal::Traversal(syncable::BaseTransaction* trans, 362 Traversal::Traversal(syncable::BaseTransaction* trans,
270 int64_t max_entries, 363 int64_t max_entries,
271 syncable::Directory::Metahandles* out) 364 syncable::Directory::Metahandles* out)
272 : out_(out), max_entries_(max_entries), trans_(trans) {} 365 : out_(out), max_entries_(max_entries), trans_(trans) {}
273 366
274 Traversal::~Traversal() {} 367 Traversal::~Traversal() {}
275 368
276 bool Traversal::AddUncommittedParents( 369 void Traversal::AddUncommittedParents(
277 const std::set<int64_t>& ready_unsynced_set, 370 const std::set<int64_t>& ready_unsynced_set,
278 const syncable::Entry& item, 371 const syncable::Entry& item,
279 syncable::Directory::Metahandles* result) const { 372 syncable::Directory::Metahandles* result) const {
280 DCHECK(SupportsHierarchy(item)); 373 DCHECK(SupportsHierarchy(item));
281 syncable::Directory::Metahandles dependencies; 374 syncable::Directory::Metahandles dependencies;
282 syncable::Id parent_id = item.GetParentId(); 375 syncable::Id parent_id = item.GetParentId();
283 376
284 // Climb the tree adding entries leaf -> root. 377 // Climb the tree adding entries leaf -> root.
285 while (!parent_id.ServerKnows()) { 378 while (!parent_id.ServerKnows()) {
286 syncable::Entry parent(trans_, syncable::GET_BY_ID, parent_id); 379 syncable::Entry parent(trans_, syncable::GET_BY_ID, parent_id);
287 CHECK(parent.good()) << "Bad user-only parent in item path."; 380 CHECK(parent.good()) << "Bad user-only parent in item path.";
288 int64_t handle = parent.GetMetahandle(); 381 int64_t handle = parent.GetMetahandle();
289 if (HaveItem(handle)) { 382 if (HaveItem(handle)) {
290 // We've already added this parent (and therefore all of its parents). 383 // We've already added this parent (and therefore all of its parents).
291 // We can return early. 384 // We can return early.
292 break; 385 break;
293 } 386 }
294 if (IsEntryInConflict(parent)) { 387
295 // We ignore all entries that are children of a conflicing item. Return 388 if (!TryAddItem(ready_unsynced_set, parent, &dependencies)) {
296 // false immediately to forget the traversal we've built up so far. 389 // The parent isn't in |ready_unsynced_set|.
297 DVLOG(1) << "Parent was in conflict, omitting " << item; 390 break;
298 return false;
299 } 391 }
300 TryAddItem(ready_unsynced_set, parent, &dependencies); 392
301 parent_id = parent.GetParentId(); 393 parent_id = parent.GetParentId();
302 } 394 }
303 395
304 // Reverse what we added to get the correct order. 396 // Reverse what we added to get the correct order.
305 result->insert(result->end(), dependencies.rbegin(), dependencies.rend()); 397 result->insert(result->end(), dependencies.rbegin(), dependencies.rend());
306 return true;
307 } 398 }
308 399
309 // Adds the given item to the list if it is unsynced and ready for commit. 400 // Adds the given item to the list if it is unsynced and ready for commit.
310 void Traversal::TryAddItem(const std::set<int64_t>& ready_unsynced_set, 401 bool Traversal::TryAddItem(const std::set<int64_t>& ready_unsynced_set,
311 const syncable::Entry& item, 402 const syncable::Entry& item,
312 syncable::Directory::Metahandles* result) const { 403 syncable::Directory::Metahandles* result) const {
313 DCHECK(item.GetIsUnsynced()); 404 DCHECK(item.GetIsUnsynced());
314 int64_t item_handle = item.GetMetahandle(); 405 int64_t item_handle = item.GetMetahandle();
315 if (ready_unsynced_set.count(item_handle) != 0) { 406 if (ready_unsynced_set.count(item_handle) != 0) {
316 result->push_back(item_handle); 407 result->push_back(item_handle);
408 return true;
317 } 409 }
410 return false;
318 } 411 }
319 412
320 // Traverses the tree from bottom to top, adding the deleted parents of the 413 // Traverses the tree from bottom to top, adding the deleted parents of the
321 // given |item|. Stops traversing if it encounters a non-deleted node, or 414 // given |item|. Stops traversing if it encounters a non-deleted node, or
322 // a node that was already listed in the |traversed| list. Returns an error 415 // a node that was already listed in the |traversed| list.
323 // (false) if a node along the traversal is in a conflict state.
324 // 416 //
325 // The result list is reversed before it is returned, so the resulting 417 // The result list is reversed before it is returned, so the resulting
326 // traversal is in top to bottom order. Also note that this function appends 418 // traversal is in top to bottom order. Also note that this function appends
327 // to the result list without clearing it. 419 // to the result list without clearing it.
328 bool Traversal::AddDeletedParents( 420 void Traversal::AddDeletedParents(
329 const std::set<int64_t>& ready_unsynced_set, 421 const std::set<int64_t>& ready_unsynced_set,
330 const syncable::Entry& item, 422 const syncable::Entry& item,
331 const syncable::Directory::Metahandles& traversed, 423 const syncable::Directory::Metahandles& traversed,
332 syncable::Directory::Metahandles* result) const { 424 syncable::Directory::Metahandles* result) const {
333 DCHECK(SupportsHierarchy(item)); 425 DCHECK(SupportsHierarchy(item));
334 syncable::Directory::Metahandles dependencies; 426 syncable::Directory::Metahandles dependencies;
335 syncable::Id parent_id = item.GetParentId(); 427 syncable::Id parent_id = item.GetParentId();
336 428
337 // Climb the tree adding entries leaf -> root. 429 // Climb the tree adding entries leaf -> root.
338 while (!parent_id.IsRoot()) { 430 while (!parent_id.IsRoot()) {
(...skipping 17 matching lines...) Expand all
356 if (!parent.GetIsDel()) { 448 if (!parent.GetIsDel()) {
357 // We're not intersted in non-deleted parents. 449 // We're not intersted in non-deleted parents.
358 break; 450 break;
359 } 451 }
360 if (std::find(traversed.begin(), traversed.end(), handle) != 452 if (std::find(traversed.begin(), traversed.end(), handle) !=
361 traversed.end()) { 453 traversed.end()) {
362 // We've already added this parent (and therefore all of its parents). 454 // We've already added this parent (and therefore all of its parents).
363 // We can return early. 455 // We can return early.
364 break; 456 break;
365 } 457 }
366 if (IsEntryInConflict(parent)) { 458
367 // We ignore all entries that are children of a conflicing item. Return 459 if (!TryAddItem(ready_unsynced_set, parent, &dependencies)) {
368 // false immediately to forget the traversal we've built up so far. 460 // The parent isn't in ready_unsynced_set.
369 DVLOG(1) << "Parent was in conflict, omitting " << item; 461 break;
370 return false;
371 } 462 }
372 TryAddItem(ready_unsynced_set, parent, &dependencies); 463
373 parent_id = parent.GetParentId(); 464 parent_id = parent.GetParentId();
374 } 465 }
375 466
376 // Reverse what we added to get the correct order. 467 // Reverse what we added to get the correct order.
377 result->insert(result->end(), dependencies.rbegin(), dependencies.rend()); 468 result->insert(result->end(), dependencies.rbegin(), dependencies.rend());
378 return true;
379 } 469 }
380 470
381 bool Traversal::IsFull() const { 471 bool Traversal::IsFull() const {
382 return out_->size() >= max_entries_; 472 return out_->size() >= max_entries_;
383 } 473 }
384 474
385 bool Traversal::HaveItem(int64_t handle) const { 475 bool Traversal::HaveItem(int64_t handle) const {
386 return added_handles_.find(handle) != added_handles_.end(); 476 return added_handles_.find(handle) != added_handles_.end();
387 } 477 }
388 478
389 bool Traversal::SupportsHierarchy(const syncable::Entry& item) const {
390 // Types with explicit server supported hierarchy only.
391 return IsTypeWithServerGeneratedRoot(item.GetModelType());
392 }
393
394 void Traversal::AppendManyToTraversal( 479 void Traversal::AppendManyToTraversal(
395 const syncable::Directory::Metahandles& handles) { 480 const syncable::Directory::Metahandles& handles) {
396 out_->insert(out_->end(), handles.begin(), handles.end()); 481 out_->insert(out_->end(), handles.begin(), handles.end());
397 added_handles_.insert(handles.begin(), handles.end()); 482 added_handles_.insert(handles.begin(), handles.end());
398 } 483 }
399 484
400 void Traversal::AppendToTraversal(int64_t metahandle) { 485 void Traversal::AppendToTraversal(int64_t metahandle) {
401 out_->push_back(metahandle); 486 out_->push_back(metahandle);
402 added_handles_.insert(metahandle); 487 added_handles_.insert(metahandle);
403 } 488 }
404 489
405 void Traversal::AddCreatesAndMoves( 490 void Traversal::AddCreatesAndMoves(
406 const std::set<int64_t>& ready_unsynced_set) { 491 const std::set<int64_t>& ready_unsynced_set) {
407 // Add moves and creates, and prepend their uncommitted parents. 492 // Add moves and creates, and prepend their uncommitted parents.
408 for (std::set<int64_t>::const_iterator iter = ready_unsynced_set.begin(); 493 for (std::set<int64_t>::const_iterator iter = ready_unsynced_set.begin();
409 !IsFull() && iter != ready_unsynced_set.end(); ++iter) { 494 !IsFull() && iter != ready_unsynced_set.end(); ++iter) {
410 int64_t metahandle = *iter; 495 int64_t metahandle = *iter;
411 if (HaveItem(metahandle)) 496 if (HaveItem(metahandle))
412 continue; 497 continue;
413 498
414 syncable::Entry entry(trans_, 499 syncable::Entry entry(trans_,
415 syncable::GET_BY_HANDLE, 500 syncable::GET_BY_HANDLE,
416 metahandle); 501 metahandle);
417 if (!entry.GetIsDel()) { 502 if (!entry.GetIsDel()) {
418 if (SupportsHierarchy(entry)) { 503 if (SupportsHierarchy(entry)) {
419 // We only commit an item + its dependencies if it and all its 504 // We only commit an item + its dependencies if it and all its
420 // dependencies are not in conflict. 505 // dependencies are not in conflict.
421 syncable::Directory::Metahandles item_dependencies; 506 syncable::Directory::Metahandles item_dependencies;
422 if (AddUncommittedParents(ready_unsynced_set, entry, 507 AddUncommittedParents(ready_unsynced_set, entry, &item_dependencies);
423 &item_dependencies)) { 508 TryAddItem(ready_unsynced_set, entry, &item_dependencies);
424 TryAddItem(ready_unsynced_set, entry, &item_dependencies); 509 AppendManyToTraversal(item_dependencies);
425 AppendManyToTraversal(item_dependencies);
426 }
427 } else { 510 } else {
428 // No hierarchy dependencies, just commit the item itself. 511 // No hierarchy dependencies, just commit the item itself.
429 AppendToTraversal(metahandle); 512 AppendToTraversal(metahandle);
430 } 513 }
431 } 514 }
432 } 515 }
433 516
434 // It's possible that we overcommitted while trying to expand dependent 517 // It's possible that we overcommitted while trying to expand dependent
435 // items. If so, truncate the set down to the allowed size. 518 // items. If so, truncate the set down to the allowed size.
436 if (out_->size() > max_entries_) 519 if (out_->size() > max_entries_)
(...skipping 17 matching lines...) Expand all
454 deletion_list.end()) { 537 deletion_list.end()) {
455 continue; 538 continue;
456 } 539 }
457 540
458 syncable::Entry entry(trans_, syncable::GET_BY_HANDLE, 541 syncable::Entry entry(trans_, syncable::GET_BY_HANDLE,
459 metahandle); 542 metahandle);
460 543
461 if (entry.GetIsDel()) { 544 if (entry.GetIsDel()) {
462 if (SupportsHierarchy(entry)) { 545 if (SupportsHierarchy(entry)) {
463 syncable::Directory::Metahandles parents; 546 syncable::Directory::Metahandles parents;
464 if (AddDeletedParents(ready_unsynced_set, entry, deletion_list, 547 AddDeletedParents(ready_unsynced_set, entry, deletion_list, &parents);
465 &parents)) { 548 // Append parents and chilren in top to bottom order.
466 // Append parents and chilren in top to bottom order. 549 deletion_list.insert(deletion_list.end(), parents.begin(),
467 deletion_list.insert(deletion_list.end(), parents.begin(), 550 parents.end());
468 parents.end());
469 deletion_list.push_back(metahandle);
470 }
471 } else {
472 deletion_list.push_back(metahandle);
473 } 551 }
552 deletion_list.push_back(metahandle);
474 } 553 }
475 } 554 }
476 555
477 // We've been gathering deletions in top to bottom order. Now we reverse the 556 // We've been gathering deletions in top to bottom order. Now we reverse the
478 // order as we prepare the list. 557 // order as we prepare the list.
479 std::reverse(deletion_list.begin(), deletion_list.end()); 558 std::reverse(deletion_list.begin(), deletion_list.end());
480 AppendManyToTraversal(deletion_list); 559 AppendManyToTraversal(deletion_list);
481 560
482 // It's possible that we overcommitted while trying to expand dependent 561 // It's possible that we overcommitted while trying to expand dependent
483 // items. If so, truncate the set down to the allowed size. 562 // items. If so, truncate the set down to the allowed size.
(...skipping 18 matching lines...) Expand all
502 // Add moves and creates, and prepend their uncommitted parents. 581 // Add moves and creates, and prepend their uncommitted parents.
503 traversal.AddCreatesAndMoves(ready_unsynced_set); 582 traversal.AddCreatesAndMoves(ready_unsynced_set);
504 583
505 // Add all deletes. 584 // Add all deletes.
506 traversal.AddDeletes(ready_unsynced_set); 585 traversal.AddDeletes(ready_unsynced_set);
507 } 586 }
508 587
509 } // namespace 588 } // namespace
510 589
511 } // namespace syncer 590 } // namespace syncer
OLDNEW
« no previous file with comments | « no previous file | sync/engine/syncer_unittest.cc » ('j') | sync/engine/syncer_unittest.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698