reftable/block: store block pointer in the block iterator

The block iterator requires access to a bunch of data from the underlying `reftable_block` that it is iterating over. This data is stored by copying over relevant data into a separate set of variables. This has multiple downsides: - We require more storage space than necessary. This is more of a theoretical issue as we shouldn't ever have many blocks. - We have to perform more bookkeeping, and the variable names are inconsistent across the two data structures. This can lead to some confusion. - The lifetime of the block iterator is tied to the block anyway, but we hide that a bit by only storing pointers pointing into the block. There isn't really any good reason why we rip out parts of the block instead of storing a pointer to the block itself. Refactor the code to do so. Despite being simpler, it also allows us to decouple the lifetime of the block iterator from seeking in a subsequent commit. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Apr 7, 2025 at 15:16 UTC 156d79cef0de565408e41f840bbda87114367977
2 files changed +9 -17
reftable/block.c
+8 -14
@@ -381,13 +381,11 @@ static uint32_t block_restart_offset(const struct reftable_block *b, size_t idx)
381 return reftable_get_be24(b->block_data.data + b->restart_off + 3 * idx);
382 }
383
384 -void block_iter_seek_start(struct block_iter *it, const struct reftable_block *b)
384 +void block_iter_seek_start(struct block_iter *it, const struct reftable_block *block)
385 {
386 - it->block = b->block_data.data;
387 - it->block_len = b->restart_off;
388 - it->hash_size = b->hash_size;
386 + it->block = block;
387 reftable_buf_reset(&it->last_key);
390 - it->next_off = b->header_off + 4;
388 + it->next_off = block->header_off + 4;
389 }
390
391 struct restart_needle_less_args {
@@ -435,14 +433,14 @@ static int restart_needle_less(size_t idx, void *_args)
433 int block_iter_next(struct block_iter *it, struct reftable_record *rec)
434 {
435 struct string_view in = {
438 - .buf = (unsigned char *) it->block + it->next_off,
439 - .len = it->block_len - it->next_off,
436 + .buf = (unsigned char *) it->block->block_data.data + it->next_off,
437 + .len = it->block->restart_off - it->next_off,
438 };
439 struct string_view start = in;
440 uint8_t extra = 0;
441 int n = 0;
442
445 - if (it->next_off >= it->block_len)
443 + if (it->next_off >= it->block->restart_off)
444 return 1;
445
446 n = reftable_decode_key(&it->last_key, &extra, in);
@@ -452,7 +450,7 @@ int block_iter_next(struct block_iter *it, struct reftable_record *rec)
450 return REFTABLE_FORMAT_ERROR;
451
452 string_view_consume(&in, n);
455 - n = reftable_record_decode(rec, it->last_key, extra, in, it->hash_size,
453 + n = reftable_record_decode(rec, it->last_key, extra, in, it->block->hash_size,
454 &it->scratch);
455 if (n < 0)
456 return -1;
@@ -467,8 +465,6 @@ void block_iter_reset(struct block_iter *it)
465 reftable_buf_reset(&it->last_key);
466 it->next_off = 0;
467 it->block = NULL;
470 - it->block_len = 0;
471 - it->hash_size = 0;
468 }
469
470 void block_iter_close(struct block_iter *it)
@@ -528,9 +524,7 @@ int block_iter_seek_key(struct block_iter *it, const struct reftable_block *bloc
524 it->next_off = block_restart_offset(block, i - 1);
525 else
526 it->next_off = block->header_off + 4;
531 - it->block = block->block_data.data;
532 - it->block_len = block->restart_off;
533 - it->hash_size = block->hash_size;
527 + it->block = block;
528
529 err = reftable_record_init(&rec, reftable_block_type(block));
530 if (err < 0)
reftable/block.h
+1 -3
@@ -67,9 +67,7 @@ void block_writer_release(struct block_writer *bw);
67 struct block_iter {
68 /* offset within the block of the next entry to read. */
69 uint32_t next_off;
70 - const unsigned char *block;
71 - size_t block_len;
72 - uint32_t hash_size;
70 + const struct reftable_block *block;
71
72 /* key for last entry we read. */
73 struct reftable_buf last_key;