test generic b-tree interface
This commit is contained in:
292
src/create.c
292
src/create.c
@@ -1,17 +1,221 @@
|
|||||||
#include "bin.h"
|
#include "bin.h"
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
|
#include "b-tree.h"
|
||||||
|
|
||||||
#include <blue/cmd.h>
|
#include <blue/cmd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <zstd.h>
|
#include <zstd.h>
|
||||||
|
|
||||||
|
#define INVALID_NODE_PTR 0xFFFF
|
||||||
|
|
||||||
|
#define ORDER 6
|
||||||
|
#define MAX (ORDER - 1)
|
||||||
|
#define MIN (MAX / 2)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ARG_INPATH,
|
ARG_INPATH,
|
||||||
OPT_OUTPATH,
|
OPT_OUTPATH,
|
||||||
OPT_OUTPATH_PATH,
|
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(
|
static int create(
|
||||||
const b_command *self,
|
const b_command *self,
|
||||||
const b_arglist *opt,
|
const b_arglist *opt,
|
||||||
@@ -19,16 +223,6 @@ static int create(
|
|||||||
{
|
{
|
||||||
const char *in_path = NULL, *out_path = NULL;
|
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(
|
b_arglist_get_string(
|
||||||
opt,
|
opt,
|
||||||
B_COMMAND_INVALID_ID,
|
B_COMMAND_INVALID_ID,
|
||||||
@@ -40,72 +234,28 @@ static int create(
|
|||||||
printf("in path: %s\n", in_path);
|
printf("in path: %s\n", in_path);
|
||||||
printf("out path: %s\n", out_path);
|
printf("out path: %s\n", out_path);
|
||||||
|
|
||||||
size_t in_bufsz = ZSTD_CStreamInSize();
|
FILE *fp = fopen(out_path, "w+b");
|
||||||
size_t out_bufsz = ZSTD_CStreamOutSize();
|
|
||||||
|
|
||||||
printf("in buffer: %zu\n", in_bufsz);
|
struct node root;
|
||||||
printf("out buffer: %zu\n", out_bufsz);
|
node_init(&root);
|
||||||
|
fwrite(&root, sizeof root, 1, fp);
|
||||||
|
|
||||||
FILE *in = fopen(in_path, "rb");
|
struct data_tree tree;
|
||||||
if (!in) {
|
b_tree_init(&tree.base, &ops, ORDER);
|
||||||
return -1;
|
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");
|
tree_print(&tree.base);
|
||||||
if (!out) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZSTD_CCtx *zstd = ZSTD_createCCtx();
|
fclose(fp);
|
||||||
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);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user