Working on removing keys from B+ trees

This commit is contained in:
2018-06-24 12:34:00 +01:00
parent 5cd7fd44c3
commit 12a39b5049
3 changed files with 120 additions and 5 deletions

View File

@@ -91,6 +91,28 @@ bool bplus_node_insert_kv(BPlusNode *node, BPlusKV *kv) {
return true;
}
bool bplus_node_remove_kv(BPlusNode *node, BPlusKV *kv) {
bool removed = false;
//Find key
for (size_t i = 0; i < node->keyCount; i++) {
if (node->keys[i] == kv) {
node->keys[i] = NULL;
node->keyCount--;
//Move keys down
for (; i < node->keyCount; i++) {
node->keys[i] = node->keys[i + 1];
}
removed = true;
break;
}
}
return removed;
}
bool bplus_node_merge(BPlusNode *left, BPlusNode *right) {
}
void print_bplus_node(BPlusNode *node, size_t indent) {
char *indentStr = calloc(indent + 1, sizeof(char));
memset(indentStr, ' ', sizeof(char) * indent);
@@ -213,7 +235,7 @@ BPlusNode *bplus_tree_find_leaf(BPlusTree *tree, uint64_t key) {
bool bplus_tree_insert(BPlusTree *tree, uint64_t newKey, void *newValue) {
BPlusNode *node = bplus_tree_find_leaf(tree, newKey);
assert(node != NULL);
assert(node != NULL && node->isInternal == false);
if (node->keyCount < node->order - 1) {
//Can insert at this node
@@ -294,6 +316,86 @@ 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);
//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]);
assert(removed);
free_bplus_kv(kv);
break;
}
}
if (!removed) {
return false;
}
if (node->keyCount >= tree->minFill || node->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));
//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;
break;
}
}
return true;
}
//Check left leaf
if (node->leftLeaf != NULL
&& node->leftLeaf->parent == node->parent
&& node->leftLeaf->keyCount > tree->minFill) {
//Borrow 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;
break;
}
}
}
//No key to borrow, merge with a sibling
//Look right and left for leafs with same parent and where merging would result in keys < order
//Try right leaf
if (node->rightLeaf != NULL
&& node->parent == node->rightLeaf->parent
&& node->keyCount + node->rightLeaf->keyCount < tree->order) {
return bplus_node_merge(node, node->rightLeaf);
}
//Try left leaf
if (node->leftLeaf != NULL
&& node->parent == node->leftLeaf->parent
&& node->keyCount + node->leftLeaf->keyCount < tree->order) {
return bplus_node_merge(node->leftLeaf, node);
}
}
BPlusKV *bplus_tree_find(BPlusTree *tree, uint64_t key) {
BPlusNode *leaf = bplus_tree_find_leaf(tree, key);
if (leaf == NULL) {

View File

@@ -41,9 +41,13 @@ void free_bplus_node(BPlusNode *node);
bool bplus_node_insert_kv(BPlusNode *node, BPlusKV *kv);
bool bplus_node_remove_kv(BPlusNode *node, BPlusKV *kv);
bool bplus_node_merge(BPlusNode *left, BPlusNode *right);
void print_bplus_node(BPlusNode *node, size_t indent);
char * debug_bplus_node_str(BPlusNode *node, char *str, size_t *strSize);
char *debug_bplus_node_str(BPlusNode *node, char *str, size_t *strSize);
struct BPlusTree_t {
size_t order;
@@ -58,13 +62,16 @@ BPlusTree *new_bplus_tree(size_t order);
void free_bplus_tree(BPlusTree *tree);
void print_bplus_tree(BPlusTree *tree);
char *debug_bplus_tree_str(BPlusTree *tree, char *str);
BPlusNode * bplus_tree_find_leaf(BPlusTree *tree, uint64_t key);
BPlusNode *bplus_tree_find_leaf(BPlusTree *tree, uint64_t key);
bool bplus_tree_insert(BPlusTree *tree, uint64_t key, void *value);
BPlusKV * bplus_tree_find(BPlusTree *tree, uint64_t key);
bool bplus_tree_delete(BPlusTree *tree, uint64_t key);
BPlusKV *bplus_tree_find(BPlusTree *tree, uint64_t key);
enum BPlusFindComp_t {
FIND_NONE = 0,
@@ -73,6 +80,7 @@ enum BPlusFindComp_t {
FIND_GT = 4
};
typedef enum BPlusFindComp_t BPlusFindComp;
BPlusKV * bplus_tree_find_closest(BPlusTree *tree, uint64_t key, BPlusFindComp dir);
BPlusKV *bplus_tree_find_closest(BPlusTree *tree, uint64_t key, BPlusFindComp dir);
#endif //SDB_BPLUS_TREE_H