Chromium Code Reviews| 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 1747 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1758 int64 result; | 1758 int64 result; |
| 1759 { | 1759 { |
| 1760 ScopedKernelLock lock(this); | 1760 ScopedKernelLock lock(this); |
| 1761 result = (kernel_->persisted_info.next_id)--; | 1761 result = (kernel_->persisted_info.next_id)--; |
| 1762 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; | 1762 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; |
| 1763 } | 1763 } |
| 1764 DCHECK_LT(result, 0); | 1764 DCHECK_LT(result, 0); |
| 1765 return Id::CreateFromClientString(base::Int64ToString(result)); | 1765 return Id::CreateFromClientString(base::Int64ToString(result)); |
| 1766 } | 1766 } |
| 1767 | 1767 |
| 1768 bool Directory::HasChildren(BaseTransaction* trans, const Id& id) { | |
| 1769 ScopedKernelLock lock(this); | |
| 1770 return (GetPossibleFirstChild(lock, id) != NULL); | |
| 1771 } | |
| 1772 | |
| 1768 Id Directory::GetFirstChildId(BaseTransaction* trans, | 1773 Id Directory::GetFirstChildId(BaseTransaction* trans, |
| 1769 const Id& parent_id) { | 1774 const Id& parent_id) { |
| 1770 ScopedKernelLock lock(this); | 1775 ScopedKernelLock lock(this); |
| 1771 // We can use the server positional ordering as a hint because it's generally | 1776 EntryKernel* entry = GetPossibleFirstChild(lock, parent_id); |
| 1772 // in sync with the local (linked-list) positional ordering, and we have an | 1777 if (!entry) |
| 1773 // index on it. | 1778 return Id(); |
| 1774 ParentIdChildIndex::iterator candidate = | 1779 |
| 1775 GetParentChildIndexLowerBound(lock, parent_id); | 1780 // Walk to the front of the list; the server position ordering |
| 1776 ParentIdChildIndex::iterator end_range = | 1781 // is commonly identical to the linked-list ordering, but pending |
| 1777 GetParentChildIndexUpperBound(lock, parent_id); | 1782 // unsynced or unapplied items may diverge. |
| 1778 for (; candidate != end_range; ++candidate) { | 1783 while (!entry->ref(PREV_ID).IsRoot()) { |
| 1779 EntryKernel* entry = *candidate; | 1784 // TODO(akalin): Gracefully handle GetEntryById returning NULL |
| 1780 // Filter out self-looped items, which are temporarily not in the child | 1785 // (http://crbug.com/100907). |
| 1781 // ordering. | 1786 entry = GetEntryById(entry->ref(PREV_ID), &lock); |
| 1782 if (entry->ref(PREV_ID).IsRoot() || | |
| 1783 entry->ref(PREV_ID) != entry->ref(NEXT_ID)) { | |
| 1784 // Walk to the front of the list; the server position ordering | |
| 1785 // is commonly identical to the linked-list ordering, but pending | |
| 1786 // unsynced or unapplied items may diverge. | |
| 1787 while (!entry->ref(PREV_ID).IsRoot()) { | |
| 1788 entry = GetEntryById(entry->ref(PREV_ID), &lock); | |
| 1789 } | |
| 1790 return entry->ref(ID); | |
| 1791 } | |
| 1792 } | 1787 } |
| 1793 // There were no children in the linked list. | 1788 return entry->ref(ID); |
| 1794 return Id(); | |
| 1795 } | 1789 } |
| 1796 | 1790 |
| 1797 Id Directory::GetLastChildId(BaseTransaction* trans, | 1791 Id Directory::GetLastChildId(BaseTransaction* trans, |
| 1798 const Id& parent_id) { | 1792 const Id& parent_id) { |
| 1799 ScopedKernelLock lock(this); | 1793 ScopedKernelLock lock(this); |
| 1800 // We can use the server positional ordering as a hint because it's generally | 1794 // We can use the server positional ordering as a hint because it's generally |
| 1801 // in sync with the local (linked-list) positional ordering, and we have an | 1795 // in sync with the local (linked-list) positional ordering, and we have an |
| 1802 // index on it. | 1796 // index on it. |
| 1803 ParentIdChildIndex::iterator begin_range = | 1797 ParentIdChildIndex::iterator begin_range = |
| 1804 GetParentChildIndexLowerBound(lock, parent_id); | 1798 GetParentChildIndexLowerBound(lock, parent_id); |
| 1805 ParentIdChildIndex::iterator candidate = | 1799 ParentIdChildIndex::iterator candidate = |
| 1806 GetParentChildIndexUpperBound(lock, parent_id); | 1800 GetParentChildIndexUpperBound(lock, parent_id); |
| 1807 | 1801 |
| 1808 while (begin_range != candidate) { | 1802 while (begin_range != candidate) { |
| 1809 --candidate; | 1803 --candidate; |
| 1810 EntryKernel* entry = *candidate; | 1804 EntryKernel* entry = *candidate; |
| 1811 | 1805 |
| 1812 // Filter out self-looped items, which are temporarily not in the child | 1806 // Filter out self-looped items, which are temporarily not in the child |
| 1813 // ordering. | 1807 // ordering. |
| 1814 if (entry->ref(NEXT_ID).IsRoot() || | 1808 if (entry->ref(NEXT_ID).IsRoot() || |
| 1815 entry->ref(NEXT_ID) != entry->ref(PREV_ID)) { | 1809 entry->ref(NEXT_ID) != entry->ref(PREV_ID)) { |
| 1816 // Walk to the back of the list; the server position ordering | 1810 // Walk to the back of the list; the server position ordering |
| 1817 // is commonly identical to the linked-list ordering, but pending | 1811 // is commonly identical to the linked-list ordering, but pending |
| 1818 // unsynced or unapplied items may diverge. | 1812 // unsynced or unapplied items may diverge. |
| 1819 while (!entry->ref(NEXT_ID).IsRoot()) | 1813 while (!entry->ref(NEXT_ID).IsRoot()) |
| 1814 // TODO(akalin): Gracefully handle GetEntryById returning NULL | |
| 1815 // (http://crbug.com/100907). | |
| 1820 entry = GetEntryById(entry->ref(NEXT_ID), &lock); | 1816 entry = GetEntryById(entry->ref(NEXT_ID), &lock); |
| 1821 return entry->ref(ID); | 1817 return entry->ref(ID); |
| 1822 } | 1818 } |
| 1823 } | 1819 } |
| 1824 // There were no children in the linked list. | 1820 // There were no children in the linked list. |
| 1825 return Id(); | 1821 return Id(); |
| 1826 } | 1822 } |
| 1827 | 1823 |
| 1828 Id Directory::ComputePrevIdFromServerPosition( | 1824 Id Directory::ComputePrevIdFromServerPosition( |
| 1829 const EntryKernel* entry, | 1825 const EntryKernel* entry, |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1954 Directory::ParentIdChildIndex::iterator | 1950 Directory::ParentIdChildIndex::iterator |
| 1955 Directory::GetParentChildIndexLowerBound(const ScopedKernelLock& lock, | 1951 Directory::GetParentChildIndexLowerBound(const ScopedKernelLock& lock, |
| 1956 const Id& parent_id) { | 1952 const Id& parent_id) { |
| 1957 // Peg the parent ID, and use the least values for the remaining | 1953 // Peg the parent ID, and use the least values for the remaining |
| 1958 // index variables. | 1954 // index variables. |
| 1959 return LocateInParentChildIndex(lock, parent_id, | 1955 return LocateInParentChildIndex(lock, parent_id, |
| 1960 std::numeric_limits<int64>::min(), | 1956 std::numeric_limits<int64>::min(), |
| 1961 Id::GetLeastIdForLexicographicComparison()); | 1957 Id::GetLeastIdForLexicographicComparison()); |
| 1962 } | 1958 } |
| 1963 | 1959 |
| 1964 | |
| 1965 Directory::ParentIdChildIndex::iterator | 1960 Directory::ParentIdChildIndex::iterator |
| 1966 Directory::GetParentChildIndexUpperBound(const ScopedKernelLock& lock, | 1961 Directory::GetParentChildIndexUpperBound(const ScopedKernelLock& lock, |
| 1967 const Id& parent_id) { | 1962 const Id& parent_id) { |
| 1968 // The upper bound of |parent_id|'s range is the lower | 1963 // The upper bound of |parent_id|'s range is the lower |
| 1969 // bound of |++parent_id|'s range. | 1964 // bound of |++parent_id|'s range. |
| 1970 return GetParentChildIndexLowerBound(lock, | 1965 return GetParentChildIndexLowerBound(lock, |
| 1971 parent_id.GetLexicographicSuccessor()); | 1966 parent_id.GetLexicographicSuccessor()); |
| 1972 } | 1967 } |
| 1973 | 1968 |
| 1974 void Directory::AppendChildHandles(const ScopedKernelLock& lock, | 1969 void Directory::AppendChildHandles(const ScopedKernelLock& lock, |
| 1975 const Id& parent_id, | 1970 const Id& parent_id, |
| 1976 Directory::ChildHandles* result) { | 1971 Directory::ChildHandles* result) { |
| 1977 typedef ParentIdChildIndex::iterator iterator; | 1972 typedef ParentIdChildIndex::iterator iterator; |
| 1978 CHECK(result); | 1973 CHECK(result); |
| 1979 for (iterator i = GetParentChildIndexLowerBound(lock, parent_id), | 1974 for (iterator i = GetParentChildIndexLowerBound(lock, parent_id), |
| 1980 end = GetParentChildIndexUpperBound(lock, parent_id); | 1975 end = GetParentChildIndexUpperBound(lock, parent_id); |
| 1981 i != end; ++i) { | 1976 i != end; ++i) { |
| 1982 DCHECK_EQ(parent_id, (*i)->ref(PARENT_ID)); | 1977 DCHECK_EQ(parent_id, (*i)->ref(PARENT_ID)); |
| 1983 result->push_back((*i)->ref(META_HANDLE)); | 1978 result->push_back((*i)->ref(META_HANDLE)); |
| 1984 } | 1979 } |
| 1985 } | 1980 } |
| 1986 | 1981 |
| 1982 EntryKernel* Directory::GetPossibleFirstChild( | |
|
rlarocque
2011/10/26 22:43:18
nit:
Could we name this "GetFirstChildInServerOrde
akalin
2011/10/27 00:19:21
Meh, I kinda disagree. The callers of this class
| |
| 1983 const ScopedKernelLock& lock, const Id& parent_id) { | |
| 1984 // We can use the server positional ordering as a hint because it's generally | |
| 1985 // in sync with the local (linked-list) positional ordering, and we have an | |
| 1986 // index on it. | |
| 1987 ParentIdChildIndex::iterator candidate = | |
| 1988 GetParentChildIndexLowerBound(lock, parent_id); | |
| 1989 ParentIdChildIndex::iterator end_range = | |
| 1990 GetParentChildIndexUpperBound(lock, parent_id); | |
| 1991 for (; candidate != end_range; ++candidate) { | |
| 1992 EntryKernel* entry = *candidate; | |
| 1993 // Filter out self-looped items, which are temporarily not in the child | |
| 1994 // ordering. | |
| 1995 if (entry->ref(PREV_ID).IsRoot() || | |
| 1996 entry->ref(PREV_ID) != entry->ref(NEXT_ID)) { | |
| 1997 return entry; | |
| 1998 } | |
| 1999 } | |
| 2000 // There were no children in the linked list. | |
| 2001 return NULL; | |
| 2002 } | |
| 2003 | |
| 1987 } // namespace syncable | 2004 } // namespace syncable |
| OLD | NEW |