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 "tag.h"
#include <blue/core/hash.h>
#include <stdlib.h>
#include <string.h>
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;
}

View File

@@ -1,6 +1,7 @@
#ifndef CHUNK_TABLE_H_
#define CHUNK_TABLE_H_
#include "b-tree.h"
#include "bin.h"
#include <blue/core/btree.h>
@@ -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(