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 |