From c5d8b4e88194319f756ab4e1cdea20a240d93402 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 2 Feb 2025 15:20:11 +0000 Subject: [PATCH] create cluster table while writing tag data to image --- src/b-tree.c | 313 ++++++++++++++++++++++++++++++++++---------------- src/b-tree.h | 40 +++++-- src/bin.h | 87 +++++++------- src/cluster.c | 218 ++++++++++++++++++++++++++++++++--- src/create.c | 89 +++++++++----- src/write.c | 20 +++- 6 files changed, 569 insertions(+), 198 deletions(-) diff --git a/src/b-tree.c b/src/b-tree.c index 255b0d3..9c51a41 100644 --- a/src/b-tree.c +++ b/src/b-tree.c @@ -1,10 +1,10 @@ +#include "b-tree.h" + +#include #include #include -#include #include -#include "b-tree.h" - #define SWAP(type, x, y) \ do { \ type tmp = x; \ @@ -18,15 +18,17 @@ struct cache_entry { /* ... node data here ... */ }; -#define GET_ENTRY(tree, entries, index) \ - (b_tree_node_entry *)((unsigned char *)(entries) + ((index) * (tree)->tree_entry_size)); - +#define GET_ENTRY(tree, entries, index) \ + (b_tree_node_entry *)((unsigned char *)(entries) \ + + ((index) * (tree)->tree_entry_size)); static b_tree_node *cache_alloc_node(struct b_tree *tree) { - b_queue_iterator it = { 0 }; - b_queue_foreach (&it, &tree->tree_cache) { - struct cache_entry *e = b_unbox(struct cache_entry, it.entry, c_entry); + b_queue_iterator it = {0}; + b_queue_foreach(&it, &tree->tree_cache) + { + struct cache_entry *e + = b_unbox(struct cache_entry, it.entry, c_entry); if (!e->c_allocated) { e->c_allocated = 1; return (b_tree_node *)(e + 1); @@ -49,11 +51,27 @@ static b_tree_node *cache_alloc_node(struct b_tree *tree) static void cache_free_node(struct b_tree *tree, b_tree_node *node) { - struct cache_entry *e = (struct cache_entry *)((unsigned char *)node - sizeof *e); + struct cache_entry *e + = (struct cache_entry *)((unsigned char *)node - sizeof *e); e->c_allocated = 0; } -void b_tree_init(struct b_tree *tree, const struct b_tree_ops *ops, unsigned int node_size, unsigned int entry_size, unsigned int order) +b_tree_node *b_tree_cache_alloc_node(struct b_tree *tree) +{ + return cache_alloc_node(tree); +} + +void b_tree_cache_release_node(struct b_tree *tree, b_tree_node *node) +{ + cache_free_node(tree, node); +} + +void b_tree_init( + struct b_tree *tree, + const struct b_tree_ops *ops, + unsigned int node_size, + unsigned int entry_size, + unsigned int order) { memset(tree, 0x0, sizeof *tree); assert((order % 2) == 0); @@ -83,82 +101,95 @@ static unsigned long node_get_nr_entries(struct b_tree *tree, b_tree_node *node) return tree->tree_ops->node_get_nr_entries(node); } -static void node_set_nr_entries(struct b_tree *tree, b_tree_node *node, unsigned long val) +static void node_set_nr_entries( + struct b_tree *tree, + b_tree_node *node, + unsigned long val) { tree->tree_ops->node_set_nr_entries(node, val); } -static long node_get_child(struct b_tree *tree, b_tree_node *node, unsigned long index) +static unsigned long node_get_child( + struct b_tree *tree, + b_tree_node *node, + unsigned long index) { - uint16_t *children = tree->tree_ops->node_get_children(node); - if (children[index] == 0xFFFF) { - return B_TREE_INVALID_PTR; - } - - return children[index]; + return tree->tree_ops->node_get_child(node, index); } -static void node_set_child(struct b_tree *tree, b_tree_node *node, unsigned long index, long ptr) +static void node_set_child( + struct b_tree *tree, + b_tree_node *node, + unsigned long index, + unsigned long ptr) { - uint16_t *children = tree->tree_ops->node_get_children(node); - if (ptr == B_TREE_INVALID_PTR) { - children[index] = 0xFFFF; - } else { - children[index] = ptr; - } + tree->tree_ops->node_set_child(node, index, ptr); } -static b_tree_node_entry *node_get_entry(struct b_tree *tree, b_tree_node *node, unsigned long index) +static b_tree_node_entry *node_get_entry( + struct b_tree *tree, + b_tree_node *node, + unsigned long index) { - b_tree_node_entry *entries = tree->tree_ops->node_get_entries(node); - return GET_ENTRY(tree, entries, index); + return tree->tree_ops->node_get_entry(node, index); } -static void node_set_entry(struct b_tree *tree, b_tree_node *node, unsigned long index, const b_tree_node_entry *entry) +static void node_set_entry( + struct b_tree *tree, + b_tree_node *node, + unsigned long index, + const b_tree_node_entry *entry) { - b_tree_node_entry *entries = tree->tree_ops->node_get_entries(node); - b_tree_node_entry *dest = GET_ENTRY(tree, entries, index); - memcpy(dest, entry, tree->tree_entry_size); + tree->tree_ops->node_set_entry(node, index, entry); } -static void node_kill_entry(struct b_tree *tree, b_tree_node *node, unsigned long index) +static void node_kill_entry( + struct b_tree *tree, + b_tree_node *node, + unsigned long index) { - b_tree_node_entry *entries = tree->tree_ops->node_get_entries(node); - b_tree_node_entry *dest = GET_ENTRY(tree, entries, index); - memset(dest, 0x0, tree->tree_entry_size); + tree->tree_ops->node_kill_entry(node, index); } -static void node_shift_entries(struct b_tree *tree, b_tree_node *node, unsigned long shift_from, long shift_by) +static void node_shift_entries( + struct b_tree *tree, + b_tree_node *node, + unsigned long shift_from, + long shift_by) { unsigned long nr_entries = node_get_nr_entries(tree, node); - b_tree_node_entry *entries = tree->tree_ops->node_get_entries(node); if (shift_from >= nr_entries) { return; } - b_tree_node_entry *src = GET_ENTRY(tree, entries, shift_from); - b_tree_node_entry *dest = GET_ENTRY(tree, entries, shift_from + shift_by); - unsigned int count = nr_entries - shift_from; + unsigned long src = shift_from; + unsigned long dest = shift_from + shift_by; + unsigned long count = nr_entries - shift_from; - memmove(dest, src, tree->tree_entry_size * count); - if (shift_by < 0) { - dest = GET_ENTRY(tree, entries, nr_entries + shift_by); - count = abs(shift_by); + for (unsigned long i = 0; i < count; i++) { + b_tree_node_entry *entry = node_get_entry(tree, node, src + i); + node_set_entry(tree, node, dest + i, entry); } - else { + + if (shift_by < 0) { + dest = nr_entries + shift_by; + count = labs(shift_by); + } else { dest = src; count = shift_by; } - memset(dest, 0x0, count * tree->tree_entry_size); - return; + node_kill_entry(tree, node, dest); } -static void node_shift_children(struct b_tree *tree, b_tree_node *node, unsigned long shift_from, long shift_by) +static void node_shift_children( + struct b_tree *tree, + b_tree_node *node, + unsigned long shift_from, + long shift_by) { unsigned long nr_entries = node_get_nr_entries(tree, node); - uint16_t *children = tree->tree_ops->node_get_children(node); if (shift_from >= nr_entries + 1) { return; @@ -168,42 +199,56 @@ static void node_shift_children(struct b_tree *tree, b_tree_node *node, unsigned return; } - uint16_t *src = &children[shift_from]; - uint16_t *dest = &children[shift_from + shift_by]; - unsigned int count = nr_entries + 1 - shift_from; + unsigned long src = shift_from; + unsigned long dest = shift_from + shift_by; + unsigned long count = nr_entries + 1 - shift_from; if (shift_by > 0) { count -= shift_by; } - memmove(dest, src, sizeof(uint16_t) * count); - if (shift_by < 0) { - dest = &children[nr_entries + 1 + shift_from]; - count = abs(shift_by); + for (unsigned long i = 0; i < count; i++) { + unsigned long child = node_get_child(tree, node, src + i); + node_set_child(tree, node, dest + i, child); } - else { + + if (shift_by < 0) { + dest = nr_entries + 1 + shift_from; + count = labs(shift_by); + } else { dest = src; count = shift_by; } - memset(dest, 0xFF, count * sizeof(uint16_t)); + node_set_child(tree, node, dest, B_TREE_INVALID_PTR); } -static void node_move_entries(struct b_tree *tree, b_tree_node *from, b_tree_node *to, unsigned long src_index, unsigned long dest_index, unsigned long count) +static void node_move_entries( + struct b_tree *tree, + b_tree_node *from, + b_tree_node *to, + unsigned long src_index, + unsigned long dest_index, + unsigned long count) { unsigned long from_nr_entries = node_get_nr_entries(tree, from); unsigned long to_nr_entries = node_get_nr_entries(tree, to); - b_tree_node_entry *from_entries = tree->tree_ops->node_get_entries(from); - b_tree_node_entry *to_entries = tree->tree_ops->node_get_entries(to); + for (unsigned long i = 0; i < count; i++) { + b_tree_node_entry *entry + = node_get_entry(tree, from, src_index + i); + node_set_entry(tree, to, dest_index + i, entry); + } - b_tree_node_entry *src = GET_ENTRY(tree, from_entries, src_index); - b_tree_node_entry *dest = GET_ENTRY(tree, to_entries, dest_index); - - memmove(dest, src, count * tree->tree_entry_size); if (src_index + count >= from_nr_entries) { - memset(src, 0x0, count * tree->tree_entry_size); + for (unsigned int i = 0; i < count; i++) { + node_kill_entry(tree, from, src_index + i); + } } else { - node_shift_entries(tree, from, src_index + count, (int)count * -1); + node_shift_entries( + tree, + from, + src_index + count, + (int)count * -1); } from_nr_entries -= count; @@ -213,26 +258,50 @@ static void node_move_entries(struct b_tree *tree, b_tree_node *from, b_tree_nod node_set_nr_entries(tree, to, to_nr_entries); } -static void node_move_children(struct b_tree *tree, b_tree_node *from, b_tree_node *to, unsigned long src_index, unsigned long dest_index, unsigned long count) +static void node_move_children( + struct b_tree *tree, + b_tree_node *from, + b_tree_node *to, + unsigned long src_index, + unsigned long dest_index, + unsigned long count) { unsigned long from_nr_entries = node_get_nr_entries(tree, from); - uint16_t *from_children = tree->tree_ops->node_get_children(from); - uint16_t *to_children = tree->tree_ops->node_get_children(to); - - uint16_t *src = &from_children[src_index]; - uint16_t *dest = &to_children[dest_index]; - - memmove(dest, src, count * sizeof(uint16_t)); - if (src_index + count >= from_nr_entries + 1) { - memset(src, 0xFF, count * sizeof(uint16_t)); + for (unsigned long i = 0; i < count; i++) { + unsigned long child = node_get_child(tree, from, src_index + i); + node_set_child(tree, to, dest_index + i, child); } - else { - node_shift_children(tree, from, src_index + count, (int)count * -1); + + if (src_index + count >= from_nr_entries + 1) { + for (unsigned int i = 0; i < count; i++) { + node_set_child( + tree, + from, + src_index + i, + B_TREE_INVALID_PTR); + } + } else { + node_shift_children( + tree, + from, + src_index + count, + (int)count * -1); } } -static int node_put(struct b_tree *tree, b_tree_node *n, const b_tree_node_entry *e) +static int entry_compare( + struct b_tree *tree, + const b_tree_node_entry *a, + const b_tree_node_entry *b) +{ + return tree->tree_ops->entry_compare(a, b); +} + +static int node_put( + struct b_tree *tree, + b_tree_node *n, + const b_tree_node_entry *e) { unsigned long nr_entries = node_get_nr_entries(tree, n); if (nr_entries == 0) { @@ -253,8 +322,7 @@ static int node_put(struct b_tree *tree, b_tree_node *n, const b_tree_node_entry if (insert_at != -1) { node_shift_entries(tree, n, insert_at, 1); - } - else { + } else { insert_at = nr_entries; } @@ -278,18 +346,13 @@ static void node_init(struct b_tree *tree, b_tree_node *out) } } -static int entry_compare(struct b_tree *tree, const b_tree_node_entry *a, const b_tree_node_entry *b) -{ - return tree->tree_ops->entry_compare(a, b); -} - int b_tree_put(struct b_tree *tree, const b_tree_node_entry *to_put) { int depth = 0; long current_id = tree->tree_root; long next_id = -1; - + b_tree_node *current = cache_alloc_node(tree); b_tree_node *next = cache_alloc_node(tree); @@ -305,7 +368,7 @@ int b_tree_put(struct b_tree *tree, const b_tree_node_entry *to_put) /* root node is full. split it pre-emptively. */ b_tree_node *a = next; b_tree_node *b = cache_alloc_node(tree); - + node_init(tree, a); node_init(tree, b); @@ -341,7 +404,8 @@ int b_tree_put(struct b_tree *tree, const b_tree_node_entry *to_put) next_id = node_get_child(tree, current, nr_entries); for (i = 0; i < nr_entries; i++) { - b_tree_node_entry *entry = node_get_entry(tree, current, i); + b_tree_node_entry *entry + = node_get_entry(tree, current, i); int cmp = entry_compare(tree, entry, to_put); if (cmp == 1) { @@ -358,8 +422,6 @@ int b_tree_put(struct b_tree *tree, const b_tree_node_entry *to_put) nr_entries = node_get_nr_entries(tree, next); if (nr_entries < tree->tree_order - 1) { /* swap current and next pointers. */ - SWAP(b_tree_node *, current, next); - current_id = next_id; leaf = node_is_leaf(tree, current); @@ -380,7 +442,8 @@ int b_tree_put(struct b_tree *tree, const b_tree_node_entry *to_put) bool n3_is_next = false; nr_entries = node_get_nr_entries(tree, next); int median = nr_entries / 2; - b_tree_node_entry *median_node = node_get_entry(tree, next, median); + b_tree_node_entry *median_node + = node_get_entry(tree, next, median); int cmp = entry_compare(tree, median_node, to_put); if (cmp == -1) { // median++; @@ -401,7 +464,7 @@ int b_tree_put(struct b_tree *tree, const b_tree_node_entry *to_put) median + 1, 0, nr_entries - median); - + int index = node_put(tree, current, median_node); node_kill_entry(tree, next, median); nr_entries = node_get_nr_entries(tree, next); @@ -420,8 +483,7 @@ int b_tree_put(struct b_tree *tree, const b_tree_node_entry *to_put) cache_free_node(tree, current); current = n3; current_id = n3_id; - } - else { + } else { SWAP(b_tree_node *, current, next); current_id = next_id; } @@ -434,4 +496,57 @@ int b_tree_put(struct b_tree *tree, const b_tree_node_entry *to_put) node_write(tree, current_id, current); return 0; -} \ No newline at end of file +} + +int b_tree_get(struct b_tree *tree, b_tree_node_entry *to_get) +{ + long current_id = tree->tree_root; + long next_id = -1; + + b_tree_node *current = cache_alloc_node(tree); + b_tree_node *next = cache_alloc_node(tree); + + int err = node_read(tree, current_id, current); + + if (err != 0) { + return err; + } + + unsigned long nr_entries = node_get_nr_entries(tree, current); + + while (1) { + unsigned int i; + bool found_bigger_key = false; + + nr_entries = node_get_nr_entries(tree, current); + next_id = node_get_child(tree, current, nr_entries); + + for (i = 0; i < nr_entries; i++) { + b_tree_node_entry *entry + = node_get_entry(tree, current, i); + int cmp = entry_compare(tree, entry, to_get); + + if (cmp == 0) { + memcpy(to_get, entry, tree->tree_entry_size); + return 0; + } + + if (cmp == 1) { + next_id = node_get_child(tree, current, i); + break; + } + } + + err = node_read(tree, next_id, next); + if (err != 0) { + return err; + } + + /* swap current and next pointers. */ + SWAP(b_tree_node *, current, next); + current_id = next_id; + nr_entries = node_get_nr_entries(tree, current); + } + + return -1; +} diff --git a/src/b-tree.h b/src/b-tree.h index fbd4413..f5fdf17 100644 --- a/src/b-tree.h +++ b/src/b-tree.h @@ -1,27 +1,42 @@ #ifndef B_TREE_H_ #define B_TREE_H_ +#include #include #include -#include #define B_TREE_INVALID_PTR -1 struct b_tree; -typedef struct { char _x; } b_tree_node; -typedef struct { char _x; }b_tree_node_entry; +typedef struct { + char _x; +} b_tree_node; +typedef struct { + char _x; +} b_tree_node_entry; struct b_tree_ops { int (*tree_get_node)(struct b_tree *, unsigned long, b_tree_node *); - int (*tree_put_node)(struct b_tree *, unsigned long, const b_tree_node *); + int (*tree_put_node)( + struct b_tree *, + unsigned long, + const b_tree_node *); long (*tree_alloc_node)(struct b_tree *); unsigned long (*node_get_nr_entries)(b_tree_node *); void (*node_set_nr_entries)(b_tree_node *, unsigned long); - b_tree_node_entry *(*node_get_entries)(b_tree_node *); - uint16_t *(*node_get_children)(b_tree_node *); + b_tree_node_entry *(*node_get_entry)(b_tree_node *, unsigned long); + void (*node_set_entry)( + b_tree_node *, + unsigned long, + const b_tree_node_entry *); + void (*node_kill_entry)(b_tree_node *, unsigned long); + unsigned long (*node_get_child)(b_tree_node *, unsigned long); + void (*node_set_child)(b_tree_node *, unsigned long, unsigned long); - int (*entry_compare)(const b_tree_node_entry *, const b_tree_node_entry *); + int (*entry_compare)( + const b_tree_node_entry *, + const b_tree_node_entry *); }; struct b_tree { @@ -33,7 +48,16 @@ struct b_tree { long tree_root; }; -extern void b_tree_init(struct b_tree *tree, const struct b_tree_ops *ops, unsigned int node_size, unsigned int entry_size, unsigned int order); +extern void b_tree_init( + struct b_tree *tree, + const struct b_tree_ops *ops, + unsigned int node_size, + unsigned int entry_size, + unsigned int order); extern int b_tree_put(struct b_tree *tree, const b_tree_node_entry *entry); +extern int b_tree_get(struct b_tree *tree, b_tree_node_entry *entry); + +extern b_tree_node *b_tree_cache_alloc_node(struct b_tree *tree); +extern void b_tree_cache_release_node(struct b_tree *tree, b_tree_node *node); #endif diff --git a/src/bin.h b/src/bin.h index b695c24..3654547 100644 --- a/src/bin.h +++ b/src/bin.h @@ -1,9 +1,10 @@ #ifndef BIN_H_ #define BIN_H_ -#include #include "misc.h" +#include + #define EC3_SIGNATURE 0x45433358 #define EC3_VERSION_1_0 0x0100 @@ -34,6 +35,8 @@ #define EC3_TAG_COMPRESSED 0x00000002u #define EC3_TAG_ENCRYPTED 0x00000004u +#define EC3_INVALID_OFFSET 0xFFFFFFFFu + /* 32K per cluster group */ #define EC3_CLUSTERS_PER_GROUP 1637 /* 1K per extent group */ @@ -68,52 +71,46 @@ typedef uint8_t ec3_chunk_id[EC3_CHUNK_ID_SIZE]; -PACK( - struct ec3_header { - b_i32 h_magic; - b_i16 h_version; - b_i16 h_cluster_size; - b_i64 h_tag_table_offset; - b_i64 h_extent_table_offset; - b_i64 h_cluster_table_offset; - b_i32 h_tag_count; - b_i32 h_extent_count; - b_i32 h_cluster_group_count; - b_i16 h_compression; - b_i16 h_encryption; - b_i64 h_app_magic; - uint8_t h_reserved[8]; - } -); +PACK(struct ec3_header { + b_i32 h_magic; + b_i16 h_version; + b_i16 h_cluster_size; + b_i64 h_tag_table_offset; + b_i64 h_extent_table_offset; + b_i64 h_cluster_table_offset; + b_i32 h_tag_count; + b_i32 h_extent_count; + b_i32 h_cluster_group_count; + b_i16 h_compression; + b_i16 h_encryption; + b_i64 h_app_magic; + uint8_t h_reserved[8]; +}); -PACK( - struct ec3_cluster { - /* cluster identifier */ - b_i32 c_id; - /* lower 32-bits of the cluster bounds */ - b_i32 c_bounds0; - /* upper 32-bits of the cluster bounds */ - b_i32 c_bounds1; - /* CRC-16 of the on-disk cluster data */ - b_i16 c_checksum; - /* flags that apply to this cluster */ - b_i16 c_flags; - } -); +PACK(struct ec3_cluster { + /* cluster identifier */ + b_i32 c_id; + /* lower 32-bits of the cluster bounds */ + b_i32 c_bounds0; + /* upper 32-bits of the cluster bounds */ + b_i32 c_bounds1; + /* CRC-16 of the on-disk cluster data */ + b_i16 c_checksum; + /* flags that apply to this cluster */ + b_i16 c_flags; +}); -PACK( - struct ec3_cluster_group { - /* the number of clusters that this group contains */ - b_i16 g_nr_clusters; - uint8_t g_reserved[2]; - /* array of clusters contained within the group. */ - struct ec3_cluster g_clusters[EC3_CLUSTERS_PER_GROUP]; - /* offsets to other cluster groups, relative to the start of the - * cluster group table. the cluster groups form a B-tree. */ - b_i32 g_child_offsets[EC3_CLUSTERS_PER_GROUP + 1]; - uint8_t g_padding[20]; - } -); +PACK(struct ec3_cluster_group { + /* the number of clusters that this group contains */ + b_i16 g_nr_clusters; + uint8_t g_reserved[2]; + /* array of clusters contained within the group. */ + struct ec3_cluster g_clusters[EC3_CLUSTERS_PER_GROUP]; + /* offsets to other cluster groups, relative to the start of the + * cluster group table. the cluster groups form a B-tree. */ + b_i32 g_child_offsets[EC3_CLUSTERS_PER_GROUP + 1]; + uint8_t g_padding[20]; +}); struct ec3_tag_table_entry { b_i32 tag_type; diff --git a/src/cluster.c b/src/cluster.c index 76dcdff..20f56dc 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -1,19 +1,149 @@ -#include - -#include "bin.h" #include "cluster.h" +#include "bin.h" + +#include + +static int node_init(struct ec3_cluster_group *n) +{ + memset(n, 0x0, sizeof *n); + + for (int i = 0; i < EC3_CLUSTERS_PER_GROUP + 1; i++) { + n->g_child_offsets[i] = b_i32_htob(EC3_INVALID_OFFSET); + } + + return 0; +} + +static int tree_get_node(struct b_tree *p, unsigned long id, b_tree_node *n) +{ + struct cluster_table *table = (struct cluster_table *)p; + size_t offset = (id * sizeof(struct ec3_cluster_group)); + fseek(table->t_storage, offset, SEEK_SET); + size_t r + = fread(n, + sizeof(struct ec3_cluster_group), + 1, + table->t_storage); + return r == 1 ? 0 : -1; +} + +static int tree_put_node( + struct b_tree *p, + unsigned long id, + const b_tree_node *n) +{ + struct cluster_table *table = (struct cluster_table *)p; + size_t offset = (id * sizeof(struct ec3_cluster_group)); + fseek(table->t_storage, offset, SEEK_SET); + size_t r = fwrite( + n, + sizeof(struct ec3_cluster_group), + 1, + table->t_storage); + return r == 1 ? 0 : -1; +} + +static long tree_alloc_node(struct b_tree *p) +{ + struct cluster_table *table = (struct cluster_table *)p; + size_t pos = ftell(table->t_storage); + fseek(table->t_storage, 0, SEEK_END); + size_t len = ftell(table->t_storage); + + struct ec3_cluster_group *n + = (struct ec3_cluster_group *)b_tree_cache_alloc_node(p); + node_init(n); + + fwrite(&n, sizeof *n, 1, table->t_storage); + + fseek(table->t_storage, pos, SEEK_SET); + + len /= sizeof *n; + + return (long)len; +} + +static unsigned long node_get_nr_entries(b_tree_node *n) +{ + struct ec3_cluster_group *node = (struct ec3_cluster_group *)n; + return b_i16_btoh(node->g_nr_clusters); +} + +static void node_set_nr_entries(b_tree_node *n, unsigned long val) +{ + struct ec3_cluster_group *node = (struct ec3_cluster_group *)n; + node->g_nr_clusters = b_i16_htob(val); +} + +static b_tree_node_entry *node_get_entry(b_tree_node *n, unsigned long index) +{ + struct ec3_cluster_group *node = (struct ec3_cluster_group *)n; + return (b_tree_node_entry *)&node->g_clusters[index]; +} + +static void node_set_entry( + b_tree_node *n, + unsigned long index, + const b_tree_node_entry *entry) +{ + struct ec3_cluster_group *node = (struct ec3_cluster_group *)n; + memmove(&node->g_clusters[index], entry, sizeof(struct ec3_cluster)); +} + +static unsigned long node_get_child(b_tree_node *n, unsigned long index) +{ + struct ec3_cluster_group *node = (struct ec3_cluster_group *)n; + b_i32 enc_child = node->g_child_offsets[index]; + unsigned long child = b_i32_btoh(enc_child); + return child == EC3_INVALID_OFFSET ? B_TREE_INVALID_PTR : child; +} + +static void node_set_child( + b_tree_node *n, + unsigned long index, + unsigned long ptr) +{ + struct ec3_cluster_group *node = (struct ec3_cluster_group *)n; + unsigned long child = ptr == B_TREE_INVALID_PTR ? EC3_INVALID_OFFSET + : (uint16_t)ptr; + node->g_child_offsets[index] = b_i32_htob(child); +} + +static int entry_compare( + const b_tree_node_entry *e0, + const b_tree_node_entry *e1) +{ + struct ec3_cluster *a = (struct ec3_cluster *)e0, + *b = (struct ec3_cluster *)e1; + + unsigned long a_id = b_i32_btoh(a->c_id); + unsigned long b_id = b_i32_btoh(b->c_id); + + if (a_id < b_id) { + return -1; + } + + if (a_id > b_id) { + return 1; + } + + return 0; +} + static const struct b_tree_ops cluster_table_ops = { - .tree_get_node = NULL, - .tree_put_node = NULL, - .tree_alloc_node = NULL, + .tree_get_node = tree_get_node, + .tree_put_node = tree_put_node, + .tree_alloc_node = tree_alloc_node, - .node_get_nr_entries = NULL, - .node_set_nr_entries = NULL, - .node_get_entries = NULL, - .node_get_children = NULL, + .node_get_nr_entries = node_get_nr_entries, + .node_set_nr_entries = node_set_nr_entries, + .node_get_entry = node_get_entry, + .node_set_entry = node_set_entry, + .node_get_child = node_get_child, + .node_set_child = node_set_child, - .entry_compare = NULL, + .entry_compare = entry_compare, }; void cluster_table_init(struct cluster_table *table, FILE *storage) @@ -22,20 +152,74 @@ void cluster_table_init(struct cluster_table *table, FILE *storage) table->t_storage = storage; - b_tree_init(&table->t_base, &cluster_table_ops, sizeof(struct ec3_cluster_group), sizeof(struct ec3_cluster), EC3_CLUSTERS_PER_GROUP + 1); + b_tree_init( + &table->t_base, + &cluster_table_ops, + sizeof(struct ec3_cluster_group), + sizeof(struct ec3_cluster), + EC3_CLUSTERS_PER_GROUP + 1); + + /* allocate root node */ + struct ec3_cluster_group *root + = (struct ec3_cluster_group *)b_tree_cache_alloc_node( + &table->t_base); + node_init(root); + tree_put_node(&table->t_base, 0, (b_tree_node *)root); + b_tree_cache_release_node(&table->t_base, (b_tree_node *)root); } void cluster_table_finish(struct cluster_table *table) { - } -int cluster_table_get(struct cluster_table *table, unsigned long id, struct cluster *out) +static void encode_cluster(const struct cluster *in, struct ec3_cluster *out) { - return -1; + out->c_id = b_i32_htob(in->c_id); + out->c_flags = b_i16_htob(in->c_flags); + out->c_checksum = b_i16_htob(in->c_checksum); + uint32_t bounds_lo = in->c_base & 0xFFFFFFFF; + uint32_t bounds_hi = (in->c_base >> 32) & 0xFFFF; + bounds_hi |= ((uint32_t)(in->c_len & 0xFFFF)) << 16; + + out->c_bounds0 = b_i32_htob(bounds_lo); + out->c_bounds1 = b_i32_htob(bounds_hi); +} + +static void decode_cluster(const struct ec3_cluster *in, struct cluster *out) +{ + out->c_id = b_i32_btoh(in->c_id); + out->c_flags = b_i16_btoh(in->c_flags); + out->c_checksum = b_i16_btoh(in->c_checksum); + + uint32_t bounds_lo = b_i32_btoh(in->c_bounds0); + uint32_t bounds_hi = b_i32_btoh(in->c_bounds1); + + out->c_base = (size_t)bounds_lo | ((size_t)bounds_hi & 0xFFFF) << 32; + out->c_len = ((size_t)bounds_hi >> 16) & 0xFFFF; +} + +int cluster_table_get( + struct cluster_table *table, + unsigned long id, + struct cluster *out) +{ + struct ec3_cluster entry = {0}; + entry.c_id = b_i32_htob(id); + + int err = b_tree_get(&table->t_base, (b_tree_node_entry *)&entry); + + if (err != 0) { + return err; + } + + decode_cluster(&entry, out); + return 0; } int cluster_table_put(struct cluster_table *table, const struct cluster *in) { - return -1; -} \ No newline at end of file + struct ec3_cluster entry = {0}; + encode_cluster(in, &entry); + + return b_tree_put(&table->t_base, (b_tree_node_entry *)&entry); +} diff --git a/src/create.c b/src/create.c index 9a52654..1601000 100644 --- a/src/create.c +++ b/src/create.c @@ -1,17 +1,17 @@ +#include "b-tree.h" #include "bin.h" #include "commands.h" -#include "b-tree.h" #include #include #include #include -#define INVALID_NODE_PTR 0xFFFF +#define INVALID_NODE_PTR 0xFFFF -#define ORDER 6 -#define MAX (ORDER - 1) -#define MIN (MAX / 2) +#define ORDER 6 +#define MAX (ORDER - 1) +#define MIN (MAX / 2) enum { ARG_INPATH, @@ -19,8 +19,7 @@ enum { OPT_OUTPATH_PATH, }; -struct entry -{ +struct entry { uint32_t key; uint32_t value; }; @@ -38,7 +37,7 @@ struct data_tree { static int node_init(struct node *n) { - memset(n, 0x0, sizeof * n); + memset(n, 0x0, sizeof *n); for (int i = 0; i < ORDER; i++) { n->children[i] = INVALID_NODE_PTR; @@ -56,7 +55,10 @@ static int tree_get_node(struct b_tree *p, unsigned long id, b_tree_node *n) return r == 1 ? 0 : -1; } -static int tree_put_node(struct b_tree *p, unsigned long id, const b_tree_node *n) +static int tree_put_node( + struct b_tree *p, + unsigned long id, + const b_tree_node *n) { struct data_tree *tree = (struct data_tree *)p; size_t offset = (id * sizeof(struct node)); @@ -96,19 +98,42 @@ static void node_set_nr_entries(b_tree_node *n, unsigned long val) node->nr_entries = val; } -static b_tree_node_entry *node_get_entries(b_tree_node *n) +static b_tree_node_entry *node_get_entry(b_tree_node *n, unsigned long index) { struct node *node = (struct node *)n; - return (b_tree_node_entry *)node->entries; + return (b_tree_node_entry *)&node->entries[index]; } -static uint16_t *node_get_children(b_tree_node *n) +static void node_set_entry( + b_tree_node *n, + unsigned long index, + const b_tree_node_entry *entry) { struct node *node = (struct node *)n; - return node->children; + memmove(&node->entries[index], entry, sizeof(struct entry)); } -static int entry_compare(const b_tree_node_entry *e0, const b_tree_node_entry *e1) +static unsigned long node_get_child(b_tree_node *n, unsigned long index) +{ + struct node *node = (struct node *)n; + uint16_t child = node->children[index]; + return child == INVALID_NODE_PTR ? B_TREE_INVALID_PTR : child; +} + +static void node_set_child( + b_tree_node *n, + unsigned long index, + unsigned long ptr) +{ + struct node *node = (struct node *)n; + uint16_t child + = ptr == B_TREE_INVALID_PTR ? INVALID_NODE_PTR : (uint16_t)ptr; + node->children[index] = child; +} + +static int entry_compare( + const b_tree_node_entry *e0, + const b_tree_node_entry *e1) { struct entry *a = (struct entry *)e0, *b = (struct entry *)e1; @@ -130,8 +155,10 @@ static const struct b_tree_ops ops = { .node_get_nr_entries = node_get_nr_entries, .node_set_nr_entries = node_set_nr_entries, - .node_get_entries = node_get_entries, - .node_get_children = node_get_children, + .node_get_entry = node_get_entry, + .node_set_entry = node_set_entry, + .node_get_child = node_get_child, + .node_set_child = node_set_child, .entry_compare = entry_compare, }; @@ -161,10 +188,13 @@ int node_print(struct b_tree *tree, struct node *n, int depth) continue; } - err = tree_get_node(tree, n->children[index], (b_tree_node *)&child); + err = tree_get_node( + tree, + n->children[index], + (b_tree_node *)&child); if (err != 0) { printf("ERR: failed to read node %u\n", - n->children[index]); + n->children[index]); continue; } @@ -193,10 +223,13 @@ int node_print(struct b_tree *tree, struct node *n, int depth) continue; } - err = tree_get_node(tree, n->children[index], (b_tree_node *)&child); + err = tree_get_node( + tree, + n->children[index], + (b_tree_node *)&child); if (err != 0) { printf("ERR: failed to read node %u\n", - n->children[index]); + n->children[index]); continue; } @@ -240,20 +273,24 @@ static int create( fwrite(&root, sizeof root, 1, fp); struct data_tree tree; - b_tree_init(&tree.base, &ops, sizeof(struct node), sizeof(struct entry), ORDER); + b_tree_init( + &tree.base, + &ops, + sizeof(struct node), + sizeof(struct entry), + ORDER); tree.fp = fp; - for (int i = 1; i <= 32; i++) { int key = rand() % 65535; - //int key = i; - // printf("%d: adding [%d]\n", i, key); - struct entry e = { .key = key, .value = key * 2 }; + // int key = i; + // printf("%d: adding [%d]\n", i, key); + struct entry e = {.key = key, .value = key * 2}; b_tree_put(&tree.base, (b_tree_node_entry *)&e); } tree_print(&tree.base); - + fclose(fp); return 0; diff --git a/src/write.c b/src/write.c index f552709..8945dd7 100644 --- a/src/write.c +++ b/src/write.c @@ -1,6 +1,7 @@ #include "write.h" #include "bin.h" +#include "cluster.h" #include "pipeline.h" #include @@ -19,9 +20,10 @@ struct ec3_writer { size_t w_extent_nr_clusters; size_t w_data_offset; + size_t w_next_cluster_id; FILE *w_data; - FILE *w_cluster_table; + struct cluster_table w_cluster_table; FILE *w_extent_table; FILE *w_tag_table; @@ -83,8 +85,10 @@ enum ec3_status ec3_writer_create( size_t cluster_size = cluster_sizes[param->p_cluster_size]; + FILE *cluster_table = tmpfile(); + writer->w_data = param->p_outp; - writer->w_cluster_table = tmpfile(); + cluster_table_init(&writer->w_cluster_table, cluster_table); writer->w_extent_table = tmpfile(); writer->w_tag_table = tmpfile(); @@ -190,7 +194,7 @@ void ec3_writer_finish(struct ec3_writer *w) } size_t cluster_table_offset = ftell(w->w_data); - status = copy_file(w->w_cluster_table, w->w_data); + status = copy_file(w->w_cluster_table.t_storage, w->w_data); size_t extent_table_offset = ftell(w->w_data); status = copy_file(w->w_extent_table, w->w_data); @@ -291,6 +295,16 @@ static enum ec3_status flush_tag_buffer(struct ec3_tag_writer *w) return status; } + struct cluster cluster = { + .c_id = container->w_next_cluster_id++, + .c_base = container->w_data_offset, + .c_len = nr_written, + .c_flags = w->w_flags, + .c_checksum = 0, + }; + + cluster_table_put(&container->w_cluster_table, &cluster); + container->w_data_offset += nr_written; w->w_ptr = 0; w->w_nr_clusters++;