pack-bitmap.c: open and store incremental bitmap layers

Prepare the pack-bitmap machinery to work with incremental MIDXs by adding a new "base" field to keep track of the bitmap index associated with the previous MIDX layer. The changes in this commit are mostly boilerplate to open the correct bitmap(s), add them to the chain of bitmap layers along the "base" pointer, ensure that the correct packs and their reverse indexes are loaded across MIDX layers, etc. While we're at it, keep track of a base_nr field to indicate how many bitmap layers (including the current bitmap) exist. This will be used in a future commit to allocate an array of 'struct ewah_bitmap' pointers to collect all of the respective type bitmaps among all layers to initialize a multi-EWAH iterator. Subsequent commits will teach the functions within the pack-bitmap machinery how to interact with these new fields. Signed-off-by: Taylor Blau <me@ttaylorr.com> Acked-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Taylor Blau committed Mar 20, 2025 at 13:56 UTC f31a17cea5f6f66436e20f5dcefb6a0464238864
1 file changed +48 -14
pack-bitmap.c
+48 -14
@@ -54,6 +54,16 @@ struct bitmap_index {
54 struct packed_git *pack;
55 struct multi_pack_index *midx;
56
57 + /*
58 + * If using a multi-pack index chain, 'base' points to the
59 + * bitmap index corresponding to this bitmap's midx->base_midx.
60 + *
61 + * base_nr indicates how many layers precede this one, and is
62 + * zero when base is NULL.
63 + */
64 + struct bitmap_index *base;
65 + uint32_t base_nr;
66 +
67 /* mmapped buffer of the whole bitmap index */
68 unsigned char *map;
69 size_t map_size; /* size of the mmaped buffer */
@@ -386,8 +396,15 @@ static int load_bitmap_entries_v1(struct bitmap_index *index)
396 char *midx_bitmap_filename(struct multi_pack_index *midx)
397 {
398 struct strbuf buf = STRBUF_INIT;
389 - get_midx_filename_ext(midx->repo->hash_algo, &buf, midx->object_dir,
390 - get_midx_checksum(midx), MIDX_EXT_BITMAP);
399 + if (midx->has_chain)
400 + get_split_midx_filename_ext(midx->repo->hash_algo, &buf,
401 + midx->object_dir,
402 + get_midx_checksum(midx),
403 + MIDX_EXT_BITMAP);
404 + else
405 + get_midx_filename_ext(midx->repo->hash_algo, &buf,
406 + midx->object_dir, get_midx_checksum(midx),
407 + MIDX_EXT_BITMAP);
408
409 return strbuf_detach(&buf, NULL);
410 }
@@ -454,16 +471,21 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git,
471 goto cleanup;
472 }
473
457 - for (i = 0; i < bitmap_git->midx->num_packs; i++) {
458 - if (prepare_midx_pack(bitmap_repo(bitmap_git),
459 - bitmap_git->midx,
460 - i)) {
474 + for (i = 0; i < bitmap_git->midx->num_packs + bitmap_git->midx->num_packs_in_base; i++) {
475 + if (prepare_midx_pack(bitmap_repo(bitmap_git), bitmap_git->midx, i)) {
476 warning(_("could not open pack %s"),
477 bitmap_git->midx->pack_names[i]);
478 goto cleanup;
479 }
480 }
481
482 + if (midx->base_midx) {
483 + bitmap_git->base = prepare_midx_bitmap_git(midx->base_midx);
484 + bitmap_git->base_nr = bitmap_git->base->base_nr + 1;
485 + } else {
486 + bitmap_git->base_nr = 0;
487 + }
488 +
489 return 0;
490
491 cleanup:
@@ -515,6 +537,7 @@ static int open_pack_bitmap_1(struct bitmap_index *bitmap_git, struct packed_git
537 bitmap_git->map_size = xsize_t(st.st_size);
538 bitmap_git->map = xmmap(NULL, bitmap_git->map_size, PROT_READ, MAP_PRIVATE, fd, 0);
539 bitmap_git->map_pos = 0;
540 + bitmap_git->base_nr = 0;
541 close(fd);
542
543 if (load_bitmap_header(bitmap_git) < 0) {
@@ -534,8 +557,7 @@ static int open_pack_bitmap_1(struct bitmap_index *bitmap_git, struct packed_git
557 static int load_reverse_index(struct repository *r, struct bitmap_index *bitmap_git)
558 {
559 if (bitmap_is_midx(bitmap_git)) {
537 - uint32_t i;
538 - int ret;
560 + struct multi_pack_index *m;
561
562 /*
563 * The multi-pack-index's .rev file is already loaded via
@@ -544,10 +566,15 @@ static int load_reverse_index(struct repository *r, struct bitmap_index *bitmap_
566 * But we still need to open the individual pack .rev files,
567 * since we will need to make use of them in pack-objects.
568 */
547 - for (i = 0; i < bitmap_git->midx->num_packs; i++) {
548 - ret = load_pack_revindex(r, bitmap_git->midx->packs[i]);
549 - if (ret)
550 - return ret;
569 + for (m = bitmap_git->midx; m; m = m->base_midx) {
570 + uint32_t i;
571 + int ret;
572 +
573 + for (i = 0; i < m->num_packs; i++) {
574 + ret = load_pack_revindex(r, m->packs[i]);
575 + if (ret)
576 + return ret;
577 + }
578 }
579 return 0;
580 }
@@ -573,6 +600,13 @@ static int load_bitmap(struct repository *r, struct bitmap_index *bitmap_git)
600 if (!bitmap_git->table_lookup && load_bitmap_entries_v1(bitmap_git) < 0)
601 goto failed;
602
603 + if (bitmap_git->base) {
604 + if (!bitmap_is_midx(bitmap_git))
605 + BUG("non-MIDX bitmap has non-NULL base bitmap index");
606 + if (load_bitmap(r, bitmap_git->base) < 0)
607 + goto failed;
608 + }
609 +
610 return 0;
611
612 failed:
@@ -657,10 +691,9 @@ struct bitmap_index *prepare_bitmap_git(struct repository *r)
691
692 struct bitmap_index *prepare_midx_bitmap_git(struct multi_pack_index *midx)
693 {
660 - struct repository *r = midx->repo;
694 struct bitmap_index *bitmap_git = xcalloc(1, sizeof(*bitmap_git));
695
663 - if (!open_midx_bitmap_1(bitmap_git, midx) && !load_bitmap(r, bitmap_git))
696 + if (!open_midx_bitmap_1(bitmap_git, midx))
697 return bitmap_git;
698
699 free_bitmap_index(bitmap_git);
@@ -2901,6 +2934,7 @@ void free_bitmap_index(struct bitmap_index *b)
2934 close_midx_revindex(b->midx);
2935 }
2936 free_pseudo_merge_map(&b->pseudo_merges);
2937 + free_bitmap_index(b->base);
2938 free(b);
2939 }
2940