STX B+ Tree Template Classes 0.8.6
|
00001 // $Id: btree.h 128 2011-05-18 07:23:35Z tb $ -*- fill-column: 79 -*- 00006 /* 00007 * STX B+ Tree Template Classes v0.8.6 00008 * Copyright (C) 2008-2011 Timo Bingmann 00009 * 00010 * This library is free software; you can redistribute it and/or modify it 00011 * under the terms of the GNU Lesser General Public License as published by the 00012 * Free Software Foundation; either version 2.1 of the License, or (at your 00013 * option) any later version. 00014 * 00015 * This library is distributed in the hope that it will be useful, but WITHOUT 00016 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00017 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License 00018 * for more details. 00019 * 00020 * You should have received a copy of the GNU Lesser General Public License 00021 * along with this library; if not, write to the Free Software Foundation, 00022 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00023 */ 00024 00025 #ifndef _STX_BTREE_H_ 00026 #define _STX_BTREE_H_ 00027 00028 // *** Required Headers from the STL 00029 00030 #include <algorithm> 00031 #include <functional> 00032 #include <istream> 00033 #include <ostream> 00034 #include <memory> 00035 #include <cstddef> 00036 #include <assert.h> 00037 00038 // *** Debugging Macros 00039 00040 #ifdef BTREE_DEBUG 00041 00042 #include <iostream> 00043 00045 #define BTREE_PRINT(x) do { if (debug) (std::cout << x); } while(0) 00046 00048 #define BTREE_ASSERT(x) do { assert(x); } while(0) 00049 00050 #else 00051 00053 #define BTREE_PRINT(x) do { } while(0) 00054 00056 #define BTREE_ASSERT(x) do { } while(0) 00057 00058 #endif 00059 00061 #define BTREE_MAX(a,b) ((a) < (b) ? (b) : (a)) 00062 00063 #ifndef BTREE_FRIENDS 00064 00065 00066 00067 #define BTREE_FRIENDS friend class btree_friend; 00068 #endif 00069 00071 namespace stx { 00072 00075 template <typename _Key> 00076 struct btree_default_set_traits 00077 { 00080 static const bool selfverify = false; 00081 00086 static const bool debug = false; 00087 00090 static const int leafslots = BTREE_MAX( 8, 256 / (sizeof(_Key)) ); 00091 00094 static const int innerslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(void*)) ); 00095 }; 00096 00099 template <typename _Key, typename _Data> 00100 struct btree_default_map_traits 00101 { 00104 static const bool selfverify = false; 00105 00110 static const bool debug = false; 00111 00114 static const int leafslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(_Data)) ); 00115 00118 static const int innerslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(void*)) ); 00119 }; 00120 00134 template <typename _Key, typename _Data, 00135 typename _Value = std::pair<_Key, _Data>, 00136 typename _Compare = std::less<_Key>, 00137 typename _Traits = btree_default_map_traits<_Key, _Data>, 00138 bool _Duplicates = false, 00139 typename _Alloc = std::allocator<_Value> > 00140 class btree 00141 { 00142 public: 00143 // *** Template Parameter Types 00144 00147 typedef _Key key_type; 00148 00151 typedef _Data data_type; 00152 00157 typedef _Value value_type; 00158 00160 typedef _Compare key_compare; 00161 00164 typedef _Traits traits; 00165 00168 static const bool allow_duplicates = _Duplicates; 00169 00171 typedef _Alloc allocator_type; 00172 00173 // The macro BTREE_FRIENDS can be used by outside class to access the B+ 00174 // tree internals. This was added for wxBTreeDemo to be able to draw the 00175 // tree. 00176 BTREE_FRIENDS 00177 00178 public: 00179 // *** Constructed Types 00180 00182 typedef btree<key_type, data_type, value_type, key_compare, 00183 traits, allow_duplicates, allocator_type> btree_self; 00184 00186 typedef size_t size_type; 00187 00189 typedef std::pair<key_type, data_type> pair_type; 00190 00191 public: 00192 // *** Static Constant Options and Values of the B+ Tree 00193 00195 static const unsigned short leafslotmax = traits::leafslots; 00196 00199 static const unsigned short innerslotmax = traits::innerslots; 00200 00204 static const unsigned short minleafslots = (leafslotmax / 2); 00205 00209 static const unsigned short mininnerslots = (innerslotmax / 2); 00210 00213 static const bool selfverify = traits::selfverify; 00214 00218 static const bool debug = traits::debug; 00219 00220 private: 00221 // *** Node Classes for In-Memory Nodes 00222 00225 struct node 00226 { 00228 unsigned short level; 00229 00232 unsigned short slotuse; 00233 00235 inline void initialize(const unsigned short l) 00236 { 00237 level = l; 00238 slotuse = 0; 00239 } 00240 00242 inline bool isleafnode() const 00243 { 00244 return (level == 0); 00245 } 00246 }; 00247 00250 struct inner_node : public node 00251 { 00253 typedef typename _Alloc::template rebind<inner_node>::other alloc_type; 00254 00256 key_type slotkey[innerslotmax]; 00257 00259 node* childid[innerslotmax+1]; 00260 00262 inline void initialize(const unsigned short l) 00263 { 00264 node::initialize(l); 00265 } 00266 00268 inline bool isfull() const 00269 { 00270 return (node::slotuse == innerslotmax); 00271 } 00272 00274 inline bool isfew() const 00275 { 00276 return (node::slotuse <= mininnerslots); 00277 } 00278 00280 inline bool isunderflow() const 00281 { 00282 return (node::slotuse < mininnerslots); 00283 } 00284 }; 00285 00289 struct leaf_node : public node 00290 { 00292 typedef typename _Alloc::template rebind<leaf_node>::other alloc_type; 00293 00295 leaf_node *prevleaf; 00296 00298 leaf_node *nextleaf; 00299 00301 key_type slotkey[leafslotmax]; 00302 00304 data_type slotdata[leafslotmax]; 00305 00307 inline void initialize() 00308 { 00309 node::initialize(0); 00310 prevleaf = nextleaf = NULL; 00311 } 00312 00314 inline bool isfull() const 00315 { 00316 return (node::slotuse == leafslotmax); 00317 } 00318 00320 inline bool isfew() const 00321 { 00322 return (node::slotuse <= minleafslots); 00323 } 00324 00326 inline bool isunderflow() const 00327 { 00328 return (node::slotuse < minleafslots); 00329 } 00330 }; 00331 00332 private: 00333 // *** Template Magic to Convert a pair or key/data types to a value_type 00334 00337 template <typename value_type, typename pair_type> 00338 struct btree_pair_to_value 00339 { 00341 inline value_type operator()(pair_type& p) const { 00342 return p.first; 00343 } 00345 inline value_type operator()(const pair_type& p) const { 00346 return p.first; 00347 } 00348 }; 00349 00351 template <typename value_type> 00352 struct btree_pair_to_value<value_type, value_type> 00353 { 00355 inline value_type operator()(pair_type& p) const { 00356 return p; 00357 } 00359 inline value_type operator()(const pair_type& p) const { 00360 return p; 00361 } 00362 }; 00363 00366 typedef btree_pair_to_value<value_type, pair_type> pair_to_value_type; 00367 00368 public: 00369 // *** Iterators and Reverse Iterators 00370 00371 class iterator; 00372 class const_iterator; 00373 class reverse_iterator; 00374 class const_reverse_iterator; 00375 00378 class iterator 00379 { 00380 public: 00381 // *** Types 00382 00384 typedef typename btree::key_type key_type; 00385 00387 typedef typename btree::data_type data_type; 00388 00390 typedef typename btree::value_type value_type; 00391 00393 typedef typename btree::pair_type pair_type; 00394 00396 typedef value_type& reference; 00397 00399 typedef value_type* pointer; 00400 00402 typedef std::bidirectional_iterator_tag iterator_category; 00403 00405 typedef ptrdiff_t difference_type; 00406 00408 typedef iterator self; 00409 00410 private: 00411 // *** Members 00412 00414 typename btree::leaf_node* currnode; 00415 00417 unsigned short currslot; 00418 00420 friend class const_iterator; 00421 00423 friend class reverse_iterator; 00424 00426 friend class const_reverse_iterator; 00427 00430 friend class btree<key_type, data_type, value_type, key_compare, traits, allow_duplicates>; 00431 00434 mutable value_type temp_value; 00435 00436 // The macro BTREE_FRIENDS can be used by outside class to access the B+ 00437 // tree internals. This was added for wxBTreeDemo to be able to draw the 00438 // tree. 00439 BTREE_FRIENDS 00440 00441 public: 00442 // *** Methods 00443 00445 inline iterator() 00446 : currnode(NULL), currslot(0) 00447 { } 00448 00450 inline iterator(typename btree::leaf_node *l, unsigned short s) 00451 : currnode(l), currslot(s) 00452 { } 00453 00455 inline iterator(const reverse_iterator &it) 00456 : currnode(it.currnode), currslot(it.currslot) 00457 { } 00458 00461 inline reference operator*() const 00462 { 00463 temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot], 00464 currnode->slotdata[currslot]) ); 00465 return temp_value; 00466 } 00467 00471 inline pointer operator->() const 00472 { 00473 temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot], 00474 currnode->slotdata[currslot]) ); 00475 return &temp_value; 00476 } 00477 00479 inline const key_type& key() const 00480 { 00481 return currnode->slotkey[currslot]; 00482 } 00483 00485 inline data_type& data() const 00486 { 00487 return currnode->slotdata[currslot]; 00488 } 00489 00491 inline self& operator++() 00492 { 00493 if (currslot + 1 < currnode->slotuse) { 00494 ++currslot; 00495 } 00496 else if (currnode->nextleaf != NULL) { 00497 currnode = currnode->nextleaf; 00498 currslot = 0; 00499 } 00500 else { 00501 // this is end() 00502 currslot = currnode->slotuse; 00503 } 00504 00505 return *this; 00506 } 00507 00509 inline self operator++(int) 00510 { 00511 self tmp = *this; // copy ourselves 00512 00513 if (currslot + 1 < currnode->slotuse) { 00514 ++currslot; 00515 } 00516 else if (currnode->nextleaf != NULL) { 00517 currnode = currnode->nextleaf; 00518 currslot = 0; 00519 } 00520 else { 00521 // this is end() 00522 currslot = currnode->slotuse; 00523 } 00524 00525 return tmp; 00526 } 00527 00529 inline self& operator--() 00530 { 00531 if (currslot > 0) { 00532 --currslot; 00533 } 00534 else if (currnode->prevleaf != NULL) { 00535 currnode = currnode->prevleaf; 00536 currslot = currnode->slotuse - 1; 00537 } 00538 else { 00539 // this is begin() 00540 currslot = 0; 00541 } 00542 00543 return *this; 00544 } 00545 00547 inline self operator--(int) 00548 { 00549 self tmp = *this; // copy ourselves 00550 00551 if (currslot > 0) { 00552 --currslot; 00553 } 00554 else if (currnode->prevleaf != NULL) { 00555 currnode = currnode->prevleaf; 00556 currslot = currnode->slotuse - 1; 00557 } 00558 else { 00559 // this is begin() 00560 currslot = 0; 00561 } 00562 00563 return tmp; 00564 } 00565 00567 inline bool operator==(const self& x) const 00568 { 00569 return (x.currnode == currnode) && (x.currslot == currslot); 00570 } 00571 00573 inline bool operator!=(const self& x) const 00574 { 00575 return (x.currnode != currnode) || (x.currslot != currslot); 00576 } 00577 }; 00578 00581 class const_iterator 00582 { 00583 public: 00584 // *** Types 00585 00587 typedef typename btree::key_type key_type; 00588 00590 typedef typename btree::data_type data_type; 00591 00593 typedef typename btree::value_type value_type; 00594 00596 typedef typename btree::pair_type pair_type; 00597 00599 typedef const value_type& reference; 00600 00602 typedef const value_type* pointer; 00603 00605 typedef std::bidirectional_iterator_tag iterator_category; 00606 00608 typedef ptrdiff_t difference_type; 00609 00611 typedef const_iterator self; 00612 00613 private: 00614 // *** Members 00615 00617 const typename btree::leaf_node* currnode; 00618 00620 unsigned short currslot; 00621 00623 friend class const_reverse_iterator; 00624 00627 mutable value_type temp_value; 00628 00629 // The macro BTREE_FRIENDS can be used by outside class to access the B+ 00630 // tree internals. This was added for wxBTreeDemo to be able to draw the 00631 // tree. 00632 BTREE_FRIENDS 00633 00634 public: 00635 // *** Methods 00636 00638 inline const_iterator() 00639 : currnode(NULL), currslot(0) 00640 { } 00641 00643 inline const_iterator(const typename btree::leaf_node *l, unsigned short s) 00644 : currnode(l), currslot(s) 00645 { } 00646 00648 inline const_iterator(const iterator &it) 00649 : currnode(it.currnode), currslot(it.currslot) 00650 { } 00651 00653 inline const_iterator(const reverse_iterator &it) 00654 : currnode(it.currnode), currslot(it.currslot) 00655 { } 00656 00658 inline const_iterator(const const_reverse_iterator &it) 00659 : currnode(it.currnode), currslot(it.currslot) 00660 { } 00661 00665 inline reference operator*() const 00666 { 00667 temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot], 00668 currnode->slotdata[currslot]) ); 00669 return temp_value; 00670 } 00671 00675 inline pointer operator->() const 00676 { 00677 temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot], 00678 currnode->slotdata[currslot]) ); 00679 return &temp_value; 00680 } 00681 00683 inline const key_type& key() const 00684 { 00685 return currnode->slotkey[currslot]; 00686 } 00687 00689 inline const data_type& data() const 00690 { 00691 return currnode->slotdata[currslot]; 00692 } 00693 00695 inline self& operator++() 00696 { 00697 if (currslot + 1 < currnode->slotuse) { 00698 ++currslot; 00699 } 00700 else if (currnode->nextleaf != NULL) { 00701 currnode = currnode->nextleaf; 00702 currslot = 0; 00703 } 00704 else { 00705 // this is end() 00706 currslot = currnode->slotuse; 00707 } 00708 00709 return *this; 00710 } 00711 00713 inline self operator++(int) 00714 { 00715 self tmp = *this; // copy ourselves 00716 00717 if (currslot + 1 < currnode->slotuse) { 00718 ++currslot; 00719 } 00720 else if (currnode->nextleaf != NULL) { 00721 currnode = currnode->nextleaf; 00722 currslot = 0; 00723 } 00724 else { 00725 // this is end() 00726 currslot = currnode->slotuse; 00727 } 00728 00729 return tmp; 00730 } 00731 00733 inline self& operator--() 00734 { 00735 if (currslot > 0) { 00736 --currslot; 00737 } 00738 else if (currnode->prevleaf != NULL) { 00739 currnode = currnode->prevleaf; 00740 currslot = currnode->slotuse - 1; 00741 } 00742 else { 00743 // this is begin() 00744 currslot = 0; 00745 } 00746 00747 return *this; 00748 } 00749 00751 inline self operator--(int) 00752 { 00753 self tmp = *this; // copy ourselves 00754 00755 if (currslot > 0) { 00756 --currslot; 00757 } 00758 else if (currnode->prevleaf != NULL) { 00759 currnode = currnode->prevleaf; 00760 currslot = currnode->slotuse - 1; 00761 } 00762 else { 00763 // this is begin() 00764 currslot = 0; 00765 } 00766 00767 return tmp; 00768 } 00769 00771 inline bool operator==(const self& x) const 00772 { 00773 return (x.currnode == currnode) && (x.currslot == currslot); 00774 } 00775 00777 inline bool operator!=(const self& x) const 00778 { 00779 return (x.currnode != currnode) || (x.currslot != currslot); 00780 } 00781 }; 00782 00785 class reverse_iterator 00786 { 00787 public: 00788 // *** Types 00789 00791 typedef typename btree::key_type key_type; 00792 00794 typedef typename btree::data_type data_type; 00795 00797 typedef typename btree::value_type value_type; 00798 00800 typedef typename btree::pair_type pair_type; 00801 00803 typedef value_type& reference; 00804 00806 typedef value_type* pointer; 00807 00809 typedef std::bidirectional_iterator_tag iterator_category; 00810 00812 typedef ptrdiff_t difference_type; 00813 00815 typedef reverse_iterator self; 00816 00817 private: 00818 // *** Members 00819 00821 typename btree::leaf_node* currnode; 00822 00824 unsigned short currslot; 00825 00827 friend class iterator; 00828 00830 friend class const_iterator; 00831 00833 friend class const_reverse_iterator; 00834 00837 mutable value_type temp_value; 00838 00839 // The macro BTREE_FRIENDS can be used by outside class to access the B+ 00840 // tree internals. This was added for wxBTreeDemo to be able to draw the 00841 // tree. 00842 BTREE_FRIENDS 00843 00844 public: 00845 // *** Methods 00846 00848 inline reverse_iterator() 00849 : currnode(NULL), currslot(0) 00850 { } 00851 00853 inline reverse_iterator(typename btree::leaf_node *l, unsigned short s) 00854 : currnode(l), currslot(s) 00855 { } 00856 00858 inline reverse_iterator(const iterator &it) 00859 : currnode(it.currnode), currslot(it.currslot) 00860 { } 00861 00864 inline reference operator*() const 00865 { 00866 BTREE_ASSERT(currslot > 0); 00867 temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot - 1], 00868 currnode->slotdata[currslot - 1]) ); 00869 return temp_value; 00870 } 00871 00875 inline pointer operator->() const 00876 { 00877 BTREE_ASSERT(currslot > 0); 00878 temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot - 1], 00879 currnode->slotdata[currslot - 1]) ); 00880 return &temp_value; 00881 } 00882 00884 inline const key_type& key() const 00885 { 00886 BTREE_ASSERT(currslot > 0); 00887 return currnode->slotkey[currslot - 1]; 00888 } 00889 00891 inline data_type& data() const 00892 { 00893 BTREE_ASSERT(currslot > 0); 00894 return currnode->slotdata[currslot - 1]; 00895 } 00896 00898 inline self& operator++() 00899 { 00900 if (currslot > 1) { 00901 --currslot; 00902 } 00903 else if (currnode->prevleaf != NULL) { 00904 currnode = currnode->prevleaf; 00905 currslot = currnode->slotuse; 00906 } 00907 else { 00908 // this is begin() == rend() 00909 currslot = 0; 00910 } 00911 00912 return *this; 00913 } 00914 00916 inline self operator++(int) 00917 { 00918 self tmp = *this; // copy ourselves 00919 00920 if (currslot > 1) { 00921 --currslot; 00922 } 00923 else if (currnode->prevleaf != NULL) { 00924 currnode = currnode->prevleaf; 00925 currslot = currnode->slotuse; 00926 } 00927 else { 00928 // this is begin() == rend() 00929 currslot = 0; 00930 } 00931 00932 return tmp; 00933 } 00934 00936 inline self& operator--() 00937 { 00938 if (currslot < currnode->slotuse) { 00939 ++currslot; 00940 } 00941 else if (currnode->nextleaf != NULL) { 00942 currnode = currnode->nextleaf; 00943 currslot = 1; 00944 } 00945 else { 00946 // this is end() == rbegin() 00947 currslot = currnode->slotuse; 00948 } 00949 00950 return *this; 00951 } 00952 00954 inline self operator--(int) 00955 { 00956 self tmp = *this; // copy ourselves 00957 00958 if (currslot < currnode->slotuse) { 00959 ++currslot; 00960 } 00961 else if (currnode->nextleaf != NULL) { 00962 currnode = currnode->nextleaf; 00963 currslot = 1; 00964 } 00965 else { 00966 // this is end() == rbegin() 00967 currslot = currnode->slotuse; 00968 } 00969 00970 return tmp; 00971 } 00972 00974 inline bool operator==(const self& x) const 00975 { 00976 return (x.currnode == currnode) && (x.currslot == currslot); 00977 } 00978 00980 inline bool operator!=(const self& x) const 00981 { 00982 return (x.currnode != currnode) || (x.currslot != currslot); 00983 } 00984 }; 00985 00988 class const_reverse_iterator 00989 { 00990 public: 00991 // *** Types 00992 00994 typedef typename btree::key_type key_type; 00995 00997 typedef typename btree::data_type data_type; 00998 01000 typedef typename btree::value_type value_type; 01001 01003 typedef typename btree::pair_type pair_type; 01004 01006 typedef const value_type& reference; 01007 01009 typedef const value_type* pointer; 01010 01012 typedef std::bidirectional_iterator_tag iterator_category; 01013 01015 typedef ptrdiff_t difference_type; 01016 01018 typedef const_reverse_iterator self; 01019 01020 private: 01021 // *** Members 01022 01024 const typename btree::leaf_node* currnode; 01025 01027 unsigned short currslot; 01028 01030 friend class reverse_iterator; 01031 01034 mutable value_type temp_value; 01035 01036 // The macro BTREE_FRIENDS can be used by outside class to access the B+ 01037 // tree internals. This was added for wxBTreeDemo to be able to draw the 01038 // tree. 01039 BTREE_FRIENDS 01040 01041 public: 01042 // *** Methods 01043 01045 inline const_reverse_iterator() 01046 : currnode(NULL), currslot(0) 01047 { } 01048 01050 inline const_reverse_iterator(const typename btree::leaf_node *l, unsigned short s) 01051 : currnode(l), currslot(s) 01052 { } 01053 01055 inline const_reverse_iterator(const iterator &it) 01056 : currnode(it.currnode), currslot(it.currslot) 01057 { } 01058 01060 inline const_reverse_iterator(const const_iterator &it) 01061 : currnode(it.currnode), currslot(it.currslot) 01062 { } 01063 01065 inline const_reverse_iterator(const reverse_iterator &it) 01066 : currnode(it.currnode), currslot(it.currslot) 01067 { } 01068 01072 inline reference operator*() const 01073 { 01074 BTREE_ASSERT(currslot > 0); 01075 temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot - 1], 01076 currnode->slotdata[currslot - 1]) ); 01077 return temp_value; 01078 } 01079 01083 inline pointer operator->() const 01084 { 01085 BTREE_ASSERT(currslot > 0); 01086 temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot - 1], 01087 currnode->slotdata[currslot - 1]) ); 01088 return &temp_value; 01089 } 01090 01092 inline const key_type& key() const 01093 { 01094 BTREE_ASSERT(currslot > 0); 01095 return currnode->slotkey[currslot - 1]; 01096 } 01097 01099 inline const data_type& data() const 01100 { 01101 BTREE_ASSERT(currslot > 0); 01102 return currnode->slotdata[currslot - 1]; 01103 } 01104 01106 inline self& operator++() 01107 { 01108 if (currslot > 1) { 01109 --currslot; 01110 } 01111 else if (currnode->prevleaf != NULL) { 01112 currnode = currnode->prevleaf; 01113 currslot = currnode->slotuse; 01114 } 01115 else { 01116 // this is begin() == rend() 01117 currslot = 0; 01118 } 01119 01120 return *this; 01121 } 01122 01124 inline self operator++(int) 01125 { 01126 self tmp = *this; // copy ourselves 01127 01128 if (currslot > 1) { 01129 --currslot; 01130 } 01131 else if (currnode->prevleaf != NULL) { 01132 currnode = currnode->prevleaf; 01133 currslot = currnode->slotuse; 01134 } 01135 else { 01136 // this is begin() == rend() 01137 currslot = 0; 01138 } 01139 01140 return tmp; 01141 } 01142 01144 inline self& operator--() 01145 { 01146 if (currslot < currnode->slotuse) { 01147 ++currslot; 01148 } 01149 else if (currnode->nextleaf != NULL) { 01150 currnode = currnode->nextleaf; 01151 currslot = 1; 01152 } 01153 else { 01154 // this is end() == rbegin() 01155 currslot = currnode->slotuse; 01156 } 01157 01158 return *this; 01159 } 01160 01162 inline self operator--(int) 01163 { 01164 self tmp = *this; // copy ourselves 01165 01166 if (currslot < currnode->slotuse) { 01167 ++currslot; 01168 } 01169 else if (currnode->nextleaf != NULL) { 01170 currnode = currnode->nextleaf; 01171 currslot = 1; 01172 } 01173 else { 01174 // this is end() == rbegin() 01175 currslot = currnode->slotuse; 01176 } 01177 01178 return tmp; 01179 } 01180 01182 inline bool operator==(const self& x) const 01183 { 01184 return (x.currnode == currnode) && (x.currslot == currslot); 01185 } 01186 01188 inline bool operator!=(const self& x) const 01189 { 01190 return (x.currnode != currnode) || (x.currslot != currslot); 01191 } 01192 }; 01193 01194 public: 01195 // *** Small Statistics Structure 01196 01199 struct tree_stats 01200 { 01202 size_type itemcount; 01203 01205 size_type leaves; 01206 01208 size_type innernodes; 01209 01211 static const unsigned short leafslots = btree_self::leafslotmax; 01212 01214 static const unsigned short innerslots = btree_self::innerslotmax; 01215 01217 inline tree_stats() 01218 : itemcount(0), 01219 leaves(0), innernodes(0) 01220 { 01221 } 01222 01224 inline size_type nodes() const 01225 { 01226 return innernodes + leaves; 01227 } 01228 01230 inline double avgfill_leaves() const 01231 { 01232 return static_cast<double>(itemcount) / (leaves * leafslots); 01233 } 01234 }; 01235 01236 private: 01237 // *** Tree Object Data Members 01238 01240 node* root; 01241 01243 leaf_node *headleaf; 01244 01246 leaf_node *tailleaf; 01247 01249 tree_stats stats; 01250 01253 key_compare key_less; 01254 01256 allocator_type allocator; 01257 01258 public: 01259 // *** Constructors and Destructor 01260 01263 explicit inline btree(const allocator_type &alloc = allocator_type()) 01264 : root(NULL), headleaf(NULL), tailleaf(NULL), allocator(alloc) 01265 { 01266 } 01267 01270 explicit inline btree(const key_compare &kcf, 01271 const allocator_type &alloc = allocator_type()) 01272 : root(NULL), headleaf(NULL), tailleaf(NULL), 01273 key_less(kcf), allocator(alloc) 01274 { 01275 } 01276 01278 template <class InputIterator> 01279 inline btree(InputIterator first, InputIterator last, 01280 const allocator_type &alloc = allocator_type()) 01281 : root(NULL), headleaf(NULL), tailleaf(NULL), allocator(alloc) 01282 { 01283 insert(first, last); 01284 } 01285 01288 template <class InputIterator> 01289 inline btree(InputIterator first, InputIterator last, const key_compare &kcf, 01290 const allocator_type &alloc = allocator_type()) 01291 : root(NULL), headleaf(NULL), tailleaf(NULL), 01292 key_less(kcf), allocator(alloc) 01293 { 01294 insert(first, last); 01295 } 01296 01298 inline ~btree() 01299 { 01300 clear(); 01301 } 01302 01304 void swap(btree_self& from) 01305 { 01306 std::swap(root, from.root); 01307 std::swap(headleaf, from.headleaf); 01308 std::swap(tailleaf, from.tailleaf); 01309 std::swap(stats, from.stats); 01310 std::swap(key_less, from.key_less); 01311 std::swap(allocator, from.allocator); 01312 } 01313 01314 public: 01315 // *** Key and Value Comparison Function Objects 01316 01318 class value_compare 01319 { 01320 protected: 01322 key_compare key_comp; 01323 01325 inline value_compare(key_compare kc) 01326 : key_comp(kc) 01327 { } 01328 01330 friend class btree<key_type, data_type, value_type, key_compare, traits, allow_duplicates>; 01331 01332 public: 01334 inline bool operator()(const value_type& x, const value_type& y) const 01335 { 01336 return key_comp(x.first, y.first); 01337 } 01338 }; 01339 01341 inline key_compare key_comp() const 01342 { 01343 return key_less; 01344 } 01345 01348 inline value_compare value_comp() const 01349 { 01350 return value_compare(key_less); 01351 } 01352 01353 private: 01354 // *** Convenient Key Comparison Functions Generated From key_less 01355 01357 inline bool key_lessequal(const key_type &a, const key_type b) const 01358 { 01359 return !key_less(b, a); 01360 } 01361 01363 inline bool key_greater(const key_type &a, const key_type &b) const 01364 { 01365 return key_less(b, a); 01366 } 01367 01369 inline bool key_greaterequal(const key_type &a, const key_type b) const 01370 { 01371 return !key_less(a, b); 01372 } 01373 01376 inline bool key_equal(const key_type &a, const key_type &b) const 01377 { 01378 return !key_less(a, b) && !key_less(b, a); 01379 } 01380 01381 public: 01382 // *** Allocators 01383 01385 allocator_type get_allocator() const 01386 { 01387 return allocator; 01388 } 01389 01390 private: 01391 // *** Node Object Allocation and Deallocation Functions 01392 01394 typename leaf_node::alloc_type leaf_node_allocator() 01395 { 01396 return typename leaf_node::alloc_type(allocator); 01397 } 01398 01400 typename inner_node::alloc_type inner_node_allocator() 01401 { 01402 return typename inner_node::alloc_type(allocator); 01403 } 01404 01406 inline leaf_node* allocate_leaf() 01407 { 01408 leaf_node *n = new (leaf_node_allocator().allocate(1)) leaf_node(); 01409 n->initialize(); 01410 stats.leaves++; 01411 return n; 01412 } 01413 01415 inline inner_node* allocate_inner(unsigned short level) 01416 { 01417 inner_node *n = new (inner_node_allocator().allocate(1)) inner_node(); 01418 n->initialize(level); 01419 stats.innernodes++; 01420 return n; 01421 } 01422 01425 inline void free_node(node *n) 01426 { 01427 if (n->isleafnode()) { 01428 leaf_node *ln = static_cast<leaf_node*>(n); 01429 typename leaf_node::alloc_type a(leaf_node_allocator()); 01430 a.destroy(ln); 01431 a.deallocate(ln, 1); 01432 stats.leaves--; 01433 } 01434 else { 01435 inner_node *in = static_cast<inner_node*>(n); 01436 typename inner_node::alloc_type a(inner_node_allocator()); 01437 a.destroy(in); 01438 a.deallocate(in, 1); 01439 stats.innernodes--; 01440 } 01441 } 01442 01443 public: 01444 // *** Fast Destruction of the B+ Tree 01445 01447 void clear() 01448 { 01449 if (root) 01450 { 01451 clear_recursive(root); 01452 free_node(root); 01453 01454 root = NULL; 01455 headleaf = tailleaf = NULL; 01456 01457 stats = tree_stats(); 01458 } 01459 01460 BTREE_ASSERT(stats.itemcount == 0); 01461 } 01462 01463 private: 01465 void clear_recursive(node *n) 01466 { 01467 if (n->isleafnode()) 01468 { 01469 leaf_node *leafnode = static_cast<leaf_node*>(n); 01470 01471 for (unsigned int slot = 0; slot < leafnode->slotuse; ++slot) 01472 { 01473 // data objects are deleted by leaf_node's destructor 01474 } 01475 } 01476 else 01477 { 01478 inner_node *innernode = static_cast<inner_node*>(n); 01479 01480 for (unsigned short slot = 0; slot < innernode->slotuse + 1; ++slot) 01481 { 01482 clear_recursive(innernode->childid[slot]); 01483 free_node(innernode->childid[slot]); 01484 } 01485 } 01486 } 01487 01488 public: 01489 // *** STL Iterator Construction Functions 01490 01493 inline iterator begin() 01494 { 01495 return iterator(headleaf, 0); 01496 } 01497 01500 inline iterator end() 01501 { 01502 return iterator(tailleaf, tailleaf ? tailleaf->slotuse : 0); 01503 } 01504 01507 inline const_iterator begin() const 01508 { 01509 return const_iterator(headleaf, 0); 01510 } 01511 01514 inline const_iterator end() const 01515 { 01516 return const_iterator(tailleaf, tailleaf ? tailleaf->slotuse : 0); 01517 } 01518 01521 inline reverse_iterator rbegin() 01522 { 01523 return reverse_iterator(end()); 01524 } 01525 01528 inline reverse_iterator rend() 01529 { 01530 return reverse_iterator(begin()); 01531 } 01532 01535 inline const_reverse_iterator rbegin() const 01536 { 01537 return const_reverse_iterator(end()); 01538 } 01539 01542 inline const_reverse_iterator rend() const 01543 { 01544 return const_reverse_iterator(begin()); 01545 } 01546 01547 private: 01548 // *** B+ Tree Node Binary Search Functions 01549 01554 template <typename node_type> 01555 inline int find_lower(const node_type *n, const key_type& key) const 01556 { 01557 if (n->slotuse == 0) return 0; 01558 01559 int lo = 0, 01560 hi = n->slotuse - 1; 01561 01562 while(lo < hi) 01563 { 01564 int mid = (lo + hi) >> 1; 01565 01566 if (key_lessequal(key, n->slotkey[mid])) { 01567 hi = mid - 1; 01568 } 01569 else { 01570 lo = mid + 1; 01571 } 01572 } 01573 01574 if (hi < 0 || key_less(n->slotkey[hi], key)) 01575 hi++; 01576 01577 BTREE_PRINT("btree::find_lower: on " << n << " key " << key << " -> (" << lo << ") " << hi << ", "); 01578 01579 // verify result using simple linear search 01580 if (selfverify) 01581 { 01582 int i = n->slotuse - 1; 01583 while(i >= 0 && key_lessequal(key, n->slotkey[i])) 01584 i--; 01585 i++; 01586 01587 BTREE_PRINT("testfind: " << i << std::endl); 01588 BTREE_ASSERT(i == hi); 01589 } 01590 else { 01591 BTREE_PRINT(std::endl); 01592 } 01593 01594 return hi; 01595 } 01596 01601 template <typename node_type> 01602 inline int find_upper(const node_type *n, const key_type& key) const 01603 { 01604 if (n->slotuse == 0) return 0; 01605 01606 int lo = 0, 01607 hi = n->slotuse - 1; 01608 01609 while(lo < hi) 01610 { 01611 int mid = (lo + hi) >> 1; 01612 01613 if (key_less(key, n->slotkey[mid])) { 01614 hi = mid - 1; 01615 } 01616 else { 01617 lo = mid + 1; 01618 } 01619 } 01620 01621 if (hi < 0 || key_lessequal(n->slotkey[hi], key)) 01622 hi++; 01623 01624 BTREE_PRINT("btree::find_upper: on " << n << " key " << key << " -> (" << lo << ") " << hi << ", "); 01625 01626 // verify result using simple linear search 01627 if (selfverify) 01628 { 01629 int i = n->slotuse - 1; 01630 while(i >= 0 && key_less(key, n->slotkey[i])) 01631 i--; 01632 i++; 01633 01634 BTREE_PRINT("btree::find_upper testfind: " << i << std::endl); 01635 BTREE_ASSERT(i == hi); 01636 } 01637 else { 01638 BTREE_PRINT(std::endl); 01639 } 01640 01641 return hi; 01642 } 01643 01644 public: 01645 // *** Access Functions to the Item Count 01646 01648 inline size_type size() const 01649 { 01650 return stats.itemcount; 01651 } 01652 01654 inline bool empty() const 01655 { 01656 return (size() == size_type(0)); 01657 } 01658 01661 inline size_type max_size() const 01662 { 01663 return size_type(-1); 01664 } 01665 01667 inline const struct tree_stats& get_stats() const 01668 { 01669 return stats; 01670 } 01671 01672 public: 01673 // *** Standard Access Functions Querying the Tree by Descending to a Leaf 01674 01677 bool exists(const key_type &key) const 01678 { 01679 const node *n = root; 01680 if (!n) return false; 01681 01682 while(!n->isleafnode()) 01683 { 01684 const inner_node *inner = static_cast<const inner_node*>(n); 01685 int slot = find_lower(inner, key); 01686 01687 n = inner->childid[slot]; 01688 } 01689 01690 const leaf_node *leaf = static_cast<const leaf_node*>(n); 01691 01692 int slot = find_lower(leaf, key); 01693 return (slot < leaf->slotuse && key_equal(key, leaf->slotkey[slot])); 01694 } 01695 01698 iterator find(const key_type &key) 01699 { 01700 node *n = root; 01701 if (!n) return end(); 01702 01703 while(!n->isleafnode()) 01704 { 01705 const inner_node *inner = static_cast<const inner_node*>(n); 01706 int slot = find_lower(inner, key); 01707 01708 n = inner->childid[slot]; 01709 } 01710 01711 leaf_node *leaf = static_cast<leaf_node*>(n); 01712 01713 int slot = find_lower(leaf, key); 01714 return (slot < leaf->slotuse && key_equal(key, leaf->slotkey[slot])) 01715 ? iterator(leaf, slot) : end(); 01716 } 01717 01720 const_iterator find(const key_type &key) const 01721 { 01722 const node *n = root; 01723 if (!n) return end(); 01724 01725 while(!n->isleafnode()) 01726 { 01727 const inner_node *inner = static_cast<const inner_node*>(n); 01728 int slot = find_lower(inner, key); 01729 01730 n = inner->childid[slot]; 01731 } 01732 01733 const leaf_node *leaf = static_cast<const leaf_node*>(n); 01734 01735 int slot = find_lower(leaf, key); 01736 return (slot < leaf->slotuse && key_equal(key, leaf->slotkey[slot])) 01737 ? const_iterator(leaf, slot) : end(); 01738 } 01739 01742 size_type count(const key_type &key) const 01743 { 01744 const node *n = root; 01745 if (!n) return 0; 01746 01747 while(!n->isleafnode()) 01748 { 01749 const inner_node *inner = static_cast<const inner_node*>(n); 01750 int slot = find_lower(inner, key); 01751 01752 n = inner->childid[slot]; 01753 } 01754 01755 const leaf_node *leaf = static_cast<const leaf_node*>(n); 01756 01757 int slot = find_lower(leaf, key); 01758 size_type num = 0; 01759 01760 while (leaf && slot < leaf->slotuse && key_equal(key, leaf->slotkey[slot])) 01761 { 01762 ++num; 01763 if (++slot >= leaf->slotuse) 01764 { 01765 leaf = leaf->nextleaf; 01766 slot = 0; 01767 } 01768 } 01769 01770 return num; 01771 } 01772 01775 iterator lower_bound(const key_type& key) 01776 { 01777 node *n = root; 01778 if (!n) return end(); 01779 01780 while(!n->isleafnode()) 01781 { 01782 const inner_node *inner = static_cast<const inner_node*>(n); 01783 int slot = find_lower(inner, key); 01784 01785 n = inner->childid[slot]; 01786 } 01787 01788 leaf_node *leaf = static_cast<leaf_node*>(n); 01789 01790 int slot = find_lower(leaf, key); 01791 return iterator(leaf, slot); 01792 } 01793 01797 const_iterator lower_bound(const key_type& key) const 01798 { 01799 const node *n = root; 01800 if (!n) return end(); 01801 01802 while(!n->isleafnode()) 01803 { 01804 const inner_node *inner = static_cast<const inner_node*>(n); 01805 int slot = find_lower(inner, key); 01806 01807 n = inner->childid[slot]; 01808 } 01809 01810 const leaf_node *leaf = static_cast<const leaf_node*>(n); 01811 01812 int slot = find_lower(leaf, key); 01813 return const_iterator(leaf, slot); 01814 } 01815 01818 iterator upper_bound(const key_type& key) 01819 { 01820 node *n = root; 01821 if (!n) return end(); 01822 01823 while(!n->isleafnode()) 01824 { 01825 const inner_node *inner = static_cast<const inner_node*>(n); 01826 int slot = find_upper(inner, key); 01827 01828 n = inner->childid[slot]; 01829 } 01830 01831 leaf_node *leaf = static_cast<leaf_node*>(n); 01832 01833 int slot = find_upper(leaf, key); 01834 return iterator(leaf, slot); 01835 } 01836 01840 const_iterator upper_bound(const key_type& key) const 01841 { 01842 const node *n = root; 01843 if (!n) return end(); 01844 01845 while(!n->isleafnode()) 01846 { 01847 const inner_node *inner = static_cast<const inner_node*>(n); 01848 int slot = find_upper(inner, key); 01849 01850 n = inner->childid[slot]; 01851 } 01852 01853 const leaf_node *leaf = static_cast<const leaf_node*>(n); 01854 01855 int slot = find_upper(leaf, key); 01856 return const_iterator(leaf, slot); 01857 } 01858 01860 inline std::pair<iterator, iterator> equal_range(const key_type& key) 01861 { 01862 return std::pair<iterator, iterator>(lower_bound(key), upper_bound(key)); 01863 } 01864 01866 inline std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const 01867 { 01868 return std::pair<const_iterator, const_iterator>(lower_bound(key), upper_bound(key)); 01869 } 01870 01871 public: 01872 // *** B+ Tree Object Comparison Functions 01873 01877 inline bool operator==(const btree_self &other) const 01878 { 01879 return (size() == other.size()) && std::equal(begin(), end(), other.begin()); 01880 } 01881 01883 inline bool operator!=(const btree_self &other) const 01884 { 01885 return !(*this == other); 01886 } 01887 01890 inline bool operator<(const btree_self &other) const 01891 { 01892 return std::lexicographical_compare(begin(), end(), other.begin(), other.end()); 01893 } 01894 01896 inline bool operator>(const btree_self &other) const 01897 { 01898 return other < *this; 01899 } 01900 01902 inline bool operator<=(const btree_self &other) const 01903 { 01904 return !(other < *this); 01905 } 01906 01908 inline bool operator>=(const btree_self &other) const 01909 { 01910 return !(*this < other); 01911 } 01912 01913 public: 01915 01917 inline btree_self& operator= (const btree_self &other) 01918 { 01919 if (this != &other) 01920 { 01921 clear(); 01922 01923 key_less = other.key_comp(); 01924 allocator = other.get_allocator(); 01925 01926 if (other.size() != 0) 01927 { 01928 stats.leaves = stats.innernodes = 0; 01929 if (other.root) { 01930 root = copy_recursive(other.root); 01931 } 01932 stats = other.stats; 01933 } 01934 01935 if (selfverify) verify(); 01936 } 01937 return *this; 01938 } 01939 01942 inline btree(const btree_self &other) 01943 : root(NULL), headleaf(NULL), tailleaf(NULL), 01944 stats( other.stats ), 01945 key_less( other.key_comp() ), 01946 allocator( other.get_allocator() ) 01947 { 01948 if (size() > 0) 01949 { 01950 stats.leaves = stats.innernodes = 0; 01951 if (other.root) { 01952 root = copy_recursive(other.root); 01953 } 01954 if (selfverify) verify(); 01955 } 01956 } 01957 01958 private: 01960 struct node* copy_recursive(const node *n) 01961 { 01962 if (n->isleafnode()) 01963 { 01964 const leaf_node *leaf = static_cast<const leaf_node*>(n); 01965 leaf_node *newleaf = allocate_leaf(); 01966 01967 newleaf->slotuse = leaf->slotuse; 01968 std::copy(leaf->slotkey, leaf->slotkey + leaf->slotuse, newleaf->slotkey); 01969 std::copy(leaf->slotdata, leaf->slotdata + leaf->slotuse, newleaf->slotdata); 01970 01971 if (headleaf == NULL) 01972 { 01973 headleaf = tailleaf = newleaf; 01974 newleaf->prevleaf = newleaf->nextleaf = NULL; 01975 } 01976 else 01977 { 01978 newleaf->prevleaf = tailleaf; 01979 tailleaf->nextleaf = newleaf; 01980 tailleaf = newleaf; 01981 } 01982 01983 return newleaf; 01984 } 01985 else 01986 { 01987 const inner_node *inner = static_cast<const inner_node*>(n); 01988 inner_node *newinner = allocate_inner(inner->level); 01989 01990 newinner->slotuse = inner->slotuse; 01991 std::copy(inner->slotkey, inner->slotkey + inner->slotuse, newinner->slotkey); 01992 01993 for (unsigned short slot = 0; slot <= inner->slotuse; ++slot) 01994 { 01995 newinner->childid[slot] = copy_recursive(inner->childid[slot]); 01996 } 01997 01998 return newinner; 01999 } 02000 } 02001 02002 public: 02003 // *** Public Insertion Functions 02004 02008 inline std::pair<iterator, bool> insert(const pair_type& x) 02009 { 02010 return insert_start(x.first, x.second); 02011 } 02012 02017 inline std::pair<iterator, bool> insert(const key_type& key, const data_type& data) 02018 { 02019 return insert_start(key, data); 02020 } 02021 02026 inline std::pair<iterator, bool> insert2(const key_type& key, const data_type& data) 02027 { 02028 return insert_start(key, data); 02029 } 02030 02033 inline iterator insert(iterator /* hint */, const pair_type &x) 02034 { 02035 return insert_start(x.first, x.second).first; 02036 } 02037 02040 inline iterator insert2(iterator /* hint */, const key_type& key, const data_type& data) 02041 { 02042 return insert_start(key, data).first; 02043 } 02044 02047 template <typename InputIterator> 02048 inline void insert(InputIterator first, InputIterator last) 02049 { 02050 InputIterator iter = first; 02051 while(iter != last) 02052 { 02053 insert(*iter); 02054 ++iter; 02055 } 02056 } 02057 02058 private: 02059 // *** Private Insertion Functions 02060 02063 std::pair<iterator, bool> insert_start(const key_type& key, const data_type& value) 02064 { 02065 node *newchild = NULL; 02066 key_type newkey = key_type(); 02067 02068 if (root == NULL) { 02069 root = headleaf = tailleaf = allocate_leaf(); 02070 } 02071 02072 std::pair<iterator, bool> r = insert_descend(root, key, value, &newkey, &newchild); 02073 02074 if (newchild) 02075 { 02076 inner_node *newroot = allocate_inner(root->level + 1); 02077 newroot->slotkey[0] = newkey; 02078 02079 newroot->childid[0] = root; 02080 newroot->childid[1] = newchild; 02081 02082 newroot->slotuse = 1; 02083 02084 root = newroot; 02085 } 02086 02087 // increment itemcount if the item was inserted 02088 if (r.second) ++stats.itemcount; 02089 02090 #ifdef BTREE_DEBUG 02091 if (debug) print(std::cout); 02092 #endif 02093 02094 if (selfverify) { 02095 verify(); 02096 BTREE_ASSERT(exists(key)); 02097 } 02098 02099 return r; 02100 } 02101 02109 std::pair<iterator, bool> insert_descend(node* n, 02110 const key_type& key, const data_type& value, 02111 key_type* splitkey, node** splitnode) 02112 { 02113 if (!n->isleafnode()) 02114 { 02115 inner_node *inner = static_cast<inner_node*>(n); 02116 02117 key_type newkey = key_type(); 02118 node *newchild = NULL; 02119 02120 int slot = find_lower(inner, key); 02121 02122 BTREE_PRINT("btree::insert_descend into " << inner->childid[slot] << std::endl); 02123 02124 std::pair<iterator, bool> r = insert_descend(inner->childid[slot], 02125 key, value, &newkey, &newchild); 02126 02127 if (newchild) 02128 { 02129 BTREE_PRINT("btree::insert_descend newchild with key " << newkey << " node " << newchild << " at slot " << slot << std::endl); 02130 02131 if (inner->isfull()) 02132 { 02133 split_inner_node(inner, splitkey, splitnode, slot); 02134 02135 BTREE_PRINT("btree::insert_descend done split_inner: putslot: " << slot << " putkey: " << newkey << " upkey: " << *splitkey << std::endl); 02136 02137 #ifdef BTREE_DEBUG 02138 if (debug) 02139 { 02140 print_node(std::cout, inner); 02141 print_node(std::cout, *splitnode); 02142 } 02143 #endif 02144 02145 // check if insert slot is in the split sibling node 02146 BTREE_PRINT("btree::insert_descend switch: " << slot << " > " << inner->slotuse+1 << std::endl); 02147 02148 if (slot == inner->slotuse+1 && inner->slotuse < (*splitnode)->slotuse) 02149 { 02150 // special case when the insert slot matches the split 02151 // place between the two nodes, then the insert key 02152 // becomes the split key. 02153 02154 BTREE_ASSERT(inner->slotuse + 1 < innerslotmax); 02155 02156 inner_node *splitinner = static_cast<inner_node*>(*splitnode); 02157 02158 // move the split key and it's datum into the left node 02159 inner->slotkey[inner->slotuse] = *splitkey; 02160 inner->childid[inner->slotuse+1] = splitinner->childid[0]; 02161 inner->slotuse++; 02162 02163 // set new split key and move corresponding datum into right node 02164 splitinner->childid[0] = newchild; 02165 *splitkey = newkey; 02166 02167 return r; 02168 } 02169 else if (slot >= inner->slotuse+1) 02170 { 02171 // in case the insert slot is in the newly create split 02172 // node, we reuse the code below. 02173 02174 slot -= inner->slotuse+1; 02175 inner = static_cast<inner_node*>(*splitnode); 02176 BTREE_PRINT("btree::insert_descend switching to splitted node " << inner << " slot " << slot <<std::endl); 02177 } 02178 } 02179 02180 // put pointer to child node into correct slot 02181 BTREE_ASSERT(slot >= 0 && slot <= inner->slotuse); 02182 02183 int i = inner->slotuse; 02184 02185 while(i > slot) { 02186 inner->slotkey[i] = inner->slotkey[i - 1]; 02187 inner->childid[i + 1] = inner->childid[i]; 02188 i--; 02189 } 02190 02191 inner->slotkey[slot] = newkey; 02192 inner->childid[slot + 1] = newchild; 02193 inner->slotuse++; 02194 } 02195 02196 return r; 02197 } 02198 else // n->isleafnode() == true 02199 { 02200 leaf_node *leaf = static_cast<leaf_node*>(n); 02201 02202 int slot = find_lower(leaf, key); 02203 02204 if (!allow_duplicates && slot < leaf->slotuse && key_equal(key, leaf->slotkey[slot])) { 02205 return std::pair<iterator, bool>(iterator(leaf, slot), false); 02206 } 02207 02208 if (leaf->isfull()) 02209 { 02210 split_leaf_node(leaf, splitkey, splitnode); 02211 02212 // check if insert slot is in the split sibling node 02213 if (slot >= leaf->slotuse) 02214 { 02215 slot -= leaf->slotuse; 02216 leaf = static_cast<leaf_node*>(*splitnode); 02217 } 02218 } 02219 02220 // put data item into correct data slot 02221 02222 int i = leaf->slotuse - 1; 02223 BTREE_ASSERT(i + 1 < leafslotmax); 02224 02225 while(i >= 0 && key_less(key, leaf->slotkey[i])) { 02226 leaf->slotkey[i + 1] = leaf->slotkey[i]; 02227 leaf->slotdata[i + 1] = leaf->slotdata[i]; 02228 i--; 02229 } 02230 02231 leaf->slotkey[i + 1] = key; 02232 leaf->slotdata[i + 1] = value; 02233 leaf->slotuse++; 02234 02235 if (splitnode && leaf != *splitnode && slot == leaf->slotuse-1) 02236 { 02237 // special case: the node was split, and the insert is at the 02238 // last slot of the old node. then the splitkey must be 02239 // updated. 02240 *splitkey = key; 02241 } 02242 02243 return std::pair<iterator, bool>(iterator(leaf, i + 1), true); 02244 } 02245 } 02246 02249 void split_leaf_node(leaf_node* leaf, key_type* _newkey, node** _newleaf) 02250 { 02251 BTREE_ASSERT(leaf->isfull()); 02252 02253 unsigned int mid = (leaf->slotuse >> 1); 02254 02255 BTREE_PRINT("btree::split_leaf_node on " << leaf << std::endl); 02256 02257 leaf_node *newleaf = allocate_leaf(); 02258 02259 newleaf->slotuse = leaf->slotuse - mid; 02260 02261 newleaf->nextleaf = leaf->nextleaf; 02262 if (newleaf->nextleaf == NULL) { 02263 BTREE_ASSERT(leaf == tailleaf); 02264 tailleaf = newleaf; 02265 } 02266 else { 02267 newleaf->nextleaf->prevleaf = newleaf; 02268 } 02269 02270 for(unsigned int slot = mid; slot < leaf->slotuse; ++slot) 02271 { 02272 unsigned int ni = slot - mid; 02273 newleaf->slotkey[ni] = leaf->slotkey[slot]; 02274 newleaf->slotdata[ni] = leaf->slotdata[slot]; 02275 } 02276 02277 leaf->slotuse = mid; 02278 leaf->nextleaf = newleaf; 02279 newleaf->prevleaf = leaf; 02280 02281 *_newkey = leaf->slotkey[leaf->slotuse-1]; 02282 *_newleaf = newleaf; 02283 } 02284 02289 void split_inner_node(inner_node* inner, key_type* _newkey, node** _newinner, unsigned int addslot) 02290 { 02291 BTREE_ASSERT(inner->isfull()); 02292 02293 unsigned int mid = (inner->slotuse >> 1); 02294 02295 BTREE_PRINT("btree::split_inner: mid " << mid << " addslot " << addslot << std::endl); 02296 02297 // if the split is uneven and the overflowing item will be put into the 02298 // larger node, then the smaller split node may underflow 02299 if (addslot <= mid && mid > inner->slotuse - (mid + 1)) 02300 mid--; 02301 02302 BTREE_PRINT("btree::split_inner: mid " << mid << " addslot " << addslot << std::endl); 02303 02304 BTREE_PRINT("btree::split_inner_node on " << inner << " into two nodes " << mid << " and " << inner->slotuse - (mid + 1) << " sized" << std::endl); 02305 02306 inner_node *newinner = allocate_inner(inner->level); 02307 02308 newinner->slotuse = inner->slotuse - (mid + 1); 02309 02310 for(unsigned int slot = mid + 1; slot < inner->slotuse; ++slot) 02311 { 02312 unsigned int ni = slot - (mid + 1); 02313 newinner->slotkey[ni] = inner->slotkey[slot]; 02314 newinner->childid[ni] = inner->childid[slot]; 02315 } 02316 newinner->childid[newinner->slotuse] = inner->childid[inner->slotuse]; 02317 02318 inner->slotuse = mid; 02319 02320 *_newkey = inner->slotkey[mid]; 02321 *_newinner = newinner; 02322 } 02323 02324 private: 02325 // *** Support Class Encapsulating Deletion Results 02326 02328 enum result_flags_t 02329 { 02331 btree_ok = 0, 02332 02334 btree_not_found = 1, 02335 02338 btree_update_lastkey = 2, 02339 02342 btree_fixmerge = 4 02343 }; 02344 02347 struct result_t 02348 { 02350 result_flags_t flags; 02351 02353 key_type lastkey; 02354 02357 inline result_t(result_flags_t f = btree_ok) 02358 : flags(f), lastkey() 02359 { } 02360 02362 inline result_t(result_flags_t f, const key_type &k) 02363 : flags(f), lastkey(k) 02364 { } 02365 02367 inline bool has(result_flags_t f) const 02368 { 02369 return (flags & f) != 0; 02370 } 02371 02373 inline result_t& operator|= (const result_t &other) 02374 { 02375 flags = result_flags_t(flags | other.flags); 02376 02377 // we overwrite existing lastkeys on purpose 02378 if (other.has(btree_update_lastkey)) 02379 lastkey = other.lastkey; 02380 02381 return *this; 02382 } 02383 }; 02384 02385 public: 02386 // *** Public Erase Functions 02387 02390 bool erase_one(const key_type &key) 02391 { 02392 BTREE_PRINT("btree::erase_one(" << key << ") on btree size " << size() << std::endl); 02393 02394 if (selfverify) verify(); 02395 02396 if (!root) return false; 02397 02398 result_t result = erase_one_descend(key, root, NULL, NULL, NULL, NULL, NULL, 0); 02399 02400 if (!result.has(btree_not_found)) 02401 --stats.itemcount; 02402 02403 #ifdef BTREE_DEBUG 02404 if (debug) print(std::cout); 02405 #endif 02406 if (selfverify) verify(); 02407 02408 return !result.has(btree_not_found); 02409 } 02410 02413 size_type erase(const key_type &key) 02414 { 02415 size_type c = 0; 02416 02417 while( erase_one(key) ) 02418 { 02419 ++c; 02420 if (!allow_duplicates) break; 02421 } 02422 02423 return c; 02424 } 02425 02427 void erase(iterator iter) 02428 { 02429 BTREE_PRINT("btree::erase_iter(" << iter.currnode << "," << iter.currslot << ") on btree size " << size() << std::endl); 02430 02431 if (selfverify) verify(); 02432 02433 if (!root) return; 02434 02435 result_t result = erase_iter_descend(iter, root, NULL, NULL, NULL, NULL, NULL, 0); 02436 02437 if (!result.has(btree_not_found)) 02438 --stats.itemcount; 02439 02440 #ifdef BTREE_DEBUG 02441 if (debug) print(std::cout); 02442 #endif 02443 if (selfverify) verify(); 02444 } 02445 02446 #ifdef BTREE_TODO 02447 02448 02449 void erase(iterator /* first */, iterator /* last */) 02450 { 02451 abort(); 02452 } 02453 #endif 02454 02455 private: 02456 // *** Private Erase Functions 02457 02467 result_t erase_one_descend(const key_type& key, 02468 node *curr, 02469 node *left, node *right, 02470 inner_node *leftparent, inner_node *rightparent, 02471 inner_node *parent, unsigned int parentslot) 02472 { 02473 if (curr->isleafnode()) 02474 { 02475 leaf_node *leaf = static_cast<leaf_node*>(curr); 02476 leaf_node *leftleaf = static_cast<leaf_node*>(left); 02477 leaf_node *rightleaf = static_cast<leaf_node*>(right); 02478 02479 int slot = find_lower(leaf, key); 02480 02481 if (slot >= leaf->slotuse || !key_equal(key, leaf->slotkey[slot])) 02482 { 02483 BTREE_PRINT("Could not find key " << key << " to erase." << std::endl); 02484 02485 return btree_not_found; 02486 } 02487 02488 BTREE_PRINT("Found key in leaf " << curr << " at slot " << slot << std::endl); 02489 02490 for (int i = slot; i < leaf->slotuse - 1; i++) 02491 { 02492 leaf->slotkey[i] = leaf->slotkey[i + 1]; 02493 leaf->slotdata[i] = leaf->slotdata[i + 1]; 02494 } 02495 leaf->slotuse--; 02496 02497 result_t myres = btree_ok; 02498 02499 // if the last key of the leaf was changed, the parent is notified 02500 // and updates the key of this leaf 02501 if (slot == leaf->slotuse) 02502 { 02503 if (parent && parentslot < parent->slotuse) 02504 { 02505 BTREE_ASSERT(parent->childid[parentslot] == curr); 02506 parent->slotkey[parentslot] = leaf->slotkey[leaf->slotuse - 1]; 02507 } 02508 else 02509 { 02510 if (leaf->slotuse >= 1) 02511 { 02512 BTREE_PRINT("Scheduling lastkeyupdate: key " << leaf->slotkey[leaf->slotuse - 1] << std::endl); 02513 myres |= result_t(btree_update_lastkey, leaf->slotkey[leaf->slotuse - 1]); 02514 } 02515 else 02516 { 02517 BTREE_ASSERT(leaf == root); 02518 } 02519 } 02520 } 02521 02522 if (leaf->isunderflow() && !(leaf == root && leaf->slotuse >= 1)) 02523 { 02524 // determine what to do about the underflow 02525 02526 // case : if this empty leaf is the root, then delete all nodes 02527 // and set root to NULL. 02528 if (leftleaf == NULL && rightleaf == NULL) 02529 { 02530 BTREE_ASSERT(leaf == root); 02531 BTREE_ASSERT(leaf->slotuse == 0); 02532 02533 free_node(root); 02534 02535 root = leaf = NULL; 02536 headleaf = tailleaf = NULL; 02537 02538 // will be decremented soon by insert_start() 02539 BTREE_ASSERT(stats.itemcount == 1); 02540 BTREE_ASSERT(stats.leaves == 0); 02541 BTREE_ASSERT(stats.innernodes == 0); 02542 02543 return btree_ok; 02544 } 02545 // case : if both left and right leaves would underflow in case of 02546 // a shift, then merging is necessary. choose the more local merger 02547 // with our parent 02548 else if ( (leftleaf == NULL || leftleaf->isfew()) && (rightleaf == NULL || rightleaf->isfew()) ) 02549 { 02550 if (leftparent == parent) 02551 myres |= merge_leaves(leftleaf, leaf, leftparent); 02552 else 02553 myres |= merge_leaves(leaf, rightleaf, rightparent); 02554 } 02555 // case : the right leaf has extra data, so balance right with current 02556 else if ( (leftleaf != NULL && leftleaf->isfew()) && (rightleaf != NULL && !rightleaf->isfew()) ) 02557 { 02558 if (rightparent == parent) 02559 myres |= shift_left_leaf(leaf, rightleaf, rightparent, parentslot); 02560 else 02561 myres |= merge_leaves(leftleaf, leaf, leftparent); 02562 } 02563 // case : the left leaf has extra data, so balance left with current 02564 else if ( (leftleaf != NULL && !leftleaf->isfew()) && (rightleaf != NULL && rightleaf->isfew()) ) 02565 { 02566 if (leftparent == parent) 02567 shift_right_leaf(leftleaf, leaf, leftparent, parentslot - 1); 02568 else 02569 myres |= merge_leaves(leaf, rightleaf, rightparent); 02570 } 02571 // case : both the leaf and right leaves have extra data and our 02572 // parent, choose the leaf with more data 02573 else if (leftparent == rightparent) 02574 { 02575 if (leftleaf->slotuse <= rightleaf->slotuse) 02576 myres |= shift_left_leaf(leaf, rightleaf, rightparent, parentslot); 02577 else 02578 shift_right_leaf(leftleaf, leaf, leftparent, parentslot - 1); 02579 } 02580 else 02581 { 02582 if (leftparent == parent) 02583 shift_right_leaf(leftleaf, leaf, leftparent, parentslot - 1); 02584 else 02585 myres |= shift_left_leaf(leaf, rightleaf, rightparent, parentslot); 02586 } 02587 } 02588 02589 return myres; 02590 } 02591 else // !curr->isleafnode() 02592 { 02593 inner_node *inner = static_cast<inner_node*>(curr); 02594 inner_node *leftinner = static_cast<inner_node*>(left); 02595 inner_node *rightinner = static_cast<inner_node*>(right); 02596 02597 node *myleft, *myright; 02598 inner_node *myleftparent, *myrightparent; 02599 02600 int slot = find_lower(inner, key); 02601 02602 if (slot == 0) { 02603 myleft = (left == NULL) ? NULL : (static_cast<inner_node*>(left))->childid[left->slotuse - 1]; 02604 myleftparent = leftparent; 02605 } 02606 else { 02607 myleft = inner->childid[slot - 1]; 02608 myleftparent = inner; 02609 } 02610 02611 if (slot == inner->slotuse) { 02612 myright = (right == NULL) ? NULL : (static_cast<inner_node*>(right))->childid[0]; 02613 myrightparent = rightparent; 02614 } 02615 else { 02616 myright = inner->childid[slot + 1]; 02617 myrightparent = inner; 02618 } 02619 02620 BTREE_PRINT("erase_one_descend into " << inner->childid[slot] << std::endl); 02621 02622 result_t result = erase_one_descend(key, 02623 inner->childid[slot], 02624 myleft, myright, 02625 myleftparent, myrightparent, 02626 inner, slot); 02627 02628 result_t myres = btree_ok; 02629 02630 if (result.has(btree_not_found)) 02631 { 02632 return result; 02633 } 02634 02635 if (result.has(btree_update_lastkey)) 02636 { 02637 if (parent && parentslot < parent->slotuse) 02638 { 02639 BTREE_PRINT("Fixing lastkeyupdate: key " << result.lastkey << " into parent " << parent << " at parentslot " << parentslot << std::endl); 02640 02641 BTREE_ASSERT(parent->childid[parentslot] == curr); 02642 parent->slotkey[parentslot] = result.lastkey; 02643 } 02644 else 02645 { 02646 BTREE_PRINT("Forwarding lastkeyupdate: key " << result.lastkey << std::endl); 02647 myres |= result_t(btree_update_lastkey, result.lastkey); 02648 } 02649 } 02650 02651 if (result.has(btree_fixmerge)) 02652 { 02653 // either the current node or the next is empty and should be removed 02654 if (inner->childid[slot]->slotuse != 0) 02655 slot++; 02656 02657 // this is the child slot invalidated by the merge 02658 BTREE_ASSERT(inner->childid[slot]->slotuse == 0); 02659 02660 free_node(inner->childid[slot]); 02661 02662 for(int i = slot; i < inner->slotuse; i++) 02663 { 02664 inner->slotkey[i - 1] = inner->slotkey[i]; 02665 inner->childid[i] = inner->childid[i + 1]; 02666 } 02667 inner->slotuse--; 02668 02669 if (inner->level == 1) 02670 { 02671 // fix split key for children leaves 02672 slot--; 02673 leaf_node *child = static_cast<leaf_node*>(inner->childid[slot]); 02674 inner->slotkey[slot] = child->slotkey[ child->slotuse-1 ]; 02675 } 02676 } 02677 02678 if (inner->isunderflow() && !(inner == root && inner->slotuse >= 1)) 02679 { 02680 // case: the inner node is the root and has just one child. that child becomes the new root 02681 if (leftinner == NULL && rightinner == NULL) 02682 { 02683 BTREE_ASSERT(inner == root); 02684 BTREE_ASSERT(inner->slotuse == 0); 02685 02686 root = inner->childid[0]; 02687 02688 inner->slotuse = 0; 02689 free_node(inner); 02690 02691 return btree_ok; 02692 } 02693 // case : if both left and right leaves would underflow in case of 02694 // a shift, then merging is necessary. choose the more local merger 02695 // with our parent 02696 else if ( (leftinner == NULL || leftinner->isfew()) && (rightinner == NULL || rightinner->isfew()) ) 02697 { 02698 if (leftparent == parent) 02699 myres |= merge_inner(leftinner, inner, leftparent, parentslot - 1); 02700 else 02701 myres |= merge_inner(inner, rightinner, rightparent, parentslot); 02702 } 02703 // case : the right leaf has extra data, so balance right with current 02704 else if ( (leftinner != NULL && leftinner->isfew()) && (rightinner != NULL && !rightinner->isfew()) ) 02705 { 02706 if (rightparent == parent) 02707 shift_left_inner(inner, rightinner, rightparent, parentslot); 02708 else 02709 myres |= merge_inner(leftinner, inner, leftparent, parentslot - 1); 02710 } 02711 // case : the left leaf has extra data, so balance left with current 02712 else if ( (leftinner != NULL && !leftinner->isfew()) && (rightinner != NULL && rightinner->isfew()) ) 02713 { 02714 if (leftparent == parent) 02715 shift_right_inner(leftinner, inner, leftparent, parentslot - 1); 02716 else 02717 myres |= merge_inner(inner, rightinner, rightparent, parentslot); 02718 } 02719 // case : both the leaf and right leaves have extra data and our 02720 // parent, choose the leaf with more data 02721 else if (leftparent == rightparent) 02722 { 02723 if (leftinner->slotuse <= rightinner->slotuse) 02724 shift_left_inner(inner, rightinner, rightparent, parentslot); 02725 else 02726 shift_right_inner(leftinner, inner, leftparent, parentslot - 1); 02727 } 02728 else 02729 { 02730 if (leftparent == parent) 02731 shift_right_inner(leftinner, inner, leftparent, parentslot - 1); 02732 else 02733 shift_left_inner(inner, rightinner, rightparent, parentslot); 02734 } 02735 } 02736 02737 return myres; 02738 } 02739 } 02740 02756 result_t erase_iter_descend(const iterator& iter, 02757 node *curr, 02758 node *left, node *right, 02759 inner_node *leftparent, inner_node *rightparent, 02760 inner_node *parent, unsigned int parentslot) 02761 { 02762 if (curr->isleafnode()) 02763 { 02764 leaf_node *leaf = static_cast<leaf_node*>(curr); 02765 leaf_node *leftleaf = static_cast<leaf_node*>(left); 02766 leaf_node *rightleaf = static_cast<leaf_node*>(right); 02767 02768 // if this is not the correct leaf, get next step in recursive 02769 // search 02770 if (leaf != iter.currnode) 02771 { 02772 return btree_not_found; 02773 } 02774 02775 if (iter.currslot >= leaf->slotuse) 02776 { 02777 BTREE_PRINT("Could not find iterator (" << iter.currnode << "," << iter.currslot << ") to erase. Invalid leaf node?" << std::endl); 02778 02779 return btree_not_found; 02780 } 02781 02782 int slot = iter.currslot; 02783 02784 BTREE_PRINT("Found iterator in leaf " << curr << " at slot " << slot << std::endl); 02785 02786 for (int i = slot; i < leaf->slotuse - 1; i++) 02787 { 02788 leaf->slotkey[i] = leaf->slotkey[i + 1]; 02789 leaf->slotdata[i] = leaf->slotdata[i + 1]; 02790 } 02791 leaf->slotuse--; 02792 02793 result_t myres = btree_ok; 02794 02795 // if the last key of the leaf was changed, the parent is notified 02796 // and updates the key of this leaf 02797 if (slot == leaf->slotuse) 02798 { 02799 if (parent && parentslot < parent->slotuse) 02800 { 02801 BTREE_ASSERT(parent->childid[parentslot] == curr); 02802 parent->slotkey[parentslot] = leaf->slotkey[leaf->slotuse - 1]; 02803 } 02804 else 02805 { 02806 if (leaf->slotuse >= 1) 02807 { 02808 BTREE_PRINT("Scheduling lastkeyupdate: key " << leaf->slotkey[leaf->slotuse - 1] << std::endl); 02809 myres |= result_t(btree_update_lastkey, leaf->slotkey[leaf->slotuse - 1]); 02810 } 02811 else 02812 { 02813 BTREE_ASSERT(leaf == root); 02814 } 02815 } 02816 } 02817 02818 if (leaf->isunderflow() && !(leaf == root && leaf->slotuse >= 1)) 02819 { 02820 // determine what to do about the underflow 02821 02822 // case : if this empty leaf is the root, then delete all nodes 02823 // and set root to NULL. 02824 if (leftleaf == NULL && rightleaf == NULL) 02825 { 02826 BTREE_ASSERT(leaf == root); 02827 BTREE_ASSERT(leaf->slotuse == 0); 02828 02829 free_node(root); 02830 02831 root = leaf = NULL; 02832 headleaf = tailleaf = NULL; 02833 02834 // will be decremented soon by insert_start() 02835 BTREE_ASSERT(stats.itemcount == 1); 02836 BTREE_ASSERT(stats.leaves == 0); 02837 BTREE_ASSERT(stats.innernodes == 0); 02838 02839 return btree_ok; 02840 } 02841 // case : if both left and right leaves would underflow in case of 02842 // a shift, then merging is necessary. choose the more local merger 02843 // with our parent 02844 else if ( (leftleaf == NULL || leftleaf->isfew()) && (rightleaf == NULL || rightleaf->isfew()) ) 02845 { 02846 if (leftparent == parent) 02847 myres |= merge_leaves(leftleaf, leaf, leftparent); 02848 else 02849 myres |= merge_leaves(leaf, rightleaf, rightparent); 02850 } 02851 // case : the right leaf has extra data, so balance right with current 02852 else if ( (leftleaf != NULL && leftleaf->isfew()) && (rightleaf != NULL && !rightleaf->isfew()) ) 02853 { 02854 if (rightparent == parent) 02855 myres |= shift_left_leaf(leaf, rightleaf, rightparent, parentslot); 02856 else 02857 myres |= merge_leaves(leftleaf, leaf, leftparent); 02858 } 02859 // case : the left leaf has extra data, so balance left with current 02860 else if ( (leftleaf != NULL && !leftleaf->isfew()) && (rightleaf != NULL && rightleaf->isfew()) ) 02861 { 02862 if (leftparent == parent) 02863 shift_right_leaf(leftleaf, leaf, leftparent, parentslot - 1); 02864 else 02865 myres |= merge_leaves(leaf, rightleaf, rightparent); 02866 } 02867 // case : both the leaf and right leaves have extra data and our 02868 // parent, choose the leaf with more data 02869 else if (leftparent == rightparent) 02870 { 02871 if (leftleaf->slotuse <= rightleaf->slotuse) 02872 myres |= shift_left_leaf(leaf, rightleaf, rightparent, parentslot); 02873 else 02874 shift_right_leaf(leftleaf, leaf, leftparent, parentslot - 1); 02875 } 02876 else 02877 { 02878 if (leftparent == parent) 02879 shift_right_leaf(leftleaf, leaf, leftparent, parentslot - 1); 02880 else 02881 myres |= shift_left_leaf(leaf, rightleaf, rightparent, parentslot); 02882 } 02883 } 02884 02885 return myres; 02886 } 02887 else // !curr->isleafnode() 02888 { 02889 inner_node *inner = static_cast<inner_node*>(curr); 02890 inner_node *leftinner = static_cast<inner_node*>(left); 02891 inner_node *rightinner = static_cast<inner_node*>(right); 02892 02893 // find first slot below which the searched iterator might be 02894 // located. 02895 02896 result_t result; 02897 int slot = find_lower(inner, iter.key()); 02898 02899 while (slot <= inner->slotuse) 02900 { 02901 node *myleft, *myright; 02902 inner_node *myleftparent, *myrightparent; 02903 02904 if (slot == 0) { 02905 myleft = (left == NULL) ? NULL : (static_cast<inner_node*>(left))->childid[left->slotuse - 1]; 02906 myleftparent = leftparent; 02907 } 02908 else { 02909 myleft = inner->childid[slot - 1]; 02910 myleftparent = inner; 02911 } 02912 02913 if (slot == inner->slotuse) { 02914 myright = (right == NULL) ? NULL : (static_cast<inner_node*>(right))->childid[0]; 02915 myrightparent = rightparent; 02916 } 02917 else { 02918 myright = inner->childid[slot + 1]; 02919 myrightparent = inner; 02920 } 02921 02922 BTREE_PRINT("erase_iter_descend into " << inner->childid[slot] << std::endl); 02923 02924 result = erase_iter_descend(iter, 02925 inner->childid[slot], 02926 myleft, myright, 02927 myleftparent, myrightparent, 02928 inner, slot); 02929 02930 if (!result.has(btree_not_found)) 02931 break; 02932 02933 // continue recursive search for leaf on next slot 02934 02935 if (slot < inner->slotuse && key_less(inner->slotkey[slot],iter.key())) 02936 return btree_not_found; 02937 02938 ++slot; 02939 } 02940 02941 if (slot > inner->slotuse) 02942 return btree_not_found; 02943 02944 result_t myres = btree_ok; 02945 02946 if (result.has(btree_update_lastkey)) 02947 { 02948 if (parent && parentslot < parent->slotuse) 02949 { 02950 BTREE_PRINT("Fixing lastkeyupdate: key " << result.lastkey << " into parent " << parent << " at parentslot " << parentslot << std::endl); 02951 02952 BTREE_ASSERT(parent->childid[parentslot] == curr); 02953 parent->slotkey[parentslot] = result.lastkey; 02954 } 02955 else 02956 { 02957 BTREE_PRINT("Forwarding lastkeyupdate: key " << result.lastkey << std::endl); 02958 myres |= result_t(btree_update_lastkey, result.lastkey); 02959 } 02960 } 02961 02962 if (result.has(btree_fixmerge)) 02963 { 02964 // either the current node or the next is empty and should be removed 02965 if (inner->childid[slot]->slotuse != 0) 02966 slot++; 02967 02968 // this is the child slot invalidated by the merge 02969 BTREE_ASSERT(inner->childid[slot]->slotuse == 0); 02970 02971 free_node(inner->childid[slot]); 02972 02973 for(int i = slot; i < inner->slotuse; i++) 02974 { 02975 inner->slotkey[i - 1] = inner->slotkey[i]; 02976 inner->childid[i] = inner->childid[i + 1]; 02977 } 02978 inner->slotuse--; 02979 02980 if (inner->level == 1) 02981 { 02982 // fix split key for children leaves 02983 slot--; 02984 leaf_node *child = static_cast<leaf_node*>(inner->childid[slot]); 02985 inner->slotkey[slot] = child->slotkey[ child->slotuse-1 ]; 02986 } 02987 } 02988 02989 if (inner->isunderflow() && !(inner == root && inner->slotuse >= 1)) 02990 { 02991 // case: the inner node is the root and has just one child. that child becomes the new root 02992 if (leftinner == NULL && rightinner == NULL) 02993 { 02994 BTREE_ASSERT(inner == root); 02995 BTREE_ASSERT(inner->slotuse == 0); 02996 02997 root = inner->childid[0]; 02998 02999 inner->slotuse = 0; 03000 free_node(inner); 03001 03002 return btree_ok; 03003 } 03004 // case : if both left and right leaves would underflow in case of 03005 // a shift, then merging is necessary. choose the more local merger 03006 // with our parent 03007 else if ( (leftinner == NULL || leftinner->isfew()) && (rightinner == NULL || rightinner->isfew()) ) 03008 { 03009 if (leftparent == parent) 03010 myres |= merge_inner(leftinner, inner, leftparent, parentslot - 1); 03011 else 03012 myres |= merge_inner(inner, rightinner, rightparent, parentslot); 03013 } 03014 // case : the right leaf has extra data, so balance right with current 03015 else if ( (leftinner != NULL && leftinner->isfew()) && (rightinner != NULL && !rightinner->isfew()) ) 03016 { 03017 if (rightparent == parent) 03018 shift_left_inner(inner, rightinner, rightparent, parentslot); 03019 else 03020 myres |= merge_inner(leftinner, inner, leftparent, parentslot - 1); 03021 } 03022 // case : the left leaf has extra data, so balance left with current 03023 else if ( (leftinner != NULL && !leftinner->isfew()) && (rightinner != NULL && rightinner->isfew()) ) 03024 { 03025 if (leftparent == parent) 03026 shift_right_inner(leftinner, inner, leftparent, parentslot - 1); 03027 else 03028 myres |= merge_inner(inner, rightinner, rightparent, parentslot); 03029 } 03030 // case : both the leaf and right leaves have extra data and our 03031 // parent, choose the leaf with more data 03032 else if (leftparent == rightparent) 03033 { 03034 if (leftinner->slotuse <= rightinner->slotuse) 03035 shift_left_inner(inner, rightinner, rightparent, parentslot); 03036 else 03037 shift_right_inner(leftinner, inner, leftparent, parentslot - 1); 03038 } 03039 else 03040 { 03041 if (leftparent == parent) 03042 shift_right_inner(leftinner, inner, leftparent, parentslot - 1); 03043 else 03044 shift_left_inner(inner, rightinner, rightparent, parentslot); 03045 } 03046 } 03047 03048 return myres; 03049 } 03050 } 03051 03055 result_t merge_leaves(leaf_node* left, leaf_node* right, inner_node* parent) 03056 { 03057 BTREE_PRINT("Merge leaf nodes " << left << " and " << right << " with common parent " << parent << "." << std::endl); 03058 (void)parent; 03059 03060 BTREE_ASSERT(left->isleafnode() && right->isleafnode()); 03061 BTREE_ASSERT(parent->level == 1); 03062 03063 BTREE_ASSERT(left->slotuse + right->slotuse < leafslotmax); 03064 03065 for (unsigned int i = 0; i < right->slotuse; i++) 03066 { 03067 left->slotkey[left->slotuse + i] = right->slotkey[i]; 03068 left->slotdata[left->slotuse + i] = right->slotdata[i]; 03069 } 03070 left->slotuse += right->slotuse; 03071 03072 left->nextleaf = right->nextleaf; 03073 if (left->nextleaf) 03074 left->nextleaf->prevleaf = left; 03075 else 03076 tailleaf = left; 03077 03078 right->slotuse = 0; 03079 03080 return btree_fixmerge; 03081 } 03082 03086 static result_t merge_inner(inner_node* left, inner_node* right, inner_node* parent, unsigned int parentslot) 03087 { 03088 BTREE_PRINT("Merge inner nodes " << left << " and " << right << " with common parent " << parent << "." << std::endl); 03089 03090 BTREE_ASSERT(left->level == right->level); 03091 BTREE_ASSERT(parent->level == left->level + 1); 03092 03093 BTREE_ASSERT(parent->childid[parentslot] == left); 03094 03095 BTREE_ASSERT(left->slotuse + right->slotuse < innerslotmax); 03096 03097 if (selfverify) 03098 { 03099 // find the left node's slot in the parent's children 03100 unsigned int leftslot = 0; 03101 while(leftslot <= parent->slotuse && parent->childid[leftslot] != left) 03102 ++leftslot; 03103 03104 BTREE_ASSERT(leftslot < parent->slotuse); 03105 BTREE_ASSERT(parent->childid[leftslot] == left); 03106 BTREE_ASSERT(parent->childid[leftslot+1] == right); 03107 03108 BTREE_ASSERT(parentslot == leftslot); 03109 } 03110 03111 // retrieve the decision key from parent 03112 left->slotkey[left->slotuse] = parent->slotkey[parentslot]; 03113 left->slotuse++; 03114 03115 // copy over keys and children from right 03116 for (unsigned int i = 0; i < right->slotuse; i++) 03117 { 03118 left->slotkey[left->slotuse + i] = right->slotkey[i]; 03119 left->childid[left->slotuse + i] = right->childid[i]; 03120 } 03121 left->slotuse += right->slotuse; 03122 03123 left->childid[left->slotuse] = right->childid[right->slotuse]; 03124 03125 right->slotuse = 0; 03126 03127 return btree_fixmerge; 03128 } 03129 03133 static result_t shift_left_leaf(leaf_node *left, leaf_node *right, inner_node *parent, unsigned int parentslot) 03134 { 03135 BTREE_ASSERT(left->isleafnode() && right->isleafnode()); 03136 BTREE_ASSERT(parent->level == 1); 03137 03138 BTREE_ASSERT(left->nextleaf == right); 03139 BTREE_ASSERT(left == right->prevleaf); 03140 03141 BTREE_ASSERT(left->slotuse < right->slotuse); 03142 BTREE_ASSERT(parent->childid[parentslot] == left); 03143 03144 unsigned int shiftnum = (right->slotuse - left->slotuse) >> 1; 03145 03146 BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to left " << left << " from right " << right << " with common parent " << parent << "." << std::endl); 03147 03148 BTREE_ASSERT(left->slotuse + shiftnum < leafslotmax); 03149 03150 // copy the first items from the right node to the last slot in the left node. 03151 for(unsigned int i = 0; i < shiftnum; i++) 03152 { 03153 left->slotkey[left->slotuse + i] = right->slotkey[i]; 03154 left->slotdata[left->slotuse + i] = right->slotdata[i]; 03155 } 03156 left->slotuse += shiftnum; 03157 03158 // shift all slots in the right node to the left 03159 03160 right->slotuse -= shiftnum; 03161 for(int i = 0; i < right->slotuse; i++) 03162 { 03163 right->slotkey[i] = right->slotkey[i + shiftnum]; 03164 right->slotdata[i] = right->slotdata[i + shiftnum]; 03165 } 03166 03167 // fixup parent 03168 if (parentslot < parent->slotuse) { 03169 parent->slotkey[parentslot] = left->slotkey[left->slotuse - 1]; 03170 return btree_ok; 03171 } 03172 else { // the update is further up the tree 03173 return result_t(btree_update_lastkey, left->slotkey[left->slotuse - 1]); 03174 } 03175 } 03176 03180 static void shift_left_inner(inner_node *left, inner_node *right, inner_node *parent, unsigned int parentslot) 03181 { 03182 BTREE_ASSERT(left->level == right->level); 03183 BTREE_ASSERT(parent->level == left->level + 1); 03184 03185 BTREE_ASSERT(left->slotuse < right->slotuse); 03186 BTREE_ASSERT(parent->childid[parentslot] == left); 03187 03188 unsigned int shiftnum = (right->slotuse - left->slotuse) >> 1; 03189 03190 BTREE_PRINT("Shifting (inner) " << shiftnum << " entries to left " << left << " from right " << right << " with common parent " << parent << "." << std::endl); 03191 03192 BTREE_ASSERT(left->slotuse + shiftnum < innerslotmax); 03193 03194 if (selfverify) 03195 { 03196 // find the left node's slot in the parent's children and compare to parentslot 03197 03198 unsigned int leftslot = 0; 03199 while(leftslot <= parent->slotuse && parent->childid[leftslot] != left) 03200 ++leftslot; 03201 03202 BTREE_ASSERT(leftslot < parent->slotuse); 03203 BTREE_ASSERT(parent->childid[leftslot] == left); 03204 BTREE_ASSERT(parent->childid[leftslot+1] == right); 03205 03206 BTREE_ASSERT(leftslot == parentslot); 03207 } 03208 03209 // copy the parent's decision slotkey and childid to the first new key on the left 03210 left->slotkey[left->slotuse] = parent->slotkey[parentslot]; 03211 left->slotuse++; 03212 03213 // copy the other items from the right node to the last slots in the left node. 03214 for(unsigned int i = 0; i < shiftnum - 1; i++) 03215 { 03216 left->slotkey[left->slotuse + i] = right->slotkey[i]; 03217 left->childid[left->slotuse + i] = right->childid[i]; 03218 } 03219 left->slotuse += shiftnum - 1; 03220 03221 // fixup parent 03222 parent->slotkey[parentslot] = right->slotkey[shiftnum - 1]; 03223 // last pointer in left 03224 left->childid[left->slotuse] = right->childid[shiftnum - 1]; 03225 03226 // shift all slots in the right node 03227 03228 right->slotuse -= shiftnum; 03229 for(int i = 0; i < right->slotuse; i++) 03230 { 03231 right->slotkey[i] = right->slotkey[i + shiftnum]; 03232 right->childid[i] = right->childid[i + shiftnum]; 03233 } 03234 right->childid[right->slotuse] = right->childid[right->slotuse + shiftnum]; 03235 } 03236 03240 static void shift_right_leaf(leaf_node *left, leaf_node *right, inner_node *parent, unsigned int parentslot) 03241 { 03242 BTREE_ASSERT(left->isleafnode() && right->isleafnode()); 03243 BTREE_ASSERT(parent->level == 1); 03244 03245 BTREE_ASSERT(left->nextleaf == right); 03246 BTREE_ASSERT(left == right->prevleaf); 03247 BTREE_ASSERT(parent->childid[parentslot] == left); 03248 03249 BTREE_ASSERT(left->slotuse > right->slotuse); 03250 03251 unsigned int shiftnum = (left->slotuse - right->slotuse) >> 1; 03252 03253 BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to right " << right << " from left " << left << " with common parent " << parent << "." << std::endl); 03254 03255 if (selfverify) 03256 { 03257 // find the left node's slot in the parent's children 03258 unsigned int leftslot = 0; 03259 while(leftslot <= parent->slotuse && parent->childid[leftslot] != left) 03260 ++leftslot; 03261 03262 BTREE_ASSERT(leftslot < parent->slotuse); 03263 BTREE_ASSERT(parent->childid[leftslot] == left); 03264 BTREE_ASSERT(parent->childid[leftslot+1] == right); 03265 03266 BTREE_ASSERT(leftslot == parentslot); 03267 } 03268 03269 // shift all slots in the right node 03270 03271 BTREE_ASSERT(right->slotuse + shiftnum < leafslotmax); 03272 03273 for(int i = right->slotuse-1; i >= 0; i--) 03274 { 03275 right->slotkey[i + shiftnum] = right->slotkey[i]; 03276 right->slotdata[i + shiftnum] = right->slotdata[i]; 03277 } 03278 right->slotuse += shiftnum; 03279 03280 // copy the last items from the left node to the first slot in the right node. 03281 for(unsigned int i = 0; i < shiftnum; i++) 03282 { 03283 right->slotkey[i] = left->slotkey[left->slotuse - shiftnum + i]; 03284 right->slotdata[i] = left->slotdata[left->slotuse - shiftnum + i]; 03285 } 03286 left->slotuse -= shiftnum; 03287 03288 parent->slotkey[parentslot] = left->slotkey[left->slotuse-1]; 03289 } 03290 03294 static void shift_right_inner(inner_node *left, inner_node *right, inner_node *parent, unsigned int parentslot) 03295 { 03296 BTREE_ASSERT(left->level == right->level); 03297 BTREE_ASSERT(parent->level == left->level + 1); 03298 03299 BTREE_ASSERT(left->slotuse > right->slotuse); 03300 BTREE_ASSERT(parent->childid[parentslot] == left); 03301 03302 unsigned int shiftnum = (left->slotuse - right->slotuse) >> 1; 03303 03304 BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to right " << right << " from left " << left << " with common parent " << parent << "." << std::endl); 03305 03306 if (selfverify) 03307 { 03308 // find the left node's slot in the parent's children 03309 unsigned int leftslot = 0; 03310 while(leftslot <= parent->slotuse && parent->childid[leftslot] != left) 03311 ++leftslot; 03312 03313 BTREE_ASSERT(leftslot < parent->slotuse); 03314 BTREE_ASSERT(parent->childid[leftslot] == left); 03315 BTREE_ASSERT(parent->childid[leftslot+1] == right); 03316 03317 BTREE_ASSERT(leftslot == parentslot); 03318 } 03319 03320 // shift all slots in the right node 03321 03322 BTREE_ASSERT(right->slotuse + shiftnum < innerslotmax); 03323 03324 right->childid[right->slotuse + shiftnum] = right->childid[right->slotuse]; 03325 for(int i = right->slotuse-1; i >= 0; i--) 03326 { 03327 right->slotkey[i + shiftnum] = right->slotkey[i]; 03328 right->childid[i + shiftnum] = right->childid[i]; 03329 } 03330 right->slotuse += shiftnum; 03331 03332 // copy the parent's decision slotkey and childid to the last new key on the right 03333 right->slotkey[shiftnum - 1] = parent->slotkey[parentslot]; 03334 right->childid[shiftnum - 1] = left->childid[left->slotuse]; 03335 03336 // copy the remaining last items from the left node to the first slot in the right node. 03337 for(unsigned int i = 0; i < shiftnum - 1; i++) 03338 { 03339 right->slotkey[i] = left->slotkey[left->slotuse - shiftnum + i + 1]; 03340 right->childid[i] = left->childid[left->slotuse - shiftnum + i + 1]; 03341 } 03342 03343 // copy the first to-be-removed key from the left node to the parent's decision slot 03344 parent->slotkey[parentslot] = left->slotkey[left->slotuse - shiftnum]; 03345 03346 left->slotuse -= shiftnum; 03347 } 03348 03349 #ifdef BTREE_DEBUG 03350 public: 03351 // *** Debug Printing 03352 03356 void print(std::ostream &os) const 03357 { 03358 if (root) { 03359 print_node(os, root, 0, true); 03360 } 03361 } 03362 03364 void print_leaves(std::ostream &os) const 03365 { 03366 os << "leaves:" << std::endl; 03367 03368 const leaf_node *n = headleaf; 03369 03370 while(n) 03371 { 03372 os << " " << n << std::endl; 03373 03374 n = n->nextleaf; 03375 } 03376 } 03377 03378 private: 03379 03381 static void print_node(std::ostream &os, const node* node, unsigned int depth=0, bool recursive=false) 03382 { 03383 for(unsigned int i = 0; i < depth; i++) os << " "; 03384 03385 os << "node " << node << " level " << node->level << " slotuse " << node->slotuse << std::endl; 03386 03387 if (node->isleafnode()) 03388 { 03389 const leaf_node *leafnode = static_cast<const leaf_node*>(node); 03390 03391 for(unsigned int i = 0; i < depth; i++) os << " "; 03392 os << " leaf prev " << leafnode->prevleaf << " next " << leafnode->nextleaf << std::endl; 03393 03394 for(unsigned int i = 0; i < depth; i++) os << " "; 03395 03396 for (unsigned int slot = 0; slot < leafnode->slotuse; ++slot) 03397 { 03398 os << leafnode->slotkey[slot] << " "; // << "(data: " << leafnode->slotdata[slot] << ") "; 03399 } 03400 os << std::endl; 03401 } 03402 else 03403 { 03404 const inner_node *innernode = static_cast<const inner_node*>(node); 03405 03406 for(unsigned int i = 0; i < depth; i++) os << " "; 03407 03408 for (unsigned short slot = 0; slot < innernode->slotuse; ++slot) 03409 { 03410 os << "(" << innernode->childid[slot] << ") " << innernode->slotkey[slot] << " "; 03411 } 03412 os << "(" << innernode->childid[innernode->slotuse] << ")" << std::endl; 03413 03414 if (recursive) 03415 { 03416 for (unsigned short slot = 0; slot < innernode->slotuse + 1; ++slot) 03417 { 03418 print_node(os, innernode->childid[slot], depth + 1, recursive); 03419 } 03420 } 03421 } 03422 } 03423 #endif 03424 03425 public: 03426 // *** Verification of B+ Tree Invariants 03427 03430 void verify() const 03431 { 03432 key_type minkey, maxkey; 03433 tree_stats vstats; 03434 03435 if (root) 03436 { 03437 verify_node(root, &minkey, &maxkey, vstats); 03438 03439 assert( vstats.itemcount == stats.itemcount ); 03440 assert( vstats.leaves == stats.leaves ); 03441 assert( vstats.innernodes == stats.innernodes ); 03442 03443 verify_leaflinks(); 03444 } 03445 } 03446 03447 private: 03448 03450 void verify_node(const node* n, key_type* minkey, key_type* maxkey, tree_stats &vstats) const 03451 { 03452 BTREE_PRINT("verifynode " << n << std::endl); 03453 03454 if (n->isleafnode()) 03455 { 03456 const leaf_node *leaf = static_cast<const leaf_node*>(n); 03457 03458 assert( leaf == root || !leaf->isunderflow() ); 03459 assert( leaf->slotuse > 0 ); 03460 03461 for(unsigned short slot = 0; slot < leaf->slotuse - 1; ++slot) 03462 { 03463 assert(key_lessequal(leaf->slotkey[slot], leaf->slotkey[slot + 1])); 03464 } 03465 03466 *minkey = leaf->slotkey[0]; 03467 *maxkey = leaf->slotkey[leaf->slotuse - 1]; 03468 03469 vstats.leaves++; 03470 vstats.itemcount += leaf->slotuse; 03471 } 03472 else // !n->isleafnode() 03473 { 03474 const inner_node *inner = static_cast<const inner_node*>(n); 03475 vstats.innernodes++; 03476 03477 assert( inner == root || !inner->isunderflow() ); 03478 assert( inner->slotuse > 0 ); 03479 03480 for(unsigned short slot = 0; slot < inner->slotuse - 1; ++slot) 03481 { 03482 assert(key_lessequal(inner->slotkey[slot], inner->slotkey[slot + 1])); 03483 } 03484 03485 for(unsigned short slot = 0; slot <= inner->slotuse; ++slot) 03486 { 03487 const node *subnode = inner->childid[slot]; 03488 key_type subminkey = key_type(); 03489 key_type submaxkey = key_type(); 03490 03491 assert(subnode->level + 1 == inner->level); 03492 verify_node(subnode, &subminkey, &submaxkey, vstats); 03493 03494 BTREE_PRINT("verify subnode " << subnode << ": " << subminkey << " - " << submaxkey << std::endl); 03495 03496 if (slot == 0) 03497 *minkey = subminkey; 03498 else 03499 assert(key_greaterequal(subminkey, inner->slotkey[slot-1])); 03500 03501 if (slot == inner->slotuse) 03502 *maxkey = submaxkey; 03503 else 03504 assert(key_equal(inner->slotkey[slot], submaxkey)); 03505 03506 if (inner->level == 1 && slot < inner->slotuse) 03507 { 03508 // children are leaves and must be linked together in the 03509 // correct order 03510 const leaf_node *leafa = static_cast<const leaf_node*>(inner->childid[slot]); 03511 const leaf_node *leafb = static_cast<const leaf_node*>(inner->childid[slot + 1]); 03512 03513 assert(leafa->nextleaf == leafb); 03514 assert(leafa == leafb->prevleaf); 03515 (void)leafa; (void)leafb; 03516 } 03517 if (inner->level == 2 && slot < inner->slotuse) 03518 { 03519 // verify leaf links between the adjacent inner nodes 03520 const inner_node *parenta = static_cast<const inner_node*>(inner->childid[slot]); 03521 const inner_node *parentb = static_cast<const inner_node*>(inner->childid[slot+1]); 03522 03523 const leaf_node *leafa = static_cast<const leaf_node*>(parenta->childid[parenta->slotuse]); 03524 const leaf_node *leafb = static_cast<const leaf_node*>(parentb->childid[0]); 03525 03526 assert(leafa->nextleaf == leafb); 03527 assert(leafa == leafb->prevleaf); 03528 (void)leafa; (void)leafb; 03529 } 03530 } 03531 } 03532 } 03533 03535 void verify_leaflinks() const 03536 { 03537 const leaf_node *n = headleaf; 03538 03539 assert(n->level == 0); 03540 assert(!n || n->prevleaf == NULL); 03541 03542 unsigned int testcount = 0; 03543 03544 while(n) 03545 { 03546 assert(n->level == 0); 03547 assert(n->slotuse > 0); 03548 03549 for(unsigned short slot = 0; slot < n->slotuse - 1; ++slot) 03550 { 03551 assert(key_lessequal(n->slotkey[slot], n->slotkey[slot + 1])); 03552 } 03553 03554 testcount += n->slotuse; 03555 03556 if (n->nextleaf) 03557 { 03558 assert(key_lessequal(n->slotkey[n->slotuse-1], n->nextleaf->slotkey[0])); 03559 03560 assert(n == n->nextleaf->prevleaf); 03561 } 03562 else 03563 { 03564 assert(tailleaf == n); 03565 } 03566 03567 n = n->nextleaf; 03568 } 03569 03570 assert(testcount == size()); 03571 } 03572 03573 private: 03574 // *** Dump and Restore of B+ Trees 03575 03579 struct dump_header 03580 { 03582 char signature[12]; 03583 03585 unsigned short version; 03586 03588 unsigned short key_type_size; 03589 03591 unsigned short data_type_size; 03592 03594 unsigned short leafslots; 03595 03597 unsigned short innerslots; 03598 03600 bool allow_duplicates; 03601 03603 size_type itemcount; 03604 03607 inline void fill() 03608 { 03609 // don't want to include string.h just for this signature 03610 signature[0] = 's'; signature[1] = 't'; signature[2] = 'x'; signature[3] = '-'; 03611 signature[4] = 'b'; signature[5] = 't'; signature[6] = 'r'; signature[7] = 'e'; 03612 signature[8] = 'e'; signature[9] = 0; signature[10] = 0; signature[11] = 0; 03613 03614 version = 0; 03615 key_type_size = sizeof(typename btree_self::key_type); 03616 data_type_size = sizeof(typename btree_self::data_type); 03617 leafslots = btree_self::leafslotmax; 03618 innerslots = btree_self::innerslotmax; 03619 allow_duplicates = btree_self::allow_duplicates; 03620 } 03621 03623 inline bool same(const struct dump_header &o) const 03624 { 03625 return (signature[0] == 's' && signature[1] == 't' && signature[2] == 'x' && signature[3] == '-' && 03626 signature[4] == 'b' && signature[5] == 't' && signature[6] == 'r' && signature[7] == 'e' && 03627 signature[8] == 'e' && signature[9] == 0 && signature[10] == 0 && signature[11] == 0) 03628 && (version == o.version) 03629 && (key_type_size == o.key_type_size) 03630 && (data_type_size == o.data_type_size) 03631 && (leafslots == o.leafslots) 03632 && (innerslots == o.innerslots) 03633 && (allow_duplicates == o.allow_duplicates); 03634 } 03635 }; 03636 03637 public: 03638 03643 void dump(std::ostream &os) const 03644 { 03645 struct dump_header header; 03646 header.fill(); 03647 header.itemcount = size(); 03648 03649 os.write(reinterpret_cast<char*>(&header), sizeof(header)); 03650 03651 if (root) { 03652 dump_node(os, root); 03653 } 03654 } 03655 03660 bool restore(std::istream &is) 03661 { 03662 struct dump_header fileheader; 03663 is.read(reinterpret_cast<char*>(&fileheader), sizeof(fileheader)); 03664 if (!is.good()) return false; 03665 03666 struct dump_header myheader; 03667 myheader.fill(); 03668 myheader.itemcount = fileheader.itemcount; 03669 03670 if (!myheader.same(fileheader)) 03671 { 03672 BTREE_PRINT("btree::restore: file header does not match instantiation signature." << std::endl); 03673 return false; 03674 } 03675 03676 clear(); 03677 03678 if (fileheader.itemcount > 0) 03679 { 03680 root = restore_node(is); 03681 if (root == NULL) return false; 03682 03683 stats.itemcount = fileheader.itemcount; 03684 } 03685 03686 #ifdef BTREE_DEBUG 03687 if (debug) print(std::cout); 03688 #endif 03689 if (selfverify) verify(); 03690 03691 return true; 03692 } 03693 03694 private: 03695 03697 void dump_node(std::ostream &os, const node* n) const 03698 { 03699 BTREE_PRINT("dump_node " << n << std::endl); 03700 03701 if (n->isleafnode()) 03702 { 03703 const leaf_node *leaf = static_cast<const leaf_node*>(n); 03704 03705 os.write(reinterpret_cast<const char*>(leaf), sizeof(*leaf)); 03706 } 03707 else // !n->isleafnode() 03708 { 03709 const inner_node *inner = static_cast<const inner_node*>(n); 03710 03711 os.write(reinterpret_cast<const char*>(inner), sizeof(*inner)); 03712 03713 for(unsigned short slot = 0; slot <= inner->slotuse; ++slot) 03714 { 03715 const node *subnode = inner->childid[slot]; 03716 03717 dump_node(os, subnode); 03718 } 03719 } 03720 } 03721 03724 node* restore_node(std::istream &is) 03725 { 03726 union { 03727 node top; 03728 leaf_node leaf; 03729 inner_node inner; 03730 } nu; 03731 03732 // first read only the top of the node 03733 is.read(reinterpret_cast<char*>(&nu.top), sizeof(nu.top)); 03734 if (!is.good()) return NULL; 03735 03736 if (nu.top.isleafnode()) 03737 { 03738 // read remaining data of leaf node 03739 is.read(reinterpret_cast<char*>(&nu.leaf) + sizeof(nu.top), sizeof(nu.leaf) - sizeof(nu.top)); 03740 if (!is.good()) return NULL; 03741 03742 leaf_node *newleaf = allocate_leaf(); 03743 03744 // copy over all data, the leaf nodes contain only their double linked list pointers 03745 *newleaf = nu.leaf; 03746 03747 // reconstruct the linked list from the order in the file 03748 if (headleaf == NULL) { 03749 BTREE_ASSERT(newleaf->prevleaf == NULL); 03750 headleaf = tailleaf = newleaf; 03751 } 03752 else { 03753 newleaf->prevleaf = tailleaf; 03754 tailleaf->nextleaf = newleaf; 03755 tailleaf = newleaf; 03756 } 03757 03758 return newleaf; 03759 } 03760 else 03761 { 03762 // read remaining data of inner node 03763 is.read(reinterpret_cast<char*>(&nu.inner) + sizeof(nu.top), sizeof(nu.inner) - sizeof(nu.top)); 03764 if (!is.good()) return NULL; 03765 03766 inner_node *newinner = allocate_inner(0); 03767 03768 // copy over all data, the inner nodes contain only pointers to their children 03769 *newinner = nu.inner; 03770 03771 for(unsigned short slot = 0; slot <= newinner->slotuse; ++slot) 03772 { 03773 newinner->childid[slot] = restore_node(is); 03774 } 03775 03776 return newinner; 03777 } 03778 } 03779 }; 03780 03781 } // namespace stx 03782 03783 #endif // _STX_BTREE_H_