13 #ifndef STXXL_CONTAINERS_BTREE_BTREE_HEADER
14 #define STXXL_CONTAINERS_BTREE_BTREE_HEADER
31 template <
class KeyType,
82 min_node_size = node_type::min_size,
83 max_node_size = node_type::max_size,
84 min_leaf_size = leaf_type::min_size,
85 max_leaf_size = leaf_type::max_size
111 std::pair<root_node_iterator_type, bool> result =
112 root_node_.insert(splitter);
114 if (root_node_.size() > max_node_size)
116 STXXL_VERBOSE1(
"btree::insert_into_root, overflow happened, splitting");
119 node_type* LeftNode = node_cache_.get_new_node(LeftBid);
122 node_type* RightNode = node_cache_.get_new_node(RightBid);
137 LeftNode->
block().
info.cur_size = (
unsigned int)half;
149 key_type RightKey = (RightNode->
block()[right_size - 1]).first;
151 assert(old_size == RightNode->
size() + LeftNode->
size());
161 if (node_cache_.size() < (height_ - 1))
163 STXXL_THROW2(std::runtime_error,
"btree::bulk_construction",
"The height of the tree (" << height_ <<
") has exceeded the required capacity (" << (node_cache_.size() + 1) <<
") of the node cache. Increase the node cache size.");
168 template <
class CacheType>
171 typedef typename CacheType::node_type local_node_type;
172 typedef typename local_node_type::bid_type local_bid_type;
175 if (UIt->first == key_compare::max_value())
177 assert(UIt != root_node_.begin());
185 assert(rightIt != root_node_.end());
189 local_bid_type LeftBid = (local_bid_type)leftIt->second;
190 local_bid_type RightBid = (local_bid_type)rightIt->second;
191 local_node_type* LeftNode = cache_.get_node(LeftBid,
true);
192 local_node_type* RightNode = cache_.get_node(RightBid,
true);
194 const unsigned_type TotalSize = LeftNode->size() + RightNode->size();
195 if (TotalSize <= RightNode->max_nelements())
198 RightNode->fuse(*LeftNode);
200 cache_.unfix_node(RightBid);
201 cache_.delete_node(LeftBid);
203 root_node_.erase(leftIt);
209 key_type NewSplitter = RightNode->balance(*LeftNode);
211 root_node_.erase(leftIt);
215 cache_.unfix_node(LeftBid);
216 cache_.unfix_node(RightBid);
223 leaf_type* NewLeaf = leaf_cache_.get_new_node(NewBid);
225 end_iterator = NewLeaf->
end();
235 for ( ; it != root_node_.end(); ++it)
244 for ( ; it != root_node_.end(); ++it)
255 template <
class InputIterator>
256 void bulk_construction(InputIterator b, InputIterator e,
double node_fill_factor,
double leaf_fill_factor)
258 assert(node_fill_factor >= 0.5);
259 assert(leaf_fill_factor >= 0.5);
260 key_type lastKey = key_compare::max_value();
262 typedef std::pair<key_type, node_bid_type> key_bid_pair;
264 node_block_type::raw_size>::result key_bid_vector_type;
266 key_bid_vector_type Bids;
269 leaf_type* Leaf = leaf_cache_.get_new_node(NewBid);
277 if (key_compare_(b->first, lastKey) || key_compare_(lastKey, b->first))
280 if (Leaf->
size() == max_leaf_elements)
285 leaf_type* NewLeaf = leaf_cache_.get_new_node(NewBid);
306 Leaf->
fuse(*LeftLeaf);
307 leaf_cache_.delete_node((
leaf_bid_type)(Bids.back().second));
315 Bids.back().first = NewSplitter;
322 end_iterator = Leaf->
end();
324 Bids.push_back(key_bid_pair(key_compare::max_value(), (
node_bid_type)NewBid));
328 while (Bids.size() > max_node_elements)
330 key_bid_vector_type ParentBids;
333 assert(nparents >= 2);
334 STXXL_VERBOSE1(
"btree bulk constructBids.size() " << Bids.size() <<
" nparents: " << nparents <<
" max_ns: "
335 << max_node_elements);
337 typename key_bid_vector_type::const_iterator it = Bids.begin();
342 node_type* Node = node_cache_.get_new_node(NewBid);
345 for ( ; cnt < max_node_elements && it != Bids.end(); ++cnt, ++it)
354 assert(it == Bids.end());
355 assert(!ParentBids.empty());
357 node_type* LeftNode = node_cache_.get_node(ParentBids.back().second);
361 Node->
fuse(*LeftNode);
362 node_cache_.delete_node(ParentBids.back().second);
363 ParentBids.pop_back();
368 ParentBids.back().first = NewSplitter;
369 assert(!LeftNode->overflows() && !LeftNode->underflows());
374 ParentBids.push_back(key_bid_pair(Node->
back().first, NewBid));
375 }
while (it != Bids.end());
377 std::swap(ParentBids, Bids);
379 assert(nparents == Bids.size() || (nparents - 1) == Bids.size());
383 if (node_cache_.size() < (height_ - 1))
385 STXXL_THROW2(std::runtime_error,
"btree::bulk_construction",
"The height of the tree (" << height_ <<
") has exceeded the required capacity (" << (node_cache_.size() + 1) <<
") of the node cache. Increase the node cache size.");
389 root_node_.insert(Bids.begin(), Bids.end());
396 node_cache_(node_cache_size_in_bytes, this, key_compare_),
397 leaf_cache_(leaf_cache_size_in_bytes, this, key_compare_),
401 prefetching_enabled_(true),
421 node_cache_(node_cache_size_in_bytes, this, key_compare_),
422 leaf_cache_(leaf_cache_size_in_bytes, this, key_compare_),
426 prefetching_enabled_(true),
440 deallocate_children();
465 assert(!root_node_.empty());
466 assert(it != root_node_.end());
472 std::pair<key_type, leaf_bid_type> Splitter;
473 std::pair<iterator, bool> result = Leaf->
insert(x, Splitter);
479 if (!(key_compare_(key_compare::max_value(), Splitter.first) ||
480 key_compare_(Splitter.first, key_compare::max_value())))
486 insert_into_root(std::make_pair(Splitter.first,
node_bid_type(Splitter.second)));
488 assert(leaf_cache_.nfixed() == 0);
489 assert(node_cache_.nfixed() == 0);
497 std::pair<key_type, node_bid_type> Splitter;
498 std::pair<iterator, bool> result = Node->
insert(x, height_ - 1, Splitter);
504 if (!(key_compare_(key_compare::max_value(), Splitter.first) ||
505 key_compare_(Splitter.first, key_compare::max_value())))
511 insert_into_root(Splitter);
513 assert(leaf_cache_.nfixed() == 0);
514 assert(node_cache_.nfixed() == 0);
522 assert(it != root_node_.end());
530 assert(leaf_cache_.nfixed() == 0);
531 assert(node_cache_.nfixed() == 0);
532 return Leaf->
begin();
542 assert(leaf_cache_.nfixed() == 0);
543 assert(node_cache_.nfixed() == 0);
551 assert(it != root_node_.end());
558 assert(leaf_cache_.nfixed() == 0);
559 assert(node_cache_.nfixed() == 0);
560 return Leaf->
begin();
569 assert(leaf_cache_.nfixed() == 0);
570 assert(node_cache_.nfixed() == 0);
592 assert(it != root_node_.end());
601 assert(result == end() || result->first == k);
602 assert(leaf_cache_.nfixed() == 0);
603 assert(node_cache_.nfixed() == 0);
614 assert(result == end() || result->first == k);
615 assert(leaf_cache_.nfixed() == 0);
616 assert(node_cache_.nfixed() == 0);
623 assert(it != root_node_.end());
632 assert(result == end() || result->first == k);
633 assert(leaf_cache_.nfixed() == 0);
634 assert(node_cache_.nfixed() == 0);
645 assert(result == end() || result->first == k);
646 assert(leaf_cache_.nfixed() == 0);
647 assert(node_cache_.nfixed() == 0);
654 assert(it != root_node_.end());
663 assert(leaf_cache_.nfixed() == 0);
664 assert(node_cache_.nfixed() == 0);
675 assert(leaf_cache_.nfixed() == 0);
676 assert(node_cache_.nfixed() == 0);
683 assert(it != root_node_.end());
693 assert(leaf_cache_.nfixed() == 0);
694 assert(node_cache_.nfixed() == 0);
705 assert(leaf_cache_.nfixed() == 0);
706 assert(node_cache_.nfixed() == 0);
713 assert(it != root_node_.end());
723 assert(leaf_cache_.nfixed() == 0);
724 assert(node_cache_.nfixed() == 0);
735 assert(leaf_cache_.nfixed() == 0);
736 assert(node_cache_.nfixed() == 0);
743 assert(it != root_node_.end());
753 assert(leaf_cache_.nfixed() == 0);
754 assert(node_cache_.nfixed() == 0);
765 assert(leaf_cache_.nfixed() == 0);
766 assert(node_cache_.nfixed() == 0);
774 if (l == end() || key_compare_(k, l->first))
775 return std::pair<iterator, iterator>(l, l);
781 assert(leaf_cache_.nfixed() == 0);
782 assert(node_cache_.nfixed() == 0);
784 return std::pair<iterator, iterator>(l, u);
791 if (l == end() || key_compare_(k, l->first))
792 return std::pair<const_iterator, const_iterator>(l, l);
798 assert(leaf_cache_.nfixed() == 0);
799 assert(node_cache_.nfixed() == 0);
800 return std::pair<const_iterator, const_iterator>(l, u);
806 assert(it != root_node_.end());
815 assert(leaf_cache_.nfixed() == 0);
816 assert(node_cache_.nfixed() == 0);
818 if ((!Leaf->
underflows()) || root_node_.size() == 1)
823 fuse_or_balance(it, leaf_cache_);
825 assert(leaf_cache_.nfixed() == 0);
826 assert(node_cache_.nfixed() == 0);
833 assert(root_node_.size() >= 2);
836 size_type result = Node->erase(k, height_ - 1);
839 assert(leaf_cache_.nfixed() == 0);
840 assert(node_cache_.nfixed() == 0);
841 if (!Node->underflows())
846 fuse_or_balance(it, node_cache_);
848 if (root_node_.size() == 1)
852 it = root_node_.begin();
854 assert(it->first == key_compare::max_value());
855 node_type* RootNode = node_cache_.get_node(RootBid);
857 assert(RootNode->
back().first == key_compare::max_value());
862 node_cache_.delete_node(RootBid);
867 assert(leaf_cache_.nfixed() == 0);
868 assert(node_cache_.nfixed() == 0);
875 if (
find(k) == end())
883 assert(pos != end());
890 assert(size() == old_size - 1);
895 return insert(x).first;
900 deallocate_children();
908 assert(leaf_cache_.nfixed() == 0);
909 assert(node_cache_.nfixed() == 0);
912 template <
class InputIterator>
913 void insert(InputIterator b, InputIterator e)
921 template <
class InputIterator>
927 bool range_sorted =
false,
928 double node_fill_factor = 0.75,
929 double leaf_fill_factor = 0.6
932 node_cache_(node_cache_size_in_bytes, this, key_compare_),
933 leaf_cache_(leaf_cache_size_in_bytes, this, key_compare_),
937 prefetching_enabled_(true),
944 if (range_sorted ==
false)
948 assert(leaf_cache_.nfixed() == 0);
949 assert(node_cache_.nfixed() == 0);
953 bulk_construction(b, e, node_fill_factor, leaf_fill_factor);
954 assert(leaf_cache_.nfixed() == 0);
955 assert(node_cache_.nfixed() == 0);
959 template <
class InputIterator>
964 bool range_sorted =
false,
965 double node_fill_factor = 0.75,
966 double leaf_fill_factor = 0.6
968 node_cache_(node_cache_size_in_bytes, this, key_compare_),
969 leaf_cache_(leaf_cache_size_in_bytes, this, key_compare_),
973 prefetching_enabled_(true),
980 if (range_sorted ==
false)
984 assert(leaf_cache_.nfixed() == 0);
985 assert(node_cache_.nfixed() == 0);
989 bulk_construction(b, e, node_fill_factor, leaf_fill_factor);
990 assert(leaf_cache_.nfixed() == 0);
991 assert(node_cache_.nfixed() == 0);
996 if (first == begin() && last == end())
1000 while (first != last)
1006 return key_compare_;
1024 std::swap(size_, obj.
size_);
1025 std::swap(height_, obj.
height_);
1032 prefetching_enabled_ =
true;
1036 prefetching_enabled_ =
false;
1040 return prefetching_enabled_;
1045 o <<
"Node cache statistics:" << std::endl;
1046 node_cache_.print_statistics(o);
1047 o <<
"Leaf cache statistics:" << std::endl;
1048 leaf_cache_.print_statistics(o);
1052 node_cache_.reset_statistics();
1053 leaf_cache_.reset_statistics();
1057 template <
class KeyType,
1060 unsigned LogNodeSize,
1061 unsigned LogLeafSize,
1062 class PDAllocStrategy
1070 template <
class KeyType,
1073 unsigned LogNodeSize,
1074 unsigned LogLeafSize,
1075 class PDAllocStrategy
1084 template <
class KeyType,
1087 unsigned LogNodeSize,
1088 unsigned LogLeafSize,
1089 class PDAllocStrategy
1091 inline bool operator < (const btree<KeyType, DataType, CompareType, LogNodeSize, LogLeafSize, PDAllocStrategy>& a,
1094 return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
1098 template <
class KeyType,
1101 unsigned LogNodeSize,
1102 unsigned LogLeafSize,
1103 class PDAllocStrategy
1112 template <
class KeyType,
1115 unsigned LogNodeSize,
1116 unsigned LogLeafSize,
1117 class PDAllocStrategy
1119 inline bool operator <= (const btree<KeyType, DataType, CompareType, LogNodeSize, LogLeafSize, PDAllocStrategy>& a,
1125 template <
class KeyType,
1128 unsigned LogNodeSize,
1129 unsigned LogLeafSize,
1130 class PDAllocStrategy
1145 template <
class KeyType,
1148 unsigned LogNodeSize,
1149 unsigned LogLeafSize,
1150 class PDAllocStrategy
1161 #endif // !STXXL_CONTAINERS_BTREE_BTREE_HEADER
std::pair< key_type, bid_type > insert(const std::pair< key_type, bid_type > &splitter, const block_iterator &place2insert)
#define STXXL_ASSERT(condition)
node_cache< leaf_type, SelfType > leaf_cache_type
std::pair< iterator, bool > insert(const value_type &x, std::pair< key_type, bid_type > &splitter)
const bid_type & my_bid() const
bool prefetching_enabled_
key_type balance(normal_node &Left)
void insert(InputIterator b, InputIterator e)
std::pair< iterator, iterator > equal_range(const key_type &k)
unsigned long long int uint64
void bulk_construction(InputIterator b, InputIterator e, double node_fill_factor, double leaf_fill_factor)
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.
void deallocate_children()
normal_node< key_type, key_compare, RawNodeSize, SelfType > node_type
iterator_map< SelfType > iterator_map_type
unsigned min_nelements() const
btree_const_iterator< SelfType > const_iterator
node_type::block_type node_block_type
PDAllocStrategy alloc_strategy_type
const_iterator lower_bound(const key_type &k) const
void fuse(const normal_node &Src)
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)
iterator upper_bound(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)
size_type erase(const key_type &k)
alloc_strategy_type alloc_strategy_
leaf_type::block_type leaf_block_type
iterator find(const key_type &k)
iterator find(const key_type &k, unsigned height)
std::pair< const key_type, data_type > value_type
key_type balance(normal_leaf &Left)
iterator insert(iterator, const value_type &x)
root_node_type::const_iterator root_node_const_iterator_type
Block containing elements of fixed length.
unsigned max_nelements() const
stxxl::int64 difference_type
bool prefetching_enabled()
bool operator!=(const uint_pair &b) const
inequality checking operator
normal_leaf< key_type, data_type, key_compare, RawLeafSize, SelfType > leaf_type
const value_type & const_reference
bool operator>(const uint_pair &b) const
greater comparison operator
btree(InputIterator b, InputIterator e, 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)
iterator_map_type iterator_map_
void enable_prefetching()
const_iterator upper_bound(const key_type &k) const
bool operator>=(const uint_pair &b) const
greater-or-equal comparison operator
leaf_cache_type leaf_cache_
#define STXXL_BEGIN_NAMESPACE
void STXXL_UNUSED(const U &)
iterator lower_bound(const key_type &k)
size_type count(const key_type &k)
iterator begin(unsigned height)
#define STXXL_VERBOSE1(x)
btree_iterator< SelfType > iterator
value_compare value_comp() const
btree(const key_compare &c_, unsigned_type node_cache_size_in_bytes, unsigned_type leaf_cache_size_in_bytes)
void fuse_or_balance(root_node_iterator_type UIt, CacheType &cache_)
#define STXXL_THROW2(exception_type, location, error_message)
Throws exception_type with "Error in [location] : [error_message]".
static uint_pair max()
return an uint_pair instance containing the largest value possible
node_cache_type node_cache_
iterator begin()
Returns iterator pointing to the first element.
value_type const * const_pointer
void deallocate_children(unsigned height)
iterator find(const key_type &k)
iterator upper_bound(const key_type &k)
choose_int_types< my_pointer_size >::unsigned_type unsigned_type
compat::remove_const< Integral >::type div_ceil(Integral __n, Integral2 __d)
node_cache< node_type, SelfType > node_cache_type
void push_back(const value_type &x)
unsigned max_nelements() const
void print_statistics(std::ostream &o) const
root_node_type root_node_
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
btree(InputIterator b, InputIterator e, 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)
iterator lower_bound(const key_type &k, 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.
void push_back(const value_type &x)
const_iterator begin() const
std::pair< key_type, node_bid_type > root_node_pair_type
void fuse(const normal_leaf &Src)
key_compare key_comp() const
bool operator==(const uint_pair &b) const
equality checking operator
#define STXXL_END_NAMESPACE
btree< KeyType, DataType, CompareType, RawNodeSize, RawLeafSize, PDAllocStrategy > SelfType
iterator upper_bound(const key_type &k, unsigned height)