diff --git a/src/create.c b/src/create.c index c4986f7..05bfa61 100644 --- a/src/create.c +++ b/src/create.c @@ -1,17 +1,221 @@ #include "bin.h" #include "commands.h" +#include "b-tree.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_entries(b_tree_node *n) +{ + struct node *node = (struct node *)n; + return (b_tree_node_entry *)node->entries; +} + +static uint16_t *node_get_children(b_tree_node *n) +{ + struct node *node = (struct node *)n; + return node->children; +} + +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 = { + .node_size = sizeof(struct node), + .entry_size = sizeof(struct entry), + + .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_entries = node_get_entries, + .node_get_children = node_get_children, + + .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, @@ -19,16 +223,6 @@ static int create( { const char *in_path = NULL, *out_path = NULL; - printf("cluster group = %zu\n", sizeof(struct ec3_cluster_group)); - printf("chunk group = %zu\n", sizeof(struct ec3_chunk_group)); - printf("vnode group = %zu\n", sizeof(struct ec3_vnode_group)); - printf("vnch group = %zu\n", sizeof(struct ec3_vnode_chunk_group)); - printf("vnode = %zu\n", sizeof(struct ec3_vnode)); - printf("chunk = %zu\n", sizeof(struct ec3_chunk)); - printf("link = %zu\n", sizeof(struct ec3_vnode_chunk)); - - return 0; - b_arglist_get_string( opt, B_COMMAND_INVALID_ID, @@ -40,72 +234,28 @@ static int create( printf("in path: %s\n", in_path); printf("out path: %s\n", out_path); - size_t in_bufsz = ZSTD_CStreamInSize(); - size_t out_bufsz = ZSTD_CStreamOutSize(); + FILE *fp = fopen(out_path, "w+b"); - printf("in buffer: %zu\n", in_bufsz); - printf("out buffer: %zu\n", out_bufsz); + struct node root; + node_init(&root); + fwrite(&root, sizeof root, 1, fp); - FILE *in = fopen(in_path, "rb"); - if (!in) { - return -1; + struct data_tree tree; + b_tree_init(&tree.base, &ops, 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); } - FILE *out = fopen(out_path, "wb"); - if (!out) { - return -1; - } - - ZSTD_CCtx *zstd = ZSTD_createCCtx(); - ZSTD_CCtx_setParameter(zstd, ZSTD_c_compressionLevel, 22); - ZSTD_CCtx_setParameter(zstd, ZSTD_c_checksumFlag, 1); - - void *in_buf = malloc(in_bufsz); - void *out_buf = malloc(out_bufsz); - - size_t total = 0; - - while (1) { - size_t r = fread(in_buf, 1, in_bufsz, in); - if (r == 0) { - break; - } - - if ((total % 0x1000000) == 0) { - printf("read %zu MB bytes\n", total / 1000000); - } - total += r; - - bool last_chunk = r < in_bufsz; - ZSTD_EndDirective mode - = last_chunk ? ZSTD_e_end : ZSTD_e_continue; - - ZSTD_inBuffer input = {in_buf, r, 0}; - int finished; - do { - ZSTD_outBuffer output = {out_buf, out_bufsz, 0}; - size_t remaining = ZSTD_compressStream2( - zstd, - &output, - &input, - mode); - - fwrite(out_buf, 1, output.pos, out); - - finished = last_chunk ? (remaining == 0) - : (input.pos == input.size); - } while (!finished); - - if (last_chunk) { - break; - } - } - - ZSTD_freeCCtx(zstd); - fclose(out); - fclose(in); - free(in_buf); - free(out_buf); + tree_print(&tree.base); + + fclose(fp); return 0; }