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