summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
-}