13 #ifndef STXXL_CONTAINERS_BTREE__NODE_H
14 #define STXXL_CONTAINERS_BTREE__NODE_H
16 #include <stxxl/bits/containers/btree/iterator.h>
17 #include <stxxl/bits/containers/btree/node_cache.h>
20 __STXXL_BEGIN_NAMESPACE
24 template <
class NodeType,
class BTreeType>
27 template <
class KeyType_,
class KeyCmp_,
unsigned RawSize_,
class BTreeType>
28 class normal_node :
private noncopyable
31 typedef normal_node<KeyType_, KeyCmp_, RawSize_, BTreeType> SelfType;
33 friend class node_cache<SelfType, BTreeType>;
35 typedef KeyType_ key_type;
36 typedef KeyCmp_ key_compare;
42 typedef bid_type node_bid_type;
43 typedef SelfType node_type;
44 typedef std::pair<key_type, bid_type> value_type;
45 typedef value_type & reference;
46 typedef const value_type & const_reference;
59 min_size = nelements / 2
61 typedef typename block_type::iterator block_iterator;
62 typedef typename block_type::const_iterator block_const_iterator;
64 typedef BTreeType btree_type;
65 typedef typename btree_type::size_type size_type;
66 typedef typename btree_type::iterator iterator;
67 typedef typename btree_type::const_iterator const_iterator;
69 typedef typename btree_type::value_type btree_value_type;
70 typedef typename btree_type::leaf_bid_type leaf_bid_type;
71 typedef typename btree_type::leaf_type leaf_type;
73 typedef node_cache<normal_node, btree_type> node_cache_type;
76 struct value_compare :
public std::binary_function<value_type, value_type, bool>
80 value_compare(key_compare c) : comp(c) { }
82 bool operator () (
const value_type & x,
const value_type & y)
const
84 return comp(x.first, y.first);
94 template <
class BIDType>
95 std::pair<key_type, bid_type> insert(
const std::pair<key_type, BIDType> & splitter,
96 const block_iterator & place2insert)
98 std::pair<key_type, bid_type> result(key_compare::max_value(), bid_type());
101 assert(vcmp_(*place2insert, splitter) || vcmp_(splitter, *place2insert));
103 block_iterator cur = block_->begin() + size() - 1;
104 for ( ; cur >= place2insert; --cur)
108 *place2insert = splitter;
110 ++(block_->info.cur_size);
112 if (size() > max_nelements())
114 STXXL_VERBOSE1(
"btree::normal_node::insert overflow happened, splitting");
117 btree_->node_cache_.get_new_node(NewBid);
118 normal_node * NewNode = btree_->node_cache_.get_node(NewBid,
true);
121 const unsigned end_of_smaller_part = size() / 2;
123 result.first = ((*block_)[end_of_smaller_part - 1]).first;
124 result.second = NewBid;
127 const unsigned old_size = size();
129 std::copy(block_->begin(), block_->begin() + end_of_smaller_part, NewNode->block_->begin());
130 NewNode->block_->info.cur_size = end_of_smaller_part;
132 std::copy(block_->begin() + end_of_smaller_part,
133 block_->begin() + old_size, block_->begin());
134 block_->info.cur_size = old_size - end_of_smaller_part;
135 assert(size() + NewNode->size() == old_size);
137 btree_->node_cache_.unfix_node(NewBid);
139 STXXL_VERBOSE1(
"btree::normal_node split leaf " <<
this
140 <<
" splitter: " << result.first);
146 template <
class CacheType>
147 void fuse_or_balance(block_iterator UIt, CacheType & cache_)
149 typedef typename CacheType::node_type local_node_type;
150 typedef typename local_node_type::bid_type local_bid_type;
152 block_iterator leftIt, rightIt;
153 if (UIt == (block_->begin() + size() - 1))
155 assert(UIt != block_->begin());
163 assert(rightIt != (block_->begin() + size()));
167 local_bid_type LeftBid = (local_bid_type)leftIt->second;
168 local_bid_type RightBid = (local_bid_type)rightIt->second;
169 local_node_type * LeftNode = cache_.get_node(LeftBid,
true);
170 local_node_type * RightNode = cache_.get_node(RightBid,
true);
172 const unsigned TotalSize = LeftNode->size() + RightNode->size();
173 if (TotalSize <= RightNode->max_nelements())
176 RightNode->fuse(*LeftNode);
178 cache_.unfix_node(RightBid);
179 cache_.delete_node(LeftBid);
181 std::copy(leftIt + 1, block_->begin() + size(), leftIt);
182 --(block_->info.cur_size);
188 key_type NewSplitter = RightNode->balance(*LeftNode);
191 leftIt->first = NewSplitter;
192 assert(vcmp_(*leftIt, *rightIt));
194 cache_.unfix_node(LeftBid);
195 cache_.unfix_node(RightBid);
200 virtual ~normal_node()
205 normal_node(btree_type * btree__,
207 block_(new block_type),
212 assert(min_nelements() >= 2);
213 assert(2 * min_nelements() - 1 <= max_nelements());
214 assert(max_nelements() <= nelements);
223 bool overflows()
const {
return block_->info.cur_size > max_nelements(); }
224 bool underflows()
const {
return block_->info.cur_size < min_nelements(); }
226 unsigned max_nelements()
const {
return max_size; }
227 unsigned min_nelements()
const {
return min_size; }
253 unsigned size()
const
255 return block_->info.cur_size;
258 bid_type my_bid()
const
260 return block_->info.me;
273 assert(bid == my_bid());
279 return block_->read(bid);
282 void init(
const bid_type & my_bid_)
284 block_->info.me = my_bid_;
285 block_->info.cur_size = 0;
288 reference operator [] (
int i)
293 const_reference operator [] (
int i)
const
300 return (*block_)[size() - 1];
305 return *(block_->begin());
308 const_reference back()
const
310 return (*block_)[size() - 1];
313 const_reference front()
const
315 return *(block_->begin());
319 std::pair<iterator, bool> insert(
320 const btree_value_type & x,
322 std::pair<key_type, bid_type> & splitter)
324 assert(size() <= max_nelements());
325 splitter.first = key_compare::max_value();
327 value_type Key2Search(x.first, bid_type());
329 std::lower_bound(block_->begin(), block_->begin() + size(), Key2Search, vcmp_);
331 assert(it != (block_->begin() + size()));
333 bid_type found_bid = it->second;
334 STXXL_UNUSED(found_bid);
338 STXXL_VERBOSE1(
"btree::normal_node Inserting new value into a leaf");
339 leaf_type * Leaf = btree_->leaf_cache_.get_node((leaf_bid_type)it->second,
true);
341 std::pair<key_type, leaf_bid_type> BotSplitter;
342 std::pair<iterator, bool> result = Leaf->insert(x, BotSplitter);
343 btree_->leaf_cache_.unfix_node((leaf_bid_type)it->second);
345 if (!(cmp_(key_compare::max_value(), BotSplitter.first) ||
346 cmp_(BotSplitter.first, key_compare::max_value())))
350 STXXL_VERBOSE1(
"btree::normal_node Inserting new value in *this");
352 splitter = insert(BotSplitter, it);
358 STXXL_VERBOSE1(
"btree::normal_node Inserting new value into a node");
359 node_type * Node = btree_->node_cache_.get_node((node_bid_type)it->second,
true);
361 std::pair<key_type, node_bid_type> BotSplitter;
362 std::pair<iterator, bool> result = Node->insert(x, height - 1, BotSplitter);
363 btree_->node_cache_.unfix_node((node_bid_type)it->second);
365 if (!(cmp_(key_compare::max_value(), BotSplitter.first) ||
366 cmp_(BotSplitter.first, key_compare::max_value())))
370 STXXL_VERBOSE1(
"btree::normal_node Inserting new value in *this");
372 splitter = insert(BotSplitter, it);
378 iterator begin(
unsigned height)
380 bid_type FirstBid = block_->begin()->second;
384 STXXL_VERBOSE1(
"btree::node retrieveing begin() from the first leaf");
385 leaf_type * Leaf = btree_->leaf_cache_.get_node((leaf_bid_type)FirstBid);
387 return Leaf->begin();
391 STXXL_VERBOSE1(
"btree: retrieveing begin() from the first node");
392 node_type * Node = btree_->node_cache_.get_node((node_bid_type)FirstBid,
true);
394 iterator result = Node->begin(height - 1);
395 btree_->node_cache_.unfix_node((node_bid_type)FirstBid);
400 const_iterator begin(
unsigned height)
const
402 bid_type FirstBid = block_->begin()->second;
406 STXXL_VERBOSE1(
"btree::node retrieveing begin() from the first leaf");
407 leaf_type
const * Leaf = btree_->leaf_cache_.get_const_node((leaf_bid_type)FirstBid);
409 return Leaf->begin();
413 STXXL_VERBOSE1(
"btree: retrieveing begin() from the first node");
414 node_type
const * Node = btree_->node_cache_.get_const_node((node_bid_type)FirstBid,
true);
416 const_iterator result = Node->begin(height - 1);
417 btree_->node_cache_.unfix_node((node_bid_type)FirstBid);
422 iterator
find(
const key_type & k,
unsigned height)
424 value_type Key2Search(k, bid_type());
427 std::lower_bound(block_->begin(), block_->begin() + size(), Key2Search, vcmp_);
429 assert(it != (block_->begin() + size()));
431 bid_type found_bid = it->second;
435 STXXL_VERBOSE1(
"Searching in a leaf");
436 leaf_type * Leaf = btree_->leaf_cache_.get_node((leaf_bid_type)found_bid,
true);
438 iterator result = Leaf->find(k);
439 btree_->leaf_cache_.unfix_node((leaf_bid_type)found_bid);
445 STXXL_VERBOSE1(
"Searching in a node");
446 node_type * Node = btree_->node_cache_.get_node((node_bid_type)found_bid,
true);
448 iterator result = Node->find(k, height - 1);
449 btree_->node_cache_.unfix_node((node_bid_type)found_bid);
454 const_iterator
find(
const key_type & k,
unsigned height)
const
456 value_type Key2Search(k, bid_type());
459 std::lower_bound(block_->begin(), block_->begin() + size(), Key2Search, vcmp_);
461 assert(it != (block_->begin() + size()));
463 bid_type found_bid = it->second;
467 STXXL_VERBOSE1(
"Searching in a leaf");
468 leaf_type
const * Leaf = btree_->leaf_cache_.get_const_node((leaf_bid_type)found_bid,
true);
470 const_iterator result = Leaf->find(k);
471 btree_->leaf_cache_.unfix_node((leaf_bid_type)found_bid);
477 STXXL_VERBOSE1(
"Searching in a node");
478 node_type
const * Node = btree_->node_cache_.get_const_node((node_bid_type)found_bid,
true);
480 const_iterator result = Node->find(k, height - 1);
481 btree_->node_cache_.unfix_node((node_bid_type)found_bid);
486 iterator lower_bound(
const key_type & k,
unsigned height)
488 value_type Key2Search(k, bid_type());
489 assert(!vcmp_(back(), Key2Search));
491 std::lower_bound(block_->begin(), block_->begin() + size(), Key2Search, vcmp_);
493 assert(it != (block_->begin() + size()));
495 bid_type found_bid = it->second;
499 STXXL_VERBOSE1(
"Searching lower bound in a leaf");
500 leaf_type * Leaf = btree_->leaf_cache_.get_node((leaf_bid_type)found_bid,
true);
502 iterator result = Leaf->lower_bound(k);
503 btree_->leaf_cache_.unfix_node((leaf_bid_type)found_bid);
509 STXXL_VERBOSE1(
"Searching lower bound in a node");
510 node_type * Node = btree_->node_cache_.get_node((node_bid_type)found_bid,
true);
512 iterator result = Node->lower_bound(k, height - 1);
513 btree_->node_cache_.unfix_node((node_bid_type)found_bid);
518 const_iterator lower_bound(
const key_type & k,
unsigned height)
const
520 value_type Key2Search(k, bid_type());
521 assert(!vcmp_(back(), Key2Search));
523 std::lower_bound(block_->begin(), block_->begin() + size(), Key2Search, vcmp_);
525 assert(it != (block_->begin() + size()));
527 bid_type found_bid = it->second;
531 STXXL_VERBOSE1(
"Searching lower bound in a leaf");
532 leaf_type
const * Leaf = btree_->leaf_cache_.get_const_node((leaf_bid_type)found_bid,
true);
534 const_iterator result = Leaf->lower_bound(k);
535 btree_->leaf_cache_.unfix_node((leaf_bid_type)found_bid);
541 STXXL_VERBOSE1(
"Searching lower bound in a node");
542 node_type
const * Node = btree_->node_cache_.get_const_node((node_bid_type)found_bid,
true);
544 const_iterator result = Node->lower_bound(k, height - 1);
545 btree_->node_cache_.unfix_node((node_bid_type)found_bid);
550 iterator upper_bound(
const key_type & k,
unsigned height)
552 value_type Key2Search(k, bid_type());
553 assert(vcmp_(Key2Search, back()));
555 std::upper_bound(block_->begin(), block_->begin() + size(), Key2Search, vcmp_);
557 assert(it != (block_->begin() + size()));
559 bid_type found_bid = it->second;
563 STXXL_VERBOSE1(
"Searching upper bound in a leaf");
564 leaf_type * Leaf = btree_->leaf_cache_.get_node((leaf_bid_type)found_bid,
true);
566 iterator result = Leaf->upper_bound(k);
567 btree_->leaf_cache_.unfix_node((leaf_bid_type)found_bid);
573 STXXL_VERBOSE1(
"Searching upper bound in a node");
574 node_type * Node = btree_->node_cache_.get_node((node_bid_type)found_bid,
true);
576 iterator result = Node->upper_bound(k, height - 1);
577 btree_->node_cache_.unfix_node((node_bid_type)found_bid);
582 const_iterator upper_bound(
const key_type & k,
unsigned height)
const
584 value_type Key2Search(k, bid_type());
585 assert(vcmp_(Key2Search, back()));
587 std::upper_bound(block_->begin(), block_->begin() + size(), Key2Search, vcmp_);
589 assert(it != (block_->begin() + size()));
591 bid_type found_bid = it->second;
595 STXXL_VERBOSE1(
"Searching upper bound in a leaf");
596 leaf_type
const * Leaf = btree_->leaf_cache_.get_const_node((leaf_bid_type)found_bid,
true);
598 const_iterator result = Leaf->upper_bound(k);
599 btree_->leaf_cache_.unfix_node((leaf_bid_type)found_bid);
605 STXXL_VERBOSE1(
"Searching upper bound in a node");
606 node_type
const * Node = btree_->node_cache_.get_const_node((node_bid_type)found_bid,
true);
608 const_iterator result = Node->upper_bound(k, height - 1);
609 btree_->node_cache_.unfix_node((node_bid_type)found_bid);
614 void fuse(
const normal_node & Src)
616 assert(vcmp_(Src.back(), front()));
617 const unsigned SrcSize = Src.size();
619 block_iterator cur = block_->begin() + size() - 1;
620 block_const_iterator begin = block_->begin();
622 for ( ; cur >= begin; --cur)
623 *(cur + SrcSize) = *cur;
627 std::copy(Src.block_->begin(), Src.block_->begin() + SrcSize, block_->begin());
629 block_->info.cur_size += SrcSize;
633 key_type balance(normal_node & Left)
635 const unsigned TotalSize = Left.size() + size();
636 unsigned newLeftSize = TotalSize / 2;
637 assert(newLeftSize <= Left.max_nelements());
638 assert(newLeftSize >= Left.min_nelements());
639 unsigned newRightSize = TotalSize - newLeftSize;
640 assert(newRightSize <= max_nelements());
641 assert(newRightSize >= min_nelements());
643 assert(vcmp_(Left.back(), front()) || size() == 0);
645 if (newLeftSize < Left.size())
647 const unsigned nEl2Move = Left.size() - newLeftSize;
649 block_iterator cur = block_->begin() + size() - 1;
650 block_const_iterator begin = block_->begin();
652 for ( ; cur >= begin; --cur)
653 *(cur + nEl2Move) = *cur;
657 std::copy(Left.block_->begin() + newLeftSize,
658 Left.block_->begin() + Left.size(), block_->begin());
662 assert(newRightSize < size());
664 const unsigned nEl2Move = size() - newRightSize;
667 std::copy(block_->begin(),
668 block_->begin() + nEl2Move, Left.block_->begin() + Left.size());
670 std::copy(block_->begin() + nEl2Move,
671 block_->begin() + size(), block_->begin());
674 block_->info.cur_size = newRightSize;
675 Left.block_->info.cur_size = newLeftSize;
677 return Left.back().first;
680 size_type erase(
const key_type & k,
unsigned height)
682 value_type Key2Search(k, bid_type());
685 std::lower_bound(block_->begin(), block_->begin() + size(), Key2Search, vcmp_);
687 assert(it != (block_->begin() + size()));
689 bid_type found_bid = it->second;
695 STXXL_VERBOSE1(
"btree::normal_node Deleting key from a leaf");
696 leaf_type * Leaf = btree_->leaf_cache_.get_node((leaf_bid_type)found_bid,
true);
698 size_type result = Leaf->erase(k);
699 btree_->leaf_cache_.unfix_node((leaf_bid_type)it->second);
700 if (!Leaf->underflows())
704 STXXL_VERBOSE1(
"btree::normal_node Fusing or rebalancing a leaf");
705 fuse_or_balance(it, btree_->leaf_cache_);
711 STXXL_VERBOSE1(
"btree::normal_node Deleting key from a node");
712 node_type * Node = btree_->node_cache_.get_node((node_bid_type)found_bid,
true);
714 size_type result = Node->erase(k, height - 1);
715 btree_->node_cache_.unfix_node((node_bid_type)found_bid);
716 if (!Node->underflows())
720 STXXL_VERBOSE1(
"btree::normal_node Fusing or rebalancing a node");
721 fuse_or_balance(it, btree_->node_cache_);
726 void deallocate_children(
unsigned height)
731 block_const_iterator it = block().begin();
732 for ( ; it != block().begin() + size(); ++it)
735 btree_->leaf_cache_.delete_node((leaf_bid_type)it->second);
740 block_const_iterator it = block().begin();
741 for ( ; it != block().begin() + size(); ++it)
743 node_type * Node = btree_->node_cache_.get_node((node_bid_type)it->second);
745 Node->deallocate_children(height - 1);
747 btree_->node_cache_.delete_node((node_bid_type)it->second);
752 void push_back(
const value_type & x)
755 ++(block_->info.cur_size);
761 __STXXL_END_NAMESPACE
Block containing elements of fixed length.
Definition: typed_block.h:223
number of elements in block
Definition: typed_block.h:240
Implemented as reference counting smart pointer.
Definition: request_ptr.h:34
_ExtIterator find(_ExtIterator _begin, _ExtIterator _end, const _EqualityComparable &_value, int_type nbuffers)
External equivalent of std::find.
Definition: scan.h:215
virtual void wait(bool measure_time=true)=0
Suspends calling thread until completion of the request.