b-tree: fix corruption bug when inserting an entry in the middle of a node
This commit is contained in:
25
src/b-tree.c
25
src/b-tree.c
@@ -180,8 +180,10 @@ static void node_shift_entries(
|
||||
unsigned long count = nr_entries - shift_from;
|
||||
|
||||
for (unsigned long i = 0; i < count; i++) {
|
||||
b_tree_node_entry *entry = node_get_entry(tree, node, src + i);
|
||||
node_set_entry(tree, node, dest + i, entry);
|
||||
unsigned long from = (src + count - 1) - i;
|
||||
unsigned long to = (dest + count - 1) - i;
|
||||
b_tree_node_entry *entry = node_get_entry(tree, node, from);
|
||||
node_set_entry(tree, node, to, entry);
|
||||
}
|
||||
|
||||
if (shift_by < 0) {
|
||||
@@ -323,15 +325,28 @@ static int node_put(
|
||||
}
|
||||
|
||||
int insert_at = -1;
|
||||
bool exact_match = false;
|
||||
|
||||
for (unsigned long i = 0; i < nr_entries; i++) {
|
||||
const b_tree_node_entry *cur = node_get_entry(tree, n, i);
|
||||
int cmp = entry_compare(tree, cur, e);
|
||||
if (cmp == 0) {
|
||||
insert_at = i;
|
||||
exact_match = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmp == 1) {
|
||||
insert_at = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (exact_match) {
|
||||
node_set_entry(tree, n, insert_at, e);
|
||||
return insert_at;
|
||||
}
|
||||
|
||||
if (insert_at != -1) {
|
||||
node_shift_entries(tree, n, insert_at, 1);
|
||||
} else {
|
||||
@@ -443,9 +458,9 @@ int b_tree_put(struct b_tree *tree, const b_tree_node_entry *to_put)
|
||||
|
||||
/* this node is full, split it. */
|
||||
|
||||
/* half the nodes from `next` will be moved into `n3`. the other
|
||||
half will stay put. the median entry will be moved to
|
||||
`current`.
|
||||
/* half the nodes from `next` will be moved into `n3`.
|
||||
the other half will stay put. the median entry will
|
||||
be moved to `current`.
|
||||
|
||||
`n3` will become the right sibling of `next` */
|
||||
b_tree_node *n3 = cache_alloc_node(tree);
|
||||
|
||||
Reference in New Issue
Block a user