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>
This commit is contained in:
Patrick Steinhardt
2024-04-08 14:24:20 +02:00
committed by Junio C Hamano
parent d0dd119f72
commit 7e892fec47

View File

@ -659,58 +659,74 @@ static void writer_clear_index(struct reftable_writer *w)
w->index_cap = 0; w->index_cap = 0;
} }
static const int debug = 0;
static int writer_flush_nonempty_block(struct reftable_writer *w) static int writer_flush_nonempty_block(struct reftable_writer *w)
{ {
struct reftable_index_record index_record = {
.last_key = STRBUF_INIT,
};
uint8_t typ = block_writer_type(w->block_writer); uint8_t typ = block_writer_type(w->block_writer);
struct reftable_block_stats *bstats = struct reftable_block_stats *bstats;
writer_reftable_block_stats(w, typ); int raw_bytes, padding = 0, err;
uint64_t block_typ_off = (bstats->blocks == 0) ? w->next : 0; uint64_t block_typ_off;
int raw_bytes = block_writer_finish(w->block_writer);
int padding = 0; /*
int err = 0; * Finish the current block. This will cause the block writer to emit
struct reftable_index_record ir = { .last_key = STRBUF_INIT }; * restart points and potentially compress records in case we are
* writing a log block.
*
* Note that this is still happening in memory.
*/
raw_bytes = block_writer_finish(w->block_writer);
if (raw_bytes < 0) if (raw_bytes < 0)
return raw_bytes; return raw_bytes;
if (!w->opts.unpadded && typ != BLOCK_TYPE_LOG) { /*
* By default, all records except for log records are padded to the
* block size.
*/
if (!w->opts.unpadded && typ != BLOCK_TYPE_LOG)
padding = w->opts.block_size - raw_bytes; padding = w->opts.block_size - raw_bytes;
}
if (block_typ_off > 0) { bstats = writer_reftable_block_stats(w, typ);
block_typ_off = (bstats->blocks == 0) ? w->next : 0;
if (block_typ_off > 0)
bstats->offset = block_typ_off; bstats->offset = block_typ_off;
}
bstats->entries += w->block_writer->entries; bstats->entries += w->block_writer->entries;
bstats->restarts += w->block_writer->restart_len; bstats->restarts += w->block_writer->restart_len;
bstats->blocks++; bstats->blocks++;
w->stats.blocks++; w->stats.blocks++;
if (debug) { /*
fprintf(stderr, "block %c off %" PRIu64 " sz %d (%d)\n", typ, * If this is the first block we're writing to the table then we need
w->next, raw_bytes, * to also write the reftable header.
get_be24(w->block + w->block_writer->header_off + 1)); */
} if (!w->next)
if (w->next == 0) {
writer_write_header(w, w->block); writer_write_header(w, w->block);
}
err = padded_write(w, w->block, raw_bytes, padding); err = padded_write(w, w->block, raw_bytes, padding);
if (err < 0) if (err < 0)
return err; return err;
/*
* Add an index record for every block that we're writing. If we end up
* having more than a threshold of index records we will end up writing
* an index section in `writer_finish_section()`. Each index record
* contains the last record key of the block it is indexing as well as
* the offset of that block.
*
* Note that this also applies when flushing index blocks, in which
* case we will end up with a multi-level index.
*/
REFTABLE_ALLOC_GROW(w->index, w->index_len + 1, w->index_cap); REFTABLE_ALLOC_GROW(w->index, w->index_len + 1, w->index_cap);
index_record.offset = w->next;
ir.offset = w->next; strbuf_reset(&index_record.last_key);
strbuf_reset(&ir.last_key); strbuf_addbuf(&index_record.last_key, &w->block_writer->last_key);
strbuf_addbuf(&ir.last_key, &w->block_writer->last_key); w->index[w->index_len] = index_record;
w->index[w->index_len] = ir;
w->index_len++; w->index_len++;
w->next += padding + raw_bytes; w->next += padding + raw_bytes;
w->block_writer = NULL; w->block_writer = NULL;
return 0; return 0;
} }