From 82ace40392829e6361f3052941e3c60effeb8a98 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Fri, 5 Jun 2020 18:19:42 +0200 Subject: Move the fragment deduplication hash table back into the block processor Fragment deduplication really doesn't belong into the public API of the fragment table. Signed-off-by: David Oberhollenzer --- include/sqfs/frag_table.h | 42 --------------------- lib/sqfs/block_processor/common.c | 62 ++++++++++++++++++++++++------ lib/sqfs/block_processor/internal.h | 11 ++++++ lib/sqfs/frag_table.c | 75 ------------------------------------- 4 files changed, 62 insertions(+), 128 deletions(-) diff --git a/include/sqfs/frag_table.h b/include/sqfs/frag_table.h index fc2c8a4..bcdee20 100644 --- a/include/sqfs/frag_table.h +++ b/include/sqfs/frag_table.h @@ -146,48 +146,6 @@ SQFS_API int sqfs_frag_table_set(sqfs_frag_table_t *tbl, sqfs_u32 index, */ SQFS_API size_t sqfs_frag_table_get_size(sqfs_frag_table_t *tbl); -/** - * @brief Remember a specific tail end chunk within a fragment block. - * - * @memberof sqfs_frag_table_t - * - * This is a convenience function that memorizes a specific tail end packed - * into a fragment block, primarily for looking it up later by hash and size - * using @ref sqfs_frag_table_find_tail_end. - * - * @param tbl A pointer to the fragmen table object. - * @param index An index into the fragment table that identifies the - * fragment block. - * @param offset A byte offset into the actual fragment block itself. - * @param size The size of the tail en inside the fragment block. - * @param hash An arbitrary 32 bit data hash to memorize. - * - * @return Zero on success, an @ref SQFS_ERROR on faiure. - */ -SQFS_API int sqfs_frag_table_add_tail_end(sqfs_frag_table_t *tbl, - sqfs_u32 index, sqfs_u32 offset, - sqfs_u32 size, sqfs_u32 hash); - -/** - * @brief RFetch a fragment block index and offset by hash and size - * - * @memberof sqfs_frag_table_t - * - * This is a convenience function that can find data chunks previously - * memorized using @ref sqfs_frag_table_add_tail_end. - * - * @param tbl A pointer to the fragmen table object. - * @param hash An arbitrary 32 bit data hash that describes the chunk. - * @param size The size of the chunk to look for. - * @param index Returns an index into the fragment table on success. - * @param offset Returns a byte offset into the fragment block on success. - * - * @return Zero on success, non-zero if the chunk could not be found. - */ -SQFS_API int sqfs_frag_table_find_tail_end(sqfs_frag_table_t *tbl, - sqfs_u32 hash, sqfs_u32 size, - sqfs_u32 *index, sqfs_u32 *offset); - #ifdef __cplusplus } #endif diff --git a/lib/sqfs/block_processor/common.c b/lib/sqfs/block_processor/common.c index 11cbd51..25a15c2 100644 --- a/lib/sqfs/block_processor/common.c +++ b/lib/sqfs/block_processor/common.c @@ -180,6 +180,8 @@ static int process_completed_fragment(sqfs_block_processor_t *proc, sqfs_block_t *frag, sqfs_block_t **blk_out) { + chunk_info_t *chunk, search; + struct hash_entry *entry; sqfs_u32 index, offset; size_t size; int err; @@ -197,15 +199,18 @@ static int process_completed_fragment(sqfs_block_processor_t *proc, proc->stats.total_frag_count += 1; - if (!(frag->flags & SQFS_BLK_DONT_DEDUPLICATE) && - proc->frag_tbl != NULL) { - err = sqfs_frag_table_find_tail_end(proc->frag_tbl, - frag->checksum, frag->size, - &index, &offset); - if (err == 0) { + if (!(frag->flags & SQFS_BLK_DONT_DEDUPLICATE)) { + search.hash = frag->checksum; + search.size = frag->size; + + entry = hash_table_search_pre_hashed(proc->frag_ht, + search.hash, &search); + if (entry != NULL) { if (frag->inode != NULL) { + chunk = entry->data; sqfs_inode_set_frag_location(*(frag->inode), - index, offset); + chunk->index, + chunk->offset); } release_old_block(proc, frag); return 0; @@ -248,11 +253,21 @@ static int process_completed_fragment(sqfs_block_processor_t *proc, } if (proc->frag_tbl != NULL) { - err = sqfs_frag_table_add_tail_end(proc->frag_tbl, - index, offset, - frag->size, frag->checksum); - if (err) + chunk = calloc(1, sizeof(*chunk)); + if (chunk == NULL) goto fail_outblk; + + chunk->index = index; + chunk->offset = offset; + chunk->size = frag->size; + chunk->hash = frag->checksum; + + entry = hash_table_insert_pre_hashed(proc->frag_ht, chunk->hash, + chunk, chunk); + if (entry == NULL) { + free(chunk); + goto fail_outblk; + } } if (frag->inode != NULL) @@ -270,6 +285,24 @@ fail_outblk: return err; } +static uint32_t chunk_info_hash(const void *key) +{ + const chunk_info_t *chunk = key; + return chunk->hash; +} + +static bool chunk_info_equals(const void *a, const void *b) +{ + const chunk_info_t *a_ = a, *b_ = b; + return a_->size == b_->size && + a_->hash == b_->hash; +} + +static void ht_delete_function(struct hash_entry *entry) +{ + free(entry->data); +} + void block_processor_cleanup(sqfs_block_processor_t *base) { sqfs_block_t *it; @@ -284,6 +317,8 @@ void block_processor_cleanup(sqfs_block_processor_t *base) base->free_list = it->next; free(it); } + + hash_table_destroy(base->frag_ht, ht_delete_function); } int block_processor_init(sqfs_block_processor_t *base, size_t max_block_size, @@ -298,5 +333,10 @@ int block_processor_init(sqfs_block_processor_t *base, size_t max_block_size, base->frag_tbl = tbl; base->wr = wr; base->stats.size = sizeof(base->stats); + + base->frag_ht = hash_table_create(chunk_info_hash, chunk_info_equals); + if (base->frag_ht == NULL) + return -1; + return 0; } diff --git a/lib/sqfs/block_processor/internal.h b/lib/sqfs/block_processor/internal.h index d50a452..0c4f2b3 100644 --- a/lib/sqfs/block_processor/internal.h +++ b/lib/sqfs/block_processor/internal.h @@ -18,12 +18,22 @@ #include "sqfs/error.h" #include "sqfs/block.h" #include "sqfs/io.h" + +#include "hash_table.h" #include "util.h" #include #include #include +typedef struct chunk_info_t { + struct chunk_info_t *next; + sqfs_u32 index; + sqfs_u32 offset; + sqfs_u32 size; + sqfs_u32 hash; +} chunk_info_t; + enum { BLK_FLAG_MANUAL_SUBMISSION = 0x10000000, BLK_FLAG_INTERNAL = 0x10000000, @@ -69,6 +79,7 @@ struct sqfs_block_processor_t { sqfs_u32 blk_index; void *user; + struct hash_table *frag_ht; sqfs_block_t *free_list; size_t max_block_size; diff --git a/lib/sqfs/frag_table.c b/lib/sqfs/frag_table.c index 366cb85..f0b01da 100644 --- a/lib/sqfs/frag_table.c +++ b/lib/sqfs/frag_table.c @@ -14,54 +14,21 @@ #include "sqfs/block.h" #include "compat.h" -#include "hash_table.h" - #include #include - -typedef struct chunk_info_t { - struct chunk_info_t *next; - sqfs_u32 index; - sqfs_u32 offset; - sqfs_u32 size; - sqfs_u32 hash; -} chunk_info_t; - - struct sqfs_frag_table_t { sqfs_object_t base; size_t capacity; size_t used; sqfs_fragment_t *table; - - struct hash_table *ht; }; -static uint32_t chunk_info_hash(const void *key) -{ - const chunk_info_t *chunk = key; - return chunk->hash; -} - -static bool chunk_info_equals(const void *a, const void *b) -{ - const chunk_info_t *a_ = a, *b_ = b; - return a_->size == b_->size && - a_->hash == b_->hash; -} - -static void delete_function(struct hash_entry *entry) -{ - free(entry->data); -} - static void frag_table_destroy(sqfs_object_t *obj) { sqfs_frag_table_t *tbl = (sqfs_frag_table_t *)obj; - hash_table_destroy(tbl->ht, delete_function); free(tbl->table); free(tbl); } @@ -76,8 +43,6 @@ static sqfs_object_t *frag_table_copy(const sqfs_object_t *obj) return NULL; memcpy(copy, tbl, sizeof(*tbl)); - - copy->ht = hash_table_clone(tbl->ht); return (sqfs_object_t *)copy; } @@ -92,8 +57,6 @@ sqfs_frag_table_t *sqfs_frag_table_create(sqfs_u32 flags) if (tbl == NULL) return NULL; - tbl->ht = hash_table_create(chunk_info_hash, chunk_info_equals); - ((sqfs_object_t *)tbl)->copy = frag_table_copy; ((sqfs_object_t *)tbl)->destroy = frag_table_destroy; return tbl; @@ -249,41 +212,3 @@ size_t sqfs_frag_table_get_size(sqfs_frag_table_t *tbl) { return tbl->used; } - -int sqfs_frag_table_add_tail_end(sqfs_frag_table_t *tbl, - sqfs_u32 index, sqfs_u32 offset, - sqfs_u32 size, sqfs_u32 hash) -{ - chunk_info_t *new = calloc(1, sizeof(*new)); - if (new == NULL) - return SQFS_ERROR_ALLOC; - - new->index = index; - new->offset = offset; - new->size = size; - new->hash = hash; - - hash_table_insert_pre_hashed(tbl->ht, new->hash, new, new); - - return 0; -} - -int sqfs_frag_table_find_tail_end(sqfs_frag_table_t *tbl, - sqfs_u32 hash, sqfs_u32 size, - sqfs_u32 *index, sqfs_u32 *offset) -{ - struct hash_entry *entry; - chunk_info_t *chunk, search; - - search.hash = hash; - search.size = size; - - entry = hash_table_search_pre_hashed(tbl->ht, hash, &search); - if (!entry) - return SQFS_ERROR_NO_ENTRY; - - chunk = entry->data; - *index = chunk->index; - *offset = chunk->offset; - return 0; -} -- cgit v1.2.3