chunk: implement chunk_table_put
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user