00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef STXXL_CONTAINERS_BTREE__LEAF_H
00014 #define STXXL_CONTAINERS_BTREE__LEAF_H
00015
00016 #include <stxxl/bits/containers/btree/iterator.h>
00017 #include <stxxl/bits/containers/btree/node_cache.h>
00018
00019
00020 __STXXL_BEGIN_NAMESPACE
00021
00022 namespace btree
00023 {
00024 template <class NodeType, class BTreeType>
00025 class node_cache;
00026
00027 template <class KeyType_, class DataType_, class KeyCmp_, unsigned RawSize_, class BTreeType>
00028 class normal_leaf : private noncopyable
00029 {
00030 public:
00031 typedef normal_leaf<KeyType_, DataType_, KeyCmp_, RawSize_, BTreeType> SelfType;
00032
00033 friend class node_cache<SelfType, BTreeType>;
00034
00035 typedef KeyType_ key_type;
00036 typedef DataType_ data_type;
00037 typedef KeyCmp_ key_compare;
00038 typedef std::pair<key_type, data_type> value_type;
00039 typedef value_type & reference;
00040 typedef const value_type & const_reference;
00041
00042 enum {
00043 raw_size = RawSize_
00044 };
00045 typedef BID<raw_size> bid_type;
00046 struct InfoType
00047 {
00048 bid_type me, pred, succ;
00049 unsigned cur_size;
00050 };
00051
00052 typedef typed_block<raw_size, value_type, 0, InfoType> block_type;
00053 enum {
00054 nelements = block_type::size - 1,
00055 max_size = nelements,
00056 min_size = nelements / 2
00057 };
00058
00059 typedef BTreeType btree_type;
00060 typedef typename btree_type::size_type size_type;
00061 typedef btree_iterator_base<btree_type> iterator_base;
00062 typedef btree_iterator<btree_type> iterator;
00063 typedef btree_const_iterator<btree_type> const_iterator;
00064
00065 typedef node_cache<normal_leaf, btree_type> leaf_cache_type;
00066
00067 public:
00068 struct value_compare : public std::binary_function<value_type, value_type, bool>
00069 {
00070 key_compare comp;
00071
00072 value_compare(key_compare c) : comp(c) { }
00073
00074 bool operator () (const value_type & x, const value_type & y) const
00075 {
00076 return comp(x.first, y.first);
00077 }
00078 };
00079
00080 private:
00081 block_type * block_;
00082 btree_type * btree_;
00083
00084 key_compare cmp_;
00085 value_compare vcmp_;
00086
00087 void split(std::pair<key_type, bid_type> & splitter)
00088 {
00089 bid_type NewBid;
00090 btree_->leaf_cache_.get_new_node(NewBid);
00091 normal_leaf * NewLeaf = btree_->leaf_cache_.get_node(NewBid, true);
00092 assert(NewLeaf);
00093
00094
00095 NewLeaf->succ() = my_bid();
00096 normal_leaf * PredLeaf = NULL;
00097 if (pred().valid())
00098 {
00099 NewLeaf->pred() = pred();
00100 PredLeaf = btree_->leaf_cache_.get_node(pred());
00101 assert(PredLeaf);
00102 assert(vcmp_(PredLeaf->back(), front()));
00103 PredLeaf->succ() = NewBid;
00104 }
00105 pred() = NewBid;
00106
00107 std::vector<iterator_base *> Iterators2Fix;
00108 btree_->iterator_map_.find(my_bid(), 0, size(), Iterators2Fix);
00109
00110 const unsigned end_of_smaller_part = size() / 2;
00111
00112 splitter.first = ((*block_)[end_of_smaller_part - 1]).first;
00113 splitter.second = NewBid;
00114
00115 const unsigned old_size = size();
00116
00117 std::copy(block_->begin(), block_->begin() + end_of_smaller_part, NewLeaf->block_->begin());
00118 NewLeaf->block_->info.cur_size = end_of_smaller_part;
00119
00120 std::copy(block_->begin() + end_of_smaller_part,
00121 block_->begin() + old_size, block_->begin());
00122 block_->info.cur_size = old_size - end_of_smaller_part;
00123 assert(size() + NewLeaf->size() == old_size);
00124
00125
00126 typename std::vector<iterator_base *>::iterator it2fix = Iterators2Fix.begin();
00127 for ( ; it2fix != Iterators2Fix.end(); ++it2fix)
00128 {
00129 btree_->iterator_map_.unregister_iterator(**it2fix);
00130
00131 if ((*it2fix)->pos < end_of_smaller_part)
00132 (*it2fix)->bid = NewBid;
00133
00134 else
00135 (*it2fix)->pos -= end_of_smaller_part;
00136
00137
00138 btree_->iterator_map_.register_iterator(**it2fix);
00139 }
00140
00141
00142 STXXL_VERBOSE1("btree::normal_leaf split leaf " << this
00143 << " splitter: " << splitter.first);
00144
00145 #if STXXL_VERBOSE_LEVEL >= 1
00146 if (PredLeaf)
00147 {
00148 STXXL_VERBOSE1("btree::normal_leaf pred_part.smallest = " << PredLeaf->front().first);
00149 STXXL_VERBOSE1("btree::normal_leaf pred_part.largest = " << PredLeaf->back().first);
00150 }
00151 #endif
00152 STXXL_VERBOSE1("btree::normal_leaf smaller_part.smallest = " << NewLeaf->front().first);
00153 STXXL_VERBOSE1("btree::normal_leaf smaller_part.largest = " << NewLeaf->back().first);
00154 STXXL_VERBOSE1("btree::normal_leaf larger_part.smallest = " << front().first);
00155 STXXL_VERBOSE1("btree::normal_leaf larger_part.largest = " << back().first);
00156
00157 btree_->leaf_cache_.unfix_node(NewBid);
00158 }
00159
00160 public:
00161 virtual ~normal_leaf()
00162 {
00163 delete block_;
00164 }
00165
00166 normal_leaf(btree_type * btree__,
00167 key_compare cmp) :
00168 block_(new block_type),
00169 btree_(btree__),
00170 cmp_(cmp),
00171 vcmp_(cmp)
00172 {
00173 assert(min_nelements() >= 2);
00174 assert(2 * min_nelements() - 1 <= max_nelements());
00175 assert(max_nelements() <= nelements);
00176 assert(unsigned(block_type::size) >= nelements + 1);
00177 }
00178
00179 bool overflows() const { return block_->info.cur_size > max_nelements(); }
00180 bool underflows() const { return block_->info.cur_size < min_nelements(); }
00181
00182 unsigned max_nelements() const { return max_size; }
00183 unsigned min_nelements() const { return min_size; }
00184
00185
00186 bid_type & succ()
00187 {
00188 return block_->info.succ;
00189 }
00190 bid_type & pred()
00191 {
00192 return block_->info.pred;
00193 }
00194
00195 const bid_type & succ() const
00196 {
00197 return block_->info.succ;
00198 }
00199 const bid_type & pred() const
00200 {
00201 return block_->info.pred;
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 unsigned size() const
00229 {
00230 return block_->info.cur_size;
00231 }
00232
00233 const bid_type & my_bid() const
00234 {
00235 return block_->info.me;
00236 }
00237
00238 void save()
00239 {
00240 request_ptr req = block_->write(my_bid());
00241 req->wait();
00242 }
00243
00244 request_ptr load(const bid_type & bid)
00245 {
00246 request_ptr req = block_->read(bid);
00247 req->wait();
00248 assert(bid == my_bid());
00249 return req;
00250 }
00251
00252 request_ptr prefetch(const bid_type & bid)
00253 {
00254 return block_->read(bid);
00255 }
00256
00257 void init(const bid_type & my_bid_)
00258 {
00259 block_->info.me = my_bid_;
00260 block_->info.succ = bid_type();
00261 block_->info.pred = bid_type();
00262 block_->info.cur_size = 0;
00263 }
00264
00265 reference operator [] (int i)
00266 {
00267 return (*block_)[i];
00268 }
00269
00270 const_reference operator [] (int i) const
00271 {
00272 return (*block_)[i];
00273 }
00274
00275 reference back()
00276 {
00277 return (*block_)[size() - 1];
00278 }
00279
00280 reference front()
00281 {
00282 return *(block_->begin());
00283 }
00284
00285 const_reference back() const
00286 {
00287 return (*block_)[size() - 1];
00288 }
00289
00290 const_reference front() const
00291 {
00292 return *(block_->begin());
00293 }
00294
00295 void dump()
00296 {
00297 STXXL_VERBOSE2("Dump of leaf " << this);
00298 for (unsigned i = 0; i < size(); ++i)
00299 STXXL_VERBOSE2((*this)[i].first << " " << (*this)[i].second);
00300 }
00301
00302 std::pair<iterator, bool> insert(
00303 const value_type & x,
00304 std::pair<key_type, bid_type> & splitter)
00305 {
00306 assert(size() <= max_nelements());
00307 splitter.first = key_compare::max_value();
00308
00309 typename block_type::iterator it =
00310 std::lower_bound(block_->begin(), block_->begin() + size(), x, vcmp_);
00311
00312 if (!(vcmp_(*it, x) || vcmp_(x, *it)) && it != (block_->begin() + size()))
00313 {
00314
00315 return std::pair<iterator, bool>(
00316 iterator(btree_, my_bid(), it - block_->begin()),
00317 false);
00318 }
00319
00320 typename block_type::iterator cur = block_->begin() + size() - 1;
00321
00322 for ( ; cur >= it; --cur)
00323 *(cur + 1) = *cur;
00324
00325
00326 *it = x;
00327
00328 std::vector<iterator_base *> Iterators2Fix;
00329 btree_->iterator_map_.find(my_bid(), it - block_->begin(), size(), Iterators2Fix);
00330 typename std::vector<iterator_base *>::iterator it2fix = Iterators2Fix.begin();
00331 for ( ; it2fix != Iterators2Fix.end(); ++it2fix)
00332 {
00333 btree_->iterator_map_.unregister_iterator(**it2fix);
00334 ++((*it2fix)->pos);
00335 btree_->iterator_map_.register_iterator(**it2fix);
00336 }
00337
00338 ++(block_->info.cur_size);
00339
00340 std::pair<iterator, bool> result(iterator(btree_, my_bid(), it - block_->begin()), true);
00341
00342 if (size() <= max_nelements())
00343 {
00344
00345 dump();
00346 return result;
00347 }
00348
00349
00350
00351 split(splitter);
00352
00353 return result;
00354 }
00355
00356 iterator begin()
00357 {
00358 return iterator(btree_, my_bid(), 0);
00359 }
00360
00361 const_iterator begin() const
00362 {
00363 return const_iterator(btree_, my_bid(), 0);
00364 }
00365
00366 iterator end()
00367 {
00368 return iterator(btree_, my_bid(), size());
00369 }
00370
00371 void increment_iterator(iterator_base & it) const
00372 {
00373 assert(it.bid == my_bid());
00374 assert(it.pos != size());
00375
00376 btree_->iterator_map_.unregister_iterator(it);
00377
00378 ++(it.pos);
00379 if (it.pos == size() && succ().valid())
00380 {
00381
00382 STXXL_VERBOSE1("btree::normal_leaf jumping to the next block");
00383 it.pos = 0;
00384 it.bid = succ();
00385 } else if (it.pos == 1 && btree_->prefetching_enabled_)
00386 {
00387
00388 if (succ().valid())
00389 btree_->leaf_cache_.prefetch_node(succ());
00390 }
00391 btree_->iterator_map_.register_iterator(it);
00392 }
00393
00394 void decrement_iterator(iterator_base & it) const
00395 {
00396 assert(it.bid == my_bid());
00397
00398 btree_->iterator_map_.unregister_iterator(it);
00399
00400 if (it.pos == 0)
00401 {
00402 assert(pred().valid());
00403
00404 it.bid = pred();
00405 normal_leaf const * PredLeaf = btree_->leaf_cache_.get_const_node(pred(), true);
00406 assert(PredLeaf);
00407 it.pos = PredLeaf->size() - 1;
00408
00409
00410 if (btree_->prefetching_enabled_ && PredLeaf->pred().valid())
00411 btree_->leaf_cache_.prefetch_node(PredLeaf->pred());
00412
00413
00414 btree_->leaf_cache_.unfix_node(pred());
00415 }
00416 else
00417 --it.pos;
00418
00419
00420 btree_->iterator_map_.register_iterator(it);
00421 }
00422
00423 iterator find(const key_type & k)
00424 {
00425 value_type searchVal(k, data_type());
00426 typename block_type::iterator lb =
00427 std::lower_bound(block_->begin(), block_->begin() + size(), searchVal, vcmp_);
00428 if (lb == block_->begin() + size() || lb->first != k)
00429 return btree_->end();
00430
00431
00432 return iterator(btree_, my_bid(), lb - block_->begin());
00433 }
00434
00435 const_iterator find(const key_type & k) const
00436 {
00437 value_type searchVal(k, data_type());
00438 typename block_type::iterator lb =
00439 std::lower_bound(block_->begin(), block_->begin() + size(), searchVal, vcmp_);
00440 if (lb == block_->begin() + size() || lb->first != k)
00441 return btree_->end();
00442
00443
00444 return const_iterator(btree_, my_bid(), lb - block_->begin());
00445 }
00446
00447 iterator lower_bound(const key_type & k)
00448 {
00449 value_type searchVal(k, data_type());
00450
00451 typename block_type::iterator lb =
00452 std::lower_bound(block_->begin(), block_->begin() + size(), searchVal, vcmp_);
00453
00454
00455 if (lb == block_->begin() + size() && succ().valid())
00456 {
00457 return iterator(btree_, succ(), 0);
00458 }
00459
00460 return iterator(btree_, my_bid(), lb - block_->begin());
00461 }
00462
00463 const_iterator lower_bound(const key_type & k) const
00464 {
00465 value_type searchVal(k, data_type());
00466 typename block_type::iterator lb =
00467 std::lower_bound(block_->begin(), block_->begin() + size(), searchVal, vcmp_);
00468
00469
00470 if (lb == block_->begin() + size() && succ().valid())
00471 {
00472 return iterator(btree_, succ(), 0);
00473 }
00474
00475 return const_iterator(btree_, my_bid(), lb - block_->begin());
00476 }
00477
00478 iterator upper_bound(const key_type & k)
00479 {
00480 value_type searchVal(k, data_type());
00481 typename block_type::iterator lb =
00482 std::upper_bound(block_->begin(), block_->begin() + size(), searchVal, vcmp_);
00483
00484
00485 if (lb == block_->begin() + size() && succ().valid())
00486 {
00487 return iterator(btree_, succ(), 0);
00488 }
00489
00490 return iterator(btree_, my_bid(), lb - block_->begin());
00491 }
00492
00493 const_iterator upper_bound(const key_type & k) const
00494 {
00495 value_type searchVal(k, data_type());
00496 typename block_type::iterator lb =
00497 std::upper_bound(block_->begin(), block_->begin() + size(), searchVal, vcmp_);
00498
00499
00500 if (lb == block_->begin() + size() && succ().valid())
00501 {
00502 return const_iterator(btree_, succ(), 0);
00503 }
00504
00505 return const_iterator(btree_, my_bid(), lb - block_->begin());
00506 }
00507
00508 size_type erase(const key_type & k)
00509 {
00510 value_type searchVal(k, data_type());
00511 typename block_type::iterator it =
00512 std::lower_bound(block_->begin(), block_->begin() + size(), searchVal, vcmp_);
00513
00514 if (it == block_->begin() + size() || it->first != k)
00515 return 0;
00516
00517
00518
00519 std::copy(it + 1, block_->begin() + size(), it);
00520
00521 std::vector<iterator_base *> Iterators2Fix;
00522 btree_->iterator_map_.find(my_bid(), it + 1 - block_->begin(), size(), Iterators2Fix);
00523 typename std::vector<iterator_base *>::iterator it2fix = Iterators2Fix.begin();
00524 for ( ; it2fix != Iterators2Fix.end(); ++it2fix)
00525 {
00526 STXXL_VERBOSE2("btree::normal_leaf updating iterator " << (*it2fix) << " (pos--)");
00527 btree_->iterator_map_.unregister_iterator(**it2fix);
00528 --((*it2fix)->pos);
00529 btree_->iterator_map_.register_iterator(**it2fix);
00530 }
00531
00532 --(block_->info.cur_size);
00533
00534 return 1;
00535 }
00536
00537 void fuse(const normal_leaf & Src)
00538 {
00539 STXXL_VERBOSE1("btree::normal_leaf Fusing");
00540 assert(vcmp_(Src.back(), front()));
00541 const unsigned SrcSize = Src.size();
00542
00543 typename block_type::iterator cur = block_->begin() + size() - 1;
00544 typename block_type::const_iterator begin = block_->begin();
00545
00546 for ( ; cur >= begin; --cur)
00547 *(cur + SrcSize) = *cur;
00548
00549
00550
00551 std::copy(Src.block_->begin(), Src.block_->begin() + SrcSize, block_->begin());
00552
00553
00554 std::vector<iterator_base *> Iterators2Fix;
00555 btree_->iterator_map_.find(my_bid(), 0, size(), Iterators2Fix);
00556 typename std::vector<iterator_base *>::iterator it2fix = Iterators2Fix.begin();
00557 for ( ; it2fix != Iterators2Fix.end(); ++it2fix)
00558 {
00559 STXXL_VERBOSE2("btree::normal_leaf updating iterator " << (*it2fix) <<
00560 " (pos+" << SrcSize << ")");
00561 btree_->iterator_map_.unregister_iterator(**it2fix);
00562 ((*it2fix)->pos) += SrcSize;
00563 btree_->iterator_map_.register_iterator(**it2fix);
00564 }
00565
00566 Iterators2Fix.clear();
00567 btree_->iterator_map_.find(Src.my_bid(), 0, SrcSize, Iterators2Fix);
00568 it2fix = Iterators2Fix.begin();
00569 for ( ; it2fix != Iterators2Fix.end(); ++it2fix)
00570 {
00571 STXXL_VERBOSE2("btree::normal_leaf updating iterator " << (*it2fix) <<
00572 " (bid=" << my_bid() << ")");
00573 btree_->iterator_map_.unregister_iterator(**it2fix);
00574 ((*it2fix)->bid) = my_bid();
00575 btree_->iterator_map_.register_iterator(**it2fix);
00576 }
00577
00578 block_->info.cur_size += SrcSize;
00579
00580
00581 pred() = Src.pred();
00582 if (pred().valid())
00583 {
00584 normal_leaf * NewPred = btree_->leaf_cache_.get_node(pred());
00585 assert(NewPred);
00586 NewPred->succ() = my_bid();
00587 }
00588 }
00589
00590 key_type balance(normal_leaf & Left)
00591 {
00592 STXXL_VERBOSE1("btree::normal_leaf Balancing leaves with bids " <<
00593 Left.my_bid() << " and " << my_bid());
00594 const unsigned TotalSize = Left.size() + size();
00595 unsigned newLeftSize = TotalSize / 2;
00596 assert(newLeftSize <= Left.max_nelements());
00597 assert(newLeftSize >= Left.min_nelements());
00598 unsigned newRightSize = TotalSize - newLeftSize;
00599 assert(newRightSize <= max_nelements());
00600 assert(newRightSize >= min_nelements());
00601
00602 assert(vcmp_(Left.back(), front()) || size() == 0);
00603
00604 if (newLeftSize < Left.size())
00605 {
00606 const unsigned nEl2Move = Left.size() - newLeftSize;
00607
00608 typename block_type::iterator cur = block_->begin() + size() - 1;
00609 typename block_type::const_iterator begin = block_->begin();
00610
00611 for ( ; cur >= begin; --cur)
00612 *(cur + nEl2Move) = *cur;
00613
00614
00615
00616 std::copy(Left.block_->begin() + newLeftSize,
00617 Left.block_->begin() + Left.size(), block_->begin());
00618
00619 std::vector<iterator_base *> Iterators2Fix1;
00620 std::vector<iterator_base *> Iterators2Fix2;
00621 btree_->iterator_map_.find(my_bid(), 0, size(), Iterators2Fix1);
00622 btree_->iterator_map_.find(Left.my_bid(), newLeftSize, Left.size(), Iterators2Fix2);
00623
00624 typename std::vector<iterator_base *>::iterator it2fix = Iterators2Fix1.begin();
00625 for ( ; it2fix != Iterators2Fix1.end(); ++it2fix)
00626 {
00627 STXXL_VERBOSE2("btree::normal_leaf updating iterator " << (*it2fix) <<
00628 " (pos+" << nEl2Move << ")");
00629 btree_->iterator_map_.unregister_iterator(**it2fix);
00630 ((*it2fix)->pos) += nEl2Move;
00631 btree_->iterator_map_.register_iterator(**it2fix);
00632 }
00633
00634
00635 it2fix = Iterators2Fix2.begin();
00636 for ( ; it2fix != Iterators2Fix2.end(); ++it2fix)
00637 {
00638 STXXL_VERBOSE2("btree::normal_leaf updating iterator " << (*it2fix) <<
00639 " (pos-" << newLeftSize << " bid=" << my_bid() << ")");
00640 btree_->iterator_map_.unregister_iterator(**it2fix);
00641 ((*it2fix)->bid) = my_bid();
00642 ((*it2fix)->pos) -= newLeftSize;
00643 btree_->iterator_map_.register_iterator(**it2fix);
00644 }
00645 }
00646 else
00647 {
00648 assert(newRightSize < size());
00649
00650 const unsigned nEl2Move = size() - newRightSize;
00651
00652
00653 std::copy(block_->begin(),
00654 block_->begin() + nEl2Move, Left.block_->begin() + Left.size());
00655
00656 std::copy(block_->begin() + nEl2Move,
00657 block_->begin() + size(), block_->begin());
00658
00659 std::vector<iterator_base *> Iterators2Fix1;
00660 std::vector<iterator_base *> Iterators2Fix2;
00661 btree_->iterator_map_.find(my_bid(), nEl2Move, size(), Iterators2Fix1);
00662 btree_->iterator_map_.find(my_bid(), 0, nEl2Move - 1, Iterators2Fix2);
00663
00664 typename std::vector<iterator_base *>::iterator it2fix = Iterators2Fix1.begin();
00665 for ( ; it2fix != Iterators2Fix1.end(); ++it2fix)
00666 {
00667 STXXL_VERBOSE2("btree::normal_leaf updating iterator " << (*it2fix) <<
00668 " (pos-" << nEl2Move << ")");
00669 btree_->iterator_map_.unregister_iterator(**it2fix);
00670 ((*it2fix)->pos) -= nEl2Move;
00671 btree_->iterator_map_.register_iterator(**it2fix);
00672 }
00673
00674
00675 it2fix = Iterators2Fix2.begin();
00676 for ( ; it2fix != Iterators2Fix2.end(); ++it2fix)
00677 {
00678 STXXL_VERBOSE2("btree::normal_leaf updating iterator " << (*it2fix) <<
00679 " (pos+" << Left.size() << " bid=" << Left.my_bid() << ")");
00680 btree_->iterator_map_.unregister_iterator(**it2fix);
00681 ((*it2fix)->bid) = Left.my_bid();
00682 ((*it2fix)->pos) += Left.size();
00683 btree_->iterator_map_.register_iterator(**it2fix);
00684 }
00685 }
00686
00687 block_->info.cur_size = newRightSize;
00688 Left.block_->info.cur_size = newLeftSize;
00689
00690 return Left.back().first;
00691 }
00692
00693 void push_back(const value_type & x)
00694 {
00695 (*this)[size()] = x;
00696 ++(block_->info.cur_size);
00697 }
00698 };
00699 }
00700
00701
00702 __STXXL_END_NAMESPACE
00703
00704 #endif