LTP GCOV extension - code coverage report
Current view: directory - include/stx - btree.h
Test: STX B+ Tree Testsuite
Date: 2007-05-08 Instrumented lines: 854
Code covered: 89.2 % Executed lines: 762

       1                 : // $Id: btree.h 37 2007-04-27 12:13:27Z tb $
       2                 : /** \file btree.h
       3                 :  * Contains the main B+ tree implementation template class btree.
       4                 :  */
       5                 : 
       6                 : /*
       7                 :  * STX B+ Tree Template Classes v0.7
       8                 :  * Copyright (C) 2007 Timo Bingmann
       9                 :  *
      10                 :  * This library is free software; you can redistribute it and/or modify it
      11                 :  * under the terms of the GNU Lesser General Public License as published by the
      12                 :  * Free Software Foundation; either version 2.1 of the License, or (at your
      13                 :  * option) any later version.
      14                 :  *
      15                 :  * This library is distributed in the hope that it will be useful, but WITHOUT
      16                 :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      17                 :  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
      18                 :  * for more details.
      19                 :  *
      20                 :  * You should have received a copy of the GNU Lesser General Public License
      21                 :  * along with this library; if not, write to the Free Software Foundation,
      22                 :  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      23                 :  */
      24                 : 
      25                 : #ifndef _STX_BTREE_H_
      26                 : #define _STX_BTREE_H_
      27                 : 
      28                 : // *** Required Headers from the STL
      29                 : 
      30                 : #include <functional>
      31                 : #include <algorithm>
      32                 : #include <istream>
      33                 : #include <ostream>
      34                 : #include <assert.h>
      35                 : 
      36                 : // *** Debugging Macros
      37                 : 
      38                 : #ifdef BTREE_DEBUG
      39                 : 
      40                 : #include <iostream>
      41                 : 
      42                 : /// Print out debug information to std::cout if BTREE_DEBUG is defined.
      43                 : #define BTREE_PRINT(x)          do { if (debug) (std::cout << x); } while(0)
      44                 : 
      45                 : /// Assertion only if BTREE_DEBUG is defined. This is not used in verify().
      46                 : #define BTREE_ASSERT(x)         do { assert(x); } while(0)
      47                 : 
      48                 : #else
      49                 : 
      50                 : /// Print out debug information to std::cout if BTREE_DEBUG is defined.
      51                 : #define BTREE_PRINT(x)          do { } while(0)
      52                 : 
      53                 : /// Assertion only if BTREE_DEBUG is defined. This is not used in verify().
      54                 : #define BTREE_ASSERT(x)         do { } while(0)
      55                 : 
      56                 : #endif
      57                 : 
      58                 : /// The maximum of a and b. Used in some compile-time formulas.
      59                 : #define BTREE_MAX(a,b)          ((a) < (b) ? (b) : (a))
      60                 : 
      61                 : /// STX - Some Template Extensions namespace
      62                 : namespace stx {
      63                 : 
      64                 : /** Generates default traits for a B+ tree used as a set. It estimates leaf and
      65                 :  * inner node sizes by assuming a cache line size of 256 bytes. */
      66                 : template <typename _Key>
      67                 : struct btree_default_set_traits
      68                 : {
      69                 :     /// If true, the tree will self verify it's invariants after each insert()
      70                 :     /// or erase(). The header must have been compiled with BTREE_DEBUG defined.
      71                 :     static const bool   selfverify = false;
      72                 : 
      73                 :     /// If true, the tree will print out debug information and a tree dump
      74                 :     /// during insert() or erase() operation. The header must have been
      75                 :     /// compiled with BTREE_DEBUG defined and key_type must be std::ostream
      76                 :     /// printable.
      77                 :     static const bool   debug = false;
      78                 : 
      79                 :     /// Number of slots in each leaf of the tree. Estimated so that each node
      80                 :     /// has a size of about 256 bytes.
      81                 :     static const int    leafslots = BTREE_MAX( 8, 256 / (sizeof(_Key)) );
      82                 : 
      83                 :     /// Number of slots in each inner node of the tree. Estimated so that each node
      84                 :     /// has a size of about 256 bytes.
      85                 :     static const int    innerslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(void*)) );
      86                 : };
      87                 : 
      88                 : /** Generates default traits for a B+ tree used as a map. It estimates leaf and
      89                 :  * inner node sizes by assuming a cache line size of 256 bytes. */
      90                 : template <typename _Key, typename _Data>
      91                 : struct btree_default_map_traits
      92                 : {
      93                 :     /// If true, the tree will self verify it's invariants after each insert()
      94                 :     /// or erase(). The header must have been compiled with BTREE_DEBUG defined.
      95                 :     static const bool   selfverify = false;
      96                 : 
      97                 :     /// If true, the tree will print out debug information and a tree dump
      98                 :     /// during insert() or erase() operation. The header must have been
      99                 :     /// compiled with BTREE_DEBUG defined and key_type must be std::ostream
     100                 :     /// printable.
     101                 :     static const bool   debug = false;
     102                 : 
     103                 :     /// Number of slots in each leaf of the tree. Estimated so that each node
     104                 :     /// has a size of about 256 bytes.
     105                 :     static const int    leafslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(_Data)) );
     106                 : 
     107                 :     /// Number of slots in each inner node of the tree. Estimated so that each node
     108                 :     /// has a size of about 256 bytes.
     109                 :     static const int    innerslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(void*)) );
     110                 : };
     111                 : 
     112                 : /** @brief Basic class implementing a base B+ tree data structure in memory.
     113                 :  *
     114                 :  * The base implementation of a memory B+ tree. It is based on the
     115                 :  * implementation in Cormen's Introduction into Algorithms, Jan Jannink's paper
     116                 :  * and other algorithm resources. Almost all STL-required function calls are
     117                 :  * implemented. The asymptotic time requirements of the STL are not always
     118                 :  * fulfilled in theory, however in practice this B+ tree performs better than a
     119                 :  * red-black tree by using more memory. The insertion function splits the nodes
     120                 :  * on the recursion unroll. Erase is largely based on Jannink's ideas.
     121                 :  *
     122                 :  * This class is specialized into btree_set, btree_multiset, btree_map and
     123                 :  * btree_multimap using default template parameters and facade functions.
     124                 :  */
     125                 : template <typename _Key, typename _Data,
     126                 :           typename _Value = std::pair<_Key, _Data>,
     127                 :           typename _Compare = std::less<_Key>,
     128                 :           typename _Traits = btree_default_map_traits<_Key, _Data>,
     129                 :           bool _Duplicates = false>
     130                 : class btree
     131                 : {
     132                 : public:
     133                 :     // *** Template Parameter Types
     134                 : 
     135                 :     /// First template parameter: The key type of the B+ tree. This is stored
     136                 :     /// in inner nodes and leaves
     137                 :     typedef _Key                        key_type;
     138                 : 
     139                 :     /// Second template parameter: The data type associated with each
     140                 :     /// key. Stored in the B+ tree's leaves
     141                 :     typedef _Data                       data_type;
     142                 : 
     143                 :     /// Third template parameter: Composition pair of key and data types, this
     144                 :     /// is required by the STL standard. The B+ tree does not store key and
     145                 :     /// data together. If value_type == key_type then the B+ tree implements a
     146                 :     /// set.
     147                 :     typedef _Value                      value_type;
     148                 : 
     149                 :     /// Fourth template parameter: Key comparison function object
     150                 :     typedef _Compare                    key_compare;
     151                 : 
     152                 :     /// Fifth template parameter: Traits object used to define more parameters
     153                 :     /// of the B+ tree
     154                 :     typedef _Traits                     traits;
     155                 : 
     156                 :     /// Sixth template parameter: Allow duplicate keys in the B+ tree. Used to
     157                 :     /// implement multiset and multimap.
     158                 :     static const bool                   allow_duplicates = _Duplicates;
     159                 : 
     160                 : public:
     161                 :     // *** Constructed Types
     162                 : 
     163                 :     /// Typedef of our own type
     164                 :     typedef btree<key_type, data_type, value_type,
     165                 :                   key_compare, traits, allow_duplicates>     btree_self;
     166                 : 
     167                 :     /// Size type used to count keys
     168                 :     typedef size_t                              size_type;
     169                 : 
     170                 :     /// The pair of key_type and data_type, this may be different from value_type.
     171                 :     typedef std::pair<key_type, data_type>        pair_type;
     172                 : 
     173                 : public:
     174                 :     // *** Static Constant Options and Values of the B+ Tree
     175                 : 
     176                 :     /// Base B+ tree parameter: The number of key/data slots in each leaf
     177                 :     static const unsigned short         leafslotmax =  traits::leafslots;
     178                 : 
     179                 :     /// Base B+ tree parameter: The number of key slots in each inner node,
     180                 :     /// this can differ from slots in each leaf.
     181                 :     static const unsigned short         innerslotmax =  traits::innerslots;
     182                 : 
     183                 :     /// Computed B+ tree parameter: The minimum number of key/data slots used
     184                 :     /// in a leaf. If fewer slots are used, the leaf will be merged or slots
     185                 :     /// shifted from it's siblings.
     186                 :     static const unsigned short         minleafslots = (leafslotmax / 2);
     187                 : 
     188                 :     /// Computed B+ tree parameter: The minimum number of key slots used
     189                 :     /// in an inner node. If fewer slots are used, the inner node will be
     190                 :     /// merged or slots shifted from it's siblings.
     191                 :     static const unsigned short         mininnerslots = (innerslotmax / 2);
     192                 : 
     193                 :     /// Debug parameter: Enables expensive and thorough checking of the B+ tree
     194                 :     /// invariants after each insert/erase operation.
     195                 :     static const bool                   selfverify = traits::selfverify;
     196                 : 
     197                 :     /// Debug parameter: Prints out lots of debug information about how the
     198                 :     /// algorithms change the tree. Requires the header file to be compiled
     199                 :     /// with BTREE_PRINT and the key type must be std::ostream printable.
     200                 :     static const bool                   debug = traits::debug;
     201                 : 
     202                 : private:
     203                 :     // *** Node Classes for In-Memory Nodes
     204                 : 
     205                 :     /// The header structure of each node in-memory. This structure is extended
     206                 :     /// by inner_node or leaf_node.
     207                 :     struct node
     208              65 :     {
     209                 :         /// Level in the b-tree, if level == 0 -> leaf node
     210                 :         unsigned short  level;
     211                 : 
     212                 :         /// Number of key slotuse use, so number of valid children or data
     213                 :         /// pointers
     214                 :         unsigned short  slotuse;
     215                 : 
     216                 :         /// Delayed initialisation of constructed node
     217            8693 :         inline void initialize(const unsigned short l)
     218                 :         {
     219            8693 :             level = l;
     220            8693 :             slotuse = 0;
     221                 :         }
     222                 :         
     223                 :         /// True if this is a leaf node
     224        61849855 :         inline bool isleafnode() const
     225                 :         {
     226        61849855 :             return (level == 0);
     227                 :         }
     228                 :     };
     229                 : 
     230                 :     /// Extended structure of a inner node in-memory. Contains only keys and no
     231                 :     /// data items.
     232                 :     struct inner_node : public node
     233               9 :     {
     234                 :         /// Keys of children or data pointers
     235                 :         key_type        slotkey[innerslotmax];
     236                 : 
     237                 :         /// Pointers to children
     238                 :         node*           childid[innerslotmax+1];
     239                 : 
     240                 :         /// Set variables to initial values
     241            1537 :         inline void initialize(const unsigned short l)
     242                 :         {
     243            1537 :             node::initialize(l);
     244                 :         }
     245                 : 
     246                 :         /// True if the node's slots are full
     247            8191 :         inline bool isfull() const
     248                 :         {
     249            8191 :             return (node::slotuse == innerslotmax);
     250                 :         }
     251                 : 
     252                 :         /// True if few used entries, less than half full
     253            3488 :         inline bool isfew() const
     254                 :         {
     255            3488 :             return (node::slotuse <= mininnerslots);
     256                 :         }
     257                 : 
     258                 :         /// True if node has too few entries
     259        11803777 :         inline bool isunderflow() const
     260                 :         {
     261        11803777 :             return (node::slotuse < mininnerslots);
     262                 :         }
     263                 :     };
     264                 : 
     265                 :     /// Extended structure of a leaf node in memory. Contains pairs of keys and
     266                 :     /// data items. Key and data slots are kept in separate arrays, because the
     267                 :     /// key array is traversed very often compared to accessing the data items.
     268                 :     struct leaf_node : public node
     269              56 :     {
     270                 :         /// Double linked list pointers to traverse the leaves
     271                 :         leaf_node       *prevleaf;
     272                 : 
     273                 :         /// Double linked list pointers to traverse the leaves
     274                 :         leaf_node       *nextleaf;
     275                 : 
     276                 :         /// Keys of children or data pointers
     277                 :         key_type        slotkey[leafslotmax];
     278                 : 
     279                 :         /// Array of data
     280                 :         data_type       slotdata[leafslotmax];
     281                 : 
     282                 :         /// Set variables to initial values
     283            7156 :         inline void initialize()
     284                 :         {
     285            7156 :             node::initialize(0);
     286            7156 :             prevleaf = nextleaf = NULL;
     287                 :         }
     288                 : 
     289                 :         /// True if the node's slots are full
     290           30514 :         inline bool isfull() const
     291                 :         {
     292           30514 :             return (node::slotuse == leafslotmax);
     293                 :         }
     294                 : 
     295                 :         /// True if few used entries, less than half full
     296           13759 :         inline bool isfew() const
     297                 :         {
     298           13759 :             return (node::slotuse <= minleafslots);
     299                 :         }
     300                 : 
     301                 :         /// True if node has too few entries
     302        49332010 :         inline bool isunderflow() const
     303                 :         {
     304        49332010 :             return (node::slotuse < minleafslots);
     305                 :         }
     306                 :     };
     307                 : 
     308                 : private:
     309                 :     // *** Template Magic to Convert a pair or key/data types to a value_type
     310                 : 
     311                 :     /// \internal For sets the second pair_type is an empty struct, so the
     312                 :     /// value_type should only be the first.
     313                 :     template <typename value_type, typename pair_type>
     314                 :     struct btree_pair_to_value
     315                 :     {
     316                 :         /// Convert a fake pair type to just the first component
     317                 :         inline value_type operator()(pair_type& p) const {
     318                 :             return p.first;
     319                 :         }
     320                 :         /// Convert a fake pair type to just the first component
     321           16316 :         inline value_type operator()(const pair_type& p) const {
     322           16316 :             return p.first;
     323                 :         }
     324                 :     };
     325                 : 
     326                 :     /// \internal For maps value_type is the same as the pair_type
     327                 :     template <typename value_type>
     328                 :     struct btree_pair_to_value<value_type, value_type>
     329                 :     {
     330                 :         /// Identity "convert" a real pair type to just the first component
     331                 :         inline value_type operator()(pair_type& p) const {
     332                 :             return p;
     333                 :         }
     334                 :         /// Identity "convert" a real pair type to just the first component
     335               0 :         inline value_type operator()(const pair_type& p) const {
     336               0 :             return p;
     337                 :         }
     338                 :     };
     339                 : 
     340                 :     /// Using template specialization select the correct converter used by the
     341                 :     /// iterators
     342                 :     typedef btree_pair_to_value<value_type, pair_type> pair_to_value_type;
     343                 : 
     344                 : public:
     345                 :     // *** Iterators and Reverse Iterators
     346                 : 
     347                 :     class iterator;
     348                 :     class const_iterator;
     349                 : 
     350                 :     /// STL-like iterator object for B+ tree items. The iterator points to a
     351                 :     /// specific slot number in a leaf.
     352                 :     class iterator
     353                 :     {
     354                 :     public:
     355                 :         // *** Types
     356                 : 
     357                 :         /// The key type of the btree. Returned by key().
     358                 :         typedef typename btree::key_type                key_type;
     359                 : 
     360                 :         /// The data type of the btree. Returned by data().
     361                 :         typedef typename btree::data_type               data_type;
     362                 : 
     363                 :         /// The value type of the btree. Returned by operator*().
     364                 :         typedef typename btree::value_type              value_type;
     365                 : 
     366                 :         /// The pair type of the btree.
     367                 :         typedef typename btree::pair_type               pair_type;
     368                 : 
     369                 :         /// Reference to the value_type. Required by the reverse_iterator.
     370                 :         typedef value_type&         reference;
     371                 : 
     372                 :         /// Pointer to the value_type. Required by the reverse_iterator.
     373                 :         typedef value_type*             pointer;
     374                 : 
     375                 :         /// STL-magic iterator category
     376                 :         typedef std::bidirectional_iterator_tag iterator_category;
     377                 : 
     378                 :         /// STL-magic
     379                 :         typedef ptrdiff_t               difference_type;
     380                 : 
     381                 :         /// Our own type
     382                 :         typedef iterator                self;
     383                 : 
     384                 :     private:
     385                 :         // *** Members
     386                 : 
     387                 :         /// The currently referenced leaf node of the tree
     388                 :         typename btree::leaf_node*      currnode;
     389                 : 
     390                 :         /// Current key/data slot referenced
     391                 :         unsigned short  currslot;
     392                 :     
     393                 :         /// Friendly to the const_iterator, so it may access the two data items directly
     394                 :         friend class btree<key_type, data_type, value_type, key_compare, traits, allow_duplicates>::const_iterator;
     395                 :         
     396                 :         /// Evil! A temporary value_type to STL-correctly deliver operator* and
     397                 :         /// operator->
     398                 :         mutable value_type              temp_value;
     399                 : 
     400                 :     public:
     401                 :         // *** Methods
     402                 : 
     403                 :         /// Constructor of a mutable iterator
     404           51852 :         inline iterator(typename btree::leaf_node *l, unsigned short s)
     405           51852 :             : currnode(l), currslot(s)
     406           51852 :         { }
     407                 : 
     408                 :         /// Dereference the iterator, this is not a value_type& because key and
     409                 :         /// value are not stored together
     410            9600 :         inline reference operator*() const
     411                 :         {
     412            9600 :             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
     413                 :                                                          currnode->slotdata[currslot]) );
     414            9600 :             return temp_value;
     415                 :         }
     416                 : 
     417                 :         /// Dereference the iterator. Do not use this if possible, use key()
     418                 :         /// and data() instead. The B+ tree does not stored key and data
     419                 :         /// together.
     420                 :         inline pointer operator->() const
     421                 :         {
     422                 :             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
     423                 :                                                          currnode->slotdata[currslot]) );
     424                 :             return &temp_value;
     425                 :         }
     426                 : 
     427                 :         /// Key of the current slot
     428           17360 :         inline const key_type& key() const
     429                 :         {
     430           17360 :             return currnode->slotkey[currslot];
     431                 :         }
     432                 : 
     433                 :         /// Writable reference to the current data object
     434               0 :         inline data_type& data() const
     435                 :         {
     436               0 :             return currnode->slotdata[currslot];
     437                 :         }
     438                 : 
     439                 :         /// Prefix++ advance the iterator to the next slot
     440           23760 :         inline self& operator++()
     441                 :         {
     442           23760 :             if (currslot + 1 < currnode->slotuse) {
     443           18365 :                 ++currslot;
     444                 :             }
     445            5395 :             else if (currnode->nextleaf != NULL) {
     446            5387 :                 currnode = currnode->nextleaf;
     447            5387 :                 currslot = 0;
     448                 :             }
     449                 :             else {
     450                 :                 // this is end()
     451               8 :                 currslot = currnode->slotuse;
     452                 :             }
     453                 : 
     454           23760 :             return *this;
     455                 :         }
     456                 : 
     457                 :         /// Postfix++ advance the iterator to the next slot
     458                 :         inline self operator++(int)
     459                 :         {
     460                 :             self tmp = *this;   // copy ourselves
     461                 : 
     462                 :             if (currslot + 1 < currnode->slotuse) {
     463                 :                 ++currslot;
     464                 :             }
     465                 :             else if (currnode->nextleaf != NULL) {
     466                 :                 currnode = currnode->nextleaf;
     467                 :                 currslot = 0;
     468                 :             }
     469                 :             else {
     470                 :                 // this is end()
     471                 :                 currslot = currnode->slotuse;
     472                 :             }
     473                 : 
     474                 :             return tmp;
     475                 :         }
     476                 : 
     477                 :         /// Prefix-- backstep the iterator to the last slot
     478           16000 :         inline self& operator--()
     479                 :         {
     480           16000 :             if (currslot > 0) {
     481           13150 :                 --currslot;
     482                 :             }
     483            2850 :             else if (currnode->prevleaf != NULL) {
     484            2850 :                 currnode = currnode->prevleaf;
     485            2850 :                 currslot = currnode->slotuse - 1;
     486                 :             }
     487                 :             else {
     488                 :                 // this is begin()
     489               0 :                 currslot = 0;
     490                 :             }
     491                 : 
     492           16000 :             return *this;
     493                 :         }
     494                 : 
     495                 :         /// Postfix-- backstep the iterator to the last slot
     496                 :         inline self operator--(int)
     497                 :         {
     498                 :             self tmp = *this;   // copy ourselves
     499                 : 
     500                 :             if (currslot > 0) {
     501                 :                 --currslot;
     502                 :             }
     503                 :             else if (currnode->prevleaf != NULL) {
     504                 :                 currnode = currnode->prevleaf;
     505                 :                 currslot = currnode->slotuse - 1;
     506                 :             }
     507                 :             else {
     508                 :                 // this is begin()
     509                 :                 currslot = 0;
     510                 :             }
     511                 : 
     512                 :             return tmp;
     513                 :         }
     514                 : 
     515                 :         /// Equality of iterators
     516            6410 :         inline bool operator==(const self& x) const
     517                 :         {
     518            6410 :             return (x.currnode == currnode) && (x.currslot == currslot);
     519                 :         }
     520                 : 
     521                 :         /// Inequality of iterators
     522           23768 :         inline bool operator!=(const self& x) const
     523                 :         {
     524           23768 :             return (x.currnode != currnode) || (x.currslot != currslot);
     525                 :         }    
     526                 :     };
     527                 : 
     528                 :     /// STL-like read-only iterator object for B+ tree items. The iterator
     529                 :     /// points to a specific slot number in a leaf.
     530                 :     class const_iterator
     531                 :     {
     532                 :     public:
     533                 :         // *** Types
     534                 : 
     535                 :         /// The key type of the btree. Returned by key().
     536                 :         typedef typename btree::key_type                key_type;
     537                 : 
     538                 :         /// The data type of the btree. Returned by data().
     539                 :         typedef typename btree::data_type               data_type;
     540                 : 
     541                 :         /// The value type of the btree. Returned by operator*().
     542                 :         typedef typename btree::value_type              value_type;
     543                 : 
     544                 :         /// The pair type of the btree.
     545                 :         typedef typename btree::pair_type               pair_type;
     546                 : 
     547                 :         /// Reference to the value_type. Required by the reverse_iterator.
     548                 :         typedef const value_type&   reference;
     549                 : 
     550                 :         /// Pointer to the value_type. Required by the reverse_iterator.
     551                 :         typedef const value_type*       pointer;
     552                 : 
     553                 :         /// STL-magic iterator category
     554                 :         typedef std::bidirectional_iterator_tag iterator_category;
     555                 : 
     556                 :         /// STL-magic
     557                 :         typedef ptrdiff_t               difference_type;
     558                 : 
     559                 :         /// Our own type
     560                 :         typedef const_iterator          self;
     561                 : 
     562                 :     private:
     563                 :         // *** Members
     564                 : 
     565                 :         /// The currently referenced leaf node of the tree
     566                 :         const typename btree::leaf_node*        currnode;
     567                 : 
     568                 :         /// Current key/data slot referenced
     569                 :         unsigned short  currslot;
     570                 :     
     571                 :         /// Evil! A temporary value_type to STL-correctly deliver operator* and
     572                 :         /// operator->
     573                 :         mutable value_type              temp_value;
     574                 : 
     575                 :     public:
     576                 :         // *** Methods
     577                 : 
     578                 :         /// Constructor of a const iterator
     579              31 :         inline const_iterator(const typename btree::leaf_node *l, unsigned short s)
     580              31 :             : currnode(l), currslot(s)
     581              31 :         { }
     582                 : 
     583                 :         /// Copy-constructor from a mutable const iterator
     584            9680 :         inline const_iterator(const iterator &it)
     585            9680 :             : currnode(it.currnode), currslot(it.currslot)
     586            9680 :         { }
     587                 : 
     588                 :         /// Dereference the iterator. Do not use this if possible, use key()
     589                 :         /// and data() instead. The B+ tree does not stored key and data
     590                 :         /// together.
     591            6716 :         inline reference operator*() const
     592                 :         {
     593            6716 :             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
     594                 :                                                          currnode->slotdata[currslot]) );
     595            6716 :             return temp_value;
     596                 :         }
     597                 : 
     598                 :         /// Dereference the iterator. Do not use this if possible, use key()
     599                 :         /// and data() instead. The B+ tree does not stored key and data
     600                 :         /// together.
     601                 :         inline pointer operator->() const
     602                 :         {
     603                 :             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
     604                 :                                                          currnode->slotdata[currslot]) );
     605                 :             return &temp_value;
     606                 :         }
     607                 : 
     608                 :         /// Key of the current slot
     609            4024 :         inline const key_type& key() const
     610                 :         {
     611            4024 :             return currnode->slotkey[currslot];
     612                 :         }
     613                 : 
     614                 :         /// Read-only reference to the current data object
     615                 :         inline const data_type& data() const
     616                 :         {
     617                 :             return currnode->slotdata[currslot];
     618                 :         }
     619                 : 
     620                 :         /// Prefix++ advance the iterator to the next slot
     621            4796 :         inline self& operator++()
     622                 :         {
     623            4796 :             if (currslot + 1 < currnode->slotuse) {
     624            3962 :                 ++currslot;
     625                 :             }
     626             834 :             else if (currnode->nextleaf != NULL) {
     627             822 :                 currnode = currnode->nextleaf;
     628             822 :                 currslot = 0;
     629                 :             }
     630                 :             else {
     631                 :                 // this is end()
     632              12 :                 currslot = currnode->slotuse;
     633                 :             }
     634                 : 
     635            4796 :             return *this;
     636                 :         }
     637                 : 
     638                 :         /// Postfix++ advance the iterator to the next slot
     639                 :         inline self operator++(int)
     640                 :         {
     641                 :             self tmp = *this;   // copy ourselves
     642                 : 
     643                 :             if (currslot + 1 < currnode->slotuse) {
     644                 :                 ++currslot;
     645                 :             }
     646                 :             else if (currnode->nextleaf != NULL) {
     647                 :                 currnode = currnode->nextleaf;
     648                 :                 currslot = 0;
     649                 :             }
     650                 :             else {
     651                 :                 // this is end()
     652                 :                 currslot = currnode->slotuse;
     653                 :             }
     654                 : 
     655                 :             return tmp;
     656                 :         }
     657                 : 
     658                 :         /// Prefix-- backstep the iterator to the last slot
     659                 :         inline self& operator--()
     660                 :         {
     661                 :             if (currslot > 0) {
     662                 :                 --currslot;
     663                 :             }
     664                 :             else if (currnode->prevleaf != NULL) {
     665                 :                 currnode = currnode->prevleaf;
     666                 :                 currslot = currnode->slotuse - 1;
     667                 :             }
     668                 :             else {
     669                 :                 // this is begin()
     670                 :                 currslot = 0;
     671                 :             }
     672                 : 
     673                 :             return *this;
     674                 :         }
     675                 : 
     676                 :         /// Postfix-- backstep the iterator to the last slot
     677                 :         inline self operator--(int)
     678                 :         {
     679                 :             self tmp = *this;   // copy ourselves
     680                 : 
     681                 :             if (currslot > 0) {
     682                 :                 --currslot;
     683                 :             }
     684                 :             else if (currnode->prevleaf != NULL) {
     685                 :                 currnode = currnode->prevleaf;
     686                 :                 currslot = currnode->slotuse - 1;
     687                 :             }
     688                 :             else {
     689                 :                 // this is begin()
     690                 :                 currslot = 0;
     691                 :             }
     692                 : 
     693                 :             return tmp;
     694                 :         }
     695                 : 
     696                 :         /// Equality of iterators
     697            4842 :         inline bool operator==(const self& x) const
     698                 :         {
     699            4842 :             return (x.currnode == currnode) && (x.currslot == currslot);
     700                 :         }
     701                 : 
     702                 :         /// Inequality of iterators
     703            3367 :         inline bool operator!=(const self& x) const
     704                 :         {
     705            3367 :             return (x.currnode != currnode) || (x.currslot != currslot);
     706                 :         }    
     707                 :     };
     708                 : 
     709                 :     /// create mutable reverse iterator by using STL magic
     710                 :     typedef std::reverse_iterator<iterator>       reverse_iterator;
     711                 : 
     712                 :     /// create constant reverse iterator by using STL magic
     713                 :     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
     714                 : 
     715                 : public:
     716                 :     // *** Small Statistics Structure
     717                 : 
     718                 :     /** A small struct containing basic statistics about the B+ tree. It can be
     719                 :      * fetched using get_stats(). */
     720                 :     struct tree_stats
     721                 :     {
     722                 :         /// Number of items in the B+ tree
     723                 :         size_type       itemcount;
     724                 : 
     725                 :         /// Number of leaves in the B+ tree
     726                 :         size_type       leaves;
     727                 : 
     728                 :         /// Number of inner nodes in the B+ tree
     729                 :         size_type       innernodes;
     730                 : 
     731                 :         /// Base B+ tree parameter: The number of key/data slots in each leaf
     732                 :         static const unsigned short     leafslots = btree_self::leafslotmax;
     733                 : 
     734                 :         /// Base B+ tree parameter: The number of key slots in each inner node.
     735                 :         static const unsigned short     innerslots = btree_self::innerslotmax;
     736                 : 
     737                 :         /// Zero initialized
     738           66713 :         inline tree_stats()
     739                 :             : itemcount(0),
     740           66713 :               leaves(0), innernodes(0)
     741           66713 :         {
     742                 :         }
     743                 : 
     744                 :         /// Return the total number of nodes
     745                 :         inline size_type nodes() const
     746                 :         {
     747                 :             return innernodes + leaves;
     748                 :         }
     749                 : 
     750                 :         /// Return the average fill of leaves
     751                 :         inline double avgfill_leaves() const
     752                 :         {
     753                 :             return static_cast<double>(itemcount) / (leaves * leafslots);
     754                 :         }
     755                 :     };
     756                 : 
     757                 : private:
     758                 :     // *** Tree Object Data Members
     759                 : 
     760                 :     /// Pointer to the B+ tree's root node, either leaf or inner node
     761                 :     node*       root;
     762                 : 
     763                 :     /// Pointer to first leaf in the double linked leaf chain
     764                 :     leaf_node   *headleaf;
     765                 : 
     766                 :     /// Pointer to last leaf in the double linked leaf chain
     767                 :     leaf_node   *tailleaf;
     768                 : 
     769                 :     /// Other small statistics about the B+ tree
     770                 :     tree_stats  stats;
     771                 : 
     772                 :     /// Key comparison object. More comparison functions are generated from
     773                 :     /// this < relation.
     774                 :     key_compare key_less;
     775                 : 
     776                 : public:
     777                 :     // *** Constructors and Destructor
     778                 : 
     779                 :     /// Default constructor initializing an empty B+ tree with the standard key
     780                 :     /// comparison function
     781              15 :     inline btree()
     782              15 :         : root(NULL), headleaf(NULL), tailleaf(NULL)
     783              15 :     {
     784                 :     }
     785                 : 
     786                 :     /// Constructor initializing an empty B+ tree with a special key
     787                 :     /// comparison object
     788               1 :     inline btree(const key_compare &kcf)
     789                 :         : root(NULL), headleaf(NULL), tailleaf(NULL),
     790               1 :           key_less(kcf)
     791               1 :     {
     792                 :     }
     793                 : 
     794                 :     /// Constructor initializing a B+ tree with the range [first,last)
     795                 :     template <class InputIterator>
     796                 :     inline btree(InputIterator first, InputIterator last)
     797                 :         : root(NULL), headleaf(NULL), tailleaf(NULL)
     798                 :     {
     799                 :         insert(first, last);
     800                 :     }
     801                 : 
     802                 :     /// Constructor initializing a B+ tree with the range [first,last) and a
     803                 :     /// special key comparison object
     804                 :     template <class InputIterator>
     805                 :     inline btree(InputIterator first, InputIterator last, const key_compare &kcf)
     806                 :         : root(NULL), headleaf(NULL), tailleaf(NULL),
     807                 :           key_less(kcf)
     808                 :     {
     809                 :         insert(first, last);
     810                 :     }
     811                 : 
     812                 :     /// Frees up all used B+ tree memory pages
     813              18 :     inline ~btree()
     814                 :     {
     815              18 :         clear();
     816                 :     }
     817                 : 
     818                 :     /// Fast swapping of two identical B+ tree objects.
     819                 :     void swap(btree_self& from)
     820                 :     {
     821                 :         std::swap(root, from.root);
     822                 :         std::swap(headleaf, from.headleaf);
     823                 :         std::swap(tailleaf, from.tailleaf);
     824                 :         std::swap(stats, from.stats);
     825                 :         std::swap(key_less, from.key_less);
     826                 :     }
     827                 : 
     828                 : public:
     829                 :     // *** Key and Value Comparison Function Objects
     830                 : 
     831                 :     /// Function class to compare value_type objects. Required by the STL
     832                 :     class value_compare
     833                 :     {
     834                 :     protected:
     835                 :         /// Key comparison function from the template parameter
     836                 :         key_compare     key_comp;
     837                 :  
     838                 :         /// Constructor called from btree::value_comp()
     839               0 :         inline value_compare(key_compare kc)
     840               0 :             : key_comp(kc)
     841               0 :         { }
     842                 : 
     843                 :         /// Friendly to the btree class so it may call the constructor
     844                 :         friend class btree<key_type, data_type, value_type, key_compare, traits, allow_duplicates>;
     845                 :  
     846                 :     public:
     847                 :         /// Function call "less"-operator resulting in true if x < y.
     848                 :         inline bool operator()(const value_type& x, const value_type& y) const
     849                 :         {
     850                 :             return key_comp(x.first, y.first);
     851                 :         }
     852                 :     };
     853                 : 
     854                 :     /// Constant access to the key comparison object sorting the B+ tree
     855               3 :     inline key_compare key_comp() const
     856                 :     {
     857               3 :         return key_less;
     858                 :     }
     859                 : 
     860                 :     /// Constant access to a constructed value_type comparison object. Required
     861                 :     /// by the STL
     862               0 :     inline value_compare value_comp() const
     863                 :     {
     864               0 :         return value_compare(key_less);
     865                 :     }
     866                 : 
     867                 : private:
     868                 :     // *** Convenient Key Comparison Functions Generated From key_less
     869                 : 
     870                 :     /// True if a <= b ? constructed from key_less()
     871       395638602 :     inline bool key_lessequal(const key_type &a, const key_type b) const
     872                 :     {
     873       395638602 :         return !key_less(b, a);
     874                 :     }
     875                 : 
     876                 :     /// True if a > b ? constructed from key_less()
     877                 :     inline bool key_greater(const key_type &a, const key_type &b) const
     878                 :     {
     879                 :         return key_less(b, a);
     880                 :     }
     881                 : 
     882                 :     /// True if a >= b ? constructed from key_less()
     883        49244640 :     inline bool key_greaterequal(const key_type &a, const key_type b) const
     884                 :     {
     885        49244640 :         return !key_less(a, b);
     886                 :     }
     887                 : 
     888                 :     /// True if a == b ? constructed from key_less(). This requires the <
     889                 :     /// relation to be a total order, otherwise the B+ tree cannot be sorted.
     890        52455581 :     inline bool key_equal(const key_type &a, const key_type &b) const
     891                 :     {
     892        52455581 :         return !key_less(a, b) && !key_less(b, a);
     893                 :     }
     894                 : 
     895                 : private:
     896                 :     // *** Node Object Allocation and Deallocation Functions
     897                 : 
     898                 :     /// Allocate and initialize a leaf node
     899            7156 :     inline leaf_node* allocate_leaf()
     900                 :     {
     901            7156 :         leaf_node* n = new leaf_node;
     902            7156 :         n->initialize();
     903            7156 :         stats.leaves++;
     904            7156 :         return n;
     905                 :     }
     906                 : 
     907                 :     /// Allocate and initialize an inner node
     908            1537 :     inline inner_node* allocate_inner(unsigned short l)
     909                 :     {
     910            1537 :         inner_node* n = new inner_node;
     911            1537 :         n->initialize(l);
     912            1537 :         stats.innernodes++;
     913            1537 :         return n;
     914                 :     }
     915                 :     
     916                 :     /// Correctly free either inner or leaf node, destructs all contained key
     917                 :     /// and value objects
     918            8693 :     inline void free_node(node *n)
     919                 :     {
     920            8693 :         if (n->isleafnode()) {
     921            7156 :             delete static_cast<leaf_node*>(n);
     922            7156 :             stats.leaves--;
     923                 :         }
     924                 :         else {
     925            1537 :             delete static_cast<inner_node*>(n);
     926            1537 :             stats.innernodes--;
     927                 :         }
     928                 :     }
     929                 : 
     930                 : public:
     931                 :     // *** Fast Destruction of the B+ Tree
     932                 : 
     933                 :     /// Frees all key/data pairs and all nodes of the tree
     934              20 :     void clear()
     935                 :     {
     936              20 :         if (root)
     937                 :         {
     938              17 :             clear_recursive(root);
     939              17 :             free_node(root);
     940                 : 
     941              17 :             root = NULL;
     942              17 :             headleaf = tailleaf = NULL;
     943                 : 
     944              17 :             stats = tree_stats();
     945                 :         }
     946                 : 
     947              20 :         BTREE_ASSERT(stats.itemcount == 0);
     948                 :     }
     949                 : 
     950                 : private:
     951                 :     /// Recursively free up nodes
     952            2676 :     void clear_recursive(node *n)
     953                 :     {
     954            2676 :         if (n->isleafnode())
     955                 :         {
     956            2273 :             leaf_node *leafnode = static_cast<leaf_node*>(n);
     957                 : 
     958            2273 :             for (unsigned int slot = 0; slot < leafnode->slotuse; ++slot)
     959                 :             {
     960                 :                 // data objects are deleted by leaf_node's destructor
     961                 :             }
     962                 :         }
     963                 :         else
     964                 :         {
     965             403 :             inner_node *innernode = static_cast<inner_node*>(n);
     966                 : 
     967            3062 :             for (unsigned short slot = 0; slot < innernode->slotuse + 1; ++slot)
     968                 :             {
     969            2659 :                 clear_recursive(innernode->childid[slot]);
     970            5335 :                 free_node(innernode->childid[slot]);
     971                 :             }
     972                 :         }
     973                 :     }
     974                 : 
     975                 : public:
     976                 :     // *** STL Iterator Construction Functions
     977                 : 
     978                 :     /// Constructs a read/data-write iterator that points to the first slot in
     979                 :     /// the first leaf of the B+ tree.
     980               9 :     inline iterator begin()
     981                 :     {
     982               9 :         return iterator(headleaf, 0);
     983                 :     }
     984                 : 
     985                 :     /// Constructs a read/data-write iterator that points to the first invalid
     986                 :     /// slot in the last leaf of the B+ tree.
     987           22215 :     inline iterator end()
     988                 :     {
     989           22215 :         return iterator(tailleaf, tailleaf->slotuse);
     990                 :     }
     991                 : 
     992                 :     /// Constructs a read-only constant iterator that points to the first slot
     993                 :     /// in the first leaf of the B+ tree.
     994              18 :     inline const_iterator begin() const
     995                 :     {
     996              18 :         return const_iterator(headleaf, 0);
     997                 :     }
     998                 : 
     999                 :     /// Constructs a read-only constant iterator that points to the first
    1000                 :     /// invalid slot in the last leaf of the B+ tree.
    1001              13 :     inline const_iterator end() const
    1002                 :     {
    1003              13 :         return const_iterator(tailleaf, tailleaf->slotuse);
    1004                 :     }
    1005                 : 
    1006                 :     /// Constructs a read/data-write reverse iterator that points to the first
    1007                 :     /// invalid slot in the last leaf of the B+ tree. Uses STL magic.
    1008               2 :     inline reverse_iterator rbegin()
    1009                 :     {
    1010               2 :         return reverse_iterator(end());
    1011                 :     }
    1012                 : 
    1013                 :     /// Constructs a read/data-write reverse iterator that points to the first
    1014                 :     /// slot in the first leaf of the B+ tree. Uses STL magic.
    1015               2 :     inline reverse_iterator rend()
    1016                 :     {
    1017               2 :         return reverse_iterator(begin());
    1018                 :     }
    1019                 : 
    1020                 :     /// Constructs a read-only reverse iterator that points to the first
    1021                 :     /// invalid slot in the last leaf of the B+ tree. Uses STL magic.
    1022               0 :     inline const_reverse_iterator rbegin() const
    1023                 :     {
    1024               0 :         return const_reverse_iterator(end());
    1025                 :     }
    1026                 : 
    1027                 :     /// Constructs a read-only reverse iterator that points to the first slot
    1028                 :     /// in the first leaf of the B+ tree. Uses STL magic.
    1029               0 :     inline const_reverse_iterator rend() const
    1030                 :     {
    1031               0 :         return const_reverse_iterator(begin());
    1032                 :     }
    1033                 : 
    1034                 : private:
    1035                 :     // *** B+ Tree Node Binary Search Functions
    1036                 : 
    1037                 :     /// Searches for the first key in the node n less or equal to key. Uses
    1038                 :     /// binary search with an optional linear self-verification. This is a
    1039                 :     /// template function, because the slotkey array is located at different
    1040                 :     /// places in leaf_node and inner_node.
    1041                 :     template <typename node_type>
    1042          712539 :     inline int find_lower(const node_type *n, const key_type& key) const
    1043                 :     {
    1044          712539 :         if (n->slotuse == 0) return 0;
    1045                 : 
    1046          712526 :         int lo = 0,
    1047          712526 :             hi = n->slotuse - 1;
    1048                 : 
    1049         2655710 :         while(lo < hi)
    1050                 :         {
    1051         1230658 :             int mid = (lo + hi) / 2;
    1052                 : 
    1053         1230658 :             if (key_lessequal(key, n->slotkey[mid])) {
    1054          573768 :                 hi = mid - 1;
    1055                 :             }
    1056                 :             else {
    1057          656890 :                 lo = mid + 1;
    1058                 :             }
    1059                 :         }
    1060                 : 
    1061          712526 :         if (hi < 0 || key_less(n->slotkey[hi], key))
    1062          422444 :             hi++;
    1063                 : 
    1064                 :         BTREE_PRINT("btree::find_lower: on " << n << " key " << key << " -> (" << lo << ") " << hi << ", ");
    1065                 : 
    1066                 :         // verify result using simple linear search
    1067                 :         if (selfverify)
    1068                 :         {
    1069          712526 :             int i = n->slotuse - 1;
    1070         3399314 :             while(i >= 0 && key_lessequal(key, n->slotkey[i]))
    1071         1974262 :                 i--;
    1072          712526 :             i++;
    1073                 : 
    1074                 :             BTREE_PRINT("testfind: " << i << std::endl);
    1075          712526 :             BTREE_ASSERT(i == hi);
    1076                 :         }
    1077                 :         else {
    1078                 :             BTREE_PRINT(std::endl);
    1079                 :         }
    1080                 :         
    1081          712526 :         return hi;
    1082                 :     }
    1083                 : 
    1084                 :     /// Searches for the first key in the node n greater than key. Uses binary
    1085                 :     /// search with an optional linear self-verification. This is a template
    1086                 :     /// function, because the slotkey array is located at different places in
    1087                 :     /// leaf_node and inner_node.
    1088                 :     template <typename node_type>
    1089            7700 :     inline int find_upper(const node_type *n, const key_type& key) const
    1090                 :     {
    1091            7700 :         if (n->slotuse == 0) return 0;
    1092                 : 
    1093            7700 :         int lo = 0,
    1094            7700 :             hi = n->slotuse - 1;
    1095                 : 
    1096           30732 :         while(lo < hi)
    1097                 :         {
    1098           15332 :             int mid = (lo + hi) / 2;
    1099                 : 
    1100           15332 :             if (key_less(key, n->slotkey[mid])) {
    1101            6026 :                 hi = mid - 1;
    1102                 :             }
    1103                 :             else {
    1104            9306 :                 lo = mid + 1;
    1105                 :             }
    1106                 :         }
    1107                 : 
    1108            7700 :         if (hi < 0 || key_lessequal(n->slotkey[hi], key))
    1109            4748 :             hi++;
    1110                 : 
    1111                 :         BTREE_PRINT("btree::find_upper: on " << n << " key " << key << " -> (" << lo << ") " << hi << ", ");
    1112                 : 
    1113                 :         // verify result using simple linear search
    1114                 :         if (selfverify)
    1115                 :         {
    1116            7700 :             int i = n->slotuse - 1;
    1117           36122 :             while(i >= 0 && key_less(key, n->slotkey[i]))
    1118           20722 :                 i--;
    1119            7700 :             i++;
    1120                 : 
    1121                 :             BTREE_PRINT("btree::find_upper testfind: " << i << std::endl);
    1122            7700 :             BTREE_ASSERT(i == hi);
    1123                 :         }
    1124                 :         else {
    1125                 :             BTREE_PRINT(std::endl);
    1126                 :         }
    1127                 :         
    1128            7700 :         return hi;
    1129                 :     }
    1130                 : 
    1131                 : public:
    1132                 :     // *** Access Functions to the Item Count
    1133                 : 
    1134                 :     /// Return the number of key/data pairs in the B+ tree
    1135          144086 :     inline size_type size() const
    1136                 :     {
    1137          144086 :         return stats.itemcount;
    1138                 :     }
    1139                 : 
    1140                 :     /// Returns true if there is at least one key/data pair in the B+ tree
    1141               7 :     inline bool empty() const
    1142                 :     {
    1143               7 :         return (size() == size_type(0));
    1144                 :     }
    1145                 :     
    1146                 :     /// Returns the largest possible size of the B+ Tree. This is just a
    1147                 :     /// function required by the STL standard, the B+ Tree can hold more items.
    1148               0 :     inline size_type max_size() const
    1149                 :     {
    1150               0 :         return size_type(-1);
    1151                 :     }
    1152                 : 
    1153                 :     /// Return a const reference to the current statistics.
    1154               0 :     inline const struct tree_stats& get_stats() const
    1155                 :     {
    1156               0 :         return stats;
    1157                 :     }
    1158                 : 
    1159                 : public:
    1160                 :     // *** Standard Access Functions Querying the Tree by Descending to a Leaf
    1161                 : 
    1162                 :     /// Non-STL function checking whether a key is in the B+ tree. The same as
    1163                 :     /// (find(k) != end()) or (count() != 0).
    1164           62708 :     bool exists(const key_type &key) const
    1165                 :     {
    1166           62708 :         const node *n = root;
    1167                 : 
    1168           62708 :         if (!n) return false;
    1169                 : 
    1170          373026 :         while(!n->isleafnode())
    1171                 :         {
    1172          247610 :             const inner_node *inner = static_cast<const inner_node*>(n);
    1173          247610 :             int slot = find_lower(inner, key);
    1174                 : 
    1175          247610 :             n = inner->childid[slot];
    1176                 :         }
    1177                 : 
    1178           62708 :         const leaf_node *leaf = static_cast<const leaf_node*>(n);
    1179                 : 
    1180           62708 :         int slot = find_lower(leaf, key);
    1181           62708 :         return key_equal(key, leaf->slotkey[slot]);
    1182                 :     }
    1183                 : 
    1184                 :     /// Tries to locate a key in the B+ tree and returns an iterator to the
    1185                 :     /// key/data slot if found. If unsuccessful it returns end().
    1186               0 :     iterator find(const key_type &key)
    1187                 :     {
    1188               0 :         node *n = root;
    1189               0 :         if (!n) return end();
    1190                 : 
    1191               0 :         while(!n->isleafnode())
    1192                 :         {
    1193               0 :             const inner_node *inner = static_cast<const inner_node*>(n);
    1194               0 :             int slot = find_lower(inner, key);
    1195                 : 
    1196               0 :             n = inner->childid[slot];
    1197                 :         }
    1198                 : 
    1199               0 :         leaf_node *leaf = static_cast<leaf_node*>(n);
    1200                 : 
    1201               0 :         int slot = find_lower(leaf, key);
    1202               0 :         return key_equal(key, leaf->slotkey[slot]) ? iterator(leaf, slot) : end();
    1203                 :     }
    1204                 : 
    1205                 :     /// Tries to locate a key in the B+ tree and returns an constant iterator
    1206                 :     /// to the key/data slot if found. If unsuccessful it returns end().
    1207               0 :     const_iterator find(const key_type &key) const
    1208                 :     {
    1209               0 :         const node *n = root;
    1210               0 :         if (!n) return end();
    1211                 : 
    1212               0 :         while(!n->isleafnode())
    1213                 :         {
    1214               0 :             const inner_node *inner = static_cast<const inner_node*>(n);
    1215               0 :             int slot = find_lower(inner, key);
    1216                 : 
    1217               0 :             n = inner->childid[slot];
    1218                 :         }
    1219                 : 
    1220               0 :         const leaf_node *leaf = static_cast<const leaf_node*>(n);
    1221                 : 
    1222               0 :         int slot = find_lower(leaf, key);
    1223               0 :         return key_equal(key, leaf->slotkey[slot]) ? const_iterator(leaf, slot) : end();
    1224                 :     }
    1225                 : 
    1226                 :     /// Tries to locate a key in the B+ tree and returns the number of
    1227                 :     /// identical key entries found.    
    1228           34720 :     size_type count(const key_type &key) const
    1229                 :     {
    1230           34720 :         const node *n = root;
    1231           34720 :         if (!n) return 0;
    1232                 : 
    1233          214767 :         while(!n->isleafnode())
    1234                 :         {
    1235          145327 :             const inner_node *inner = static_cast<const inner_node*>(n);
    1236          145327 :             int slot = find_lower(inner, key);
    1237                 : 
    1238          145327 :             n = inner->childid[slot];
    1239                 :         }
    1240                 : 
    1241           34720 :         const leaf_node *leaf = static_cast<const leaf_node*>(n);
    1242                 : 
    1243           34720 :         int slot = find_lower(leaf, key);
    1244           34720 :         size_type num = 0;
    1245                 : 
    1246         3173397 :         while (leaf && key_equal(key, leaf->slotkey[slot]))
    1247                 :         {
    1248         3103957 :             ++num;
    1249         3103957 :             if (++slot >= leaf->slotuse)
    1250                 :             {
    1251          775421 :                 leaf = leaf->nextleaf;
    1252          775421 :                 slot = 0;
    1253                 :             }
    1254                 :         }
    1255                 : 
    1256           34720 :         return num;
    1257                 :     }
    1258                 : 
    1259                 :     /// Searches the B+ tree and returns an iterator to the first key less or
    1260                 :     /// equal to the parameter. If unsuccessful it returns end().
    1261            2420 :     iterator lower_bound(const key_type& key)
    1262                 :     {
    1263            2420 :         node *n = root;
    1264            2420 :         if (!n) return end();
    1265                 : 
    1266           10120 :         while(!n->isleafnode())
    1267                 :         {
    1268            5280 :             const inner_node *inner = static_cast<const inner_node*>(n);
    1269            5280 :             int slot = find_lower(inner, key);
    1270                 : 
    1271            5280 :             n = inner->childid[slot];
    1272                 :         }
    1273                 : 
    1274            2420 :         leaf_node *leaf = static_cast<leaf_node*>(n);
    1275                 : 
    1276            2420 :         int slot = find_lower(leaf, key);
    1277            2420 :         return iterator(leaf, slot);
    1278                 :     }
    1279                 : 
    1280                 :     /// Searches the B+ tree and returns an constant iterator to the first key less or
    1281                 :     /// equal to the parameter. If unsuccessful it returns end().
    1282               0 :     const_iterator lower_bound(const key_type& key) const
    1283                 :     {
    1284               0 :         const node *n = root;
    1285               0 :         if (!n) return end();
    1286                 : 
    1287               0 :         while(!n->isleafnode())
    1288                 :         {
    1289               0 :             const inner_node *inner = static_cast<const inner_node*>(n);
    1290               0 :             int slot = find_lower(inner, key);
    1291                 : 
    1292               0 :             n = inner->childid[slot];
    1293                 :         }
    1294                 : 
    1295               0 :         const leaf_node *leaf = static_cast<const leaf_node*>(n);
    1296                 : 
    1297               0 :         int slot = find_lower(leaf, key);
    1298               0 :         return const_iterator(leaf, slot);
    1299                 :     }
    1300                 : 
    1301                 :     /// Searches the B+ tree and returns an iterator to the first key greater
    1302                 :     /// than the parameter. If unsuccessful it returns end().
    1303            2420 :     iterator upper_bound(const key_type& key)
    1304                 :     {
    1305            2420 :         node *n = root;
    1306            2420 :         if (!n) return end();
    1307                 : 
    1308           10120 :         while(!n->isleafnode())
    1309                 :         {
    1310            5280 :             const inner_node *inner = static_cast<const inner_node*>(n);
    1311            5280 :             int slot = find_upper(inner, key);
    1312                 : 
    1313            5280 :             n = inner->childid[slot];
    1314                 :         }
    1315                 : 
    1316            2420 :         leaf_node *leaf = static_cast<leaf_node*>(n);
    1317                 : 
    1318            2420 :         int slot = find_upper(leaf, key);
    1319            2420 :         return iterator(leaf, slot);
    1320                 :     }
    1321                 : 
    1322                 :     /// Searches the B+ tree and returns an constant iterator to the first key
    1323                 :     /// greater than the parameter. If unsuccessful it returns end().
    1324               0 :     const_iterator upper_bound(const key_type& key) const
    1325                 :     {
    1326               0 :         const node *n = root;
    1327               0 :         if (!n) return end();
    1328                 : 
    1329               0 :         while(!n->isleafnode())
    1330                 :         {
    1331               0 :             const inner_node *inner = static_cast<const inner_node*>(n);
    1332               0 :             int slot = find_upper(inner, key);
    1333                 : 
    1334               0 :             n = inner->childid[slot];
    1335                 :         }
    1336                 : 
    1337               0 :         const leaf_node *leaf = static_cast<const leaf_node*>(n);
    1338                 : 
    1339               0 :         int slot = find_upper(leaf, key);
    1340               0 :         return const_iterator(leaf, slot);
    1341                 :     }
    1342                 : 
    1343                 :     /// Searches the B+ tree and returns both lower_bound() and upper_bound().
    1344            1210 :     inline std::pair<iterator, iterator> equal_range(const key_type& key)
    1345                 :     {
    1346            1210 :         return std::pair<iterator, iterator>(lower_bound(key), upper_bound(key));
    1347                 :     }
    1348                 : 
    1349                 :     /// Searches the B+ tree and returns both lower_bound() and upper_bound().
    1350               0 :     inline std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const
    1351                 :     {
    1352               0 :         return std::pair<const_iterator, const_iterator>(lower_bound(key), upper_bound(key));
    1353                 :     }
    1354                 : 
    1355                 : public:
    1356                 :     // *** B+ Tree Object Comparison Functions
    1357                 : 
    1358                 :     /// Equality relation of B+ trees of the same type. B+ trees of the same
    1359                 :     /// size and equal elements (both key and data) are considered
    1360                 :     /// equal. Beware of the random ordering of duplicate keys.
    1361               5 :     inline bool operator==(const btree_self &other) const
    1362                 :     {
    1363               5 :         return (size() == other.size()) && std::equal(begin(), end(), other.begin());
    1364                 :     }
    1365                 : 
    1366                 :     /// Inequality relation. Based on operator==.
    1367               1 :     inline bool operator!=(const btree_self &other) const
    1368                 :     {
    1369               1 :         return !(*this == other);
    1370                 :     }
    1371                 : 
    1372                 :     /// Total ordering relation of B+ trees of the same type. It uses
    1373                 :     /// std::lexicographical_compare() for the actual comparison of elements.
    1374               4 :     inline bool operator<(const btree_self &other) const
    1375                 :     {
    1376               4 :         return std::lexicographical_compare(begin(), end(), other.begin(), other.end());
    1377                 :     }
    1378                 : 
    1379                 :     /// Greater relation. Based on operator<.
    1380               1 :     inline bool operator>(const btree_self &other) const
    1381                 :     {
    1382               1 :         return other < *this;
    1383                 :     }
    1384                 : 
    1385                 :     /// Less-equal relation. Based on operator<.
    1386               1 :     inline bool operator<=(const btree_self &other) const
    1387                 :     {
    1388               1 :         return !(other < *this);
    1389                 :     }
    1390                 : 
    1391                 :     /// Greater-equal relation. Based on operator<.
    1392               1 :     inline bool operator>=(const btree_self &other) const
    1393                 :     {
    1394               1 :         return !(*this < other);
    1395                 :     }
    1396                 : 
    1397                 : public:
    1398                 :     /// *** Fast Copy: Assign Operator and Copy Constructors
    1399                 : 
    1400                 :     /// Assignment operator. All the key/data pairs are copied
    1401               1 :     inline btree_self& operator= (const btree_self &other)
    1402                 :     {
    1403               1 :         if (this != &other)
    1404                 :         {
    1405               1 :             clear();
    1406                 : 
    1407               1 :             key_less = other.key_comp();
    1408               1 :             if (other.size() != 0)
    1409                 :             {
    1410               1 :                 stats.leaves = stats.innernodes = 0;
    1411               1 :                 root = copy_recursive(other.root);
    1412               1 :                 stats = other.stats;
    1413                 :             }
    1414                 : 
    1415               1 :             if (selfverify) verify();
    1416                 :         }
    1417               1 :         return *this;
    1418                 :     }
    1419                 : 
    1420                 :     /// Copy constructor. The newly initialized B+ tree object will contain a
    1421                 :     /// copy of all key/data pairs.
    1422               2 :     inline btree(const btree_self &other)
    1423                 :         : root(NULL), headleaf(NULL), tailleaf(NULL),
    1424                 :           stats( other.stats ),
    1425               2 :           key_less( other.key_comp() )
    1426                 :     {
    1427               2 :         if (size() > 0)
    1428                 :         {
    1429               2 :             stats.leaves = stats.innernodes = 0;
    1430               2 :             root = copy_recursive(other.root);
    1431               2 :             if (selfverify) verify();
    1432                 :         }
    1433                 :     }
    1434                 :     
    1435                 : private:
    1436                 :     /// Recursively copy nodes from another B+ tree object
    1437             802 :     class node* copy_recursive(const node *n)
    1438                 :     {
    1439             802 :         if (n->isleafnode())
    1440                 :         {
    1441             683 :             const leaf_node *leaf = static_cast<const leaf_node*>(n);
    1442             683 :             leaf_node *newleaf = allocate_leaf();
    1443                 : 
    1444             683 :             newleaf->slotuse = leaf->slotuse;
    1445             683 :             std::copy(leaf->slotkey, leaf->slotkey + leaf->slotuse, newleaf->slotkey);
    1446             683 :             std::copy(leaf->slotdata, leaf->slotdata + leaf->slotuse, newleaf->slotdata);
    1447                 : 
    1448             683 :             if (headleaf == NULL)
    1449                 :             {
    1450               3 :                 headleaf = tailleaf = newleaf;
    1451               3 :                 newleaf->prevleaf = newleaf->nextleaf = NULL;
    1452                 :             }
    1453                 :             else
    1454                 :             {
    1455             680 :                 newleaf->prevleaf = tailleaf;
    1456             680 :                 tailleaf->nextleaf = newleaf;
    1457             680 :                 tailleaf = newleaf;
    1458                 :             }
    1459                 : 
    1460             683 :             return newleaf;
    1461                 :         }
    1462                 :         else
    1463                 :         {
    1464             119 :             const inner_node *inner = static_cast<const inner_node*>(n);
    1465             119 :             inner_node *newinner = allocate_inner(inner->level);
    1466                 : 
    1467             119 :             newinner->slotuse = inner->slotuse;
    1468             119 :             std::copy(inner->slotkey, inner->slotkey + inner->slotuse, newinner->slotkey);
    1469                 : 
    1470             918 :             for (unsigned short slot = 0; slot <= inner->slotuse; ++slot)
    1471                 :             {
    1472             799 :                 newinner->childid[slot] = copy_recursive(inner->childid[slot]);
    1473                 :             }
    1474                 : 
    1475             119 :             return newinner;
    1476                 :         }
    1477                 :     }
    1478                 : 
    1479                 : public:
    1480                 :     // *** Public Insertion Functions
    1481                 : 
    1482                 :     /// Attempt to insert a key/data pair into the B+ tree. If the tree does not
    1483                 :     /// allow duplicate keys, then the insert may fail if it is already
    1484                 :     /// present.
    1485                 :     inline std::pair<iterator, bool> insert(const pair_type& x)
    1486                 :     {
    1487                 :         return insert_start(x.first, x.second);
    1488                 :     }
    1489                 :     
    1490                 :     /// Attempt to insert a key/data pair into the B+ tree. Beware that if
    1491                 :     /// key_type == data_type, then the template iterator insert() is called
    1492                 :     /// instead. If the tree does not allow duplicate keys, then the insert may
    1493                 :     /// fail if it is already present.
    1494                 :     inline std::pair<iterator, bool> insert(const key_type& key, const data_type& data)
    1495                 :     {
    1496                 :         return insert_start(key, data);
    1497                 :     }
    1498                 : 
    1499                 :     /// Attempt to insert a key/data pair into the B+ tree. This function is the
    1500                 :     /// same as the other insert, however if key_type == data_type then the
    1501                 :     /// non-template function cannot be called. If the tree does not allow
    1502                 :     /// duplicate keys, then the insert may fail if it is already present.
    1503           24788 :     inline std::pair<iterator, bool> insert2(const key_type& key, const data_type& data)
    1504                 :     {
    1505           24788 :         return insert_start(key, data);
    1506                 :     }
    1507                 : 
    1508                 :     /// Attempt to insert a key/data pair into the B+ tree. The iterator hint
    1509                 :     /// is currently ignored by the B+ tree insertion routine.
    1510                 :     inline iterator insert(iterator /* hint */, const pair_type &x)
    1511                 :     {
    1512                 :         return insert_start(x.first, x.second).first;
    1513                 :     }
    1514                 : 
    1515                 :     /// Attempt to insert a key/data pair into the B+ tree. The iterator hint is
    1516                 :     /// currently ignored by the B+ tree insertion routine.
    1517               0 :     inline iterator insert2(iterator /* hint */, const key_type& key, const data_type& data)
    1518                 :     {
    1519               0 :         return insert_start(key, data).first;
    1520                 :     }
    1521                 : 
    1522                 :     /// Attempt to insert the range [first,last) of value_type pairs into the B+
    1523                 :     /// tree. Each key/data pair is inserted individually.
    1524                 :     template <typename InputIterator>
    1525                 :     inline void insert(InputIterator first, InputIterator last)
    1526                 :     {
    1527                 :         InputIterator iter = first;
    1528                 :         while(iter != last)
    1529                 :         {
    1530                 :             insert(*iter);
    1531                 :             ++iter;
    1532                 :         }
    1533                 :     }
    1534                 : 
    1535                 : private:
    1536                 :     // *** Private Insertion Functions
    1537                 : 
    1538                 :     /// Start the insertion descent at the current root and handle root
    1539                 :     /// splits. Returns true if the item was inserted
    1540           24788 :     std::pair<iterator, bool> insert_start(const key_type& key, const data_type& value)
    1541                 :     {
    1542           24788 :         node *newchild = NULL;
    1543           24788 :         key_type newkey = key_type();
    1544                 : 
    1545           24788 :         if (!root)
    1546                 :         {
    1547              13 :             root = headleaf = tailleaf = allocate_leaf();
    1548                 :         }
    1549                 : 
    1550           24788 :         std::pair<iterator, bool> r = insert_descend(root, key, value, &newkey, &newchild);
    1551                 : 
    1552           24788 :         if (newchild)
    1553                 :         {
    1554              35 :             inner_node *newroot = allocate_inner(root->level + 1);
    1555              35 :             newroot->slotkey[0] = newkey;
    1556                 : 
    1557              35 :             newroot->childid[0] = root;
    1558              35 :             newroot->childid[1] = newchild;
    1559                 : 
    1560              35 :             newroot->slotuse = 1;
    1561                 : 
    1562              35 :             root = newroot;
    1563                 :         }
    1564                 : 
    1565                 :         // increment itemcount if the item was inserted
    1566           24788 :         if (r.second) ++stats.itemcount;
    1567                 : 
    1568                 :         if (debug)
    1569                 :             print();
    1570                 : 
    1571                 :         if (selfverify) {
    1572           24788 :             verify();
    1573           24788 :             BTREE_ASSERT(exists(key));
    1574                 :         }
    1575                 : 
    1576                 :         return r;
    1577                 :     }
    1578                 : 
    1579                 :     /**
    1580                 :      * @brief Insert an item into the B+ tree.
    1581                 :      *
    1582                 :      * Descend down the nodes to a leaf, insert the key/data pair in a free
    1583                 :      * slot. If the node overflows, then it must be split and the new split
    1584                 :      * node inserted into the parent. Unroll / this splitting up to the root.
    1585                 :     */
    1586                 :     std::pair<iterator, bool> insert_descend(node* n,
    1587                 :                                              const key_type& key, const data_type& value,
    1588          114702 :                                              key_type* splitkey, node** splitnode)
    1589                 :     {
    1590          114702 :         if (!n->isleafnode())
    1591                 :         {
    1592           89914 :             inner_node *inner = static_cast<inner_node*>(n);
    1593                 : 
    1594           89914 :             key_type newkey = key_type();
    1595           89914 :             node *newchild = NULL;
    1596                 : 
    1597           89914 :             int slot = find_lower(inner, key);
    1598                 : 
    1599                 :             BTREE_PRINT("btree::insert_descend into " << inner->childid[slot] << std::endl);
    1600                 : 
    1601                 :             std::pair<iterator, bool> r = insert_descend(inner->childid[slot],
    1602           89914 :                                                          key, value, &newkey, &newchild);
    1603                 : 
    1604           89914 :             if (newchild)
    1605                 :             {
    1606                 :                 BTREE_PRINT("btree::insert_descend newchild with key " << newkey << " node " << newchild << " at slot " << slot << std::endl);
    1607                 : 
    1608            6941 :                 if (inner->isfull())
    1609                 :                 {
    1610            1250 :                     split_inner_node(inner, splitkey, splitnode, slot);
    1611                 : 
    1612                 :                     BTREE_PRINT("btree::insert_descend done split_inner: putslot: " << slot << " putkey: " << newkey << " upkey: " << *splitkey << std::endl);
    1613                 : 
    1614                 :                     if (debug)
    1615                 :                     {
    1616                 :                         print_node(inner);
    1617                 :                         print_node(*splitnode);
    1618                 :                     }
    1619                 : 
    1620                 :                     // check if insert slot is in the split sibling node
    1621                 :                     BTREE_PRINT("btree::insert_descend switch: " << slot << " > " << inner->slotuse+1 << std::endl);
    1622                 : 
    1623            1250 :                     if (slot == inner->slotuse+1 && inner->slotuse < (*splitnode)->slotuse)
    1624                 :                     {
    1625                 :                         // special case when the insert slot matches the split
    1626                 :                         // place between the two nodes, then the insert key
    1627                 :                         // becomes the split key.
    1628                 : 
    1629              36 :                         BTREE_ASSERT(inner->slotuse + 1 < innerslotmax);
    1630                 : 
    1631              36 :                         inner_node *splitinner = static_cast<inner_node*>(*splitnode);
    1632                 : 
    1633                 :                         // move the split key and it's datum into the left node
    1634              36 :                         inner->slotkey[inner->slotuse] = *splitkey;
    1635              36 :                         inner->childid[inner->slotuse+1] = splitinner->childid[0];
    1636              36 :                         inner->slotuse++;
    1637                 : 
    1638                 :                         // set new split key and move corresponding datum into right node
    1639              36 :                         splitinner->childid[0] = newchild;
    1640              36 :                         *splitkey = newkey;
    1641                 : 
    1642              36 :                         return r;
    1643                 :                     }
    1644            1214 :                     else if (slot >= inner->slotuse+1)
    1645                 :                     {
    1646                 :                         // in case the insert slot is in the newly create split
    1647                 :                         // node, we reuse the code below.
    1648                 : 
    1649             753 :                         slot -= inner->slotuse+1;
    1650             753 :                         inner = static_cast<inner_node*>(*splitnode);
    1651                 :                         BTREE_PRINT("btree::insert_descend switching to splitted node " << inner << " slot " << slot <<std::endl);
    1652                 :                     }
    1653                 :                 }
    1654                 : 
    1655                 :                 // put pointer to child node into correct slot
    1656            6905 :                 BTREE_ASSERT(slot >= 0 && slot <= inner->slotuse);
    1657                 : 
    1658            6905 :                 int i = inner->slotuse;
    1659                 : 
    1660           26025 :                 while(i > slot) {
    1661           12215 :                     inner->slotkey[i] = inner->slotkey[i - 1];
    1662           12215 :                     inner->childid[i + 1] = inner->childid[i];
    1663           12215 :                     i--;
    1664                 :                 }
    1665                 : 
    1666            6905 :                 inner->slotkey[slot] = newkey;
    1667            6905 :                 inner->childid[slot + 1] = newchild;
    1668            6905 :                 inner->slotuse++;
    1669                 :             }
    1670                 :             
    1671           89878 :             return r;
    1672                 :         }
    1673                 :         else // n->isleafnode() == true
    1674                 :         {
    1675           24788 :             leaf_node *leaf = static_cast<leaf_node*>(n);
    1676                 : 
    1677           24788 :             int slot = find_lower(leaf, key);
    1678                 : 
    1679               0 :             if (!allow_duplicates && slot < leaf->slotuse && key_equal(key, leaf->slotkey[slot])) {
    1680               0 :                 return std::pair<iterator, bool>(iterator(leaf, slot), false);
    1681                 :             }
    1682                 : 
    1683           24788 :             if (leaf->isfull())
    1684                 :             {
    1685            5726 :                 split_leaf_node(leaf, splitkey, splitnode);
    1686                 : 
    1687                 :                 // check if insert slot is in the split sibling node
    1688            5726 :                 if (slot >= leaf->slotuse)
    1689                 :                 {
    1690            2950 :                     slot -= leaf->slotuse;
    1691            2950 :                     leaf = static_cast<leaf_node*>(*splitnode);
    1692                 :                 }
    1693                 :             }
    1694                 : 
    1695                 :             // put data item into correct data slot
    1696                 : 
    1697           24788 :             int i = leaf->slotuse - 1;
    1698           24788 :             BTREE_ASSERT(i + 1 < leafslotmax);
    1699                 : 
    1700           62826 :             while(i >= 0 && key_less(key, leaf->slotkey[i])) {
    1701           13250 :                 leaf->slotkey[i + 1] = leaf->slotkey[i];
    1702           13250 :                 leaf->slotdata[i + 1] = leaf->slotdata[i];
    1703           13250 :                 i--;
    1704                 :             }
    1705                 :             
    1706           24788 :             leaf->slotkey[i + 1] = key;
    1707           24788 :             leaf->slotdata[i + 1] = value;
    1708           24788 :             leaf->slotuse++;
    1709                 : 
    1710           24788 :             if (splitnode && leaf != *splitnode && slot == leaf->slotuse-1)
    1711                 :             {
    1712                 :                 // special case: the node was split, and the insert is at the
    1713                 :                 // last slot of the old node. then the splitkey must be
    1714                 :                 // updated.
    1715            7559 :                 *splitkey = key;
    1716                 :             }
    1717                 : 
    1718           24788 :             return std::pair<iterator, bool>(iterator(leaf, i + 1), true);
    1719                 :         }
    1720                 :     }
    1721                 : 
    1722                 :     /// Split up a leaf node into two equally-filled sibling leaves. Returns
    1723                 :     /// the new nodes and it's insertion key in the two parameters.
    1724            5726 :     void split_leaf_node(leaf_node* leaf, key_type* _newkey, node** _newleaf)
    1725                 :     {
    1726            5726 :         BTREE_ASSERT(leaf->isfull());
    1727                 : 
    1728            5726 :         unsigned int mid = leaf->slotuse / 2;
    1729                 : 
    1730                 :         BTREE_PRINT("btree::split_leaf_node on " << leaf << std::endl);
    1731                 : 
    1732            5726 :         leaf_node *newleaf = allocate_leaf();
    1733                 : 
    1734            5726 :         newleaf->slotuse = leaf->slotuse - mid;
    1735                 : 
    1736            5726 :         newleaf->nextleaf = leaf->nextleaf;
    1737            5726 :         if (newleaf->nextleaf == NULL) {
    1738            2567 :             BTREE_ASSERT(leaf == tailleaf);
    1739            2567 :             tailleaf = newleaf;
    1740                 :         }
    1741                 :         else {
    1742            3159 :             newleaf->nextleaf->prevleaf = newleaf;
    1743                 :         }
    1744                 : 
    1745           28630 :         for(unsigned int slot = mid; slot < leaf->slotuse; ++slot)
    1746                 :         {
    1747           22904 :             unsigned int ni = slot - mid;
    1748           22904 :             newleaf->slotkey[ni] = leaf->slotkey[slot];
    1749           22904 :             newleaf->slotdata[ni] = leaf->slotdata[slot];
    1750                 :         }
    1751                 :             
    1752            5726 :         leaf->slotuse = mid;
    1753            5726 :         leaf->nextleaf = newleaf;
    1754            5726 :         newleaf->prevleaf = leaf;
    1755                 : 
    1756            5726 :         *_newkey = leaf->slotkey[leaf->slotuse-1];
    1757            5726 :         *_newleaf = newleaf;
    1758                 :     }
    1759                 : 
    1760                 :     /// Split up an inner node into two equally-filled sibling nodes. Returns
    1761                 :     /// the new nodes and it's insertion key in the two parameters. Requires
    1762                 :     /// the slot of the item will be inserted, so the nodes will be the same
    1763                 :     /// size after the insert.
    1764            1250 :     void split_inner_node(inner_node* inner, key_type* _newkey, node** _newinner, unsigned int addslot)
    1765                 :     {
    1766            1250 :         BTREE_ASSERT(inner->isfull());
    1767                 : 
    1768            1250 :         unsigned int mid = inner->slotuse / 2;
    1769                 : 
    1770                 :         BTREE_PRINT("btree::split_inner: mid " << mid << " addslot " << addslot << std::endl);
    1771                 : 
    1772                 :         // if the split is uneven and the overflowing item will be put into the
    1773                 :         // larger node, then the smaller split node may underflow
    1774            1250 :         if (addslot <= mid && mid > inner->slotuse - (mid + 1))
    1775             497 :             mid--;
    1776                 : 
    1777                 :         BTREE_PRINT("btree::split_inner: mid " << mid << " addslot " << addslot << std::endl);
    1778                 : 
    1779                 :         BTREE_PRINT("btree::split_inner_node on " << inner << " into two nodes " << mid << " and " << inner->slotuse - (mid + 1) << " sized" << std::endl);
    1780                 : 
    1781            1250 :         inner_node *newinner = allocate_inner(inner->level);
    1782                 : 
    1783            1250 :         newinner->slotuse = inner->slotuse - (mid + 1);
    1784                 : 
    1785            5497 :         for(unsigned int slot = mid + 1; slot < inner->slotuse; ++slot)
    1786                 :         {
    1787            4247 :             unsigned int ni = slot - (mid + 1);
    1788            4247 :             newinner->slotkey[ni] = inner->slotkey[slot];
    1789            4247 :             newinner->childid[ni] = inner->childid[slot];
    1790                 :         }
    1791            1250 :         newinner->childid[newinner->slotuse] = inner->childid[inner->slotuse];
    1792                 :             
    1793            1250 :         inner->slotuse = mid;
    1794                 : 
    1795            1250 :         *_newkey = inner->slotkey[mid];
    1796            1250 :         *_newinner = newinner;
    1797                 :     }
    1798                 : 
    1799                 : private:
    1800                 :     // *** Support Class Encapsulating Deletion Results
    1801                 : 
    1802                 :     /// Result flags of recursive deletion.
    1803                 :     enum result_flags_t
    1804                 :     {
    1805                 :         /// Deletion successful and no fix-ups necessary.
    1806                 :         btree_ok = 0,
    1807                 : 
    1808                 :         /// Deletion not successful because key was not found.
    1809                 :         btree_not_found = 1,
    1810                 : 
    1811                 :         /// Deletion successful, the last key was updated so parent slotkeys
    1812                 :         /// need updates.
    1813                 :         btree_update_lastkey = 2,
    1814                 : 
    1815                 :         /// Deletion successful, children nodes were merged and the parent
    1816                 :         /// needs to remove the empty node.
    1817                 :         btree_fixmerge = 4
    1818                 :     };
    1819                 : 
    1820                 :     /// \internal B+ tree recursive deletion has much information which is
    1821                 :     /// needs to be passed upward.
    1822                 :     struct result_t
    1823                 :     {
    1824                 :         /// Merged result flags
    1825                 :         result_flags_t  flags;
    1826                 : 
    1827                 :         /// The key to be updated at the parent's slot
    1828                 :         key_type        lastkey;
    1829                 : 
    1830                 :         /// Constructor of a result with a specific flag, this can also be used
    1831                 :         /// as for implicit conversion.
    1832          106381 :         inline result_t(result_flags_t f = btree_ok)
    1833          106381 :             : flags(f), lastkey()
    1834          106381 :         { }
    1835                 : 
    1836                 :         /// Constructor with a lastkey value.
    1837             373 :         inline result_t(result_flags_t f, const key_type &k)
    1838             373 :             : flags(f), lastkey(k)
    1839             373 :         { }
    1840                 : 
    1841                 :         /// Test if this result object has a given flag set.
    1842          285317 :         inline bool has(result_flags_t f) const
    1843                 :         {
    1844          285317 :             return (flags & f);
    1845                 :         }
    1846                 : 
    1847                 :         /// Merge two results OR-ing the result flags and overwriting lastkeys.
    1848            6945 :         inline result_t& operator|= (const result_t &other)
    1849                 :         {
    1850            6945 :             flags = result_flags_t(flags | other.flags);
    1851                 : 
    1852                 :             // we overwrite existing lastkeys on purpose
    1853            6945 :             if (other.has(btree_update_lastkey))
    1854             373 :                 lastkey = other.lastkey;
    1855                 : 
    1856            6945 :             return *this;
    1857                 :         }
    1858                 :     };
    1859                 : 
    1860                 : public:
    1861                 :     // *** Public Erase Functions
    1862                 : 
    1863                 :     /// Erases one (the first) of the key/data pairs associated with the given
    1864                 :     /// key.
    1865           20944 :     bool erase_one(const key_type &key)
    1866                 :     {
    1867                 :         BTREE_PRINT("btree::erase_one(" << key << ") on btree size " << size() << std::endl);
    1868                 : 
    1869           20944 :         if (selfverify) verify();
    1870                 :         
    1871           20944 :         result_t result = erase_one_descend(key, root, NULL, NULL, NULL, NULL, NULL, 0);
    1872                 : 
    1873           20944 :         if (!result.has(btree_not_found))
    1874           20944 :             --stats.itemcount;
    1875                 : 
    1876                 :         if (debug) print();
    1877           20944 :         if (selfverify) verify();
    1878                 : 
    1879           20944 :         return !result.has(btree_not_found);
    1880                 :     }
    1881                 : 
    1882                 :     /// Erases all the key/data pairs associated with the given key. This is
    1883                 :     /// implemented using erase_one().
    1884               0 :     size_type erase(const key_type &key)
    1885                 :     {
    1886               0 :         size_type c = 0;
    1887                 : 
    1888               0 :         while( erase_one(key) )
    1889                 :         {
    1890               0 :             ++c;
    1891               0 :             if (!allow_duplicates) break;
    1892                 :         }
    1893                 : 
    1894               0 :         return c;
    1895                 :     }
    1896                 : 
    1897                 : #ifdef BTREE_TODO
    1898                 :     /// Erase the key/data pair referenced by the iterator.
    1899                 :     void erase(iterator iter)
    1900                 :     {
    1901                 : 
    1902                 :     }
    1903                 : #endif
    1904                 : 
    1905                 : #ifdef BTREE_TODO
    1906                 :     /// Erase all key/data pairs in the range [first,last). This function is
    1907                 :     /// currently not implemented by the B+ Tree.
    1908                 :     void erase(iterator /* first */, iterator /* last */)
    1909                 :     {
    1910                 :         abort();
    1911                 :     }
    1912                 : #endif
    1913                 : 
    1914                 : private:
    1915                 :     // *** Private Erase Functions
    1916                 : 
    1917                 :     /** @brief Erase one (the first) key/data pair in the B+ tree matching key.
    1918                 :      *
    1919                 :      * Descends down the tree in search of key. During the descent the parent,
    1920                 :      * left and right siblings and their parents are computed and passed
    1921                 :      * down. Once the key/data pair is found, it is removed from the leaf. If
    1922                 :      * the leaf underflows 6 different cases are handled. These cases resolve
    1923                 :      * the underflow by shifting key/data pairs from adjacent sibling nodes,
    1924                 :      * merging two sibling nodes or trimming the tree.
    1925                 :      */
    1926                 :     result_t erase_one_descend(const key_type& key,
    1927                 :                                node *curr,
    1928                 :                                node *left, node *right,
    1929                 :                                inner_node *leftparent, inner_node *rightparent,
    1930           99772 :                                inner_node *parent, unsigned int parentslot)
    1931                 :     {
    1932           99772 :         if (curr->isleafnode())
    1933                 :         {
    1934           20944 :             leaf_node *leaf = static_cast<leaf_node*>(curr);
    1935           20944 :             leaf_node *leftleaf = static_cast<leaf_node*>(left);
    1936           20944 :             leaf_node *rightleaf = static_cast<leaf_node*>(right);
    1937                 : 
    1938           20944 :             int slot = find_lower(leaf, key);
    1939                 : 
    1940           20944 :             if (!key_equal(key, leaf->slotkey[slot]))
    1941                 :             {
    1942                 :                 BTREE_PRINT("Could not find key " << key << " to erase." << std::endl);
    1943                 : 
    1944               0 :                 return btree_not_found;
    1945                 :             }
    1946                 : 
    1947                 :             BTREE_PRINT("Found key in leaf " << curr << " at slot " << slot << std::endl);
    1948                 : 
    1949           95590 :             for (int i = slot; i < leaf->slotuse - 1; i++)
    1950                 :             {
    1951           74646 :                 leaf->slotkey[i] = leaf->slotkey[i + 1];
    1952           74646 :                 leaf->slotdata[i] = leaf->slotdata[i + 1];
    1953                 :             }
    1954           20944 :             leaf->slotuse--;
    1955                 : 
    1956           20944 :             result_t myres = btree_ok;
    1957                 : 
    1958                 :             // if the last key of the leaf was changed, the parent is notified
    1959                 :             // and updates the key of this leaf
    1960           20944 :             if (slot == leaf->slotuse)
    1961                 :             {
    1962            2846 :                 if (parent && parentslot < parent->slotuse)
    1963                 :                 {
    1964            1269 :                     BTREE_ASSERT(parent->childid[parentslot] == curr);
    1965            1269 :                     parent->slotkey[parentslot] = leaf->slotkey[leaf->slotuse - 1];
    1966                 :                 }
    1967                 :                 else
    1968                 :                 {
    1969                 :                     BTREE_PRINT("Scheduling lastkeyupdate: key " << leaf->slotkey[leaf->slotuse - 1] << std::endl);
    1970             308 :                     myres |= result_t(btree_update_lastkey, leaf->slotkey[leaf->slotuse - 1]);
    1971                 :                 }
    1972                 :             }
    1973                 : 
    1974           20944 :             if (leaf->isunderflow() && !(leaf == root && leaf->slotuse >= 1))
    1975                 :             {
    1976                 :                 // determine what to do about the underflow
    1977                 : 
    1978                 :                 // case : if this empty leaf is the root, there is no way to
    1979                 :                 // correct underflow
    1980            6518 :                 if (leftleaf == NULL && rightleaf == NULL)
    1981                 :                 {
    1982              10 :                     return btree_ok;
    1983                 :                 }
    1984                 :                 // case : if both left and right leaves would underflow in case of
    1985                 :                 // a shift, then merging is necessary. choose the more local merger
    1986                 :                 // with our parent
    1987            6508 :                 else if ( (leftleaf == NULL || leftleaf->isfew()) && (rightleaf == NULL || rightleaf->isfew()) )
    1988                 :                 {
    1989            4736 :                     if (leftparent == parent)
    1990            1285 :                         myres |= merge_leaves(leftleaf, leaf, leftparent);
    1991                 :                     else
    1992            3451 :                         myres |= merge_leaves(leaf, rightleaf, rightparent);
    1993                 :                 }
    1994                 :                 // case : the right leaf has extra data, so balance right with current
    1995            1772 :                 else if ( (leftleaf != NULL && leftleaf->isfew()) && (rightleaf != NULL && !rightleaf->isfew()) )
    1996                 :                 {
    1997             421 :                     if (rightparent == parent)
    1998             339 :                         myres |= shift_left_leaf(leaf, rightleaf, rightparent, parentslot);
    1999                 :                     else
    2000              82 :                         myres |= merge_leaves(leftleaf, leaf, leftparent);
    2001                 :                 }
    2002                 :                 // case : the left leaf has extra data, so balance left with current
    2003            1351 :                 else if ( (leftleaf != NULL && !leftleaf->isfew()) && (rightleaf != NULL && rightleaf->isfew()) )
    2004                 :                 {
    2005             923 :                     if (leftparent == parent)
    2006             858 :                         shift_right_leaf(leftleaf, leaf, leftparent, parentslot - 1);
    2007                 :                     else
    2008              65 :                         myres |= merge_leaves(leaf, rightleaf, rightparent);
    2009                 :                 }
    2010                 :                 // case : both the leaf and right leaves have extra data and our
    2011                 :                 // parent, choose the leaf with more data
    2012             428 :                 else if (leftparent == rightparent)
    2013                 :                 {
    2014             274 :                     if (leftleaf->slotuse <= rightleaf->slotuse)
    2015             177 :                         myres |= shift_left_leaf(leaf, rightleaf, rightparent, parentslot);
    2016                 :                     else
    2017              97 :                         shift_right_leaf(leftleaf, leaf, leftparent, parentslot - 1);
    2018                 :                 }
    2019                 :                 else
    2020                 :                 {
    2021             154 :                     if (leftparent == parent)
    2022              88 :                         shift_right_leaf(leftleaf, leaf, leftparent, parentslot - 1);
    2023                 :                     else
    2024              66 :                         myres |= shift_left_leaf(leaf, rightleaf, rightparent, parentslot);
    2025                 :                 }
    2026                 :             }
    2027                 : 
    2028           20934 :             return myres;
    2029                 :         }
    2030                 :         else // !curr->isleafnode()
    2031                 :         {
    2032           78828 :             inner_node *inner = static_cast<inner_node*>(curr);
    2033           78828 :             inner_node *leftinner = static_cast<inner_node*>(left);
    2034           78828 :             inner_node *rightinner = static_cast<inner_node*>(right);
    2035                 : 
    2036                 :             node *myleft, *myright;
    2037                 :             inner_node *myleftparent, *myrightparent;
    2038                 : 
    2039           78828 :             int slot = find_lower(inner, key);
    2040                 : 
    2041           78828 :             if (slot == 0) {
    2042           54740 :                 myleft = (left == NULL) ? NULL : (static_cast<inner_node*>(left))->childid[left->slotuse - 1];
    2043           54740 :                 myleftparent = leftparent;
    2044                 :             }
    2045                 :             else {
    2046           24088 :                 myleft = inner->childid[slot - 1];
    2047           24088 :                 myleftparent = inner;
    2048                 :             }
    2049                 : 
    2050           78828 :             if (slot == inner->slotuse) {
    2051            5870 :                 myright = (right == NULL) ? NULL : (static_cast<inner_node*>(right))->childid[0];
    2052            5870 :                 myrightparent = rightparent;
    2053                 :             }
    2054                 :             else {
    2055           72958 :                 myright = inner->childid[slot + 1];
    2056           72958 :                 myrightparent = inner;
    2057                 :             }
    2058                 : 
    2059                 :             BTREE_PRINT("erase_one_descend into " << inner->childid[slot] << std::endl);
    2060                 : 
    2061                 :             result_t result = erase_one_descend(key,
    2062                 :                                                 inner->childid[slot],
    2063                 :                                                 myleft, myright,
    2064                 :                                                 myleftparent, myrightparent,
    2065           78828 :                                                 inner, slot);
    2066                 : 
    2067           78828 :             result_t myres = btree_ok;
    2068                 : 
    2069           78828 :             if (result.has(btree_not_found))
    2070                 :             {
    2071               0 :                 return result;
    2072                 :             }
    2073                 : 
    2074           78828 :             if (result.has(btree_update_lastkey))
    2075                 :             {
    2076             617 :                 if (parent && parentslot < parent->slotuse)
    2077                 :                 {
    2078                 :                     BTREE_PRINT("Fixing lastkeyupdate: key " << result.lastkey << " into parent " << parent << " at parentslot " << parentslot << std::endl);
    2079                 : 
    2080             276 :                     BTREE_ASSERT(parent->childid[parentslot] == curr);
    2081             276 :                     parent->slotkey[parentslot] = result.lastkey;
    2082                 :                 }
    2083                 :                 else
    2084                 :                 {
    2085                 :                     BTREE_PRINT("Forwarding lastkeyupdate: key " << result.lastkey << std::endl);
    2086              65 :                     myres |= result_t(btree_update_lastkey, result.lastkey);
    2087                 :                 }
    2088                 :             }
    2089                 : 
    2090           78828 :             if (result.has(btree_fixmerge))
    2091                 :             {
    2092                 :                 // either the current node or the next is empty and should be removed
    2093            5990 :                 if (inner->childid[slot]->slotuse != 0)
    2094            4314 :                     slot++;
    2095                 : 
    2096                 :                 // this is the child slot invalidated by the merge
    2097            5990 :                 BTREE_ASSERT(inner->childid[slot]->slotuse == 0);
    2098                 : 
    2099            5990 :                 free_node(inner->childid[slot]);
    2100                 : 
    2101           29620 :                 for(int i = slot; i < inner->slotuse; i++)
    2102                 :                 {
    2103           23630 :                     inner->slotkey[i - 1] = inner->slotkey[i];
    2104           23630 :                     inner->childid[i] = inner->childid[i + 1];
    2105                 :                 }
    2106            5990 :                 inner->slotuse--;
    2107                 : 
    2108            5990 :                 if (inner->level == 1)
    2109                 :                 {
    2110                 :                     // fix split key for children leaves
    2111            4883 :                     slot--;
    2112            4883 :                     leaf_node *child = static_cast<leaf_node*>(inner->childid[slot]);
    2113            4883 :                     inner->slotkey[slot] = child->slotkey[ child->slotuse-1 ];
    2114                 :                 }
    2115                 :             }
    2116                 : 
    2117           78828 :             if (inner->isunderflow() && !(inner == root && inner->slotuse >= 1))
    2118                 :             {
    2119                 :                 // case: the inner node is the root and has just one child. that child becomes the new root
    2120            1661 :                 if (leftinner == NULL && rightinner == NULL)
    2121                 :                 {
    2122              27 :                     BTREE_ASSERT(inner == root);
    2123              27 :                     BTREE_ASSERT(inner->slotuse == 0);
    2124                 : 
    2125              27 :                     root = inner->childid[0];
    2126                 : 
    2127              27 :                     inner->slotuse = 0;
    2128              27 :                     free_node(inner);
    2129                 : 
    2130              27 :                     return btree_ok;
    2131                 :                 }
    2132                 :                 // case : if both left and right leaves would underflow in case of
    2133                 :                 // a shift, then merging is necessary. choose the more local merger
    2134                 :                 // with our parent
    2135            1634 :                 else if ( (leftinner == NULL || leftinner->isfew()) && (rightinner == NULL || rightinner->isfew()) )
    2136                 :                 {
    2137            1095 :                     if (leftparent == parent)
    2138             303 :                         myres |= merge_inner(leftinner, inner, leftparent, parentslot - 1);
    2139                 :                     else
    2140             792 :                         myres |= merge_inner(inner, rightinner, rightparent, parentslot);
    2141                 :                 }
    2142                 :                 // case : the right leaf has extra data, so balance right with current
    2143             539 :                 else if ( (leftinner != NULL && leftinner->isfew()) && (rightinner != NULL && !rightinner->isfew()) )
    2144                 :                 {
    2145              96 :                     if (rightparent == parent)
    2146              90 :                         shift_left_inner(inner, rightinner, rightparent, parentslot);
    2147                 :                     else
    2148               6 :                         myres |= merge_inner(leftinner, inner, leftparent, parentslot - 1);
    2149                 :                 }
    2150                 :                 // case : the left leaf has extra data, so balance left with current
    2151             443 :                 else if ( (leftinner != NULL && !leftinner->isfew()) && (rightinner != NULL && rightinner->isfew()) )
    2152                 :                 {
    2153             283 :                     if (leftparent == parent)
    2154             277 :                         shift_right_inner(leftinner, inner, leftparent, parentslot - 1);
    2155                 :                     else
    2156               6 :                         myres |= merge_inner(inner, rightinner, rightparent, parentslot);
    2157                 :                 }
    2158                 :                 // case : both the leaf and right leaves have extra data and our
    2159                 :                 // parent, choose the leaf with more data
    2160             160 :                 else if (leftparent == rightparent)
    2161                 :                 {
    2162              75 :                     if (leftinner->slotuse <= rightinner->slotuse)
    2163              44 :                         shift_left_inner(inner, rightinner, rightparent, parentslot);
    2164                 :                     else
    2165              31 :                         shift_right_inner(leftinner, inner, leftparent, parentslot - 1);
    2166                 :                 }
    2167                 :                 else
    2168                 :                 {
    2169              85 :                     if (leftparent == parent)
    2170              42 :                         shift_right_inner(leftinner, inner, leftparent, parentslot - 1);
    2171                 :                     else
    2172              43 :                         shift_left_inner(inner, rightinner, rightparent, parentslot);
    2173                 :                 }
    2174                 :             }
    2175                 : 
    2176           78801 :             return myres;
    2177                 :         }
    2178                 :     }
    2179                 : 
    2180                 :     /// Merge two leaf nodes. The function moves all key/data pairs from right
    2181                 :     /// to left and sets right's slotuse to zero. The right slot is then
    2182                 :     /// removed by the calling parent node.
    2183            4883 :     result_t merge_leaves(leaf_node* left, leaf_node* right, inner_node* parent)
    2184                 :     {
    2185                 :         BTREE_PRINT("Merge leaf nodes " << left << " and " << right << " with common parent " << parent << "." << std::endl);
    2186                 :         (void)parent;
    2187                 : 
    2188            4883 :         BTREE_ASSERT(left->isleafnode() && right->isleafnode());
    2189            4883 :         BTREE_ASSERT(parent->level == 1);
    2190                 : 
    2191            4883 :         BTREE_ASSERT(left->slotuse + right->slotuse < leafslotmax);
    2192                 : 
    2193           23048 :         for (unsigned int i = 0; i < right->slotuse; i++)
    2194                 :         {
    2195           18165 :             left->slotkey[left->slotuse + i] = right->slotkey[i];
    2196           18165 :             left->slotdata[left->slotuse + i] = right->slotdata[i];
    2197                 :         }
    2198            4883 :         left->slotuse += right->slotuse;
    2199                 : 
    2200            4883 :         left->nextleaf = right->nextleaf;
    2201            4883 :         if (left->nextleaf)
    2202            4848 :             left->nextleaf->prevleaf = left;
    2203                 :         else
    2204              35 :             tailleaf = left;
    2205                 : 
    2206            4883 :         right->slotuse = 0;
    2207                 : 
    2208            4883 :         return btree_fixmerge;
    2209                 :     }
    2210                 : 
    2211                 :     /// Merge two inner nodes. The function moves all key/childid pairs from
    2212                 :     /// right to left and sets right's slotuse to zero. The right slot is then
    2213                 :     /// removed by the calling parent node.
    2214            1107 :     static result_t merge_inner(inner_node* left, inner_node* right, inner_node* parent, unsigned int parentslot)
    2215                 :     {
    2216                 :         BTREE_PRINT("Merge inner nodes " << left << " and " << right << " with common parent " << parent << "." << std::endl);
    2217                 : 
    2218            1107 :         BTREE_ASSERT(left->level == right->level);
    2219            1107 :         BTREE_ASSERT(parent->level == left->level + 1);
    2220                 : 
    2221            1107 :         BTREE_ASSERT(parent->childid[parentslot] == left);
    2222                 : 
    2223            1107 :         BTREE_ASSERT(left->slotuse + right->slotuse < innerslotmax);
    2224                 : 
    2225                 :         if (selfverify)
    2226                 :         {
    2227                 :             // find the left node's slot in the parent's children
    2228            1107 :             unsigned int leftslot = 0;
    2229            2894 :             while(leftslot <= parent->slotuse && parent->childid[leftslot] != left)
    2230             680 :                 ++leftslot;
    2231                 : 
    2232            1107 :             BTREE_ASSERT(leftslot < parent->slotuse);
    2233            1107 :             BTREE_ASSERT(parent->childid[leftslot] == left);
    2234            1107 :             BTREE_ASSERT(parent->childid[leftslot+1] == right);
    2235                 : 
    2236            1107 :             BTREE_ASSERT(parentslot == leftslot);
    2237                 :         }
    2238                 : 
    2239                 :         // retrieve the decision key from parent
    2240            1107 :         left->slotkey[left->slotuse] = parent->slotkey[parentslot];
    2241            1107 :         left->slotuse++;
    2242                 : 
    2243                 :         // copy over keys and children from right
    2244            5226 :         for (unsigned int i = 0; i < right->slotuse; i++)
    2245                 :         {
    2246            4119 :             left->slotkey[left->slotuse + i] = right->slotkey[i];
    2247            4119 :             left->childid[left->slotuse + i] = right->childid[i];
    2248                 :         }
    2249            1107 :         left->slotuse += right->slotuse;
    2250                 : 
    2251            1107 :         left->childid[left->slotuse] = right->childid[right->slotuse];
    2252                 : 
    2253            1107 :         right->slotuse = 0;
    2254                 : 
    2255            1107 :         return btree_fixmerge;
    2256                 :     }
    2257                 : 
    2258                 :     /// Balance two leaf nodes. The function moves key/data pairs from right to
    2259                 :     /// left so that both nodes are equally filled. The parent node is updated
    2260                 :     /// if possible.
    2261             582 :     static result_t shift_left_leaf(leaf_node *left, leaf_node *right, inner_node *parent, unsigned int parentslot)
    2262                 :     {
    2263             582 :         BTREE_ASSERT(left->isleafnode() && right->isleafnode());
    2264             582 :         BTREE_ASSERT(parent->level == 1);
    2265                 : 
    2266             582 :         BTREE_ASSERT(left->nextleaf == right);
    2267             582 :         BTREE_ASSERT(left == right->prevleaf);
    2268                 : 
    2269             582 :         BTREE_ASSERT(left->slotuse < right->slotuse);
    2270             582 :         BTREE_ASSERT(parent->childid[parentslot] == left);
    2271                 : 
    2272             582 :         unsigned int shiftnum = (right->slotuse - left->slotuse) / 2;
    2273                 : 
    2274                 :         BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to left " << left << " from right " << right << " with common parent " << parent << "." << std::endl);
    2275                 : 
    2276             582 :         BTREE_ASSERT(left->slotuse + shiftnum < leafslotmax);
    2277                 : 
    2278                 :         // copy the first items from the right node to the last slot in the left node.
    2279            1333 :         for(unsigned int i = 0; i < shiftnum; i++)
    2280                 :         {
    2281             751 :             left->slotkey[left->slotuse + i] = right->slotkey[i];
    2282             751 :             left->slotdata[left->slotuse + i] = right->slotdata[i];
    2283                 :         }
    2284             582 :         left->slotuse += shiftnum;
    2285                 :         
    2286                 :         // shift all slots in the right node to the left
    2287                 :     
    2288             582 :         right->slotuse -= shiftnum;
    2289            3206 :         for(int i = 0; i < right->slotuse; i++)
    2290                 :         {
    2291            2624 :             right->slotkey[i] = right->slotkey[i + shiftnum];
    2292            2624 :             right->slotdata[i] = right->slotdata[i + shiftnum];
    2293                 :         }
    2294                 : 
    2295                 :         // fixup parent
    2296             582 :         if (parentslot < parent->slotuse) {
    2297             582 :             parent->slotkey[parentslot] = left->slotkey[left->slotuse - 1];
    2298             582 :             return btree_ok;
    2299                 :         }
    2300                 :         else { // the update is further up the tree
    2301               0 :             return result_t(btree_update_lastkey, left->slotkey[left->slotuse - 1]);
    2302                 :         }
    2303                 :     }
    2304                 : 
    2305                 :     /// Balance two inner nodes. The function moves key/data pairs from right
    2306                 :     /// to left so that both nodes are equally filled. The parent node is
    2307                 :     /// updated if possible.
    2308             177 :     static void shift_left_inner(inner_node *left, inner_node *right, inner_node *parent, unsigned int parentslot)
    2309                 :     {
    2310             177 :         BTREE_ASSERT(left->level == right->level);
    2311             177 :         BTREE_ASSERT(parent->level == left->level + 1);
    2312                 : 
    2313             177 :         BTREE_ASSERT(left->slotuse < right->slotuse);
    2314             177 :         BTREE_ASSERT(parent->childid[parentslot] == left);
    2315                 : 
    2316             177 :         unsigned int shiftnum = (right->slotuse - left->slotuse) / 2;
    2317                 : 
    2318                 :         BTREE_PRINT("Shifting (inner) " << shiftnum << " entries to left " << left << " from right " << right << " with common parent " << parent << "." << std::endl);
    2319                 : 
    2320             177 :         BTREE_ASSERT(left->slotuse + shiftnum < innerslotmax);
    2321                 : 
    2322                 :         if (selfverify)
    2323                 :         {
    2324                 :             // find the left node's slot in the parent's children and compare to parentslot
    2325                 : 
    2326             177 :             unsigned int leftslot = 0;
    2327             671 :             while(leftslot <= parent->slotuse && parent->childid[leftslot] != left)
    2328             317 :                 ++leftslot;
    2329                 : 
    2330             177 :             BTREE_ASSERT(leftslot < parent->slotuse);
    2331             177 :             BTREE_ASSERT(parent->childid[leftslot] == left);
    2332             177 :             BTREE_ASSERT(parent->childid[leftslot+1] == right);
    2333                 : 
    2334             177 :             BTREE_ASSERT(leftslot == parentslot);
    2335                 :         }
    2336                 : 
    2337                 :         // copy the parent's decision slotkey and childid to the first new key on the left
    2338             177 :         left->slotkey[left->slotuse] = parent->slotkey[parentslot];
    2339             177 :         left->slotuse++;
    2340                 : 
    2341                 :         // copy the other items from the right node to the last slots in the left node.
    2342             256 :         for(unsigned int i = 0; i < shiftnum - 1; i++)
    2343                 :         {
    2344              79 :             left->slotkey[left->slotuse + i] = right->slotkey[i];
    2345              79 :             left->childid[left->slotuse + i] = right->childid[i];
    2346                 :         }
    2347             177 :         left->slotuse += shiftnum - 1;
    2348                 : 
    2349                 :         // fixup parent
    2350             177 :         parent->slotkey[parentslot] = right->slotkey[shiftnum - 1];
    2351                 :         // last pointer in left
    2352             177 :         left->childid[left->slotuse] = right->childid[shiftnum - 1];
    2353                 :         
    2354                 :         // shift all slots in the right node
    2355                 :     
    2356             177 :         right->slotuse -= shiftnum;
    2357            1044 :         for(int i = 0; i < right->slotuse; i++)
    2358                 :         {
    2359             867 :             right->slotkey[i] = right->slotkey[i + shiftnum];
    2360             867 :             right->childid[i] = right->childid[i + shiftnum];
    2361                 :         }
    2362             177 :         right->childid[right->slotuse] = right->childid[right->slotuse + shiftnum];
    2363                 :     }
    2364                 : 
    2365                 :     /// Balance two leaf nodes. The function moves key/data pairs from left to
    2366                 :     /// right so that both nodes are equally filled. The parent node is updated
    2367                 :     /// if possible.
    2368            1043 :     static void shift_right_leaf(leaf_node *left, leaf_node *right, inner_node *parent, unsigned int parentslot)
    2369                 :     {
    2370            1043 :         BTREE_ASSERT(left->isleafnode() && right->isleafnode());
    2371            1043 :         BTREE_ASSERT(parent->level == 1);
    2372                 : 
    2373            1043 :         BTREE_ASSERT(left->nextleaf == right);
    2374            1043 :         BTREE_ASSERT(left == right->prevleaf);
    2375            1043 :         BTREE_ASSERT(parent->childid[parentslot] == left);
    2376                 : 
    2377            1043 :         BTREE_ASSERT(left->slotuse > right->slotuse);
    2378                 : 
    2379            1043 :         unsigned int shiftnum = (left->slotuse - right->slotuse) / 2;
    2380                 : 
    2381                 :         BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to right " << right << " from left " << left << " with common parent " << parent << "." << std::endl);
    2382                 : 
    2383                 :         if (selfverify)
    2384                 :         {
    2385                 :             // find the left node's slot in the parent's children
    2386            1043 :             unsigned int leftslot = 0;
    2387            4835 :             while(leftslot <= parent->slotuse && parent->childid[leftslot] != left)
    2388            2749 :                 ++leftslot;
    2389                 : 
    2390            1043 :             BTREE_ASSERT(leftslot < parent->slotuse);
    2391            1043 :             BTREE_ASSERT(parent->childid[leftslot] == left);
    2392            1043 :             BTREE_ASSERT(parent->childid[leftslot+1] == right);
    2393                 : 
    2394            1043 :             BTREE_ASSERT(leftslot == parentslot);
    2395                 :         }
    2396                 : 
    2397                 :         // shift all slots in the right node
    2398                 :     
    2399            1043 :         BTREE_ASSERT(right->slotuse + shiftnum < leafslotmax);
    2400                 : 
    2401            5215 :         for(int i = right->slotuse; i >= 0; i--)
    2402                 :         {
    2403            4172 :             right->slotkey[i + shiftnum] = right->slotkey[i];
    2404            4172 :             right->slotdata[i + shiftnum] = right->slotdata[i];
    2405                 :         }
    2406            1043 :         right->slotuse += shiftnum;
    2407                 : 
    2408                 :         // copy the last items from the left node to the first slot in the right node.
    2409            2269 :         for(unsigned int i = 0; i < shiftnum; i++)
    2410                 :         {
    2411            1226 :             right->slotkey[i] = left->slotkey[left->slotuse - shiftnum + i];
    2412            1226 :             right->slotdata[i] = left->slotdata[left->slotuse - shiftnum + i];
    2413                 :         }
    2414            1043 :         left->slotuse -= shiftnum;
    2415                 : 
    2416            1043 :         parent->slotkey[parentslot] = left->slotkey[left->slotuse-1];
    2417                 :     }
    2418                 : 
    2419                 :     /// Balance two inner nodes. The function moves key/data pairs from left to
    2420                 :     /// right so that both nodes are equally filled. The parent node is updated
    2421                 :     /// if possible.
    2422             350 :     static void shift_right_inner(inner_node *left, inner_node *right, inner_node *parent, unsigned int parentslot)
    2423                 :     {
    2424             350 :         BTREE_ASSERT(left->level == right->level);
    2425             350 :         BTREE_ASSERT(parent->level == left->level + 1);
    2426                 : 
    2427             350 :         BTREE_ASSERT(left->slotuse > right->slotuse);
    2428             350 :         BTREE_ASSERT(parent->childid[parentslot] == left);
    2429                 : 
    2430             350 :         unsigned int shiftnum = (left->slotuse - right->slotuse) / 2;
    2431                 : 
    2432                 :         BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to right " << right << " from left " << left << " with common parent " << parent << "." << std::endl);
    2433                 : 
    2434                 :         if (selfverify)
    2435                 :         {
    2436                 :             // find the left node's slot in the parent's children
    2437             350 :             unsigned int leftslot = 0;
    2438            1465 :             while(leftslot <= parent->slotuse && parent->childid[leftslot] != left)
    2439             765 :                 ++leftslot;
    2440                 : 
    2441             350 :             BTREE_ASSERT(leftslot < parent->slotuse);
    2442             350 :             BTREE_ASSERT(parent->childid[leftslot] == left);
    2443             350 :             BTREE_ASSERT(parent->childid[leftslot+1] == right);
    2444                 : 
    2445             350 :             BTREE_ASSERT(leftslot == parentslot);
    2446                 :         }
    2447                 : 
    2448                 :         // shift all slots in the right node
    2449                 : 
    2450             350 :         BTREE_ASSERT(right->slotuse + shiftnum < innerslotmax);
    2451                 :     
    2452             350 :         right->childid[right->slotuse + shiftnum] = right->childid[right->slotuse];
    2453            1400 :         for(int i = right->slotuse-1; i >= 0; i--)
    2454                 :         {
    2455            1050 :             right->slotkey[i + shiftnum] = right->slotkey[i];
    2456            1050 :             right->childid[i + shiftnum] = right->childid[i];
    2457                 :         }
    2458                 : 
    2459             350 :         right->slotuse += shiftnum;
    2460                 : 
    2461                 :         // copy the parent's decision slotkey and childid to the last new key on the right
    2462             350 :         right->slotkey[shiftnum - 1] = parent->slotkey[parentslot];
    2463             350 :         right->childid[shiftnum - 1] = left->childid[left->slotuse];
    2464                 : 
    2465                 :         // copy the remaining last items from the left node to the first slot in the right node.
    2466             458 :         for(unsigned int i = 0; i < shiftnum - 1; i++)
    2467                 :         {
    2468             108 :             right->slotkey[i] = left->slotkey[left->slotuse - shiftnum + i + 1];
    2469             108 :             right->childid[i] = left->childid[left->slotuse - shiftnum + i + 1];
    2470                 :         }
    2471                 : 
    2472                 :         // copy the first to-be-removed key from the left node to the parent's decision slot
    2473             350 :         parent->slotkey[parentslot] = left->slotkey[left->slotuse - shiftnum];
    2474                 : 
    2475             350 :         left->slotuse -= shiftnum;
    2476                 :     }
    2477                 : 
    2478                 : public:
    2479                 :     // *** Debug Printing
    2480                 : 
    2481                 :     /// Print out the B+ tree structure with keys onto std::cout. This function
    2482                 :     /// requires that the header is compiled with BTREE_PRINT and that key_type
    2483                 :     /// is printable via std::ostream.
    2484               0 :     void print() const
    2485                 :     {
    2486               0 :         print_node(root, 0, true);
    2487                 :     }
    2488                 : 
    2489                 :     /// Print out only the leaves via the double linked list.
    2490               0 :     void print_leaves() const
    2491                 :     {
    2492                 :         BTREE_PRINT("leaves:" << std::endl);
    2493                 : 
    2494               0 :         const leaf_node *n = headleaf;
    2495                 : 
    2496               0 :         while(n)
    2497                 :         {
    2498                 :             BTREE_PRINT("  " << n << std::endl);
    2499                 : 
    2500               0 :             n = n->nextleaf;
    2501                 :         }
    2502                 :     }
    2503                 : 
    2504                 : private:
    2505                 : 
    2506                 :     /// Recursively descend down the tree and print out nodes.
    2507               0 :     static void print_node(const node* node, unsigned int depth=0, bool recursive=false)
    2508                 :     {
    2509               0 :         for(unsigned int i = 0; i < depth; i++) BTREE_PRINT("  ");
    2510                 :             
    2511                 :         BTREE_PRINT("node " << node << " level " << node->level << " slotuse " << node->slotuse << std::endl);
    2512                 : 
    2513               0 :         if (node->isleafnode())
    2514                 :         {
    2515               0 :             const leaf_node *leafnode = static_cast<const leaf_node*>(node);
    2516                 : 
    2517               0 :             for(unsigned int i = 0; i < depth; i++) BTREE_PRINT("  ");
    2518                 :             BTREE_PRINT("  leaf prev " << leafnode->prevleaf << " next " << leafnode->nextleaf << std::endl);
    2519                 : 
    2520               0 :             for(unsigned int i = 0; i < depth; i++) BTREE_PRINT("  ");
    2521                 : 
    2522               0 :             for (unsigned int slot = 0; slot < leafnode->slotuse; ++slot)
    2523                 :             {
    2524                 :                 BTREE_PRINT(leafnode->slotkey[slot] << "  "); // << "(data: " << leafnode->slotdata[slot] << ") ";
    2525                 :             }
    2526                 :             BTREE_PRINT(std::endl);
    2527                 :         }
    2528                 :         else
    2529                 :         {
    2530               0 :             const inner_node *innernode = static_cast<const inner_node*>(node);
    2531                 : 
    2532               0 :             for(unsigned int i = 0; i < depth; i++) BTREE_PRINT("  ");
    2533                 : 
    2534               0 :             for (unsigned short slot = 0; slot < innernode->slotuse; ++slot)
    2535                 :             {
    2536                 :                 BTREE_PRINT("(" << innernode->childid[slot] << ") " << innernode->slotkey[slot] << " ");
    2537                 :             }
    2538                 :             BTREE_PRINT("(" << innernode->childid[innernode->slotuse] << ")");
    2539                 :             BTREE_PRINT(std::endl);
    2540                 : 
    2541               0 :             if (recursive)
    2542                 :             {
    2543               0 :                 for (unsigned short slot = 0; slot < innernode->slotuse + 1; ++slot)
    2544                 :                 {
    2545               0 :                     print_node(innernode->childid[slot], depth + 1, recursive);
    2546                 :                 }
    2547                 :             }
    2548                 :         }
    2549                 :     }
    2550                 : 
    2551                 : public:
    2552                 :     // *** Verification of B+ Tree Invariants
    2553                 : 
    2554                 :     /// Run a thorough verification of all B+ tree invariants. The program
    2555                 :     /// aborts via assert() if something is wrong.
    2556           66680 :     void verify() const
    2557                 :     {
    2558             960 :         key_type minkey, maxkey;
    2559           66680 :         tree_stats vstats;
    2560                 :         
    2561           66680 :         if (root)
    2562                 :         {
    2563           66680 :             verify_node(root, &minkey, &maxkey, vstats);
    2564                 : 
    2565           66680 :             assert( vstats.itemcount == stats.itemcount );
    2566           66680 :             assert( vstats.leaves == stats.leaves );
    2567           66680 :             assert( vstats.innernodes == stats.innernodes );
    2568                 :         }
    2569                 : 
    2570           66680 :         verify_leaflinks();
    2571                 :     }
    2572                 : 
    2573                 : private:
    2574                 : 
    2575                 :     /// Recursively descend down the tree and verify each node
    2576        61102695 :     void verify_node(const node* n, key_type* minkey, key_type* maxkey, tree_stats &vstats) const
    2577                 :     {
    2578                 :         BTREE_PRINT("verifynode " << n << std::endl);
    2579                 : 
    2580        61102695 :         if (n->isleafnode())
    2581                 :         {
    2582        49311320 :             const leaf_node *leaf = static_cast<const leaf_node*>(n);
    2583                 : 
    2584        49311320 :             assert(leaf == root || !leaf->isunderflow());
    2585                 : 
    2586       201940604 :             for(unsigned short slot = 0; slot < leaf->slotuse - 1; ++slot)
    2587                 :             {
    2588       152629284 :                 assert(key_lessequal(leaf->slotkey[slot], leaf->slotkey[slot + 1]));
    2589                 :             }
    2590                 : 
    2591        49311320 :             *minkey = leaf->slotkey[0];
    2592        49311320 :             *maxkey = leaf->slotkey[leaf->slotuse - 1];
    2593                 : 
    2594        49311320 :             vstats.leaves++;
    2595        49311320 :             vstats.itemcount += leaf->slotuse;
    2596                 :         }
    2597                 :         else // !n->isleafnode()
    2598                 :         {
    2599        11791375 :             const inner_node *inner = static_cast<const inner_node*>(n);
    2600        11791375 :             vstats.innernodes++;
    2601                 : 
    2602        11791375 :             assert(inner == root || !inner->isunderflow());
    2603                 : 
    2604        49244640 :             for(unsigned short slot = 0; slot < inner->slotuse - 1; ++slot)
    2605                 :             {
    2606        37453265 :                 assert(key_lessequal(inner->slotkey[slot], inner->slotkey[slot + 1]));
    2607                 :             }
    2608                 : 
    2609        72827390 :             for(unsigned short slot = 0; slot <= inner->slotuse; ++slot)
    2610                 :             {
    2611        61036015 :                 const node *subnode = inner->childid[slot];
    2612        61036015 :                 key_type subminkey = key_type();
    2613        61036015 :                 key_type submaxkey = key_type();
    2614                 : 
    2615        61036015 :                 assert(subnode->level + 1 == inner->level);
    2616        61036015 :                 verify_node(subnode, &subminkey, &submaxkey, vstats);
    2617                 : 
    2618                 :                 BTREE_PRINT("verify subnode " << subnode << ": " << subminkey << " - " << submaxkey << std::endl);
    2619                 : 
    2620        61036015 :                 if (slot == 0)
    2621        11791375 :                     *minkey = subminkey;
    2622                 :                 else
    2623        49244640 :                     assert(key_greaterequal(subminkey, inner->slotkey[slot-1]));
    2624                 : 
    2625        61036015 :                 if (slot == inner->slotuse)
    2626        11791375 :                     *maxkey = submaxkey;
    2627                 :                 else
    2628        49244640 :                     assert(key_equal(inner->slotkey[slot], submaxkey));
    2629                 : 
    2630        61036015 :                 if (inner->level == 1 && slot < inner->slotuse)
    2631                 :                 {
    2632                 :                     // children are leaves and must be linked together in the
    2633                 :                     // correct order
    2634        39733265 :                     const leaf_node *leafa = static_cast<const leaf_node*>(inner->childid[slot]);
    2635        39733265 :                     const leaf_node *leafb = static_cast<const leaf_node*>(inner->childid[slot + 1]);
    2636                 : 
    2637        39733265 :                     assert(leafa->nextleaf == leafb);
    2638        39733265 :                     assert(leafa == leafb->prevleaf);
    2639                 :                     (void)leafa; (void)leafb;
    2640                 :                 }
    2641        61036015 :                 if (inner->level == 2 && slot < inner->slotuse)
    2642                 :                 {
    2643                 :                     // verify leaf links between the adjacent inner nodes
    2644         7763973 :                     const inner_node *parenta = static_cast<const inner_node*>(inner->childid[slot]);
    2645         7763973 :                     const inner_node *parentb = static_cast<const inner_node*>(inner->childid[slot+1]);
    2646                 : 
    2647         7763973 :                     const leaf_node *leafa = static_cast<const leaf_node*>(parenta->childid[parenta->slotuse]);
    2648         7763973 :                     const leaf_node *leafb = static_cast<const leaf_node*>(parentb->childid[0]);
    2649                 : 
    2650         7763973 :                     assert(leafa->nextleaf == leafb);
    2651         7763973 :                     assert(leafa == leafb->prevleaf);
    2652        61102695 :                     (void)leafa; (void)leafb;
    2653                 :                 }
    2654                 :             }
    2655                 :         }
    2656                 :     }
    2657                 : 
    2658                 :     /// Verify the double linked list of leaves.
    2659           66680 :     void verify_leaflinks() const
    2660                 :     {
    2661           66680 :         const leaf_node *n = headleaf;
    2662                 : 
    2663           66680 :         assert(n->level == 0);
    2664           66680 :         assert(!n || n->prevleaf == NULL);
    2665                 : 
    2666           66680 :         unsigned int testcount = 0;
    2667                 : 
    2668        49444680 :         while(n)
    2669                 :         {
    2670        49311320 :             assert(n->level == 0);
    2671                 : 
    2672       201940604 :             for(unsigned short slot = 0; slot < n->slotuse - 1; ++slot)
    2673                 :             {
    2674       152629284 :                 assert(key_lessequal(n->slotkey[slot], n->slotkey[slot + 1]));
    2675                 :             }
    2676                 : 
    2677        49311320 :             testcount += n->slotuse;
    2678                 : 
    2679        49311320 :             if (n->nextleaf)
    2680                 :             {
    2681        49244640 :                 assert(key_lessequal(n->slotkey[n->slotuse-1], n->nextleaf->slotkey[0]));
    2682                 : 
    2683        49244640 :                 assert(n == n->nextleaf->prevleaf);
    2684                 :             }
    2685                 :             else
    2686                 :             {
    2687           66680 :                 assert(tailleaf == n);
    2688                 :             }
    2689                 : 
    2690        49311320 :             n = n->nextleaf;
    2691                 :         }
    2692                 : 
    2693           66680 :         assert(testcount == size());
    2694                 :     }
    2695                 : 
    2696                 : private:
    2697                 :     // *** Dump and Restore of B+ Trees
    2698                 : 
    2699                 :     /// \internal A header for the binary image containing the base properties
    2700                 :     /// of the B+ tree. These properties have to match the current template
    2701                 :     /// instantiation.
    2702                 :     struct dump_header
    2703                 :     {
    2704                 :         /// "stx-btree", just to stop the restore() function from loading garbage
    2705                 :         char            signature[12];
    2706                 : 
    2707                 :         /// Currently 0
    2708                 :         unsigned short  version;
    2709                 : 
    2710                 :         /// sizeof(key_type)
    2711                 :         unsigned short  key_type_size;
    2712                 : 
    2713                 :         /// sizeof(data_type)
    2714                 :         unsigned short  data_type_size;
    2715                 : 
    2716                 :         /// Number of slots in the leaves
    2717                 :         unsigned short  leafslots;
    2718                 : 
    2719                 :         /// Number of slots in the inner nodes
    2720                 :         unsigned short  innerslots;
    2721                 : 
    2722                 :         /// Allow duplicates
    2723                 :         bool            allow_duplicates;
    2724                 : 
    2725                 :         /// The item count of the tree
    2726                 :         size_type       itemcount;
    2727                 : 
    2728                 :         /// Fill the struct with the current B+ tree's properties, itemcount is
    2729                 :         /// not filled.
    2730               3 :         inline void fill()
    2731                 :         {
    2732                 :             // don't want to include string.h just for this signature
    2733               3 :             *reinterpret_cast<unsigned int*>(signature+0) = 0x2d787473;
    2734               3 :             *reinterpret_cast<unsigned int*>(signature+4) = 0x65727462;
    2735               3 :             *reinterpret_cast<unsigned int*>(signature+8) = 0x00000065;
    2736                 : 
    2737               3 :             version = 0;
    2738               3 :             key_type_size = sizeof(typename btree_self::key_type);
    2739               3 :             data_type_size = sizeof(typename btree_self::data_type);
    2740               3 :             leafslots = btree_self::leafslotmax;
    2741               3 :             innerslots = btree_self::innerslotmax;
    2742               3 :             allow_duplicates = btree_self::allow_duplicates;
    2743                 :         }
    2744                 : 
    2745                 :         /// Returns true if the headers have the same vital properties
    2746               2 :         inline bool same(const struct dump_header &o) const
    2747                 :         {
    2748                 :             return (*reinterpret_cast<const unsigned int*>(signature+0) ==
    2749                 :                     *reinterpret_cast<const unsigned int*>(o.signature+0))
    2750                 :                 && (*reinterpret_cast<const unsigned int*>(signature+4) ==
    2751                 :                     *reinterpret_cast<const unsigned int*>(o.signature+4))
    2752                 :                 && (*reinterpret_cast<const unsigned int*>(signature+8) ==
    2753                 :                     *reinterpret_cast<const unsigned int*>(o.signature+8))
    2754                 : 
    2755                 :                 && (version == o.version)
    2756                 :                 && (key_type_size == o.key_type_size)
    2757                 :                 && (data_type_size == o.data_type_size)
    2758                 :                 && (leafslots == o.leafslots)
    2759                 :                 && (innerslots == o.innerslots)
    2760               2 :                 && (allow_duplicates == o.allow_duplicates);
    2761                 :         }
    2762                 :     };
    2763                 : 
    2764                 : public:
    2765                 : 
    2766                 :     /// Dump the contents of the B+ tree out onto an ostream as a binary
    2767                 :     /// image. The image contains memory pointers which will be fixed when the
    2768                 :     /// image is restored. For this to work your key_type and data_type must be
    2769                 :     /// integral types and contain no pointers or references.
    2770               1 :     void dump(std::ostream &os) const
    2771                 :     {
    2772                 :         struct dump_header header;
    2773               1 :         header.fill();
    2774               1 :         header.itemcount = size();
    2775                 : 
    2776               1 :         os.write(reinterpret_cast<char*>(&header), sizeof(header));
    2777                 : 
    2778               1 :         if (root)
    2779               1 :             dump_node(os, root);
    2780                 :     }
    2781                 : 
    2782                 :     /// Restore a binary image of a dumped B+ tree from an istream. The B+ tree
    2783                 :     /// pointers are fixed using the dump order. For dump and restore to work
    2784                 :     /// your key_type and data_type must be integral types and contain no
    2785                 :     /// pointers or references. Returns true if the restore was successful.
    2786               2 :     bool restore(std::istream &is)
    2787                 :     {
    2788                 :         struct dump_header fileheader;
    2789               2 :         is.read(reinterpret_cast<char*>(&fileheader), sizeof(fileheader));
    2790               2 :         if (!is.good()) return false;
    2791                 : 
    2792                 :         struct dump_header myheader;
    2793               2 :         myheader.fill();
    2794               2 :         myheader.itemcount = fileheader.itemcount;
    2795                 : 
    2796               2 :         if (!myheader.same(fileheader))
    2797                 :         {
    2798                 :             BTREE_PRINT("btree::restore: file header does not match instantiation signature." << std::endl);
    2799               1 :             return false;
    2800                 :         }
    2801                 : 
    2802               1 :         clear();
    2803                 : 
    2804               1 :         if (fileheader.itemcount > 0)
    2805                 :         {
    2806               1 :             root = restore_node(is);
    2807               1 :             if (root == NULL) return false;
    2808                 : 
    2809               1 :             stats.itemcount = fileheader.itemcount;
    2810                 :         }
    2811                 : 
    2812                 :         if (debug) print();
    2813               1 :         if (selfverify) verify();
    2814                 : 
    2815               1 :         return true;
    2816                 :     }
    2817                 : 
    2818                 : private:
    2819                 : 
    2820                 :     /// Recursively descend down the tree and dump each node in a precise order
    2821             867 :     void dump_node(std::ostream &os, const node* n) const
    2822                 :     {
    2823                 :         BTREE_PRINT("dump_node " << n << std::endl);
    2824                 : 
    2825             867 :         if (n->isleafnode())
    2826                 :         {
    2827             734 :             const leaf_node *leaf = static_cast<const leaf_node*>(n);
    2828                 : 
    2829             734 :             os.write(reinterpret_cast<const char*>(leaf), sizeof(*leaf));
    2830                 :         }
    2831                 :         else // !n->isleafnode()
    2832                 :         {
    2833             133 :             const inner_node *inner = static_cast<const inner_node*>(n);
    2834                 : 
    2835             133 :             os.write(reinterpret_cast<const char*>(inner), sizeof(*inner));
    2836                 : 
    2837             999 :             for(unsigned short slot = 0; slot <= inner->slotuse; ++slot)
    2838                 :             {
    2839             866 :                 const node *subnode = inner->childid[slot];
    2840                 :                 
    2841            1733 :                 dump_node(os, subnode);
    2842                 :             }
    2843                 :         }
    2844                 :     }
    2845                 : 
    2846                 :     /// Read the dump image and construct a tree from the node order in the
    2847                 :     /// serialization.
    2848             867 :     node* restore_node(std::istream &is)
    2849                 :     {
    2850                 :         union {
    2851                 :             node        top;
    2852                 :             leaf_node   leaf;
    2853                 :             inner_node  inner;
    2854                 :         } nu;
    2855                 : 
    2856                 :         // first read only the top of the node
    2857             867 :         is.read(reinterpret_cast<char*>(&nu.top), sizeof(nu.top));
    2858             867 :         if (!is.good()) return NULL;
    2859                 : 
    2860             867 :         if (nu.top.isleafnode())
    2861                 :         {
    2862                 :             // read remaining data of leaf node
    2863             734 :             is.read(reinterpret_cast<char*>(&nu.leaf) + sizeof(nu.top), sizeof(nu.leaf) - sizeof(nu.top));
    2864             734 :             if (!is.good()) return NULL;
    2865                 :             
    2866             734 :             leaf_node *newleaf = allocate_leaf();
    2867                 : 
    2868                 :             // copy over all data, the leaf nodes contain only their double linked list pointers
    2869             734 :             *newleaf = nu.leaf;
    2870                 : 
    2871                 :             // reconstruct the linked list from the order in the file
    2872             734 :             if (headleaf == NULL) {
    2873               1 :                 BTREE_ASSERT(newleaf->prevleaf == NULL);
    2874               1 :                 headleaf = tailleaf = newleaf;
    2875                 :             }
    2876                 :             else {
    2877             733 :                 newleaf->prevleaf = tailleaf;
    2878             733 :                 tailleaf->nextleaf = newleaf;
    2879             733 :                 tailleaf = newleaf;
    2880                 :             }
    2881                 : 
    2882             734 :             return newleaf;
    2883                 :         }
    2884                 :         else
    2885                 :         {
    2886                 :             // read remaining data of inner node
    2887             133 :             is.read(reinterpret_cast<char*>(&nu.inner) + sizeof(nu.top), sizeof(nu.inner) - sizeof(nu.top));
    2888             133 :             if (!is.good()) return NULL;
    2889                 : 
    2890             133 :             inner_node *newinner = allocate_inner(0);
    2891                 : 
    2892                 :             // copy over all data, the inner nodes contain only pointers to their children
    2893             133 :             *newinner = nu.inner;
    2894                 : 
    2895             999 :             for(unsigned short slot = 0; slot <= newinner->slotuse; ++slot)
    2896                 :             {
    2897             866 :                 newinner->childid[slot] = restore_node(is);
    2898                 :             }
    2899                 : 
    2900             133 :             return newinner;
    2901                 :         }
    2902                 :     }
    2903                 : };
    2904                 : 
    2905                 : } // namespace stx
    2906                 : 
    2907                 : #endif // _STX_BTREE_H_

Generated by: LTP GCOV extension version 1.4