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 3 // found in the LICENSE file. 4 5 #include "sync/syncable/parent_child_index.h" 6 7 #include "base/stl_util.h" 8 9 #include "sync/syncable/entry_kernel.h" 10 #include "sync/syncable/syncable_id.h" 11 12 namespace syncer { 13 namespace syncable { 14 15 bool ChildComparator::operator()( 16 const syncable::EntryKernel* a, 17 const syncable::EntryKernel* b) const { 18 const UniquePosition& a_pos = a->ref(UNIQUE_POSITION); 19 const UniquePosition& b_pos = b->ref(UNIQUE_POSITION); 20 21 if (a_pos.IsValid() && b_pos.IsValid()) { 22 // Position is important to this type. 23 return a_pos.LessThan(b_pos); 24 } else if (a_pos.IsValid() && !b_pos.IsValid()) { 25 // TODO(rlarocque): Remove this case. 26 // An item with valid position as sibling of one with invalid position. 27 // We should not support this, but the tests rely on it. For now, just 28 // move all invalid position items to the right. 29 return true; 30 } else if (!a_pos.IsValid() && b_pos.IsValid()) { 31 // TODO(rlarocque): Remove this case. 32 // Mirror of the above case. 33 return false; 34 } else { 35 // Position doesn't matter. 36 DCHECK(!a->ref(UNIQUE_POSITION).IsValid()); 37 DCHECK(!b->ref(UNIQUE_POSITION).IsValid()); 38 return a->ref(ID) < b->ref(ID); 39 } 40 } 41 42 ParentChildIndex::ParentChildIndex() { 43 } 44 45 ParentChildIndex::~ParentChildIndex() { 46 STLDeleteContainerPairSecondPointers( 47 parent_children_map_.begin(), parent_children_map_.end()); 48 } 49 50 bool ParentChildIndex::ShouldInclude(const EntryKernel* entry) { 51 // This index excludes deleted items and the root item. The root 52 // item is excluded so that it doesn't show up as a child of itself. 53 return !entry->ref(IS_DEL) && !entry->ref(ID).IsRoot(); 54 } 55 56 bool ParentChildIndex::Insert(EntryKernel* entry) { 57 DCHECK(ShouldInclude(entry)); 58 59 const syncable::Id& parent_id = entry->ref(PARENT_ID); 60 OrderedChildSet* children = NULL; 61 ParentChildrenMap::iterator i = parent_children_map_.find(parent_id); 62 if (i != parent_children_map_.end()) { 63 children = i->second; 64 } else { 65 children = new OrderedChildSet(); 66 parent_children_map_.insert(std::make_pair(parent_id, children)); 67 } 68 69 return children->insert(entry).second; 70 } 71 72 // Like the other containers used to help support the syncable::Directory, this 73 // one does not own any EntryKernels. This function removes references to the 74 // given EntryKernel but does not delete it. 75 void ParentChildIndex::Remove(EntryKernel* e) { 76 ParentChildrenMap::iterator parent = 77 parent_children_map_.find(e->ref(PARENT_ID)); 78 DCHECK(parent != parent_children_map_.end()); 79 80 OrderedChildSet* children = parent->second; 81 OrderedChildSet::iterator j = children->find(e); 82 DCHECK(j != children->end()); 83 84 children->erase(j); 85 if (children->empty()) { 86 delete children; 87 parent_children_map_.erase(parent); 88 } 89 } 90 91 bool ParentChildIndex::Contains(EntryKernel *e) const { 92 const syncable::Id& parent_id = e->ref(PARENT_ID); 93 ParentChildrenMap::const_iterator parent = 94 parent_children_map_.find(parent_id); 95 if (parent == parent_children_map_.end()) { 96 return false; 97 } 98 const OrderedChildSet* children = parent->second; 99 DCHECK(children && !children->empty()); 100 return children->count(e) > 0; 101 } 102 103 const OrderedChildSet* ParentChildIndex::GetChildren(const syncable::Id& id) { 104 ParentChildrenMap::iterator parent = parent_children_map_.find(id); 105 if (parent == parent_children_map_.end()) { 106 return NULL; 107 } 108 109 // A successful lookup implies at least some children exist. 110 DCHECK(!parent->second->empty()); 111 return parent->second; 112 } 113 114 } // namespace syncable 115 } // namespace syncer 116