#include "b-tree.h" #include "bin.h" #include "commands.h" #include #include #include #include #define INVALID_NODE_PTR 0xFFFF #define ORDER 6 #define MAX (ORDER - 1) #define MIN (MAX / 2) enum { ARG_INPATH, OPT_OUTPATH, OPT_OUTPATH_PATH, }; struct entry { uint32_t key; uint32_t value; }; struct node { uint16_t nr_entries; struct entry entries[MAX]; uint16_t children[ORDER]; }; struct data_tree { struct b_tree base; FILE *fp; }; static int node_init(struct node *n) { memset(n, 0x0, sizeof *n); for (int i = 0; i < ORDER; i++) { n->children[i] = INVALID_NODE_PTR; } return 0; } static int tree_get_node(struct b_tree *p, unsigned long id, b_tree_node *n) { struct data_tree *tree = (struct data_tree *)p; size_t offset = (id * sizeof(struct node)); fseek(tree->fp, offset, SEEK_SET); size_t r = fread(n, sizeof(struct node), 1, tree->fp); return r == 1 ? 0 : -1; } static int tree_put_node( struct b_tree *p, unsigned long id, const b_tree_node *n) { struct data_tree *tree = (struct data_tree *)p; size_t offset = (id * sizeof(struct node)); fseek(tree->fp, offset, SEEK_SET); size_t r = fwrite(n, sizeof(struct node), 1, tree->fp); return r == 1 ? 0 : -1; } static long tree_alloc_node(struct b_tree *p) { struct data_tree *tree = (struct data_tree *)p; size_t pos = ftell(tree->fp); fseek(tree->fp, 0, SEEK_END); size_t len = ftell(tree->fp); struct node n; node_init(&n); fwrite(&n, sizeof n, 1, tree->fp); fseek(tree->fp, pos, SEEK_SET); len /= sizeof(struct node); return (long)len; } static unsigned long node_get_nr_entries(b_tree_node *n) { struct node *node = (struct node *)n; return node->nr_entries; } static void node_set_nr_entries(b_tree_node *n, unsigned long val) { struct node *node = (struct node *)n; node->nr_entries = val; } static b_tree_node_entry *node_get_entry(b_tree_node *n, unsigned long index) { struct node *node = (struct node *)n; return (b_tree_node_entry *)&node->entries[index]; } static void node_set_entry( b_tree_node *n, unsigned long index, const b_tree_node_entry *entry) { struct node *node = (struct node *)n; memmove(&node->entries[index], entry, sizeof(struct entry)); } static unsigned long node_get_child(b_tree_node *n, unsigned long index) { struct node *node = (struct node *)n; uint16_t child = node->children[index]; return child == INVALID_NODE_PTR ? B_TREE_INVALID_PTR : child; } static void node_set_child( b_tree_node *n, unsigned long index, unsigned long ptr) { struct node *node = (struct node *)n; uint16_t child = ptr == B_TREE_INVALID_PTR ? INVALID_NODE_PTR : (uint16_t)ptr; node->children[index] = child; } static int entry_compare( const b_tree_node_entry *e0, const b_tree_node_entry *e1) { struct entry *a = (struct entry *)e0, *b = (struct entry *)e1; if (a->key < b->key) { return -1; } if (a->key > b->key) { return 1; } return 0; } static const struct b_tree_ops ops = { .tree_get_node = tree_get_node, .tree_put_node = tree_put_node, .tree_alloc_node = tree_alloc_node, .node_get_nr_entries = node_get_nr_entries, .node_set_nr_entries = node_set_nr_entries, .node_get_entry = node_get_entry, .node_set_entry = node_set_entry, .node_get_child = node_get_child, .node_set_child = node_set_child, .entry_compare = entry_compare, }; void indent(int depth) { for (int i = 0; i < depth; i++) { fputs(" ", stdout); } } int node_print(struct b_tree *tree, struct node *n, int depth) { int c_before = (n->nr_entries + 1) / 2; int c_after = n->nr_entries + 1 - c_before; int i_before = 0; int i_after = i_before + c_before; int err = 0; for (unsigned short i = 0; i < c_before; i++) { struct node child; int index = i_before + i; if (n->children[index] == INVALID_NODE_PTR) { // indent(depth + 1); continue; } err = tree_get_node( tree, n->children[index], (b_tree_node *)&child); if (err != 0) { printf("ERR: failed to read node %u\n", n->children[index]); continue; } node_print(tree, &child, depth + 1); } indent(depth); printf("["); for (unsigned short i = 0; i < n->nr_entries; i++) { if (i > 0) { printf(" "); } printf("%d", n->entries[i].key); } printf("]\n"); for (unsigned short i = 0; i < c_after; i++) { struct node child; int index = i_after + i; if (n->children[index] == INVALID_NODE_PTR) { // indent(depth + 1); continue; } err = tree_get_node( tree, n->children[index], (b_tree_node *)&child); if (err != 0) { printf("ERR: failed to read node %u\n", n->children[index]); continue; } node_print(tree, &child, depth + 1); } return 0; } int tree_print(struct b_tree *tree) { struct node root; tree_get_node(tree, 0, (b_tree_node *)&root); return node_print(tree, &root, 0); } static int create( const b_command *self, const b_arglist *opt, const b_array *args) { printf("%zu\n", sizeof(struct ec3_cluster_group)); return 0; const char *in_path = NULL, *out_path = NULL; b_arglist_get_string( opt, B_COMMAND_INVALID_ID, ARG_INPATH, 0, &in_path); b_arglist_get_string(opt, OPT_OUTPATH, OPT_OUTPATH_PATH, 0, &out_path); printf("in path: %s\n", in_path); printf("out path: %s\n", out_path); FILE *fp = fopen(out_path, "w+b"); struct node root; node_init(&root); fwrite(&root, sizeof root, 1, fp); struct data_tree tree; b_tree_init( &tree.base, &ops, sizeof(struct node), sizeof(struct entry), ORDER); tree.fp = fp; for (int i = 1; i <= 32; i++) { int key = rand() % 65535; // int key = i; // printf("%d: adding [%d]\n", i, key); struct entry e = {.key = key, .value = key * 2}; b_tree_put(&tree.base, (b_tree_node_entry *)&e); } tree_print(&tree.base); fclose(fp); return 0; } B_COMMAND(CMD_CREATE, CMD_ROOT) { B_COMMAND_NAME("create"); B_COMMAND_SHORT_NAME('C'); B_COMMAND_DESC("create an ec3 file"); B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT); B_COMMAND_FUNCTION(create); B_COMMAND_HELP_OPTION(); B_COMMAND_OPTION(OPT_OUTPATH) { B_OPTION_SHORT_NAME('o'); B_OPTION_LONG_NAME("out"); B_OPTION_DESC("the path to save the new file to"); B_OPTION_ARG(OPT_OUTPATH_PATH) { B_ARG_NAME("path"); B_ARG_NR_VALUES(1); } } B_COMMAND_ARG(ARG_INPATH) { B_ARG_NAME("input file"); B_ARG_NR_VALUES(1); } B_COMMAND_USAGE() { B_COMMAND_USAGE_ARG(ARG_INPATH); B_COMMAND_USAGE_OPT(OPT_OUTPATH); } }