13 #ifndef STXXL_CONTAINERS_BTREE_BTREE_HEADER
14 #define STXXL_CONTAINERS_BTREE_BTREE_HEADER
30 template <
class KeyType,
44 typedef btree<KeyType, DataType, CompareType,
45 RawNodeSize, RawLeafSize, PDAllocStrategy>
self_type;
81 min_node_size = node_type::min_size,
82 max_node_size = node_type::max_size,
83 min_leaf_size = leaf_type::min_size,
84 max_leaf_size = leaf_type::max_size
108 std::pair<root_node_iterator_type, bool> result =
109 m_root_node.insert(splitter);
112 if (m_root_node.size() > max_node_size)
114 STXXL_VERBOSE1(
"btree::insert_into_root, overflow happened, splitting");
117 node_type* left_node = m_node_cache.get_new_node(left_bid);
120 node_type* right_node = m_node_cache.get_new_node(right_bid);
135 left_node->
block().
info.cur_size = (
unsigned int)half;
147 key_type right_key = (right_node->
block()[right_size - 1]).first;
149 assert(old_size == right_node->
size() + left_node->
size());
158 if (m_node_cache.size() < (m_height - 1))
160 STXXL_THROW2(std::runtime_error,
"btree::bulk_construction",
161 "The height of the tree (" << m_height <<
") has exceeded the required capacity (" << (m_node_cache.size() + 1) <<
") of the node cache. Increase the node cache size.");
166 template <
class CacheType>
169 typedef typename CacheType::node_type local_node_type;
170 typedef typename local_node_type::bid_type local_bid_type;
173 if (uit->first == key_compare::max_value())
176 assert(uit != m_root_node.begin());
184 assert(right_it != m_root_node.end());
188 local_bid_type left_bid = (local_bid_type)left_it->second;
189 local_bid_type right_bid = (local_bid_type)right_it->second;
190 local_node_type* left_node = cache.get_node(left_bid,
true);
191 local_node_type* right_node = cache.get_node(right_bid,
true);
193 const unsigned_type total_size = left_node->size() + right_node->size();
194 if (total_size <= right_node->max_nelements())
199 right_node->fuse(*left_node);
201 cache.unfix_node(right_bid);
203 cache.delete_node(left_bid);
206 m_root_node.erase(left_it);
212 key_type new_splitter = right_node->balance(*left_node);
215 m_root_node.erase(left_it);
220 cache.unfix_node(left_bid);
221 cache.unfix_node(right_bid);
228 leaf_type* new_leaf = m_leaf_cache.get_new_node(new_bid);
230 m_end_iterator = new_leaf->
end();
242 it != m_root_node.end(); ++it)
251 it != m_root_node.end(); ++it)
262 template <
class InputIterator>
264 double node_fill_factor,
double leaf_fill_factor)
266 assert(node_fill_factor >= 0.5);
267 assert(leaf_fill_factor >= 0.5);
268 key_type last_key = key_compare::max_value();
270 typedef std::pair<key_type, node_bid_type> key_bid_pair;
272 key_bid_pair, 1, 1, node_block_type::raw_size
273 >::result key_bid_vector_type;
275 key_bid_vector_type bids;
278 leaf_type* leaf = m_leaf_cache.get_new_node(new_bid);
288 if (m_key_compare(begin->first, last_key) || m_key_compare(last_key, begin->first))
291 if (leaf->
size() == max_leaf_elements)
296 leaf_type* new_leaf = m_leaf_cache.get_new_node(new_bid);
305 last_key = begin->first;
318 leaf->
fuse(*left_leaf);
319 m_leaf_cache.delete_node((
leaf_bid_type)(bids.back().second));
327 bids.back().first = new_splitter;
334 m_end_iterator = leaf->
end();
336 bids.push_back(key_bid_pair(key_compare::max_value(), (
node_bid_type)new_bid));
339 double(max_node_size) * node_fill_factor
343 while (bids.size() > node_type::max_nelements())
345 key_bid_vector_type parent_bids;
348 assert(nparents >= 2);
350 <<
" bids.size=" << bids.size()
351 <<
" nparents=" << nparents
352 <<
" max_node_elements=" << max_node_elements
353 <<
" node_type::max_nelements=" << node_type::max_nelements());
355 for (
typename key_bid_vector_type::const_iterator it = bids.begin();
359 node_type* node = m_node_cache.get_new_node(new_bid);
363 cnt < max_node_elements && it != bids.end(); ++cnt, ++it)
373 assert(it == bids.end());
374 assert(!parent_bids.empty());
376 node_type* left_node = m_node_cache.get_node(parent_bids.back().second);
382 <<
" left_node.size=" << left_node->size()
383 <<
" node.size=" << node->
size());
385 node->
fuse(*left_node);
386 m_node_cache.delete_node(parent_bids.back().second);
387 parent_bids.pop_back();
393 <<
" left_node.size=" << left_node->size()
394 <<
" node.size=" << node->
size());
397 parent_bids.back().first = new_splitter;
400 <<
" left_node.size=" << left_node->size()
401 <<
" node.size=" << node->
size());
403 assert(!left_node->overflows() && !left_node->underflows());
408 parent_bids.push_back(key_bid_pair(node->
back().first, new_bid));
412 <<
" bids.size()=" << bids.size());
414 std::swap(parent_bids, bids);
416 assert(nparents == bids.size() || (nparents - 1) == bids.size());
420 if (m_node_cache.size() < (m_height - 1))
422 STXXL_THROW2(std::runtime_error,
"btree::bulk_construction",
423 "The height of the tree (" << m_height <<
") has exceeded the required capacity (" << (m_node_cache.size() + 1) <<
") of the node cache. Increase the node cache size.");
427 m_root_node.insert(bids.begin(), bids.end());
429 STXXL_VERBOSE1(
"btree bulk root_node_.size()=" << m_root_node.size());
435 : m_node_cache(node_cache_size_in_bytes, this, m_key_compare),
436 m_leaf_cache(leaf_cache_size_in_bytes, this, m_key_compare),
437 m_iterator_map(this),
440 m_prefetching_enabled(true),
457 : m_key_compare(key_compare),
458 m_node_cache(node_cache_size_in_bytes, this, m_key_compare),
459 m_leaf_cache(leaf_cache_size_in_bytes, this, m_key_compare),
460 m_iterator_map(this),
463 m_prefetching_enabled(true),
477 deallocate_children();
503 assert(!m_root_node.empty());
504 assert(it != m_root_node.end());
511 std::pair<key_type, leaf_bid_type> splitter;
512 std::pair<iterator, bool> result = leaf->
insert(x, splitter);
518 if (!(m_key_compare(key_compare::max_value(), splitter.first) ||
519 m_key_compare(splitter.first, key_compare::max_value())))
525 insert_into_root(std::make_pair(splitter.first,
node_bid_type(splitter.second)));
527 assert(m_leaf_cache.nfixed() == 0);
528 assert(m_node_cache.nfixed() == 0);
536 std::pair<key_type, node_bid_type> splitter;
537 std::pair<iterator, bool> result = node->
insert(x, m_height - 1, splitter);
543 if (!(m_key_compare(key_compare::max_value(), splitter.first) ||
544 m_key_compare(splitter.first, key_compare::max_value())))
550 insert_into_root(splitter);
552 assert(m_leaf_cache.nfixed() == 0);
553 assert(m_node_cache.nfixed() == 0);
561 assert(it != m_root_node.end());
569 assert(m_leaf_cache.nfixed() == 0);
570 assert(m_node_cache.nfixed() == 0);
571 return leaf->
begin();
581 assert(m_leaf_cache.nfixed() == 0);
582 assert(m_node_cache.nfixed() == 0);
590 assert(it != m_root_node.end());
597 assert(m_leaf_cache.nfixed() == 0);
598 assert(m_node_cache.nfixed() == 0);
599 return leaf->
begin();
608 assert(m_leaf_cache.nfixed() == 0);
609 assert(m_node_cache.nfixed() == 0);
615 return m_end_iterator;
620 return m_end_iterator;
631 assert(it != m_root_node.end());
640 assert(result == end() || result->first == k);
641 assert(m_leaf_cache.nfixed() == 0);
642 assert(m_node_cache.nfixed() == 0);
653 assert(result == end() || result->first == k);
654 assert(m_leaf_cache.nfixed() == 0);
655 assert(m_node_cache.nfixed() == 0);
662 assert(it != m_root_node.end());
671 assert(result == end() || result->first == k);
672 assert(m_leaf_cache.nfixed() == 0);
673 assert(m_node_cache.nfixed() == 0);
684 assert(result == end() || result->first == k);
685 assert(m_leaf_cache.nfixed() == 0);
686 assert(m_node_cache.nfixed() == 0);
693 assert(it != m_root_node.end());
702 assert(m_leaf_cache.nfixed() == 0);
703 assert(m_node_cache.nfixed() == 0);
714 assert(m_leaf_cache.nfixed() == 0);
715 assert(m_node_cache.nfixed() == 0);
722 assert(it != m_root_node.end());
732 assert(m_leaf_cache.nfixed() == 0);
733 assert(m_node_cache.nfixed() == 0);
744 assert(m_leaf_cache.nfixed() == 0);
745 assert(m_node_cache.nfixed() == 0);
752 assert(it != m_root_node.end());
762 assert(m_leaf_cache.nfixed() == 0);
763 assert(m_node_cache.nfixed() == 0);
774 assert(m_leaf_cache.nfixed() == 0);
775 assert(m_node_cache.nfixed() == 0);
782 assert(it != m_root_node.end());
792 assert(m_leaf_cache.nfixed() == 0);
793 assert(m_node_cache.nfixed() == 0);
804 assert(m_leaf_cache.nfixed() == 0);
805 assert(m_node_cache.nfixed() == 0);
815 if (l == end() || m_key_compare(k, l->first))
817 return std::pair<iterator, iterator>(l, l);
823 assert(m_leaf_cache.nfixed() == 0);
824 assert(m_node_cache.nfixed() == 0);
827 return std::pair<iterator, iterator>(l, u);
836 if (l == end() || m_key_compare(k, l->first))
838 return std::pair<const_iterator, const_iterator>(l, l);
844 assert(m_leaf_cache.nfixed() == 0);
845 assert(m_node_cache.nfixed() == 0);
847 return std::pair<const_iterator, const_iterator>(l, u);
853 assert(it != m_root_node.end());
863 assert(m_leaf_cache.nfixed() == 0);
864 assert(m_node_cache.nfixed() == 0);
866 if ((!Leaf->
underflows()) || m_root_node.size() == 1)
871 fuse_or_balance(it, m_leaf_cache);
873 assert(m_leaf_cache.nfixed() == 0);
874 assert(m_node_cache.nfixed() == 0);
881 assert(m_root_node.size() >= 2);
884 size_type result = node->erase(k, m_height - 1);
887 assert(m_leaf_cache.nfixed() == 0);
888 assert(m_node_cache.nfixed() == 0);
889 if (!node->underflows())
894 fuse_or_balance(it, m_node_cache);
896 if (m_root_node.size() == 1)
900 it = m_root_node.begin();
902 assert(it->first == key_compare::max_value());
905 assert(root_node->
back().first == key_compare::max_value());
907 m_root_node.insert(root_node->
block().
begin(),
910 m_node_cache.delete_node(root_bid);
915 assert(m_leaf_cache.nfixed() == 0);
916 assert(m_node_cache.nfixed() == 0);
923 if (
find(k) == end())
931 assert(pos != end());
938 assert(size() == old_size - 1);
944 return insert(x).first;
949 deallocate_children();
957 assert(m_leaf_cache.nfixed() == 0);
958 assert(m_node_cache.nfixed() == 0);
961 template <
class InputIterator>
962 void insert(InputIterator b, InputIterator e)
970 template <
class InputIterator>
976 bool range_sorted =
false,
977 double node_fill_factor = 0.75,
978 double leaf_fill_factor = 0.6)
980 m_node_cache(node_cache_size_in_bytes, this, m_key_compare),
981 m_leaf_cache(leaf_cache_size_in_bytes, this, m_key_compare),
982 m_iterator_map(this),
985 m_prefetching_enabled(true),
992 if (range_sorted ==
false)
996 assert(m_leaf_cache.nfixed() == 0);
997 assert(m_node_cache.nfixed() == 0);
1001 bulk_construction(begin, end, node_fill_factor, leaf_fill_factor);
1002 assert(m_leaf_cache.nfixed() == 0);
1003 assert(m_node_cache.nfixed() == 0);
1006 template <
class InputIterator>
1011 bool range_sorted =
false,
1012 double node_fill_factor = 0.75,
1013 double leaf_fill_factor = 0.6)
1014 : m_node_cache(node_cache_size_in_bytes, this, m_key_compare),
1015 m_leaf_cache(leaf_cache_size_in_bytes, this, m_key_compare),
1016 m_iterator_map(this),
1019 m_prefetching_enabled(true),
1026 if (range_sorted ==
false)
1028 create_empty_leaf();
1030 assert(m_leaf_cache.nfixed() == 0);
1031 assert(m_node_cache.nfixed() == 0);
1035 bulk_construction(begin, end, node_fill_factor, leaf_fill_factor);
1036 assert(m_leaf_cache.nfixed() == 0);
1037 assert(m_node_cache.nfixed() == 0);
1042 if (first == begin() && last == end())
1045 while (first != last)
1051 return m_key_compare;
1068 std::swap(m_size, obj.
m_size);
1076 m_prefetching_enabled =
true;
1080 m_prefetching_enabled =
false;
1084 return m_prefetching_enabled;
1089 o <<
"Node cache statistics:" << std::endl;
1090 m_node_cache.print_statistics(o);
1091 o <<
"Leaf cache statistics:" << std::endl;
1092 m_leaf_cache.print_statistics(o);
1096 m_node_cache.reset_statistics();
1097 m_leaf_cache.reset_statistics();
1101 template <
class KeyType,
1104 unsigned LogNodeSize,
1105 unsigned LogLeafSize,
1106 class PDAllocStrategy
1108 inline bool operator ==
1109 (
const btree<KeyType, DataType, CompareType,
1110 LogNodeSize, LogLeafSize, PDAllocStrategy>& a,
1111 const btree<KeyType, DataType, CompareType,
1112 LogNodeSize, LogLeafSize, PDAllocStrategy>& b)
1114 return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin());
1117 template <
class KeyType,
1120 unsigned LogNodeSize,
1121 unsigned LogLeafSize,
1122 class PDAllocStrategy
1124 inline bool operator !=
1125 (
const btree<KeyType, DataType, CompareType,
1126 LogNodeSize, LogLeafSize, PDAllocStrategy>& a,
1127 const btree<KeyType, DataType, CompareType,
1128 LogNodeSize, LogLeafSize, PDAllocStrategy>& b)
1133 template <
class KeyType,
1136 unsigned LogNodeSize,
1137 unsigned LogLeafSize,
1138 class PDAllocStrategy
1140 inline bool operator <
1141 (
const btree<KeyType, DataType, CompareType,
1142 LogNodeSize, LogLeafSize, PDAllocStrategy>& a,
1143 const btree<KeyType, DataType, CompareType,
1144 LogNodeSize, LogLeafSize, PDAllocStrategy>& b)
1146 return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
1149 template <
class KeyType,
1152 unsigned LogNodeSize,
1153 unsigned LogLeafSize,
1154 class PDAllocStrategy
1156 inline bool operator >
1157 (
const btree<KeyType, DataType, CompareType,
1158 LogNodeSize, LogLeafSize, PDAllocStrategy>& a,
1159 const btree<KeyType, DataType, CompareType,
1160 LogNodeSize, LogLeafSize, PDAllocStrategy>& b)
1165 template <
class KeyType,
1168 unsigned LogNodeSize,
1169 unsigned LogLeafSize,
1170 class PDAllocStrategy
1172 inline bool operator <=
1173 (
const btree<KeyType, DataType, CompareType,
1174 LogNodeSize, LogLeafSize, PDAllocStrategy>& a,
1175 const btree<KeyType, DataType, CompareType,
1176 LogNodeSize, LogLeafSize, PDAllocStrategy>& b)
1181 template <
class KeyType,
1184 unsigned LogNodeSize,
1185 unsigned LogLeafSize,
1186 class PDAllocStrategy
1188 inline bool operator >=
1189 (
const btree<KeyType, DataType, CompareType,
1190 LogNodeSize, LogLeafSize, PDAllocStrategy>& a,
1191 const btree<KeyType, DataType, CompareType,
1192 LogNodeSize, LogLeafSize, PDAllocStrategy>& b)
1203 template <
class KeyType,
1206 unsigned LogNodeSize,
1207 unsigned LogLeafSize,
1208 class PDAllocStrategy
1211 LogNodeSize, LogLeafSize, PDAllocStrategy>& a,
1213 LogNodeSize, LogLeafSize, PDAllocStrategy>& b)
1221 #endif // !STXXL_CONTAINERS_BTREE_BTREE_HEADER
#define STXXL_ASSERT(condition)
compat::remove_const< Integral >::type div_ceil(Integral n, Integral2 d)
btree_const_iterator< self_type > const_iterator
iterator_map_type m_iterator_map
void insert(InputIterator b, InputIterator e)
std::pair< iterator, iterator > equal_range(const key_type &k)
leaf_cache_type m_leaf_cache
void push_back(const value_type &x)
unsigned long long int uint64
void fuse(const normal_leaf &src)
key_type balance(normal_leaf &left)
std::pair< const_iterator, const_iterator > equal_range(const key_type &k) const
std::map< key_type, node_bid_type, key_compare > root_node_type
const_iterator end() const
info_type info
Per block information element.
static unsigned max_nelements()
key_compare m_key_compare
btree(InputIterator begin, InputIterator end, unsigned_type node_cache_size_in_bytes, unsigned_type leaf_cache_size_in_bytes, bool range_sorted=false, double node_fill_factor=0.75, double leaf_fill_factor=0.6)
bool m_prefetching_enabled
void deallocate_children()
node_type::block_type node_block_type
iterator find(const key_type &k)
static unsigned max_nelements()
btree< KeyType, DataType, CompareType, RawNodeSize, RawLeafSize, PDAllocStrategy > self_type
btree(InputIterator begin, InputIterator end, const key_compare &c_, unsigned_type node_cache_size_in_bytes, unsigned_type leaf_cache_size_in_bytes, bool range_sorted=false, double node_fill_factor=0.75, double leaf_fill_factor=0.6)
PDAllocStrategy alloc_strategy_type
static unsigned min_nelements()
std::pair< key_type, bid_type > insert(const std::pair< key_type, bid_type > &splitter, const block_iterator &place2insert)
const_iterator lower_bound(const key_type &k) const
normal_leaf< key_type, data_type, key_compare, RawLeafSize, self_type > leaf_type
node_cache< node_type, self_type > node_cache_type
btree(const key_compare &key_compare, unsigned_type node_cache_size_in_bytes, unsigned_type leaf_cache_size_in_bytes)
void insert_into_root(const std::pair< key_type, node_bid_type > &splitter)
void erase(iterator first, iterator last)
size_type erase(const key_type &k)
btree(unsigned_type node_cache_size_in_bytes, unsigned_type leaf_cache_size_in_bytes)
iterator lower_bound(const key_type &k)
std::pair< iterator, bool > insert(const value_type &x)
iterator_map< self_type > iterator_map_type
leaf_type::block_type leaf_block_type
void fuse_or_balance(root_node_iterator_type uit, CacheType &cache)
iterator find(const key_type &k)
std::pair< const key_type, data_type > value_type
iterator insert(iterator, const value_type &x)
node_cache< leaf_type, self_type > leaf_cache_type
root_node_type::const_iterator root_node_const_iterator_type
Block containing elements of fixed length.
void bulk_construction(InputIterator begin, InputIterator end, double node_fill_factor, double leaf_fill_factor)
stxxl::int64 difference_type
bool prefetching_enabled()
node_cache_type m_node_cache
const value_type & const_reference
btree_iterator< self_type > iterator
void enable_prefetching()
void push_back(const value_type &x)
const_iterator upper_bound(const key_type &k) const
root_node_type m_root_node
#define STXXL_BEGIN_NAMESPACE
size_type count(const key_type &k)
void fuse(const normal_node &src)
#define STXXL_VERBOSE1(x)
value_compare value_comp() const
iterator lower_bound(const key_type &k)
#define STXXL_THROW2(exception_type, location, error_message)
Throws exception_type with "Error in [location] : [error_message]".
void deallocate_children(unsigned height)
static uint_pair max()
return an uint_pair instance containing the largest value possible
iterator begin()
Returns iterator pointing to the first element.
alloc_strategy_type m_alloc_strategy
value_type const * const_pointer
normal_node< key_type, key_compare, RawNodeSize, self_type > node_type
key_type balance(normal_node &left, bool check_constraints=true)
std::pair< iterator, bool > insert(const value_type &x, std::pair< key_type, bid_type > &splitter)
iterator upper_bound(const key_type &k)
choose_int_types< my_pointer_size >::unsigned_type unsigned_type
iterator lower_bound(const key_type &k, unsigned height)
size_type erase(const key_type &k)
void print_statistics(std::ostream &o) const
const bid_type & my_bid() const
iterator upper_bound(const key_type &k)
iterator find(const key_type &k, unsigned height)
size_type max_size() const
root_node_type::iterator root_node_iterator_type
node_type::bid_type node_bid_type
leaf_type::bid_type leaf_bid_type
iterator begin(unsigned height)
const_iterator find(const key_type &k) const
ExtIterator find(ExtIterator begin, ExtIterator end, const EqualityComparable &value, int_type nbuffers=0)
External equivalent of std::find, see stxxl::find.
void disable_prefetching()
leaf_type::value_compare value_compare
External vector type generator.
const_iterator begin() const
std::pair< key_type, node_bid_type > root_node_pair_type
key_compare key_comp() const
#define STXXL_END_NAMESPACE
iterator upper_bound(const key_type &k, unsigned height)