This commit is contained in:
Timothy Warren 2019-05-06 16:09:00 -04:00
parent 9b9fea0984
commit e1b019000c
1 changed files with 74 additions and 8 deletions

82
db.c
View File

@ -124,7 +124,8 @@ const uint32_t INTERNAL_NODE_HEADER_SIZE = COMMON_NODE_HEADER_SIZE + INTERNAL_NO
const uint32_t INTERNAL_NODE_KEY_SIZE = sizeof(uint32_t);
const uint32_t INTERNAL_NODE_CHILD_SIZE = sizeof(uint32_t);
const uint32_t INTERNAL_NODE_CELL_SIZE = INTERNAL_NODE_CHILD_SIZE + INTERNAL_NODE_KEY_SIZE;
/* Keep this small for testing */
const uint32_t INTERNAL_NODE_MAX_CELLS = 3;
/*
* Leaf Node Header Layout
*/
@ -167,6 +168,10 @@ void set_node_root(void* node, bool is_root) {
*((uint8_t*)(node + IS_ROOT_OFFSET)) = value;
}
uint32_t* node_parent(void* node) {
return node + PARENT_POINTER_OFFSET;
}
uint32_t* internal_node_num_keys(void* node) {
return node + INTERNAL_NODE_NUM_KEYS_OFFSET;
}
@ -192,7 +197,7 @@ uint32_t* internal_node_child(void* node, uint32_t child_num) {
}
uint32_t* internal_node_key(void* node, uint32_t key_num) {
return internal_node_cell(node, key_num) + INTERNAL_NODE_CHILD_SIZE;
return (void*)internal_node_cell(node, key_num) + INTERNAL_NODE_CHILD_SIZE;
}
uint32_t* leaf_node_num_cells(void* node) {
@ -359,11 +364,14 @@ Cursor* leaf_node_find(Table* table, uint32_t page_num, uint32_t key) {
return cursor;
}
Cursor* internal_node_find(Table* table, uint32_t page_num, uint32_t key) {
void* node = get_page(table->pager, page_num);
uint32_t internal_node_find_child(void* node, uint32_t key) {
/*
* Return the index of the child which should contain
* the given key
*/
uint32_t num_keys = *internal_node_num_keys(node);
/* Binary search to find index of child to search */
/* Binary search */
uint32_t min_index = 0;
uint32_t max_index = num_keys; /* there is one more child than key */
@ -377,7 +385,14 @@ Cursor* internal_node_find(Table* table, uint32_t page_num, uint32_t key) {
}
}
uint32_t child_num = *internal_node_child(node, min_index);
return min_index;
}
Cursor* internal_node_find(Table* table, uint32_t page_num, uint32_t key) {
void *node = get_page(table->pager, page_num);
uint32_t child_index = internal_node_find_child(node, key);
uint32_t child_num = *internal_node_child(node, child_index);
void* child = get_page(table->pager, child_num);
switch (get_node_type(child)) {
case NODE_LEAF:
@ -654,6 +669,50 @@ void create_new_root(Table* table, uint32_t right_child_page_num) {
uint32_t left_child_max_key = get_node_max_key(left_child);
*internal_node_key(root, 0) = left_child_max_key;
*internal_node_right_child(root) = right_child_page_num;
*node_parent(left_child) = table->root_page_num;
*node_parent(right_child) = table->root_page_num;
}
void internal_node_insert(Table* table, uint32_t parent_page_num, uint32_t child_page_num) {
/*
* Add a new child/key pair to parent that corresponds to child
*/
void* parent = get_page(table->pager, parent_page_num);
void* child = get_page(table->pager, child_page_num);
uint32_t child_max_key = get_node_max_key(child);
uint32_t index = internal_node_find_child(parent, child_max_key);
uint32_t original_num_keys = *internal_node_num_keys(parent);
*internal_node_num_keys(parent) = original_num_keys + 1;
if (original_num_keys >= INTERNAL_NODE_MAX_CELLS) {
printf("Need to implement splitting internal node\n");
exit(EXIT_FAILURE);
}
uint32_t right_child_page_num = *internal_node_right_child(parent);
void* right_child = get_page(table->pager, right_child_page_num);
if (child_max_key > get_node_max_key(right_child)) {
/* Replace right child */
*internal_node_child(parent, original_num_keys) = right_child_page_num;
*internal_node_key(parent, original_num_keys) = get_node_max_key(right_child);
*internal_node_right_child(parent) = child_page_num;
} else {
/* Make room for new cell */
for (uint32_t i = original_num_keys; i > index; i--) {
void* destination = internal_node_cell(parent, i);
void* source = internal_node_cell(parent, i - 1);
memcpy(destination, source, INTERNAL_NODE_CELL_SIZE);
}
*internal_node_child(parent, index) = child_page_num;
*internal_node_key(parent, index) = child_max_key;
}
}
void update_internal_node_key(void* node, uint32_t old_key, uint32_t new_key) {
uint32_t old_child_index = internal_node_find_child(node, old_key);
*internal_node_key(node, old_child_index) = new_key;
}
void leaf_node_split_and_insert(Cursor* cursor, uint32_t key, Row* value) {
@ -663,9 +722,11 @@ void leaf_node_split_and_insert(Cursor* cursor, uint32_t key, Row* value) {
* Update parent or create a new parent.
*/
void* old_node = get_page(cursor->table->pager, cursor->page_num);
uint32_t old_max = get_node_max_key(old_node);
uint32_t new_page_num = get_unused_page_num(cursor->table->pager);
void* new_node = get_page(cursor->table->pager, new_page_num);
initialize_leaf_node(new_node);
*node_parent(new_node) = *node_parent(old_node);
*leaf_node_next_leaf(new_node) = *leaf_node_next_leaf(old_node);
*leaf_node_next_leaf(old_node) = new_page_num;
@ -701,8 +762,13 @@ void leaf_node_split_and_insert(Cursor* cursor, uint32_t key, Row* value) {
if (is_node_root(old_node)) {
return create_new_root(cursor->table, new_page_num);
} else {
printf("Need to implement updating parent after split\n");
exit(EXIT_FAILURE);
uint32_t parent_page_num = *node_parent(old_node);
uint32_t new_max = get_node_max_key(old_node);
void* parent = get_page(cursor->table->pager, parent_page_num);
update_internal_node_key(parent, old_max, new_max);
internal_node_insert(cursor->table, parent_page_num, new_page_num);
return;
}
}