| 502 | } |
| 503 | |
| 504 | static int writer_finish_section(struct reftable_writer *w) |
| 505 | { |
| 506 | struct reftable_block_stats *bstats = NULL; |
| 507 | uint8_t typ = block_writer_type(w->block_writer); |
| 508 | uint64_t index_start = 0; |
| 509 | int max_level = 0; |
| 510 | size_t threshold = w->opts.unpadded ? 1 : 3; |
| 511 | int before_blocks = w->stats.idx_stats.blocks; |
| 512 | int err; |
| 513 | |
| 514 | err = writer_flush_block(w); |
| 515 | if (err < 0) |
| 516 | return err; |
| 517 | |
| 518 | /* |
| 519 | * When the section we are about to index has a lot of blocks then the |
| 520 | * index itself may span across multiple blocks, as well. This would |
| 521 | * require a linear scan over index blocks only to find the desired |
| 522 | * indexed block, which is inefficient. Instead, we write a multi-level |
| 523 | * index where index records of level N+1 will refer to index blocks of |
| 524 | * level N. This isn't constant time, either, but at least logarithmic. |
| 525 | * |
| 526 | * This loop handles writing this multi-level index. Note that we write |
| 527 | * the lowest-level index pointing to the indexed blocks first. We then |
| 528 | * continue writing additional index levels until the current level has |
| 529 | * less blocks than the threshold so that the highest level will be at |
| 530 | * the end of the index section. |
| 531 | * |
| 532 | * Readers are thus required to start reading the index section from |
| 533 | * its end, which is why we set `index_start` to the beginning of the |
| 534 | * last index section. |
| 535 | */ |
| 536 | while (w->index_len > threshold) { |
| 537 | struct reftable_index_record *idx = NULL; |
| 538 | size_t i, idx_len; |
| 539 | |
| 540 | max_level++; |
| 541 | index_start = w->next; |
| 542 | err = writer_reinit_block_writer(w, REFTABLE_BLOCK_TYPE_INDEX); |
| 543 | if (err < 0) |
| 544 | return err; |
| 545 | |
| 546 | idx = w->index; |
| 547 | idx_len = w->index_len; |
| 548 | |
| 549 | w->index = NULL; |
| 550 | w->index_len = 0; |
| 551 | w->index_cap = 0; |
| 552 | for (i = 0; i < idx_len; i++) { |
| 553 | struct reftable_record rec = { |
| 554 | .type = REFTABLE_BLOCK_TYPE_INDEX, |
| 555 | .u = { |
| 556 | .idx = idx[i], |
| 557 | }, |
| 558 | }; |
| 559 | |
| 560 | err = writer_add_record(w, &rec); |
| 561 | if (err < 0) |
no test coverage detected