From 717b51df31be2dbf1201f18dadd3981e70f9fd95 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Thu, 27 Feb 2025 15:49:42 +0000 Subject: [PATCH] chunk: implement chunk_table_put --- src/chunk-table.c | 119 ++++++++++++++++++++++++++++++++++++++++++---- src/chunk-table.h | 7 +++ 2 files changed, 117 insertions(+), 9 deletions(-) diff --git a/src/chunk-table.c b/src/chunk-table.c index b0c2395..fe58789 100644 --- a/src/chunk-table.c +++ b/src/chunk-table.c @@ -4,6 +4,8 @@ #include "bin.h" #include "tag.h" +#include +#include #include struct cache_entry { @@ -18,14 +20,24 @@ static int compare_cache_node( return memcmp(a->e_id, b->e_id, sizeof a->e_id); } +static unsigned int chunk_table_orders[] = { + [EC3_CLUSTER_4K] = EC3_CHUNKS_PER_GROUP_4K + 1, + [EC3_CLUSTER_8K] = EC3_CHUNKS_PER_GROUP_8K + 1, + [EC3_CLUSTER_16K] = EC3_CHUNKS_PER_GROUP_16K + 1, + [EC3_CLUSTER_32K] = EC3_CHUNKS_PER_GROUP_32K + 1, + [EC3_CLUSTER_64K] = EC3_CHUNKS_PER_GROUP_64K + 1, +}; +static size_t nr_chunk_table_orders + = sizeof chunk_table_orders / sizeof chunk_table_orders[0]; + B_BTREE_DEFINE_INSERT( struct cache_entry, e_node, e_id, - get_cache_entry, + put_cache_entry, compare_cache_node) -struct cache_entry *cache_entry_get(const b_btree *tree, ec3_chunk_id key) +struct cache_entry *get_cache_entry(const b_btree *tree, ec3_chunk_id key) { b_btree_node *cur = tree->b_root; while (cur) { @@ -173,7 +185,7 @@ static b_tree_node_entry *node_get_entry( b_tree_node *n, unsigned long index) { - struct chunk_table *table = (struct chunk_table *)table; + struct chunk_table *table = (struct chunk_table *)tree; struct ec3_chunk_group *node = (struct ec3_chunk_group *)n; switch (table->tab_cluster_size) { @@ -198,7 +210,7 @@ static void node_set_entry( unsigned long index, const b_tree_node_entry *entry) { - struct chunk_table *table = (struct chunk_table *)table; + struct chunk_table *table = (struct chunk_table *)tree; struct ec3_chunk_group *node = (struct ec3_chunk_group *)n; switch (table->tab_cluster_size) { @@ -237,7 +249,7 @@ static void node_kill_entry( b_tree_node *n, unsigned long index) { - struct chunk_table *table = (struct chunk_table *)table; + struct chunk_table *table = (struct chunk_table *)tree; struct ec3_chunk_group *node = (struct ec3_chunk_group *)n; switch (table->tab_cluster_size) { @@ -276,7 +288,7 @@ static unsigned long node_get_child( b_tree_node *n, unsigned long index) { - struct chunk_table *table = (struct chunk_table *)table; + struct chunk_table *table = (struct chunk_table *)tree; struct ec3_chunk_group *node = (struct ec3_chunk_group *)n; unsigned long child = EC3_INVALID_OFFSET; @@ -309,7 +321,7 @@ static void node_set_child( unsigned long index, unsigned long ptr) { - struct chunk_table *table = (struct chunk_table *)table; + struct chunk_table *table = (struct chunk_table *)tree; struct ec3_chunk_group *node = (struct ec3_chunk_group *)n; unsigned long child = ptr == B_TREE_INVALID_PTR ? EC3_INVALID_OFFSET : ptr; @@ -346,7 +358,7 @@ static int entry_compare( return memcmp(a->c_id, b->c_id, sizeof a->c_id); } -static const struct b_tree_ops cluster_table_ops = { +static const struct b_tree_ops chunk_table_ops = { .tree_get_node = tree_get_node, .tree_put_node = tree_put_node, .tree_alloc_node = tree_alloc_node, @@ -374,11 +386,53 @@ enum ec3_status chunk_table_init( tab->tab_cdat = cdat; tab->tab_cluster_size = cluster_size; + size_t cluster_size_bytes = ec3_cluster_size_id_to_bytes(cluster_size); + unsigned int order = chunk_table_orders[cluster_size]; + + b_tree_init( + &tab->tab_chunks, + &chunk_table_ops, + cluster_size_bytes, + sizeof(struct ec3_chunk), + order); + + tab->tab_cluster_buf = malloc(cluster_size_bytes); + + if (!tab->tab_cluster_buf) { + return EC3_ERR_NO_MEMORY; + } + return EC3_SUCCESS; } +void chunk_table_init_empty_table(struct chunk_table *table) +{ + /* allocate root node */ + struct ec3_chunk_group *root + = (struct ec3_chunk_group *)b_tree_cache_alloc_node( + &table->tab_chunks); + node_init(table, root); + tree_put_node(&table->tab_chunks, 0, (b_tree_node *)root); + + b_tree_cache_release_node(&table->tab_chunks, (b_tree_node *)root); +} + void chunk_table_finish(struct chunk_table *tab) { + b_btree_iterator it; + b_btree_iterator_begin(&tab->tab_cache, &it); + while (b_btree_iterator_is_valid(&it)) { + struct cache_entry *entry + = b_unbox(struct cache_entry, it.node, e_node); + b_btree_iterator_erase(&it); + free(entry); + } + + b_tree_finish(&tab->tab_chunks); + + if (tab->tab_cluster_buf) { + free(tab->tab_cluster_buf); + } } enum ec3_status chunk_table_get( @@ -387,7 +441,7 @@ enum ec3_status chunk_table_get( void *out_data, size_t *out_len) { - return EC3_SUCCESS; + return EC3_ERR_NOT_SUPPORTED; } enum ec3_status chunk_table_put( @@ -396,5 +450,52 @@ enum ec3_status chunk_table_put( size_t len, ec3_chunk_id out_id) { + b_hash_ctx hash; + b_hash_ctx_init(&hash, B_HASH_SHAKE128); + b_hash_ctx_update(&hash, data, len); + + ec3_chunk_id id; + b_hash_ctx_finish(&hash, id, sizeof id); + + struct cache_entry *entry = get_cache_entry(&tab->tab_cache, id); + if (entry) { + return EC3_SUCCESS; + } + + entry = malloc(sizeof *entry); + if (!entry) { + return EC3_ERR_NO_MEMORY; + } + + size_t nr_written = 0; + + size_t cdat_cluster = tab->tab_next_cdat_cluster++; + enum ec3_status status = ec3_tag_ioctx_write_cluster( + tab->tab_cdat, + cdat_cluster, + data, + len, + &nr_written); + + if (status != EC3_SUCCESS) { + free(entry); + return status; + } + + struct ec3_chunk chunk = {0}; + memcpy(chunk.c_id, id, sizeof id); + int err = b_tree_put( + &tab->tab_chunks, + (const b_tree_node_entry *)&chunk); + + if (err != 0) { + return EC3_ERR_IO_FAILURE; + } + + memset(entry, 0x0, sizeof *entry); + memcpy(entry->e_id, id, sizeof id); + + put_cache_entry(&tab->tab_cache, entry); + return EC3_SUCCESS; } diff --git a/src/chunk-table.h b/src/chunk-table.h index 1d7b8b3..46f123f 100644 --- a/src/chunk-table.h +++ b/src/chunk-table.h @@ -1,6 +1,7 @@ #ifndef CHUNK_TABLE_H_ #define CHUNK_TABLE_H_ +#include "b-tree.h" #include "bin.h" #include @@ -10,9 +11,14 @@ struct ec3_tag_ioctx; struct chunk_table { + struct b_tree tab_chunks; enum ec3_cluster_size tab_cluster_size; b_btree tab_cache; + unsigned char *tab_cluster_buf; + + size_t tab_next_cdat_cluster; + struct ec3_tag_ioctx *tab_ctab; struct ec3_tag_ioctx *tab_cdat; }; @@ -22,6 +28,7 @@ extern enum ec3_status chunk_table_init( struct ec3_tag_ioctx *cdat, enum ec3_cluster_size cluster_size, struct chunk_table *tab); +extern void chunk_table_init_empty_table(struct chunk_table *table); extern void chunk_table_finish(struct chunk_table *tab); extern enum ec3_status chunk_table_get(