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; }
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--; }