2 * Copyright (c) 2006 Jakub Jermar
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 /** @addtogroup genericadt
35 * @brief B+tree implementation.
37 * This file implements B+tree type and operations.
39 * The B+tree has the following properties:
40 * @li it is a ballanced 3-4-5 tree (i.e. BTREE_M = 5)
41 * @li values (i.e. pointers to values) are stored only in leaves
42 * @li leaves are linked in a list
44 * Be carefull when using these trees. They need to allocate
45 * and deallocate memory for their index nodes and as such
49 #include <adt/btree.h>
57 static void btree_destroy_subtree(btree_node_t
*root
);
58 static void _btree_insert(btree_t
*t
, btree_key_t key
, void *value
, btree_node_t
*rsubtree
, btree_node_t
*node
);
59 static void _btree_remove(btree_t
*t
, btree_key_t key
, btree_node_t
*node
);
60 static void node_initialize(btree_node_t
*node
);
61 static void node_insert_key_and_lsubtree(btree_node_t
*node
, btree_key_t key
, void *value
, btree_node_t
*lsubtree
);
62 static void node_insert_key_and_rsubtree(btree_node_t
*node
, btree_key_t key
, void *value
, btree_node_t
*rsubtree
);
63 static void node_remove_key_and_lsubtree(btree_node_t
*node
, btree_key_t key
);
64 static void node_remove_key_and_rsubtree(btree_node_t
*node
, btree_key_t key
);
65 static btree_node_t
*node_split(btree_node_t
*node
, btree_key_t key
, void *value
, btree_node_t
*rsubtree
, btree_key_t
*median
);
66 static btree_node_t
*node_combine(btree_node_t
*node
);
67 static index_t
find_key_by_subtree(btree_node_t
*node
, btree_node_t
*subtree
, bool right
);
68 static void rotate_from_right(btree_node_t
*lnode
, btree_node_t
*rnode
, index_t idx
);
69 static void rotate_from_left(btree_node_t
*lnode
, btree_node_t
*rnode
, index_t idx
);
70 static bool try_insert_by_rotation_to_left(btree_node_t
*node
, btree_key_t key
, void *value
, btree_node_t
*rsubtree
);
71 static bool try_insert_by_rotation_to_right(btree_node_t
*node
, btree_key_t key
, void *value
, btree_node_t
*rsubtree
);
72 static bool try_rotation_from_left(btree_node_t
*rnode
);
73 static bool try_rotation_from_right(btree_node_t
*lnode
);
75 #define ROOT_NODE(n) (!(n)->parent)
76 #define INDEX_NODE(n) ((n)->subtree[0] != NULL)
77 #define LEAF_NODE(n) ((n)->subtree[0] == NULL)
79 #define FILL_FACTOR ((BTREE_M-1)/2)
81 #define MEDIAN_LOW_INDEX(n) (((n)->keys-1)/2)
82 #define MEDIAN_HIGH_INDEX(n) ((n)->keys/2)
83 #define MEDIAN_LOW(n) ((n)->key[MEDIAN_LOW_INDEX((n))]);
84 #define MEDIAN_HIGH(n) ((n)->key[MEDIAN_HIGH_INDEX((n))]);
86 static slab_cache_t
*btree_node_slab
;
88 /** Initialize B-trees. */
91 btree_node_slab
= slab_cache_create("btree_node_slab", sizeof(btree_node_t
), 0, NULL
, NULL
, SLAB_CACHE_MAGDEFERRED
);
94 /** Create empty B-tree.
98 void btree_create(btree_t
*t
)
100 list_initialize(&t
->leaf_head
);
101 t
->root
= (btree_node_t
*) slab_alloc(btree_node_slab
, 0);
102 node_initialize(t
->root
);
103 list_append(&t
->root
->leaf_link
, &t
->leaf_head
);
106 /** Destroy empty B-tree. */
107 void btree_destroy(btree_t
*t
)
109 btree_destroy_subtree(t
->root
);
112 /** Insert key-value pair into B-tree.
115 * @param key Key to be inserted.
116 * @param value Value to be inserted.
117 * @param leaf_node Leaf node where the insertion should begin.
119 void btree_insert(btree_t
*t
, btree_key_t key
, void *value
, btree_node_t
*leaf_node
)
127 if (btree_search(t
, key
, &lnode
)) {
128 panic("B-tree %p already contains key %d\n", t
, key
);
132 _btree_insert(t
, key
, value
, NULL
, lnode
);
135 /** Destroy subtree rooted in a node.
137 * @param root Root of the subtree.
139 void btree_destroy_subtree(btree_node_t
*root
)
144 for (i
= 0; i
< root
->keys
+ 1; i
++) {
145 if (root
->subtree
[i
])
146 btree_destroy_subtree(root
->subtree
[i
]);
149 slab_free(btree_node_slab
, root
);
152 /** Recursively insert into B-tree.
155 * @param key Key to be inserted.
156 * @param value Value to be inserted.
157 * @param rsubtree Right subtree of the inserted key.
158 * @param node Start inserting into this node.
160 void _btree_insert(btree_t
*t
, btree_key_t key
, void *value
, btree_node_t
*rsubtree
, btree_node_t
*node
)
162 if (node
->keys
< BTREE_MAX_KEYS
) {
164 * Node conatins enough space, the key can be stored immediately.
166 node_insert_key_and_rsubtree(node
, key
, value
, rsubtree
);
167 } else if (try_insert_by_rotation_to_left(node
, key
, value
, rsubtree
)) {
169 * The key-value-rsubtree triplet has been inserted because
170 * some keys could have been moved to the left sibling.
172 } else if (try_insert_by_rotation_to_right(node
, key
, value
, rsubtree
)) {
174 * The key-value-rsubtree triplet has been inserted because
175 * some keys could have been moved to the right sibling.
182 * Node is full and both siblings (if both exist) are full too.
183 * Split the node and insert the smallest key from the node containing
184 * bigger keys (i.e. the new node) into its parent.
187 rnode
= node_split(node
, key
, value
, rsubtree
, &median
);
189 if (LEAF_NODE(node
)) {
190 list_prepend(&rnode
->leaf_link
, &node
->leaf_link
);
193 if (ROOT_NODE(node
)) {
195 * We split the root node. Create new root.
197 t
->root
= (btree_node_t
*) slab_alloc(btree_node_slab
, 0);
198 node
->parent
= t
->root
;
199 rnode
->parent
= t
->root
;
200 node_initialize(t
->root
);
203 * Left-hand side subtree will be the old root (i.e. node).
204 * Right-hand side subtree will be rnode.
206 t
->root
->subtree
[0] = node
;
208 t
->root
->depth
= node
->depth
+ 1;
210 _btree_insert(t
, median
, NULL
, rnode
, node
->parent
);
215 /** Remove B-tree node.
218 * @param key Key to be removed from the B-tree along with its associated value.
219 * @param leaf_node If not NULL, pointer to the leaf node where the key is found.
221 void btree_remove(btree_t
*t
, btree_key_t key
, btree_node_t
*leaf_node
)
227 if (!btree_search(t
, key
, &lnode
)) {
228 panic("B-tree %p does not contain key %d\n", t
, key
);
232 _btree_remove(t
, key
, lnode
);
235 /** Recursively remove B-tree node.
238 * @param key Key to be removed from the B-tree along with its associated value.
239 * @param node Node where the key being removed resides.
241 void _btree_remove(btree_t
*t
, btree_key_t key
, btree_node_t
*node
)
243 if (ROOT_NODE(node
)) {
244 if (node
->keys
== 1 && node
->subtree
[0]) {
246 * Free the current root and set new root.
248 t
->root
= node
->subtree
[0];
249 t
->root
->parent
= NULL
;
250 slab_free(btree_node_slab
, node
);
253 * Remove the key from the root node.
254 * Note that the right subtree is removed because when
255 * combining two nodes, the left-side sibling is preserved
256 * and the right-side sibling is freed.
258 node_remove_key_and_rsubtree(node
, key
);
263 if (node
->keys
<= FILL_FACTOR
) {
265 * If the node is below the fill factor,
266 * try to borrow keys from left or right sibling.
268 if (!try_rotation_from_left(node
))
269 try_rotation_from_right(node
);
272 if (node
->keys
> FILL_FACTOR
) {
276 * The key can be immediatelly removed.
278 * Note that the right subtree is removed because when
279 * combining two nodes, the left-side sibling is preserved
280 * and the right-side sibling is freed.
282 node_remove_key_and_rsubtree(node
, key
);
283 for (i
= 0; i
< node
->parent
->keys
; i
++) {
284 if (node
->parent
->key
[i
] == key
)
285 node
->parent
->key
[i
] = node
->key
[0];
290 btree_node_t
*rnode
, *parent
;
293 * The node is below the fill factor as well as its left and right sibling.
294 * Resort to combining the node with one of its siblings.
295 * The node which is on the left is preserved and the node on the right is
298 parent
= node
->parent
;
299 node_remove_key_and_rsubtree(node
, key
);
300 rnode
= node_combine(node
);
301 if (LEAF_NODE(rnode
))
302 list_remove(&rnode
->leaf_link
);
303 idx
= find_key_by_subtree(parent
, rnode
, true);
304 ASSERT((int) idx
!= -1);
305 slab_free(btree_node_slab
, rnode
);
306 _btree_remove(t
, parent
->key
[idx
], parent
);
310 /** Search key in a B-tree.
313 * @param key Key to be searched.
314 * @param leaf_node Address where to put pointer to visited leaf node.
316 * @return Pointer to value or NULL if there is no such key.
318 void *btree_search(btree_t
*t
, btree_key_t key
, btree_node_t
**leaf_node
)
320 btree_node_t
*cur
, *next
;
323 * Iteratively descend to the leaf that can contain the searched key.
325 for (cur
= t
->root
; cur
; cur
= next
) {
327 /* Last iteration will set this with proper leaf node address. */
331 * The key can be in the leftmost subtree.
332 * Test it separately.
334 if (key
< cur
->key
[0]) {
335 next
= cur
->subtree
[0];
342 * Now if the key is smaller than cur->key[i]
343 * it can only mean that the value is in cur->subtree[i]
344 * or it is not in the tree at all.
346 for (i
= 1; i
< cur
->keys
; i
++) {
347 if (key
< cur
->key
[i
]) {
348 next
= cur
->subtree
[i
];
349 val
= cur
->value
[i
- 1];
352 return key
== cur
->key
[i
- 1] ? val
: NULL
;
359 * Last possibility is that the key is in the rightmost subtree.
361 next
= cur
->subtree
[i
];
362 val
= cur
->value
[i
- 1];
364 return key
== cur
->key
[i
- 1] ? val
: NULL
;
371 * The key was not found in the *leaf_node and is smaller than any of its keys.
376 /** Return pointer to B-tree leaf node's left neighbour.
379 * @param node Node whose left neighbour will be returned.
381 * @return Left neighbour of the node or NULL if the node does not have the left neighbour.
383 btree_node_t
*btree_leaf_node_left_neighbour(btree_t
*t
, btree_node_t
*node
)
385 ASSERT(LEAF_NODE(node
));
386 if (node
->leaf_link
.prev
!= &t
->leaf_head
)
387 return list_get_instance(node
->leaf_link
.prev
, btree_node_t
, leaf_link
);
392 /** Return pointer to B-tree leaf node's right neighbour.
395 * @param node Node whose right neighbour will be returned.
397 * @return Right neighbour of the node or NULL if the node does not have the right neighbour.
399 btree_node_t
*btree_leaf_node_right_neighbour(btree_t
*t
, btree_node_t
*node
)
401 ASSERT(LEAF_NODE(node
));
402 if (node
->leaf_link
.next
!= &t
->leaf_head
)
403 return list_get_instance(node
->leaf_link
.next
, btree_node_t
, leaf_link
);
408 /** Initialize B-tree node.
410 * @param node B-tree node.
412 void node_initialize(btree_node_t
*node
)
418 /* Clean also space for the extra key. */
419 for (i
= 0; i
< BTREE_MAX_KEYS
+ 1; i
++) {
421 node
->value
[i
] = NULL
;
422 node
->subtree
[i
] = NULL
;
424 node
->subtree
[i
] = NULL
;
428 link_initialize(&node
->leaf_link
);
430 link_initialize(&node
->bfs_link
);
434 /** Insert key-value-lsubtree triplet into B-tree node.
436 * It is actually possible to have more keys than BTREE_MAX_KEYS.
437 * This feature is used during insert by right rotation.
439 * @param node B-tree node into wich the new key is to be inserted.
440 * @param key The key to be inserted.
441 * @param value Pointer to value to be inserted.
442 * @param lsubtree Pointer to the left subtree.
444 void node_insert_key_and_lsubtree(btree_node_t
*node
, btree_key_t key
, void *value
, btree_node_t
*lsubtree
)
448 for (i
= 0; i
< node
->keys
; i
++) {
449 if (key
< node
->key
[i
]) {
452 for (j
= node
->keys
; j
> i
; j
--) {
453 node
->key
[j
] = node
->key
[j
- 1];
454 node
->value
[j
] = node
->value
[j
- 1];
455 node
->subtree
[j
+ 1] = node
->subtree
[j
];
457 node
->subtree
[j
+ 1] = node
->subtree
[j
];
462 node
->value
[i
] = value
;
463 node
->subtree
[i
] = lsubtree
;
468 /** Insert key-value-rsubtree triplet into B-tree node.
470 * It is actually possible to have more keys than BTREE_MAX_KEYS.
471 * This feature is used during splitting the node when the
472 * number of keys is BTREE_MAX_KEYS + 1. Insert by left rotation
473 * also makes use of this feature.
475 * @param node B-tree node into wich the new key is to be inserted.
476 * @param key The key to be inserted.
477 * @param value Pointer to value to be inserted.
478 * @param rsubtree Pointer to the right subtree.
480 void node_insert_key_and_rsubtree(btree_node_t
*node
, btree_key_t key
, void *value
, btree_node_t
*rsubtree
)
484 for (i
= 0; i
< node
->keys
; i
++) {
485 if (key
< node
->key
[i
]) {
488 for (j
= node
->keys
; j
> i
; j
--) {
489 node
->key
[j
] = node
->key
[j
- 1];
490 node
->value
[j
] = node
->value
[j
- 1];
491 node
->subtree
[j
+ 1] = node
->subtree
[j
];
497 node
->value
[i
] = value
;
498 node
->subtree
[i
+ 1] = rsubtree
;
503 /** Remove key and its left subtree pointer from B-tree node.
505 * Remove the key and eliminate gaps in node->key array.
506 * Note that the value pointer and the left subtree pointer
507 * is removed from the node as well.
509 * @param node B-tree node.
510 * @param key Key to be removed.
512 void node_remove_key_and_lsubtree(btree_node_t
*node
, btree_key_t key
)
516 for (i
= 0; i
< node
->keys
; i
++) {
517 if (key
== node
->key
[i
]) {
518 for (j
= i
+ 1; j
< node
->keys
; j
++) {
519 node
->key
[j
- 1] = node
->key
[j
];
520 node
->value
[j
- 1] = node
->value
[j
];
521 node
->subtree
[j
- 1] = node
->subtree
[j
];
523 node
->subtree
[j
- 1] = node
->subtree
[j
];
528 panic("node %p does not contain key %d\n", node
, key
);
531 /** Remove key and its right subtree pointer from B-tree node.
533 * Remove the key and eliminate gaps in node->key array.
534 * Note that the value pointer and the right subtree pointer
535 * is removed from the node as well.
537 * @param node B-tree node.
538 * @param key Key to be removed.
540 void node_remove_key_and_rsubtree(btree_node_t
*node
, btree_key_t key
)
544 for (i
= 0; i
< node
->keys
; i
++) {
545 if (key
== node
->key
[i
]) {
546 for (j
= i
+ 1; j
< node
->keys
; j
++) {
547 node
->key
[j
- 1] = node
->key
[j
];
548 node
->value
[j
- 1] = node
->value
[j
];
549 node
->subtree
[j
] = node
->subtree
[j
+ 1];
555 panic("node %p does not contain key %d\n", node
, key
);
558 /** Split full B-tree node and insert new key-value-right-subtree triplet.
560 * This function will split a node and return a pointer to a newly created
561 * node containing keys greater than or equal to the greater of medians
562 * (or median) of the old keys and the newly added key. It will also write
563 * the median key to a memory address supplied by the caller.
565 * If the node being split is an index node, the median will not be
566 * included in the new node. If the node is a leaf node,
567 * the median will be copied there.
569 * @param node B-tree node wich is going to be split.
570 * @param key The key to be inserted.
571 * @param value Pointer to the value to be inserted.
572 * @param rsubtree Pointer to the right subtree of the key being added.
573 * @param median Address in memory, where the median key will be stored.
575 * @return Newly created right sibling of node.
577 btree_node_t
*node_split(btree_node_t
*node
, btree_key_t key
, void *value
, btree_node_t
*rsubtree
, btree_key_t
*median
)
583 ASSERT(node
->keys
== BTREE_MAX_KEYS
);
586 * Use the extra space to store the extra node.
588 node_insert_key_and_rsubtree(node
, key
, value
, rsubtree
);
591 * Compute median of keys.
593 *median
= MEDIAN_HIGH(node
);
596 * Allocate and initialize new right sibling.
598 rnode
= (btree_node_t
*) slab_alloc(btree_node_slab
, 0);
599 node_initialize(rnode
);
600 rnode
->parent
= node
->parent
;
601 rnode
->depth
= node
->depth
;
604 * Copy big keys, values and subtree pointers to the new right sibling.
605 * If this is an index node, do not copy the median.
607 i
= (int) INDEX_NODE(node
);
608 for (i
+= MEDIAN_HIGH_INDEX(node
), j
= 0; i
< node
->keys
; i
++, j
++) {
609 rnode
->key
[j
] = node
->key
[i
];
610 rnode
->value
[j
] = node
->value
[i
];
611 rnode
->subtree
[j
] = node
->subtree
[i
];
614 * Fix parent links in subtrees.
616 if (rnode
->subtree
[j
])
617 rnode
->subtree
[j
]->parent
= rnode
;
620 rnode
->subtree
[j
] = node
->subtree
[i
];
621 if (rnode
->subtree
[j
])
622 rnode
->subtree
[j
]->parent
= rnode
;
624 rnode
->keys
= j
; /* Set number of keys of the new node. */
625 node
->keys
/= 2; /* Shrink the old node. */
630 /** Combine node with any of its siblings.
632 * The siblings are required to be below the fill factor.
634 * @param node Node to combine with one of its siblings.
636 * @return Pointer to the rightmost of the two nodes.
638 btree_node_t
*node_combine(btree_node_t
*node
)
644 ASSERT(!ROOT_NODE(node
));
646 idx
= find_key_by_subtree(node
->parent
, node
, false);
647 if (idx
== node
->parent
->keys
) {
649 * Rightmost subtree of its parent, combine with the left sibling.
653 node
= node
->parent
->subtree
[idx
];
655 rnode
= node
->parent
->subtree
[idx
+ 1];
658 /* Index nodes need to insert parent node key in between left and right node. */
659 if (INDEX_NODE(node
))
660 node
->key
[node
->keys
++] = node
->parent
->key
[idx
];
662 /* Copy the key-value-subtree triplets from the right node. */
663 for (i
= 0; i
< rnode
->keys
; i
++) {
664 node
->key
[node
->keys
+ i
] = rnode
->key
[i
];
665 node
->value
[node
->keys
+ i
] = rnode
->value
[i
];
666 if (INDEX_NODE(node
)) {
667 node
->subtree
[node
->keys
+ i
] = rnode
->subtree
[i
];
668 rnode
->subtree
[i
]->parent
= node
;
671 if (INDEX_NODE(node
)) {
672 node
->subtree
[node
->keys
+ i
] = rnode
->subtree
[i
];
673 rnode
->subtree
[i
]->parent
= node
;
676 node
->keys
+= rnode
->keys
;
681 /** Find key by its left or right subtree.
683 * @param node B-tree node.
684 * @param subtree Left or right subtree of a key found in node.
685 * @param right If true, subtree is a right subtree. If false, subtree is a left subtree.
687 * @return Index of the key associated with the subtree.
689 index_t
find_key_by_subtree(btree_node_t
*node
, btree_node_t
*subtree
, bool right
)
693 for (i
= 0; i
< node
->keys
+ 1; i
++) {
694 if (subtree
== node
->subtree
[i
])
695 return i
- (int) (right
!= false);
697 panic("node %p does not contain subtree %p\n", node
, subtree
);
700 /** Rotate one key-value-rsubtree triplet from the left sibling to the right sibling.
702 * The biggest key and its value and right subtree is rotated from the left node
703 * to the right. If the node is an index node, than the parent node key belonging to
704 * the left node takes part in the rotation.
706 * @param lnode Left sibling.
707 * @param rnode Right sibling.
708 * @param idx Index of the parent node key that is taking part in the rotation.
710 void rotate_from_left(btree_node_t
*lnode
, btree_node_t
*rnode
, index_t idx
)
714 key
= lnode
->key
[lnode
->keys
- 1];
716 if (LEAF_NODE(lnode
)) {
719 value
= lnode
->value
[lnode
->keys
- 1];
720 node_remove_key_and_rsubtree(lnode
, key
);
721 node_insert_key_and_lsubtree(rnode
, key
, value
, NULL
);
722 lnode
->parent
->key
[idx
] = key
;
724 btree_node_t
*rsubtree
;
726 rsubtree
= lnode
->subtree
[lnode
->keys
];
727 node_remove_key_and_rsubtree(lnode
, key
);
728 node_insert_key_and_lsubtree(rnode
, lnode
->parent
->key
[idx
], NULL
, rsubtree
);
729 lnode
->parent
->key
[idx
] = key
;
731 /* Fix parent link of the reconnected right subtree. */
732 rsubtree
->parent
= rnode
;
737 /** Rotate one key-value-lsubtree triplet from the right sibling to the left sibling.
739 * The smallest key and its value and left subtree is rotated from the right node
740 * to the left. If the node is an index node, than the parent node key belonging to
741 * the right node takes part in the rotation.
743 * @param lnode Left sibling.
744 * @param rnode Right sibling.
745 * @param idx Index of the parent node key that is taking part in the rotation.
747 void rotate_from_right(btree_node_t
*lnode
, btree_node_t
*rnode
, index_t idx
)
753 if (LEAF_NODE(rnode
)) {
756 value
= rnode
->value
[0];
757 node_remove_key_and_lsubtree(rnode
, key
);
758 node_insert_key_and_rsubtree(lnode
, key
, value
, NULL
);
759 rnode
->parent
->key
[idx
] = rnode
->key
[0];
761 btree_node_t
*lsubtree
;
763 lsubtree
= rnode
->subtree
[0];
764 node_remove_key_and_lsubtree(rnode
, key
);
765 node_insert_key_and_rsubtree(lnode
, rnode
->parent
->key
[idx
], NULL
, lsubtree
);
766 rnode
->parent
->key
[idx
] = key
;
768 /* Fix parent link of the reconnected left subtree. */
769 lsubtree
->parent
= lnode
;
774 /** Insert key-value-rsubtree triplet and rotate the node to the left, if this operation can be done.
776 * Left sibling of the node (if it exists) is checked for free space.
777 * If there is free space, the key is inserted and the smallest key of
778 * the node is moved there. The index node which is the parent of both
781 * @param node B-tree node.
782 * @param inskey Key to be inserted.
783 * @param insvalue Value to be inserted.
784 * @param rsubtree Right subtree of inskey.
786 * @return True if the rotation was performed, false otherwise.
788 bool try_insert_by_rotation_to_left(btree_node_t
*node
, btree_key_t inskey
, void *insvalue
, btree_node_t
*rsubtree
)
794 * If this is root node, the rotation can not be done.
799 idx
= find_key_by_subtree(node
->parent
, node
, true);
800 if ((int) idx
== -1) {
802 * If this node is the leftmost subtree of its parent,
803 * the rotation can not be done.
808 lnode
= node
->parent
->subtree
[idx
];
809 if (lnode
->keys
< BTREE_MAX_KEYS
) {
811 * The rotaion can be done. The left sibling has free space.
813 node_insert_key_and_rsubtree(node
, inskey
, insvalue
, rsubtree
);
814 rotate_from_right(lnode
, node
, idx
);
821 /** Insert key-value-rsubtree triplet and rotate the node to the right, if this operation can be done.
823 * Right sibling of the node (if it exists) is checked for free space.
824 * If there is free space, the key is inserted and the biggest key of
825 * the node is moved there. The index node which is the parent of both
828 * @param node B-tree node.
829 * @param inskey Key to be inserted.
830 * @param insvalue Value to be inserted.
831 * @param rsubtree Right subtree of inskey.
833 * @return True if the rotation was performed, false otherwise.
835 bool try_insert_by_rotation_to_right(btree_node_t
*node
, btree_key_t inskey
, void *insvalue
, btree_node_t
*rsubtree
)
841 * If this is root node, the rotation can not be done.
846 idx
= find_key_by_subtree(node
->parent
, node
, false);
847 if (idx
== node
->parent
->keys
) {
849 * If this node is the rightmost subtree of its parent,
850 * the rotation can not be done.
855 rnode
= node
->parent
->subtree
[idx
+ 1];
856 if (rnode
->keys
< BTREE_MAX_KEYS
) {
858 * The rotaion can be done. The right sibling has free space.
860 node_insert_key_and_rsubtree(node
, inskey
, insvalue
, rsubtree
);
861 rotate_from_left(node
, rnode
, idx
);
868 /** Rotate in a key from the left sibling or from the index node, if this operation can be done.
870 * @param rnode Node into which to add key from its left sibling or from the index node.
872 * @return True if the rotation was performed, false otherwise.
874 bool try_rotation_from_left(btree_node_t
*rnode
)
880 * If this is root node, the rotation can not be done.
882 if (ROOT_NODE(rnode
))
885 idx
= find_key_by_subtree(rnode
->parent
, rnode
, true);
886 if ((int) idx
== -1) {
888 * If this node is the leftmost subtree of its parent,
889 * the rotation can not be done.
894 lnode
= rnode
->parent
->subtree
[idx
];
895 if (lnode
->keys
> FILL_FACTOR
) {
896 rotate_from_left(lnode
, rnode
, idx
);
903 /** Rotate in a key from the right sibling or from the index node, if this operation can be done.
905 * @param lnode Node into which to add key from its right sibling or from the index node.
907 * @return True if the rotation was performed, false otherwise.
909 bool try_rotation_from_right(btree_node_t
*lnode
)
915 * If this is root node, the rotation can not be done.
917 if (ROOT_NODE(lnode
))
920 idx
= find_key_by_subtree(lnode
->parent
, lnode
, false);
921 if (idx
== lnode
->parent
->keys
) {
923 * If this node is the rightmost subtree of its parent,
924 * the rotation can not be done.
929 rnode
= lnode
->parent
->subtree
[idx
+ 1];
930 if (rnode
->keys
> FILL_FACTOR
) {
931 rotate_from_right(lnode
, rnode
, idx
);
940 * @param t Print out B-tree.
942 void btree_print(btree_t
*t
)
944 int i
, depth
= t
->root
->depth
;
947 printf("Printing B-tree:\n");
948 list_initialize(&head
);
949 list_append(&t
->root
->bfs_link
, &head
);
952 * Use BFS search to print out the tree.
953 * Levels are distinguished from one another by node->depth.
955 while (!list_empty(&head
)) {
960 ASSERT(hlp
!= &head
);
961 node
= list_get_instance(hlp
, btree_node_t
, bfs_link
);
966 if (node
->depth
!= depth
) {
972 for (i
= 0; i
< node
->keys
; i
++) {
973 printf("%lld%s", node
->key
[i
], i
< node
->keys
- 1 ? "," : "");
974 if (node
->depth
&& node
->subtree
[i
]) {
975 list_append(&node
->subtree
[i
]->bfs_link
, &head
);
978 if (node
->depth
&& node
->subtree
[i
]) {
979 list_append(&node
->subtree
[i
]->bfs_link
, &head
);
985 printf("Printing list of leaves:\n");
986 for (cur
= t
->leaf_head
.next
; cur
!= &t
->leaf_head
; cur
= cur
->next
) {
989 node
= list_get_instance(cur
, btree_node_t
, leaf_link
);
994 for (i
= 0; i
< node
->keys
; i
++)
995 printf("%lld%s", node
->key
[i
], i
< node
->keys
- 1 ? "," : "");