| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "chrome/browser/sync/syncable/syncable.h" | 5 #include "chrome/browser/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 1699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1710 LOG(ERROR) << "Predecessor is not good : " | 1710 LOG(ERROR) << "Predecessor is not good : " |
| 1711 << predecessor_id.GetServerId(); | 1711 << predecessor_id.GetServerId(); |
| 1712 return false; | 1712 return false; |
| 1713 } | 1713 } |
| 1714 if (predecessor.Get(PARENT_ID) != Get(PARENT_ID)) | 1714 if (predecessor.Get(PARENT_ID) != Get(PARENT_ID)) |
| 1715 return false; | 1715 return false; |
| 1716 successor_id = predecessor.Get(NEXT_ID); | 1716 successor_id = predecessor.Get(NEXT_ID); |
| 1717 predecessor.Put(NEXT_ID, Get(ID)); | 1717 predecessor.Put(NEXT_ID, Get(ID)); |
| 1718 } else { | 1718 } else { |
| 1719 syncable::Directory* dir = trans()->directory(); | 1719 syncable::Directory* dir = trans()->directory(); |
| 1720 successor_id = dir->GetFirstChildId(trans(), Get(PARENT_ID)); | 1720 if (!dir->GetFirstChildId(trans(), Get(PARENT_ID), &successor_id)) { |
| 1721 return false; |
| 1722 } |
| 1721 } | 1723 } |
| 1722 if (!successor_id.IsRoot()) { | 1724 if (!successor_id.IsRoot()) { |
| 1723 MutableEntry successor(write_transaction(), GET_BY_ID, successor_id); | 1725 MutableEntry successor(write_transaction(), GET_BY_ID, successor_id); |
| 1724 if (!successor.good()) { | 1726 if (!successor.good()) { |
| 1725 LOG(ERROR) << "Successor is not good: " | 1727 LOG(ERROR) << "Successor is not good: " |
| 1726 << successor_id.GetServerId(); | 1728 << successor_id.GetServerId(); |
| 1727 return false; | 1729 return false; |
| 1728 } | 1730 } |
| 1729 if (successor.Get(PARENT_ID) != Get(PARENT_ID)) | 1731 if (successor.Get(PARENT_ID) != Get(PARENT_ID)) |
| 1730 return false; | 1732 return false; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1763 } | 1765 } |
| 1764 DCHECK_LT(result, 0); | 1766 DCHECK_LT(result, 0); |
| 1765 return Id::CreateFromClientString(base::Int64ToString(result)); | 1767 return Id::CreateFromClientString(base::Int64ToString(result)); |
| 1766 } | 1768 } |
| 1767 | 1769 |
| 1768 bool Directory::HasChildren(BaseTransaction* trans, const Id& id) { | 1770 bool Directory::HasChildren(BaseTransaction* trans, const Id& id) { |
| 1769 ScopedKernelLock lock(this); | 1771 ScopedKernelLock lock(this); |
| 1770 return (GetPossibleFirstChild(lock, id) != NULL); | 1772 return (GetPossibleFirstChild(lock, id) != NULL); |
| 1771 } | 1773 } |
| 1772 | 1774 |
| 1773 Id Directory::GetFirstChildId(BaseTransaction* trans, | 1775 bool Directory::GetFirstChildId(BaseTransaction* trans, |
| 1774 const Id& parent_id) { | 1776 const Id& parent_id, |
| 1777 Id* first_child_id) { |
| 1775 ScopedKernelLock lock(this); | 1778 ScopedKernelLock lock(this); |
| 1776 EntryKernel* entry = GetPossibleFirstChild(lock, parent_id); | 1779 EntryKernel* entry = GetPossibleFirstChild(lock, parent_id); |
| 1777 if (!entry) | 1780 if (!entry) { |
| 1778 return Id(); | 1781 *first_child_id = Id(); |
| 1782 return true; |
| 1783 } |
| 1779 | 1784 |
| 1780 // Walk to the front of the list; the server position ordering | 1785 // Walk to the front of the list; the server position ordering |
| 1781 // is commonly identical to the linked-list ordering, but pending | 1786 // is commonly identical to the linked-list ordering, but pending |
| 1782 // unsynced or unapplied items may diverge. | 1787 // unsynced or unapplied items may diverge. |
| 1783 while (!entry->ref(PREV_ID).IsRoot()) { | 1788 while (!entry->ref(PREV_ID).IsRoot()) { |
| 1784 // TODO(akalin): Gracefully handle GetEntryById returning NULL | |
| 1785 // (http://crbug.com/100907). | |
| 1786 entry = GetEntryById(entry->ref(PREV_ID), &lock); | 1789 entry = GetEntryById(entry->ref(PREV_ID), &lock); |
| 1790 if (!entry) { |
| 1791 *first_child_id = Id(); |
| 1792 return false; |
| 1793 } |
| 1787 } | 1794 } |
| 1788 return entry->ref(ID); | 1795 *first_child_id = entry->ref(ID); |
| 1796 return true; |
| 1789 } | 1797 } |
| 1790 | 1798 |
| 1791 Id Directory::GetLastChildId(BaseTransaction* trans, | 1799 bool Directory::GetLastChildIdForTest( |
| 1792 const Id& parent_id) { | 1800 BaseTransaction* trans, const Id& parent_id, Id* last_child_id) { |
| 1793 ScopedKernelLock lock(this); | 1801 ScopedKernelLock lock(this); |
| 1794 // We can use the server positional ordering as a hint because it's generally | 1802 EntryKernel* entry = GetPossibleLastChildForTest(lock, parent_id); |
| 1795 // in sync with the local (linked-list) positional ordering, and we have an | 1803 if (!entry) { |
| 1796 // index on it. | 1804 *last_child_id = Id(); |
| 1797 ParentIdChildIndex::iterator begin_range = | 1805 return true; |
| 1798 GetParentChildIndexLowerBound(lock, parent_id); | 1806 } |
| 1799 ParentIdChildIndex::iterator candidate = | |
| 1800 GetParentChildIndexUpperBound(lock, parent_id); | |
| 1801 | 1807 |
| 1802 while (begin_range != candidate) { | 1808 // Walk to the back of the list; the server position ordering |
| 1803 --candidate; | 1809 // is commonly identical to the linked-list ordering, but pending |
| 1804 EntryKernel* entry = *candidate; | 1810 // unsynced or unapplied items may diverge. |
| 1805 | 1811 while (!entry->ref(NEXT_ID).IsRoot()) { |
| 1806 // Filter out self-looped items, which are temporarily not in the child | 1812 entry = GetEntryById(entry->ref(NEXT_ID), &lock); |
| 1807 // ordering. | 1813 if (!entry) { |
| 1808 if (entry->ref(NEXT_ID).IsRoot() || | 1814 *last_child_id = Id(); |
| 1809 entry->ref(NEXT_ID) != entry->ref(PREV_ID)) { | 1815 return false; |
| 1810 // Walk to the back of the list; the server position ordering | |
| 1811 // is commonly identical to the linked-list ordering, but pending | |
| 1812 // unsynced or unapplied items may diverge. | |
| 1813 while (!entry->ref(NEXT_ID).IsRoot()) | |
| 1814 // TODO(akalin): Gracefully handle GetEntryById returning NULL | |
| 1815 // (http://crbug.com/100907). | |
| 1816 entry = GetEntryById(entry->ref(NEXT_ID), &lock); | |
| 1817 return entry->ref(ID); | |
| 1818 } | 1816 } |
| 1819 } | 1817 } |
| 1820 // There were no children in the linked list. | 1818 |
| 1821 return Id(); | 1819 *last_child_id = entry->ref(ID); |
| 1820 return true; |
| 1822 } | 1821 } |
| 1823 | 1822 |
| 1824 Id Directory::ComputePrevIdFromServerPosition( | 1823 Id Directory::ComputePrevIdFromServerPosition( |
| 1825 const EntryKernel* entry, | 1824 const EntryKernel* entry, |
| 1826 const syncable::Id& parent_id) { | 1825 const syncable::Id& parent_id) { |
| 1827 ScopedKernelLock lock(this); | 1826 ScopedKernelLock lock(this); |
| 1828 | 1827 |
| 1829 // Find the natural insertion point in the parent_id_child_index, and | 1828 // Find the natural insertion point in the parent_id_child_index, and |
| 1830 // work back from there, filtering out ineligible candidates. | 1829 // work back from there, filtering out ineligible candidates. |
| 1831 ParentIdChildIndex::iterator sibling = LocateInParentChildIndex(lock, | 1830 ParentIdChildIndex::iterator sibling = LocateInParentChildIndex(lock, |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1994 // ordering. | 1993 // ordering. |
| 1995 if (entry->ref(PREV_ID).IsRoot() || | 1994 if (entry->ref(PREV_ID).IsRoot() || |
| 1996 entry->ref(PREV_ID) != entry->ref(NEXT_ID)) { | 1995 entry->ref(PREV_ID) != entry->ref(NEXT_ID)) { |
| 1997 return entry; | 1996 return entry; |
| 1998 } | 1997 } |
| 1999 } | 1998 } |
| 2000 // There were no children in the linked list. | 1999 // There were no children in the linked list. |
| 2001 return NULL; | 2000 return NULL; |
| 2002 } | 2001 } |
| 2003 | 2002 |
| 2003 EntryKernel* Directory::GetPossibleLastChildForTest( |
| 2004 const ScopedKernelLock& lock, const Id& parent_id) { |
| 2005 // We can use the server positional ordering as a hint because it's generally |
| 2006 // in sync with the local (linked-list) positional ordering, and we have an |
| 2007 // index on it. |
| 2008 ParentIdChildIndex::iterator begin_range = |
| 2009 GetParentChildIndexLowerBound(lock, parent_id); |
| 2010 ParentIdChildIndex::iterator candidate = |
| 2011 GetParentChildIndexUpperBound(lock, parent_id); |
| 2012 |
| 2013 while (begin_range != candidate) { |
| 2014 --candidate; |
| 2015 EntryKernel* entry = *candidate; |
| 2016 |
| 2017 // Filter out self-looped items, which are temporarily not in the child |
| 2018 // ordering. |
| 2019 if (entry->ref(NEXT_ID).IsRoot() || |
| 2020 entry->ref(NEXT_ID) != entry->ref(PREV_ID)) { |
| 2021 return entry; |
| 2022 } |
| 2023 } |
| 2024 // There were no children in the linked list. |
| 2025 return NULL; |
| 2026 } |
| 2027 |
| 2004 } // namespace syncable | 2028 } // namespace syncable |
| OLD | NEW |