summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-06-05 18:19:42 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-06-07 02:44:10 +0200
commit82ace40392829e6361f3052941e3c60effeb8a98 (patch)
treef6be752822c83c5675df651f169ba310a35ab7cb
parent9c61e28d9b9faf6bd8b4e9b8d28ed79b441fbeb6 (diff)
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 <david.oberhollenzer@sigma-star.at>
-rw-r--r--include/sqfs/frag_table.h42
-rw-r--r--lib/sqfs/block_processor/common.c62
-rw-r--r--lib/sqfs/block_processor/internal.h11
-rw-r--r--lib/sqfs/frag_table.c75
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 <string.h>
#include <stdlib.h>
#include <assert.h>
+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 <stdlib.h>
#include <string.h>
-
-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;
-}