]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - repair/btree.c
2 * Copyright (c) 2007, Silicon Graphics, Inc. Barry Naujok <bnaujok@sgi.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 * Maximum number of keys per node. Must be greater than 2 for the code
26 #define BTREE_KEY_MAX 7
27 #define BTREE_KEY_MIN (BTREE_KEY_MAX / 2)
29 #define BTREE_PTR_MAX (BTREE_KEY_MAX + 1)
32 unsigned long num_keys
;
33 unsigned long keys
[BTREE_KEY_MAX
];
34 struct btree_node
*ptrs
[BTREE_PTR_MAX
];
38 struct btree_node
*node
;
43 struct btree_node
*root_node
;
44 struct btree_cursor
*cursor
; /* track path to end leaf */
47 int keys_valid
; /* set if the cache is valid */
48 unsigned long cur_key
;
49 unsigned long next_key
;
51 unsigned long prev_key
;
55 unsigned long num_items
;
56 unsigned long max_items
;
80 static struct btree_node
*
81 btree_node_alloc(void)
83 return calloc(1, sizeof(struct btree_node
));
88 struct btree_node
*node
)
95 struct btree_node
*node
,
101 for (i
= 0; i
<= node
->num_keys
; i
++)
102 btree_free_nodes(node
->ptrs
[i
], level
- 1);
103 btree_node_free(node
);
108 struct btree_root
*root
)
110 memset(root
, 0, sizeof(struct btree_root
));
112 root
->cursor
= calloc(1, sizeof(struct btree_cursor
));
113 root
->root_node
= btree_node_alloc();
114 ASSERT(root
->root_node
);
116 root
->stats
.max_items
= 1;
117 root
->stats
.alloced
+= 1;
123 struct btree_root
*root
)
125 btree_free_nodes(root
->root_node
, root
->height
- 1);
129 root
->root_node
= NULL
;
134 struct btree_root
**root
)
136 *root
= calloc(1, sizeof(struct btree_root
));
142 struct btree_root
*root
)
150 struct btree_root
*root
)
158 struct btree_root
*root
)
160 return root
->root_node
->num_keys
== 0;
164 btree_invalidate_cursor(
165 struct btree_root
*root
)
167 root
->cursor
[0].node
= NULL
;
168 root
->keys_valid
= 0;
171 static inline unsigned long
173 struct btree_cursor
*cursor
,
176 while (cursor
->node
->num_keys
== cursor
->index
&& --height
> 0)
178 return cursor
->node
->keys
[cursor
->index
];
183 struct btree_root
*root
,
186 struct btree_cursor
*cur
= root
->cursor
;
188 struct btree_node
*node
;
190 if (cur
->index
> 0) {
192 *key
= cur
->node
->keys
[cur
->index
- 1];
193 return cur
->node
->ptrs
[cur
->index
- 1];
196 /* else need to go up and back down the tree to find the previous */
201 } while (++level
< root
->height
);
203 if (level
== root
->height
)
206 /* the key is in the current level */
208 *key
= cur
->node
->keys
[cur
->index
- 1];
210 /* descend back down the right side to get the pointer */
211 node
= cur
->node
->ptrs
[cur
->index
- 1];
213 node
= node
->ptrs
[node
->num_keys
];
219 struct btree_root
*root
,
222 struct btree_cursor
*cur
= root
->cursor
;
224 struct btree_node
*node
;
226 while (cur
->index
== cur
->node
->num_keys
) {
227 if (++level
== root
->height
)
234 *key
= btree_key_of_cursor(cur
, root
->height
);
237 return cur
->node
->ptrs
[cur
->index
+ 1];
240 node
= cur
->node
->ptrs
[cur
->index
+ 1];
242 node
= node
->ptrs
[0];
244 *key
= node
->keys
[0];
245 return node
->ptrs
[0];
249 * Lookup/Search functions
254 struct btree_root
*root
,
258 struct btree_cursor
*cur
= root
->cursor
+ root
->height
;
259 struct btree_node
*node
= root
->root_node
;
260 int height
= root
->height
;
264 while (--height
>= 0) {
266 for (i
= 0; i
< node
->num_keys
; i
++)
267 if (node
->keys
[i
] >= key
) {
274 node
= node
->ptrs
[i
];
276 root
->keys_valid
= key_found
;
281 root
->next_value
= NULL
; /* do on-demand next value lookup */
282 root
->prev_value
= btree_get_prev(root
, &root
->prev_key
);
288 struct btree_root
*root
,
291 if (root
->keys_valid
&& key
<= root
->cur_key
&&
292 (!root
->prev_value
|| key
> root
->prev_key
)) {
294 root
->stats
.cache_hits
++;
299 root
->stats
.cache_misses
++;
301 return btree_do_search(root
, key
);
306 struct btree_root
*root
,
308 unsigned long *actual_key
)
311 root
->stats
.find
+= 1;
313 if (!btree_search(root
, key
))
317 *actual_key
= root
->cur_key
;
318 return root
->cursor
->node
->ptrs
[root
->cursor
->index
];
323 struct btree_root
*root
,
327 root
->stats
.lookup
+= 1;
329 if (!btree_search(root
, key
) || root
->cur_key
!= key
)
331 return root
->cursor
->node
->ptrs
[root
->cursor
->index
];
336 struct btree_root
*root
,
339 if (!root
->keys_valid
)
342 *key
= root
->prev_key
;
343 return root
->prev_value
;
348 struct btree_root
*root
,
351 if (!root
->keys_valid
)
353 if (!root
->next_value
)
354 root
->next_value
= btree_get_next(root
, &root
->next_key
);
356 *key
= root
->next_key
;
357 return root
->next_value
;
361 btree_move_cursor_to_next(
362 struct btree_root
*root
,
365 struct btree_cursor
*cur
= root
->cursor
;
368 while (cur
->index
== cur
->node
->num_keys
) {
369 if (++level
== root
->height
)
376 *key
= btree_key_of_cursor(cur
, root
->height
);
377 return cur
->node
->ptrs
[cur
->index
];
380 while (--level
>= 0) {
381 root
->cursor
[level
].node
= cur
->node
->ptrs
[cur
->index
];
382 root
->cursor
[level
].index
= 0;
386 *key
= cur
->node
->keys
[0];
387 return cur
->node
->ptrs
[0];
392 struct btree_root
*root
,
397 if (!root
->keys_valid
)
400 root
->prev_key
= root
->cur_key
;
401 root
->prev_value
= root
->cursor
->node
->ptrs
[root
->cursor
->index
];
403 value
= btree_move_cursor_to_next(root
, &root
->cur_key
);
405 btree_invalidate_cursor(root
);
408 root
->next_value
= NULL
; /* on-demand next value fetch */
410 *key
= root
->cur_key
;
415 btree_move_cursor_to_prev(
416 struct btree_root
*root
,
419 struct btree_cursor
*cur
= root
->cursor
;
422 while (cur
->index
== 0) {
423 if (++level
== root
->height
)
428 if (key
) /* the key is in the current level */
429 *key
= cur
->node
->keys
[cur
->index
];
432 root
->cursor
[level
].node
= cur
->node
->ptrs
[cur
->index
];
433 root
->cursor
[level
].index
= root
->cursor
[level
].node
->num_keys
;
436 return cur
->node
->ptrs
[cur
->index
];
441 struct btree_root
*root
,
446 if (!root
->keys_valid
)
449 value
= btree_move_cursor_to_prev(root
, &root
->cur_key
);
452 root
->prev_value
= btree_get_prev(root
, &root
->prev_key
);
453 root
->next_value
= NULL
; /* on-demand next value fetch */
455 *key
= root
->cur_key
;
460 btree_uncached_lookup(
461 struct btree_root
*root
,
464 /* cursor-less (ie. uncached) lookup */
465 int height
= root
->height
- 1;
466 struct btree_node
*node
= root
->root_node
;
470 while (height
>= 0) {
471 for (i
= 0; i
< node
->num_keys
; i
++)
472 if (node
->keys
[i
] >= key
) {
473 key_found
= node
->keys
[i
] == key
;
476 node
= node
->ptrs
[i
];
479 return key_found
? node
: NULL
;
482 /* Update functions */
485 btree_update_node_key(
486 struct btree_root
*root
,
487 struct btree_cursor
*cursor
,
489 unsigned long new_key
)
494 root
->stats
.key_update
+= 1;
498 for (i
= level
; i
< root
->height
; i
++) {
499 if (cursor
->index
< cursor
->node
->num_keys
) {
500 cursor
->node
->keys
[cursor
->index
] = new_key
;
509 struct btree_root
*root
,
510 unsigned long old_key
,
511 unsigned long new_key
)
513 if (!btree_search(root
, old_key
) || root
->cur_key
!= old_key
)
516 if (root
->next_value
&& new_key
>= root
->next_key
)
519 if (root
->prev_value
&& new_key
<= root
->prev_key
)
522 btree_update_node_key(root
, root
->cursor
, 0, new_key
);
523 root
->cur_key
= new_key
;
530 struct btree_root
*root
,
537 if (!btree_search(root
, key
) || root
->cur_key
!= key
)
541 root
->stats
.value_update
+= 1;
543 root
->cursor
->node
->ptrs
[root
->cursor
->index
] = new_value
;
549 * Cursor modification functions - used for inserting and deleting
552 static struct btree_cursor
*
553 btree_copy_cursor_prev(
554 struct btree_root
*root
,
555 struct btree_cursor
*dest_cursor
,
558 struct btree_cursor
*src_cur
= root
->cursor
+ level
;
559 struct btree_cursor
*dst_cur
;
563 if (level
>= root
->height
)
566 while (src_cur
->index
== 0) {
567 if (++l
>= root
->height
)
571 for (i
= l
; i
< root
->height
; i
++)
572 dest_cursor
[i
] = *src_cur
++;
574 dst_cur
= dest_cursor
+ l
;
576 while (l
-- >= level
) {
577 dest_cursor
[l
].node
= dst_cur
->node
->ptrs
[dst_cur
->index
];
578 dest_cursor
[l
].index
= dest_cursor
[l
].node
->num_keys
;
584 static struct btree_cursor
*
585 btree_copy_cursor_next(
586 struct btree_root
*root
,
587 struct btree_cursor
*dest_cursor
,
590 struct btree_cursor
*src_cur
= root
->cursor
+ level
;
591 struct btree_cursor
*dst_cur
;
595 if (level
>= root
->height
)
598 while (src_cur
->index
== src_cur
->node
->num_keys
) {
599 if (++l
>= root
->height
)
603 for (i
= l
; i
< root
->height
; i
++)
604 dest_cursor
[i
] = *src_cur
++;
606 dst_cur
= dest_cursor
+ l
;
608 while (l
-- >= level
) {
609 dest_cursor
[l
].node
= dst_cur
->node
->ptrs
[dst_cur
->index
];
610 dest_cursor
[l
].index
= 0;
619 * Tries to move items in the current leaf to its sibling if it has space.
620 * Used in both insert and delete functions.
621 * Returns the number of items shifted.
626 struct btree_root
*root
,
628 struct btree_cursor
*prev_cursor
,
631 struct btree_node
*node
;
632 struct btree_node
*prev_node
;
633 int num_remain
; /* # of keys left in "node" */
637 if (!prev_cursor
|| !num_children
)
640 prev_node
= prev_cursor
[level
].node
;
641 node
= root
->cursor
[level
].node
;
643 ASSERT(num_children
> 0 && num_children
<= node
->num_keys
+ 1);
645 if ((prev_node
->num_keys
+ num_children
) > BTREE_KEY_MAX
)
649 root
->stats
.shift_prev
+= 1;
652 num_remain
= node
->num_keys
- num_children
;
653 ASSERT(num_remain
== -1 || num_remain
>= BTREE_KEY_MIN
);
655 /* shift parent keys around */
658 key
= node
->keys
[num_children
- 1];
660 key
= btree_key_of_cursor(root
->cursor
+ level
,
661 root
->height
- level
);
662 while (prev_cursor
[level
].index
== prev_cursor
[level
].node
->num_keys
) {
664 ASSERT(level
< root
->height
);
666 prev_node
->keys
[prev_node
->num_keys
] =
667 prev_cursor
[level
].node
->keys
[prev_cursor
[level
].index
];
668 prev_cursor
[level
].node
->keys
[prev_cursor
[level
].index
] = key
;
670 /* copy pointers and keys to the end of the prev node */
671 for (i
= 0; i
< num_children
- 1; i
++) {
672 prev_node
->keys
[prev_node
->num_keys
+ 1 + i
] = node
->keys
[i
];
673 prev_node
->ptrs
[prev_node
->num_keys
+ 1 + i
] = node
->ptrs
[i
];
675 prev_node
->ptrs
[prev_node
->num_keys
+ 1 + i
] = node
->ptrs
[i
];
676 prev_node
->num_keys
+= num_children
;
678 /* move remaining pointers/keys to start of node */
679 if (num_remain
>= 0) {
680 for (i
= 0; i
< num_remain
; i
++) {
681 node
->keys
[i
] = node
->keys
[num_children
+ i
];
682 node
->ptrs
[i
] = node
->ptrs
[num_children
+ i
];
684 node
->ptrs
[i
] = node
->ptrs
[num_children
+ i
];
685 node
->num_keys
= num_remain
;
694 struct btree_root
*root
,
696 struct btree_cursor
*next_cursor
,
699 struct btree_node
*node
;
700 struct btree_node
*next_node
;
701 int num_remain
; /* # of children left in node */
704 if (!next_cursor
|| !num_children
)
707 node
= root
->cursor
[level
].node
;
708 next_node
= next_cursor
[level
].node
;
710 ASSERT(num_children
> 0 && num_children
<= node
->num_keys
+ 1);
712 if ((next_node
->num_keys
+ num_children
) > BTREE_KEY_MAX
)
715 num_remain
= node
->num_keys
+ 1 - num_children
;
716 ASSERT(num_remain
== 0 || num_remain
> BTREE_KEY_MIN
);
719 root
->stats
.shift_next
+= 1;
722 /* make space for "num_children" items at beginning of next-leaf */
723 i
= next_node
->num_keys
;
724 next_node
->ptrs
[num_children
+ i
] = next_node
->ptrs
[i
];
726 next_node
->keys
[num_children
+ i
] = next_node
->keys
[i
];
727 next_node
->ptrs
[num_children
+ i
] = next_node
->ptrs
[i
];
730 /* update keys in parent and next node from parent */
733 ASSERT(level
< root
->height
);
734 } while (root
->cursor
[level
].index
==
735 root
->cursor
[level
].node
->num_keys
);
737 next_node
->keys
[num_children
- 1] =
738 root
->cursor
[level
].node
->keys
[root
->cursor
[level
].index
];
739 root
->cursor
[level
].node
->keys
[root
->cursor
[level
].index
] =
740 node
->keys
[node
->num_keys
- num_children
];
742 /* copy last "num_children" items from node into start of next-node */
743 for (i
= 0; i
< num_children
- 1; i
++) {
744 next_node
->keys
[i
] = node
->keys
[num_remain
+ i
];
745 next_node
->ptrs
[i
] = node
->ptrs
[num_remain
+ i
];
747 next_node
->ptrs
[i
] = node
->ptrs
[num_remain
+ i
];
748 next_node
->num_keys
+= num_children
;
751 node
->num_keys
-= num_children
;
759 * Insertion functions
762 static struct btree_node
*
763 btree_increase_height(
764 struct btree_root
*root
)
766 struct btree_node
*new_root
;
767 struct btree_cursor
*new_cursor
;
769 new_cursor
= realloc(root
->cursor
, (root
->height
+ 1) *
770 sizeof(struct btree_cursor
));
773 root
->cursor
= new_cursor
;
775 new_root
= btree_node_alloc();
780 root
->stats
.alloced
+= 1;
781 root
->stats
.inc_height
+= 1;
782 root
->stats
.max_items
*= BTREE_PTR_MAX
;
785 new_root
->ptrs
[0] = root
->root_node
;
786 root
->root_node
= new_root
;
788 root
->cursor
[root
->height
].node
= new_root
;
789 root
->cursor
[root
->height
].index
= 0;
798 struct btree_root
*root
,
804 static struct btree_node
*
806 struct btree_root
*root
,
811 struct btree_node
*node
= root
->cursor
[level
].node
;
812 struct btree_node
*new_node
;
815 new_node
= btree_node_alloc();
819 if (btree_insert_item(root
, level
+ 1, node
->keys
[BTREE_KEY_MIN
],
821 btree_node_free(new_node
);
826 root
->stats
.alloced
+= 1;
827 root
->stats
.split
+= 1;
830 for (i
= 0; i
< BTREE_KEY_MAX
- BTREE_KEY_MIN
- 1; i
++) {
831 new_node
->keys
[i
] = node
->keys
[BTREE_KEY_MIN
+ 1 + i
];
832 new_node
->ptrs
[i
] = node
->ptrs
[BTREE_KEY_MIN
+ 1 + i
];
834 new_node
->ptrs
[i
] = node
->ptrs
[BTREE_KEY_MIN
+ 1 + i
];
835 new_node
->num_keys
= BTREE_KEY_MAX
- BTREE_KEY_MIN
- 1;
837 node
->num_keys
= BTREE_KEY_MIN
;
838 if (key
< node
->keys
[BTREE_KEY_MIN
])
839 return node
; /* index doesn't change */
841 /* insertion point is in new node... */
842 *index
-= BTREE_KEY_MIN
+ 1;
847 btree_insert_shift_to_prev(
848 struct btree_root
*root
,
852 struct btree_cursor tmp_cursor
[root
->height
];
858 if (!btree_copy_cursor_prev(root
, tmp_cursor
, level
+ 1))
861 n
= MIN(*index
, (BTREE_PTR_MAX
- tmp_cursor
[level
].node
->num_keys
) / 2);
862 if (!n
|| !btree_shift_to_prev(root
, level
, tmp_cursor
, n
))
870 btree_insert_shift_to_next(
871 struct btree_root
*root
,
875 struct btree_cursor tmp_cursor
[root
->height
];
878 if (*index
>= BTREE_KEY_MAX
)
881 if (!btree_copy_cursor_next(root
, tmp_cursor
, level
+ 1))
884 n
= MIN(BTREE_KEY_MAX
- *index
,
885 (BTREE_PTR_MAX
- tmp_cursor
[level
].node
->num_keys
) / 2);
886 if (!n
|| !btree_shift_to_next(root
, level
, tmp_cursor
, n
))
893 struct btree_root
*root
,
898 struct btree_node
*node
= root
->cursor
[level
].node
;
899 int index
= root
->cursor
[level
].index
;
902 if (node
->num_keys
== BTREE_KEY_MAX
) {
903 if (btree_insert_shift_to_prev(root
, level
, &index
) == 0)
905 if (btree_insert_shift_to_next(root
, level
, &index
) == 0)
907 if (level
== root
->height
- 1) {
908 if (!btree_increase_height(root
))
911 node
= btree_split(root
, level
, key
, &index
);
916 ASSERT(index
<= node
->num_keys
);
919 node
->ptrs
[i
+ 1] = node
->ptrs
[i
];
920 while (--i
>= index
) {
921 node
->keys
[i
+ 1] = node
->keys
[i
];
922 node
->ptrs
[i
+ 1] = node
->ptrs
[i
];
926 node
->keys
[index
] = key
;
929 node
->ptrs
[index
] = value
;
931 node
->ptrs
[index
+ 1] = value
;
940 struct btree_root
*root
,
949 if (btree_search(root
, key
) && root
->cur_key
== key
)
953 root
->stats
.insert
+= 1;
954 root
->stats
.num_items
+= 1;
957 result
= btree_insert_item(root
, 0, key
, value
);
959 btree_invalidate_cursor(root
);
968 * Rather more complicated as deletions has 4 ways to go once a node
969 * ends up with less than the minimum number of keys:
970 * - move remainder to previous node
971 * - move remainder to next node
972 * (both will involve a parent deletion which may recurse)
973 * - balance by moving some items from previous node
974 * - balance by moving some items from next node
978 btree_decrease_height(
979 struct btree_root
*root
)
981 struct btree_node
*old_root
= root
->root_node
;
983 ASSERT(old_root
->num_keys
== 0);
986 root
->stats
.alloced
-= 1;
987 root
->stats
.dec_height
+= 1;
988 root
->stats
.max_items
/= BTREE_PTR_MAX
;
990 root
->root_node
= old_root
->ptrs
[0];
991 btree_node_free(old_root
);
996 btree_merge_with_prev(
997 struct btree_root
*root
,
999 struct btree_cursor
*prev_cursor
)
1004 if (!btree_shift_to_prev(root
, level
, prev_cursor
,
1005 root
->cursor
[level
].node
->num_keys
+ 1))
1009 root
->stats
.merge_prev
+= 1;
1015 btree_merge_with_next(
1016 struct btree_root
*root
,
1018 struct btree_cursor
*next_cursor
)
1023 if (!btree_shift_to_next(root
, level
, next_cursor
,
1024 root
->cursor
[level
].node
->num_keys
+ 1))
1028 root
->stats
.merge_next
+= 1;
1034 btree_balance_with_prev(
1035 struct btree_root
*root
,
1037 struct btree_cursor
*prev_cursor
)
1039 struct btree_cursor
*root_cursor
= root
->cursor
;
1043 ASSERT(prev_cursor
[level
].node
->num_keys
> BTREE_KEY_MIN
);
1046 root
->stats
.balance_prev
+= 1;
1049 * Move some nodes from the prev node into the current node.
1050 * As the shift operation is a right shift and is relative to
1051 * the root cursor, make the root cursor the prev cursor and
1052 * pass in the root cursor as the next cursor.
1055 root
->cursor
= prev_cursor
;
1056 if (!btree_shift_to_next(root
, level
, root_cursor
,
1057 (prev_cursor
[level
].node
->num_keys
+ 1 - BTREE_KEY_MIN
) / 2))
1059 root
->cursor
= root_cursor
;
1065 btree_balance_with_next(
1066 struct btree_root
*root
,
1068 struct btree_cursor
*next_cursor
)
1070 struct btree_cursor
*root_cursor
= root
->cursor
;
1074 assert(next_cursor
[level
].node
->num_keys
> BTREE_KEY_MIN
);
1077 root
->stats
.balance_next
+= 1;
1080 * move some nodes from the next node into the current node.
1081 * as the shift operation is a left shift and is relative to
1082 * the root cursor, make the root cursor the next cursor and
1083 * pass in the root cursor as the prev cursor.
1086 root
->cursor
= next_cursor
;
1087 if (!btree_shift_to_prev(root
, level
, root_cursor
,
1088 (next_cursor
[level
].node
->num_keys
+ 1 - BTREE_KEY_MIN
) / 2))
1090 root
->cursor
= root_cursor
;
1098 struct btree_root
*root
,
1102 * btree_delete_node:
1104 * Return 0 if it's done or 1 if the next level needs to be collapsed
1108 struct btree_root
*root
,
1111 struct btree_cursor prev_cursor
[root
->height
];
1112 struct btree_cursor next_cursor
[root
->height
];
1113 struct btree_cursor
*pc
;
1114 struct btree_cursor
*nc
;
1117 * the node has underflowed, grab or merge keys/items from a
1118 * neighbouring node.
1121 if (level
== root
->height
- 1) {
1122 if (level
> 0 && root
->root_node
->num_keys
== 0)
1123 btree_decrease_height(root
);
1127 pc
= btree_copy_cursor_prev(root
, prev_cursor
, level
+ 1);
1128 if (!btree_merge_with_prev(root
, level
, pc
)) {
1129 nc
= btree_copy_cursor_next(root
, next_cursor
, level
+ 1);
1130 if (!btree_merge_with_next(root
, level
, nc
)) {
1131 /* merging failed, try redistrubution */
1132 if (!btree_balance_with_prev(root
, level
, pc
) &&
1133 !btree_balance_with_next(root
, level
, nc
))
1135 return; /* when balancing, then the node isn't freed */
1140 root
->stats
.alloced
-= 1;
1142 btree_node_free(root
->cursor
[level
].node
);
1144 btree_delete_key(root
, level
+ 1);
1149 struct btree_root
*root
,
1152 struct btree_node
*node
= root
->cursor
[level
].node
;
1153 int index
= root
->cursor
[level
].index
;
1156 if (index
<= node
->num_keys
) {
1158 * if not deleting the last item, shift higher items down
1159 * to cover the item being deleted
1161 while (index
< node
->num_keys
) {
1162 node
->keys
[index
] = node
->keys
[index
+ 1];
1163 node
->ptrs
[index
] = node
->ptrs
[index
+ 1];
1166 node
->ptrs
[index
] = node
->ptrs
[index
+ 1];
1169 * else update the associated parent key as the last key
1170 * in the leaf has changed
1172 btree_update_node_key(root
, root
->cursor
, level
+ 1,
1173 node
->keys
[node
->num_keys
]);
1176 * if node underflows, either merge with sibling or rebalance
1179 if (node
->num_keys
< BTREE_KEY_MIN
)
1180 btree_delete_node(root
, level
);
1185 struct btree_root
*root
,
1190 value
= btree_lookup(root
, key
);
1195 root
->stats
.delete += 1;
1196 root
->stats
.num_items
-= 1;
1199 btree_delete_key(root
, 0);
1201 btree_invalidate_cursor(root
);
1209 struct btree_root
*root
,
1212 unsigned long max_items
= root
->stats
.max_items
*
1213 (root
->root_node
->num_keys
+ 1);
1215 fprintf(f
, "\tnum_items = %lu, max_items = %lu (%lu%%)\n",
1216 root
->stats
.num_items
, max_items
,
1217 root
->stats
.num_items
* 100 / max_items
);
1218 fprintf(f
, "\talloced = %d nodes, %lu bytes, %lu bytes per item\n",
1219 root
->stats
.alloced
,
1220 root
->stats
.alloced
* sizeof(struct btree_node
),
1221 root
->stats
.alloced
* sizeof(struct btree_node
) /
1222 root
->stats
.num_items
);
1223 fprintf(f
, "\tlookup = %d\n", root
->stats
.lookup
);
1224 fprintf(f
, "\tfind = %d\n", root
->stats
.find
);
1225 fprintf(f
, "\tcache_hits = %d\n", root
->stats
.cache_hits
);
1226 fprintf(f
, "\tcache_misses = %d\n", root
->stats
.cache_misses
);
1227 fprintf(f
, "\tkey_update = %d\n", root
->stats
.key_update
);
1228 fprintf(f
, "\tvalue_update = %d\n", root
->stats
.value_update
);
1229 fprintf(f
, "\tinsert = %d\n", root
->stats
.insert
);
1230 fprintf(f
, "\tshift_prev = %d\n", root
->stats
.shift_prev
);
1231 fprintf(f
, "\tshift_next = %d\n", root
->stats
.shift_next
);
1232 fprintf(f
, "\tsplit = %d\n", root
->stats
.split
);
1233 fprintf(f
, "\tinc_height = %d\n", root
->stats
.inc_height
);
1234 fprintf(f
, "\tdelete = %d\n", root
->stats
.delete);
1235 fprintf(f
, "\tmerge_prev = %d\n", root
->stats
.merge_prev
);
1236 fprintf(f
, "\tmerge_next = %d\n", root
->stats
.merge_next
);
1237 fprintf(f
, "\tbalance_prev = %d\n", root
->stats
.balance_prev
);
1238 fprintf(f
, "\tbalance_next = %d\n", root
->stats
.balance_next
);
1239 fprintf(f
, "\tdec_height = %d\n", root
->stats
.dec_height
);