Git fork

Merge branch 'ps/packfile-store'

Code clean-up around the in-core list of all the pack files and
object database(s).

* ps/packfile-store:
packfile: refactor `get_packed_git_mru()` to work on packfile store
packfile: refactor `get_all_packs()` to work on packfile store
packfile: refactor `get_packed_git()` to work on packfile store
packfile: move `get_multi_pack_index()` into "midx.c"
packfile: introduce function to load and add packfiles
packfile: refactor `install_packed_git()` to work on packfile store
packfile: split up responsibilities of `reprepare_packed_git()`
packfile: refactor `prepare_packed_git()` to work on packfile store
packfile: reorder functions to avoid function declaration
odb: move kept cache into `struct packfile_store`
odb: move MRU list of packfiles into `struct packfile_store`
odb: move packfile map into `struct packfile_store`
odb: move initialization bit into `struct packfile_store`
odb: move list of packfiles into `struct packfile_store`
packfile: introduce a new `struct packfile_store`

+396 -269
+1 -1
builtin/backfill.c
··· 53 53 * We likely have a new packfile. Add it to the packed list to 54 54 * avoid possible duplicate downloads of the same objects. 55 55 */ 56 - reprepare_packed_git(ctx->repo); 56 + odb_reprepare(ctx->repo->objects); 57 57 } 58 58 59 59 static int fill_missing_blobs(const char *path UNUSED,
+2 -1
builtin/cat-file.c
··· 852 852 853 853 if (bitmap && !for_each_bitmapped_object(bitmap, &opt->objects_filter, 854 854 batch_one_object_bitmapped, &payload)) { 855 + struct packfile_store *packs = the_repository->objects->packfiles; 855 856 struct packed_git *pack; 856 857 857 - for (pack = get_all_packs(the_repository); pack; pack = pack->next) { 858 + for (pack = packfile_store_get_all_packs(packs); pack; pack = pack->next) { 858 859 if (bitmap_index_contains_pack(bitmap, pack) || 859 860 open_pack_index(pack)) 860 861 continue;
+2 -1
builtin/count-objects.c
··· 122 122 count_loose, count_cruft, NULL, NULL); 123 123 124 124 if (verbose) { 125 + struct packfile_store *packs = the_repository->objects->packfiles; 125 126 struct packed_git *p; 126 127 unsigned long num_pack = 0; 127 128 off_t size_pack = 0; ··· 129 130 struct strbuf pack_buf = STRBUF_INIT; 130 131 struct strbuf garbage_buf = STRBUF_INIT; 131 132 132 - for (p = get_all_packs(the_repository); p; p = p->next) { 133 + for (p = packfile_store_get_all_packs(packs); p; p = p->next) { 133 134 if (!p->pack_local) 134 135 continue; 135 136 if (open_pack_index(p))
+6 -4
builtin/fast-import.c
··· 899 899 idx_name = keep_pack(create_index()); 900 900 901 901 /* Register the packfile with core git's machinery. */ 902 - new_p = add_packed_git(pack_data->repo, idx_name, strlen(idx_name), 1); 902 + new_p = packfile_store_load_pack(pack_data->repo->objects->packfiles, 903 + idx_name, 1); 903 904 if (!new_p) 904 905 die("core git rejected index %s", idx_name); 905 906 all_packs[pack_id] = new_p; 906 - install_packed_git(the_repository, new_p); 907 907 free(idx_name); 908 908 909 909 /* Print the boundary */ ··· 954 954 struct object_id *oidout, 955 955 uintmax_t mark) 956 956 { 957 + struct packfile_store *packs = the_repository->objects->packfiles; 957 958 void *out, *delta; 958 959 struct object_entry *e; 959 960 unsigned char hdr[96]; ··· 977 978 if (e->idx.offset) { 978 979 duplicate_count_by_type[type]++; 979 980 return 1; 980 - } else if (find_oid_pack(&oid, get_all_packs(the_repository))) { 981 + } else if (find_oid_pack(&oid, packfile_store_get_all_packs(packs))) { 981 982 e->type = type; 982 983 e->pack_id = MAX_PACK_ID; 983 984 e->idx.offset = 1; /* just not zero! */ ··· 1094 1095 1095 1096 static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark) 1096 1097 { 1098 + struct packfile_store *packs = the_repository->objects->packfiles; 1097 1099 size_t in_sz = 64 * 1024, out_sz = 64 * 1024; 1098 1100 unsigned char *in_buf = xmalloc(in_sz); 1099 1101 unsigned char *out_buf = xmalloc(out_sz); ··· 1177 1179 duplicate_count_by_type[OBJ_BLOB]++; 1178 1180 truncate_pack(&checkpoint); 1179 1181 1180 - } else if (find_oid_pack(&oid, get_all_packs(the_repository))) { 1182 + } else if (find_oid_pack(&oid, packfile_store_get_all_packs(packs))) { 1181 1183 e->type = OBJ_BLOB; 1182 1184 e->pack_id = MAX_PACK_ID; 1183 1185 e->idx.offset = 1; /* just not zero! */
+7 -4
builtin/fsck.c
··· 867 867 868 868 static int check_pack_rev_indexes(struct repository *r, int show_progress) 869 869 { 870 + struct packfile_store *packs = r->objects->packfiles; 870 871 struct progress *progress = NULL; 871 872 uint32_t pack_count = 0; 872 873 int res = 0; 873 874 874 875 if (show_progress) { 875 - for (struct packed_git *p = get_all_packs(r); p; p = p->next) 876 + for (struct packed_git *p = packfile_store_get_all_packs(packs); p; p = p->next) 876 877 pack_count++; 877 878 progress = start_delayed_progress(the_repository, 878 879 "Verifying reverse pack-indexes", pack_count); 879 880 pack_count = 0; 880 881 } 881 882 882 - for (struct packed_git *p = get_all_packs(r); p; p = p->next) { 883 + for (struct packed_git *p = packfile_store_get_all_packs(packs); p; p = p->next) { 883 884 int load_error = load_pack_revindex_from_disk(p); 884 885 885 886 if (load_error < 0) { ··· 999 1000 for_each_packed_object(the_repository, 1000 1001 mark_packed_for_connectivity, NULL, 0); 1001 1002 } else { 1003 + struct packfile_store *packs = the_repository->objects->packfiles; 1004 + 1002 1005 odb_prepare_alternates(the_repository->objects); 1003 1006 for (source = the_repository->objects->sources; source; source = source->next) 1004 1007 fsck_source(source); ··· 1009 1012 struct progress *progress = NULL; 1010 1013 1011 1014 if (show_progress) { 1012 - for (p = get_all_packs(the_repository); p; 1015 + for (p = packfile_store_get_all_packs(packs); p; 1013 1016 p = p->next) { 1014 1017 if (open_pack_index(p)) 1015 1018 continue; ··· 1019 1022 progress = start_progress(the_repository, 1020 1023 _("Checking objects"), total); 1021 1024 } 1022 - for (p = get_all_packs(the_repository); p; 1025 + for (p = packfile_store_get_all_packs(packs); p; 1023 1026 p = p->next) { 1024 1027 /* verify gives error messages itself */ 1025 1028 if (verify_pack(the_repository,
+8 -6
builtin/gc.c
··· 487 487 static struct packed_git *find_base_packs(struct string_list *packs, 488 488 unsigned long limit) 489 489 { 490 + struct packfile_store *packfiles = the_repository->objects->packfiles; 490 491 struct packed_git *p, *base = NULL; 491 492 492 - for (p = get_all_packs(the_repository); p; p = p->next) { 493 + for (p = packfile_store_get_all_packs(packfiles); p; p = p->next) { 493 494 if (!p->pack_local || p->is_cruft) 494 495 continue; 495 496 if (limit) { ··· 508 509 509 510 static int too_many_packs(struct gc_config *cfg) 510 511 { 512 + struct packfile_store *packs = the_repository->objects->packfiles; 511 513 struct packed_git *p; 512 514 int cnt; 513 515 514 516 if (cfg->gc_auto_pack_limit <= 0) 515 517 return 0; 516 518 517 - for (cnt = 0, p = get_all_packs(the_repository); p; p = p->next) { 519 + for (cnt = 0, p = packfile_store_get_all_packs(packs); p; p = p->next) { 518 520 if (!p->pack_local) 519 521 continue; 520 522 if (p->pack_keep) ··· 1042 1044 die(FAILED_RUN, "rerere"); 1043 1045 1044 1046 report_garbage = report_pack_garbage; 1045 - reprepare_packed_git(the_repository); 1047 + odb_reprepare(the_repository->objects); 1046 1048 if (pack_garbage.nr > 0) { 1047 1049 close_object_store(the_repository->objects); 1048 1050 clean_pack_garbage(); ··· 1423 1425 if (incremental_repack_auto_limit < 0) 1424 1426 return 1; 1425 1427 1426 - for (p = get_packed_git(the_repository); 1428 + for (p = packfile_store_get_packs(the_repository->objects->packfiles); 1427 1429 count < incremental_repack_auto_limit && p; 1428 1430 p = p->next) { 1429 1431 if (!p->multi_pack_index) ··· 1491 1493 struct packed_git *p; 1492 1494 struct repository *r = the_repository; 1493 1495 1494 - reprepare_packed_git(r); 1495 - for (p = get_all_packs(r); p; p = p->next) { 1496 + odb_reprepare(r->objects); 1497 + for (p = packfile_store_get_all_packs(r->objects->packfiles); p; p = p->next) { 1496 1498 if (p->pack_size > max_size) { 1497 1499 second_largest_size = max_size; 1498 1500 max_size = p->pack_size;
+1 -1
builtin/grep.c
··· 1214 1214 if (recurse_submodules) 1215 1215 repo_read_gitmodules(the_repository, 1); 1216 1216 if (startup_info->have_repository) 1217 - (void)get_packed_git(the_repository); 1217 + (void)packfile_store_get_packs(the_repository->objects->packfiles); 1218 1218 1219 1219 start_threads(&opt); 1220 1220 } else {
+3 -7
builtin/index-pack.c
··· 1640 1640 rename_tmp_packfile(&final_index_name, curr_index_name, &index_name, 1641 1641 hash, "idx", 1); 1642 1642 1643 - if (do_fsck_object) { 1644 - struct packed_git *p; 1645 - p = add_packed_git(the_repository, final_index_name, 1646 - strlen(final_index_name), 0); 1647 - if (p) 1648 - install_packed_git(the_repository, p); 1649 - } 1643 + if (do_fsck_object) 1644 + packfile_store_load_pack(the_repository->objects->packfiles, 1645 + final_index_name, 0); 1650 1646 1651 1647 if (!from_stdin) { 1652 1648 printf("%s\n", hash_to_hex(hash));
+21 -11
builtin/pack-objects.c
··· 1748 1748 } 1749 1749 } 1750 1750 1751 - list_for_each(pos, get_packed_git_mru(the_repository)) { 1751 + list_for_each(pos, packfile_store_get_packs_mru(the_repository->objects->packfiles)) { 1752 1752 struct packed_git *p = list_entry(pos, struct packed_git, mru); 1753 1753 want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset, found_mtime); 1754 1754 if (!exclude && want > 0) 1755 1755 list_move(&p->mru, 1756 - get_packed_git_mru(the_repository)); 1756 + packfile_store_get_packs_mru(the_repository->objects->packfiles)); 1757 1757 if (want != -1) 1758 1758 return want; 1759 1759 } ··· 3831 3831 3832 3832 static void read_packs_list_from_stdin(struct rev_info *revs) 3833 3833 { 3834 + struct packfile_store *packs = the_repository->objects->packfiles; 3834 3835 struct strbuf buf = STRBUF_INIT; 3835 3836 struct string_list include_packs = STRING_LIST_INIT_DUP; 3836 3837 struct string_list exclude_packs = STRING_LIST_INIT_DUP; ··· 3855 3856 string_list_sort(&exclude_packs); 3856 3857 string_list_remove_duplicates(&exclude_packs, 0); 3857 3858 3858 - for (p = get_all_packs(the_repository); p; p = p->next) { 3859 + for (p = packfile_store_get_all_packs(packs); p; p = p->next) { 3859 3860 const char *pack_name = pack_basename(p); 3860 3861 3861 3862 if ((item = string_list_lookup(&include_packs, pack_name))) ··· 4076 4077 4077 4078 static void enumerate_and_traverse_cruft_objects(struct string_list *fresh_packs) 4078 4079 { 4080 + struct packfile_store *packs = the_repository->objects->packfiles; 4079 4081 struct packed_git *p; 4080 4082 struct rev_info revs; 4081 4083 int ret; ··· 4105 4107 * Re-mark only the fresh packs as kept so that objects in 4106 4108 * unknown packs do not halt the reachability traversal early. 4107 4109 */ 4108 - for (p = get_all_packs(the_repository); p; p = p->next) 4110 + for (p = packfile_store_get_all_packs(packs); p; p = p->next) 4109 4111 p->pack_keep_in_core = 0; 4110 4112 mark_pack_kept_in_core(fresh_packs, 1); 4111 4113 ··· 4122 4124 4123 4125 static void read_cruft_objects(void) 4124 4126 { 4127 + struct packfile_store *packs = the_repository->objects->packfiles; 4125 4128 struct strbuf buf = STRBUF_INIT; 4126 4129 struct string_list discard_packs = STRING_LIST_INIT_DUP; 4127 4130 struct string_list fresh_packs = STRING_LIST_INIT_DUP; ··· 4142 4145 string_list_sort(&discard_packs); 4143 4146 string_list_sort(&fresh_packs); 4144 4147 4145 - for (p = get_all_packs(the_repository); p; p = p->next) { 4148 + for (p = packfile_store_get_all_packs(packs); p; p = p->next) { 4146 4149 const char *pack_name = pack_basename(p); 4147 4150 struct string_list_item *item; 4148 4151 ··· 4390 4393 4391 4394 static int has_sha1_pack_kept_or_nonlocal(const struct object_id *oid) 4392 4395 { 4396 + struct packfile_store *packs = the_repository->objects->packfiles; 4393 4397 static struct packed_git *last_found = (void *)1; 4394 4398 struct packed_git *p; 4395 4399 4396 4400 p = (last_found != (void *)1) ? last_found : 4397 - get_all_packs(the_repository); 4401 + packfile_store_get_all_packs(packs); 4398 4402 4399 4403 while (p) { 4400 4404 if ((!p->pack_local || p->pack_keep || ··· 4404 4408 return 1; 4405 4409 } 4406 4410 if (p == last_found) 4407 - p = get_all_packs(the_repository); 4411 + p = packfile_store_get_all_packs(packs); 4408 4412 else 4409 4413 p = p->next; 4410 4414 if (p == last_found) ··· 4436 4440 4437 4441 static void loosen_unused_packed_objects(void) 4438 4442 { 4443 + struct packfile_store *packs = the_repository->objects->packfiles; 4439 4444 struct packed_git *p; 4440 4445 uint32_t i; 4441 4446 uint32_t loosened_objects_nr = 0; 4442 4447 struct object_id oid; 4443 4448 4444 - for (p = get_all_packs(the_repository); p; p = p->next) { 4449 + for (p = packfile_store_get_all_packs(packs); p; p = p->next) { 4445 4450 if (!p->pack_local || p->pack_keep || p->pack_keep_in_core) 4446 4451 continue; 4447 4452 ··· 4742 4747 4743 4748 static void add_extra_kept_packs(const struct string_list *names) 4744 4749 { 4750 + struct packfile_store *packs = the_repository->objects->packfiles; 4745 4751 struct packed_git *p; 4746 4752 4747 4753 if (!names->nr) 4748 4754 return; 4749 4755 4750 - for (p = get_all_packs(the_repository); p; p = p->next) { 4756 + for (p = packfile_store_get_all_packs(packs); p; p = p->next) { 4751 4757 const char *name = basename(p->pack_name); 4752 4758 int i; 4753 4759 ··· 5185 5191 5186 5192 add_extra_kept_packs(&keep_pack_list); 5187 5193 if (ignore_packed_keep_on_disk) { 5194 + struct packfile_store *packs = the_repository->objects->packfiles; 5188 5195 struct packed_git *p; 5189 - for (p = get_all_packs(the_repository); p; p = p->next) 5196 + 5197 + for (p = packfile_store_get_all_packs(packs); p; p = p->next) 5190 5198 if (p->pack_local && p->pack_keep) 5191 5199 break; 5192 5200 if (!p) /* no keep-able packs found */ ··· 5198 5206 * want to unset "local" based on looking at packs, as 5199 5207 * it also covers non-local objects 5200 5208 */ 5209 + struct packfile_store *packs = the_repository->objects->packfiles; 5201 5210 struct packed_git *p; 5202 - for (p = get_all_packs(the_repository); p; p = p->next) { 5211 + 5212 + for (p = packfile_store_get_all_packs(packs); p; p = p->next) { 5203 5213 if (!p->pack_local) { 5204 5214 have_non_local_packs = 1; 5205 5215 break;
+4 -2
builtin/pack-redundant.c
··· 566 566 567 567 static struct pack_list * add_pack_file(const char *filename) 568 568 { 569 - struct packed_git *p = get_all_packs(the_repository); 569 + struct packfile_store *packs = the_repository->objects->packfiles; 570 + struct packed_git *p = packfile_store_get_all_packs(packs); 570 571 571 572 if (strlen(filename) < 40) 572 573 die("Bad pack filename: %s", filename); ··· 581 582 582 583 static void load_all(void) 583 584 { 584 - struct packed_git *p = get_all_packs(the_repository); 585 + struct packfile_store *packs = the_repository->objects->packfiles; 586 + struct packed_git *p = packfile_store_get_all_packs(packs); 585 587 586 588 while (p) { 587 589 add_pack(p);
+1 -1
builtin/receive-pack.c
··· 2389 2389 status = finish_command(&child); 2390 2390 if (status) 2391 2391 return "index-pack abnormal exit"; 2392 - reprepare_packed_git(the_repository); 2392 + odb_reprepare(the_repository->objects); 2393 2393 } 2394 2394 return NULL; 2395 2395 }
+7 -4
builtin/repack.c
··· 265 265 static void collect_pack_filenames(struct existing_packs *existing, 266 266 const struct string_list *extra_keep) 267 267 { 268 + struct packfile_store *packs = the_repository->objects->packfiles; 268 269 struct packed_git *p; 269 270 struct strbuf buf = STRBUF_INIT; 270 271 271 - for (p = get_all_packs(the_repository); p; p = p->next) { 272 + for (p = packfile_store_get_all_packs(packs); p; p = p->next) { 272 273 int i; 273 274 const char *base; 274 275 ··· 497 498 struct existing_packs *existing, 498 499 const struct pack_objects_args *args) 499 500 { 501 + struct packfile_store *packs = the_repository->objects->packfiles; 500 502 struct packed_git *p; 501 503 struct strbuf buf = STRBUF_INIT; 502 504 503 - for (p = get_all_packs(the_repository); p; p = p->next) { 505 + for (p = packfile_store_get_all_packs(packs); p; p = p->next) { 504 506 if (args->local && !p->pack_local) 505 507 /* 506 508 * When asked to only repack local packfiles we skip ··· 1137 1139 static void combine_small_cruft_packs(FILE *in, size_t combine_cruft_below_size, 1138 1140 struct existing_packs *existing) 1139 1141 { 1142 + struct packfile_store *packs = the_repository->objects->packfiles; 1140 1143 struct packed_git *p; 1141 1144 struct strbuf buf = STRBUF_INIT; 1142 1145 size_t i; 1143 1146 1144 - for (p = get_all_packs(the_repository); p; p = p->next) { 1147 + for (p = packfile_store_get_all_packs(packs); p; p = p->next) { 1145 1148 if (!(p->is_cruft && p->pack_local)) 1146 1149 continue; 1147 1150 ··· 1685 1688 goto cleanup; 1686 1689 } 1687 1690 1688 - reprepare_packed_git(the_repository); 1691 + odb_reprepare(the_repository->objects); 1689 1692 1690 1693 if (delete_redundant) { 1691 1694 int opts = 0;
+3 -2
connected.c
··· 72 72 * Before checking for promisor packs, be sure we have the 73 73 * latest pack-files loaded into memory. 74 74 */ 75 - reprepare_packed_git(the_repository); 75 + odb_reprepare(the_repository->objects); 76 76 do { 77 + struct packfile_store *packs = the_repository->objects->packfiles; 77 78 struct packed_git *p; 78 79 79 - for (p = get_all_packs(the_repository); p; p = p->next) { 80 + for (p = packfile_store_get_all_packs(packs); p; p = p->next) { 80 81 if (!p->pack_promisor) 81 82 continue; 82 83 if (find_pack_entry_one(oid, p))
+2 -2
fetch-pack.c
··· 1983 1983 * remote is shallow, but this is a clone, there are 1984 1984 * no objects in repo to worry about. Accept any 1985 1985 * shallow points that exist in the pack (iow in repo 1986 - * after get_pack() and reprepare_packed_git()) 1986 + * after get_pack() and odb_reprepare()) 1987 1987 */ 1988 1988 struct oid_array extra = OID_ARRAY_INIT; 1989 1989 struct object_id *oid = si->shallow->oid; ··· 2108 2108 ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought, 2109 2109 &si, pack_lockfiles); 2110 2110 } 2111 - reprepare_packed_git(the_repository); 2111 + odb_reprepare(the_repository->objects); 2112 2112 2113 2113 if (!args->cloning && args->deepen) { 2114 2114 struct check_connected_options opt = CHECK_CONNECTED_INIT;
+3 -2
http-backend.c
··· 603 603 static void get_info_packs(struct strbuf *hdr, char *arg UNUSED) 604 604 { 605 605 size_t objdirlen = strlen(repo_get_object_directory(the_repository)); 606 + struct packfile_store *packs = the_repository->objects->packfiles; 606 607 struct strbuf buf = STRBUF_INIT; 607 608 struct packed_git *p; 608 609 size_t cnt = 0; 609 610 610 611 select_getanyfile(hdr); 611 - for (p = get_all_packs(the_repository); p; p = p->next) { 612 + for (p = packfile_store_get_all_packs(packs); p; p = p->next) { 612 613 if (p->pack_local) 613 614 cnt++; 614 615 } 615 616 616 617 strbuf_grow(&buf, cnt * 53 + 2); 617 - for (p = get_all_packs(the_repository); p; p = p->next) { 618 + for (p = packfile_store_get_all_packs(packs); p; p = p->next) { 618 619 if (p->pack_local) 619 620 strbuf_addf(&buf, "P %s\n", p->pack_name + objdirlen + 6); 620 621 }
+3 -2
http.c
··· 2416 2416 static int fetch_and_setup_pack_index(struct packed_git **packs_head, 2417 2417 unsigned char *sha1, const char *base_url) 2418 2418 { 2419 + struct packfile_store *packs = the_repository->objects->packfiles; 2419 2420 struct packed_git *new_pack, *p; 2420 2421 char *tmp_idx = NULL; 2421 2422 int ret; ··· 2424 2425 * If we already have the pack locally, no need to fetch its index or 2425 2426 * even add it to list; we already have all of its objects. 2426 2427 */ 2427 - for (p = get_all_packs(the_repository); p; p = p->next) { 2428 + for (p = packfile_store_get_all_packs(packs); p; p = p->next) { 2428 2429 if (hasheq(p->hash, sha1, the_repository->hash_algo)) 2429 2430 return 0; 2430 2431 } ··· 2549 2550 lst = &((*lst)->next); 2550 2551 *lst = (*lst)->next; 2551 2552 2552 - install_packed_git(the_repository, p); 2553 + packfile_store_add_pack(the_repository->objects->packfiles, p); 2553 2554 } 2554 2555 2555 2556 struct http_pack_request *new_http_pack_request(
+1 -1
http.h
··· 210 210 void release_http_pack_request(struct http_pack_request *preq); 211 211 212 212 /* 213 - * Remove p from the given list, and invoke install_packed_git() on it. 213 + * Remove p from the given list, and invoke packfile_store_add_pack() on it. 214 214 * 215 215 * This is a convenience function for users that have obtained a list of packs 216 216 * from http_get_info_packs() and have chosen a specific pack to fetch.
+10 -19
midx.c
··· 93 93 return 0; 94 94 } 95 95 96 + struct multi_pack_index *get_multi_pack_index(struct odb_source *source) 97 + { 98 + packfile_store_prepare(source->odb->packfiles); 99 + return source->midx; 100 + } 101 + 96 102 static struct multi_pack_index *load_multi_pack_index_one(struct odb_source *source, 97 103 const char *midx_name) 98 104 { ··· 443 449 { 444 450 struct repository *r = m->source->odb->repo; 445 451 struct strbuf pack_name = STRBUF_INIT; 446 - struct strbuf key = STRBUF_INIT; 447 452 struct packed_git *p; 448 453 449 454 pack_int_id = midx_for_pack(&m, pack_int_id); ··· 455 460 456 461 strbuf_addf(&pack_name, "%s/pack/%s", m->source->path, 457 462 m->pack_names[pack_int_id]); 458 - 459 - /* pack_map holds the ".pack" name, but we have the .idx */ 460 - strbuf_addbuf(&key, &pack_name); 461 - strbuf_strip_suffix(&key, ".idx"); 462 - strbuf_addstr(&key, ".pack"); 463 - p = hashmap_get_entry_from_hash(&r->objects->pack_map, 464 - strhash(key.buf), key.buf, 465 - struct packed_git, packmap_ent); 466 - if (!p) { 467 - p = add_packed_git(r, pack_name.buf, pack_name.len, 468 - m->source->local); 469 - if (p) { 470 - install_packed_git(r, p); 471 - list_add_tail(&p->mru, &r->objects->packed_git_mru); 472 - } 473 - } 474 - 463 + p = packfile_store_load_pack(r->objects->packfiles, 464 + pack_name.buf, m->source->local); 465 + if (p) 466 + list_add_tail(&p->mru, &r->objects->packfiles->mru); 475 467 strbuf_release(&pack_name); 476 - strbuf_release(&key); 477 468 478 469 if (!p) { 479 470 m->packs[pack_int_id] = MIDX_PACK_ERROR;
+1
midx.h
··· 94 94 void get_split_midx_filename_ext(struct odb_source *source, struct strbuf *buf, 95 95 const unsigned char *hash, const char *ext); 96 96 97 + struct multi_pack_index *get_multi_pack_index(struct odb_source *source); 97 98 struct multi_pack_index *load_multi_pack_index(struct odb_source *source); 98 99 int prepare_midx_pack(struct multi_pack_index *m, uint32_t pack_int_id); 99 100 struct packed_git *nth_midxed_pack(struct multi_pack_index *m,
+1 -1
object-file.c
··· 1504 1504 1505 1505 strbuf_release(&packname); 1506 1506 /* Make objects we just wrote available to ourselves */ 1507 - reprepare_packed_git(repo); 1507 + odb_reprepare(repo->objects); 1508 1508 } 1509 1509 1510 1510 /*
+3 -3
object-name.c
··· 213 213 unique_in_midx(m, ds); 214 214 } 215 215 216 - for (p = get_packed_git(ds->repo); p && !ds->ambiguous; 216 + for (p = packfile_store_get_packs(ds->repo->objects->packfiles); p && !ds->ambiguous; 217 217 p = p->next) 218 218 unique_in_pack(p, ds); 219 219 } ··· 596 596 * or migrated from loose to packed. 597 597 */ 598 598 if (status == MISSING_OBJECT) { 599 - reprepare_packed_git(r); 599 + odb_reprepare(r->objects); 600 600 find_short_object_filename(&ds); 601 601 find_short_packed_object(&ds); 602 602 status = finish_object_disambiguation(&ds, oid); ··· 805 805 find_abbrev_len_for_midx(m, mad); 806 806 } 807 807 808 - for (p = get_packed_git(mad->repo); p; p = p->next) 808 + for (p = packfile_store_get_packs(mad->repo->objects->packfiles); p; p = p->next) 809 809 find_abbrev_len_for_pack(p, mad); 810 810 } 811 811
+27 -13
odb.c
··· 694 694 695 695 /* Not a loose object; someone else may have just packed it. */ 696 696 if (!(flags & OBJECT_INFO_QUICK)) { 697 - reprepare_packed_git(odb->repo); 697 + odb_reprepare(odb->repo->objects); 698 698 if (find_pack_entry(odb->repo, real, &e)) 699 699 break; 700 700 } ··· 996 996 997 997 memset(o, 0, sizeof(*o)); 998 998 o->repo = repo; 999 - INIT_LIST_HEAD(&o->packed_git_mru); 1000 - hashmap_init(&o->pack_map, pack_map_entry_cmp, NULL, 0); 999 + o->packfiles = packfile_store_new(o); 1001 1000 pthread_mutex_init(&o->replace_mutex, NULL); 1002 1001 string_list_init_dup(&o->submodule_source_paths); 1003 1002 return o; ··· 1035 1034 free((char *) o->cached_objects[i].value.buf); 1036 1035 FREE_AND_NULL(o->cached_objects); 1037 1036 1038 - INIT_LIST_HEAD(&o->packed_git_mru); 1039 1037 close_object_store(o); 1038 + packfile_store_free(o->packfiles); 1039 + o->packfiles = NULL; 1040 + 1041 + string_list_clear(&o->submodule_source_paths, 0); 1042 + } 1043 + 1044 + void odb_reprepare(struct object_database *o) 1045 + { 1046 + struct odb_source *source; 1047 + 1048 + obj_read_lock(); 1040 1049 1041 1050 /* 1042 - * `close_object_store()` only closes the packfiles, but doesn't free 1043 - * them. We thus have to do this manually. 1051 + * Reprepare alt odbs, in case the alternates file was modified 1052 + * during the course of this process. This only _adds_ odbs to 1053 + * the linked list, so existing odbs will continue to exist for 1054 + * the lifetime of the process. 1044 1055 */ 1045 - for (struct packed_git *p = o->packed_git, *next; p; p = next) { 1046 - next = p->next; 1047 - free(p); 1048 - } 1049 - o->packed_git = NULL; 1056 + o->loaded_alternates = 0; 1057 + odb_prepare_alternates(o); 1058 + 1059 + for (source = o->sources; source; source = source->next) 1060 + odb_clear_loose_cache(source); 1061 + 1062 + o->approximate_object_count_valid = 0; 1063 + 1064 + packfile_store_reprepare(o->packfiles); 1050 1065 1051 - hashmap_clear(&o->pack_map); 1052 - string_list_clear(&o->submodule_source_paths, 0); 1066 + obj_read_unlock(); 1053 1067 } 1054 1068 1055 1069 struct odb_transaction *odb_transaction_begin(struct object_database *odb)
+9 -27
odb.h
··· 3 3 4 4 #include "hashmap.h" 5 5 #include "object.h" 6 - #include "list.h" 7 6 #include "oidset.h" 8 7 #include "oidmap.h" 9 8 #include "string-list.h" ··· 91 90 }; 92 91 93 92 struct packed_git; 93 + struct packfile_store; 94 94 struct cached_object_entry; 95 95 struct odb_transaction; 96 96 ··· 139 139 struct commit_graph *commit_graph; 140 140 unsigned commit_graph_attempted : 1; /* if loading has been attempted */ 141 141 142 - /* 143 - * private data 144 - * 145 - * should only be accessed directly by packfile.c 146 - */ 147 - 148 - struct packed_git *packed_git; 149 - /* A most-recently-used ordered version of the packed_git list. */ 150 - struct list_head packed_git_mru; 151 - 152 - struct { 153 - struct packed_git **packs; 154 - unsigned flags; 155 - } kept_pack_cache; 142 + /* Should only be accessed directly by packfile.c and midx.c. */ 143 + struct packfile_store *packfiles; 156 144 157 145 /* 158 146 * This is meant to hold a *small* number of objects that you would ··· 164 152 size_t cached_object_nr, cached_object_alloc; 165 153 166 154 /* 167 - * A map of packfiles to packed_git structs for tracking which 168 - * packs have been loaded already. 169 - */ 170 - struct hashmap pack_map; 171 - 172 - /* 173 155 * A fast, rough count of the number of objects in the repository. 174 156 * These two fields are not meant for direct access. Use 175 157 * repo_approximate_object_count() instead. ··· 178 160 unsigned approximate_object_count_valid : 1; 179 161 180 162 /* 181 - * Whether packed_git has already been populated with this repository's 182 - * packs. 183 - */ 184 - unsigned packed_git_initialized : 1; 185 - 186 - /* 187 163 * Submodule source paths that will be added as additional sources to 188 164 * allow lookup of submodule objects via the main object database. 189 165 */ ··· 192 168 193 169 struct object_database *odb_new(struct repository *repo); 194 170 void odb_clear(struct object_database *o); 171 + 172 + /* 173 + * Clear caches, reload alternates and then reload object sources so that new 174 + * objects may become accessible. 175 + */ 176 + void odb_reprepare(struct object_database *o); 195 177 196 178 /* 197 179 * Starts an ODB transaction. Subsequent objects are written to the transaction
+2 -2
pack-bitmap.c
··· 664 664 struct packed_git *p; 665 665 int ret = -1; 666 666 667 - for (p = get_all_packs(r); p; p = p->next) { 667 + for (p = packfile_store_get_all_packs(r->objects->packfiles); p; p = p->next) { 668 668 if (open_pack_bitmap_1(bitmap_git, p) == 0) { 669 669 ret = 0; 670 670 /* ··· 3362 3362 free(midx_bitmap_name); 3363 3363 } 3364 3364 3365 - for (struct packed_git *p = get_all_packs(r); 3365 + for (struct packed_git *p = packfile_store_get_all_packs(r->objects->packfiles); 3366 3366 p; p = p->next) { 3367 3367 char *pack_bitmap_name = pack_bitmap_filename(p); 3368 3368 res |= verify_bitmap_file(r->hash_algo, pack_bitmap_name);
+2 -1
pack-objects.c
··· 86 86 87 87 static void prepare_in_pack_by_idx(struct packing_data *pdata) 88 88 { 89 + struct packfile_store *packs = pdata->repo->objects->packfiles; 89 90 struct packed_git **mapping, *p; 90 91 int cnt = 0, nr = 1U << OE_IN_PACK_BITS; 91 92 ··· 95 96 * (i.e. in_pack_idx also zero) should return NULL. 96 97 */ 97 98 mapping[cnt++] = NULL; 98 - for (p = get_all_packs(pdata->repo); p; p = p->next, cnt++) { 99 + for (p = packfile_store_get_all_packs(packs); p; p = p->next, cnt++) { 99 100 if (cnt == nr) { 100 101 free(mapping); 101 102 return;
+155 -128
packfile.c
··· 278 278 279 279 if (current) 280 280 scan_windows(current, &lru_p, &lru_w, &lru_l); 281 - for (p = current->repo->objects->packed_git; p; p = p->next) 281 + for (p = current->repo->objects->packfiles->packs; p; p = p->next) 282 282 scan_windows(p, &lru_p, &lru_w, &lru_l); 283 283 if (lru_p) { 284 284 munmap(lru_w->base, lru_w->len); ··· 362 362 void close_object_store(struct object_database *o) 363 363 { 364 364 struct odb_source *source; 365 - struct packed_git *p; 366 365 367 - for (p = o->packed_git; p; p = p->next) 368 - if (p->do_not_close) 369 - BUG("want to close pack marked 'do-not-close'"); 370 - else 371 - close_pack(p); 366 + packfile_store_close(o->packfiles); 372 367 373 368 for (source = o->sources; source; source = source->next) { 374 369 if (source->midx) ··· 468 463 struct pack_window *mru_w = NULL; 469 464 int accept_windows_inuse = 1; 470 465 471 - for (p = r->objects->packed_git; p; p = p->next) { 466 + for (p = r->objects->packfiles->packs; p; p = p->next) { 472 467 if (p->pack_fd == -1) 473 468 continue; 474 469 find_lru_pack(p, &lru_p, &mru_w, &accept_windows_inuse); ··· 784 779 return p; 785 780 } 786 781 787 - void install_packed_git(struct repository *r, struct packed_git *pack) 782 + void packfile_store_add_pack(struct packfile_store *store, 783 + struct packed_git *pack) 788 784 { 789 785 if (pack->pack_fd != -1) 790 786 pack_open_fds++; 791 787 792 - pack->next = r->objects->packed_git; 793 - r->objects->packed_git = pack; 788 + pack->next = store->packs; 789 + store->packs = pack; 794 790 795 791 hashmap_entry_init(&pack->packmap_ent, strhash(pack->pack_name)); 796 - hashmap_add(&r->objects->pack_map, &pack->packmap_ent); 792 + hashmap_add(&store->map, &pack->packmap_ent); 793 + } 794 + 795 + struct packed_git *packfile_store_load_pack(struct packfile_store *store, 796 + const char *idx_path, int local) 797 + { 798 + struct strbuf key = STRBUF_INIT; 799 + struct packed_git *p; 800 + 801 + /* 802 + * We're being called with the path to the index file, but `pack_map` 803 + * holds the path to the packfile itself. 804 + */ 805 + strbuf_addstr(&key, idx_path); 806 + strbuf_strip_suffix(&key, ".idx"); 807 + strbuf_addstr(&key, ".pack"); 808 + 809 + p = hashmap_get_entry_from_hash(&store->map, strhash(key.buf), key.buf, 810 + struct packed_git, packmap_ent); 811 + if (!p) { 812 + p = add_packed_git(store->odb->repo, idx_path, 813 + strlen(idx_path), local); 814 + if (p) 815 + packfile_store_add_pack(store, p); 816 + } 817 + 818 + strbuf_release(&key); 819 + return p; 797 820 } 798 821 799 822 void (*report_garbage)(unsigned seen_bits, const char *path); ··· 895 918 const char *file_name, void *_data) 896 919 { 897 920 struct prepare_pack_data *data = (struct prepare_pack_data *)_data; 898 - struct packed_git *p; 899 921 size_t base_len = full_name_len; 900 922 901 923 if (strip_suffix_mem(full_name, &base_len, ".idx") && 902 924 !(data->m && midx_contains_pack(data->m, file_name))) { 903 - struct hashmap_entry hent; 904 - char *pack_name = xstrfmt("%.*s.pack", (int)base_len, full_name); 905 - unsigned int hash = strhash(pack_name); 906 - hashmap_entry_init(&hent, hash); 907 - 908 - /* Don't reopen a pack we already have. */ 909 - if (!hashmap_get(&data->r->objects->pack_map, &hent, pack_name)) { 910 - p = add_packed_git(data->r, full_name, full_name_len, data->local); 911 - if (p) 912 - install_packed_git(data->r, p); 913 - } 914 - free(pack_name); 925 + char *trimmed_path = xstrndup(full_name, full_name_len); 926 + packfile_store_load_pack(data->r->objects->packfiles, 927 + trimmed_path, data->local); 928 + free(trimmed_path); 915 929 } 916 930 917 931 if (!report_garbage) ··· 951 965 string_list_clear(data.garbage, 0); 952 966 } 953 967 954 - static void prepare_packed_git(struct repository *r); 955 - /* 956 - * Give a fast, rough count of the number of objects in the repository. This 957 - * ignores loose objects completely. If you have a lot of them, then either 958 - * you should repack because your performance will be awful, or they are 959 - * all unreachable objects about to be pruned, in which case they're not really 960 - * interesting as a measure of repo size in the first place. 961 - */ 962 - unsigned long repo_approximate_object_count(struct repository *r) 963 - { 964 - if (!r->objects->approximate_object_count_valid) { 965 - struct odb_source *source; 966 - unsigned long count = 0; 967 - struct packed_git *p; 968 - 969 - prepare_packed_git(r); 970 - 971 - for (source = r->objects->sources; source; source = source->next) { 972 - struct multi_pack_index *m = get_multi_pack_index(source); 973 - if (m) 974 - count += m->num_objects; 975 - } 976 - 977 - for (p = r->objects->packed_git; p; p = p->next) { 978 - if (open_pack_index(p)) 979 - continue; 980 - count += p->num_objects; 981 - } 982 - r->objects->approximate_object_count = count; 983 - r->objects->approximate_object_count_valid = 1; 984 - } 985 - return r->objects->approximate_object_count; 986 - } 987 - 988 968 DEFINE_LIST_SORT(static, sort_packs, struct packed_git, next); 989 969 990 970 static int sort_pack(const struct packed_git *a, const struct packed_git *b) ··· 1013 993 return -1; 1014 994 } 1015 995 1016 - static void rearrange_packed_git(struct repository *r) 1017 - { 1018 - sort_packs(&r->objects->packed_git, sort_pack); 1019 - } 1020 - 1021 - static void prepare_packed_git_mru(struct repository *r) 996 + static void packfile_store_prepare_mru(struct packfile_store *store) 1022 997 { 1023 998 struct packed_git *p; 1024 999 1025 - INIT_LIST_HEAD(&r->objects->packed_git_mru); 1000 + INIT_LIST_HEAD(&store->mru); 1026 1001 1027 - for (p = r->objects->packed_git; p; p = p->next) 1028 - list_add_tail(&p->mru, &r->objects->packed_git_mru); 1002 + for (p = store->packs; p; p = p->next) 1003 + list_add_tail(&p->mru, &store->mru); 1029 1004 } 1030 1005 1031 - static void prepare_packed_git(struct repository *r) 1006 + void packfile_store_prepare(struct packfile_store *store) 1032 1007 { 1033 1008 struct odb_source *source; 1034 1009 1035 - if (r->objects->packed_git_initialized) 1010 + if (store->initialized) 1036 1011 return; 1037 1012 1038 - odb_prepare_alternates(r->objects); 1039 - for (source = r->objects->sources; source; source = source->next) { 1013 + odb_prepare_alternates(store->odb); 1014 + for (source = store->odb->sources; source; source = source->next) { 1040 1015 prepare_multi_pack_index_one(source); 1041 1016 prepare_packed_git_one(source); 1042 1017 } 1043 - rearrange_packed_git(r); 1018 + sort_packs(&store->packs, sort_pack); 1044 1019 1045 - prepare_packed_git_mru(r); 1046 - r->objects->packed_git_initialized = 1; 1020 + packfile_store_prepare_mru(store); 1021 + store->initialized = true; 1047 1022 } 1048 1023 1049 - void reprepare_packed_git(struct repository *r) 1024 + void packfile_store_reprepare(struct packfile_store *store) 1050 1025 { 1051 - struct odb_source *source; 1052 - 1053 - obj_read_lock(); 1054 - 1055 - /* 1056 - * Reprepare alt odbs, in case the alternates file was modified 1057 - * during the course of this process. This only _adds_ odbs to 1058 - * the linked list, so existing odbs will continue to exist for 1059 - * the lifetime of the process. 1060 - */ 1061 - r->objects->loaded_alternates = 0; 1062 - odb_prepare_alternates(r->objects); 1063 - 1064 - for (source = r->objects->sources; source; source = source->next) 1065 - odb_clear_loose_cache(source); 1066 - 1067 - r->objects->approximate_object_count_valid = 0; 1068 - r->objects->packed_git_initialized = 0; 1069 - prepare_packed_git(r); 1070 - obj_read_unlock(); 1026 + store->initialized = false; 1027 + packfile_store_prepare(store); 1071 1028 } 1072 1029 1073 - struct packed_git *get_packed_git(struct repository *r) 1030 + struct packed_git *packfile_store_get_packs(struct packfile_store *store) 1074 1031 { 1075 - prepare_packed_git(r); 1076 - return r->objects->packed_git; 1032 + packfile_store_prepare(store); 1033 + return store->packs; 1077 1034 } 1078 1035 1079 - struct multi_pack_index *get_multi_pack_index(struct odb_source *source) 1036 + struct packed_git *packfile_store_get_all_packs(struct packfile_store *store) 1080 1037 { 1081 - prepare_packed_git(source->odb->repo); 1082 - return source->midx; 1083 - } 1038 + packfile_store_prepare(store); 1084 1039 1085 - struct packed_git *get_all_packs(struct repository *r) 1086 - { 1087 - prepare_packed_git(r); 1088 - 1089 - for (struct odb_source *source = r->objects->sources; source; source = source->next) { 1040 + for (struct odb_source *source = store->odb->sources; source; source = source->next) { 1090 1041 struct multi_pack_index *m = source->midx; 1091 1042 if (!m) 1092 1043 continue; ··· 1094 1045 prepare_midx_pack(m, i); 1095 1046 } 1096 1047 1097 - return r->objects->packed_git; 1048 + return store->packs; 1098 1049 } 1099 1050 1100 - struct list_head *get_packed_git_mru(struct repository *r) 1051 + struct list_head *packfile_store_get_packs_mru(struct packfile_store *store) 1101 1052 { 1102 - prepare_packed_git(r); 1103 - return &r->objects->packed_git_mru; 1053 + packfile_store_prepare(store); 1054 + return &store->mru; 1055 + } 1056 + 1057 + /* 1058 + * Give a fast, rough count of the number of objects in the repository. This 1059 + * ignores loose objects completely. If you have a lot of them, then either 1060 + * you should repack because your performance will be awful, or they are 1061 + * all unreachable objects about to be pruned, in which case they're not really 1062 + * interesting as a measure of repo size in the first place. 1063 + */ 1064 + unsigned long repo_approximate_object_count(struct repository *r) 1065 + { 1066 + if (!r->objects->approximate_object_count_valid) { 1067 + struct odb_source *source; 1068 + unsigned long count = 0; 1069 + struct packed_git *p; 1070 + 1071 + packfile_store_prepare(r->objects->packfiles); 1072 + 1073 + for (source = r->objects->sources; source; source = source->next) { 1074 + struct multi_pack_index *m = get_multi_pack_index(source); 1075 + if (m) 1076 + count += m->num_objects; 1077 + } 1078 + 1079 + for (p = r->objects->packfiles->packs; p; p = p->next) { 1080 + if (open_pack_index(p)) 1081 + continue; 1082 + count += p->num_objects; 1083 + } 1084 + r->objects->approximate_object_count = count; 1085 + r->objects->approximate_object_count_valid = 1; 1086 + } 1087 + return r->objects->approximate_object_count; 1104 1088 } 1105 1089 1106 1090 unsigned long unpack_object_header_buffer(const unsigned char *buf, ··· 1155 1139 * 1156 1140 * Other worrying sections could be the call to close_pack_fd(), 1157 1141 * which can close packs even with in-use windows, and to 1158 - * reprepare_packed_git(). Regarding the former, mmap doc says: 1142 + * odb_reprepare(). Regarding the former, mmap doc says: 1159 1143 * "closing the file descriptor does not unmap the region". And 1160 1144 * for the latter, it won't re-open already available packs. 1161 1145 */ ··· 1219 1203 { 1220 1204 struct packed_git *p; 1221 1205 1222 - for (p = r->objects->packed_git; p; p = p->next) 1206 + for (p = r->objects->packfiles->packs; p; p = p->next) 1223 1207 if (oidset_contains(&p->bad_objects, oid)) 1224 1208 return p; 1225 1209 return NULL; ··· 2074 2058 { 2075 2059 struct list_head *pos; 2076 2060 2077 - prepare_packed_git(r); 2061 + packfile_store_prepare(r->objects->packfiles); 2078 2062 2079 2063 for (struct odb_source *source = r->objects->sources; source; source = source->next) 2080 2064 if (source->midx && fill_midx_entry(source->midx, oid, e)) 2081 2065 return 1; 2082 2066 2083 - if (!r->objects->packed_git) 2067 + if (!r->objects->packfiles->packs) 2084 2068 return 0; 2085 2069 2086 - list_for_each(pos, &r->objects->packed_git_mru) { 2070 + list_for_each(pos, &r->objects->packfiles->mru) { 2087 2071 struct packed_git *p = list_entry(pos, struct packed_git, mru); 2088 2072 if (!p->multi_pack_index && fill_pack_entry(oid, e, p)) { 2089 - list_move(&p->mru, &r->objects->packed_git_mru); 2073 + list_move(&p->mru, &r->objects->packfiles->mru); 2090 2074 return 1; 2091 2075 } 2092 2076 } ··· 2096 2080 static void maybe_invalidate_kept_pack_cache(struct repository *r, 2097 2081 unsigned flags) 2098 2082 { 2099 - if (!r->objects->kept_pack_cache.packs) 2083 + if (!r->objects->packfiles->kept_cache.packs) 2100 2084 return; 2101 - if (r->objects->kept_pack_cache.flags == flags) 2085 + if (r->objects->packfiles->kept_cache.flags == flags) 2102 2086 return; 2103 - FREE_AND_NULL(r->objects->kept_pack_cache.packs); 2104 - r->objects->kept_pack_cache.flags = 0; 2087 + FREE_AND_NULL(r->objects->packfiles->kept_cache.packs); 2088 + r->objects->packfiles->kept_cache.flags = 0; 2105 2089 } 2106 2090 2107 2091 struct packed_git **kept_pack_cache(struct repository *r, unsigned flags) 2108 2092 { 2109 2093 maybe_invalidate_kept_pack_cache(r, flags); 2110 2094 2111 - if (!r->objects->kept_pack_cache.packs) { 2095 + if (!r->objects->packfiles->kept_cache.packs) { 2112 2096 struct packed_git **packs = NULL; 2113 2097 size_t nr = 0, alloc = 0; 2114 2098 struct packed_git *p; ··· 2121 2105 * covers, one kept and one not kept, but the midx returns only 2122 2106 * the non-kept version. 2123 2107 */ 2124 - for (p = get_all_packs(r); p; p = p->next) { 2108 + for (p = packfile_store_get_all_packs(r->objects->packfiles); p; p = p->next) { 2125 2109 if ((p->pack_keep && (flags & ON_DISK_KEEP_PACKS)) || 2126 2110 (p->pack_keep_in_core && (flags & IN_CORE_KEEP_PACKS))) { 2127 2111 ALLOC_GROW(packs, nr + 1, alloc); ··· 2131 2115 ALLOC_GROW(packs, nr + 1, alloc); 2132 2116 packs[nr] = NULL; 2133 2117 2134 - r->objects->kept_pack_cache.packs = packs; 2135 - r->objects->kept_pack_cache.flags = flags; 2118 + r->objects->packfiles->kept_cache.packs = packs; 2119 + r->objects->packfiles->kept_cache.flags = flags; 2136 2120 } 2137 2121 2138 - return r->objects->kept_pack_cache.packs; 2122 + return r->objects->packfiles->kept_cache.packs; 2139 2123 } 2140 2124 2141 2125 int find_kept_pack_entry(struct repository *r, ··· 2218 2202 int r = 0; 2219 2203 int pack_errors = 0; 2220 2204 2221 - for (p = get_all_packs(repo); p; p = p->next) { 2205 + for (p = packfile_store_get_all_packs(repo->objects->packfiles); p; p = p->next) { 2222 2206 if ((flags & FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local) 2223 2207 continue; 2224 2208 if ((flags & FOR_EACH_OBJECT_PROMISOR_ONLY) && ··· 2332 2316 *len = hdr - out; 2333 2317 return 0; 2334 2318 } 2319 + 2320 + static int pack_map_entry_cmp(const void *cmp_data UNUSED, 2321 + const struct hashmap_entry *entry, 2322 + const struct hashmap_entry *entry2, 2323 + const void *keydata) 2324 + { 2325 + const char *key = keydata; 2326 + const struct packed_git *pg1, *pg2; 2327 + 2328 + pg1 = container_of(entry, const struct packed_git, packmap_ent); 2329 + pg2 = container_of(entry2, const struct packed_git, packmap_ent); 2330 + 2331 + return strcmp(pg1->pack_name, key ? key : pg2->pack_name); 2332 + } 2333 + 2334 + struct packfile_store *packfile_store_new(struct object_database *odb) 2335 + { 2336 + struct packfile_store *store; 2337 + CALLOC_ARRAY(store, 1); 2338 + store->odb = odb; 2339 + INIT_LIST_HEAD(&store->mru); 2340 + hashmap_init(&store->map, pack_map_entry_cmp, NULL, 0); 2341 + return store; 2342 + } 2343 + 2344 + void packfile_store_free(struct packfile_store *store) 2345 + { 2346 + for (struct packed_git *p = store->packs, *next; p; p = next) { 2347 + next = p->next; 2348 + free(p); 2349 + } 2350 + hashmap_clear(&store->map); 2351 + free(store); 2352 + } 2353 + 2354 + void packfile_store_close(struct packfile_store *store) 2355 + { 2356 + for (struct packed_git *p = store->packs; p; p = p->next) { 2357 + if (p->do_not_close) 2358 + BUG("want to close pack marked 'do-not-close'"); 2359 + close_pack(p); 2360 + } 2361 + }
+106 -19
packfile.h
··· 52 52 char pack_name[FLEX_ARRAY]; /* more */ 53 53 }; 54 54 55 - static inline int pack_map_entry_cmp(const void *cmp_data UNUSED, 56 - const struct hashmap_entry *entry, 57 - const struct hashmap_entry *entry2, 58 - const void *keydata) 59 - { 60 - const char *key = keydata; 61 - const struct packed_git *pg1, *pg2; 55 + /* 56 + * A store that manages packfiles for a given object database. 57 + */ 58 + struct packfile_store { 59 + struct object_database *odb; 60 + 61 + /* 62 + * The list of packfiles in the order in which they are being added to 63 + * the store. 64 + */ 65 + struct packed_git *packs; 66 + 67 + /* 68 + * Cache of packfiles which are marked as "kept", either because there 69 + * is an on-disk ".keep" file or because they are marked as "kept" in 70 + * memory. 71 + * 72 + * Should not be accessed directly, but via `kept_pack_cache()`. The 73 + * list of packs gets invalidated when the stored flags and the flags 74 + * passed to `kept_pack_cache()` mismatch. 75 + */ 76 + struct { 77 + struct packed_git **packs; 78 + unsigned flags; 79 + } kept_cache; 80 + 81 + /* A most-recently-used ordered version of the packs list. */ 82 + struct list_head mru; 83 + 84 + /* 85 + * A map of packfile names to packed_git structs for tracking which 86 + * packs have been loaded already. 87 + */ 88 + struct hashmap map; 89 + 90 + /* 91 + * Whether packfiles have already been populated with this store's 92 + * packs. 93 + */ 94 + bool initialized; 95 + }; 96 + 97 + /* 98 + * Allocate and initialize a new empty packfile store for the given object 99 + * database. 100 + */ 101 + struct packfile_store *packfile_store_new(struct object_database *odb); 102 + 103 + /* 104 + * Free the packfile store and all its associated state. All packfiles 105 + * tracked by the store will be closed. 106 + */ 107 + void packfile_store_free(struct packfile_store *store); 108 + 109 + /* 110 + * Close all packfiles associated with this store. The packfiles won't be 111 + * free'd, so they can be re-opened at a later point in time. 112 + */ 113 + void packfile_store_close(struct packfile_store *store); 114 + 115 + /* 116 + * Prepare the packfile store by loading packfiles and multi-pack indices for 117 + * all alternates. This becomes a no-op if the store is already prepared. 118 + * 119 + * It shouldn't typically be necessary to call this function directly, as 120 + * functions that access the store know to prepare it. 121 + */ 122 + void packfile_store_prepare(struct packfile_store *store); 62 123 63 - pg1 = container_of(entry, const struct packed_git, packmap_ent); 64 - pg2 = container_of(entry2, const struct packed_git, packmap_ent); 124 + /* 125 + * Clear the packfile caches and try to look up any new packfiles that have 126 + * appeared since last preparing the packfiles store. 127 + * 128 + * This function must be called under the `odb_read_lock()`. 129 + */ 130 + void packfile_store_reprepare(struct packfile_store *store); 65 131 66 - return strcmp(pg1->pack_name, key ? key : pg2->pack_name); 67 - } 132 + /* 133 + * Add the pack to the store so that contained objects become accessible via 134 + * the store. This moves ownership into the store. 135 + */ 136 + void packfile_store_add_pack(struct packfile_store *store, 137 + struct packed_git *pack); 138 + 139 + /* 140 + * Get packs managed by the given store. Does not load the MIDX or any packs 141 + * referenced by it. 142 + */ 143 + struct packed_git *packfile_store_get_packs(struct packfile_store *store); 144 + 145 + /* 146 + * Get all packs managed by the given store, including packfiles that are 147 + * referenced by multi-pack indices. 148 + */ 149 + struct packed_git *packfile_store_get_all_packs(struct packfile_store *store); 150 + 151 + /* 152 + * Get all packs in most-recently-used order. 153 + */ 154 + struct list_head *packfile_store_get_packs_mru(struct packfile_store *store); 155 + 156 + /* 157 + * Open the packfile and add it to the store if it isn't yet known. Returns 158 + * either the newly opened packfile or the preexisting packfile. Returns a 159 + * `NULL` pointer in case the packfile could not be opened. 160 + */ 161 + struct packed_git *packfile_store_load_pack(struct packfile_store *store, 162 + const char *idx_path, int local); 68 163 69 164 struct pack_window { 70 165 struct pack_window *next; ··· 141 236 #define PACKDIR_FILE_IDX 2 142 237 #define PACKDIR_FILE_GARBAGE 4 143 238 extern void (*report_garbage)(unsigned seen_bits, const char *path); 144 - 145 - void reprepare_packed_git(struct repository *r); 146 - void install_packed_git(struct repository *r, struct packed_git *pack); 147 - 148 - struct packed_git *get_packed_git(struct repository *r); 149 - struct list_head *get_packed_git_mru(struct repository *r); 150 - struct multi_pack_index *get_multi_pack_index(struct odb_source *source); 151 - struct packed_git *get_all_packs(struct repository *r); 152 239 153 240 /* 154 241 * Give a rough count of objects in the repository. This sacrifices accuracy
+2 -1
server-info.c
··· 287 287 288 288 static void init_pack_info(struct repository *r, const char *infofile, int force) 289 289 { 290 + struct packfile_store *packs = r->objects->packfiles; 290 291 struct packed_git *p; 291 292 int stale; 292 293 int i; 293 294 size_t alloc = 0; 294 295 295 - for (p = get_all_packs(r); p; p = p->next) { 296 + for (p = packfile_store_get_all_packs(packs); p; p = p->next) { 296 297 /* we ignore things on alternate path since they are 297 298 * not available to the pullers in general. 298 299 */
+1 -1
t/helper/test-find-pack.c
··· 39 39 if (repo_get_oid(the_repository, argv[0], &oid)) 40 40 die("cannot parse %s as an object name", argv[0]); 41 41 42 - for (p = get_all_packs(the_repository); p; p = p->next) 42 + for (p = packfile_store_get_all_packs(the_repository->objects->packfiles); p; p = p->next) 43 43 if (find_pack_entry_one(&oid, p)) { 44 44 printf("%s\n", p->pack_name); 45 45 actual_count++;
+1 -1
t/helper/test-pack-mtimes.c
··· 37 37 if (argc != 2) 38 38 usage(pack_mtimes_usage); 39 39 40 - for (p = get_all_packs(the_repository); p; p = p->next) { 40 + for (p = packfile_store_get_all_packs(the_repository->objects->packfiles); p; p = p->next) { 41 41 strbuf_addstr(&buf, basename(p->pack_name)); 42 42 strbuf_strip_suffix(&buf, ".pack"); 43 43 strbuf_addstr(&buf, ".mtimes");
+1 -1
transport-helper.c
··· 450 450 } 451 451 strbuf_release(&buf); 452 452 453 - reprepare_packed_git(the_repository); 453 + odb_reprepare(the_repository->objects); 454 454 return 0; 455 455 } 456 456