Skip to content

Commit

Permalink
sqsh_extract_manager: own SqshExtractor instead of retrieving it from…
Browse files Browse the repository at this point in the history
… SqshArchive
  • Loading branch information
Gottox committed Jul 22, 2023
1 parent 1dc43c6 commit e0eda1d
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 96 deletions.
10 changes: 3 additions & 7 deletions include/sqsh_archive_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,7 @@ struct SqshArchive {
* @privatesection
*/
struct SqshMapManager map_manager;
struct SqshExtractor data_compression;
struct SqshExtractManager data_extract_manager;
struct SqshExtractor metablock_compression;
struct SqshExtractManager metablock_extract_manager;
struct SqshSuperblock superblock;
struct SqshIdTable id_table;
Expand Down Expand Up @@ -266,13 +264,11 @@ int sqsh__archive_data_extract_manager(
* used for decompressing metablock contents.
*
* @param archive the SqshArchive to retrieve the SqshExtractManager from.
* @param metablock_extract_manager the SqshExtractManager to retrieve.
*
* @return 0 on success, less than 0 on error.
* @return the SqshExtractManager.
*/
int sqsh__archive_metablock_extract_manager(
struct SqshArchive *archive,
struct SqshExtractManager **metablock_extract_manager);
struct SqshExtractManager *
sqsh__archive_metablock_extract_manager(struct SqshArchive *archive);

/**
* @internal
Expand Down
6 changes: 3 additions & 3 deletions include/sqsh_extract_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ struct SqshExtractManager {
* @privatesection
*/
struct SqshRcHashMap hash_map;
const struct SqshExtractor *extractor;
struct SqshExtractor extractor;
struct SqshMapManager *map_manager;
struct SqshLru lru;
sqsh_mutex_t lock;
Expand All @@ -161,14 +161,14 @@ struct SqshExtractManager {
*
* @param[in] manager The manager to initialize.
* @param[in] archive The archive to use.
* @param[in] extractor The extractor to use.
* @param[in] block_size The block size to use.
* @param[in] size The size of the manager.
*
* @return 0 on success, a negative value on error.
*/
SQSH_NO_UNUSED int sqsh__extract_manager_init(
struct SqshExtractManager *manager, struct SqshArchive *archive,
const struct SqshExtractor *extractor, size_t size);
uint32_t block_size, size_t size);

/**
* @internal
Expand Down
108 changes: 36 additions & 72 deletions lib/archive/archive.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,30 @@ enum InitializedBitmap {
INITIALIZED_XATTR_TABLE = 1 << 2,
INITIALIZED_FRAGMENT_TABLE = 1 << 3,
INITIALIZED_DATA_COMPRESSION_MANAGER = 1 << 4,
INITIALIZED_METABLOCK_COMPRESSION_MANAGER = 1 << 5,
INITIALIZED_INODE_MAP = 1 << 6,
INITIALIZED_INODE_MAP = 1 << 5,
};

static bool
is_initialized(const struct SqshArchive *archive, enum InitializedBitmap mask) {
return archive->initialized & mask;
}

static uint64_t
get_data_segment_size(const struct SqshSuperblock *superblock) {
const uint64_t inode_table_start =
sqsh_superblock_inode_table_start(superblock);
uint64_t res;
/* BUG: This function does not return exact results. It may report values
* that are too large, as it does not take into account the size of the
* compression options. This is not a problem for the current implementation
* as this size is only used for finding upper limits for the extract
* manager. */
if (SQSH_SUB_OVERFLOW(inode_table_start, SQSH_SIZEOF_SUPERBLOCK, &res)) {
return inode_table_start;
}
return res;
}

struct SqshArchive *
sqsh_archive_new(
const void *source, const struct SqshConfig *config, int *err) {
Expand Down Expand Up @@ -119,23 +134,22 @@ sqsh__archive_init(
goto out;
}

enum SqshSuperblockCompressionId compression_id =
sqsh_superblock_compression_id(&archive->superblock);
uint32_t data_block_size = sqsh_superblock_block_size(&archive->superblock);

rv = sqsh__extractor_init(
&archive->metablock_compression, compression_id,
SQSH_METABLOCK_BLOCK_SIZE);
if (rv < 0) {
goto out;
uint64_t range;
if (SQSH_SUB_OVERFLOW(
sqsh_superblock_bytes_used(&archive->superblock),
get_data_segment_size(&archive->superblock), &range)) {
rv = -SQSH_ERROR_INTEGER_OVERFLOW;
return rv;
}
const size_t metablock_capacity = SQSH_DIVIDE_CEIL(
range, SQSH_SIZEOF_METABLOCK + SQSH_METABLOCK_BLOCK_SIZE);

rv = sqsh__extractor_init(
&archive->data_compression, compression_id, data_block_size);
rv = sqsh__extract_manager_init(
&archive->metablock_extract_manager, archive,
SQSH_METABLOCK_BLOCK_SIZE, metablock_capacity);
if (rv < 0) {
goto out;
}

out:
if (rv < 0) {
sqsh__archive_cleanup(archive);
Expand All @@ -153,57 +167,9 @@ sqsh_archive_superblock(const struct SqshArchive *archive) {
return &archive->superblock;
}

static uint64_t
get_data_segment_size(const struct SqshSuperblock *superblock) {
const uint64_t inode_table_start =
sqsh_superblock_inode_table_start(superblock);
uint64_t res;
/* BUG: This function does not return exact results. It may report values
* that are too large, as it does not take into account the size of the
* compression options. This is not a problem for the current implementation
* as this size is only used for finding upper limits for the extract
* manager. */
if (SQSH_SUB_OVERFLOW(inode_table_start, SQSH_SIZEOF_SUPERBLOCK, &res)) {
return inode_table_start;
}
return res;
}

int
sqsh__archive_metablock_extract_manager(
struct SqshArchive *archive,
struct SqshExtractManager **metablock_extract_manager) {
int rv = 0;

rv = sqsh_mutex_lock(&archive->lock);
if (rv < 0) {
goto out;
}
if (!is_initialized(archive, INITIALIZED_METABLOCK_COMPRESSION_MANAGER)) {
const struct SqshSuperblock *superblock =
sqsh_archive_superblock(archive);
uint64_t range;
if (SQSH_SUB_OVERFLOW(
sqsh_superblock_bytes_used(superblock),
get_data_segment_size(superblock), &range)) {
rv = -SQSH_ERROR_INTEGER_OVERFLOW;
return rv;
}
const size_t capacity = SQSH_DIVIDE_CEIL(
range, SQSH_SIZEOF_METABLOCK + SQSH_METABLOCK_BLOCK_SIZE);

rv = sqsh__extract_manager_init(
&archive->metablock_extract_manager, archive,
&archive->metablock_compression, capacity);
if (rv < 0) {
goto out;
}
archive->initialized |= INITIALIZED_METABLOCK_COMPRESSION_MANAGER;
}
*metablock_extract_manager = &archive->metablock_extract_manager;
out:
sqsh_mutex_unlock(&archive->lock);
return rv;
struct SqshExtractManager *
sqsh__archive_metablock_extract_manager(struct SqshArchive *archive) {
return &archive->metablock_extract_manager;
}

int
Expand All @@ -222,10 +188,12 @@ sqsh__archive_data_extract_manager(
const uint64_t range = get_data_segment_size(superblock);
const size_t capacity =
SQSH_DIVIDE_CEIL(range, sqsh_superblock_block_size(superblock));
const uint32_t datablock_blocksize =
sqsh_superblock_block_size(superblock);

rv = sqsh__extract_manager_init(
&archive->data_extract_manager, archive,
&archive->data_compression, capacity);
&archive->data_extract_manager, archive, datablock_blocksize,
capacity);
if (rv < 0) {
goto out;
}
Expand Down Expand Up @@ -389,14 +357,10 @@ sqsh__archive_cleanup(struct SqshArchive *archive) {
if (is_initialized(archive, INITIALIZED_DATA_COMPRESSION_MANAGER)) {
sqsh__extract_manager_cleanup(&archive->data_extract_manager);
}
if (is_initialized(archive, INITIALIZED_METABLOCK_COMPRESSION_MANAGER)) {
sqsh__extract_manager_cleanup(&archive->metablock_extract_manager);
}
if (is_initialized(archive, INITIALIZED_INODE_MAP)) {
sqsh__inode_map_cleanup(&archive->inode_map);
}
sqsh__extractor_cleanup(&archive->data_compression);
sqsh__extractor_cleanup(&archive->metablock_compression);
sqsh__extract_manager_cleanup(&archive->metablock_extract_manager);
sqsh__superblock_cleanup(&archive->superblock);
sqsh__map_manager_cleanup(&archive->map_manager);

Expand Down
15 changes: 12 additions & 3 deletions lib/extract/extract_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,12 @@ buffer_cleanup(void *buffer) {
SQSH_NO_UNUSED int
sqsh__extract_manager_init(
struct SqshExtractManager *manager, struct SqshArchive *archive,
const struct SqshExtractor *extractor, size_t size) {
uint32_t block_size, size_t size) {
int rv;
const struct SqshConfig *config = sqsh_archive_config(archive);
const size_t lru_size =
SQSH_CONFIG_DEFAULT(config->compression_lru_size, 128);
const struct SqshSuperblock *superblock = sqsh_archive_superblock(archive);

if (size == 0) {
return -SQSH_ERROR_SIZE_MISMATCH;
Expand All @@ -112,7 +113,14 @@ sqsh__extract_manager_init(
goto out;
}
manager->map_manager = sqsh_archive_map_manager(archive);
manager->extractor = extractor;

enum SqshSuperblockCompressionId compression_id =
sqsh_superblock_compression_id(superblock);

rv = sqsh__extractor_init(&manager->extractor, compression_id, block_size);
if (rv < 0) {
goto out;
}

out:
if (rv < 0) {
Expand All @@ -126,7 +134,7 @@ sqsh__extract_manager_uncompress(
struct SqshExtractManager *manager, const struct SqshMapReader *reader,
const struct SqshBuffer **target) {
int rv = 0;
const struct SqshExtractor *extractor = manager->extractor;
const struct SqshExtractor *extractor = &manager->extractor;

rv = sqsh_mutex_lock(&manager->lock);
if (rv < 0) {
Expand Down Expand Up @@ -179,6 +187,7 @@ sqsh__extract_manager_release(
int
sqsh__extract_manager_cleanup(struct SqshExtractManager *manager) {
sqsh__lru_cleanup(&manager->lru);
sqsh__extractor_cleanup(&manager->extractor);
sqsh__rc_hash_map_cleanup(&manager->hash_map);
sqsh_mutex_destroy(&manager->lock);

Expand Down
7 changes: 2 additions & 5 deletions lib/metablock/metablock_iterator.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,8 @@ sqsh__metablock_iterator_init(

iterator->outer_size = 0;
iterator->inner_size = 0;
rv = sqsh__archive_metablock_extract_manager(
sqsh, &iterator->compression_manager);
if (rv < 0) {
goto out;
}
iterator->compression_manager =
sqsh__archive_metablock_extract_manager(sqsh);
memset(&iterator->extract_view, 0, sizeof(iterator->extract_view));
if (rv < 0) {
goto out;
Expand Down
10 changes: 4 additions & 6 deletions test/extract/extract_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,11 @@ decompress(void) {
struct SqshArchive archive = {0};
struct SqshExtractManager manager = {0};
const struct SqshBuffer *buffer = NULL;
uint8_t payload[] = {SQSH_HEADER, ZLIB_ABCD};
uint8_t payload[8192] = {SQSH_HEADER, ZLIB_ABCD};

mk_stub(&archive, payload, sizeof(payload));

struct SqshMapManager *map_manager = sqsh_archive_map_manager(&archive);
const struct SqshExtractor *compression = &archive.data_compression;
struct SqshMapReader reader = {0};
rv = sqsh__map_reader_init(
&reader, map_manager, SQSH_SIZEOF_SUPERBLOCK, sizeof(payload));
Expand All @@ -60,7 +59,7 @@ decompress(void) {
rv = sqsh__map_reader_advance(&reader, 0, CHUNK_SIZE(ZLIB_ABCD));
assert(rv == 0);

rv = sqsh__extract_manager_init(&manager, &archive, compression, 10);
rv = sqsh__extract_manager_init(&manager, &archive, 8192, 10);
assert(rv == 0);

rv = sqsh__extract_manager_uncompress(&manager, &reader, &buffer);
Expand All @@ -82,12 +81,11 @@ decompress_and_cached(void) {
struct SqshExtractManager manager = {0};
const struct SqshBuffer *buffer = NULL;
const struct SqshBuffer *cached_buffer = NULL;
uint8_t payload[] = {SQSH_HEADER, ZLIB_ABCD};
uint8_t payload[8192] = {SQSH_HEADER, ZLIB_ABCD};

mk_stub(&archive, payload, sizeof(payload));

struct SqshMapManager *map_manager = sqsh_archive_map_manager(&archive);
const struct SqshExtractor *compression = &archive.data_compression;
struct SqshMapReader reader = {0};
rv = sqsh__map_reader_init(
&reader, map_manager, SQSH_SIZEOF_SUPERBLOCK, sizeof(payload));
Expand All @@ -96,7 +94,7 @@ decompress_and_cached(void) {
rv = sqsh__map_reader_advance(&reader, 0, CHUNK_SIZE(ZLIB_ABCD));
assert(rv == 0);

rv = sqsh__extract_manager_init(&manager, &archive, compression, 10);
rv = sqsh__extract_manager_init(&manager, &archive, 8192, 10);
assert(rv == 0);

rv = sqsh__extract_manager_uncompress(&manager, &reader, &buffer);
Expand Down

0 comments on commit e0eda1d

Please sign in to comment.