STX B+ Tree Template Classes 0.8.6

stx/btree.h

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