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/sessions/ordered_commit_set.h" 6 7 #include <algorithm> 8 9 #include "base/logging.h" 10 11 namespace syncer { 12 namespace sessions { 13 14 OrderedCommitSet::OrderedCommitSet(const ModelSafeRoutingInfo& routes) 15 : routes_(routes) { 16 } 17 18 OrderedCommitSet::~OrderedCommitSet() {} 19 20 void OrderedCommitSet::AddCommitItem(const int64 metahandle, 21 const syncable::Id& commit_id, 22 ModelType type) { 23 if (!HaveCommitItem(metahandle)) { 24 inserted_metahandles_.insert(metahandle); 25 metahandle_order_.push_back(metahandle); 26 commit_ids_.push_back(commit_id); 27 projections_[GetGroupForModelType(type, routes_)].push_back( 28 commit_ids_.size() - 1); 29 types_.push_back(type); 30 types_in_list_.Put(type); 31 } 32 } 33 34 const OrderedCommitSet::Projection& OrderedCommitSet::GetCommitIdProjection( 35 ModelSafeGroup group) const { 36 Projections::const_iterator i = projections_.find(group); 37 DCHECK(i != projections_.end()); 38 return i->second; 39 } 40 41 void OrderedCommitSet::Append(const OrderedCommitSet& other) { 42 for (size_t i = 0; i < other.Size(); ++i) { 43 CommitItem item = other.GetCommitItemAt(i); 44 AddCommitItem(item.meta, item.id, item.group); 45 } 46 } 47 48 void OrderedCommitSet::AppendReverse(const OrderedCommitSet& other) { 49 for (int i = other.Size() - 1; i >= 0; i--) { 50 CommitItem item = other.GetCommitItemAt(i); 51 AddCommitItem(item.meta, item.id, item.group); 52 } 53 } 54 55 void OrderedCommitSet::Truncate(size_t max_size) { 56 if (max_size < metahandle_order_.size()) { 57 for (size_t i = max_size; i < metahandle_order_.size(); ++i) { 58 inserted_metahandles_.erase(metahandle_order_[i]); 59 } 60 61 // Some projections may refer to indices that are getting chopped. 62 // Since projections are in increasing order, it's easy to fix. Except 63 // that you can't erase(..) using a reverse_iterator, so we use binary 64 // search to find the chop point. 65 Projections::iterator it = projections_.begin(); 66 for (; it != projections_.end(); ++it) { 67 // For each projection, chop off any indices larger than or equal to 68 // max_size by looking for max_size using binary search. 69 Projection& p = it->second; 70 Projection::iterator element = std::lower_bound(p.begin(), p.end(), 71 max_size); 72 if (element != p.end()) 73 p.erase(element, p.end()); 74 } 75 commit_ids_.resize(max_size); 76 metahandle_order_.resize(max_size); 77 types_.resize(max_size); 78 } 79 } 80 81 void OrderedCommitSet::Clear() { 82 inserted_metahandles_.clear(); 83 commit_ids_.clear(); 84 metahandle_order_.clear(); 85 for (Projections::iterator it = projections_.begin(); 86 it != projections_.end(); ++it) { 87 it->second.clear(); 88 } 89 types_.clear(); 90 types_in_list_.Clear(); 91 } 92 93 OrderedCommitSet::CommitItem OrderedCommitSet::GetCommitItemAt( 94 const size_t position) const { 95 DCHECK(position < Size()); 96 CommitItem return_item = {metahandle_order_[position], 97 commit_ids_[position], 98 types_[position]}; 99 return return_item; 100 } 101 102 bool OrderedCommitSet::HasBookmarkCommitId() const { 103 ModelSafeRoutingInfo::const_iterator group = routes_.find(BOOKMARKS); 104 if (group == routes_.end()) 105 return false; 106 Projections::const_iterator proj = projections_.find(group->second); 107 if (proj == projections_.end()) 108 return false; 109 DCHECK_LE(proj->second.size(), types_.size()); 110 for (size_t i = 0; i < proj->second.size(); i++) { 111 if (types_[proj->second[i]] == BOOKMARKS) 112 return true; 113 } 114 return false; 115 } 116 117 void OrderedCommitSet::operator=(const OrderedCommitSet& other) { 118 inserted_metahandles_ = other.inserted_metahandles_; 119 commit_ids_ = other.commit_ids_; 120 metahandle_order_ = other.metahandle_order_; 121 projections_ = other.projections_; 122 types_ = other.types_; 123 routes_ = other.routes_; 124 } 125 126 } // namespace sessions 127 } // namespace syncer 128 129