Working on removing keys from B+ trees

This commit is contained in:
2018-06-30 18:53:59 +01:00
parent 1a3a2cfb6d
commit b2e27373f1
2 changed files with 157 additions and 60 deletions

View File

@@ -8,6 +8,8 @@
#include <stdio.h>
#include "bplus_tree.h"
#include "bplus_tree.helpers.c"
#define APPEND_STR(str, size, _) { \
if (strlen(_) + strlen(str) + 1 > (size)) { \
(size) *= 2; \
@@ -313,15 +315,15 @@ bool bplus_tree_insert(BPlusTree *tree, uint64_t newKey, void *newValue) {
}
bool bplus_tree_delete(BPlusTree *tree, uint64_t key) {
BPlusNode *node = bplus_tree_find_leaf(tree, key);
assert(node != NULL && node->isInternal == false);
BPlusNode *leaf = bplus_tree_find_leaf(tree, key);
assert(leaf != NULL && leaf->isInternal == false);
//Find and remove kv
bool removed = false;
for (size_t i = 0; i < node->keyCount; i++) {
if (node->keys[i]->key == key) {
BPlusKV *kv = node->keys[i];
removed = bplus_node_remove_kv(node, node->keys[i]);
for (size_t i = 0; i < leaf->keyCount; i++) {
if (leaf->keys[i]->key == key) {
BPlusKV *kv = leaf->keys[i];
removed = bplus_node_remove_kv(leaf, leaf->keys[i]);
assert(removed);
free_bplus_kv(kv);
break;
@@ -332,24 +334,24 @@ bool bplus_tree_delete(BPlusTree *tree, uint64_t key) {
return false;
}
if (node->keyCount >= tree->minFill || node->parent == NULL) {
if (leaf->keyCount >= tree->minFill || leaf->parent == NULL) {
return true;
}
//Try and borrow a key from a neighbour
//Check right leaf
if (node->rightLeaf != NULL
&& node->rightLeaf->parent == node->parent
&& node->rightLeaf->keyCount > tree->minFill) {
//Move first kv on leaf to this node
BPlusKV *kv = node->rightLeaf->keys[0];
assert(bplus_node_remove_kv(node->rightLeaf, kv));
assert(bplus_node_insert_kv(node, kv));
if (leaf->rightLeaf != NULL
&& leaf->rightLeaf->parent == leaf->parent
&& leaf->rightLeaf->keyCount > tree->minFill) {
//Move first kv on leaf to this leaf
BPlusKV *kv = leaf->rightLeaf->keys[0];
assert(bplus_node_remove_kv(leaf->rightLeaf, kv));
assert(bplus_node_insert_kv(leaf, kv));
//Update the right leafs parent pointer
for (size_t i = 0; i < node->parent->keyCount; i++) {
if (node->parent->keys[i]->rightPointer == node->rightLeaf) {
node->parent->keys[i]->key = node->rightLeaf->keys[0]->key;
for (size_t i = 0; i < leaf->parent->keyCount; i++) {
if (leaf->parent->keys[i]->rightPointer == leaf->rightLeaf) {
leaf->parent->keys[i]->key = leaf->rightLeaf->keys[0]->key;
break;
}
}
@@ -357,17 +359,17 @@ bool bplus_tree_delete(BPlusTree *tree, uint64_t key) {
}
//Check left leaf
if (node->leftLeaf != NULL
&& node->leftLeaf->parent == node->parent
&& node->leftLeaf->keyCount > tree->minFill) {
if (leaf->leftLeaf != NULL
&& leaf->leftLeaf->parent == leaf->parent
&& leaf->leftLeaf->keyCount > tree->minFill) {
//Move right most key from left leaf
BPlusKV *kv = node->leftLeaf->keys[node->keyCount - 1];
assert(bplus_node_remove_kv(node->leftLeaf, kv));
assert(bplus_node_insert_kv(node, kv));
//Update the key pointing to this node
for (size_t i = 0; i < node->parent->keyCount; i++) {
if (node->parent->keys[i]->rightPointer == node) {
node->parent->keys[i]->key = node->keys[0]->key;
BPlusKV *kv = leaf->leftLeaf->keys[leaf->keyCount - 1];
assert(bplus_node_remove_kv(leaf->leftLeaf, kv));
assert(bplus_node_insert_kv(leaf, kv));
//Update the key pointing to this leaf
for (size_t i = 0; i < leaf->parent->keyCount; i++) {
if (leaf->parent->keys[i]->rightPointer == leaf) {
leaf->parent->keys[i]->key = leaf->keys[0]->key;
break;
}
}
@@ -378,26 +380,26 @@ bool bplus_tree_delete(BPlusTree *tree, uint64_t key) {
bool merged = false;
//Try right leaf
if (node->rightLeaf != NULL
&& node->parent == node->rightLeaf->parent
&& node->keyCount + node->rightLeaf->keyCount < tree->order) {
//Move all keys from right leaf to this node
while(node->rightLeaf->keyCount > 0) {
assert(bplus_node_insert_kv(node, node->rightLeaf->keys[0]));
assert(bplus_node_remove_kv(node->rightLeaf, node->rightLeaf->keys[0]));
if (leaf->rightLeaf != NULL
&& leaf->parent == leaf->rightLeaf->parent
&& leaf->keyCount + leaf->rightLeaf->keyCount < tree->order) {
//Move all keys from right leaf to this leaf
while (leaf->rightLeaf->keyCount > 0) {
assert(bplus_node_insert_kv(leaf, leaf->rightLeaf->keys[0]));
assert(bplus_node_remove_kv(leaf->rightLeaf, leaf->rightLeaf->keys[0]));
}
//Remove right leaf and parent pointer
for(size_t i=0; i<node->parent->keyCount; i++) {
BPlusKV *kv = node->parent->keys[i];
if (kv->rightPointer == node->rightLeaf) {
for (size_t i = 0; i < leaf->parent->keyCount; i++) {
BPlusKV *kv = leaf->parent->keys[i];
if (kv->rightPointer == leaf->rightLeaf) {
//Remove key
bplus_node_remove_kv(node->parent, kv);
bplus_node_remove_kv(leaf->parent, kv);
//Update leaf pointers
node->rightLeaf = node->rightLeaf;
if (node->rightLeaf != NULL) {
node->rightLeaf->leftLeaf = node;
leaf->rightLeaf = leaf->rightLeaf;
if (leaf->rightLeaf != NULL) {
leaf->rightLeaf->leftLeaf = leaf;
}
//Free key and node
//Free key and leaf
free_bplus_kv(kv);
break;
}
@@ -406,27 +408,27 @@ bool bplus_tree_delete(BPlusTree *tree, uint64_t key) {
}
//Try left leaf
if (node->leftLeaf != NULL
&& node->parent == node->leftLeaf->parent
&& node->keyCount + node->leftLeaf->keyCount < tree->order) {
if (leaf->leftLeaf != NULL
&& leaf->parent == leaf->leftLeaf->parent
&& leaf->keyCount + leaf->leftLeaf->keyCount < tree->order) {
//Move all keys into left leaf
while(node->keyCount > 0) {
assert(bplus_node_insert_kv(node->leftLeaf, node->keys[0]));
assert(bplus_node_remove_kv(node, node->keys[0]));
while (leaf->keyCount > 0) {
assert(bplus_node_insert_kv(leaf->leftLeaf, leaf->keys[0]));
assert(bplus_node_remove_kv(leaf, leaf->keys[0]));
}
//Remove this leaf and parent pointer (if any)
for(size_t i=0; i<node->parent->keyCount; i++) {
BPlusKV *kv = node->parent->keys[i];
if (kv->rightPointer == node) {
for (size_t i = 0; i < leaf->parent->keyCount; i++) {
BPlusKV *kv = leaf->parent->keys[i];
if (kv->rightPointer == leaf) {
//Remove key
bplus_node_remove_kv(node->parent, kv);
bplus_node_remove_kv(leaf->parent, kv);
//Update leaf pointers
node->leftLeaf->rightLeaf = node->rightLeaf;
if (node->leftLeaf->rightLeaf != NULL) {
node->leftLeaf->rightLeaf->leftLeaf = node->leftLeaf;
leaf->leftLeaf->rightLeaf = leaf->rightLeaf;
if (leaf->leftLeaf->rightLeaf != NULL) {
leaf->leftLeaf->rightLeaf->leftLeaf = leaf->leftLeaf;
}
node = node->leftLeaf;
//Free key and node
leaf = leaf->leftLeaf;
//Free key and leaf
free_bplus_kv(kv);
break;
}
@@ -438,17 +440,60 @@ bool bplus_tree_delete(BPlusTree *tree, uint64_t key) {
assert(merged == true);
//Start merging parents where key count <= 1
BPlusNode *parent = node->parent;
BPlusNode *node = leaf->parent;
while(parent != NULL) {
while (node != NULL) {
if (parent->keyCount > 1) {
//Dont need to do anything if node has enough keys or is the root
if (node->keyCount > 1 || node->parent == NULL) {
break;
}
BPlusNode *left = _bplus_node_get_left_sibling(node);
BPlusNode *right = _bplus_node_get_right_sibling(node);
//Try and borrow a key from a sibling
if (right != NULL && right->keyCount > 1) {
//Take the left pointer and create a new key for it
BPlusKV *kv = new_bplus_kv(right->leftPointer->keys[0]->key, NULL, right->leftPointer);
right->leftPointer->parent = node;
bplus_node_insert_kv(node, kv);
//Consume first key to populate left pointer
right->leftPointer = right->keys[0]->rightPointer;
kv = right->keys[0];
bplus_node_remove_kv(right, kv);
kv->rightPointer = NULL;
free_bplus_kv(kv);
//Update pointer key to right
for (size_t i = 0; i < node->parent->keyCount; i++) {
if (node->parent->keys[i]->rightPointer == right) {
node->parent->keys[i]->key = right->keys[0]->key;
}
}
break;
}
if (left != NULL && left->keyCount > 1) {
//Push our left pointer to a new key
BPlusKV *newKV = new_bplus_kv(node->leftPointer->keys[0]->key, NULL, node->leftPointer);
bplus_node_insert_kv(node, newKV);
//Take the right key from the left sibling
BPlusKV *kv = left->keys[left->keyCount - 1];
bplus_node_remove_kv(left, kv);
node->leftPointer = kv->rightPointer;
node->leftPointer->parent = node;
kv->rightPointer = NULL;
free_bplus_kv(kv);
//Update our parent pointer
for (size_t i = 0; i < node->parent->keyCount; i++) {
if (node->parent->keys[i]->rightPointer == node) {
node->parent->keys[i]->key = node->keys[0]->key;
}
}
break;
}
//Couldn't borrow key, merge with a sibling
}
}

52
src/bplus_tree.helpers.c Normal file
View File

@@ -0,0 +1,52 @@
//
// Created by sam on 30/06/18.
//
BPlusNode *_bplus_node_get_left_sibling(BPlusNode *node) {
BPlusNode *parent = node->parent;
if (node->isInternal) {
if (parent == NULL) {
return NULL;
}
if (parent->leftLeaf == node) {
return NULL;
}
for (size_t i = 0; i < parent->keyCount; i++) {
if (parent->keys[i]->rightPointer == node) {
if (i == 0) {
return parent->leftPointer;
}
if (i + 1 < parent->keyCount) {
return parent->keys[i + 1]->rightPointer;
}
return NULL;
}
}
return NULL;
} else {
return node->leftLeaf;
}
}
BPlusNode *_bplus_node_get_right_sibling(BPlusNode *node) {
BPlusNode *parent = node->parent;
if (node->isInternal) {
if (parent == NULL) {
return NULL;
}
if (parent->leftPointer == node) {
return parent->keyCount > 0 ? parent->keys[0]->rightPointer : NULL;
}
for (size_t i = 0; i < parent->keyCount; i++) {
if (parent->keys[i]->rightPointer == node) {
if (i == 0) {
return parent->leftPointer;
}
return parent->keys[i - 1]->rightPointer;
}
}
return NULL;
} else {
return node->rightLeaf;
}
}