aboutsummaryrefslogtreecommitdiff
path: root/reftable/block.c
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2025-04-07 15:16:17 +0200
committerJunio C Hamano <gitster@pobox.com>2025-04-07 14:53:10 -0700
commitfd888311fbc95b0cbb3c9e580dc6f7277bb7bf7f (patch)
treeb9a91396cb5f926f6360f3445b42986d6b4311f8 /reftable/block.c
parentba620d296ab7bcd93fcedfe13b265f84df1ed1eb (diff)
downloadgit-fd888311fbc95b0cbb3c9e580dc6f7277bb7bf7f.tar.xz
reftable/table: move reading block into block reader
The logic to read blocks from a reftable is scattered across both the table and the block subsystems. Besides causing somewhat fuzzy responsibilities, it also means that we have to awkwardly pass around the ownership of blocks between the subsystems. Refactor the code so that we stop passing the block when initializing a reader, but instead by passing in the block source plus the offset at which we're supposed to read a block. Like this, the ownership of the block itself doesn't need to get handed over as the block reader is the one owning the block right from the start. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'reftable/block.c')
-rw-r--r--reftable/block.c87
1 files changed, 56 insertions, 31 deletions
diff --git a/reftable/block.c b/reftable/block.c
index f2567a8f0f..2517108b8e 100644
--- a/reftable/block.c
+++ b/reftable/block.c
@@ -209,31 +209,57 @@ int block_writer_finish(struct block_writer *w)
return w->next;
}
-int block_reader_init(struct block_reader *br, struct reftable_block *block,
- uint32_t header_off, uint32_t table_block_size,
- uint32_t hash_size)
+static int read_block(struct reftable_block_source *source,
+ struct reftable_block *dest, uint64_t off,
+ uint32_t sz)
{
+ size_t size = block_source_size(source);
+ block_source_return_block(dest);
+ if (off >= size)
+ return 0;
+ if (off + sz > size)
+ sz = size - off;
+ return block_source_read_block(source, dest, off, sz);
+}
+
+int block_reader_init(struct block_reader *br,
+ struct reftable_block_source *source,
+ uint32_t offset, uint32_t header_size,
+ uint32_t table_block_size, uint32_t hash_size)
+{
+ uint32_t guess_block_size = table_block_size ?
+ table_block_size : DEFAULT_BLOCK_SIZE;
uint32_t full_block_size = table_block_size;
- uint8_t typ = block->data[header_off];
- uint32_t sz = reftable_get_be24(block->data + header_off + 1);
uint16_t restart_count;
uint32_t restart_off;
+ uint32_t block_size;
+ uint8_t block_type;
int err;
- block_source_return_block(&br->block);
+ err = read_block(source, &br->block, offset, guess_block_size);
+ if (err < 0)
+ goto done;
- if (!reftable_is_block_type(typ)) {
- err = REFTABLE_FORMAT_ERROR;
+ block_type = br->block.data[header_size];
+ if (!reftable_is_block_type(block_type)) {
+ err = REFTABLE_FORMAT_ERROR;
goto done;
}
- if (typ == BLOCK_TYPE_LOG) {
- uint32_t block_header_skip = 4 + header_off;
- uLong dst_len = sz - block_header_skip;
- uLong src_len = block->len - block_header_skip;
+ block_size = reftable_get_be24(br->block.data + header_size + 1);
+ if (block_size > guess_block_size) {
+ err = read_block(source, &br->block, offset, block_size);
+ if (err < 0)
+ goto done;
+ }
+
+ if (block_type == BLOCK_TYPE_LOG) {
+ uint32_t block_header_skip = 4 + header_size;
+ uLong dst_len = block_size - block_header_skip;
+ uLong src_len = br->block.len - block_header_skip;
/* Log blocks specify the *uncompressed* size in their header. */
- REFTABLE_ALLOC_GROW_OR_NULL(br->uncompressed_data, sz,
+ REFTABLE_ALLOC_GROW_OR_NULL(br->uncompressed_data, block_size,
br->uncompressed_cap);
if (!br->uncompressed_data) {
err = REFTABLE_OUT_OF_MEMORY_ERROR;
@@ -241,7 +267,7 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
}
/* Copy over the block header verbatim. It's not compressed. */
- memcpy(br->uncompressed_data, block->data, block_header_skip);
+ memcpy(br->uncompressed_data, br->block.data, block_header_skip);
if (!br->zstream) {
REFTABLE_CALLOC_ARRAY(br->zstream, 1);
@@ -259,7 +285,7 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
goto done;
}
- br->zstream->next_in = block->data + block_header_skip;
+ br->zstream->next_in = br->block.data + block_header_skip;
br->zstream->avail_in = src_len;
br->zstream->next_out = br->uncompressed_data + block_header_skip;
br->zstream->avail_out = dst_len;
@@ -278,43 +304,41 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
}
err = 0;
- if (br->zstream->total_out + block_header_skip != sz) {
+ if (br->zstream->total_out + block_header_skip != block_size) {
err = REFTABLE_FORMAT_ERROR;
goto done;
}
/* We're done with the input data. */
- block_source_return_block(block);
- block->data = br->uncompressed_data;
- block->len = sz;
+ block_source_return_block(&br->block);
+ br->block.data = br->uncompressed_data;
+ br->block.len = block_size;
full_block_size = src_len + block_header_skip - br->zstream->avail_in;
} else if (full_block_size == 0) {
- full_block_size = sz;
- } else if (sz < full_block_size && sz < block->len &&
- block->data[sz] != 0) {
+ full_block_size = block_size;
+ } else if (block_size < full_block_size && block_size < br->block.len &&
+ br->block.data[block_size] != 0) {
/* If the block is smaller than the full block size, it is
padded (data followed by '\0') or the next block is
unaligned. */
- full_block_size = sz;
+ full_block_size = block_size;
}
- restart_count = reftable_get_be16(block->data + sz - 2);
- restart_off = sz - 2 - 3 * restart_count;
-
- /* transfer ownership. */
- br->block = *block;
- block->data = NULL;
- block->len = 0;
+ restart_count = reftable_get_be16(br->block.data + block_size - 2);
+ restart_off = block_size - 2 - 3 * restart_count;
+ br->block_type = block_type;
br->hash_size = hash_size;
br->restart_off = restart_off;
br->full_block_size = full_block_size;
- br->header_off = header_off;
+ br->header_off = header_size;
br->restart_count = restart_count;
err = 0;
done:
+ if (err < 0)
+ block_reader_release(br);
return err;
}
@@ -324,6 +348,7 @@ void block_reader_release(struct block_reader *br)
reftable_free(br->zstream);
reftable_free(br->uncompressed_data);
block_source_return_block(&br->block);
+ memset(br, 0, sizeof(*br));
}
uint8_t block_reader_type(const struct block_reader *r)