Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/syncable/syncable.h" | 5 #include "sync/syncable/syncable.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cstring> | 8 #include <cstring> |
| 9 #include <functional> | 9 #include <functional> |
| 10 #include <iomanip> | 10 #include <iomanip> |
| (...skipping 1718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1729 | 1729 |
| 1730 bool MutableEntry::PutIsDel(bool is_del) { | 1730 bool MutableEntry::PutIsDel(bool is_del) { |
| 1731 DCHECK(kernel_); | 1731 DCHECK(kernel_); |
| 1732 if (is_del == kernel_->ref(IS_DEL)) { | 1732 if (is_del == kernel_->ref(IS_DEL)) { |
| 1733 return true; | 1733 return true; |
| 1734 } | 1734 } |
| 1735 if (is_del) { | 1735 if (is_del) { |
| 1736 if (!UnlinkFromOrder()) { | 1736 if (!UnlinkFromOrder()) { |
| 1737 return false; | 1737 return false; |
| 1738 } | 1738 } |
| 1739 | |
| 1740 // If the server never knew about this item and it's deleted then we don't | |
| 1741 // need to keep it around. Unsetting IS_UNSYNCED will: | |
| 1742 // - Ensure that the item is never committed to the server. | |
| 1743 // - Allow any items with the same UNIQUE_CLIENT_TAG created on other | |
| 1744 // clients to override this entry. | |
| 1745 // - Let us delete this entry permanently through | |
| 1746 // DirectoryBackingStore::DropDeletedEntries() when we next restart sync. | |
| 1747 // This will save memory and avoid crbug.com/125381. | |
| 1748 if (!Get(ID).ServerKnows()) { | |
| 1749 Put(IS_UNSYNCED, false); | |
| 1750 } | |
| 1739 } | 1751 } |
| 1740 | 1752 |
| 1741 { | 1753 { |
| 1742 ScopedKernelLock lock(dir()); | 1754 ScopedKernelLock lock(dir()); |
| 1743 // Some indices don't include deleted items and must be updated | 1755 // Some indices don't include deleted items and must be updated |
| 1744 // upon a value change. | 1756 // upon a value change. |
| 1745 ScopedIndexUpdater<ParentIdAndHandleIndexer> updater(lock, kernel_, | 1757 ScopedIndexUpdater<ParentIdAndHandleIndexer> updater(lock, kernel_, |
| 1746 dir()->kernel_->parent_id_child_index); | 1758 dir()->kernel_->parent_id_child_index); |
| 1747 | 1759 |
| 1748 kernel_->put(IS_DEL, is_del); | 1760 kernel_->put(IS_DEL, is_del); |
| (...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2369 // ordering. | 2381 // ordering. |
| 2370 if (entry->ref(NEXT_ID).IsRoot() || | 2382 if (entry->ref(NEXT_ID).IsRoot() || |
| 2371 entry->ref(NEXT_ID) != entry->ref(PREV_ID)) { | 2383 entry->ref(NEXT_ID) != entry->ref(PREV_ID)) { |
| 2372 return entry; | 2384 return entry; |
| 2373 } | 2385 } |
| 2374 } | 2386 } |
| 2375 // There were no children in the linked list. | 2387 // There were no children in the linked list. |
| 2376 return NULL; | 2388 return NULL; |
| 2377 } | 2389 } |
| 2378 | 2390 |
| 2391 static void ChangeEntryIDAndUpdateChildren( | |
|
Nicolas Zea
2012/05/15 23:25:04
is there any point to keeping this function separa
rlarocque
2012/05/16 00:32:37
Probably not. I kept it separate because that's t
| |
| 2392 syncable::WriteTransaction* trans, | |
| 2393 syncable::MutableEntry* entry, | |
| 2394 const syncable::Id& new_id, | |
| 2395 syncable::Directory::ChildHandles* children) { | |
| 2396 syncable::Id old_id = entry->Get(ID); | |
| 2397 if (!entry->Put(ID, new_id)) { | |
| 2398 Entry old_entry(trans, GET_BY_ID, new_id); | |
| 2399 CHECK(old_entry.good()); | |
| 2400 LOG(FATAL) << "Attempt to change ID to " << new_id | |
| 2401 << " conflicts with existing entry.\n\n" | |
| 2402 << *entry << "\n\n" << old_entry; | |
| 2403 } | |
| 2404 if (entry->Get(IS_DIR)) { | |
| 2405 // Get all child entries of the old id. | |
| 2406 trans->directory()->GetChildHandlesById(trans, old_id, children); | |
| 2407 Directory::ChildHandles::iterator i = children->begin(); | |
| 2408 while (i != children->end()) { | |
| 2409 MutableEntry child_entry(trans, GET_BY_HANDLE, *i++); | |
| 2410 CHECK(child_entry.good()); | |
| 2411 // Use the unchecked setter here to avoid touching the child's NEXT_ID | |
| 2412 // and PREV_ID fields (which Put(PARENT_ID) would normally do to | |
| 2413 // maintain linked-list invariants). In this case, NEXT_ID and PREV_ID | |
| 2414 // among the children will be valid after the loop, since we update all | |
| 2415 // the children at once. | |
| 2416 child_entry.PutParentIdPropertyOnly(new_id); | |
| 2417 } | |
| 2418 } | |
| 2419 // Update Id references on the previous and next nodes in the sibling | |
| 2420 // order. Do this by reinserting into the linked list; the first | |
| 2421 // step in PutPredecessor is to Unlink from the existing order, which | |
| 2422 // will overwrite the stale Id value from the adjacent nodes. | |
| 2423 if (entry->Get(PREV_ID) == entry->Get(NEXT_ID) && | |
| 2424 entry->Get(PREV_ID) == old_id) { | |
| 2425 // We just need a shallow update to |entry|'s fields since it is already | |
| 2426 // self looped. | |
| 2427 entry->Put(NEXT_ID, new_id); | |
| 2428 entry->Put(PREV_ID, new_id); | |
| 2429 } else { | |
| 2430 entry->PutPredecessor(entry->Get(PREV_ID)); | |
| 2431 } | |
| 2432 } | |
| 2433 | |
| 2434 void ChangeEntryIDAndUpdateChildren( | |
| 2435 syncable::WriteTransaction* trans, | |
| 2436 syncable::MutableEntry* entry, | |
| 2437 const syncable::Id& new_id) { | |
| 2438 syncable::Directory::ChildHandles children; | |
| 2439 ChangeEntryIDAndUpdateChildren(trans, entry, new_id, &children); | |
| 2440 } | |
| 2441 | |
| 2379 } // namespace syncable | 2442 } // namespace syncable |
| OLD | NEW |