Merge branch 'ps/object-store-midx' into ps/object-store-midx-dedup-info

* ps/object-store-midx:
  midx: remove now-unused linked list of multi-pack indices
  packfile: stop using linked MIDX list in `get_all_packs()`
  packfile: stop using linked MIDX list in `find_pack_entry()`
  packfile: refactor `get_multi_pack_index()` to work on sources
  midx: stop using linked list when closing MIDX
  packfile: refactor `prepare_packed_git_one()` to work on sources
  midx: start tracking per object database source
main
Junio C Hamano 2025-07-29 11:34:08 -07:00
commit 70b7b03f98
10 changed files with 107 additions and 124 deletions

View File

@ -1706,8 +1706,8 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
uint32_t found_mtime) uint32_t found_mtime)
{ {
int want; int want;
struct odb_source *source;
struct list_head *pos; struct list_head *pos;
struct multi_pack_index *m;


if (!exclude && local && has_loose_object_nonlocal(oid)) if (!exclude && local && has_loose_object_nonlocal(oid))
return 0; return 0;
@ -1727,9 +1727,13 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
*found_offset = 0; *found_offset = 0;
} }


for (m = get_multi_pack_index(the_repository); m; m = m->next) { odb_prepare_alternates(the_repository->objects);

for (source = the_repository->objects->sources; source; source = source->next) {
struct multi_pack_index *m = get_multi_pack_index(source);
struct pack_entry e; struct pack_entry e;
if (fill_midx_entry(the_repository, oid, &e, m)) {
if (m && fill_midx_entry(the_repository, oid, &e, m)) {
want = want_object_in_pack_one(e.p, oid, exclude, found_pack, found_offset, found_mtime); want = want_object_in_pack_one(e.p, oid, exclude, found_pack, found_offset, found_mtime);
if (want != -1) if (want != -1)
return want; return want;

View File

@ -223,9 +223,9 @@ static void mark_packs_for_deletion(struct existing_packs *existing,
static void remove_redundant_pack(const char *dir_name, const char *base_name) static void remove_redundant_pack(const char *dir_name, const char *base_name)
{ {
struct strbuf buf = STRBUF_INIT; struct strbuf buf = STRBUF_INIT;
struct multi_pack_index *m = get_local_multi_pack_index(the_repository); struct multi_pack_index *m = get_multi_pack_index(the_repository->objects->sources);
strbuf_addf(&buf, "%s.pack", base_name); strbuf_addf(&buf, "%s.pack", base_name);
if (m && midx_contains_pack(m, buf.buf)) if (m && m->local && midx_contains_pack(m, buf.buf))
clear_midx_file(the_repository); clear_midx_file(the_repository);
strbuf_insertf(&buf, 0, "%s/", dir_name); strbuf_insertf(&buf, 0, "%s/", dir_name);
unlink_pack_path(buf.buf, 1); unlink_pack_path(buf.buf, 1);
@ -1531,7 +1531,7 @@ int cmd_repack(int argc,
* midx_has_unknown_packs() will make the decision for * midx_has_unknown_packs() will make the decision for
* us. * us.
*/ */
if (!get_local_multi_pack_index(the_repository)) if (!get_multi_pack_index(the_repository->objects->sources))
midx_must_contain_cruft = 1; midx_must_contain_cruft = 1;
} }


@ -1614,9 +1614,9 @@ int cmd_repack(int argc,


string_list_sort(&names); string_list_sort(&names);


if (get_local_multi_pack_index(the_repository)) { if (get_multi_pack_index(the_repository->objects->sources)) {
struct multi_pack_index *m = struct multi_pack_index *m =
get_local_multi_pack_index(the_repository); get_multi_pack_index(the_repository->objects->sources);


ALLOC_ARRAY(midx_pack_names, ALLOC_ARRAY(midx_pack_names,
m->num_packs + m->num_packs_in_base); m->num_packs + m->num_packs_in_base);

View File

@ -916,26 +916,8 @@ cleanup:
static struct multi_pack_index *lookup_multi_pack_index(struct repository *r, static struct multi_pack_index *lookup_multi_pack_index(struct repository *r,
const char *object_dir) const char *object_dir)
{ {
struct multi_pack_index *result = NULL; struct odb_source *source = odb_find_source(r->objects, object_dir);
struct multi_pack_index *cur; return get_multi_pack_index(source);
char *obj_dir_real = real_pathdup(object_dir, 1);
struct strbuf cur_path_real = STRBUF_INIT;

/* Ensure the given object_dir is local, or a known alternate. */
odb_find_source(r->objects, obj_dir_real);

for (cur = get_multi_pack_index(r); cur; cur = cur->next) {
strbuf_realpath(&cur_path_real, cur->object_dir, 1);
if (!strcmp(obj_dir_real, cur_path_real.buf)) {
result = cur;
goto cleanup;
}
}

cleanup:
free(obj_dir_real);
strbuf_release(&cur_path_real);
return result;
} }


static int fill_packs_from_midx(struct write_midx_context *ctx, static int fill_packs_from_midx(struct write_midx_context *ctx,

36
midx.c
View File

@ -401,7 +401,6 @@ void close_midx(struct multi_pack_index *m)
if (!m) if (!m)
return; return;


close_midx(m->next);
close_midx(m->base_midx); close_midx(m->base_midx);


munmap((unsigned char *)m->data, m->data_len); munmap((unsigned char *)m->data, m->data_len);
@ -724,32 +723,20 @@ int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id)
return 0; return 0;
} }


int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, int local) int prepare_multi_pack_index_one(struct odb_source *source, int local)
{ {
struct multi_pack_index *m; struct repository *r = source->odb->repo;
struct multi_pack_index *m_search;


prepare_repo_settings(r); prepare_repo_settings(r);
if (!r->settings.core_multi_pack_index) if (!r->settings.core_multi_pack_index)
return 0; return 0;


for (m_search = r->objects->multi_pack_index; m_search; m_search = m_search->next) if (source->midx)
if (!strcmp(object_dir, m_search->object_dir))
return 1;

m = load_multi_pack_index(r, object_dir, local);

if (m) {
struct multi_pack_index *mp = r->objects->multi_pack_index;
if (mp) {
m->next = mp->next;
mp->next = m;
} else
r->objects->multi_pack_index = m;
return 1; return 1;
}


return 0; source->midx = load_multi_pack_index(r, source->path, local);

return !!source->midx;
} }


int midx_checksum_valid(struct multi_pack_index *m) int midx_checksum_valid(struct multi_pack_index *m)
@ -834,9 +821,14 @@ void clear_midx_file(struct repository *r)


get_midx_filename(r->hash_algo, &midx, r->objects->sources->path); get_midx_filename(r->hash_algo, &midx, r->objects->sources->path);


if (r->objects && r->objects->multi_pack_index) { if (r->objects) {
close_midx(r->objects->multi_pack_index); struct odb_source *source;
r->objects->multi_pack_index = NULL;
for (source = r->objects->sources; source; source = source->next) {
if (source->midx)
close_midx(source->midx);
source->midx = NULL;
}
} }


if (remove_path(midx.buf)) if (remove_path(midx.buf))

5
midx.h
View File

@ -8,6 +8,7 @@ struct pack_entry;
struct repository; struct repository;
struct bitmapped_pack; struct bitmapped_pack;
struct git_hash_algo; struct git_hash_algo;
struct odb_source;


#define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */ #define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */
#define MIDX_VERSION 1 #define MIDX_VERSION 1
@ -34,8 +35,6 @@ struct git_hash_algo;
"GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL" "GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL"


struct multi_pack_index { struct multi_pack_index {
struct multi_pack_index *next;

const unsigned char *data; const unsigned char *data;
size_t data_len; size_t data_len;


@ -123,7 +122,7 @@ int fill_midx_entry(struct repository *r, const struct object_id *oid, struct pa
int midx_contains_pack(struct multi_pack_index *m, int midx_contains_pack(struct multi_pack_index *m,
const char *idx_or_pack_name); const char *idx_or_pack_name);
int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id); int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id);
int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, int local); int prepare_multi_pack_index_one(struct odb_source *source, int local);


/* /*
* Variant of write_midx_file which writes a MIDX containing only the packs * Variant of write_midx_file which writes a MIDX containing only the packs

View File

@ -199,16 +199,20 @@ static void unique_in_pack(struct packed_git *p,


static void find_short_packed_object(struct disambiguate_state *ds) static void find_short_packed_object(struct disambiguate_state *ds)
{ {
struct multi_pack_index *m; struct odb_source *source;
struct packed_git *p; struct packed_git *p;


/* Skip, unless oids from the storage hash algorithm are wanted */ /* Skip, unless oids from the storage hash algorithm are wanted */
if (ds->bin_pfx.algo && (&hash_algos[ds->bin_pfx.algo] != ds->repo->hash_algo)) if (ds->bin_pfx.algo && (&hash_algos[ds->bin_pfx.algo] != ds->repo->hash_algo))
return; return;


for (m = get_multi_pack_index(ds->repo); m && !ds->ambiguous; odb_prepare_alternates(ds->repo->objects);
m = m->next) for (source = ds->repo->objects->sources; source && !ds->ambiguous; source = source->next) {
unique_in_midx(m, ds); struct multi_pack_index *m = get_multi_pack_index(source);
if (m)
unique_in_midx(m, ds);
}

for (p = get_packed_git(ds->repo); p && !ds->ambiguous; for (p = get_packed_git(ds->repo); p && !ds->ambiguous;
p = p->next) p = p->next)
unique_in_pack(p, ds); unique_in_pack(p, ds);
@ -793,11 +797,15 @@ static void find_abbrev_len_for_pack(struct packed_git *p,


static void find_abbrev_len_packed(struct min_abbrev_data *mad) static void find_abbrev_len_packed(struct min_abbrev_data *mad)
{ {
struct multi_pack_index *m;
struct packed_git *p; struct packed_git *p;


for (m = get_multi_pack_index(mad->repo); m; m = m->next) odb_prepare_alternates(mad->repo->objects);
find_abbrev_len_for_midx(m, mad); for (struct odb_source *source = mad->repo->objects->sources; source; source = source->next) {
struct multi_pack_index *m = get_multi_pack_index(source);
if (m)
find_abbrev_len_for_midx(m, mad);
}

for (p = get_packed_git(mad->repo); p; p = p->next) for (p = get_packed_git(mad->repo); p; p = p->next)
find_abbrev_len_for_pack(p, mad); find_abbrev_len_for_pack(p, mad);
} }

16
odb.h
View File

@ -13,6 +13,7 @@ struct oidmap;
struct oidtree; struct oidtree;
struct strbuf; struct strbuf;
struct repository; struct repository;
struct multi_pack_index;


/* /*
* Compute the exact path an alternate is at and returns it. In case of * Compute the exact path an alternate is at and returns it. In case of
@ -55,6 +56,13 @@ struct odb_source {
/* Map between object IDs for loose objects. */ /* Map between object IDs for loose objects. */
struct loose_object_map *loose_map; struct loose_object_map *loose_map;


/*
* private data
*
* should only be accessed directly by packfile.c and midx.c
*/
struct multi_pack_index *midx;

/* /*
* This is a temporary object store created by the tmp_objdir * This is a temporary object store created by the tmp_objdir
* facility. Disable ref updates since the objects in the store * facility. Disable ref updates since the objects in the store
@ -75,7 +83,6 @@ struct odb_source {
}; };


struct packed_git; struct packed_git;
struct multi_pack_index;
struct cached_object_entry; struct cached_object_entry;


/* /*
@ -116,13 +123,6 @@ struct object_database {
struct commit_graph *commit_graph; struct commit_graph *commit_graph;
unsigned commit_graph_attempted : 1; /* if loading has been attempted */ unsigned commit_graph_attempted : 1; /* if loading has been attempted */


/*
* private data
*
* should only be accessed directly by packfile.c and midx.c
*/
struct multi_pack_index *multi_pack_index;

/* /*
* private data * private data
* *

View File

@ -683,13 +683,15 @@ static int open_pack_bitmap(struct repository *r,
static int open_midx_bitmap(struct repository *r, static int open_midx_bitmap(struct repository *r,
struct bitmap_index *bitmap_git) struct bitmap_index *bitmap_git)
{ {
struct odb_source *source;
int ret = -1; int ret = -1;
struct multi_pack_index *midx;


assert(!bitmap_git->map); assert(!bitmap_git->map);


for (midx = get_multi_pack_index(r); midx; midx = midx->next) { odb_prepare_alternates(r->objects);
if (!open_midx_bitmap_1(bitmap_git, midx)) for (source = r->objects->sources; source; source = source->next) {
struct multi_pack_index *midx = get_multi_pack_index(source);
if (midx && !open_midx_bitmap_1(bitmap_git, midx))
ret = 0; ret = 0;
} }
return ret; return ret;
@ -3345,11 +3347,18 @@ static int verify_bitmap_file(const struct git_hash_algo *algop,


int verify_bitmap_files(struct repository *r) int verify_bitmap_files(struct repository *r)
{ {
struct odb_source *source;
int res = 0; int res = 0;


for (struct multi_pack_index *m = get_multi_pack_index(r); odb_prepare_alternates(r->objects);
m; m = m->next) { for (source = r->objects->sources; source; source = source->next) {
char *midx_bitmap_name = midx_bitmap_filename(m); struct multi_pack_index *m = get_multi_pack_index(source);
char *midx_bitmap_name;

if (!m)
continue;

midx_bitmap_name = midx_bitmap_filename(m);
res |= verify_bitmap_file(r->hash_algo, midx_bitmap_name); res |= verify_bitmap_file(r->hash_algo, midx_bitmap_name);
free(midx_bitmap_name); free(midx_bitmap_name);
} }

View File

@ -361,6 +361,7 @@ void close_pack(struct packed_git *p)


void close_object_store(struct object_database *o) void close_object_store(struct object_database *o)
{ {
struct odb_source *source;
struct packed_git *p; struct packed_git *p;


for (p = o->packed_git; p; p = p->next) for (p = o->packed_git; p; p = p->next)
@ -369,9 +370,10 @@ void close_object_store(struct object_database *o)
else else
close_pack(p); close_pack(p);


if (o->multi_pack_index) { for (source = o->sources; source; source = source->next) {
close_midx(o->multi_pack_index); if (source->midx)
o->multi_pack_index = NULL; close_midx(source->midx);
source->midx = NULL;
} }


close_commit_graph(o); close_commit_graph(o);
@ -933,22 +935,17 @@ static void prepare_pack(const char *full_name, size_t full_name_len,
report_garbage(PACKDIR_FILE_GARBAGE, full_name); report_garbage(PACKDIR_FILE_GARBAGE, full_name);
} }


static void prepare_packed_git_one(struct repository *r, char *objdir, int local) static void prepare_packed_git_one(struct odb_source *source, int local)
{ {
struct prepare_pack_data data;
struct string_list garbage = STRING_LIST_INIT_DUP; struct string_list garbage = STRING_LIST_INIT_DUP;
struct prepare_pack_data data = {
.m = source->midx,
.r = source->odb->repo,
.garbage = &garbage,
.local = local,
};


data.m = r->objects->multi_pack_index; for_each_file_in_pack_dir(source->path, prepare_pack, &data);

/* look for the multi-pack-index for this object directory */
while (data.m && strcmp(data.m->object_dir, objdir))
data.m = data.m->next;

data.r = r;
data.garbage = &garbage;
data.local = local;

for_each_file_in_pack_dir(objdir, prepare_pack, &data);


report_pack_garbage(data.garbage); report_pack_garbage(data.garbage);
string_list_clear(data.garbage, 0); string_list_clear(data.garbage, 0);
@ -965,14 +962,18 @@ static void prepare_packed_git(struct repository *r);
unsigned long repo_approximate_object_count(struct repository *r) unsigned long repo_approximate_object_count(struct repository *r)
{ {
if (!r->objects->approximate_object_count_valid) { if (!r->objects->approximate_object_count_valid) {
unsigned long count; struct odb_source *source;
struct multi_pack_index *m; unsigned long count = 0;
struct packed_git *p; struct packed_git *p;


prepare_packed_git(r); prepare_packed_git(r);
count = 0;
for (m = get_multi_pack_index(r); m; m = m->next) for (source = r->objects->sources; source; source = source->next) {
count += m->num_objects; struct multi_pack_index *m = get_multi_pack_index(source);
if (m)
count += m->num_objects;
}

for (p = r->objects->packed_git; p; p = p->next) { for (p = r->objects->packed_git; p; p = p->next) {
if (open_pack_index(p)) if (open_pack_index(p))
continue; continue;
@ -1037,8 +1038,8 @@ static void prepare_packed_git(struct repository *r)
odb_prepare_alternates(r->objects); odb_prepare_alternates(r->objects);
for (source = r->objects->sources; source; source = source->next) { for (source = r->objects->sources; source; source = source->next) {
int local = (source == r->objects->sources); int local = (source == r->objects->sources);
prepare_multi_pack_index_one(r, source->path, local); prepare_multi_pack_index_one(source, local);
prepare_packed_git_one(r, source->path, local); prepare_packed_git_one(source, local);
} }
rearrange_packed_git(r); rearrange_packed_git(r);


@ -1076,31 +1077,21 @@ struct packed_git *get_packed_git(struct repository *r)
return r->objects->packed_git; return r->objects->packed_git;
} }


struct multi_pack_index *get_multi_pack_index(struct repository *r) struct multi_pack_index *get_multi_pack_index(struct odb_source *source)
{ {
prepare_packed_git(r); prepare_packed_git(source->odb->repo);
return r->objects->multi_pack_index; return source->midx;
}

struct multi_pack_index *get_local_multi_pack_index(struct repository *r)
{
struct multi_pack_index *m = get_multi_pack_index(r);

/* no need to iterate; we always put the local one first (if any) */
if (m && m->local)
return m;

return NULL;
} }


struct packed_git *get_all_packs(struct repository *r) struct packed_git *get_all_packs(struct repository *r)
{ {
struct multi_pack_index *m;

prepare_packed_git(r); prepare_packed_git(r);
for (m = r->objects->multi_pack_index; m; m = m->next) {
uint32_t i; for (struct odb_source *source = r->objects->sources; source; source = source->next) {
for (i = 0; i < m->num_packs + m->num_packs_in_base; i++) struct multi_pack_index *m = source->midx;
if (!m)
continue;
for (uint32_t i = 0; i < m->num_packs + m->num_packs_in_base; i++)
prepare_midx_pack(r, m, i); prepare_midx_pack(r, m, i);
} }


@ -2083,16 +2074,15 @@ static int fill_pack_entry(const struct object_id *oid,
int find_pack_entry(struct repository *r, const struct object_id *oid, struct pack_entry *e) int find_pack_entry(struct repository *r, const struct object_id *oid, struct pack_entry *e)
{ {
struct list_head *pos; struct list_head *pos;
struct multi_pack_index *m;


prepare_packed_git(r); prepare_packed_git(r);
if (!r->objects->packed_git && !r->objects->multi_pack_index)
return 0;


for (m = r->objects->multi_pack_index; m; m = m->next) { for (struct odb_source *source = r->objects->sources; source; source = source->next)
if (fill_midx_entry(r, oid, e, m)) if (source->midx && fill_midx_entry(r, oid, e, source->midx))
return 1; return 1;
}
if (!r->objects->packed_git)
return 0;


list_for_each(pos, &r->objects->packed_git_mru) { list_for_each(pos, &r->objects->packed_git_mru) {
struct packed_git *p = list_entry(pos, struct packed_git, mru); struct packed_git *p = list_entry(pos, struct packed_git, mru);

View File

@ -147,8 +147,7 @@ void install_packed_git(struct repository *r, struct packed_git *pack);


struct packed_git *get_packed_git(struct repository *r); struct packed_git *get_packed_git(struct repository *r);
struct list_head *get_packed_git_mru(struct repository *r); struct list_head *get_packed_git_mru(struct repository *r);
struct multi_pack_index *get_multi_pack_index(struct repository *r); struct multi_pack_index *get_multi_pack_index(struct odb_source *source);
struct multi_pack_index *get_local_multi_pack_index(struct repository *r);
struct packed_git *get_all_packs(struct repository *r); struct packed_git *get_all_packs(struct repository *r);


/* /*