diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..7eaa181 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,5 +1,10 @@ + + + + + diff --git a/src/bplus_tree.c b/src/bplus_tree.c index 8f5ca84..41abf35 100644 --- a/src/bplus_tree.c +++ b/src/bplus_tree.c @@ -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) { diff --git a/src/bplus_tree.h b/src/bplus_tree.h index 4160c68..9ff537d 100644 --- a/src/bplus_tree.h +++ b/src/bplus_tree.h @@ -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