reftable/writer: refactorings for `writer_flush_nonempty_block()`

Large parts of the reftable library do not conform to Git's typical code style. Refactor `writer_flush_nonempty_block()` such that it conforms better to it and add some documentation that explains some of its more intricate behaviour. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Apr 8, 2024 at 14:24 UTC 7e892fec47645ce0b791da468fb4df6c9c6d9f37
1 file changed +44 -28
reftable/writer.c
+44 -28
@@ -659,58 +659,74 @@ static void writer_clear_index(struct reftable_writer *w)
659 w->index_cap = 0;
660 }
661
662 -static const int debug = 0;
663 -
662 static int writer_flush_nonempty_block(struct reftable_writer *w)
663 {
664 + struct reftable_index_record index_record = {
665 + .last_key = STRBUF_INIT,
666 + };
667 uint8_t typ = block_writer_type(w->block_writer);
667 - struct reftable_block_stats *bstats =
668 - writer_reftable_block_stats(w, typ);
669 - uint64_t block_typ_off = (bstats->blocks == 0) ? w->next : 0;
670 - int raw_bytes = block_writer_finish(w->block_writer);
671 - int padding = 0;
672 - int err = 0;
673 - struct reftable_index_record ir = { .last_key = STRBUF_INIT };
668 + struct reftable_block_stats *bstats;
669 + int raw_bytes, padding = 0, err;
670 + uint64_t block_typ_off;
671 +
672 + /*
673 + * Finish the current block. This will cause the block writer to emit
674 + * restart points and potentially compress records in case we are
675 + * writing a log block.
676 + *
677 + * Note that this is still happening in memory.
678 + */
679 + raw_bytes = block_writer_finish(w->block_writer);
680 if (raw_bytes < 0)
681 return raw_bytes;
682
677 - if (!w->opts.unpadded && typ != BLOCK_TYPE_LOG) {
683 + /*
684 + * By default, all records except for log records are padded to the
685 + * block size.
686 + */
687 + if (!w->opts.unpadded && typ != BLOCK_TYPE_LOG)
688 padding = w->opts.block_size - raw_bytes;
679 - }
689
681 - if (block_typ_off > 0) {
690 + bstats = writer_reftable_block_stats(w, typ);
691 + block_typ_off = (bstats->blocks == 0) ? w->next : 0;
692 + if (block_typ_off > 0)
693 bstats->offset = block_typ_off;
683 - }
684 -
694 bstats->entries += w->block_writer->entries;
695 bstats->restarts += w->block_writer->restart_len;
696 bstats->blocks++;
697 w->stats.blocks++;
698
690 - if (debug) {
691 - fprintf(stderr, "block %c off %" PRIu64 " sz %d (%d)\n", typ,
692 - w->next, raw_bytes,
693 - get_be24(w->block + w->block_writer->header_off + 1));
694 - }
695 -
696 - if (w->next == 0) {
699 + /*
700 + * If this is the first block we're writing to the table then we need
701 + * to also write the reftable header.
702 + */
703 + if (!w->next)
704 writer_write_header(w, w->block);
698 - }
705
706 err = padded_write(w, w->block, raw_bytes, padding);
707 if (err < 0)
708 return err;
709
710 + /*
711 + * Add an index record for every block that we're writing. If we end up
712 + * having more than a threshold of index records we will end up writing
713 + * an index section in `writer_finish_section()`. Each index record
714 + * contains the last record key of the block it is indexing as well as
715 + * the offset of that block.
716 + *
717 + * Note that this also applies when flushing index blocks, in which
718 + * case we will end up with a multi-level index.
719 + */
720 REFTABLE_ALLOC_GROW(w->index, w->index_len + 1, w->index_cap);
705 -
706 - ir.offset = w->next;
707 - strbuf_reset(&ir.last_key);
708 - strbuf_addbuf(&ir.last_key, &w->block_writer->last_key);
709 - w->index[w->index_len] = ir;
710 -
721 + index_record.offset = w->next;
722 + strbuf_reset(&index_record.last_key);
723 + strbuf_addbuf(&index_record.last_key, &w->block_writer->last_key);
724 + w->index[w->index_len] = index_record;
725 w->index_len++;
726 +
727 w->next += padding + raw_bytes;
728 w->block_writer = NULL;
729 +
730 return 0;
731 }
732