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