finish implementing generic b-tree put() interface

This commit is contained in:
2025-01-31 21:39:19 +00:00
parent 8d2d937861
commit e181ca6b65
2 changed files with 225 additions and 39 deletions

View File

@@ -1,4 +1,6 @@
#include <blue/core/queue.h> #include <blue/core/queue.h>
#include <stdlib.h>
#include <string.h>
#include "b-tree.h" #include "b-tree.h"
@@ -15,6 +17,10 @@ struct cache_entry {
/* ... node data here ... */ /* ... 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) static b_tree_node *cache_alloc_node(struct b_tree *tree)
{ {
b_queue_iterator it = { 0 }; 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; 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) 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) 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); 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) 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) 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) 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); 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; int median = nr_entries / 2;
node_move_entries(current, &a, 0, 0, median); node_move_entries(tree, current, a, 0, 0, median);
node_move_entries(current, &b, 1, 0, median); node_move_entries(tree, current, b, 1, 0, median);
node_move_children(current, &a, 0, 0, median + 1); node_move_children(tree, current, a, 0, 0, median + 1);
node_move_children(current, &b, median + 1, 0, median + 1); node_move_children(tree, current, b, median + 1, 0, median + 1);
int a_index = tree_alloc_id(tree); int a_index = tree_alloc_id(tree);
node_write(tree, a_index, a); 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; n3_is_next = true;
} }
#if 0
node_move_entries( node_move_entries(
tree,
next, next,
&n3, n3,
median + 1, median + 1,
0, 0,
nr_entries - median - 1); nr_entries - median - 1);
node_move_children( node_move_children(
tree,
next, next,
&n3, n3,
median + 1, median + 1,
0, 0,
nr_entries - median); nr_entries - median);
int index = node_put(current, &next->entries[median]);
memset(&next->entries[median], 0x00, sizeof(struct entry)); int index = node_put(tree, current, median_node);
next->nr_entries--; node_kill_entry(tree, next, median);
node_shift_children(current, index + 1, 1); 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); int n3_id = tree_alloc_id(tree);
current->children[index + 1] = n3_id; node_set_child(tree, current, index + 1, n3_id);
node_write(tree->fp, current_id, current); node_write(tree, current_id, current);
node_write(tree->fp, next_id, next); node_write(tree, next_id, next);
node_write(tree->fp, n3_id, &n3); node_write(tree, n3_id, n3);
if (n3_is_next) { if (n3_is_next) {
memcpy(current, &n3, sizeof n3); cache_free_node(tree, current);
current = n3;
current_id = n3_id; current_id = n3_id;
} }
else { else {
SWAP(struct node *, current, next); SWAP(b_tree_node *, current, next);
current_id = next_id; current_id = next_id;
} }
depth++; depth++;
leaf = node_is_leaf(current); leaf = node_is_leaf(tree, current);
#endif
} }
#if 0
node_put(current, e); node_put(tree, current, to_put);
node_write(tree->fp, current_id, current); node_write(tree, current_id, current);
#endif
return 0; return 0;
} }

View File

@@ -2,29 +2,29 @@
#define B_TREE_H_ #define B_TREE_H_
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
#include <blue/core/queue.h> #include <blue/core/queue.h>
#define B_TREE_INVALID_PTR -1 #define B_TREE_INVALID_PTR -1
struct b_tree; struct b_tree;
typedef void *b_tree_node; typedef struct { char _x; } b_tree_node;
typedef void *b_tree_node_entry; typedef struct { char _x; }b_tree_node_entry;
struct b_tree_ops { struct b_tree_ops {
size_t node_size; size_t node_size;
size_t entry_size; size_t entry_size;
int (*tree_get_node)(struct b_tree *, long, void *); int (*tree_get_node)(struct b_tree *, unsigned long, b_tree_node *);
int (*tree_put_node)(struct b_tree *, long, void *); int (*tree_put_node)(struct b_tree *, unsigned long, const b_tree_node *);
int (*tree_alloc_node)(struct b_tree *); long (*tree_alloc_node)(struct b_tree *);
long (*node_get_nr_entries)(b_tree_node *); unsigned long (*node_get_nr_entries)(b_tree_node *);
b_tree_node_entry *(*node_get_entry)(b_tree_node *, unsigned long); void (*node_set_nr_entries)(b_tree_node *, unsigned long);
void (*node_set_entry)(b_tree_node *, int, const b_tree_node_entry *); b_tree_node_entry *(*node_get_entries)(b_tree_node *);
long (*node_get_child)(b_tree_node *, unsigned long); uint16_t *(*node_get_children)(b_tree_node *);
int (*node_set_child)(b_tree_node *, unsigned long, long);
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 { struct b_tree {