midx: start tracking per object database source

Multi-pack indices are tracked via `struct multi_pack_index`. This data structure is stored as a linked list inside `struct object_database`, which is the global database that spans across all of the object sources. This layout causes two problems: - Object databases consist of multiple object sources (e.g. one source per alternate object directory), where each multi-pack index is specific to one of those sources. Regardless of that though, the MIDX is not tracked per source, but tracked globally for the whole object database. This creates a mismatch between the on-disk layout and how things are organized in the object database subsystems and makes some parts, like figuring out whether a source has an MIDX, quite awkward. - Multi-pack indices are an implementation detail of how efficient access for packfiles work. As such, they are neither relevant in the context of loose objects, nor in a potential future where we have pluggable backends. Refactor `prepare_multi_pack_index_one()` so that it works on a specific source, which allows us to easily store a pointer to the multi-pack index inside of it. For now, this pointer exists next to the existing linked list we have in the object database. Users will be adjusted in subsequent patches to instead use the per-source pointers. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jul 15, 2025 at 13:29 UTC 4d8be89d973b69a826911385c5cf3d40d347394b
4 files changed +24 -11
midx.c
+11 -8
@@ -724,28 +724,29 @@ int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id)
724 return 0;
725 }
726
727 -int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, int local)
727 +int prepare_multi_pack_index_one(struct odb_source *source, int local)
728 {
729 + struct repository *r = source->odb->repo;
730 struct multi_pack_index *m;
730 - struct multi_pack_index *m_search;
731
732 prepare_repo_settings(r);
733 if (!r->settings.core_multi_pack_index)
734 return 0;
735
736 - for (m_search = r->objects->multi_pack_index; m_search; m_search = m_search->next)
737 - if (!strcmp(object_dir, m_search->object_dir))
738 - return 1;
739 -
740 - m = load_multi_pack_index(r, object_dir, local);
736 + if (source->midx)
737 + return 1;
738
739 + m = load_multi_pack_index(r, source->path, local);
740 if (m) {
741 struct multi_pack_index *mp = r->objects->multi_pack_index;
742 if (mp) {
743 m->next = mp->next;
744 mp->next = m;
747 - } else
745 + } else {
746 r->objects->multi_pack_index = m;
747 + }
748 + source->midx = m;
749 +
750 return 1;
751 }
752
@@ -837,6 +838,8 @@ void clear_midx_file(struct repository *r)
838 if (r->objects && r->objects->multi_pack_index) {
839 close_midx(r->objects->multi_pack_index);
840 r->objects->multi_pack_index = NULL;
841 + for (struct odb_source *source = r->objects->sources; source; source = source->next)
842 + source->midx = NULL;
843 }
844
845 if (remove_path(midx.buf))
midx.h
+2 -1
@@ -8,6 +8,7 @@ struct pack_entry;
8 struct repository;
9 struct bitmapped_pack;
10 struct git_hash_algo;
11 +struct odb_source;
12
13 #define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */
14 #define MIDX_VERSION 1
@@ -123,7 +124,7 @@ int fill_midx_entry(struct repository *r, const struct object_id *oid, struct pa
124 int midx_contains_pack(struct multi_pack_index *m,
125 const char *idx_or_pack_name);
126 int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id);
126 -int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, int local);
127 +int prepare_multi_pack_index_one(struct odb_source *source, int local);
128
129 /*
130 * Variant of write_midx_file which writes a MIDX containing only the packs
odb.h
+8 -1
@@ -13,6 +13,7 @@ struct oidmap;
13 struct oidtree;
14 struct strbuf;
15 struct repository;
16 +struct multi_pack_index;
17
18 /*
19 * Compute the exact path an alternate is at and returns it. In case of
@@ -55,6 +56,13 @@ struct odb_source {
56 /* Map between object IDs for loose objects. */
57 struct loose_object_map *loose_map;
58
59 + /*
60 + * private data
61 + *
62 + * should only be accessed directly by packfile.c and midx.c
63 + */
64 + struct multi_pack_index *midx;
65 +
66 /*
67 * This is a temporary object store created by the tmp_objdir
68 * facility. Disable ref updates since the objects in the store
@@ -75,7 +83,6 @@ struct odb_source {
83 };
84
85 struct packed_git;
78 -struct multi_pack_index;
86 struct cached_object_entry;
87
88 /*
packfile.c
+3 -1
@@ -372,6 +372,8 @@ void close_object_store(struct object_database *o)
372 if (o->multi_pack_index) {
373 close_midx(o->multi_pack_index);
374 o->multi_pack_index = NULL;
375 + for (struct odb_source *source = o->sources; source; source = source->next)
376 + source->midx = NULL;
377 }
378
379 close_commit_graph(o);
@@ -1037,7 +1039,7 @@ static void prepare_packed_git(struct repository *r)
1039 odb_prepare_alternates(r->objects);
1040 for (source = r->objects->sources; source; source = source->next) {
1041 int local = (source == r->objects->sources);
1040 - prepare_multi_pack_index_one(r, source->path, local);
1042 + prepare_multi_pack_index_one(source, local);
1043 prepare_packed_git_one(r, source->path, local);
1044 }
1045 rearrange_packed_git(r);