Exemplo n.º 1
0
Arquivo: bttree.c Projeto: wtaysom/tau
int bt_delete (BtTree_s *tree, u64 key)
{
	BtNode_s *node = tree->root;
	BtNode_s *parent;

	while (node && node->num == 0) {
		if (node->is_leaf) {
			tree->root = NULL;
		} else {
			tree->root = node->first;
		}
		free(node);
		node = tree->root;
		++tree->stat.num_shrink;
	}
	while (node && !node->is_leaf) {
		parent = node;
		node = lookup(node, key);
		if (is_sparse(node)) {
			node = join(parent, key);
		}
	}
	if (!node) fatal("Key %llu not found", key);
	leaf_delete(node, key);
	++tree->stat.num_deletes;
	return 0;
}
Exemplo n.º 2
0
static void
leaf_remove(struct tree *tree, struct leaf *leaf, int key)
{
int i, j, k;
struct leaf *sibling;
int remove = key_binary_search(leaf->key, leaf->entries, key);
if (remove < 0) {
return;
}
if (leaf->entries <= (ENTRIES + 1) / 2) {
struct non_leaf *parent = leaf->parent;
if (parent != NULL) {
int borrow = 0;
/* find which sibling node with same parent to be borrowed from */
i = key_binary_search(parent->key, parent->children - 1, leaf->key[0]);
if (i >= 0) {
i = i + 1;
if (i == parent->children - 1) {
/* the last node, no right sibling, choose left one */
sibling = (struct leaf *)parent->sub_ptr[i - 1];
borrow = BORROW_FROM_LEFT;
} else {
struct leaf *l_sib = (struct leaf *)parent->sub_ptr[i - 1];
struct leaf *r_sib = (struct leaf *)parent->sub_ptr[i + 1];
/* if both left and right sibling found, choose the one with more entries */
sibling = l_sib->entries >= r_sib->entries ? l_sib : r_sib;
borrow = l_sib->entries >= r_sib->entries ? BORROW_FROM_LEFT : BORROW_FROM_RIGHT;
}
} else {
i = -i - 1;
if (i == 0) {
/* the frist node, no left sibling, choose right one */
sibling = (struct leaf *)parent->sub_ptr[i + 1];
borrow = BORROW_FROM_RIGHT;
} else if (i == parent->children - 1) {
/* the last node, no right sibling, choose left one */
sibling = (struct leaf *)parent->sub_ptr[i - 1];
borrow = BORROW_FROM_LEFT;
} else {
struct leaf *l_sib = (struct leaf *)parent->sub_ptr[i - 1];
struct leaf *r_sib = (struct leaf *)parent->sub_ptr[i + 1];
/* if both left and right sibling found, choose the one with more entries */
sibling = l_sib->entries >= r_sib->entries ? l_sib : r_sib;
borrow = l_sib->entries >= r_sib->entries ? BORROW_FROM_LEFT : BORROW_FROM_RIGHT;
}
}
/* locate parent node key index */
if (i > 0) {
i = i - 1;
}
if (borrow == BORROW_FROM_LEFT) {
if (sibling->entries > (ENTRIES + 1) / 2) {
/* leaf node right shift */
parent->key[i] = sibling->key[sibling->entries - 1];
for (; remove > 0; remove--) {
leaf->key[remove] = leaf->key[remove - 1];
leaf->data[remove] = leaf->data[remove - 1];
}
leaf->key[0] = sibling->key[sibling->entries - 1];
leaf->data[0] = sibling->data[sibling->entries - 1];
sibling->entries--;
/* adjust parent key */
parent->key[i] = leaf->key[0];
} else {
/* merge leaf and left sibling */
for (j = sibling->entries, k = 0; k < leaf->entries; k++) {
if (k != remove) {
sibling->key[j] = leaf->key[k];
sibling->data[j] = leaf->data[k];
j++;
}
}
sibling->entries = j;
/* delete merged leaf */
sibling->next = leaf->next;
leaf_delete(leaf);
/* trace upwards */
non_leaf_remove(tree, parent, i, 1);
}
} else {
/* remove entry first in case of overflow merging with sibling node */
for (; remove < leaf->entries - 1; remove++) {
leaf->key[remove] = leaf->key[remove + 1];
leaf->data[remove] = leaf->data[remove + 1];
}
leaf->entries--;
if (sibling->entries > (ENTRIES + 1) / 2) {
/* borrow */
leaf->key[leaf->entries] = sibling->key[0];
leaf->data[leaf->entries] = sibling->data[0];
leaf->entries++;
/* right sibling node left shift */
for (j = 0; j < sibling->entries - 1; j++) {
sibling->key[j] = sibling->key[j + 1];
sibling->data[j] = sibling->data[j + 1];
}
sibling->entries--;
/* adjust parent key */
parent->key[i] = sibling->key[0];
} else {
/* merge leaf node */
for (j = leaf->entries, k = 0; k < sibling->entries; j++, k++) {
leaf->key[j] = sibling->key[k];
leaf->data[j] = sibling->data[k];
}
leaf->entries = j;
/* delete merged sibling */
leaf->next = sibling->next;
leaf_delete(sibling);
/* trace upwards */
non_leaf_remove(tree, parent, i, 1);
}
}
/* deletion finishes */
return;
} else {
if (leaf->entries == 1) {
/* delete the only last node */
assert(key == leaf->key[0]);
tree->root = NULL;
tree->head[0] = NULL;
leaf_delete(leaf);
return;
}
}
}
/* simple deletion */
for (; remove < leaf->entries - 1; remove++) {
leaf->key[remove] = leaf->key[remove + 1];
leaf->data[remove] = leaf->data[remove + 1];
}
leaf->entries--;
}