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