chunk: implement chunk_table_put

This commit is contained in:
2025-02-27 15:49:42 +00:00
parent d423826815
commit 717b51df31
2 changed files with 117 additions and 9 deletions

View File

@@ -4,6 +4,8 @@
#include "bin.h" #include "bin.h"
#include "tag.h" #include "tag.h"
#include <blue/core/hash.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
struct cache_entry { struct cache_entry {
@@ -18,14 +20,24 @@ static int compare_cache_node(
return memcmp(a->e_id, b->e_id, sizeof a->e_id); 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( B_BTREE_DEFINE_INSERT(
struct cache_entry, struct cache_entry,
e_node, e_node,
e_id, e_id,
get_cache_entry, put_cache_entry,
compare_cache_node) 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; b_btree_node *cur = tree->b_root;
while (cur) { while (cur) {
@@ -173,7 +185,7 @@ static b_tree_node_entry *node_get_entry(
b_tree_node *n, b_tree_node *n,
unsigned long index) 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; struct ec3_chunk_group *node = (struct ec3_chunk_group *)n;
switch (table->tab_cluster_size) { switch (table->tab_cluster_size) {
@@ -198,7 +210,7 @@ static void node_set_entry(
unsigned long index, unsigned long index,
const b_tree_node_entry *entry) 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; struct ec3_chunk_group *node = (struct ec3_chunk_group *)n;
switch (table->tab_cluster_size) { switch (table->tab_cluster_size) {
@@ -237,7 +249,7 @@ static void node_kill_entry(
b_tree_node *n, b_tree_node *n,
unsigned long index) 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; struct ec3_chunk_group *node = (struct ec3_chunk_group *)n;
switch (table->tab_cluster_size) { switch (table->tab_cluster_size) {
@@ -276,7 +288,7 @@ static unsigned long node_get_child(
b_tree_node *n, b_tree_node *n,
unsigned long index) 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; struct ec3_chunk_group *node = (struct ec3_chunk_group *)n;
unsigned long child = EC3_INVALID_OFFSET; unsigned long child = EC3_INVALID_OFFSET;
@@ -309,7 +321,7 @@ static void node_set_child(
unsigned long index, unsigned long index,
unsigned long ptr) 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; struct ec3_chunk_group *node = (struct ec3_chunk_group *)n;
unsigned long child unsigned long child
= ptr == B_TREE_INVALID_PTR ? EC3_INVALID_OFFSET : ptr; = 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); 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_get_node = tree_get_node,
.tree_put_node = tree_put_node, .tree_put_node = tree_put_node,
.tree_alloc_node = tree_alloc_node, .tree_alloc_node = tree_alloc_node,
@@ -374,11 +386,53 @@ enum ec3_status chunk_table_init(
tab->tab_cdat = cdat; tab->tab_cdat = cdat;
tab->tab_cluster_size = cluster_size; 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; 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) 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( enum ec3_status chunk_table_get(
@@ -387,7 +441,7 @@ enum ec3_status chunk_table_get(
void *out_data, void *out_data,
size_t *out_len) size_t *out_len)
{ {
return EC3_SUCCESS; return EC3_ERR_NOT_SUPPORTED;
} }
enum ec3_status chunk_table_put( enum ec3_status chunk_table_put(
@@ -396,5 +450,52 @@ enum ec3_status chunk_table_put(
size_t len, size_t len,
ec3_chunk_id out_id) 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; return EC3_SUCCESS;
} }

View File

@@ -1,6 +1,7 @@
#ifndef CHUNK_TABLE_H_ #ifndef CHUNK_TABLE_H_
#define CHUNK_TABLE_H_ #define CHUNK_TABLE_H_
#include "b-tree.h"
#include "bin.h" #include "bin.h"
#include <blue/core/btree.h> #include <blue/core/btree.h>
@@ -10,9 +11,14 @@
struct ec3_tag_ioctx; struct ec3_tag_ioctx;
struct chunk_table { struct chunk_table {
struct b_tree tab_chunks;
enum ec3_cluster_size tab_cluster_size; enum ec3_cluster_size tab_cluster_size;
b_btree tab_cache; 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_ctab;
struct ec3_tag_ioctx *tab_cdat; struct ec3_tag_ioctx *tab_cdat;
}; };
@@ -22,6 +28,7 @@ extern enum ec3_status chunk_table_init(
struct ec3_tag_ioctx *cdat, struct ec3_tag_ioctx *cdat,
enum ec3_cluster_size cluster_size, enum ec3_cluster_size cluster_size,
struct chunk_table *tab); 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 void chunk_table_finish(struct chunk_table *tab);
extern enum ec3_status chunk_table_get( extern enum ec3_status chunk_table_get(