diff --git a/src/b-tree.c b/src/b-tree.c index c075c2d..130a795 100644 --- a/src/b-tree.c +++ b/src/b-tree.c @@ -1,4 +1,6 @@ #include +#include +#include #include "b-tree.h" @@ -15,6 +17,10 @@ struct cache_entry { /* ... node data here ... */ }; +#define GET_ENTRY(tree, entries, index) \ + (b_tree_node_entry *)((unsigned char *)(entries) + ((index) * (tree)->tree_ops->entry_size)); + + static b_tree_node *cache_alloc_node(struct b_tree *tree) { b_queue_iterator it = { 0 }; @@ -53,9 +59,19 @@ void b_tree_init(struct b_tree *tree, const struct b_tree_ops *ops, unsigned int tree->tree_order = order; } +static long tree_alloc_id(struct b_tree *tree) +{ + return tree->tree_ops->tree_alloc_node(tree); +} + static int node_read(struct b_tree *tree, long id, b_tree_node *out) { + return tree->tree_ops->tree_get_node(tree, id, out); +} +static int node_write(struct b_tree *tree, long id, const b_tree_node *in) +{ + return tree->tree_ops->tree_put_node(tree, id, in); } static unsigned long node_get_nr_entries(struct b_tree *tree, b_tree_node *node) @@ -63,19 +79,185 @@ static unsigned long node_get_nr_entries(struct b_tree *tree, b_tree_node *node) return tree->tree_ops->node_get_nr_entries(node); } +static void node_set_nr_entries(struct b_tree *tree, b_tree_node *node, unsigned long val) +{ + tree->tree_ops->node_set_nr_entries(node, val); +} + static long node_get_child(struct b_tree *tree, b_tree_node *node, unsigned long index) { - return tree->tree_ops->node_get_child(node, index); + uint16_t *children = tree->tree_ops->node_get_children(node); + if (children[index] == 0xFFFF) { + return B_TREE_INVALID_PTR; + } + + return children[index]; } static void node_set_child(struct b_tree *tree, b_tree_node *node, unsigned long index, long ptr) { - tree->tree_ops->node_set_child(node, index, ptr); + uint16_t *children = tree->tree_ops->node_get_children(node); + if (ptr == B_TREE_INVALID_PTR) { + children[index] = 0xFFFF; + } else { + children[index] = ptr; + } } -static b_tree_node_entry node_get_entry(struct b_tree *tree, b_tree_node *node, unsigned long index) +static b_tree_node_entry *node_get_entry(struct b_tree *tree, b_tree_node *node, unsigned long index) { - return tree->tree_ops->node_get_entry(node, index); + b_tree_node_entry *entries = tree->tree_ops->node_get_entries(node); + return GET_ENTRY(tree, entries, index); +} + +static void node_set_entry(struct b_tree *tree, b_tree_node *node, unsigned long index, const b_tree_node_entry *entry) +{ + b_tree_node_entry *entries = tree->tree_ops->node_get_entries(node); + b_tree_node_entry *dest = GET_ENTRY(tree, entries, index); + memcpy(dest, entry, tree->tree_ops->entry_size); +} + +static void node_kill_entry(struct b_tree *tree, b_tree_node *node, unsigned long index) +{ + b_tree_node_entry *entries = tree->tree_ops->node_get_entries(node); + b_tree_node_entry *dest = GET_ENTRY(tree, entries, index); + memset(dest, 0x0, tree->tree_ops->entry_size); +} + +static void node_shift_entries(struct b_tree *tree, b_tree_node *node, unsigned long shift_from, long shift_by) +{ + unsigned long nr_entries = node_get_nr_entries(tree, node); + b_tree_node_entry *entries = tree->tree_ops->node_get_entries(node); + + if (shift_from >= nr_entries) { + return; + } + + b_tree_node_entry *src = GET_ENTRY(tree, entries, shift_from); + b_tree_node_entry *dest = GET_ENTRY(tree, entries, shift_from + shift_by); + unsigned int count = nr_entries - shift_from; + + memmove(dest, src, tree->tree_ops->entry_size * count); + if (shift_by < 0) { + dest = GET_ENTRY(tree, entries, nr_entries + shift_by); + count = abs(shift_by); + } + else { + dest = src; + count = shift_by; + } + + memset(dest, 0x0, count * tree->tree_ops->entry_size); + return 0; +} + +static void node_shift_children(struct b_tree *tree, b_tree_node *node, unsigned long shift_from, long shift_by) +{ + unsigned long nr_entries = node_get_nr_entries(tree, node); + uint16_t *children = tree->tree_ops->node_get_children(node); + + if (shift_from >= nr_entries + 1) { + return; + } + + if (shift_from == nr_entries && shift_by > 0) { + return; + } + + uint16_t *src = &children[shift_from]; + uint16_t *dest = &children[shift_from + shift_by]; + unsigned int count = nr_entries + 1 - shift_from; + if (shift_by > 0) { + count -= shift_by; + } + + memmove(dest, src, sizeof(uint16_t) * count); + if (shift_by < 0) { + dest = &children[nr_entries + 1 + shift_from]; + count = abs(shift_by); + } + else { + dest = src; + count = shift_by; + } + + memset(dest, 0xFF, count * sizeof(uint16_t)); +} + +static void node_move_entries(struct b_tree *tree, b_tree_node *from, b_tree_node *to, unsigned long src_index, unsigned long dest_index, unsigned long count) +{ + unsigned long from_nr_entries = node_get_nr_entries(tree, from); + unsigned long to_nr_entries = node_get_nr_entries(tree, to); + + b_tree_node_entry *from_entries = tree->tree_ops->node_get_entries(from); + b_tree_node_entry *to_entries = tree->tree_ops->node_get_entries(to); + + b_tree_node_entry *src = GET_ENTRY(tree, from_entries, src_index); + b_tree_node_entry *dest = GET_ENTRY(tree, to_entries, dest_index); + + memmove(dest, src, count * tree->tree_ops->entry_size); + if (src_index + count >= from_nr_entries) { + memset(src, 0x0, count * tree->tree_ops->entry_size); + } else { + node_shift_entries(tree, from, src_index + count, (int)count * -1); + } + + from_nr_entries -= count; + to_nr_entries += count; + + node_set_nr_entries(tree, from, from_nr_entries); + node_set_nr_entries(tree, to, to_nr_entries); +} + +static void node_move_children(struct b_tree *tree, b_tree_node *from, b_tree_node *to, unsigned long src_index, unsigned long dest_index, unsigned long count) +{ + unsigned long from_nr_entries = node_get_nr_entries(tree, from); + + uint16_t *from_children = tree->tree_ops->node_get_children(from); + uint16_t *to_children = tree->tree_ops->node_get_children(to); + + uint16_t *src = &from_children[src_index]; + uint16_t *dest = &to_children[dest_index]; + + memmove(dest, src, count * sizeof(uint16_t)); + if (src_index + count >= from_nr_entries + 1) { + memset(src, 0xFF, count * sizeof(uint16_t)); + } + else { + node_shift_children(tree, from, src_index + count, (int)count * -1); + } +} + +static int node_put(struct b_tree *tree, b_tree_node *n, const b_tree_node_entry *e) +{ + unsigned long nr_entries = node_get_nr_entries(tree, n); + if (nr_entries == 0) { + node_set_entry(tree, n, 0, e); + node_set_nr_entries(tree, n, 1); + return 0; + } + + int insert_at = -1; + for (unsigned long i = 0; i < nr_entries; i++) { + const b_tree_node_entry *cur = node_get_entry(tree, n, i); + int cmp = entry_compare(tree, cur, e); + if (cmp == 1) { + insert_at = i; + break; + } + } + + if (insert_at != -1) { + node_shift_entries(tree, n, insert_at, 1); + } + else { + insert_at = nr_entries; + } + + node_set_entry(tree, n, insert_at, e); + nr_entries++; + node_set_nr_entries(tree, n, nr_entries); + return insert_at; } static int node_is_leaf(struct b_tree *tree, b_tree_node *node) @@ -92,7 +274,7 @@ static void node_init(struct b_tree *tree, b_tree_node *out) } } -static int entry_compare(struct b_tree *tree, b_tree_node_entry *a, b_tree_node_entry *b) +static int entry_compare(struct b_tree *tree, const b_tree_node_entry *a, const b_tree_node_entry *b) { return tree->tree_ops->entry_compare(a, b); } @@ -125,11 +307,11 @@ int b_tree_put(struct b_tree *tree, const b_tree_node_entry *to_put) int median = nr_entries / 2; - node_move_entries(current, &a, 0, 0, median); - node_move_entries(current, &b, 1, 0, median); + node_move_entries(tree, current, a, 0, 0, median); + node_move_entries(tree, current, b, 1, 0, median); - node_move_children(current, &a, 0, 0, median + 1); - node_move_children(current, &b, median + 1, 0, median + 1); + node_move_children(tree, current, a, 0, 0, median + 1); + node_move_children(tree, current, b, median + 1, 0, median + 1); int a_index = tree_alloc_id(tree); node_write(tree, a_index, a); @@ -201,47 +383,51 @@ int b_tree_put(struct b_tree *tree, const b_tree_node_entry *to_put) n3_is_next = true; } -#if 0 node_move_entries( + tree, next, - &n3, + n3, median + 1, 0, nr_entries - median - 1); node_move_children( + tree, next, - &n3, + n3, median + 1, 0, nr_entries - median); - int index = node_put(current, &next->entries[median]); - memset(&next->entries[median], 0x00, sizeof(struct entry)); - next->nr_entries--; - node_shift_children(current, index + 1, 1); + + int index = node_put(tree, current, median_node); + node_kill_entry(tree, next, median); + nr_entries = node_get_nr_entries(tree, next); + nr_entries--; + node_set_nr_entries(tree, next, nr_entries); + node_shift_children(tree, current, index + 1, 1); int n3_id = tree_alloc_id(tree); - current->children[index + 1] = n3_id; - node_write(tree->fp, current_id, current); - node_write(tree->fp, next_id, next); - node_write(tree->fp, n3_id, &n3); + node_set_child(tree, current, index + 1, n3_id); + node_write(tree, current_id, current); + node_write(tree, next_id, next); + node_write(tree, n3_id, n3); if (n3_is_next) { - memcpy(current, &n3, sizeof n3); + cache_free_node(tree, current); + current = n3; current_id = n3_id; } else { - SWAP(struct node *, current, next); + SWAP(b_tree_node *, current, next); current_id = next_id; } depth++; - leaf = node_is_leaf(current); -#endif + leaf = node_is_leaf(tree, current); } -#if 0 - node_put(current, e); - node_write(tree->fp, current_id, current); -#endif + + node_put(tree, current, to_put); + node_write(tree, current_id, current); + return 0; } \ No newline at end of file diff --git a/src/b-tree.h b/src/b-tree.h index 8471a9c..dd9ec8e 100644 --- a/src/b-tree.h +++ b/src/b-tree.h @@ -2,29 +2,29 @@ #define B_TREE_H_ #include +#include #include #define B_TREE_INVALID_PTR -1 struct b_tree; -typedef void *b_tree_node; -typedef void *b_tree_node_entry; +typedef struct { char _x; } b_tree_node; +typedef struct { char _x; }b_tree_node_entry; struct b_tree_ops { size_t node_size; size_t entry_size; - int (*tree_get_node)(struct b_tree *, long, void *); - int (*tree_put_node)(struct b_tree *, long, void *); - int (*tree_alloc_node)(struct b_tree *); + int (*tree_get_node)(struct b_tree *, unsigned long, b_tree_node *); + int (*tree_put_node)(struct b_tree *, unsigned long, const b_tree_node *); + long (*tree_alloc_node)(struct b_tree *); - long (*node_get_nr_entries)(b_tree_node *); - b_tree_node_entry *(*node_get_entry)(b_tree_node *, unsigned long); - void (*node_set_entry)(b_tree_node *, int, const b_tree_node_entry *); - long (*node_get_child)(b_tree_node *, unsigned long); - int (*node_set_child)(b_tree_node *, unsigned long, long); + unsigned long (*node_get_nr_entries)(b_tree_node *); + void (*node_set_nr_entries)(b_tree_node *, unsigned long); + b_tree_node_entry *(*node_get_entries)(b_tree_node *); + uint16_t *(*node_get_children)(b_tree_node *); - int (*entry_compare)(b_tree_node_entry *, b_tree_node_entry *); + int (*entry_compare)(const b_tree_node_entry *, const b_tree_node_entry *); }; struct b_tree {