diff --git a/builtin/grep.c b/builtin/grep.c index 77f0c4dc90..d3d86abe01 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -25,12 +25,11 @@ #include "setup.h" #include "submodule.h" #include "submodule-config.h" -#include "object-file.h" #include "object-name.h" #include "odb.h" +#include "odb/source.h" #include "oid-array.h" #include "oidset.h" -#include "packfile.h" #include "pager.h" #include "path.h" #include "promisor-remote.h" @@ -1357,15 +1356,8 @@ int cmd_grep(int argc, if (recurse_submodules) repo_read_gitmodules(the_repository, 1); - if (startup_info->have_repository) { - struct odb_source *source; - - odb_prepare_alternates(the_repository->objects); - for (source = the_repository->objects->sources; source; source = source->next) { - struct odb_source_files *files = odb_source_files_downcast(source); - odb_source_packed_prepare(files->packed); - } - } + if (startup_info->have_repository) + odb_prepare(the_repository->objects, 0); start_threads(&opt); } else { diff --git a/midx.c b/midx.c index cc6b94f9dd..76c3f92cc3 100644 --- a/midx.c +++ b/midx.c @@ -101,7 +101,7 @@ static int midx_read_object_offsets(const unsigned char *chunk_start, struct multi_pack_index *get_multi_pack_index(struct odb_source_packed *source) { - odb_source_packed_prepare(source); + odb_source_prepare(&source->base, 0); return source->midx; } diff --git a/odb.c b/odb.c index 7d555be09f..68dca6357f 100644 --- a/odb.c +++ b/odb.c @@ -1070,7 +1070,7 @@ void odb_free(struct object_database *o) free(o); } -void odb_reprepare(struct object_database *o) +void odb_prepare(struct object_database *o, enum odb_prepare_flags flags) { struct odb_source *source; @@ -1082,13 +1082,19 @@ void odb_reprepare(struct object_database *o) * the linked list, so existing odbs will continue to exist for * the lifetime of the process. */ - o->loaded_alternates = 0; + if (flags & ODB_PREPARE_FLUSH_CACHES) { + o->loaded_alternates = 0; + o->object_count_valid = 0; + } + odb_prepare_alternates(o); - for (source = o->sources; source; source = source->next) - odb_source_reprepare(source); - - o->object_count_valid = 0; + odb_source_prepare(source, flags); obj_read_unlock(); } + +void odb_reprepare(struct object_database *o) +{ + odb_prepare(o, ODB_PREPARE_FLUSH_CACHES); +} diff --git a/odb.h b/odb.h index 3834a0dcbf..a194865052 100644 --- a/odb.h +++ b/odb.h @@ -124,10 +124,22 @@ void odb_free(struct object_database *o); */ void odb_close(struct object_database *o); +enum odb_prepare_flags { + /* + * Flush caches, reload alternates and then re-prepare each object + * source so that new objects may become accessible. + */ + ODB_PREPARE_FLUSH_CACHES = (1 << 0), +}; + /* - * Clear caches, reload alternates and then reload object sources so that new - * objects may become accessible. + * Prepare the object database for use. Calling this function is generally not + * needed, but can be useful in case the caller wants to pre-open individual + * sources. */ +void odb_prepare(struct object_database *o, enum odb_prepare_flags flags); + +/* Equivalent to `odb_prepare(o, ODB_PREPARE_FLUSH_CACHES)`. */ void odb_reprepare(struct object_database *o); /* diff --git a/odb/source-files.c b/odb/source-files.c index bbd1784b33..6c8e935c75 100644 --- a/odb/source-files.c +++ b/odb/source-files.c @@ -41,11 +41,12 @@ static void odb_source_files_close(struct odb_source *source) odb_source_close(&files->packed->base); } -static void odb_source_files_reprepare(struct odb_source *source) +static void odb_source_files_prepare(struct odb_source *source, + enum odb_prepare_flags flags) { struct odb_source_files *files = odb_source_files_downcast(source); - odb_source_reprepare(&files->loose->base); - odb_source_reprepare(&files->packed->base); + odb_source_prepare(&files->loose->base, flags); + odb_source_prepare(&files->packed->base, flags); } static int odb_source_files_read_object_info(struct odb_source *source, @@ -273,7 +274,7 @@ struct odb_source_files *odb_source_files_new(struct object_database *odb, files->base.free = odb_source_files_free; files->base.close = odb_source_files_close; - files->base.reprepare = odb_source_files_reprepare; + files->base.prepare = odb_source_files_prepare; files->base.read_object_info = odb_source_files_read_object_info; files->base.read_object_stream = odb_source_files_read_object_stream; files->base.for_each_object = odb_source_files_for_each_object; diff --git a/odb/source-inmemory.c b/odb/source-inmemory.c index 7f1b6f4636..0b51c58238 100644 --- a/odb/source-inmemory.c +++ b/odb/source-inmemory.c @@ -325,7 +325,8 @@ static void odb_source_inmemory_close(struct odb_source *source UNUSED) { } -static void odb_source_inmemory_reprepare(struct odb_source *source UNUSED) +static void odb_source_inmemory_prepare(struct odb_source *source UNUSED, + enum odb_prepare_flags flags UNUSED) { } @@ -365,7 +366,7 @@ struct odb_source_inmemory *odb_source_inmemory_new(struct object_database *odb) source->base.free = odb_source_inmemory_free; source->base.close = odb_source_inmemory_close; - source->base.reprepare = odb_source_inmemory_reprepare; + source->base.prepare = odb_source_inmemory_prepare; source->base.read_object_info = odb_source_inmemory_read_object_info; source->base.read_object_stream = odb_source_inmemory_read_object_stream; source->base.for_each_object = odb_source_inmemory_for_each_object; diff --git a/odb/source-loose.c b/odb/source-loose.c index 6211348a4d..a404046d50 100644 --- a/odb/source-loose.c +++ b/odb/source-loose.c @@ -664,10 +664,12 @@ static void odb_source_loose_clear_cache(struct odb_source_loose *loose) sizeof(loose->subdir_seen)); } -static void odb_source_loose_reprepare(struct odb_source *source) +static void odb_source_loose_prepare(struct odb_source *source, + enum odb_prepare_flags flags) { struct odb_source_loose *loose = odb_source_loose_downcast(source); - odb_source_loose_clear_cache(loose); + if (flags & ODB_PREPARE_FLUSH_CACHES) + odb_source_loose_clear_cache(loose); } static void odb_source_loose_close(struct odb_source *source UNUSED) @@ -708,7 +710,7 @@ struct odb_source_loose *odb_source_loose_new(struct object_database *odb, loose->base.free = odb_source_loose_free; loose->base.close = odb_source_loose_close; - loose->base.reprepare = odb_source_loose_reprepare; + loose->base.prepare = odb_source_loose_prepare; loose->base.read_object_info = odb_source_loose_read_object_info; loose->base.read_object_stream = odb_source_loose_read_object_stream; loose->base.for_each_object = odb_source_loose_for_each_object; diff --git a/odb/source-packed.c b/odb/source-packed.c index 06b31dd743..a0259b95bf 100644 --- a/odb/source-packed.c +++ b/odb/source-packed.c @@ -15,7 +15,7 @@ static int find_pack_entry(struct odb_source_packed *store, { struct packfile_list_entry *l; - odb_source_packed_prepare(store); + odb_source_prepare(&store->base, 0); if (store->midx && fill_midx_entry(store->midx, oid, e)) return 1; @@ -47,7 +47,7 @@ static int odb_source_packed_read_object_info(struct odb_source *source, * been added since the last time we have prepared the packfile store. */ if (flags & OBJECT_INFO_SECOND_READ) - odb_source_reprepare(source); + odb_source_prepare(source, ODB_PREPARE_FLUSH_CACHES); if (!find_pack_entry(packed, oid, &e)) return 1; @@ -692,27 +692,25 @@ static int sort_pack(const struct packfile_list_entry *a, return -1; } -void odb_source_packed_prepare(struct odb_source_packed *source) -{ - if (source->initialized) - return; - - prepare_multi_pack_index_one(source); - prepare_packed_git_one(source); - - sort_packs(&source->packs.head, sort_pack); - for (struct packfile_list_entry *e = source->packs.head; e; e = e->next) - if (!e->next) - source->packs.tail = e; - - source->initialized = true; -} - -static void odb_source_packed_reprepare(struct odb_source *source) +static void odb_source_packed_prepare(struct odb_source *source, + enum odb_prepare_flags flags) { struct odb_source_packed *packed = odb_source_packed_downcast(source); - packed->initialized = false; - odb_source_packed_prepare(packed); + + if (flags & ODB_PREPARE_FLUSH_CACHES) + packed->initialized = false; + if (packed->initialized) + return; + + prepare_multi_pack_index_one(packed); + prepare_packed_git_one(packed); + + sort_packs(&packed->packs.head, sort_pack); + for (struct packfile_list_entry *e = packed->packs.head; e; e = e->next) + if (!e->next) + packed->packs.tail = e; + + packed->initialized = true; } static void odb_source_packed_reparent(const char *name UNUSED, @@ -768,7 +766,7 @@ struct odb_source_packed *odb_source_packed_new(struct object_database *odb, packed->base.free = odb_source_packed_free; packed->base.close = odb_source_packed_close; - packed->base.reprepare = odb_source_packed_reprepare; + packed->base.prepare = odb_source_packed_prepare; packed->base.read_object_info = odb_source_packed_read_object_info; packed->base.read_object_stream = odb_source_packed_read_object_stream; packed->base.for_each_object = odb_source_packed_for_each_object; diff --git a/odb/source-packed.h b/odb/source-packed.h index f0724b204c..77309ddd09 100644 --- a/odb/source-packed.h +++ b/odb/source-packed.h @@ -82,13 +82,4 @@ static inline struct odb_source_packed *odb_source_packed_downcast(struct odb_so return container_of(source, struct odb_source_packed, base); } -/* - * Prepare the source by loading packfiles and multi-pack indices for - * all alternates. This becomes a no-op if the source is already prepared. - * - * It shouldn't typically be necessary to call this function directly, as - * functions that access the source know to prepare it. - */ -void odb_source_packed_prepare(struct odb_source_packed *source); - #endif diff --git a/odb/source.h b/odb/source.h index 8767708c9c..efeff7ed12 100644 --- a/odb/source.h +++ b/odb/source.h @@ -83,11 +83,12 @@ struct odb_source { void (*close)(struct odb_source *source); /* - * This callback is expected to clear underlying caches of the object - * database source. The function is called when the repository has for - * example just been repacked so that new objects will become visible. + * This callback is expected to prepare the source so that it becomes + * ready for use. It optionally clears underlying caches of the object + * database source. */ - void (*reprepare)(struct odb_source *source); + void (*prepare)(struct odb_source *source, + enum odb_prepare_flags flags); /* * This callback is expected to read object information from the object @@ -308,13 +309,14 @@ static inline void odb_source_close(struct odb_source *source) } /* - * Reprepare the object database source and clear any caches. Depending on the + * Prepare the object database source and clear any caches. Depending on the * backend used this may have the effect that concurrently-written objects * become visible. */ -static inline void odb_source_reprepare(struct odb_source *source) +static inline void odb_source_prepare(struct odb_source *source, + enum odb_prepare_flags flags) { - source->reprepare(source); + source->prepare(source, flags); } /* diff --git a/packfile.c b/packfile.c index 1d1b23b6cc..60dd0f286a 100644 --- a/packfile.c +++ b/packfile.c @@ -855,7 +855,7 @@ void for_each_file_in_pack_dir(const char *objdir, struct packfile_list_entry *packfile_store_get_packs(struct odb_source_packed *store) { - odb_source_packed_prepare(store); + odb_source_prepare(&store->base, 0); if (store->midx) { struct multi_pack_index *m = store->midx;