stx/btree.h

Go to the documentation of this file.
00001 // $Id: btree.h 59 2007-05-13 11:08:30Z tb $
00006 /*
00007  * STX B+ Tree Template Classes v0.8
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 <algorithm>
00031 #include <functional>
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 
00061 #ifndef BTREE_FRIENDS
00065 #define BTREE_FRIENDS           friend class btree_friend;
00066 #endif
00067 
00069 namespace stx {
00070 
00073 template <typename _Key>
00074 struct btree_default_set_traits
00075 {
00078     static const bool   selfverify = false;
00079 
00084     static const bool   debug = false;
00085 
00088     static const int    leafslots = BTREE_MAX( 8, 256 / (sizeof(_Key)) );
00089 
00092     static const int    innerslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(void*)) );
00093 };
00094 
00097 template <typename _Key, typename _Data>
00098 struct btree_default_map_traits
00099 {
00102     static const bool   selfverify = false;
00103 
00108     static const bool   debug = false;
00109 
00112     static const int    leafslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(_Data)) );
00113 
00116     static const int    innerslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(void*)) );
00117 };
00118 
00132 template <typename _Key, typename _Data,
00133           typename _Value = std::pair<_Key, _Data>,
00134           typename _Compare = std::less<_Key>,
00135           typename _Traits = btree_default_map_traits<_Key, _Data>,
00136           bool _Duplicates = false>
00137 class btree
00138 {
00139 public:
00140     // *** Template Parameter Types
00141 
00144     typedef _Key                        key_type;
00145 
00148     typedef _Data                       data_type;
00149 
00154     typedef _Value                      value_type;
00155 
00157     typedef _Compare                    key_compare;
00158 
00161     typedef _Traits                     traits;
00162 
00165     static const bool                   allow_duplicates = _Duplicates;
00166 
00167     // The macro BTREE_FRIENDS can be used by outside class to access the B+
00168     // tree internals. This was added for wxBTreeDemo to be able to draw the
00169     // tree.
00170     BTREE_FRIENDS
00171 
00172 public:
00173     // *** Constructed Types
00174 
00176     typedef btree<key_type, data_type, value_type,
00177                   key_compare, traits, allow_duplicates>        btree_self;
00178 
00180     typedef size_t                              size_type;
00181 
00183     typedef std::pair<key_type, data_type>      pair_type;
00184 
00185 public:
00186     // *** Static Constant Options and Values of the B+ Tree
00187 
00189     static const unsigned short         leafslotmax =  traits::leafslots;
00190 
00193     static const unsigned short         innerslotmax =  traits::innerslots;
00194 
00198     static const unsigned short         minleafslots = (leafslotmax / 2);
00199 
00203     static const unsigned short         mininnerslots = (innerslotmax / 2);
00204 
00207     static const bool                   selfverify = traits::selfverify;
00208 
00212     static const bool                   debug = traits::debug;
00213 
00214 private:
00215     // *** Node Classes for In-Memory Nodes
00216 
00219     struct node
00220     {
00222         unsigned short  level;
00223 
00226         unsigned short  slotuse;
00227 
00229         inline void initialize(const unsigned short l)
00230         {
00231             level = l;
00232             slotuse = 0;
00233         }
00234         
00236         inline bool isleafnode() const
00237         {
00238             return (level == 0);
00239         }
00240     };
00241 
00244     struct inner_node : public node
00245     {
00247         key_type        slotkey[innerslotmax];
00248 
00250         node*           childid[innerslotmax+1];
00251 
00253         inline void initialize(const unsigned short l)
00254         {
00255             node::initialize(l);
00256         }
00257 
00259         inline bool isfull() const
00260         {
00261             return (node::slotuse == innerslotmax);
00262         }
00263 
00265         inline bool isfew() const
00266         {
00267             return (node::slotuse <= mininnerslots);
00268         }
00269 
00271         inline bool isunderflow() const
00272         {
00273             return (node::slotuse < mininnerslots);
00274         }
00275     };
00276 
00280     struct leaf_node : public node
00281     {
00283         leaf_node       *prevleaf;
00284 
00286         leaf_node       *nextleaf;
00287 
00289         key_type        slotkey[leafslotmax];
00290 
00292         data_type       slotdata[leafslotmax];
00293 
00295         inline void initialize()
00296         {
00297             node::initialize(0);
00298             prevleaf = nextleaf = NULL;
00299         }
00300 
00302         inline bool isfull() const
00303         {
00304             return (node::slotuse == leafslotmax);
00305         }
00306 
00308         inline bool isfew() const
00309         {
00310             return (node::slotuse <= minleafslots);
00311         }
00312 
00314         inline bool isunderflow() const
00315         {
00316             return (node::slotuse < minleafslots);
00317         }
00318     };
00319 
00320 private:
00321     // *** Template Magic to Convert a pair or key/data types to a value_type
00322 
00325     template <typename value_type, typename pair_type>
00326     struct btree_pair_to_value
00327     {
00329         inline value_type operator()(pair_type& p) const {
00330             return p.first;
00331         }
00333         inline value_type operator()(const pair_type& p) const {
00334             return p.first;
00335         }
00336     };
00337 
00339     template <typename value_type>
00340     struct btree_pair_to_value<value_type, value_type>
00341     {
00343         inline value_type operator()(pair_type& p) const {
00344             return p;
00345         }
00347         inline value_type operator()(const pair_type& p) const {
00348             return p;
00349         }
00350     };
00351 
00354     typedef btree_pair_to_value<value_type, pair_type> pair_to_value_type;
00355 
00356 public:
00357     // *** Iterators and Reverse Iterators
00358 
00359     class iterator;
00360     class const_iterator;
00361 
00364     class iterator
00365     {
00366     public:
00367         // *** Types
00368 
00370         typedef typename btree::key_type                key_type;
00371 
00373         typedef typename btree::data_type               data_type;
00374 
00376         typedef typename btree::value_type              value_type;
00377 
00379         typedef typename btree::pair_type               pair_type;
00380 
00382         typedef value_type&             reference;
00383 
00385         typedef value_type*             pointer;
00386 
00388         typedef std::bidirectional_iterator_tag iterator_category;
00389 
00391         typedef ptrdiff_t               difference_type;
00392 
00394         typedef iterator                self;
00395 
00396     private:
00397         // *** Members
00398 
00400         typename btree::leaf_node*      currnode;
00401 
00403         unsigned short  currslot;
00404     
00406         friend class btree<key_type, data_type, value_type, key_compare, traits, allow_duplicates>::const_iterator;
00407         
00410         mutable value_type              temp_value;
00411 
00412         // The macro BTREE_FRIENDS can be used by outside class to access the B+
00413         // tree internals. This was added for wxBTreeDemo to be able to draw the
00414         // tree.
00415         BTREE_FRIENDS
00416 
00417     public:
00418         // *** Methods
00419 
00421         inline iterator(typename btree::leaf_node *l, unsigned short s)
00422             : currnode(l), currslot(s)
00423         { }
00424 
00427         inline reference operator*() const
00428         {
00429             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
00430                                                          currnode->slotdata[currslot]) );
00431             return temp_value;
00432         }
00433 
00437         inline pointer operator->() const
00438         {
00439             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
00440                                                          currnode->slotdata[currslot]) );
00441             return &temp_value;
00442         }
00443 
00445         inline const key_type& key() const
00446         {
00447             return currnode->slotkey[currslot];
00448         }
00449 
00451         inline data_type& data() const
00452         {
00453             return currnode->slotdata[currslot];
00454         }
00455 
00457         inline self& operator++()
00458         {
00459             if (currslot + 1 < currnode->slotuse) {
00460                 ++currslot;
00461             }
00462             else if (currnode->nextleaf != NULL) {
00463                 currnode = currnode->nextleaf;
00464                 currslot = 0;
00465             }
00466             else {
00467                 // this is end()
00468                 currslot = currnode->slotuse;
00469             }
00470 
00471             return *this;
00472         }
00473 
00475         inline self operator++(int)
00476         {
00477             self tmp = *this;   // copy ourselves
00478 
00479             if (currslot + 1 < currnode->slotuse) {
00480                 ++currslot;
00481             }
00482             else if (currnode->nextleaf != NULL) {
00483                 currnode = currnode->nextleaf;
00484                 currslot = 0;
00485             }
00486             else {
00487                 // this is end()
00488                 currslot = currnode->slotuse;
00489             }
00490 
00491             return tmp;
00492         }
00493 
00495         inline self& operator--()
00496         {
00497             if (currslot > 0) {
00498                 --currslot;
00499             }
00500             else if (currnode->prevleaf != NULL) {
00501                 currnode = currnode->prevleaf;
00502                 currslot = currnode->slotuse - 1;
00503             }
00504             else {
00505                 // this is begin()
00506                 currslot = 0;
00507             }
00508 
00509             return *this;
00510         }
00511 
00513         inline self operator--(int)
00514         {
00515             self tmp = *this;   // copy ourselves
00516 
00517             if (currslot > 0) {
00518                 --currslot;
00519             }
00520             else if (currnode->prevleaf != NULL) {
00521                 currnode = currnode->prevleaf;
00522                 currslot = currnode->slotuse - 1;
00523             }
00524             else {
00525                 // this is begin()
00526                 currslot = 0;
00527             }
00528 
00529             return tmp;
00530         }
00531 
00533         inline bool operator==(const self& x) const
00534         {
00535             return (x.currnode == currnode) && (x.currslot == currslot);
00536         }
00537 
00539         inline bool operator!=(const self& x) const
00540         {
00541             return (x.currnode != currnode) || (x.currslot != currslot);
00542         }    
00543     };
00544 
00547     class const_iterator
00548     {
00549     public:
00550         // *** Types
00551 
00553         typedef typename btree::key_type                key_type;
00554 
00556         typedef typename btree::data_type               data_type;
00557 
00559         typedef typename btree::value_type              value_type;
00560 
00562         typedef typename btree::pair_type               pair_type;
00563 
00565         typedef const value_type&       reference;
00566 
00568         typedef const value_type*       pointer;
00569 
00571         typedef std::bidirectional_iterator_tag iterator_category;
00572 
00574         typedef ptrdiff_t               difference_type;
00575 
00577         typedef const_iterator          self;
00578 
00579     private:
00580         // *** Members
00581 
00583         const typename btree::leaf_node*        currnode;
00584 
00586         unsigned short  currslot;
00587     
00590         mutable value_type              temp_value;
00591 
00592         // The macro BTREE_FRIENDS can be used by outside class to access the B+
00593         // tree internals. This was added for wxBTreeDemo to be able to draw the
00594         // tree.
00595         BTREE_FRIENDS
00596 
00597     public:
00598         // *** Methods
00599 
00601         inline const_iterator(const typename btree::leaf_node *l, unsigned short s)
00602             : currnode(l), currslot(s)
00603         { }
00604 
00606         inline const_iterator(const iterator &it)
00607             : currnode(it.currnode), currslot(it.currslot)
00608         { }
00609 
00613         inline reference operator*() const
00614         {
00615             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
00616                                                          currnode->slotdata[currslot]) );
00617             return temp_value;
00618         }
00619 
00623         inline pointer operator->() const
00624         {
00625             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
00626                                                          currnode->slotdata[currslot]) );
00627             return &temp_value;
00628         }
00629 
00631         inline const key_type& key() const
00632         {
00633             return currnode->slotkey[currslot];
00634         }
00635 
00637         inline const data_type& data() const
00638         {
00639             return currnode->slotdata[currslot];
00640         }
00641 
00643         inline self& operator++()
00644         {
00645             if (currslot + 1 < currnode->slotuse) {
00646                 ++currslot;
00647             }
00648             else if (currnode->nextleaf != NULL) {
00649                 currnode = currnode->nextleaf;
00650                 currslot = 0;
00651             }
00652             else {
00653                 // this is end()
00654                 currslot = currnode->slotuse;
00655             }
00656 
00657             return *this;
00658         }
00659 
00661         inline self operator++(int)
00662         {
00663             self tmp = *this;   // copy ourselves
00664 
00665             if (currslot + 1 < currnode->slotuse) {
00666                 ++currslot;
00667             }
00668             else if (currnode->nextleaf != NULL) {
00669                 currnode = currnode->nextleaf;
00670                 currslot = 0;
00671             }
00672             else {
00673                 // this is end()
00674                 currslot = currnode->slotuse;
00675             }
00676 
00677             return tmp;
00678         }
00679 
00681         inline self& operator--()
00682         {
00683             if (currslot > 0) {
00684                 --currslot;
00685             }
00686             else if (currnode->prevleaf != NULL) {
00687                 currnode = currnode->prevleaf;
00688                 currslot = currnode->slotuse - 1;
00689             }
00690             else {
00691                 // this is begin()
00692                 currslot = 0;
00693             }
00694 
00695             return *this;
00696         }
00697 
00699         inline self operator--(int)
00700         {
00701             self tmp = *this;   // copy ourselves
00702 
00703             if (currslot > 0) {
00704                 --currslot;
00705             }
00706             else if (currnode->prevleaf != NULL) {
00707                 currnode = currnode->prevleaf;
00708                 currslot = currnode->slotuse - 1;
00709             }
00710             else {
00711                 // this is begin()
00712                 currslot = 0;
00713             }
00714 
00715             return tmp;
00716         }
00717 
00719         inline bool operator==(const self& x) const
00720         {
00721             return (x.currnode == currnode) && (x.currslot == currslot);
00722         }
00723 
00725         inline bool operator!=(const self& x) const
00726         {
00727             return (x.currnode != currnode) || (x.currslot != currslot);
00728         }    
00729     };
00730 
00732     typedef std::reverse_iterator<iterator>       reverse_iterator;
00733 
00735     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00736 
00737 public:
00738     // *** Small Statistics Structure
00739 
00742     struct tree_stats
00743     {
00745         size_type       itemcount;
00746 
00748         size_type       leaves;
00749 
00751         size_type       innernodes;
00752 
00754         static const unsigned short     leafslots = btree_self::leafslotmax;
00755 
00757         static const unsigned short     innerslots = btree_self::innerslotmax;
00758 
00760         inline tree_stats()
00761             : itemcount(0),
00762               leaves(0), innernodes(0)
00763         {
00764         }
00765 
00767         inline size_type nodes() const
00768         {
00769             return innernodes + leaves;
00770         }
00771 
00773         inline double avgfill_leaves() const
00774         {
00775             return static_cast<double>(itemcount) / (leaves * leafslots);
00776         }
00777     };
00778 
00779 private:
00780     // *** Tree Object Data Members
00781 
00783     node*       root;
00784 
00786     leaf_node   *headleaf;
00787 
00789     leaf_node   *tailleaf;
00790 
00792     tree_stats  stats;
00793 
00796     key_compare key_less;
00797 
00798 public:
00799     // *** Constructors and Destructor
00800 
00803     inline btree()
00804         : root(NULL), headleaf(NULL), tailleaf(NULL)
00805     {
00806     }
00807 
00810     inline btree(const key_compare &kcf)
00811         : root(NULL), headleaf(NULL), tailleaf(NULL),
00812           key_less(kcf)
00813     {
00814     }
00815 
00817     template <class InputIterator>
00818     inline btree(InputIterator first, InputIterator last)
00819         : root(NULL), headleaf(NULL), tailleaf(NULL)
00820     {
00821         insert(first, last);
00822     }
00823 
00826     template <class InputIterator>
00827     inline btree(InputIterator first, InputIterator last, const key_compare &kcf)
00828         : root(NULL), headleaf(NULL), tailleaf(NULL),
00829           key_less(kcf)
00830     {
00831         insert(first, last);
00832     }
00833 
00835     inline ~btree()
00836     {
00837         clear();
00838     }
00839 
00841     void swap(btree_self& from)
00842     {
00843         std::swap(root, from.root);
00844         std::swap(headleaf, from.headleaf);
00845         std::swap(tailleaf, from.tailleaf);
00846         std::swap(stats, from.stats);
00847         std::swap(key_less, from.key_less);
00848     }
00849 
00850 public:
00851     // *** Key and Value Comparison Function Objects
00852 
00854     class value_compare
00855     {
00856     protected:
00858         key_compare     key_comp;
00859  
00861         inline value_compare(key_compare kc)
00862             : key_comp(kc)
00863         { }
00864 
00866         friend class btree<key_type, data_type, value_type, key_compare, traits, allow_duplicates>;
00867  
00868     public:
00870         inline bool operator()(const value_type& x, const value_type& y) const
00871         {
00872             return key_comp(x.first, y.first);
00873         }
00874     };
00875 
00877     inline key_compare key_comp() const
00878     {
00879         return key_less;
00880     }
00881 
00884     inline value_compare value_comp() const
00885     {
00886         return value_compare(key_less);
00887     }
00888 
00889 private:
00890     // *** Convenient Key Comparison Functions Generated From key_less
00891 
00893     inline bool key_lessequal(const key_type &a, const key_type b) const
00894     {
00895         return !key_less(b, a);
00896     }
00897 
00899     inline bool key_greater(const key_type &a, const key_type &b) const
00900     {
00901         return key_less(b, a);
00902     }
00903 
00905     inline bool key_greaterequal(const key_type &a, const key_type b) const
00906     {
00907         return !key_less(a, b);
00908     }
00909 
00912     inline bool key_equal(const key_type &a, const key_type &b) const
00913     {
00914         return !key_less(a, b) && !key_less(b, a);
00915     }
00916 
00917 private:
00918     // *** Node Object Allocation and Deallocation Functions
00919 
00921     inline leaf_node* allocate_leaf()
00922     {
00923         leaf_node* n = new leaf_node;
00924         n->initialize();
00925         stats.leaves++;
00926         return n;
00927     }
00928 
00930     inline inner_node* allocate_inner(unsigned short l)
00931     {
00932         inner_node* n = new inner_node;
00933         n->initialize(l);
00934         stats.innernodes++;
00935         return n;
00936     }
00937     
00940     inline void free_node(node *n)
00941     {
00942         if (n->isleafnode()) {
00943             delete static_cast<leaf_node*>(n);
00944             stats.leaves--;
00945         }
00946         else {
00947             delete static_cast<inner_node*>(n);
00948             stats.innernodes--;
00949         }
00950     }
00951 
00952 public:
00953     // *** Fast Destruction of the B+ Tree
00954 
00956     void clear()
00957     {
00958         if (root)
00959         {
00960             clear_recursive(root);
00961             free_node(root);
00962 
00963             root = NULL;
00964             headleaf = tailleaf = NULL;
00965 
00966             stats = tree_stats();
00967         }
00968 
00969         BTREE_ASSERT(stats.itemcount == 0);
00970     }
00971 
00972 private:
00974     void clear_recursive(node *n)
00975     {
00976         if (n->isleafnode())
00977         {
00978             leaf_node *leafnode = static_cast<leaf_node*>(n);
00979 
00980             for (unsigned int slot = 0; slot < leafnode->slotuse; ++slot)
00981             {
00982                 // data objects are deleted by leaf_node's destructor
00983             }
00984         }
00985         else
00986         {
00987             inner_node *innernode = static_cast<inner_node*>(n);
00988 
00989             for (unsigned short slot = 0; slot < innernode->slotuse + 1; ++slot)
00990             {
00991                 clear_recursive(innernode->childid[slot]);
00992                 free_node(innernode->childid[slot]);
00993             }
00994         }
00995     }
00996 
00997 public:
00998     // *** STL Iterator Construction Functions
00999 
01002     inline iterator begin()
01003     {
01004         return iterator(headleaf, 0);
01005     }
01006 
01009     inline iterator end()
01010     {
01011         return iterator(tailleaf, tailleaf ? tailleaf->slotuse : 0);
01012     }
01013 
01016     inline const_iterator begin() const
01017     {
01018         return const_iterator(headleaf, 0);
01019     }
01020 
01023     inline const_iterator end() const
01024     {
01025         return const_iterator(tailleaf, tailleaf ? tailleaf->slotuse : 0);
01026     }
01027 
01030     inline reverse_iterator rbegin()
01031     {
01032         return reverse_iterator(end());
01033     }
01034 
01037     inline reverse_iterator rend()
01038     {
01039         return reverse_iterator(begin());
01040     }
01041 
01044     inline const_reverse_iterator rbegin() const
01045     {
01046         return const_reverse_iterator(end());
01047     }
01048 
01051     inline const_reverse_iterator rend() const
01052     {
01053         return const_reverse_iterator(begin());
01054     }
01055 
01056 private:
01057     // *** B+ Tree Node Binary Search Functions
01058 
01063     template <typename node_type>
01064     inline int find_lower(const node_type *n, const key_type& key) const
01065     {
01066         if (n->slotuse == 0) return 0;
01067 
01068         int lo = 0,
01069             hi = n->slotuse - 1;
01070 
01071         while(lo < hi)
01072         {
01073             int mid = (lo + hi) / 2;
01074 
01075             if (key_lessequal(key, n->slotkey[mid])) {
01076                 hi = mid - 1;
01077             }
01078             else {
01079                 lo = mid + 1;
01080             }
01081         }
01082 
01083         if (hi < 0 || key_less(n->slotkey[hi], key))
01084             hi++;
01085 
01086         BTREE_PRINT("btree::find_lower: on " << n << " key " << key << " -> (" << lo << ") " << hi << ", ");
01087 
01088         // verify result using simple linear search
01089         if (selfverify)
01090         {
01091             int i = n->slotuse - 1;
01092             while(i >= 0 && key_lessequal(key, n->slotkey[i]))
01093                 i--;
01094             i++;
01095 
01096             BTREE_PRINT("testfind: " << i << std::endl);
01097             BTREE_ASSERT(i == hi);
01098         }
01099         else {
01100             BTREE_PRINT(std::endl);
01101         }
01102         
01103         return hi;
01104     }
01105 
01110     template <typename node_type>
01111     inline int find_upper(const node_type *n, const key_type& key) const
01112     {
01113         if (n->slotuse == 0) return 0;
01114 
01115         int lo = 0,
01116             hi = n->slotuse - 1;
01117 
01118         while(lo < hi)
01119         {
01120             int mid = (lo + hi) / 2;
01121 
01122             if (key_less(key, n->slotkey[mid])) {
01123                 hi = mid - 1;
01124             }
01125             else {
01126                 lo = mid + 1;
01127             }
01128         }
01129 
01130         if (hi < 0 || key_lessequal(n->slotkey[hi], key))
01131             hi++;
01132 
01133         BTREE_PRINT("btree::find_upper: on " << n << " key " << key << " -> (" << lo << ") " << hi << ", ");
01134 
01135         // verify result using simple linear search
01136         if (selfverify)
01137         {
01138             int i = n->slotuse - 1;
01139             while(i >= 0 && key_less(key, n->slotkey[i]))
01140                 i--;
01141             i++;
01142 
01143             BTREE_PRINT("btree::find_upper testfind: " << i << std::endl);
01144             BTREE_ASSERT(i == hi);
01145         }
01146         else {
01147             BTREE_PRINT(std::endl);
01148         }
01149         
01150         return hi;
01151     }
01152 
01153 public:
01154     // *** Access Functions to the Item Count
01155 
01157     inline size_type size() const
01158     {
01159         return stats.itemcount;
01160     }
01161 
01163     inline bool empty() const
01164     {
01165         return (size() == size_type(0));
01166     }
01167     
01170     inline size_type max_size() const
01171     {
01172         return size_type(-1);
01173     }
01174 
01176     inline const struct tree_stats& get_stats() const
01177     {
01178         return stats;
01179     }
01180 
01181 public:
01182     // *** Standard Access Functions Querying the Tree by Descending to a Leaf
01183 
01186     bool exists(const key_type &key) const
01187     {
01188         const node *n = root;
01189 
01190         if (!n) return false;
01191 
01192         while(!n->isleafnode())
01193         {
01194             const inner_node *inner = static_cast<const inner_node*>(n);
01195             int slot = find_lower(inner, key);
01196 
01197             n = inner->childid[slot];
01198         }
01199 
01200         const leaf_node *leaf = static_cast<const leaf_node*>(n);
01201 
01202         int slot = find_lower(leaf, key);
01203         return key_equal(key, leaf->slotkey[slot]);
01204     }
01205 
01208     iterator find(const key_type &key)
01209     {
01210         node *n = root;
01211         if (!n) return end();
01212 
01213         while(!n->isleafnode())
01214         {
01215             const inner_node *inner = static_cast<const inner_node*>(n);
01216             int slot = find_lower(inner, key);
01217 
01218             n = inner->childid[slot];
01219         }
01220 
01221         leaf_node *leaf = static_cast<leaf_node*>(n);
01222 
01223         int slot = find_lower(leaf, key);
01224         return key_equal(key, leaf->slotkey[slot]) ? iterator(leaf, slot) : end();
01225     }
01226 
01229     const_iterator find(const key_type &key) const
01230     {
01231         const node *n = root;
01232         if (!n) return end();
01233 
01234         while(!n->isleafnode())
01235         {
01236             const inner_node *inner = static_cast<const inner_node*>(n);
01237             int slot = find_lower(inner, key);
01238 
01239             n = inner->childid[slot];
01240         }
01241 
01242         const leaf_node *leaf = static_cast<const leaf_node*>(n);
01243 
01244         int slot = find_lower(leaf, key);
01245         return key_equal(key, leaf->slotkey[slot]) ? const_iterator(leaf, slot) : end();
01246     }
01247 
01250     size_type count(const key_type &key) const
01251     {
01252         const node *n = root;
01253         if (!n) return 0;
01254 
01255         while(!n->isleafnode())
01256         {
01257             const inner_node *inner = static_cast<const inner_node*>(n);
01258             int slot = find_lower(inner, key);
01259 
01260             n = inner->childid[slot];
01261         }
01262 
01263         const leaf_node *leaf = static_cast<const leaf_node*>(n);
01264 
01265         int slot = find_lower(leaf, key);
01266         size_type num = 0;
01267 
01268         while (leaf && key_equal(key, leaf->slotkey[slot]))
01269         {
01270             ++num;
01271             if (++slot >= leaf->slotuse)
01272             {
01273                 leaf = leaf->nextleaf;
01274                 slot = 0;
01275             }
01276         }
01277 
01278         return num;
01279     }
01280 
01283     iterator lower_bound(const key_type& key)
01284     {
01285         node *n = root;
01286         if (!n) return end();
01287 
01288         while(!n->isleafnode())
01289         {
01290             const inner_node *inner = static_cast<const inner_node*>(n);
01291             int slot = find_lower(inner, key);
01292 
01293             n = inner->childid[slot];
01294         }
01295 
01296         leaf_node *leaf = static_cast<leaf_node*>(n);
01297 
01298         int slot = find_lower(leaf, key);
01299         return iterator(leaf, slot);
01300     }
01301 
01304     const_iterator lower_bound(const key_type& key) const
01305     {
01306         const node *n = root;
01307         if (!n) return end();
01308 
01309         while(!n->isleafnode())
01310         {
01311             const inner_node *inner = static_cast<const inner_node*>(n);
01312             int slot = find_lower(inner, key);
01313 
01314             n = inner->childid[slot];
01315         }
01316 
01317         const leaf_node *leaf = static_cast<const leaf_node*>(n);
01318 
01319         int slot = find_lower(leaf, key);
01320         return const_iterator(leaf, slot);
01321     }
01322 
01325     iterator upper_bound(const key_type& key)
01326     {
01327         node *n = root;
01328         if (!n) return end();
01329 
01330         while(!n->isleafnode())
01331         {
01332             const inner_node *inner = static_cast<const inner_node*>(n);
01333             int slot = find_upper(inner, key);
01334 
01335             n = inner->childid[slot];
01336         }
01337 
01338         leaf_node *leaf = static_cast<leaf_node*>(n);
01339 
01340         int slot = find_upper(leaf, key);
01341         return iterator(leaf, slot);
01342     }
01343 
01346     const_iterator upper_bound(const key_type& key) const
01347     {
01348         const node *n = root;
01349         if (!n) return end();
01350 
01351         while(!n->isleafnode())
01352         {
01353             const inner_node *inner = static_cast<const inner_node*>(n);
01354             int slot = find_upper(inner, key);
01355 
01356             n = inner->childid[slot];
01357         }
01358 
01359         const leaf_node *leaf = static_cast<const leaf_node*>(n);
01360 
01361         int slot = find_upper(leaf, key);
01362         return const_iterator(leaf, slot);
01363     }
01364 
01366     inline std::pair<iterator, iterator> equal_range(const key_type& key)
01367     {
01368         return std::pair<iterator, iterator>(lower_bound(key), upper_bound(key));
01369     }
01370 
01372     inline std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const
01373     {
01374         return std::pair<const_iterator, const_iterator>(lower_bound(key), upper_bound(key));
01375     }
01376 
01377 public:
01378     // *** B+ Tree Object Comparison Functions
01379 
01383     inline bool operator==(const btree_self &other) const
01384     {
01385         return (size() == other.size()) && std::equal(begin(), end(), other.begin());
01386     }
01387 
01389     inline bool operator!=(const btree_self &other) const
01390     {
01391         return !(*this == other);
01392     }
01393 
01396     inline bool operator<(const btree_self &other) const
01397     {
01398         return std::lexicographical_compare(begin(), end(), other.begin(), other.end());
01399     }
01400 
01402     inline bool operator>(const btree_self &other) const
01403     {
01404         return other < *this;
01405     }
01406 
01408     inline bool operator<=(const btree_self &other) const
01409     {
01410         return !(other < *this);
01411     }
01412 
01414     inline bool operator>=(const btree_self &other) const
01415     {
01416         return !(*this < other);
01417     }
01418 
01419 public:
01421 
01423     inline btree_self& operator= (const btree_self &other)
01424     {
01425         if (this != &other)
01426         {
01427             clear();
01428 
01429             key_less = other.key_comp();
01430             if (other.size() != 0)
01431             {
01432                 stats.leaves = stats.innernodes = 0;
01433                 root = copy_recursive(other.root);
01434                 stats = other.stats;
01435             }
01436 
01437             if (selfverify) verify();
01438         }
01439         return *this;
01440     }
01441 
01444     inline btree(const btree_self &other)
01445         : root(NULL), headleaf(NULL), tailleaf(NULL),
01446           stats( other.stats ),
01447           key_less( other.key_comp() )
01448     {
01449         if (size() > 0)
01450         {
01451             stats.leaves = stats.innernodes = 0;
01452             root = copy_recursive(other.root);
01453             if (selfverify) verify();
01454         }
01455     }
01456     
01457 private:
01459     struct node* copy_recursive(const node *n)
01460     {
01461         if (n->isleafnode())
01462         {
01463             const leaf_node *leaf = static_cast<const leaf_node*>(n);
01464             leaf_node *newleaf = allocate_leaf();
01465 
01466             newleaf->slotuse = leaf->slotuse;
01467             std::copy(leaf->slotkey, leaf->slotkey + leaf->slotuse, newleaf->slotkey);
01468             std::copy(leaf->slotdata, leaf->slotdata + leaf->slotuse, newleaf->slotdata);
01469 
01470             if (headleaf == NULL)
01471             {
01472                 headleaf = tailleaf = newleaf;
01473                 newleaf->prevleaf = newleaf->nextleaf = NULL;
01474             }
01475             else
01476             {
01477                 newleaf->prevleaf = tailleaf;
01478                 tailleaf->nextleaf = newleaf;
01479                 tailleaf = newleaf;
01480             }
01481 
01482             return newleaf;
01483         }
01484         else
01485         {
01486             const inner_node *inner = static_cast<const inner_node*>(n);
01487             inner_node *newinner = allocate_inner(inner->level);
01488 
01489             newinner->slotuse = inner->slotuse;
01490             std::copy(inner->slotkey, inner->slotkey + inner->slotuse, newinner->slotkey);
01491 
01492             for (unsigned short slot = 0; slot <= inner->slotuse; ++slot)
01493             {
01494                 newinner->childid[slot] = copy_recursive(inner->childid[slot]);
01495             }
01496 
01497             return newinner;
01498         }
01499     }
01500 
01501 public:
01502     // *** Public Insertion Functions
01503 
01507     inline std::pair<iterator, bool> insert(const pair_type& x)
01508     {
01509         return insert_start(x.first, x.second);
01510     }
01511     
01516     inline std::pair<iterator, bool> insert(const key_type& key, const data_type& data)
01517     {
01518         return insert_start(key, data);
01519     }
01520 
01525     inline std::pair<iterator, bool> insert2(const key_type& key, const data_type& data)
01526     {
01527         return insert_start(key, data);
01528     }
01529 
01532     inline iterator insert(iterator /* hint */, const pair_type &x)
01533     {
01534         return insert_start(x.first, x.second).first;
01535     }
01536 
01539     inline iterator insert2(iterator /* hint */, const key_type& key, const data_type& data)
01540     {
01541         return insert_start(key, data).first;
01542     }
01543 
01546     template <typename InputIterator>
01547     inline void insert(InputIterator first, InputIterator last)
01548     {
01549         InputIterator iter = first;
01550         while(iter != last)
01551         {
01552             insert(*iter);
01553             ++iter;
01554         }
01555     }
01556 
01557 private:
01558     // *** Private Insertion Functions
01559 
01562     std::pair<iterator, bool> insert_start(const key_type& key, const data_type& value)
01563     {
01564         node *newchild = NULL;
01565         key_type newkey = key_type();
01566 
01567         if (!root)
01568         {
01569             root = headleaf = tailleaf = allocate_leaf();
01570         }
01571 
01572         std::pair<iterator, bool> r = insert_descend(root, key, value, &newkey, &newchild);
01573 
01574         if (newchild)
01575         {
01576             inner_node *newroot = allocate_inner(root->level + 1);
01577             newroot->slotkey[0] = newkey;
01578 
01579             newroot->childid[0] = root;
01580             newroot->childid[1] = newchild;
01581 
01582             newroot->slotuse = 1;
01583 
01584             root = newroot;
01585         }
01586 
01587         // increment itemcount if the item was inserted
01588         if (r.second) ++stats.itemcount;
01589 
01590         if (debug)
01591             print(std::cout);
01592 
01593         if (selfverify) {
01594             verify();
01595             BTREE_ASSERT(exists(key));
01596         }
01597 
01598         return r;
01599     }
01600 
01608     std::pair<iterator, bool> insert_descend(node* n,
01609                                              const key_type& key, const data_type& value,
01610                                              key_type* splitkey, node** splitnode)
01611     {
01612         if (!n->isleafnode())
01613         {
01614             inner_node *inner = static_cast<inner_node*>(n);
01615 
01616             key_type newkey = key_type();
01617             node *newchild = NULL;
01618 
01619             int slot = find_lower(inner, key);
01620 
01621             BTREE_PRINT("btree::insert_descend into " << inner->childid[slot] << std::endl);
01622 
01623             std::pair<iterator, bool> r = insert_descend(inner->childid[slot],
01624                                                          key, value, &newkey, &newchild);
01625 
01626             if (newchild)
01627             {
01628                 BTREE_PRINT("btree::insert_descend newchild with key " << newkey << " node " << newchild << " at slot " << slot << std::endl);
01629 
01630                 if (inner->isfull())
01631                 {
01632                     split_inner_node(inner, splitkey, splitnode, slot);
01633 
01634                     BTREE_PRINT("btree::insert_descend done split_inner: putslot: " << slot << " putkey: " << newkey << " upkey: " << *splitkey << std::endl);
01635 
01636                     if (debug)
01637                     {
01638                         print_node(std::cout, inner);
01639                         print_node(std::cout, *splitnode);
01640                     }
01641 
01642                     // check if insert slot is in the split sibling node
01643                     BTREE_PRINT("btree::insert_descend switch: " << slot << " > " << inner->slotuse+1 << std::endl);
01644 
01645                     if (slot == inner->slotuse+1 && inner->slotuse < (*splitnode)->slotuse)
01646                     {
01647                         // special case when the insert slot matches the split
01648                         // place between the two nodes, then the insert key
01649                         // becomes the split key.
01650 
01651                         BTREE_ASSERT(inner->slotuse + 1 < innerslotmax);
01652 
01653                         inner_node *splitinner = static_cast<inner_node*>(*splitnode);
01654 
01655                         // move the split key and it's datum into the left node
01656                         inner->slotkey[inner->slotuse] = *splitkey;
01657                         inner->childid[inner->slotuse+1] = splitinner->childid[0];
01658                         inner->slotuse++;
01659 
01660                         // set new split key and move corresponding datum into right node
01661                         splitinner->childid[0] = newchild;
01662                         *splitkey = newkey;
01663 
01664                         return r;
01665                     }
01666                     else if (slot >= inner->slotuse+1)
01667                     {
01668                         // in case the insert slot is in the newly create split
01669                         // node, we reuse the code below.
01670 
01671                         slot -= inner->slotuse+1;
01672                         inner = static_cast<inner_node*>(*splitnode);
01673                         BTREE_PRINT("btree::insert_descend switching to splitted node " << inner << " slot " << slot <<std::endl);
01674                     }
01675                 }
01676 
01677                 // put pointer to child node into correct slot
01678                 BTREE_ASSERT(slot >= 0 && slot <= inner->slotuse);
01679 
01680                 int i = inner->slotuse;
01681 
01682                 while(i > slot) {
01683                     inner->slotkey[i] = inner->slotkey[i - 1];
01684                     inner->childid[i + 1] = inner->childid[i];
01685                     i--;
01686                 }
01687 
01688                 inner->slotkey[slot] = newkey;
01689                 inner->childid[slot + 1] = newchild;
01690                 inner->slotuse++;
01691             }
01692             
01693             return r;
01694         }
01695         else // n->isleafnode() == true
01696         {
01697             leaf_node *leaf = static_cast<leaf_node*>(n);
01698 
01699             int slot = find_lower(leaf, key);
01700 
01701             if (!allow_duplicates && slot < leaf->slotuse && key_equal(key, leaf->slotkey[slot])) {
01702                 return std::pair<iterator, bool>(iterator(leaf, slot), false);
01703             }
01704 
01705             if (leaf->isfull())
01706             {
01707                 split_leaf_node(leaf, splitkey, splitnode);
01708 
01709                 // check if insert slot is in the split sibling node
01710                 if (slot >= leaf->slotuse)
01711                 {
01712                     slot -= leaf->slotuse;
01713                     leaf = static_cast<leaf_node*>(*splitnode);
01714                 }
01715             }
01716 
01717             // put data item into correct data slot
01718 
01719             int i = leaf->slotuse - 1;
01720             BTREE_ASSERT(i + 1 < leafslotmax);
01721 
01722             while(i >= 0 && key_less(key, leaf->slotkey[i])) {
01723                 leaf->slotkey[i + 1] = leaf->slotkey[i];
01724                 leaf->slotdata[i + 1] = leaf->slotdata[i];
01725                 i--;
01726             }
01727             
01728             leaf->slotkey[i + 1] = key;
01729             leaf->slotdata[i + 1] = value;
01730             leaf->slotuse++;
01731 
01732             if (splitnode && leaf != *splitnode && slot == leaf->slotuse-1)
01733             {
01734                 // special case: the node was split, and the insert is at the
01735                 // last slot of the old node. then the splitkey must be
01736                 // updated.
01737                 *splitkey = key;
01738             }
01739 
01740             return std::pair<iterator, bool>(iterator(leaf, i + 1), true);
01741         }
01742     }
01743 
01746     void split_leaf_node(leaf_node* leaf, key_type* _newkey, node** _newleaf)
01747     {
01748         BTREE_ASSERT(leaf->isfull());
01749 
01750         unsigned int mid = leaf->slotuse / 2;
01751 
01752         BTREE_PRINT("btree::split_leaf_node on " << leaf << std::endl);
01753 
01754         leaf_node *newleaf = allocate_leaf();
01755 
01756         newleaf->slotuse = leaf->slotuse - mid;
01757 
01758         newleaf->nextleaf = leaf->nextleaf;
01759         if (newleaf->nextleaf == NULL) {
01760             BTREE_ASSERT(leaf == tailleaf);
01761             tailleaf = newleaf;
01762         }
01763         else {
01764             newleaf->nextleaf->prevleaf = newleaf;
01765         }
01766 
01767         for(unsigned int slot = mid; slot < leaf->slotuse; ++slot)
01768         {
01769             unsigned int ni = slot - mid;
01770             newleaf->slotkey[ni] = leaf->slotkey[slot];
01771             newleaf->slotdata[ni] = leaf->slotdata[slot];
01772         }
01773             
01774         leaf->slotuse = mid;
01775         leaf->nextleaf = newleaf;
01776         newleaf->prevleaf = leaf;
01777 
01778         *_newkey = leaf->slotkey[leaf->slotuse-1];
01779         *_newleaf = newleaf;
01780     }
01781 
01786     void split_inner_node(inner_node* inner, key_type* _newkey, node** _newinner, unsigned int addslot)
01787     {
01788         BTREE_ASSERT(inner->isfull());
01789 
01790         unsigned int mid = inner->slotuse / 2;
01791 
01792         BTREE_PRINT("btree::split_inner: mid " << mid << " addslot " << addslot << std::endl);
01793 
01794         // if the split is uneven and the overflowing item will be put into the
01795         // larger node, then the smaller split node may underflow
01796         if (addslot <= mid && mid > inner->slotuse - (mid + 1))
01797             mid--;
01798 
01799         BTREE_PRINT("btree::split_inner: mid " << mid << " addslot " << addslot << std::endl);
01800 
01801         BTREE_PRINT("btree::split_inner_node on " << inner << " into two nodes " << mid << " and " << inner->slotuse - (mid + 1) << " sized" << std::endl);
01802 
01803         inner_node *newinner = allocate_inner(inner->level);
01804 
01805         newinner->slotuse = inner->slotuse - (mid + 1);
01806 
01807         for(unsigned int slot = mid + 1; slot < inner->slotuse; ++slot)
01808         {
01809             unsigned int ni = slot - (mid + 1);
01810             newinner->slotkey[ni] = inner->slotkey[slot];
01811             newinner->childid[ni] = inner->childid[slot];
01812         }
01813         newinner->childid[newinner->slotuse] = inner->childid[inner->slotuse];
01814             
01815         inner->slotuse = mid;
01816 
01817         *_newkey = inner->slotkey[mid];
01818         *_newinner = newinner;
01819     }
01820 
01821 private:
01822     // *** Support Class Encapsulating Deletion Results
01823 
01825     enum result_flags_t
01826     {
01828         btree_ok = 0,
01829 
01831         btree_not_found = 1,
01832 
01835         btree_update_lastkey = 2,
01836 
01839         btree_fixmerge = 4
01840     };
01841 
01844     struct result_t
01845     {
01847         result_flags_t  flags;
01848 
01850         key_type        lastkey;
01851 
01854         inline result_t(result_flags_t f = btree_ok)
01855             : flags(f), lastkey()
01856         { }
01857 
01859         inline result_t(result_flags_t f, const key_type &k)
01860             : flags(f), lastkey(k)
01861         { }
01862 
01864         inline bool has(result_flags_t f) const
01865         {
01866             return (flags & f) != 0;
01867         }
01868 
01870         inline result_t& operator|= (const result_t &other)
01871         {
01872             flags = result_flags_t(flags | other.flags);
01873 
01874             // we overwrite existing lastkeys on purpose
01875             if (other.has(btree_update_lastkey))
01876                 lastkey = other.lastkey;
01877 
01878             return *this;
01879         }
01880     };
01881 
01882 public:
01883     // *** Public Erase Functions
01884 
01887     bool erase_one(const key_type &key)
01888     {
01889         BTREE_PRINT("btree::erase_one(" << key << ") on btree size " << size() << std::endl);
01890 
01891         if (selfverify) verify();
01892         
01893         result_t result = erase_one_descend(key, root, NULL, NULL, NULL, NULL, NULL, 0);
01894 
01895         if (!result.has(btree_not_found))
01896             --stats.itemcount;
01897 
01898         if (debug) print(std::cout);
01899         if (selfverify) verify();
01900 
01901         return !result.has(btree_not_found);
01902     }
01903 
01906     size_type erase(const key_type &key)
01907     {
01908         size_type c = 0;
01909 
01910         while( erase_one(key) )
01911         {
01912             ++c;
01913             if (!allow_duplicates) break;
01914         }
01915 
01916         return c;
01917     }
01918 
01919 #ifdef BTREE_TODO
01921     void erase(iterator iter)
01922     {
01923 
01924     }
01925 #endif
01926 
01927 #ifdef BTREE_TODO
01930     void erase(iterator /* first */, iterator /* last */)
01931     {
01932         abort();
01933     }
01934 #endif
01935 
01936 private:
01937     // *** Private Erase Functions
01938 
01948     result_t erase_one_descend(const key_type& key,
01949                                node *curr,
01950                                node *left, node *right,
01951                                inner_node *leftparent, inner_node *rightparent,
01952                                inner_node *parent, unsigned int parentslot)
01953     {
01954         if (curr->isleafnode())
01955         {
01956             leaf_node *leaf = static_cast<leaf_node*>(curr);
01957             leaf_node *leftleaf = static_cast<leaf_node*>(left);
01958             leaf_node *rightleaf = static_cast<leaf_node*>(right);
01959 
01960             int slot = find_lower(leaf, key);
01961 
01962             if (!key_equal(key, leaf->slotkey[slot]))
01963             {
01964                 BTREE_PRINT("Could not find key " << key << " to erase." << std::endl);
01965 
01966                 return btree_not_found;
01967             }
01968 
01969             BTREE_PRINT("Found key in leaf " << curr << " at slot " << slot << std::endl);
01970 
01971             for (int i = slot; i < leaf->slotuse - 1; i++)
01972             {
01973                 leaf->slotkey[i] = leaf->slotkey[i + 1];
01974                 leaf->slotdata[i] = leaf->slotdata[i + 1];
01975             }
01976             leaf->slotuse--;
01977 
01978             result_t myres = btree_ok;
01979 
01980             // if the last key of the leaf was changed, the parent is notified
01981             // and updates the key of this leaf
01982             if (slot == leaf->slotuse)
01983             {
01984                 if (parent && parentslot < parent->slotuse)
01985                 {
01986                     BTREE_ASSERT(parent->childid[parentslot] == curr);
01987                     parent->slotkey[parentslot] = leaf->slotkey[leaf->slotuse - 1];
01988                 }
01989                 else
01990                 {
01991                     BTREE_PRINT("Scheduling lastkeyupdate: key " << leaf->slotkey[leaf->slotuse - 1] << std::endl);
01992                     myres |= result_t(btree_update_lastkey, leaf->slotkey[leaf->slotuse - 1]);
01993                 }
01994             }
01995 
01996             if (leaf->isunderflow() && !(leaf == root && leaf->slotuse >= 1))
01997             {
01998                 // determine what to do about the underflow
01999 
02000                 // case : if this empty leaf is the root, there is no way to
02001                 // correct underflow
02002                 if (leftleaf == NULL && rightleaf == NULL)
02003                 {
02004                     return btree_ok;
02005                 }
02006                 // case : if both left and right leaves would underflow in case of
02007                 // a shift, then merging is necessary. choose the more local merger
02008                 // with our parent
02009                 else if ( (leftleaf == NULL || leftleaf->isfew()) && (rightleaf == NULL || rightleaf->isfew()) )
02010                 {
02011                     if (leftparent == parent)
02012                         myres |= merge_leaves(leftleaf, leaf, leftparent);
02013                     else
02014                         myres |= merge_leaves(leaf, rightleaf, rightparent);
02015                 }
02016                 // case : the right leaf has extra data, so balance right with current
02017                 else if ( (leftleaf != NULL && leftleaf->isfew()) && (rightleaf != NULL && !rightleaf->isfew()) )
02018                 {
02019                     if (rightparent == parent)
02020                         myres |= shift_left_leaf(leaf, rightleaf, rightparent, parentslot);
02021                     else
02022                         myres |= merge_leaves(leftleaf, leaf, leftparent);
02023                 }
02024                 // case : the left leaf has extra data, so balance left with current
02025                 else if ( (leftleaf != NULL && !leftleaf->isfew()) && (rightleaf != NULL && rightleaf->isfew()) )
02026                 {
02027                     if (leftparent == parent)
02028                         shift_right_leaf(leftleaf, leaf, leftparent, parentslot - 1);
02029                     else
02030                         myres |= merge_leaves(leaf, rightleaf, rightparent);
02031                 }
02032                 // case : both the leaf and right leaves have extra data and our
02033                 // parent, choose the leaf with more data
02034                 else if (leftparent == rightparent)
02035                 {
02036                     if (leftleaf->slotuse <= rightleaf->slotuse)
02037                         myres |= shift_left_leaf(leaf, rightleaf, rightparent, parentslot);
02038                     else
02039                         shift_right_leaf(leftleaf, leaf, leftparent, parentslot - 1);
02040                 }
02041                 else
02042                 {
02043                     if (leftparent == parent)
02044                         shift_right_leaf(leftleaf, leaf, leftparent, parentslot - 1);
02045                     else
02046                         myres |= shift_left_leaf(leaf, rightleaf, rightparent, parentslot);
02047                 }
02048             }
02049 
02050             return myres;
02051         }
02052         else // !curr->isleafnode()
02053         {
02054             inner_node *inner = static_cast<inner_node*>(curr);
02055             inner_node *leftinner = static_cast<inner_node*>(left);
02056             inner_node *rightinner = static_cast<inner_node*>(right);
02057 
02058             node *myleft, *myright;
02059             inner_node *myleftparent, *myrightparent;
02060 
02061             int slot = find_lower(inner, key);
02062 
02063             if (slot == 0) {
02064                 myleft = (left == NULL) ? NULL : (static_cast<inner_node*>(left))->childid[left->slotuse - 1];
02065                 myleftparent = leftparent;
02066             }
02067             else {
02068                 myleft = inner->childid[slot - 1];
02069                 myleftparent = inner;
02070             }
02071 
02072             if (slot == inner->slotuse) {
02073                 myright = (right == NULL) ? NULL : (static_cast<inner_node*>(right))->childid[0];
02074                 myrightparent = rightparent;
02075             }
02076             else {
02077                 myright = inner->childid[slot + 1];
02078                 myrightparent = inner;
02079             }
02080 
02081             BTREE_PRINT("erase_one_descend into " << inner->childid[slot] << std::endl);
02082 
02083             result_t result = erase_one_descend(key,
02084                                                 inner->childid[slot],
02085                                                 myleft, myright,
02086                                                 myleftparent, myrightparent,
02087                                                 inner, slot);
02088 
02089             result_t myres = btree_ok;
02090 
02091             if (result.has(btree_not_found))
02092             {
02093                 return result;
02094             }
02095 
02096             if (result.has(btree_update_lastkey))
02097             {
02098                 if (parent && parentslot < parent->slotuse)
02099                 {
02100                     BTREE_PRINT("Fixing lastkeyupdate: key " << result.lastkey << " into parent " << parent << " at parentslot " << parentslot << std::endl);
02101 
02102                     BTREE_ASSERT(parent->childid[parentslot] == curr);
02103                     parent->slotkey[parentslot] = result.lastkey;
02104                 }
02105                 else
02106                 {
02107                     BTREE_PRINT("Forwarding lastkeyupdate: key " << result.lastkey << std::endl);
02108                     myres |= result_t(btree_update_lastkey, result.lastkey);
02109                 }
02110             }
02111 
02112             if (result.has(btree_fixmerge))
02113             {
02114                 // either the current node or the next is empty and should be removed
02115                 if (inner->childid[slot]->slotuse != 0)
02116                     slot++;
02117 
02118                 // this is the child slot invalidated by the merge
02119                 BTREE_ASSERT(inner->childid[slot]->slotuse == 0);
02120 
02121                 free_node(inner->childid[slot]);
02122 
02123                 for(int i = slot; i < inner->slotuse; i++)
02124                 {
02125                     inner->slotkey[i - 1] = inner->slotkey[i];
02126                     inner->childid[i] = inner->childid[i + 1];
02127                 }
02128                 inner->slotuse--;
02129 
02130                 if (inner->level == 1)
02131                 {
02132                     // fix split key for children leaves
02133                     slot--;
02134                     leaf_node *child = static_cast<leaf_node*>(inner->childid[slot]);
02135                     inner->slotkey[slot] = child->slotkey[ child->slotuse-1 ];
02136                 }
02137             }
02138 
02139             if (inner->isunderflow() && !(inner == root && inner->slotuse >= 1))
02140             {
02141                 // case: the inner node is the root and has just one child. that child becomes the new root
02142                 if (leftinner == NULL && rightinner == NULL)
02143                 {
02144                     BTREE_ASSERT(inner == root);
02145                     BTREE_ASSERT(inner->slotuse == 0);
02146 
02147                     root = inner->childid[0];
02148 
02149                     inner->slotuse = 0;
02150                     free_node(inner);
02151 
02152                     return btree_ok;
02153                 }
02154                 // case : if both left and right leaves would underflow in case of
02155                 // a shift, then merging is necessary. choose the more local merger
02156                 // with our parent
02157                 else if ( (leftinner == NULL || leftinner->isfew()) && (rightinner == NULL || rightinner->isfew()) )
02158                 {
02159                     if (leftparent == parent)
02160                         myres |= merge_inner(leftinner, inner, leftparent, parentslot - 1);
02161                     else
02162                         myres |= merge_inner(inner, rightinner, rightparent, parentslot);
02163                 }
02164                 // case : the right leaf has extra data, so balance right with current
02165                 else if ( (leftinner != NULL && leftinner->isfew()) && (rightinner != NULL && !rightinner->isfew()) )
02166                 {
02167                     if (rightparent == parent)
02168                         shift_left_inner(inner, rightinner, rightparent, parentslot);
02169                     else
02170                         myres |= merge_inner(leftinner, inner, leftparent, parentslot - 1);
02171                 }
02172                 // case : the left leaf has extra data, so balance left with current
02173                 else if ( (leftinner != NULL && !leftinner->isfew()) && (rightinner != NULL && rightinner->isfew()) )
02174                 {
02175                     if (leftparent == parent)
02176                         shift_right_inner(leftinner, inner, leftparent, parentslot - 1);
02177                     else
02178                         myres |= merge_inner(inner, rightinner, rightparent, parentslot);
02179                 }
02180                 // case : both the leaf and right leaves have extra data and our
02181                 // parent, choose the leaf with more data
02182                 else if (leftparent == rightparent)
02183                 {
02184                     if (leftinner->slotuse <= rightinner->slotuse)
02185                         shift_left_inner(inner, rightinner, rightparent, parentslot);
02186                     else
02187                         shift_right_inner(leftinner, inner, leftparent, parentslot - 1);
02188                 }
02189                 else
02190                 {
02191                     if (leftparent == parent)
02192                         shift_right_inner(leftinner, inner, leftparent, parentslot - 1);
02193                     else
02194                         shift_left_inner(inner, rightinner, rightparent, parentslot);
02195                 }
02196             }
02197 
02198             return myres;
02199         }
02200     }
02201 
02205     result_t merge_leaves(leaf_node* left, leaf_node* right, inner_node* parent)
02206     {
02207         BTREE_PRINT("Merge leaf nodes " << left << " and " << right << " with common parent " << parent << "." << std::endl);
02208         (void)parent;
02209 
02210         BTREE_ASSERT(left->isleafnode() && right->isleafnode());
02211         BTREE_ASSERT(parent->level == 1);
02212 
02213         BTREE_ASSERT(left->slotuse + right->slotuse < leafslotmax);
02214 
02215         for (unsigned int i = 0; i < right->slotuse; i++)
02216         {
02217             left->slotkey[left->slotuse + i] = right->slotkey[i];
02218             left->slotdata[left->slotuse + i] = right->slotdata[i];
02219         }
02220         left->slotuse += right->slotuse;
02221 
02222         left->nextleaf = right->nextleaf;
02223         if (left->nextleaf)
02224             left->nextleaf->prevleaf = left;
02225         else
02226             tailleaf = left;
02227 
02228         right->slotuse = 0;
02229 
02230         return btree_fixmerge;
02231     }
02232 
02236     static result_t merge_inner(inner_node* left, inner_node* right, inner_node* parent, unsigned int parentslot)
02237     {
02238         BTREE_PRINT("Merge inner nodes " << left << " and " << right << " with common parent " << parent << "." << std::endl);
02239 
02240         BTREE_ASSERT(left->level == right->level);
02241         BTREE_ASSERT(parent->level == left->level + 1);
02242 
02243         BTREE_ASSERT(parent->childid[parentslot] == left);
02244 
02245         BTREE_ASSERT(left->slotuse + right->slotuse < innerslotmax);
02246 
02247         if (selfverify)
02248         {
02249             // find the left node's slot in the parent's children
02250             unsigned int leftslot = 0;
02251             while(leftslot <= parent->slotuse && parent->childid[leftslot] != left)
02252                 ++leftslot;
02253 
02254             BTREE_ASSERT(leftslot < parent->slotuse);
02255             BTREE_ASSERT(parent->childid[leftslot] == left);
02256             BTREE_ASSERT(parent->childid[leftslot+1] == right);
02257 
02258             BTREE_ASSERT(parentslot == leftslot);
02259         }
02260 
02261         // retrieve the decision key from parent
02262         left->slotkey[left->slotuse] = parent->slotkey[parentslot];
02263         left->slotuse++;
02264 
02265         // copy over keys and children from right
02266         for (unsigned int i = 0; i < right->slotuse; i++)
02267         {
02268             left->slotkey[left->slotuse + i] = right->slotkey[i];
02269             left->childid[left->slotuse + i] = right->childid[i];
02270         }
02271         left->slotuse += right->slotuse;
02272 
02273         left->childid[left->slotuse] = right->childid[right->slotuse];
02274 
02275         right->slotuse = 0;
02276 
02277         return btree_fixmerge;
02278     }
02279 
02283     static result_t shift_left_leaf(leaf_node *left, leaf_node *right, inner_node *parent, unsigned int parentslot)
02284     {
02285         BTREE_ASSERT(left->isleafnode() && right->isleafnode());
02286         BTREE_ASSERT(parent->level == 1);
02287 
02288         BTREE_ASSERT(left->nextleaf == right);
02289         BTREE_ASSERT(left == right->prevleaf);
02290 
02291         BTREE_ASSERT(left->slotuse < right->slotuse);
02292         BTREE_ASSERT(parent->childid[parentslot] == left);
02293 
02294         unsigned int shiftnum = (right->slotuse - left->slotuse) / 2;
02295 
02296         BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to left " << left << " from right " << right << " with common parent " << parent << "." << std::endl);
02297 
02298         BTREE_ASSERT(left->slotuse + shiftnum < leafslotmax);
02299 
02300         // copy the first items from the right node to the last slot in the left node.
02301         for(unsigned int i = 0; i < shiftnum; i++)
02302         {
02303             left->slotkey[left->slotuse + i] = right->slotkey[i];
02304             left->slotdata[left->slotuse + i] = right->slotdata[i];
02305         }
02306         left->slotuse += shiftnum;
02307         
02308         // shift all slots in the right node to the left
02309     
02310         right->slotuse -= shiftnum;
02311         for(int i = 0; i < right->slotuse; i++)
02312         {
02313             right->slotkey[i] = right->slotkey[i + shiftnum];
02314             right->slotdata[i] = right->slotdata[i + shiftnum];
02315         }
02316 
02317         // fixup parent
02318         if (parentslot < parent->slotuse) {
02319             parent->slotkey[parentslot] = left->slotkey[left->slotuse - 1];
02320             return btree_ok;
02321         }
02322         else { // the update is further up the tree
02323             return result_t(btree_update_lastkey, left->slotkey[left->slotuse - 1]);
02324         }
02325     }
02326 
02330     static void shift_left_inner(inner_node *left, inner_node *right, inner_node *parent, unsigned int parentslot)
02331     {
02332         BTREE_ASSERT(left->level == right->level);
02333         BTREE_ASSERT(parent->level == left->level + 1);
02334 
02335         BTREE_ASSERT(left->slotuse < right->slotuse);
02336         BTREE_ASSERT(parent->childid[parentslot] == left);
02337 
02338         unsigned int shiftnum = (right->slotuse - left->slotuse) / 2;
02339 
02340         BTREE_PRINT("Shifting (inner) " << shiftnum << " entries to left " << left << " from right " << right << " with common parent " << parent << "." << std::endl);
02341 
02342         BTREE_ASSERT(left->slotuse + shiftnum < innerslotmax);
02343 
02344         if (selfverify)
02345         {
02346             // find the left node's slot in the parent's children and compare to parentslot
02347 
02348             unsigned int leftslot = 0;
02349             while(leftslot <= parent->slotuse && parent->childid[leftslot] != left)
02350                 ++leftslot;
02351 
02352             BTREE_ASSERT(leftslot < parent->slotuse);
02353             BTREE_ASSERT(parent->childid[leftslot] == left);
02354             BTREE_ASSERT(parent->childid[leftslot+1] == right);
02355 
02356             BTREE_ASSERT(leftslot == parentslot);
02357         }
02358 
02359         // copy the parent's decision slotkey and childid to the first new key on the left
02360         left->slotkey[left->slotuse] = parent->slotkey[parentslot];
02361         left->slotuse++;
02362 
02363         // copy the other items from the right node to the last slots in the left node.
02364         for(unsigned int i = 0; i < shiftnum - 1; i++)
02365         {
02366             left->slotkey[left->slotuse + i] = right->slotkey[i];
02367             left->childid[left->slotuse + i] = right->childid[i];
02368         }
02369         left->slotuse += shiftnum - 1;
02370 
02371         // fixup parent
02372         parent->slotkey[parentslot] = right->slotkey[shiftnum - 1];
02373         // last pointer in left
02374         left->childid[left->slotuse] = right->childid[shiftnum - 1];
02375         
02376         // shift all slots in the right node
02377     
02378         right->slotuse -= shiftnum;
02379         for(int i = 0; i < right->slotuse; i++)
02380         {
02381             right->slotkey[i] = right->slotkey[i + shiftnum];
02382             right->childid[i] = right->childid[i + shiftnum];
02383         }
02384         right->childid[right->slotuse] = right->childid[right->slotuse + shiftnum];
02385     }
02386 
02390     static void shift_right_leaf(leaf_node *left, leaf_node *right, inner_node *parent, unsigned int parentslot)
02391     {
02392         BTREE_ASSERT(left->isleafnode() && right->isleafnode());
02393         BTREE_ASSERT(parent->level == 1);
02394 
02395         BTREE_ASSERT(left->nextleaf == right);
02396         BTREE_ASSERT(left == right->prevleaf);
02397         BTREE_ASSERT(parent->childid[parentslot] == left);
02398 
02399         BTREE_ASSERT(left->slotuse > right->slotuse);
02400 
02401         unsigned int shiftnum = (left->slotuse - right->slotuse) / 2;
02402 
02403         BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to right " << right << " from left " << left << " with common parent " << parent << "." << std::endl);
02404 
02405         if (selfverify)
02406         {
02407             // find the left node's slot in the parent's children
02408             unsigned int leftslot = 0;
02409             while(leftslot <= parent->slotuse && parent->childid[leftslot] != left)
02410                 ++leftslot;
02411 
02412             BTREE_ASSERT(leftslot < parent->slotuse);
02413             BTREE_ASSERT(parent->childid[leftslot] == left);
02414             BTREE_ASSERT(parent->childid[leftslot+1] == right);
02415 
02416             BTREE_ASSERT(leftslot == parentslot);
02417         }
02418 
02419         // shift all slots in the right node
02420     
02421         BTREE_ASSERT(right->slotuse + shiftnum < leafslotmax);
02422 
02423         for(int i = right->slotuse; i >= 0; i--)
02424         {
02425             right->slotkey[i + shiftnum] = right->slotkey[i];
02426             right->slotdata[i + shiftnum] = right->slotdata[i];
02427         }
02428         right->slotuse += shiftnum;
02429 
02430         // copy the last items from the left node to the first slot in the right node.
02431         for(unsigned int i = 0; i < shiftnum; i++)
02432         {
02433             right->slotkey[i] = left->slotkey[left->slotuse - shiftnum + i];
02434             right->slotdata[i] = left->slotdata[left->slotuse - shiftnum + i];
02435         }
02436         left->slotuse -= shiftnum;
02437 
02438         parent->slotkey[parentslot] = left->slotkey[left->slotuse-1];
02439     }
02440 
02444     static void shift_right_inner(inner_node *left, inner_node *right, inner_node *parent, unsigned int parentslot)
02445     {
02446         BTREE_ASSERT(left->level == right->level);
02447         BTREE_ASSERT(parent->level == left->level + 1);
02448 
02449         BTREE_ASSERT(left->slotuse > right->slotuse);
02450         BTREE_ASSERT(parent->childid[parentslot] == left);
02451 
02452         unsigned int shiftnum = (left->slotuse - right->slotuse) / 2;
02453 
02454         BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to right " << right << " from left " << left << " with common parent " << parent << "." << std::endl);
02455 
02456         if (selfverify)
02457         {
02458             // find the left node's slot in the parent's children
02459             unsigned int leftslot = 0;
02460             while(leftslot <= parent->slotuse && parent->childid[leftslot] != left)
02461                 ++leftslot;
02462 
02463             BTREE_ASSERT(leftslot < parent->slotuse);
02464             BTREE_ASSERT(parent->childid[leftslot] == left);
02465             BTREE_ASSERT(parent->childid[leftslot+1] == right);
02466 
02467             BTREE_ASSERT(leftslot == parentslot);
02468         }
02469 
02470         // shift all slots in the right node
02471 
02472         BTREE_ASSERT(right->slotuse + shiftnum < innerslotmax);
02473     
02474         right->childid[right->slotuse + shiftnum] = right->childid[right->slotuse];
02475         for(int i = right->slotuse-1; i >= 0; i--)
02476         {
02477             right->slotkey[i + shiftnum] = right->slotkey[i];
02478             right->childid[i + shiftnum] = right->childid[i];
02479         }
02480 
02481         right->slotuse += shiftnum;
02482 
02483         // copy the parent's decision slotkey and childid to the last new key on the right
02484         right->slotkey[shiftnum - 1] = parent->slotkey[parentslot];
02485         right->childid[shiftnum - 1] = left->childid[left->slotuse];
02486 
02487         // copy the remaining last items from the left node to the first slot in the right node.
02488         for(unsigned int i = 0; i < shiftnum - 1; i++)
02489         {
02490             right->slotkey[i] = left->slotkey[left->slotuse - shiftnum + i + 1];
02491             right->childid[i] = left->childid[left->slotuse - shiftnum + i + 1];
02492         }
02493 
02494         // copy the first to-be-removed key from the left node to the parent's decision slot
02495         parent->slotkey[parentslot] = left->slotkey[left->slotuse - shiftnum];
02496 
02497         left->slotuse -= shiftnum;
02498     }
02499 
02500 #ifdef BTREE_DEBUG
02501 public:
02502     // *** Debug Printing
02503 
02507     void print(std::ostream &os) const
02508     {
02509         if (root) {
02510             print_node(os, root, 0, true);
02511         }
02512     }
02513 
02515     void print_leaves(std::ostream &os) const
02516     {
02517         os << "leaves:" << std::endl;
02518 
02519         const leaf_node *n = headleaf;
02520 
02521         while(n)
02522         {
02523             os << "  " << n << std::endl;
02524 
02525             n = n->nextleaf;
02526         }
02527     }
02528 
02529 private:
02530 
02532     static void print_node(std::ostream &os, const node* node, unsigned int depth=0, bool recursive=false)
02533     {
02534         for(unsigned int i = 0; i < depth; i++) os << "  ";
02535             
02536         os << "node " << node << " level " << node->level << " slotuse " << node->slotuse << std::endl;
02537 
02538         if (node->isleafnode())
02539         {
02540             const leaf_node *leafnode = static_cast<const leaf_node*>(node);
02541 
02542             for(unsigned int i = 0; i < depth; i++) os << "  ";
02543             os << "  leaf prev " << leafnode->prevleaf << " next " << leafnode->nextleaf << std::endl;
02544 
02545             for(unsigned int i = 0; i < depth; i++) os << "  ";
02546 
02547             for (unsigned int slot = 0; slot < leafnode->slotuse; ++slot)
02548             {
02549                 os << leafnode->slotkey[slot] << "  "; // << "(data: " << leafnode->slotdata[slot] << ") ";
02550             }
02551             os << std::endl;
02552         }
02553         else
02554         {
02555             const inner_node *innernode = static_cast<const inner_node*>(node);
02556 
02557             for(unsigned int i = 0; i < depth; i++) os << "  ";
02558 
02559             for (unsigned short slot = 0; slot < innernode->slotuse; ++slot)
02560             {
02561                 os << "(" << innernode->childid[slot] << ") " << innernode->slotkey[slot] << " ";
02562             }
02563             os << "(" << innernode->childid[innernode->slotuse] << ")" << std::endl;
02564 
02565             if (recursive)
02566             {
02567                 for (unsigned short slot = 0; slot < innernode->slotuse + 1; ++slot)
02568                 {
02569                     print_node(os, innernode->childid[slot], depth + 1, recursive);
02570                 }
02571             }
02572         }
02573     }
02574 
02575 #else
02576 public:
02577     // *** Dummy Debug Printing Functions
02578 
02582     void print(std::ostream&) const
02583     {
02584     }
02585 
02587     void print_leaves(std::ostream&) const
02588     {
02589     }
02590 
02591 private:
02592 
02594     static void print_node(std::ostream &, const node*, unsigned int =0, bool =false)
02595     {
02596     }
02597 #endif
02598 
02599 public:
02600     // *** Verification of B+ Tree Invariants
02601 
02604     void verify() const
02605     {
02606         key_type minkey, maxkey;
02607         tree_stats vstats;
02608         
02609         if (root)
02610         {
02611             verify_node(root, &minkey, &maxkey, vstats);
02612 
02613             assert( vstats.itemcount == stats.itemcount );
02614             assert( vstats.leaves == stats.leaves );
02615             assert( vstats.innernodes == stats.innernodes );
02616         }
02617 
02618         verify_leaflinks();
02619     }
02620 
02621 private:
02622 
02624     void verify_node(const node* n, key_type* minkey, key_type* maxkey, tree_stats &vstats) const
02625     {
02626         BTREE_PRINT("verifynode " << n << std::endl);
02627 
02628         if (n->isleafnode())
02629         {
02630             const leaf_node *leaf = static_cast<const leaf_node*>(n);
02631 
02632             assert(leaf == root || !leaf->isunderflow());
02633 
02634             for(unsigned short slot = 0; slot < leaf->slotuse - 1; ++slot)
02635             {
02636                 assert(key_lessequal(leaf->slotkey[slot], leaf->slotkey[slot + 1]));
02637             }
02638 
02639             *minkey = leaf->slotkey[0];
02640             *maxkey = leaf->slotkey[leaf->slotuse - 1];
02641 
02642             vstats.leaves++;
02643             vstats.itemcount += leaf->slotuse;
02644         }
02645         else // !n->isleafnode()
02646         {
02647             const inner_node *inner = static_cast<const inner_node*>(n);
02648             vstats.innernodes++;
02649 
02650             assert(inner == root || !inner->isunderflow());
02651 
02652             for(unsigned short slot = 0; slot < inner->slotuse - 1; ++slot)
02653             {
02654                 assert(key_lessequal(inner->slotkey[slot], inner->slotkey[slot + 1]));
02655             }
02656 
02657             for(unsigned short slot = 0; slot <= inner->slotuse; ++slot)
02658             {
02659                 const node *subnode = inner->childid[slot];
02660                 key_type subminkey = key_type();
02661                 key_type submaxkey = key_type();
02662 
02663                 assert(subnode->level + 1 == inner->level);
02664                 verify_node(subnode, &subminkey, &submaxkey, vstats);
02665 
02666                 BTREE_PRINT("verify subnode " << subnode << ": " << subminkey << " - " << submaxkey << std::endl);
02667 
02668                 if (slot == 0)
02669                     *minkey = subminkey;
02670                 else
02671                     assert(key_greaterequal(subminkey, inner->slotkey[slot-1]));
02672 
02673                 if (slot == inner->slotuse)
02674                     *maxkey = submaxkey;
02675                 else
02676                     assert(key_equal(inner->slotkey[slot], submaxkey));
02677 
02678                 if (inner->level == 1 && slot < inner->slotuse)
02679                 {
02680                     // children are leaves and must be linked together in the
02681                     // correct order
02682                     const leaf_node *leafa = static_cast<const leaf_node*>(inner->childid[slot]);
02683                     const leaf_node *leafb = static_cast<const leaf_node*>(inner->childid[slot + 1]);
02684 
02685                     assert(leafa->nextleaf == leafb);
02686                     assert(leafa == leafb->prevleaf);
02687                     (void)leafa; (void)leafb;
02688                 }
02689                 if (inner->level == 2 && slot < inner->slotuse)
02690                 {
02691                     // verify leaf links between the adjacent inner nodes
02692                     const inner_node *parenta = static_cast<const inner_node*>(inner->childid[slot]);
02693                     const inner_node *parentb = static_cast<const inner_node*>(inner->childid[slot+1]);
02694 
02695                     const leaf_node *leafa = static_cast<const leaf_node*>(parenta->childid[parenta->slotuse]);
02696                     const leaf_node *leafb = static_cast<const leaf_node*>(parentb->childid[0]);
02697 
02698                     assert(leafa->nextleaf == leafb);
02699                     assert(leafa == leafb->prevleaf);
02700                     (void)leafa; (void)leafb;
02701                 }
02702             }
02703         }
02704     }
02705 
02707     void verify_leaflinks() const
02708     {
02709         const leaf_node *n = headleaf;
02710 
02711         assert(n->level == 0);
02712         assert(!n || n->prevleaf == NULL);
02713 
02714         unsigned int testcount = 0;
02715 
02716         while(n)
02717         {
02718             assert(n->level == 0);
02719 
02720             for(unsigned short slot = 0; slot < n->slotuse - 1; ++slot)
02721             {
02722                 assert(key_lessequal(n->slotkey[slot], n->slotkey[slot + 1]));
02723             }
02724 
02725             testcount += n->slotuse;
02726 
02727             if (n->nextleaf)
02728             {
02729                 assert(key_lessequal(n->slotkey[n->slotuse-1], n->nextleaf->slotkey[0]));
02730 
02731                 assert(n == n->nextleaf->prevleaf);
02732             }
02733             else
02734             {
02735                 assert(tailleaf == n);
02736             }
02737 
02738             n = n->nextleaf;
02739         }
02740 
02741         assert(testcount == size());
02742     }
02743 
02744 private:
02745     // *** Dump and Restore of B+ Trees
02746 
02750     struct dump_header
02751     {
02753         char            signature[12];
02754 
02756         unsigned short  version;
02757 
02759         unsigned short  key_type_size;
02760 
02762         unsigned short  data_type_size;
02763 
02765         unsigned short  leafslots;
02766 
02768         unsigned short  innerslots;
02769 
02771         bool            allow_duplicates;
02772 
02774         size_type       itemcount;
02775 
02778         inline void fill()
02779         {
02780             // don't want to include string.h just for this signature
02781             *reinterpret_cast<unsigned int*>(signature+0) = 0x2d787473;
02782             *reinterpret_cast<unsigned int*>(signature+4) = 0x65727462;
02783             *reinterpret_cast<unsigned int*>(signature+8) = 0x00000065;
02784 
02785             version = 0;
02786             key_type_size = sizeof(typename btree_self::key_type);
02787             data_type_size = sizeof(typename btree_self::data_type);
02788             leafslots = btree_self::leafslotmax;
02789             innerslots = btree_self::innerslotmax;
02790             allow_duplicates = btree_self::allow_duplicates;
02791         }
02792 
02794         inline bool same(const struct dump_header &o) const
02795         {
02796             return (*reinterpret_cast<const unsigned int*>(signature+0) ==
02797                     *reinterpret_cast<const unsigned int*>(o.signature+0))
02798                 && (*reinterpret_cast<const unsigned int*>(signature+4) ==
02799                     *reinterpret_cast<const unsigned int*>(o.signature+4))
02800                 && (*reinterpret_cast<const unsigned int*>(signature+8) ==
02801                     *reinterpret_cast<const unsigned int*>(o.signature+8))
02802 
02803                 && (version == o.version)
02804                 && (key_type_size == o.key_type_size)
02805                 && (data_type_size == o.data_type_size)
02806                 && (leafslots == o.leafslots)
02807                 && (innerslots == o.innerslots)
02808                 && (allow_duplicates == o.allow_duplicates);
02809         }
02810     };
02811 
02812 public:
02813 
02818     void dump(std::ostream &os) const
02819     {
02820         struct dump_header header;
02821         header.fill();
02822         header.itemcount = size();
02823 
02824         os.write(reinterpret_cast<char*>(&header), sizeof(header));
02825 
02826         if (root)
02827             dump_node(os, root);
02828     }
02829 
02834     bool restore(std::istream &is)
02835     {
02836         struct dump_header fileheader;
02837         is.read(reinterpret_cast<char*>(&fileheader), sizeof(fileheader));
02838         if (!is.good()) return false;
02839 
02840         struct dump_header myheader;
02841         myheader.fill();
02842         myheader.itemcount = fileheader.itemcount;
02843 
02844         if (!myheader.same(fileheader))
02845         {
02846             BTREE_PRINT("btree::restore: file header does not match instantiation signature." << std::endl);
02847             return false;
02848         }
02849 
02850         clear();
02851 
02852         if (fileheader.itemcount > 0)
02853         {
02854             root = restore_node(is);
02855             if (root == NULL) return false;
02856 
02857             stats.itemcount = fileheader.itemcount;
02858         }
02859 
02860         if (debug) print(std::cout);
02861         if (selfverify) verify();
02862 
02863         return true;
02864     }
02865 
02866 private:
02867 
02869     void dump_node(std::ostream &os, const node* n) const
02870     {
02871         BTREE_PRINT("dump_node " << n << std::endl);
02872 
02873         if (n->isleafnode())
02874         {
02875             const leaf_node *leaf = static_cast<const leaf_node*>(n);
02876 
02877             os.write(reinterpret_cast<const char*>(leaf), sizeof(*leaf));
02878         }
02879         else // !n->isleafnode()
02880         {
02881             const inner_node *inner = static_cast<const inner_node*>(n);
02882 
02883             os.write(reinterpret_cast<const char*>(inner), sizeof(*inner));
02884 
02885             for(unsigned short slot = 0; slot <= inner->slotuse; ++slot)
02886             {
02887                 const node *subnode = inner->childid[slot];
02888                 
02889                 dump_node(os, subnode);
02890             }
02891         }
02892     }
02893 
02896     node* restore_node(std::istream &is)
02897     {
02898         union {
02899             node        top;
02900             leaf_node   leaf;
02901             inner_node  inner;
02902         } nu;
02903 
02904         // first read only the top of the node
02905         is.read(reinterpret_cast<char*>(&nu.top), sizeof(nu.top));
02906         if (!is.good()) return NULL;
02907 
02908         if (nu.top.isleafnode())
02909         {
02910             // read remaining data of leaf node
02911             is.read(reinterpret_cast<char*>(&nu.leaf) + sizeof(nu.top), sizeof(nu.leaf) - sizeof(nu.top));
02912             if (!is.good()) return NULL;
02913             
02914             leaf_node *newleaf = allocate_leaf();
02915 
02916             // copy over all data, the leaf nodes contain only their double linked list pointers
02917             *newleaf = nu.leaf;
02918 
02919             // reconstruct the linked list from the order in the file
02920             if (headleaf == NULL) {
02921                 BTREE_ASSERT(newleaf->prevleaf == NULL);
02922                 headleaf = tailleaf = newleaf;
02923             }
02924             else {
02925                 newleaf->prevleaf = tailleaf;
02926                 tailleaf->nextleaf = newleaf;
02927                 tailleaf = newleaf;
02928             }
02929 
02930             return newleaf;
02931         }
02932         else
02933         {
02934             // read remaining data of inner node
02935             is.read(reinterpret_cast<char*>(&nu.inner) + sizeof(nu.top), sizeof(nu.inner) - sizeof(nu.top));
02936             if (!is.good()) return NULL;
02937 
02938             inner_node *newinner = allocate_inner(0);
02939 
02940             // copy over all data, the inner nodes contain only pointers to their children
02941             *newinner = nu.inner;
02942 
02943             for(unsigned short slot = 0; slot <= newinner->slotuse; ++slot)
02944             {
02945                 newinner->childid[slot] = restore_node(is);
02946             }
02947 
02948             return newinner;
02949         }
02950     }
02951 };
02952 
02953 } // namespace stx
02954 
02955 #endif // _STX_BTREE_H_

Generated on Sun May 13 19:24:41 2007 for STX B+ Tree Template Classes by  doxygen 1.5.2