stx/btree.h

Go to the documentation of this file.
00001 // $Id: btree.h 37 2007-04-27 12:13:27Z tb $
00006 /*
00007  * STX B+ Tree Template Classes v0.7
00008  * Copyright (C) 2007 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 <functional>
00031 #include <algorithm>
00032 #include <istream>
00033 #include <ostream>
00034 #include <assert.h>
00035 
00036 // *** Debugging Macros
00037 
00038 #ifdef BTREE_DEBUG
00039 
00040 #include <iostream>
00041 
00043 #define BTREE_PRINT(x)          do { if (debug) (std::cout << x); } while(0)
00044 
00046 #define BTREE_ASSERT(x)         do { assert(x); } while(0)
00047 
00048 #else
00049 
00051 #define BTREE_PRINT(x)          do { } while(0)
00052 
00054 #define BTREE_ASSERT(x)         do { } while(0)
00055 
00056 #endif
00057 
00059 #define BTREE_MAX(a,b)          ((a) < (b) ? (b) : (a))
00060 
00062 namespace stx {
00063 
00066 template <typename _Key>
00067 struct btree_default_set_traits
00068 {
00071     static const bool   selfverify = false;
00072 
00077     static const bool   debug = false;
00078 
00081     static const int    leafslots = BTREE_MAX( 8, 256 / (sizeof(_Key)) );
00082 
00085     static const int    innerslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(void*)) );
00086 };
00087 
00090 template <typename _Key, typename _Data>
00091 struct btree_default_map_traits
00092 {
00095     static const bool   selfverify = false;
00096 
00101     static const bool   debug = false;
00102 
00105     static const int    leafslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(_Data)) );
00106 
00109     static const int    innerslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(void*)) );
00110 };
00111 
00125 template <typename _Key, typename _Data,
00126           typename _Value = std::pair<_Key, _Data>,
00127           typename _Compare = std::less<_Key>,
00128           typename _Traits = btree_default_map_traits<_Key, _Data>,
00129           bool _Duplicates = false>
00130 class btree
00131 {
00132 public:
00133     // *** Template Parameter Types
00134 
00137     typedef _Key                        key_type;
00138 
00141     typedef _Data                       data_type;
00142 
00147     typedef _Value                      value_type;
00148 
00150     typedef _Compare                    key_compare;
00151 
00154     typedef _Traits                     traits;
00155 
00158     static const bool                   allow_duplicates = _Duplicates;
00159 
00160 public:
00161     // *** Constructed Types
00162 
00164     typedef btree<key_type, data_type, value_type,
00165                   key_compare, traits, allow_duplicates>        btree_self;
00166 
00168     typedef size_t                              size_type;
00169 
00171     typedef std::pair<key_type, data_type>      pair_type;
00172 
00173 public:
00174     // *** Static Constant Options and Values of the B+ Tree
00175 
00177     static const unsigned short         leafslotmax =  traits::leafslots;
00178 
00181     static const unsigned short         innerslotmax =  traits::innerslots;
00182 
00186     static const unsigned short         minleafslots = (leafslotmax / 2);
00187 
00191     static const unsigned short         mininnerslots = (innerslotmax / 2);
00192 
00195     static const bool                   selfverify = traits::selfverify;
00196 
00200     static const bool                   debug = traits::debug;
00201 
00202 private:
00203     // *** Node Classes for In-Memory Nodes
00204 
00207     struct node
00208     {
00210         unsigned short  level;
00211 
00214         unsigned short  slotuse;
00215 
00217         inline void initialize(const unsigned short l)
00218         {
00219             level = l;
00220             slotuse = 0;
00221         }
00222         
00224         inline bool isleafnode() const
00225         {
00226             return (level == 0);
00227         }
00228     };
00229 
00232     struct inner_node : public node
00233     {
00235         key_type        slotkey[innerslotmax];
00236 
00238         node*           childid[innerslotmax+1];
00239 
00241         inline void initialize(const unsigned short l)
00242         {
00243             node::initialize(l);
00244         }
00245 
00247         inline bool isfull() const
00248         {
00249             return (node::slotuse == innerslotmax);
00250         }
00251 
00253         inline bool isfew() const
00254         {
00255             return (node::slotuse <= mininnerslots);
00256         }
00257 
00259         inline bool isunderflow() const
00260         {
00261             return (node::slotuse < mininnerslots);
00262         }
00263     };
00264 
00268     struct leaf_node : public node
00269     {
00271         leaf_node       *prevleaf;
00272 
00274         leaf_node       *nextleaf;
00275 
00277         key_type        slotkey[leafslotmax];
00278 
00280         data_type       slotdata[leafslotmax];
00281 
00283         inline void initialize()
00284         {
00285             node::initialize(0);
00286             prevleaf = nextleaf = NULL;
00287         }
00288 
00290         inline bool isfull() const
00291         {
00292             return (node::slotuse == leafslotmax);
00293         }
00294 
00296         inline bool isfew() const
00297         {
00298             return (node::slotuse <= minleafslots);
00299         }
00300 
00302         inline bool isunderflow() const
00303         {
00304             return (node::slotuse < minleafslots);
00305         }
00306     };
00307 
00308 private:
00309     // *** Template Magic to Convert a pair or key/data types to a value_type
00310 
00313     template <typename value_type, typename pair_type>
00314     struct btree_pair_to_value
00315     {
00317         inline value_type operator()(pair_type& p) const {
00318             return p.first;
00319         }
00321         inline value_type operator()(const pair_type& p) const {
00322             return p.first;
00323         }
00324     };
00325 
00327     template <typename value_type>
00328     struct btree_pair_to_value<value_type, value_type>
00329     {
00331         inline value_type operator()(pair_type& p) const {
00332             return p;
00333         }
00335         inline value_type operator()(const pair_type& p) const {
00336             return p;
00337         }
00338     };
00339 
00342     typedef btree_pair_to_value<value_type, pair_type> pair_to_value_type;
00343 
00344 public:
00345     // *** Iterators and Reverse Iterators
00346 
00347     class iterator;
00348     class const_iterator;
00349 
00352     class iterator
00353     {
00354     public:
00355         // *** Types
00356 
00358         typedef typename btree::key_type                key_type;
00359 
00361         typedef typename btree::data_type               data_type;
00362 
00364         typedef typename btree::value_type              value_type;
00365 
00367         typedef typename btree::pair_type               pair_type;
00368 
00370         typedef value_type&             reference;
00371 
00373         typedef value_type*             pointer;
00374 
00376         typedef std::bidirectional_iterator_tag iterator_category;
00377 
00379         typedef ptrdiff_t               difference_type;
00380 
00382         typedef iterator                self;
00383 
00384     private:
00385         // *** Members
00386 
00388         typename btree::leaf_node*      currnode;
00389 
00391         unsigned short  currslot;
00392     
00394         friend class btree<key_type, data_type, value_type, key_compare, traits, allow_duplicates>::const_iterator;
00395         
00398         mutable value_type              temp_value;
00399 
00400     public:
00401         // *** Methods
00402 
00404         inline iterator(typename btree::leaf_node *l, unsigned short s)
00405             : currnode(l), currslot(s)
00406         { }
00407 
00410         inline reference operator*() const
00411         {
00412             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
00413                                                          currnode->slotdata[currslot]) );
00414             return temp_value;
00415         }
00416 
00420         inline pointer operator->() const
00421         {
00422             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
00423                                                          currnode->slotdata[currslot]) );
00424             return &temp_value;
00425         }
00426 
00428         inline const key_type& key() const
00429         {
00430             return currnode->slotkey[currslot];
00431         }
00432 
00434         inline data_type& data() const
00435         {
00436             return currnode->slotdata[currslot];
00437         }
00438 
00440         inline self& operator++()
00441         {
00442             if (currslot + 1 < currnode->slotuse) {
00443                 ++currslot;
00444             }
00445             else if (currnode->nextleaf != NULL) {
00446                 currnode = currnode->nextleaf;
00447                 currslot = 0;
00448             }
00449             else {
00450                 // this is end()
00451                 currslot = currnode->slotuse;
00452             }
00453 
00454             return *this;
00455         }
00456 
00458         inline self operator++(int)
00459         {
00460             self tmp = *this;   // copy ourselves
00461 
00462             if (currslot + 1 < currnode->slotuse) {
00463                 ++currslot;
00464             }
00465             else if (currnode->nextleaf != NULL) {
00466                 currnode = currnode->nextleaf;
00467                 currslot = 0;
00468             }
00469             else {
00470                 // this is end()
00471                 currslot = currnode->slotuse;
00472             }
00473 
00474             return tmp;
00475         }
00476 
00478         inline self& operator--()
00479         {
00480             if (currslot > 0) {
00481                 --currslot;
00482             }
00483             else if (currnode->prevleaf != NULL) {
00484                 currnode = currnode->prevleaf;
00485                 currslot = currnode->slotuse - 1;
00486             }
00487             else {
00488                 // this is begin()
00489                 currslot = 0;
00490             }
00491 
00492             return *this;
00493         }
00494 
00496         inline self operator--(int)
00497         {
00498             self tmp = *this;   // copy ourselves
00499 
00500             if (currslot > 0) {
00501                 --currslot;
00502             }
00503             else if (currnode->prevleaf != NULL) {
00504                 currnode = currnode->prevleaf;
00505                 currslot = currnode->slotuse - 1;
00506             }
00507             else {
00508                 // this is begin()
00509                 currslot = 0;
00510             }
00511 
00512             return tmp;
00513         }
00514 
00516         inline bool operator==(const self& x) const
00517         {
00518             return (x.currnode == currnode) && (x.currslot == currslot);
00519         }
00520 
00522         inline bool operator!=(const self& x) const
00523         {
00524             return (x.currnode != currnode) || (x.currslot != currslot);
00525         }    
00526     };
00527 
00530     class const_iterator
00531     {
00532     public:
00533         // *** Types
00534 
00536         typedef typename btree::key_type                key_type;
00537 
00539         typedef typename btree::data_type               data_type;
00540 
00542         typedef typename btree::value_type              value_type;
00543 
00545         typedef typename btree::pair_type               pair_type;
00546 
00548         typedef const value_type&       reference;
00549 
00551         typedef const value_type*       pointer;
00552 
00554         typedef std::bidirectional_iterator_tag iterator_category;
00555 
00557         typedef ptrdiff_t               difference_type;
00558 
00560         typedef const_iterator          self;
00561 
00562     private:
00563         // *** Members
00564 
00566         const typename btree::leaf_node*        currnode;
00567 
00569         unsigned short  currslot;
00570     
00573         mutable value_type              temp_value;
00574 
00575     public:
00576         // *** Methods
00577 
00579         inline const_iterator(const typename btree::leaf_node *l, unsigned short s)
00580             : currnode(l), currslot(s)
00581         { }
00582 
00584         inline const_iterator(const iterator &it)
00585             : currnode(it.currnode), currslot(it.currslot)
00586         { }
00587 
00591         inline reference operator*() const
00592         {
00593             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
00594                                                          currnode->slotdata[currslot]) );
00595             return temp_value;
00596         }
00597 
00601         inline pointer operator->() const
00602         {
00603             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
00604                                                          currnode->slotdata[currslot]) );
00605             return &temp_value;
00606         }
00607 
00609         inline const key_type& key() const
00610         {
00611             return currnode->slotkey[currslot];
00612         }
00613 
00615         inline const data_type& data() const
00616         {
00617             return currnode->slotdata[currslot];
00618         }
00619 
00621         inline self& operator++()
00622         {
00623             if (currslot + 1 < currnode->slotuse) {
00624                 ++currslot;
00625             }
00626             else if (currnode->nextleaf != NULL) {
00627                 currnode = currnode->nextleaf;
00628                 currslot = 0;
00629             }
00630             else {
00631                 // this is end()
00632                 currslot = currnode->slotuse;
00633             }
00634 
00635             return *this;
00636         }
00637 
00639         inline self operator++(int)
00640         {
00641             self tmp = *this;   // copy ourselves
00642 
00643             if (currslot + 1 < currnode->slotuse) {
00644                 ++currslot;
00645             }
00646             else if (currnode->nextleaf != NULL) {
00647                 currnode = currnode->nextleaf;
00648                 currslot = 0;
00649             }
00650             else {
00651                 // this is end()
00652                 currslot = currnode->slotuse;
00653             }
00654 
00655             return tmp;
00656         }
00657 
00659         inline self& operator--()
00660         {
00661             if (currslot > 0) {
00662                 --currslot;
00663             }
00664             else if (currnode->prevleaf != NULL) {
00665                 currnode = currnode->prevleaf;
00666                 currslot = currnode->slotuse - 1;
00667             }
00668             else {
00669                 // this is begin()
00670                 currslot = 0;
00671             }
00672 
00673             return *this;
00674         }
00675 
00677         inline self operator--(int)
00678         {
00679             self tmp = *this;   // copy ourselves
00680 
00681             if (currslot > 0) {
00682                 --currslot;
00683             }
00684             else if (currnode->prevleaf != NULL) {
00685                 currnode = currnode->prevleaf;
00686                 currslot = currnode->slotuse - 1;
00687             }
00688             else {
00689                 // this is begin()
00690                 currslot = 0;
00691             }
00692 
00693             return tmp;
00694         }
00695 
00697         inline bool operator==(const self& x) const
00698         {
00699             return (x.currnode == currnode) && (x.currslot == currslot);
00700         }
00701 
00703         inline bool operator!=(const self& x) const
00704         {
00705             return (x.currnode != currnode) || (x.currslot != currslot);
00706         }    
00707     };
00708 
00710     typedef std::reverse_iterator<iterator>       reverse_iterator;
00711 
00713     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00714 
00715 public:
00716     // *** Small Statistics Structure
00717 
00720     struct tree_stats
00721     {
00723         size_type       itemcount;
00724 
00726         size_type       leaves;
00727 
00729         size_type       innernodes;
00730 
00732         static const unsigned short     leafslots = btree_self::leafslotmax;
00733 
00735         static const unsigned short     innerslots = btree_self::innerslotmax;
00736 
00738         inline tree_stats()
00739             : itemcount(0),
00740               leaves(0), innernodes(0)
00741         {
00742         }
00743 
00745         inline size_type nodes() const
00746         {
00747             return innernodes + leaves;
00748         }
00749 
00751         inline double avgfill_leaves() const
00752         {
00753             return static_cast<double>(itemcount) / (leaves * leafslots);
00754         }
00755     };
00756 
00757 private:
00758     // *** Tree Object Data Members
00759 
00761     node*       root;
00762 
00764     leaf_node   *headleaf;
00765 
00767     leaf_node   *tailleaf;
00768 
00770     tree_stats  stats;
00771 
00774     key_compare key_less;
00775 
00776 public:
00777     // *** Constructors and Destructor
00778 
00781     inline btree()
00782         : root(NULL), headleaf(NULL), tailleaf(NULL)
00783     {
00784     }
00785 
00788     inline btree(const key_compare &kcf)
00789         : root(NULL), headleaf(NULL), tailleaf(NULL),
00790           key_less(kcf)
00791     {
00792     }
00793 
00795     template <class InputIterator>
00796     inline btree(InputIterator first, InputIterator last)
00797         : root(NULL), headleaf(NULL), tailleaf(NULL)
00798     {
00799         insert(first, last);
00800     }
00801 
00804     template <class InputIterator>
00805     inline btree(InputIterator first, InputIterator last, const key_compare &kcf)
00806         : root(NULL), headleaf(NULL), tailleaf(NULL),
00807           key_less(kcf)
00808     {
00809         insert(first, last);
00810     }
00811 
00813     inline ~btree()
00814     {
00815         clear();
00816     }
00817 
00819     void swap(btree_self& from)
00820     {
00821         std::swap(root, from.root);
00822         std::swap(headleaf, from.headleaf);
00823         std::swap(tailleaf, from.tailleaf);
00824         std::swap(stats, from.stats);
00825         std::swap(key_less, from.key_less);
00826     }
00827 
00828 public:
00829     // *** Key and Value Comparison Function Objects
00830 
00832     class value_compare
00833     {
00834     protected:
00836         key_compare     key_comp;
00837  
00839         inline value_compare(key_compare kc)
00840             : key_comp(kc)
00841         { }
00842 
00844         friend class btree<key_type, data_type, value_type, key_compare, traits, allow_duplicates>;
00845  
00846     public:
00848         inline bool operator()(const value_type& x, const value_type& y) const
00849         {
00850             return key_comp(x.first, y.first);
00851         }
00852     };
00853 
00855     inline key_compare key_comp() const
00856     {
00857         return key_less;
00858     }
00859 
00862     inline value_compare value_comp() const
00863     {
00864         return value_compare(key_less);
00865     }
00866 
00867 private:
00868     // *** Convenient Key Comparison Functions Generated From key_less
00869 
00871     inline bool key_lessequal(const key_type &a, const key_type b) const
00872     {
00873         return !key_less(b, a);
00874     }
00875 
00877     inline bool key_greater(const key_type &a, const key_type &b) const
00878     {
00879         return key_less(b, a);
00880     }
00881 
00883     inline bool key_greaterequal(const key_type &a, const key_type b) const
00884     {
00885         return !key_less(a, b);
00886     }
00887 
00890     inline bool key_equal(const key_type &a, const key_type &b) const
00891     {
00892         return !key_less(a, b) && !key_less(b, a);
00893     }
00894 
00895 private:
00896     // *** Node Object Allocation and Deallocation Functions
00897 
00899     inline leaf_node* allocate_leaf()
00900     {
00901         leaf_node* n = new leaf_node;
00902         n->initialize();
00903         stats.leaves++;
00904         return n;
00905     }
00906 
00908     inline inner_node* allocate_inner(unsigned short l)
00909     {
00910         inner_node* n = new inner_node;
00911         n->initialize(l);
00912         stats.innernodes++;
00913         return n;
00914     }
00915     
00918     inline void free_node(node *n)
00919     {
00920         if (n->isleafnode()) {
00921             delete static_cast<leaf_node*>(n);
00922             stats.leaves--;
00923         }
00924         else {
00925             delete static_cast<inner_node*>(n);
00926             stats.innernodes--;
00927         }
00928     }
00929 
00930 public:
00931     // *** Fast Destruction of the B+ Tree
00932 
00934     void clear()
00935     {
00936         if (root)
00937         {
00938             clear_recursive(root);
00939             free_node(root);
00940 
00941             root = NULL;
00942             headleaf = tailleaf = NULL;
00943 
00944             stats = tree_stats();
00945         }
00946 
00947         BTREE_ASSERT(stats.itemcount == 0);
00948     }
00949 
00950 private:
00952     void clear_recursive(node *n)
00953     {
00954         if (n->isleafnode())
00955         {
00956             leaf_node *leafnode = static_cast<leaf_node*>(n);
00957 
00958             for (unsigned int slot = 0; slot < leafnode->slotuse; ++slot)
00959             {
00960                 // data objects are deleted by leaf_node's destructor
00961             }
00962         }
00963         else
00964         {
00965             inner_node *innernode = static_cast<inner_node*>(n);
00966 
00967             for (unsigned short slot = 0; slot < innernode->slotuse + 1; ++slot)
00968             {
00969                 clear_recursive(innernode->childid[slot]);
00970                 free_node(innernode->childid[slot]);
00971             }
00972         }
00973     }
00974 
00975 public:
00976     // *** STL Iterator Construction Functions
00977 
00980     inline iterator begin()
00981     {
00982         return iterator(headleaf, 0);
00983     }
00984 
00987     inline iterator end()
00988     {
00989         return iterator(tailleaf, tailleaf->slotuse);
00990     }
00991 
00994     inline const_iterator begin() const
00995     {
00996         return const_iterator(headleaf, 0);
00997     }
00998 
01001     inline const_iterator end() const
01002     {
01003         return const_iterator(tailleaf, tailleaf->slotuse);
01004     }
01005 
01008     inline reverse_iterator rbegin()
01009     {
01010         return reverse_iterator(end());
01011     }
01012 
01015     inline reverse_iterator rend()
01016     {
01017         return reverse_iterator(begin());
01018     }
01019 
01022     inline const_reverse_iterator rbegin() const
01023     {
01024         return const_reverse_iterator(end());
01025     }
01026 
01029     inline const_reverse_iterator rend() const
01030     {
01031         return const_reverse_iterator(begin());
01032     }
01033 
01034 private:
01035     // *** B+ Tree Node Binary Search Functions
01036 
01041     template <typename node_type>
01042     inline int find_lower(const node_type *n, const key_type& key) const
01043     {
01044         if (n->slotuse == 0) return 0;
01045 
01046         int lo = 0,
01047             hi = n->slotuse - 1;
01048 
01049         while(lo < hi)
01050         {
01051             int mid = (lo + hi) / 2;
01052 
01053             if (key_lessequal(key, n->slotkey[mid])) {
01054                 hi = mid - 1;
01055             }
01056             else {
01057                 lo = mid + 1;
01058             }
01059         }
01060 
01061         if (hi < 0 || key_less(n->slotkey[hi], key))
01062             hi++;
01063 
01064         BTREE_PRINT("btree::find_lower: on " << n << " key " << key << " -> (" << lo << ") " << hi << ", ");
01065 
01066         // verify result using simple linear search
01067         if (selfverify)
01068         {
01069             int i = n->slotuse - 1;
01070             while(i >= 0 && key_lessequal(key, n->slotkey[i]))
01071                 i--;
01072             i++;
01073 
01074             BTREE_PRINT("testfind: " << i << std::endl);
01075             BTREE_ASSERT(i == hi);
01076         }
01077         else {
01078             BTREE_PRINT(std::endl);
01079         }
01080         
01081         return hi;
01082     }
01083 
01088     template <typename node_type>
01089     inline int find_upper(const node_type *n, const key_type& key) const
01090     {
01091         if (n->slotuse == 0) return 0;
01092 
01093         int lo = 0,
01094             hi = n->slotuse - 1;
01095 
01096         while(lo < hi)
01097         {
01098             int mid = (lo + hi) / 2;
01099 
01100             if (key_less(key, n->slotkey[mid])) {
01101                 hi = mid - 1;
01102             }
01103             else {
01104                 lo = mid + 1;
01105             }
01106         }
01107 
01108         if (hi < 0 || key_lessequal(n->slotkey[hi], key))
01109             hi++;
01110 
01111         BTREE_PRINT("btree::find_upper: on " << n << " key " << key << " -> (" << lo << ") " << hi << ", ");
01112 
01113         // verify result using simple linear search
01114         if (selfverify)
01115         {
01116             int i = n->slotuse - 1;
01117             while(i >= 0 && key_less(key, n->slotkey[i]))
01118                 i--;
01119             i++;
01120 
01121             BTREE_PRINT("btree::find_upper testfind: " << i << std::endl);
01122             BTREE_ASSERT(i == hi);
01123         }
01124         else {
01125             BTREE_PRINT(std::endl);
01126         }
01127         
01128         return hi;
01129     }
01130 
01131 public:
01132     // *** Access Functions to the Item Count
01133 
01135     inline size_type size() const
01136     {
01137         return stats.itemcount;
01138     }
01139 
01141     inline bool empty() const
01142     {
01143         return (size() == size_type(0));
01144     }
01145     
01148     inline size_type max_size() const
01149     {
01150         return size_type(-1);
01151     }
01152 
01154     inline const struct tree_stats& get_stats() const
01155     {
01156         return stats;
01157     }
01158 
01159 public:
01160     // *** Standard Access Functions Querying the Tree by Descending to a Leaf
01161 
01164     bool exists(const key_type &key) const
01165     {
01166         const node *n = root;
01167 
01168         if (!n) return false;
01169 
01170         while(!n->isleafnode())
01171         {
01172             const inner_node *inner = static_cast<const inner_node*>(n);
01173             int slot = find_lower(inner, key);
01174 
01175             n = inner->childid[slot];
01176         }
01177 
01178         const leaf_node *leaf = static_cast<const leaf_node*>(n);
01179 
01180         int slot = find_lower(leaf, key);
01181         return key_equal(key, leaf->slotkey[slot]);
01182     }
01183 
01186     iterator find(const key_type &key)
01187     {
01188         node *n = root;
01189         if (!n) return end();
01190 
01191         while(!n->isleafnode())
01192         {
01193             const inner_node *inner = static_cast<const inner_node*>(n);
01194             int slot = find_lower(inner, key);
01195 
01196             n = inner->childid[slot];
01197         }
01198 
01199         leaf_node *leaf = static_cast<leaf_node*>(n);
01200 
01201         int slot = find_lower(leaf, key);
01202         return key_equal(key, leaf->slotkey[slot]) ? iterator(leaf, slot) : end();
01203     }
01204 
01207     const_iterator find(const key_type &key) const
01208     {
01209         const node *n = root;
01210         if (!n) return end();
01211 
01212         while(!n->isleafnode())
01213         {
01214             const inner_node *inner = static_cast<const inner_node*>(n);
01215             int slot = find_lower(inner, key);
01216 
01217             n = inner->childid[slot];
01218         }
01219 
01220         const leaf_node *leaf = static_cast<const leaf_node*>(n);
01221 
01222         int slot = find_lower(leaf, key);
01223         return key_equal(key, leaf->slotkey[slot]) ? const_iterator(leaf, slot) : end();
01224     }
01225 
01228     size_type count(const key_type &key) const
01229     {
01230         const node *n = root;
01231         if (!n) return 0;
01232 
01233         while(!n->isleafnode())
01234         {
01235             const inner_node *inner = static_cast<const inner_node*>(n);
01236             int slot = find_lower(inner, key);
01237 
01238             n = inner->childid[slot];
01239         }
01240 
01241         const leaf_node *leaf = static_cast<const leaf_node*>(n);
01242 
01243         int slot = find_lower(leaf, key);
01244         size_type num = 0;
01245 
01246         while (leaf && key_equal(key, leaf->slotkey[slot]))
01247         {
01248             ++num;
01249             if (++slot >= leaf->slotuse)
01250             {
01251                 leaf = leaf->nextleaf;
01252                 slot = 0;
01253             }
01254         }
01255 
01256         return num;
01257     }
01258 
01261     iterator lower_bound(const key_type& key)
01262     {
01263         node *n = root;
01264         if (!n) return end();
01265 
01266         while(!n->isleafnode())
01267         {
01268             const inner_node *inner = static_cast<const inner_node*>(n);
01269             int slot = find_lower(inner, key);
01270 
01271             n = inner->childid[slot];
01272         }
01273 
01274         leaf_node *leaf = static_cast<leaf_node*>(n);
01275 
01276         int slot = find_lower(leaf, key);
01277         return iterator(leaf, slot);
01278     }
01279 
01282     const_iterator lower_bound(const key_type& key) const
01283     {
01284         const node *n = root;
01285         if (!n) return end();
01286 
01287         while(!n->isleafnode())
01288         {
01289             const inner_node *inner = static_cast<const inner_node*>(n);
01290             int slot = find_lower(inner, key);
01291 
01292             n = inner->childid[slot];
01293         }
01294 
01295         const leaf_node *leaf = static_cast<const leaf_node*>(n);
01296 
01297         int slot = find_lower(leaf, key);
01298         return const_iterator(leaf, slot);
01299     }
01300 
01303     iterator upper_bound(const key_type& key)
01304     {
01305         node *n = root;
01306         if (!n) return end();
01307 
01308         while(!n->isleafnode())
01309         {
01310             const inner_node *inner = static_cast<const inner_node*>(n);
01311             int slot = find_upper(inner, key);
01312 
01313             n = inner->childid[slot];
01314         }
01315 
01316         leaf_node *leaf = static_cast<leaf_node*>(n);
01317 
01318         int slot = find_upper(leaf, key);
01319         return iterator(leaf, slot);
01320     }
01321 
01324     const_iterator upper_bound(const key_type& key) const
01325     {
01326         const node *n = root;
01327         if (!n) return end();
01328 
01329         while(!n->isleafnode())
01330         {
01331             const inner_node *inner = static_cast<const inner_node*>(n);
01332             int slot = find_upper(inner, key);
01333 
01334             n = inner->childid[slot];
01335         }
01336 
01337         const leaf_node *leaf = static_cast<const leaf_node*>(n);
01338 
01339         int slot = find_upper(leaf, key);
01340         return const_iterator(leaf, slot);
01341     }
01342 
01344     inline std::pair<iterator, iterator> equal_range(const key_type& key)
01345     {
01346         return std::pair<iterator, iterator>(lower_bound(key), upper_bound(key));
01347     }
01348 
01350     inline std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const
01351     {
01352         return std::pair<const_iterator, const_iterator>(lower_bound(key), upper_bound(key));
01353     }
01354 
01355 public:
01356     // *** B+ Tree Object Comparison Functions
01357 
01361     inline bool operator==(const btree_self &other) const
01362     {
01363         return (size() == other.size()) && std::equal(begin(), end(), other.begin());
01364     }
01365 
01367     inline bool operator!=(const btree_self &other) const
01368     {
01369         return !(*this == other);
01370     }
01371 
01374     inline bool operator<(const btree_self &other) const
01375     {
01376         return std::lexicographical_compare(begin(), end(), other.begin(), other.end());
01377     }
01378 
01380     inline bool operator>(const btree_self &other) const
01381     {
01382         return other < *this;
01383     }
01384 
01386     inline bool operator<=(const btree_self &other) const
01387     {
01388         return !(other < *this);
01389     }
01390 
01392     inline bool operator>=(const btree_self &other) const
01393     {
01394         return !(*this < other);
01395     }
01396 
01397 public:
01399 
01401     inline btree_self& operator= (const btree_self &other)
01402     {
01403         if (this != &other)
01404         {
01405             clear();
01406 
01407             key_less = other.key_comp();
01408             if (other.size() != 0)
01409             {
01410                 stats.leaves = stats.innernodes = 0;
01411                 root = copy_recursive(other.root);
01412                 stats = other.stats;
01413             }
01414 
01415             if (selfverify) verify();
01416         }
01417         return *this;
01418     }
01419 
01422     inline btree(const btree_self &other)
01423         : root(NULL), headleaf(NULL), tailleaf(NULL),
01424           stats( other.stats ),
01425           key_less( other.key_comp() )
01426     {
01427         if (size() > 0)
01428         {
01429             stats.leaves = stats.innernodes = 0;
01430             root = copy_recursive(other.root);
01431             if (selfverify) verify();
01432         }
01433     }
01434     
01435 private:
01437     class node* copy_recursive(const node *n)
01438     {
01439         if (n->isleafnode())
01440         {
01441             const leaf_node *leaf = static_cast<const leaf_node*>(n);
01442             leaf_node *newleaf = allocate_leaf();
01443 
01444             newleaf->slotuse = leaf->slotuse;
01445             std::copy(leaf->slotkey, leaf->slotkey + leaf->slotuse, newleaf->slotkey);
01446             std::copy(leaf->slotdata, leaf->slotdata + leaf->slotuse, newleaf->slotdata);
01447 
01448             if (headleaf == NULL)
01449             {
01450                 headleaf = tailleaf = newleaf;
01451                 newleaf->prevleaf = newleaf->nextleaf = NULL;
01452             }
01453             else
01454             {
01455                 newleaf->prevleaf = tailleaf;
01456                 tailleaf->nextleaf = newleaf;
01457                 tailleaf = newleaf;
01458             }
01459 
01460             return newleaf;
01461         }
01462         else
01463         {
01464             const inner_node *inner = static_cast<const inner_node*>(n);
01465             inner_node *newinner = allocate_inner(inner->level);
01466 
01467             newinner->slotuse = inner->slotuse;
01468             std::copy(inner->slotkey, inner->slotkey + inner->slotuse, newinner->slotkey);
01469 
01470             for (unsigned short slot = 0; slot <= inner->slotuse; ++slot)
01471             {
01472                 newinner->childid[slot] = copy_recursive(inner->childid[slot]);
01473             }
01474 
01475             return newinner;
01476         }
01477     }
01478 
01479 public:
01480     // *** Public Insertion Functions
01481 
01485     inline std::pair<iterator, bool> insert(const pair_type& x)
01486     {
01487         return insert_start(x.first, x.second);
01488     }
01489     
01494     inline std::pair<iterator, bool> insert(const key_type& key, const data_type& data)
01495     {
01496         return insert_start(key, data);
01497     }
01498 
01503     inline std::pair<iterator, bool> insert2(const key_type& key, const data_type& data)
01504     {
01505         return insert_start(key, data);
01506     }
01507 
01510     inline iterator insert(iterator /* hint */, const pair_type &x)
01511     {
01512         return insert_start(x.first, x.second).first;
01513     }
01514 
01517     inline iterator insert2(iterator /* hint */, const key_type& key, const data_type& data)
01518     {
01519         return insert_start(key, data).first;
01520     }
01521 
01524     template <typename InputIterator>
01525     inline void insert(InputIterator first, InputIterator last)
01526     {
01527         InputIterator iter = first;
01528         while(iter != last)
01529         {
01530             insert(*iter);
01531             ++iter;
01532         }
01533     }
01534 
01535 private:
01536     // *** Private Insertion Functions
01537 
01540     std::pair<iterator, bool> insert_start(const key_type& key, const data_type& value)
01541     {
01542         node *newchild = NULL;
01543         key_type newkey = key_type();
01544 
01545         if (!root)
01546         {
01547             root = headleaf = tailleaf = allocate_leaf();
01548         }
01549 
01550         std::pair<iterator, bool> r = insert_descend(root, key, value, &newkey, &newchild);
01551 
01552         if (newchild)
01553         {
01554             inner_node *newroot = allocate_inner(root->level + 1);
01555             newroot->slotkey[0] = newkey;
01556 
01557             newroot->childid[0] = root;
01558             newroot->childid[1] = newchild;
01559 
01560             newroot->slotuse = 1;
01561 
01562             root = newroot;
01563         }
01564 
01565         // increment itemcount if the item was inserted
01566         if (r.second) ++stats.itemcount;
01567 
01568         if (debug)
01569             print();
01570 
01571         if (selfverify) {
01572             verify();
01573             BTREE_ASSERT(exists(key));
01574         }
01575 
01576         return r;
01577     }
01578 
01586     std::pair<iterator, bool> insert_descend(node* n,
01587                                              const key_type& key, const data_type& value,
01588                                              key_type* splitkey, node** splitnode)
01589     {
01590         if (!n->isleafnode())
01591         {
01592             inner_node *inner = static_cast<inner_node*>(n);
01593 
01594             key_type newkey = key_type();
01595             node *newchild = NULL;
01596 
01597             int slot = find_lower(inner, key);
01598 
01599             BTREE_PRINT("btree::insert_descend into " << inner->childid[slot] << std::endl);
01600 
01601             std::pair<iterator, bool> r = insert_descend(inner->childid[slot],
01602                                                          key, value, &newkey, &newchild);
01603 
01604             if (newchild)
01605             {
01606                 BTREE_PRINT("btree::insert_descend newchild with key " << newkey << " node " << newchild << " at slot " << slot << std::endl);
01607 
01608                 if (inner->isfull())
01609                 {
01610                     split_inner_node(inner, splitkey, splitnode, slot);
01611 
01612                     BTREE_PRINT("btree::insert_descend done split_inner: putslot: " << slot << " putkey: " << newkey << " upkey: " << *splitkey << std::endl);
01613 
01614                     if (debug)
01615                     {
01616                         print_node(inner);
01617                         print_node(*splitnode);
01618                     }
01619 
01620                     // check if insert slot is in the split sibling node
01621                     BTREE_PRINT("btree::insert_descend switch: " << slot << " > " << inner->slotuse+1 << std::endl);
01622 
01623                     if (slot == inner->slotuse+1 && inner->slotuse < (*splitnode)->slotuse)
01624                     {
01625                         // special case when the insert slot matches the split
01626                         // place between the two nodes, then the insert key
01627                         // becomes the split key.
01628 
01629                         BTREE_ASSERT(inner->slotuse + 1 < innerslotmax);
01630 
01631                         inner_node *splitinner = static_cast<inner_node*>(*splitnode);
01632 
01633                         // move the split key and it's datum into the left node
01634                         inner->slotkey[inner->slotuse] = *splitkey;
01635                         inner->childid[inner->slotuse+1] = splitinner->childid[0];
01636                         inner->slotuse++;
01637 
01638                         // set new split key and move corresponding datum into right node
01639                         splitinner->childid[0] = newchild;
01640                         *splitkey = newkey;
01641 
01642                         return r;
01643                     }
01644                     else if (slot >= inner->slotuse+1)
01645                     {
01646                         // in case the insert slot is in the newly create split
01647                         // node, we reuse the code below.
01648 
01649                         slot -= inner->slotuse+1;
01650                         inner = static_cast<inner_node*>(*splitnode);
01651                         BTREE_PRINT("btree::insert_descend switching to splitted node " << inner << " slot " << slot <<std::endl);
01652                     }
01653                 }
01654 
01655                 // put pointer to child node into correct slot
01656                 BTREE_ASSERT(slot >= 0 && slot <= inner->slotuse);
01657 
01658                 int i = inner->slotuse;
01659 
01660                 while(i > slot) {
01661                     inner->slotkey[i] = inner->slotkey[i - 1];
01662                     inner->childid[i + 1] = inner->childid[i];
01663                     i--;
01664                 }
01665 
01666                 inner->slotkey[slot] = newkey;
01667                 inner->childid[slot + 1] = newchild;
01668                 inner->slotuse++;
01669             }
01670             
01671             return r;
01672         }
01673         else // n->isleafnode() == true
01674         {
01675             leaf_node *leaf = static_cast<leaf_node*>(n);
01676 
01677             int slot = find_lower(leaf, key);
01678 
01679             if (!allow_duplicates && slot < leaf->slotuse && key_equal(key, leaf->slotkey[slot])) {
01680                 return std::pair<iterator, bool>(iterator(leaf, slot), false);
01681             }
01682 
01683             if (leaf->isfull())
01684             {
01685                 split_leaf_node(leaf, splitkey, splitnode);
01686 
01687                 // check if insert slot is in the split sibling node
01688                 if (slot >= leaf->slotuse)
01689                 {
01690                     slot -= leaf->slotuse;
01691                     leaf = static_cast<leaf_node*>(*splitnode);
01692                 }
01693             }
01694 
01695             // put data item into correct data slot
01696 
01697             int i = leaf->slotuse - 1;
01698             BTREE_ASSERT(i + 1 < leafslotmax);
01699 
01700             while(i >= 0 && key_less(key, leaf->slotkey[i])) {
01701                 leaf->slotkey[i + 1] = leaf->slotkey[i];
01702                 leaf->slotdata[i + 1] = leaf->slotdata[i];
01703                 i--;
01704             }
01705             
01706             leaf->slotkey[i + 1] = key;
01707             leaf->slotdata[i + 1] = value;
01708             leaf->slotuse++;
01709 
01710             if (splitnode && leaf != *splitnode && slot == leaf->slotuse-1)
01711             {
01712                 // special case: the node was split, and the insert is at the
01713                 // last slot of the old node. then the splitkey must be
01714                 // updated.
01715                 *splitkey = key;
01716             }
01717 
01718             return std::pair<iterator, bool>(iterator(leaf, i + 1), true);
01719         }
01720     }
01721 
01724     void split_leaf_node(leaf_node* leaf, key_type* _newkey, node** _newleaf)
01725     {
01726         BTREE_ASSERT(leaf->isfull());
01727 
01728         unsigned int mid = leaf->slotuse / 2;
01729 
01730         BTREE_PRINT("btree::split_leaf_node on " << leaf << std::endl);
01731 
01732         leaf_node *newleaf = allocate_leaf();
01733 
01734         newleaf->slotuse = leaf->slotuse - mid;
01735 
01736         newleaf->nextleaf = leaf->nextleaf;
01737         if (newleaf->nextleaf == NULL) {
01738             BTREE_ASSERT(leaf == tailleaf);
01739             tailleaf = newleaf;
01740         }
01741         else {
01742             newleaf->nextleaf->prevleaf = newleaf;
01743         }
01744 
01745         for(unsigned int slot = mid; slot < leaf->slotuse; ++slot)
01746         {
01747             unsigned int ni = slot - mid;
01748             newleaf->slotkey[ni] = leaf->slotkey[slot];
01749             newleaf->slotdata[ni] = leaf->slotdata[slot];
01750         }
01751             
01752         leaf->slotuse = mid;
01753         leaf->nextleaf = newleaf;
01754         newleaf->prevleaf = leaf;
01755 
01756         *_newkey = leaf->slotkey[leaf->slotuse-1];
01757         *_newleaf = newleaf;
01758     }
01759 
01764     void split_inner_node(inner_node* inner, key_type* _newkey, node** _newinner, unsigned int addslot)
01765     {
01766         BTREE_ASSERT(inner->isfull());
01767 
01768         unsigned int mid = inner->slotuse / 2;
01769 
01770         BTREE_PRINT("btree::split_inner: mid " << mid << " addslot " << addslot << std::endl);
01771 
01772         // if the split is uneven and the overflowing item will be put into the
01773         // larger node, then the smaller split node may underflow
01774         if (addslot <= mid && mid > inner->slotuse - (mid + 1))
01775             mid--;
01776 
01777         BTREE_PRINT("btree::split_inner: mid " << mid << " addslot " << addslot << std::endl);
01778 
01779         BTREE_PRINT("btree::split_inner_node on " << inner << " into two nodes " << mid << " and " << inner->slotuse - (mid + 1) << " sized" << std::endl);
01780 
01781         inner_node *newinner = allocate_inner(inner->level);
01782 
01783         newinner->slotuse = inner->slotuse - (mid + 1);
01784 
01785         for(unsigned int slot = mid + 1; slot < inner->slotuse; ++slot)
01786         {
01787             unsigned int ni = slot - (mid + 1);
01788             newinner->slotkey[ni] = inner->slotkey[slot];
01789             newinner->childid[ni] = inner->childid[slot];
01790         }
01791         newinner->childid[newinner->slotuse] = inner->childid[inner->slotuse];
01792             
01793         inner->slotuse = mid;
01794 
01795         *_newkey = inner->slotkey[mid];
01796         *_newinner = newinner;
01797     }
01798 
01799 private:
01800     // *** Support Class Encapsulating Deletion Results
01801 
01803     enum result_flags_t
01804     {
01806         btree_ok = 0,
01807 
01809         btree_not_found = 1,
01810 
01813         btree_update_lastkey = 2,
01814 
01817         btree_fixmerge = 4
01818     };
01819 
01822     struct result_t
01823     {
01825         result_flags_t  flags;
01826 
01828         key_type        lastkey;
01829 
01832         inline result_t(result_flags_t f = btree_ok)
01833             : flags(f), lastkey()
01834         { }
01835 
01837         inline result_t(result_flags_t f, const key_type &k)
01838             : flags(f), lastkey(k)
01839         { }
01840 
01842         inline bool has(result_flags_t f) const
01843         {
01844             return (flags & f);
01845         }
01846 
01848         inline result_t& operator|= (const result_t &other)
01849         {
01850             flags = result_flags_t(flags | other.flags);
01851 
01852             // we overwrite existing lastkeys on purpose
01853             if (other.has(btree_update_lastkey))
01854                 lastkey = other.lastkey;
01855 
01856             return *this;
01857         }
01858     };
01859 
01860 public:
01861     // *** Public Erase Functions
01862 
01865     bool erase_one(const key_type &key)
01866     {
01867         BTREE_PRINT("btree::erase_one(" << key << ") on btree size " << size() << std::endl);
01868 
01869         if (selfverify) verify();
01870         
01871         result_t result = erase_one_descend(key, root, NULL, NULL, NULL, NULL, NULL, 0);
01872 
01873         if (!result.has(btree_not_found))
01874             --stats.itemcount;
01875 
01876         if (debug) print();
01877         if (selfverify) verify();
01878 
01879         return !result.has(btree_not_found);
01880     }
01881 
01884     size_type erase(const key_type &key)
01885     {
01886         size_type c = 0;
01887 
01888         while( erase_one(key) )
01889         {
01890             ++c;
01891             if (!allow_duplicates) break;
01892         }
01893 
01894         return c;
01895     }
01896 
01897 #ifdef BTREE_TODO
01899     void erase(iterator iter)
01900     {
01901 
01902     }
01903 #endif
01904 
01905 #ifdef BTREE_TODO
01908     void erase(iterator /* first */, iterator /* last */)
01909     {
01910         abort();
01911     }
01912 #endif
01913 
01914 private:
01915     // *** Private Erase Functions
01916 
01926     result_t erase_one_descend(const key_type& key,
01927                                node *curr,
01928                                node *left, node *right,
01929                                inner_node *leftparent, inner_node *rightparent,
01930                                inner_node *parent, unsigned int parentslot)
01931     {
01932         if (curr->isleafnode())
01933         {
01934             leaf_node *leaf = static_cast<leaf_node*>(curr);
01935             leaf_node *leftleaf = static_cast<leaf_node*>(left);
01936             leaf_node *rightleaf = static_cast<leaf_node*>(right);
01937 
01938             int slot = find_lower(leaf, key);
01939 
01940             if (!key_equal(key, leaf->slotkey[slot]))
01941             {
01942                 BTREE_PRINT("Could not find key " << key << " to erase." << std::endl);
01943 
01944                 return btree_not_found;
01945             }
01946 
01947             BTREE_PRINT("Found key in leaf " << curr << " at slot " << slot << std::endl);
01948 
01949             for (int i = slot; i < leaf->slotuse - 1; i++)
01950             {
01951                 leaf->slotkey[i] = leaf->slotkey[i + 1];
01952                 leaf->slotdata[i] = leaf->slotdata[i + 1];
01953             }
01954             leaf->slotuse--;
01955 
01956             result_t myres = btree_ok;
01957 
01958             // if the last key of the leaf was changed, the parent is notified
01959             // and updates the key of this leaf
01960             if (slot == leaf->slotuse)
01961             {
01962                 if (parent && parentslot < parent->slotuse)
01963                 {
01964                     BTREE_ASSERT(parent->childid[parentslot] == curr);
01965                     parent->slotkey[parentslot] = leaf->slotkey[leaf->slotuse - 1];
01966                 }
01967                 else
01968                 {
01969                     BTREE_PRINT("Scheduling lastkeyupdate: key " << leaf->slotkey[leaf->slotuse - 1] << std::endl);
01970                     myres |= result_t(btree_update_lastkey, leaf->slotkey[leaf->slotuse - 1]);
01971                 }
01972             }
01973 
01974             if (leaf->isunderflow() && !(leaf == root && leaf->slotuse >= 1))
01975             {
01976                 // determine what to do about the underflow
01977 
01978                 // case : if this empty leaf is the root, there is no way to
01979                 // correct underflow
01980                 if (leftleaf == NULL && rightleaf == NULL)
01981                 {
01982                     return btree_ok;
01983                 }
01984                 // case : if both left and right leaves would underflow in case of
01985                 // a shift, then merging is necessary. choose the more local merger
01986                 // with our parent
01987                 else if ( (leftleaf == NULL || leftleaf->isfew()) && (rightleaf == NULL || rightleaf->isfew()) )
01988                 {
01989                     if (leftparent == parent)
01990                         myres |= merge_leaves(leftleaf, leaf, leftparent);
01991                     else
01992                         myres |= merge_leaves(leaf, rightleaf, rightparent);
01993                 }
01994                 // case : the right leaf has extra data, so balance right with current
01995                 else if ( (leftleaf != NULL && leftleaf->isfew()) && (rightleaf != NULL && !rightleaf->isfew()) )
01996                 {
01997                     if (rightparent == parent)
01998                         myres |= shift_left_leaf(leaf, rightleaf, rightparent, parentslot);
01999                     else
02000                         myres |= merge_leaves(leftleaf, leaf, leftparent);
02001                 }
02002                 // case : the left leaf has extra data, so balance left with current
02003                 else if ( (leftleaf != NULL && !leftleaf->isfew()) && (rightleaf != NULL && rightleaf->isfew()) )
02004                 {
02005                     if (leftparent == parent)
02006                         shift_right_leaf(leftleaf, leaf, leftparent, parentslot - 1);
02007                     else
02008                         myres |= merge_leaves(leaf, rightleaf, rightparent);
02009                 }
02010                 // case : both the leaf and right leaves have extra data and our
02011                 // parent, choose the leaf with more data
02012                 else if (leftparent == rightparent)
02013                 {
02014                     if (leftleaf->slotuse <= rightleaf->slotuse)
02015                         myres |= shift_left_leaf(leaf, rightleaf, rightparent, parentslot);
02016                     else
02017                         shift_right_leaf(leftleaf, leaf, leftparent, parentslot - 1);
02018                 }
02019                 else
02020                 {
02021                     if (leftparent == parent)
02022                         shift_right_leaf(leftleaf, leaf, leftparent, parentslot - 1);
02023                     else
02024                         myres |= shift_left_leaf(leaf, rightleaf, rightparent, parentslot);
02025                 }
02026             }
02027 
02028             return myres;
02029         }
02030         else // !curr->isleafnode()
02031         {
02032             inner_node *inner = static_cast<inner_node*>(curr);
02033             inner_node *leftinner = static_cast<inner_node*>(left);
02034             inner_node *rightinner = static_cast<inner_node*>(right);
02035 
02036             node *myleft, *myright;
02037             inner_node *myleftparent, *myrightparent;
02038 
02039             int slot = find_lower(inner, key);
02040 
02041             if (slot == 0) {
02042                 myleft = (left == NULL) ? NULL : (static_cast<inner_node*>(left))->childid[left->slotuse - 1];
02043                 myleftparent = leftparent;
02044             }
02045             else {
02046                 myleft = inner->childid[slot - 1];
02047                 myleftparent = inner;
02048             }
02049 
02050             if (slot == inner->slotuse) {
02051                 myright = (right == NULL) ? NULL : (static_cast<inner_node*>(right))->childid[0];
02052                 myrightparent = rightparent;
02053             }
02054             else {
02055                 myright = inner->childid[slot + 1];
02056                 myrightparent = inner;
02057             }
02058 
02059             BTREE_PRINT("erase_one_descend into " << inner->childid[slot] << std::endl);
02060 
02061             result_t result = erase_one_descend(key,
02062                                                 inner->childid[slot],
02063                                                 myleft, myright,
02064                                                 myleftparent, myrightparent,
02065                                                 inner, slot);
02066 
02067             result_t myres = btree_ok;
02068 
02069             if (result.has(btree_not_found))
02070             {
02071                 return result;
02072             }
02073 
02074             if (result.has(btree_update_lastkey))
02075             {
02076                 if (parent && parentslot < parent->slotuse)
02077                 {
02078                     BTREE_PRINT("Fixing lastkeyupdate: key " << result.lastkey << " into parent " << parent << " at parentslot " << parentslot << std::endl);
02079 
02080                     BTREE_ASSERT(parent->childid[parentslot] == curr);
02081                     parent->slotkey[parentslot] = result.lastkey;
02082                 }
02083                 else
02084                 {
02085                     BTREE_PRINT("Forwarding lastkeyupdate: key " << result.lastkey << std::endl);
02086                     myres |= result_t(btree_update_lastkey, result.lastkey);
02087                 }
02088             }
02089 
02090             if (result.has(btree_fixmerge))
02091             {
02092                 // either the current node or the next is empty and should be removed
02093                 if (inner->childid[slot]->slotuse != 0)
02094                     slot++;
02095 
02096                 // this is the child slot invalidated by the merge
02097                 BTREE_ASSERT(inner->childid[slot]->slotuse == 0);
02098 
02099                 free_node(inner->childid[slot]);
02100 
02101                 for(int i = slot; i < inner->slotuse; i++)
02102                 {
02103                     inner->slotkey[i - 1] = inner->slotkey[i];
02104                     inner->childid[i] = inner->childid[i + 1];
02105                 }
02106                 inner->slotuse--;
02107 
02108                 if (inner->level == 1)
02109                 {
02110                     // fix split key for children leaves
02111                     slot--;
02112                     leaf_node *child = static_cast<leaf_node*>(inner->childid[slot]);
02113                     inner->slotkey[slot] = child->slotkey[ child->slotuse-1 ];
02114                 }
02115             }
02116 
02117             if (inner->isunderflow() && !(inner == root && inner->slotuse >= 1))
02118             {
02119                 // case: the inner node is the root and has just one child. that child becomes the new root
02120                 if (leftinner == NULL && rightinner == NULL)
02121                 {
02122                     BTREE_ASSERT(inner == root);
02123                     BTREE_ASSERT(inner->slotuse == 0);
02124 
02125                     root = inner->childid[0];
02126 
02127                     inner->slotuse = 0;
02128                     free_node(inner);
02129 
02130                     return btree_ok;
02131                 }
02132                 // case : if both left and right leaves would underflow in case of
02133                 // a shift, then merging is necessary. choose the more local merger
02134                 // with our parent
02135                 else if ( (leftinner == NULL || leftinner->isfew()) && (rightinner == NULL || rightinner->isfew()) )
02136                 {
02137                     if (leftparent == parent)
02138                         myres |= merge_inner(leftinner, inner, leftparent, parentslot - 1);
02139                     else
02140                         myres |= merge_inner(inner, rightinner, rightparent, parentslot);
02141                 }
02142                 // case : the right leaf has extra data, so balance right with current
02143                 else if ( (leftinner != NULL && leftinner->isfew()) && (rightinner != NULL && !rightinner->isfew()) )
02144                 {
02145                     if (rightparent == parent)
02146                         shift_left_inner(inner, rightinner, rightparent, parentslot);
02147                     else
02148                         myres |= merge_inner(leftinner, inner, leftparent, parentslot - 1);
02149                 }
02150                 // case : the left leaf has extra data, so balance left with current
02151                 else if ( (leftinner != NULL && !leftinner->isfew()) && (rightinner != NULL && rightinner->isfew()) )
02152                 {
02153                     if (leftparent == parent)
02154                         shift_right_inner(leftinner, inner, leftparent, parentslot - 1);
02155                     else
02156                         myres |= merge_inner(inner, rightinner, rightparent, parentslot);
02157                 }
02158                 // case : both the leaf and right leaves have extra data and our
02159                 // parent, choose the leaf with more data
02160                 else if (leftparent == rightparent)
02161                 {
02162                     if (leftinner->slotuse <= rightinner->slotuse)
02163                         shift_left_inner(inner, rightinner, rightparent, parentslot);
02164                     else
02165                         shift_right_inner(leftinner, inner, leftparent, parentslot - 1);
02166                 }
02167                 else
02168                 {
02169                     if (leftparent == parent)
02170                         shift_right_inner(leftinner, inner, leftparent, parentslot - 1);
02171                     else
02172                         shift_left_inner(inner, rightinner, rightparent, parentslot);
02173                 }
02174             }
02175 
02176             return myres;
02177         }
02178     }
02179 
02183     result_t merge_leaves(leaf_node* left, leaf_node* right, inner_node* parent)
02184     {
02185         BTREE_PRINT("Merge leaf nodes " << left << " and " << right << " with common parent " << parent << "." << std::endl);
02186         (void)parent;
02187 
02188         BTREE_ASSERT(left->isleafnode() && right->isleafnode());
02189         BTREE_ASSERT(parent->level == 1);
02190 
02191         BTREE_ASSERT(left->slotuse + right->slotuse < leafslotmax);
02192 
02193         for (unsigned int i = 0; i < right->slotuse; i++)
02194         {
02195             left->slotkey[left->slotuse + i] = right->slotkey[i];
02196             left->slotdata[left->slotuse + i] = right->slotdata[i];
02197         }
02198         left->slotuse += right->slotuse;
02199 
02200         left->nextleaf = right->nextleaf;
02201         if (left->nextleaf)
02202             left->nextleaf->prevleaf = left;
02203         else
02204             tailleaf = left;
02205 
02206         right->slotuse = 0;
02207 
02208         return btree_fixmerge;
02209     }
02210 
02214     static result_t merge_inner(inner_node* left, inner_node* right, inner_node* parent, unsigned int parentslot)
02215     {
02216         BTREE_PRINT("Merge inner nodes " << left << " and " << right << " with common parent " << parent << "." << std::endl);
02217 
02218         BTREE_ASSERT(left->level == right->level);
02219         BTREE_ASSERT(parent->level == left->level + 1);
02220 
02221         BTREE_ASSERT(parent->childid[parentslot] == left);
02222 
02223         BTREE_ASSERT(left->slotuse + right->slotuse < innerslotmax);
02224 
02225         if (selfverify)
02226         {
02227             // find the left node's slot in the parent's children
02228             unsigned int leftslot = 0;
02229             while(leftslot <= parent->slotuse && parent->childid[leftslot] != left)
02230                 ++leftslot;
02231 
02232             BTREE_ASSERT(leftslot < parent->slotuse);
02233             BTREE_ASSERT(parent->childid[leftslot] == left);
02234             BTREE_ASSERT(parent->childid[leftslot+1] == right);
02235 
02236             BTREE_ASSERT(parentslot == leftslot);
02237         }
02238 
02239         // retrieve the decision key from parent
02240         left->slotkey[left->slotuse] = parent->slotkey[parentslot];
02241         left->slotuse++;
02242 
02243         // copy over keys and children from right
02244         for (unsigned int i = 0; i < right->slotuse; i++)
02245         {
02246             left->slotkey[left->slotuse + i] = right->slotkey[i];
02247             left->childid[left->slotuse + i] = right->childid[i];
02248         }
02249         left->slotuse += right->slotuse;
02250 
02251         left->childid[left->slotuse] = right->childid[right->slotuse];
02252 
02253         right->slotuse = 0;
02254 
02255         return btree_fixmerge;
02256     }
02257 
02261     static result_t shift_left_leaf(leaf_node *left, leaf_node *right, inner_node *parent, unsigned int parentslot)
02262     {
02263         BTREE_ASSERT(left->isleafnode() && right->isleafnode());
02264         BTREE_ASSERT(parent->level == 1);
02265 
02266         BTREE_ASSERT(left->nextleaf == right);
02267         BTREE_ASSERT(left == right->prevleaf);
02268 
02269         BTREE_ASSERT(left->slotuse < right->slotuse);
02270         BTREE_ASSERT(parent->childid[parentslot] == left);
02271 
02272         unsigned int shiftnum = (right->slotuse - left->slotuse) / 2;
02273 
02274         BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to left " << left << " from right " << right << " with common parent " << parent << "." << std::endl);
02275 
02276         BTREE_ASSERT(left->slotuse + shiftnum < leafslotmax);
02277 
02278         // copy the first items from the right node to the last slot in the left node.
02279         for(unsigned int i = 0; i < shiftnum; i++)
02280         {
02281             left->slotkey[left->slotuse + i] = right->slotkey[i];
02282             left->slotdata[left->slotuse + i] = right->slotdata[i];
02283         }
02284         left->slotuse += shiftnum;
02285         
02286         // shift all slots in the right node to the left
02287     
02288         right->slotuse -= shiftnum;
02289         for(int i = 0; i < right->slotuse; i++)
02290         {
02291             right->slotkey[i] = right->slotkey[i + shiftnum];
02292             right->slotdata[i] = right->slotdata[i + shiftnum];
02293         }
02294 
02295         // fixup parent
02296         if (parentslot < parent->slotuse) {
02297             parent->slotkey[parentslot] = left->slotkey[left->slotuse - 1];
02298             return btree_ok;
02299         }
02300         else { // the update is further up the tree
02301             return result_t(btree_update_lastkey, left->slotkey[left->slotuse - 1]);
02302         }
02303     }
02304 
02308     static void shift_left_inner(inner_node *left, inner_node *right, inner_node *parent, unsigned int parentslot)
02309     {
02310         BTREE_ASSERT(left->level == right->level);
02311         BTREE_ASSERT(parent->level == left->level + 1);
02312 
02313         BTREE_ASSERT(left->slotuse < right->slotuse);
02314         BTREE_ASSERT(parent->childid[parentslot] == left);
02315 
02316         unsigned int shiftnum = (right->slotuse - left->slotuse) / 2;
02317 
02318         BTREE_PRINT("Shifting (inner) " << shiftnum << " entries to left " << left << " from right " << right << " with common parent " << parent << "." << std::endl);
02319 
02320         BTREE_ASSERT(left->slotuse + shiftnum < innerslotmax);
02321 
02322         if (selfverify)
02323         {
02324             // find the left node's slot in the parent's children and compare to parentslot
02325 
02326             unsigned int leftslot = 0;
02327             while(leftslot <= parent->slotuse && parent->childid[leftslot] != left)
02328                 ++leftslot;
02329 
02330             BTREE_ASSERT(leftslot < parent->slotuse);
02331             BTREE_ASSERT(parent->childid[leftslot] == left);
02332             BTREE_ASSERT(parent->childid[leftslot+1] == right);
02333 
02334             BTREE_ASSERT(leftslot == parentslot);
02335         }
02336 
02337         // copy the parent's decision slotkey and childid to the first new key on the left
02338         left->slotkey[left->slotuse] = parent->slotkey[parentslot];
02339         left->slotuse++;
02340 
02341         // copy the other items from the right node to the last slots in the left node.
02342         for(unsigned int i = 0; i < shiftnum - 1; i++)
02343         {
02344             left->slotkey[left->slotuse + i] = right->slotkey[i];
02345             left->childid[left->slotuse + i] = right->childid[i];
02346         }
02347         left->slotuse += shiftnum - 1;
02348 
02349         // fixup parent
02350         parent->slotkey[parentslot] = right->slotkey[shiftnum - 1];
02351         // last pointer in left
02352         left->childid[left->slotuse] = right->childid[shiftnum - 1];
02353         
02354         // shift all slots in the right node
02355     
02356         right->slotuse -= shiftnum;
02357         for(int i = 0; i < right->slotuse; i++)
02358         {
02359             right->slotkey[i] = right->slotkey[i + shiftnum];
02360             right->childid[i] = right->childid[i + shiftnum];
02361         }
02362         right->childid[right->slotuse] = right->childid[right->slotuse + shiftnum];
02363     }
02364 
02368     static void shift_right_leaf(leaf_node *left, leaf_node *right, inner_node *parent, unsigned int parentslot)
02369     {
02370         BTREE_ASSERT(left->isleafnode() && right->isleafnode());
02371         BTREE_ASSERT(parent->level == 1);
02372 
02373         BTREE_ASSERT(left->nextleaf == right);
02374         BTREE_ASSERT(left == right->prevleaf);
02375         BTREE_ASSERT(parent->childid[parentslot] == left);
02376 
02377         BTREE_ASSERT(left->slotuse > right->slotuse);
02378 
02379         unsigned int shiftnum = (left->slotuse - right->slotuse) / 2;
02380 
02381         BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to right " << right << " from left " << left << " with common parent " << parent << "." << std::endl);
02382 
02383         if (selfverify)
02384         {
02385             // find the left node's slot in the parent's children
02386             unsigned int leftslot = 0;
02387             while(leftslot <= parent->slotuse && parent->childid[leftslot] != left)
02388                 ++leftslot;
02389 
02390             BTREE_ASSERT(leftslot < parent->slotuse);
02391             BTREE_ASSERT(parent->childid[leftslot] == left);
02392             BTREE_ASSERT(parent->childid[leftslot+1] == right);
02393 
02394             BTREE_ASSERT(leftslot == parentslot);
02395         }
02396 
02397         // shift all slots in the right node
02398     
02399         BTREE_ASSERT(right->slotuse + shiftnum < leafslotmax);
02400 
02401         for(int i = right->slotuse; i >= 0; i--)
02402         {
02403             right->slotkey[i + shiftnum] = right->slotkey[i];
02404             right->slotdata[i + shiftnum] = right->slotdata[i];
02405         }
02406         right->slotuse += shiftnum;
02407 
02408         // copy the last items from the left node to the first slot in the right node.
02409         for(unsigned int i = 0; i < shiftnum; i++)
02410         {
02411             right->slotkey[i] = left->slotkey[left->slotuse - shiftnum + i];
02412             right->slotdata[i] = left->slotdata[left->slotuse - shiftnum + i];
02413         }
02414         left->slotuse -= shiftnum;
02415 
02416         parent->slotkey[parentslot] = left->slotkey[left->slotuse-1];
02417     }
02418 
02422     static void shift_right_inner(inner_node *left, inner_node *right, inner_node *parent, unsigned int parentslot)
02423     {
02424         BTREE_ASSERT(left->level == right->level);
02425         BTREE_ASSERT(parent->level == left->level + 1);
02426 
02427         BTREE_ASSERT(left->slotuse > right->slotuse);
02428         BTREE_ASSERT(parent->childid[parentslot] == left);
02429 
02430         unsigned int shiftnum = (left->slotuse - right->slotuse) / 2;
02431 
02432         BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to right " << right << " from left " << left << " with common parent " << parent << "." << std::endl);
02433 
02434         if (selfverify)
02435         {
02436             // find the left node's slot in the parent's children
02437             unsigned int leftslot = 0;
02438             while(leftslot <= parent->slotuse && parent->childid[leftslot] != left)
02439                 ++leftslot;
02440 
02441             BTREE_ASSERT(leftslot < parent->slotuse);
02442             BTREE_ASSERT(parent->childid[leftslot] == left);
02443             BTREE_ASSERT(parent->childid[leftslot+1] == right);
02444 
02445             BTREE_ASSERT(leftslot == parentslot);
02446         }
02447 
02448         // shift all slots in the right node
02449 
02450         BTREE_ASSERT(right->slotuse + shiftnum < innerslotmax);
02451     
02452         right->childid[right->slotuse + shiftnum] = right->childid[right->slotuse];
02453         for(int i = right->slotuse-1; i >= 0; i--)
02454         {
02455             right->slotkey[i + shiftnum] = right->slotkey[i];
02456             right->childid[i + shiftnum] = right->childid[i];
02457         }
02458 
02459         right->slotuse += shiftnum;
02460 
02461         // copy the parent's decision slotkey and childid to the last new key on the right
02462         right->slotkey[shiftnum - 1] = parent->slotkey[parentslot];
02463         right->childid[shiftnum - 1] = left->childid[left->slotuse];
02464 
02465         // copy the remaining last items from the left node to the first slot in the right node.
02466         for(unsigned int i = 0; i < shiftnum - 1; i++)
02467         {
02468             right->slotkey[i] = left->slotkey[left->slotuse - shiftnum + i + 1];
02469             right->childid[i] = left->childid[left->slotuse - shiftnum + i + 1];
02470         }
02471 
02472         // copy the first to-be-removed key from the left node to the parent's decision slot
02473         parent->slotkey[parentslot] = left->slotkey[left->slotuse - shiftnum];
02474 
02475         left->slotuse -= shiftnum;
02476     }
02477 
02478 public:
02479     // *** Debug Printing
02480 
02484     void print() const
02485     {
02486         print_node(root, 0, true);
02487     }
02488 
02490     void print_leaves() const
02491     {
02492         BTREE_PRINT("leaves:" << std::endl);
02493 
02494         const leaf_node *n = headleaf;
02495 
02496         while(n)
02497         {
02498             BTREE_PRINT("  " << n << std::endl);
02499 
02500             n = n->nextleaf;
02501         }
02502     }
02503 
02504 private:
02505 
02507     static void print_node(const node* node, unsigned int depth=0, bool recursive=false)
02508     {
02509         for(unsigned int i = 0; i < depth; i++) BTREE_PRINT("  ");
02510             
02511         BTREE_PRINT("node " << node << " level " << node->level << " slotuse " << node->slotuse << std::endl);
02512 
02513         if (node->isleafnode())
02514         {
02515             const leaf_node *leafnode = static_cast<const leaf_node*>(node);
02516 
02517             for(unsigned int i = 0; i < depth; i++) BTREE_PRINT("  ");
02518             BTREE_PRINT("  leaf prev " << leafnode->prevleaf << " next " << leafnode->nextleaf << std::endl);
02519 
02520             for(unsigned int i = 0; i < depth; i++) BTREE_PRINT("  ");
02521 
02522             for (unsigned int slot = 0; slot < leafnode->slotuse; ++slot)
02523             {
02524                 BTREE_PRINT(leafnode->slotkey[slot] << "  "); // << "(data: " << leafnode->slotdata[slot] << ") ";
02525             }
02526             BTREE_PRINT(std::endl);
02527         }
02528         else
02529         {
02530             const inner_node *innernode = static_cast<const inner_node*>(node);
02531 
02532             for(unsigned int i = 0; i < depth; i++) BTREE_PRINT("  ");
02533 
02534             for (unsigned short slot = 0; slot < innernode->slotuse; ++slot)
02535             {
02536                 BTREE_PRINT("(" << innernode->childid[slot] << ") " << innernode->slotkey[slot] << " ");
02537             }
02538             BTREE_PRINT("(" << innernode->childid[innernode->slotuse] << ")");
02539             BTREE_PRINT(std::endl);
02540 
02541             if (recursive)
02542             {
02543                 for (unsigned short slot = 0; slot < innernode->slotuse + 1; ++slot)
02544                 {
02545                     print_node(innernode->childid[slot], depth + 1, recursive);
02546                 }
02547             }
02548         }
02549     }
02550 
02551 public:
02552     // *** Verification of B+ Tree Invariants
02553 
02556     void verify() const
02557     {
02558         key_type minkey, maxkey;
02559         tree_stats vstats;
02560         
02561         if (root)
02562         {
02563             verify_node(root, &minkey, &maxkey, vstats);
02564 
02565             assert( vstats.itemcount == stats.itemcount );
02566             assert( vstats.leaves == stats.leaves );
02567             assert( vstats.innernodes == stats.innernodes );
02568         }
02569 
02570         verify_leaflinks();
02571     }
02572 
02573 private:
02574 
02576     void verify_node(const node* n, key_type* minkey, key_type* maxkey, tree_stats &vstats) const
02577     {
02578         BTREE_PRINT("verifynode " << n << std::endl);
02579 
02580         if (n->isleafnode())
02581         {
02582             const leaf_node *leaf = static_cast<const leaf_node*>(n);
02583 
02584             assert(leaf == root || !leaf->isunderflow());
02585 
02586             for(unsigned short slot = 0; slot < leaf->slotuse - 1; ++slot)
02587             {
02588                 assert(key_lessequal(leaf->slotkey[slot], leaf->slotkey[slot + 1]));
02589             }
02590 
02591             *minkey = leaf->slotkey[0];
02592             *maxkey = leaf->slotkey[leaf->slotuse - 1];
02593 
02594             vstats.leaves++;
02595             vstats.itemcount += leaf->slotuse;
02596         }
02597         else // !n->isleafnode()
02598         {
02599             const inner_node *inner = static_cast<const inner_node*>(n);
02600             vstats.innernodes++;
02601 
02602             assert(inner == root || !inner->isunderflow());
02603 
02604             for(unsigned short slot = 0; slot < inner->slotuse - 1; ++slot)
02605             {
02606                 assert(key_lessequal(inner->slotkey[slot], inner->slotkey[slot + 1]));
02607             }
02608 
02609             for(unsigned short slot = 0; slot <= inner->slotuse; ++slot)
02610             {
02611                 const node *subnode = inner->childid[slot];
02612                 key_type subminkey = key_type();
02613                 key_type submaxkey = key_type();
02614 
02615                 assert(subnode->level + 1 == inner->level);
02616                 verify_node(subnode, &subminkey, &submaxkey, vstats);
02617 
02618                 BTREE_PRINT("verify subnode " << subnode << ": " << subminkey << " - " << submaxkey << std::endl);
02619 
02620                 if (slot == 0)
02621                     *minkey = subminkey;
02622                 else
02623                     assert(key_greaterequal(subminkey, inner->slotkey[slot-1]));
02624 
02625                 if (slot == inner->slotuse)
02626                     *maxkey = submaxkey;
02627                 else
02628                     assert(key_equal(inner->slotkey[slot], submaxkey));
02629 
02630                 if (inner->level == 1 && slot < inner->slotuse)
02631                 {
02632                     // children are leaves and must be linked together in the
02633                     // correct order
02634                     const leaf_node *leafa = static_cast<const leaf_node*>(inner->childid[slot]);
02635                     const leaf_node *leafb = static_cast<const leaf_node*>(inner->childid[slot + 1]);
02636 
02637                     assert(leafa->nextleaf == leafb);
02638                     assert(leafa == leafb->prevleaf);
02639                     (void)leafa; (void)leafb;
02640                 }
02641                 if (inner->level == 2 && slot < inner->slotuse)
02642                 {
02643                     // verify leaf links between the adjacent inner nodes
02644                     const inner_node *parenta = static_cast<const inner_node*>(inner->childid[slot]);
02645                     const inner_node *parentb = static_cast<const inner_node*>(inner->childid[slot+1]);
02646 
02647                     const leaf_node *leafa = static_cast<const leaf_node*>(parenta->childid[parenta->slotuse]);
02648                     const leaf_node *leafb = static_cast<const leaf_node*>(parentb->childid[0]);
02649 
02650                     assert(leafa->nextleaf == leafb);
02651                     assert(leafa == leafb->prevleaf);
02652                     (void)leafa; (void)leafb;
02653                 }
02654             }
02655         }
02656     }
02657 
02659     void verify_leaflinks() const
02660     {
02661         const leaf_node *n = headleaf;
02662 
02663         assert(n->level == 0);
02664         assert(!n || n->prevleaf == NULL);
02665 
02666         unsigned int testcount = 0;
02667 
02668         while(n)
02669         {
02670             assert(n->level == 0);
02671 
02672             for(unsigned short slot = 0; slot < n->slotuse - 1; ++slot)
02673             {
02674                 assert(key_lessequal(n->slotkey[slot], n->slotkey[slot + 1]));
02675             }
02676 
02677             testcount += n->slotuse;
02678 
02679             if (n->nextleaf)
02680             {
02681                 assert(key_lessequal(n->slotkey[n->slotuse-1], n->nextleaf->slotkey[0]));
02682 
02683                 assert(n == n->nextleaf->prevleaf);
02684             }
02685             else
02686             {
02687                 assert(tailleaf == n);
02688             }
02689 
02690             n = n->nextleaf;
02691         }
02692 
02693         assert(testcount == size());
02694     }
02695 
02696 private:
02697     // *** Dump and Restore of B+ Trees
02698 
02702     struct dump_header
02703     {
02705         char            signature[12];
02706 
02708         unsigned short  version;
02709 
02711         unsigned short  key_type_size;
02712 
02714         unsigned short  data_type_size;
02715 
02717         unsigned short  leafslots;
02718 
02720         unsigned short  innerslots;
02721 
02723         bool            allow_duplicates;
02724 
02726         size_type       itemcount;
02727 
02730         inline void fill()
02731         {
02732             // don't want to include string.h just for this signature
02733             *reinterpret_cast<unsigned int*>(signature+0) = 0x2d787473;
02734             *reinterpret_cast<unsigned int*>(signature+4) = 0x65727462;
02735             *reinterpret_cast<unsigned int*>(signature+8) = 0x00000065;
02736 
02737             version = 0;
02738             key_type_size = sizeof(typename btree_self::key_type);
02739             data_type_size = sizeof(typename btree_self::data_type);
02740             leafslots = btree_self::leafslotmax;
02741             innerslots = btree_self::innerslotmax;
02742             allow_duplicates = btree_self::allow_duplicates;
02743         }
02744 
02746         inline bool same(const struct dump_header &o) const
02747         {
02748             return (*reinterpret_cast<const unsigned int*>(signature+0) ==
02749                     *reinterpret_cast<const unsigned int*>(o.signature+0))
02750                 && (*reinterpret_cast<const unsigned int*>(signature+4) ==
02751                     *reinterpret_cast<const unsigned int*>(o.signature+4))
02752                 && (*reinterpret_cast<const unsigned int*>(signature+8) ==
02753                     *reinterpret_cast<const unsigned int*>(o.signature+8))
02754 
02755                 && (version == o.version)
02756                 && (key_type_size == o.key_type_size)
02757                 && (data_type_size == o.data_type_size)
02758                 && (leafslots == o.leafslots)
02759                 && (innerslots == o.innerslots)
02760                 && (allow_duplicates == o.allow_duplicates);
02761         }
02762     };
02763 
02764 public:
02765 
02770     void dump(std::ostream &os) const
02771     {
02772         struct dump_header header;
02773         header.fill();
02774         header.itemcount = size();
02775 
02776         os.write(reinterpret_cast<char*>(&header), sizeof(header));
02777 
02778         if (root)
02779             dump_node(os, root);
02780     }
02781 
02786     bool restore(std::istream &is)
02787     {
02788         struct dump_header fileheader;
02789         is.read(reinterpret_cast<char*>(&fileheader), sizeof(fileheader));
02790         if (!is.good()) return false;
02791 
02792         struct dump_header myheader;
02793         myheader.fill();
02794         myheader.itemcount = fileheader.itemcount;
02795 
02796         if (!myheader.same(fileheader))
02797         {
02798             BTREE_PRINT("btree::restore: file header does not match instantiation signature." << std::endl);
02799             return false;
02800         }
02801 
02802         clear();
02803 
02804         if (fileheader.itemcount > 0)
02805         {
02806             root = restore_node(is);
02807             if (root == NULL) return false;
02808 
02809             stats.itemcount = fileheader.itemcount;
02810         }
02811 
02812         if (debug) print();
02813         if (selfverify) verify();
02814 
02815         return true;
02816     }
02817 
02818 private:
02819 
02821     void dump_node(std::ostream &os, const node* n) const
02822     {
02823         BTREE_PRINT("dump_node " << n << std::endl);
02824 
02825         if (n->isleafnode())
02826         {
02827             const leaf_node *leaf = static_cast<const leaf_node*>(n);
02828 
02829             os.write(reinterpret_cast<const char*>(leaf), sizeof(*leaf));
02830         }
02831         else // !n->isleafnode()
02832         {
02833             const inner_node *inner = static_cast<const inner_node*>(n);
02834 
02835             os.write(reinterpret_cast<const char*>(inner), sizeof(*inner));
02836 
02837             for(unsigned short slot = 0; slot <= inner->slotuse; ++slot)
02838             {
02839                 const node *subnode = inner->childid[slot];
02840                 
02841                 dump_node(os, subnode);
02842             }
02843         }
02844     }
02845 
02848     node* restore_node(std::istream &is)
02849     {
02850         union {
02851             node        top;
02852             leaf_node   leaf;
02853             inner_node  inner;
02854         } nu;
02855 
02856         // first read only the top of the node
02857         is.read(reinterpret_cast<char*>(&nu.top), sizeof(nu.top));
02858         if (!is.good()) return NULL;
02859 
02860         if (nu.top.isleafnode())
02861         {
02862             // read remaining data of leaf node
02863             is.read(reinterpret_cast<char*>(&nu.leaf) + sizeof(nu.top), sizeof(nu.leaf) - sizeof(nu.top));
02864             if (!is.good()) return NULL;
02865             
02866             leaf_node *newleaf = allocate_leaf();
02867 
02868             // copy over all data, the leaf nodes contain only their double linked list pointers
02869             *newleaf = nu.leaf;
02870 
02871             // reconstruct the linked list from the order in the file
02872             if (headleaf == NULL) {
02873                 BTREE_ASSERT(newleaf->prevleaf == NULL);
02874                 headleaf = tailleaf = newleaf;
02875             }
02876             else {
02877                 newleaf->prevleaf = tailleaf;
02878                 tailleaf->nextleaf = newleaf;
02879                 tailleaf = newleaf;
02880             }
02881 
02882             return newleaf;
02883         }
02884         else
02885         {
02886             // read remaining data of inner node
02887             is.read(reinterpret_cast<char*>(&nu.inner) + sizeof(nu.top), sizeof(nu.inner) - sizeof(nu.top));
02888             if (!is.good()) return NULL;
02889 
02890             inner_node *newinner = allocate_inner(0);
02891 
02892             // copy over all data, the inner nodes contain only pointers to their children
02893             *newinner = nu.inner;
02894 
02895             for(unsigned short slot = 0; slot <= newinner->slotuse; ++slot)
02896             {
02897                 newinner->childid[slot] = restore_node(is);
02898             }
02899 
02900             return newinner;
02901         }
02902     }
02903 };
02904 
02905 } // namespace stx
02906 
02907 #endif // _STX_BTREE_H_

Generated on Fri Apr 27 14:49:56 2007 for STX B+ Tree Template Classes by  doxygen 1.5.2