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( |
| 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 |