]> git.ipfire.org Git - thirdparty/git.git/commitdiff
odb: embed base source in the "files" backend
authorPatrick Steinhardt <ps@pks.im>
Thu, 5 Mar 2026 14:19:43 +0000 (15:19 +0100)
committerJunio C Hamano <gitster@pobox.com>
Thu, 5 Mar 2026 19:45:15 +0000 (11:45 -0800)
The "files" backend is implemented as a pointer in the `struct
odb_source`. This contradicts our typical pattern for pluggable backends
like we use it for example in the ref store or for object database
streams, where we typically embed the generic base structure in the
specialized implementation. This pattern has a couple of small benefits:

  - We avoid an extra allocation.

  - We hide implementation details in the generic structure.

  - We can easily downcast from a generic backend to the specialized
    structure and vice versa because the offsets are known at compile
    time.

  - It becomes trivial to identify locations where we depend on backend
    specific logic because the cast needs to be explicit.

Refactor our "files" object database source to do the same and embed the
`struct odb_source` in the `struct odb_source_files`.

There are still a bunch of sites in our code base where we do have to
access internals of the "files" backend. The intent is that those will
go away over time, but this will certainly take a while. Meanwhile,
provide a `odb_source_files_downcast()` function that can convert a
generic source into a "files" source.

As we only have a single source the downcast succeeds unconditionally
for now. Eventually though the intent is to make the cast `BUG()` in
case the caller requests to downcast a non-"files" backend to a "files"
backend.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
18 files changed:
builtin/cat-file.c
builtin/fast-import.c
builtin/grep.c
builtin/index-pack.c
builtin/pack-objects.c
commit-graph.c
http.c
loose.c
midx.c
object-file.c
odb.c
odb/source-files.c
odb/source-files.h
odb/source.c
odb/source.h
odb/streaming.c
packfile.c
packfile.h

index 01a53f3f294b126d7686ebaf84a903e04b614e0a..0c68d61b910bc9d9d521200a566594716e777159 100644 (file)
@@ -882,7 +882,8 @@ static void batch_each_object(struct batch_options *opt,
                struct object_info oi = { 0 };
 
                for (source = the_repository->objects->sources; source; source = source->next) {
-                       int ret = packfile_store_for_each_object(source->files->packed, &oi,
+                       struct odb_source_files *files = odb_source_files_downcast(source);
+                       int ret = packfile_store_for_each_object(files->packed, &oi,
                                                                 batch_one_object_oi, &payload, flags);
                        if (ret)
                                break;
index 627dcbf4f3e61a590c2eec9ce8c7636cbddc8e7e..a41f95191e79aadc410ce401498b43265b6a6f49 100644 (file)
@@ -875,6 +875,7 @@ static void end_packfile(void)
        running = 1;
        clear_delta_base_cache();
        if (object_count) {
+               struct odb_source_files *files = odb_source_files_downcast(pack_data->repo->objects->sources);
                struct packed_git *new_p;
                struct object_id cur_pack_oid;
                char *idx_name;
@@ -900,8 +901,7 @@ static void end_packfile(void)
                idx_name = keep_pack(create_index());
 
                /* Register the packfile with core git's machinery. */
-               new_p = packfile_store_load_pack(pack_data->repo->objects->sources->files->packed,
-                                                idx_name, 1);
+               new_p = packfile_store_load_pack(files->packed, idx_name, 1);
                if (!new_p)
                        die(_("core Git rejected index %s"), idx_name);
                all_packs[pack_id] = new_p;
@@ -982,7 +982,9 @@ static int store_object(
        }
 
        for (source = the_repository->objects->sources; source; source = source->next) {
-               if (!packfile_list_find_oid(packfile_store_get_packs(source->files->packed), &oid))
+               struct odb_source_files *files = odb_source_files_downcast(source);
+
+               if (!packfile_list_find_oid(packfile_store_get_packs(files->packed), &oid))
                        continue;
                e->type = type;
                e->pack_id = MAX_PACK_ID;
@@ -1187,7 +1189,9 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
        }
 
        for (source = the_repository->objects->sources; source; source = source->next) {
-               if (!packfile_list_find_oid(packfile_store_get_packs(source->files->packed), &oid))
+               struct odb_source_files *files = odb_source_files_downcast(source);
+
+               if (!packfile_list_find_oid(packfile_store_get_packs(files->packed), &oid))
                        continue;
                e->type = OBJ_BLOB;
                e->pack_id = MAX_PACK_ID;
index c8d0e51415336e9557ecd452f85b19f84da7b4bc..61379909b885fa56f2e79123ea7fee98a83bc417 100644 (file)
@@ -1218,8 +1218,10 @@ int cmd_grep(int argc,
                        struct odb_source *source;
 
                        odb_prepare_alternates(the_repository->objects);
-                       for (source = the_repository->objects->sources; source; source = source->next)
-                               packfile_store_prepare(source->files->packed);
+                       for (source = the_repository->objects->sources; source; source = source->next) {
+                               struct odb_source_files *files = odb_source_files_downcast(source);
+                               packfile_store_prepare(files->packed);
+                       }
                }
 
                start_threads(&opt);
index f0cce534b2623d10ff0b1a38cfc3bb3a284fa193..d1e47279a8c7c94720d99fc85d1a2da1b0380a5b 100644 (file)
@@ -1637,9 +1637,11 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
        rename_tmp_packfile(&final_index_name, curr_index_name, &index_name,
                            hash, "idx", 1);
 
-       if (do_fsck_object && startup_info->have_repository)
-               packfile_store_load_pack(the_repository->objects->sources->files->packed,
-                                        final_index_name, 0);
+       if (do_fsck_object && startup_info->have_repository) {
+               struct odb_source_files *files =
+                       odb_source_files_downcast(the_repository->objects->sources);
+               packfile_store_load_pack(files->packed, final_index_name, 0);
+       }
 
        if (!from_stdin) {
                printf("%s\n", hash_to_hex(hash));
index 0c3c01cdc95c079bea63041b3c5c1b8ac05fe014..63fea80b08979f9363f3863ab7cf48f367cc990b 100644 (file)
@@ -1531,7 +1531,8 @@ static int want_cruft_object_mtime(struct repository *r,
        struct odb_source *source;
 
        for (source = r->objects->sources; source; source = source->next) {
-               struct packed_git **cache = packfile_store_get_kept_pack_cache(source->files->packed, flags);
+               struct odb_source_files *files = odb_source_files_downcast(source);
+               struct packed_git **cache = packfile_store_get_kept_pack_cache(files->packed, flags);
 
                for (; *cache; cache++) {
                        struct packed_git *p = *cache;
@@ -1753,11 +1754,13 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
        }
 
        for (source = the_repository->objects->sources; source; source = source->next) {
-               for (e = source->files->packed->packs.head; e; e = e->next) {
+               struct odb_source_files *files = odb_source_files_downcast(source);
+
+               for (e = files->packed->packs.head; e; e = e->next) {
                        struct packed_git *p = e->pack;
                        want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset, found_mtime);
                        if (!exclude && want > 0)
-                               packfile_list_prepend(&source->files->packed->packs, p);
+                               packfile_list_prepend(&files->packed->packs, p);
                        if (want != -1)
                                return want;
                }
@@ -4337,10 +4340,12 @@ static void add_objects_in_unpacked_packs(void)
 
        odb_prepare_alternates(to_pack.repo->objects);
        for (source = to_pack.repo->objects->sources; source; source = source->next) {
+               struct odb_source_files *files = odb_source_files_downcast(source);
+
                if (!source->local)
                        continue;
 
-               if (packfile_store_for_each_object(source->files->packed, &oi,
+               if (packfile_store_for_each_object(files->packed, &oi,
                                                   add_object_in_unpacked_pack, NULL,
                                                   ODB_FOR_EACH_OBJECT_PACK_ORDER |
                                                   ODB_FOR_EACH_OBJECT_LOCAL_ONLY |
index 967eb77047910a86dc94d163b5868ef9610bce5b..f8e24145a513b083052ea3bfc22372972f250e68 100644 (file)
@@ -1980,9 +1980,11 @@ static void fill_oids_from_all_packs(struct write_commit_graph_context *ctx)
                        ctx->approx_nr_objects);
 
        odb_prepare_alternates(ctx->r->objects);
-       for (source = ctx->r->objects->sources; source; source = source->next)
-               packfile_store_for_each_object(source->files->packed, &oi, add_packed_commits_oi,
+       for (source = ctx->r->objects->sources; source; source = source->next) {
+               struct odb_source_files *files = odb_source_files_downcast(source);
+               packfile_store_for_each_object(files->packed, &oi, add_packed_commits_oi,
                                               ctx, ODB_FOR_EACH_OBJECT_PACK_ORDER);
+       }
 
        if (ctx->progress_done < ctx->approx_nr_objects)
                display_progress(ctx->progress, ctx->approx_nr_objects);
diff --git a/http.c b/http.c
index b44f493919c40bc6f97f424866299c5eb316c913..8ea1b9d1f68c16143130aced426df3f224b6c429 100644 (file)
--- a/http.c
+++ b/http.c
@@ -2543,8 +2543,9 @@ cleanup:
 void http_install_packfile(struct packed_git *p,
                           struct packfile_list *list_to_remove_from)
 {
+       struct odb_source_files *files = odb_source_files_downcast(the_repository->objects->sources);
        packfile_list_remove(list_to_remove_from, p);
-       packfile_store_add_pack(the_repository->objects->sources->files->packed, p);
+       packfile_store_add_pack(files->packed, p);
 }
 
 struct http_pack_request *new_http_pack_request(
diff --git a/loose.c b/loose.c
index c921d46b94ee052d813550459dba03a497554c99..07333be6969fcc370b052fa1ed7c684442ff20af 100644 (file)
--- a/loose.c
+++ b/loose.c
@@ -3,6 +3,7 @@
 #include "path.h"
 #include "object-file.h"
 #include "odb.h"
+#include "odb/source-files.h"
 #include "hex.h"
 #include "repository.h"
 #include "wrapper.h"
@@ -49,27 +50,29 @@ static int insert_loose_map(struct odb_source *source,
                            const struct object_id *oid,
                            const struct object_id *compat_oid)
 {
-       struct loose_object_map *map = source->files->loose->map;
+       struct odb_source_files *files = odb_source_files_downcast(source);
+       struct loose_object_map *map = files->loose->map;
        int inserted = 0;
 
        inserted |= insert_oid_pair(map->to_compat, oid, compat_oid);
        inserted |= insert_oid_pair(map->to_storage, compat_oid, oid);
        if (inserted)
-               oidtree_insert(source->files->loose->cache, compat_oid);
+               oidtree_insert(files->loose->cache, compat_oid);
 
        return inserted;
 }
 
 static int load_one_loose_object_map(struct repository *repo, struct odb_source *source)
 {
+       struct odb_source_files *files = odb_source_files_downcast(source);
        struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT;
        FILE *fp;
 
-       if (!source->files->loose->map)
-               loose_object_map_init(&source->files->loose->map);
-       if (!source->files->loose->cache) {
-               ALLOC_ARRAY(source->files->loose->cache, 1);
-               oidtree_init(source->files->loose->cache);
+       if (!files->loose->map)
+               loose_object_map_init(&files->loose->map);
+       if (!files->loose->cache) {
+               ALLOC_ARRAY(files->loose->cache, 1);
+               oidtree_init(files->loose->cache);
        }
 
        insert_loose_map(source, repo->hash_algo->empty_tree, repo->compat_hash_algo->empty_tree);
@@ -125,7 +128,8 @@ int repo_read_loose_object_map(struct repository *repo)
 
 int repo_write_loose_object_map(struct repository *repo)
 {
-       kh_oid_map_t *map = repo->objects->sources->files->loose->map->to_compat;
+       struct odb_source_files *files = odb_source_files_downcast(repo->objects->sources);
+       kh_oid_map_t *map = files->loose->map->to_compat;
        struct lock_file lock;
        int fd;
        khiter_t iter;
@@ -231,7 +235,8 @@ int repo_loose_object_map_oid(struct repository *repo,
        khiter_t pos;
 
        for (source = repo->objects->sources; source; source = source->next) {
-               struct loose_object_map *loose_map = source->files->loose->map;
+               struct odb_source_files *files = odb_source_files_downcast(source);
+               struct loose_object_map *loose_map = files->loose->map;
                if (!loose_map)
                        continue;
                map = (to == repo->compat_hash_algo) ?
diff --git a/midx.c b/midx.c
index 698d10a1c68c76fe26463834050d9ff36ca44a83..ab8e2611d1fe583146e6247c8cc44a7a300a0b6a 100644 (file)
--- a/midx.c
+++ b/midx.c
@@ -95,8 +95,9 @@ static int midx_read_object_offsets(const unsigned char *chunk_start,
 
 struct multi_pack_index *get_multi_pack_index(struct odb_source *source)
 {
-       packfile_store_prepare(source->files->packed);
-       return source->files->packed->midx;
+       struct odb_source_files *files = odb_source_files_downcast(source);
+       packfile_store_prepare(files->packed);
+       return files->packed->midx;
 }
 
 static struct multi_pack_index *load_multi_pack_index_one(struct odb_source *source,
@@ -447,6 +448,7 @@ static uint32_t midx_for_pack(struct multi_pack_index **_m,
 int prepare_midx_pack(struct multi_pack_index *m,
                      uint32_t pack_int_id)
 {
+       struct odb_source_files *files = odb_source_files_downcast(m->source);
        struct strbuf pack_name = STRBUF_INIT;
        struct packed_git *p;
 
@@ -457,10 +459,10 @@ int prepare_midx_pack(struct multi_pack_index *m,
        if (m->packs[pack_int_id])
                return 0;
 
-       strbuf_addf(&pack_name, "%s/pack/%s", m->source->path,
+       strbuf_addf(&pack_name, "%s/pack/%s", files->base.path,
                    m->pack_names[pack_int_id]);
-       p = packfile_store_load_pack(m->source->files->packed,
-                                    pack_name.buf, m->source->local);
+       p = packfile_store_load_pack(files->packed,
+                                    pack_name.buf, files->base.local);
        strbuf_release(&pack_name);
 
        if (!p) {
@@ -703,18 +705,19 @@ int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id)
 
 int prepare_multi_pack_index_one(struct odb_source *source)
 {
+       struct odb_source_files *files = odb_source_files_downcast(source);
        struct repository *r = source->odb->repo;
 
        prepare_repo_settings(r);
        if (!r->settings.core_multi_pack_index)
                return 0;
 
-       if (source->files->packed->midx)
+       if (files->packed->midx)
                return 1;
 
-       source->files->packed->midx = load_multi_pack_index(source);
+       files->packed->midx = load_multi_pack_index(source);
 
-       return !!source->files->packed->midx;
+       return !!files->packed->midx;
 }
 
 int midx_checksum_valid(struct multi_pack_index *m)
@@ -803,9 +806,10 @@ void clear_midx_file(struct repository *r)
                struct odb_source *source;
 
                for (source = r->objects->sources; source; source = source->next) {
-                       if (source->files->packed->midx)
-                               close_midx(source->files->packed->midx);
-                       source->files->packed->midx = NULL;
+                       struct odb_source_files *files = odb_source_files_downcast(source);
+                       if (files->packed->midx)
+                               close_midx(files->packed->midx);
+                       files->packed->midx = NULL;
                }
        }
 
index db66ae5ebe56b8a42ff99628dcd6253f4020e7b5..7ef8291a486794c7a8972eb8a37c4b0b337895fe 100644 (file)
@@ -219,8 +219,9 @@ static void *odb_source_loose_map_object(struct odb_source *source,
                                         const struct object_id *oid,
                                         unsigned long *size)
 {
+       struct odb_source_files *files = odb_source_files_downcast(source);
        const char *p;
-       int fd = open_loose_object(source->files->loose, oid, &p);
+       int fd = open_loose_object(files->loose, oid, &p);
 
        if (fd < 0)
                return NULL;
@@ -401,6 +402,7 @@ static int read_object_info_from_path(struct odb_source *source,
                                      struct object_info *oi,
                                      enum object_info_flags flags)
 {
+       struct odb_source_files *files = odb_source_files_downcast(source);
        int ret;
        int fd;
        unsigned long mapsize;
@@ -423,7 +425,7 @@ static int read_object_info_from_path(struct odb_source *source,
                struct stat st;
 
                if ((!oi || (!oi->disk_sizep && !oi->mtimep)) && (flags & OBJECT_INFO_QUICK)) {
-                       ret = quick_has_loose(source->files->loose, oid) ? 0 : -1;
+                       ret = quick_has_loose(files->loose, oid) ? 0 : -1;
                        goto out;
                }
 
@@ -1866,33 +1868,34 @@ static int append_loose_object(const struct object_id *oid,
 struct oidtree *odb_source_loose_cache(struct odb_source *source,
                                       const struct object_id *oid)
 {
+       struct odb_source_files *files = odb_source_files_downcast(source);
        int subdir_nr = oid->hash[0];
        struct strbuf buf = STRBUF_INIT;
-       size_t word_bits = bitsizeof(source->files->loose->subdir_seen[0]);
+       size_t word_bits = bitsizeof(files->loose->subdir_seen[0]);
        size_t word_index = subdir_nr / word_bits;
        size_t mask = (size_t)1u << (subdir_nr % word_bits);
        uint32_t *bitmap;
 
        if (subdir_nr < 0 ||
-           (size_t) subdir_nr >= bitsizeof(source->files->loose->subdir_seen))
+           (size_t) subdir_nr >= bitsizeof(files->loose->subdir_seen))
                BUG("subdir_nr out of range");
 
-       bitmap = &source->files->loose->subdir_seen[word_index];
+       bitmap = &files->loose->subdir_seen[word_index];
        if (*bitmap & mask)
-               return source->files->loose->cache;
-       if (!source->files->loose->cache) {
-               ALLOC_ARRAY(source->files->loose->cache, 1);
-               oidtree_init(source->files->loose->cache);
+               return files->loose->cache;
+       if (!files->loose->cache) {
+               ALLOC_ARRAY(files->loose->cache, 1);
+               oidtree_init(files->loose->cache);
        }
        strbuf_addstr(&buf, source->path);
        for_each_file_in_obj_subdir(subdir_nr, &buf,
                                    source->odb->repo->hash_algo,
                                    append_loose_object,
                                    NULL, NULL,
-                                   source->files->loose->cache);
+                                   files->loose->cache);
        *bitmap |= mask;
        strbuf_release(&buf);
-       return source->files->loose->cache;
+       return files->loose->cache;
 }
 
 static void odb_source_loose_clear_cache(struct odb_source_loose *loose)
@@ -1905,7 +1908,8 @@ static void odb_source_loose_clear_cache(struct odb_source_loose *loose)
 
 void odb_source_loose_reprepare(struct odb_source *source)
 {
-       odb_source_loose_clear_cache(source->files->loose);
+       struct odb_source_files *files = odb_source_files_downcast(source);
+       odb_source_loose_clear_cache(files->loose);
 }
 
 static int check_stream_oid(git_zstream *stream,
diff --git a/odb.c b/odb.c
index c9ebc7e741956ae90f46e66773368955dc7a1186..e5aa8deb88615cfe95ac69b8db0f3b9783950ade 100644 (file)
--- a/odb.c
+++ b/odb.c
@@ -691,7 +691,8 @@ static int do_oid_object_info_extended(struct object_database *odb,
 
                /* Most likely it's a loose object. */
                for (source = odb->sources; source; source = source->next) {
-                       if (!packfile_store_read_object_info(source->files->packed, real, oi, flags) ||
+                       struct odb_source_files *files = odb_source_files_downcast(source);
+                       if (!packfile_store_read_object_info(files->packed, real, oi, flags) ||
                            !odb_source_loose_read_object_info(source, real, oi, flags))
                                return 0;
                }
@@ -699,9 +700,11 @@ static int do_oid_object_info_extended(struct object_database *odb,
                /* Not a loose object; someone else may have just packed it. */
                if (!(flags & OBJECT_INFO_QUICK)) {
                        odb_reprepare(odb->repo->objects);
-                       for (source = odb->sources; source; source = source->next)
-                               if (!packfile_store_read_object_info(source->files->packed, real, oi, flags))
+                       for (source = odb->sources; source; source = source->next) {
+                               struct odb_source_files *files = odb_source_files_downcast(source);
+                               if (!packfile_store_read_object_info(files->packed, real, oi, flags))
                                        return 0;
+                       }
                }
 
                /*
@@ -962,7 +965,9 @@ int odb_freshen_object(struct object_database *odb,
 
        odb_prepare_alternates(odb);
        for (source = odb->sources; source; source = source->next) {
-               if (packfile_store_freshen_object(source->files->packed, oid))
+               struct odb_source_files *files = odb_source_files_downcast(source);
+
+               if (packfile_store_freshen_object(files->packed, oid))
                        return 1;
 
                if (odb_source_loose_freshen_object(source, oid))
@@ -982,6 +987,8 @@ int odb_for_each_object(struct object_database *odb,
 
        odb_prepare_alternates(odb);
        for (struct odb_source *source = odb->sources; source; source = source->next) {
+               struct odb_source_files *files = odb_source_files_downcast(source);
+
                if (flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY && !source->local)
                        continue;
 
@@ -992,7 +999,7 @@ int odb_for_each_object(struct object_database *odb,
                                return ret;
                }
 
-               ret = packfile_store_for_each_object(source->files->packed, request,
+               ret = packfile_store_for_each_object(files->packed, request,
                                                     cb, cb_data, flags);
                if (ret)
                        return ret;
@@ -1090,8 +1097,10 @@ struct object_database *odb_new(struct repository *repo,
 void odb_close(struct object_database *o)
 {
        struct odb_source *source;
-       for (source = o->sources; source; source = source->next)
-               packfile_store_close(source->files->packed);
+       for (source = o->sources; source; source = source->next) {
+               struct odb_source_files *files = odb_source_files_downcast(source);
+               packfile_store_close(files->packed);
+       }
        close_commit_graph(o);
 }
 
@@ -1148,8 +1157,9 @@ void odb_reprepare(struct object_database *o)
        odb_prepare_alternates(o);
 
        for (source = o->sources; source; source = source->next) {
+               struct odb_source_files *files = odb_source_files_downcast(source);
                odb_source_loose_reprepare(source);
-               packfile_store_reprepare(source->files->packed);
+               packfile_store_reprepare(files->packed);
        }
 
        o->approximate_object_count_valid = 0;
index cbdaa6850f5d461d310c58312f0585f3fbcbe23a..a43a1971577763a8ffddbea9d29330fa93e14bc1 100644 (file)
@@ -1,5 +1,6 @@
 #include "git-compat-util.h"
 #include "object-file.h"
+#include "odb/source.h"
 #include "odb/source-files.h"
 #include "packfile.h"
 
@@ -9,15 +10,20 @@ void odb_source_files_free(struct odb_source_files *files)
                return;
        odb_source_loose_free(files->loose);
        packfile_store_free(files->packed);
+       odb_source_release(&files->base);
        free(files);
 }
 
-struct odb_source_files *odb_source_files_new(struct odb_source *source)
+struct odb_source_files *odb_source_files_new(struct object_database *odb,
+                                             const char *path,
+                                             bool local)
 {
        struct odb_source_files *files;
+
        CALLOC_ARRAY(files, 1);
-       files->source = source;
-       files->loose = odb_source_loose_new(source);
-       files->packed = packfile_store_new(source);
+       odb_source_init(&files->base, odb, path, local);
+       files->loose = odb_source_loose_new(&files->base);
+       files->packed = packfile_store_new(&files->base);
+
        return files;
 }
index 0b8bf773ca7521ece9c093382a030b6418d237f7..859a8f518a4406831b9c7c61d1814948ce5a56f2 100644 (file)
@@ -1,8 +1,9 @@
 #ifndef ODB_SOURCE_FILES_H
 #define ODB_SOURCE_FILES_H
 
+#include "odb/source.h"
+
 struct odb_source_loose;
-struct odb_source;
 struct packfile_store;
 
 /*
@@ -10,15 +11,25 @@ struct packfile_store;
  * packfiles. It is the default backend used by Git to store objects.
  */
 struct odb_source_files {
-       struct odb_source *source;
+       struct odb_source base;
        struct odb_source_loose *loose;
        struct packfile_store *packed;
 };
 
 /* Allocate and initialize a new object source. */
-struct odb_source_files *odb_source_files_new(struct odb_source *source);
+struct odb_source_files *odb_source_files_new(struct object_database *odb,
+                                             const char *path,
+                                             bool local);
 
 /* Free the object source and release all associated resources. */
 void odb_source_files_free(struct odb_source_files *files);
 
+/*
+ * Cast the given object database source to the files backend.
+ */
+static inline struct odb_source_files *odb_source_files_downcast(struct odb_source *source)
+{
+       return container_of(source, struct odb_source_files, base);
+}
+
 #endif
index 9d7fd19f4545087326fa3093a525e4573827ba17..d8b2176a94646a88328aa03b74a27d2a49f7498e 100644 (file)
@@ -1,5 +1,6 @@
 #include "git-compat-util.h"
 #include "object-file.h"
+#include "odb/source-files.h"
 #include "odb/source.h"
 #include "packfile.h"
 
@@ -7,20 +8,31 @@ struct odb_source *odb_source_new(struct object_database *odb,
                                  const char *path,
                                  bool local)
 {
-       struct odb_source *source;
+       return &odb_source_files_new(odb, path, local)->base;
+}
 
-       CALLOC_ARRAY(source, 1);
+void odb_source_init(struct odb_source *source,
+                    struct object_database *odb,
+                    const char *path,
+                    bool local)
+{
        source->odb = odb;
        source->local = local;
        source->path = xstrdup(path);
-       source->files = odb_source_files_new(source);
-
-       return source;
 }
 
 void odb_source_free(struct odb_source *source)
 {
+       struct odb_source_files *files;
+       if (!source)
+               return;
+       files = odb_source_files_downcast(source);
+       odb_source_files_free(files);
+}
+
+void odb_source_release(struct odb_source *source)
+{
+       if (!source)
+               return;
        free(source->path);
-       odb_source_files_free(source->files);
-       free(source);
 }
index 1c34265189d8f3877013679e8ca69a0d4560c0e3..e6698b73a3c6606fbd2316116a9131e508f4d051 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef ODB_SOURCE_H
 #define ODB_SOURCE_H
 
-#include "odb/source-files.h"
-
 /*
  * The source is the part of the object database that stores the actual
  * objects. It thus encapsulates the logic to read and write the specific
@@ -21,9 +19,6 @@ struct odb_source {
        /* Object database that owns this object source. */
        struct object_database *odb;
 
-       /* The backend used to store objects. */
-       struct odb_source_files *files;
-
        /*
         * Figure out whether this is the local source of the owning
         * repository, which would typically be its ".git/objects" directory.
@@ -53,7 +48,31 @@ struct odb_source *odb_source_new(struct object_database *odb,
                                  const char *path,
                                  bool local);
 
-/* Free the object database source, releasing all associated resources. */
+/*
+ * Initialize the source for the given object database located at `path`.
+ * `local` indicates whether or not the source is the local and thus primary
+ * object source of the object database.
+ *
+ * This function is only supposed to be called by specific object source
+ * implementations.
+ */
+void odb_source_init(struct odb_source *source,
+                    struct object_database *odb,
+                    const char *path,
+                    bool local);
+
+/*
+ * Free the object database source, releasing all associated resources and
+ * freeing the structure itself.
+ */
 void odb_source_free(struct odb_source *source);
 
+/*
+ * Release the object database source, releasing all associated resources.
+ *
+ * This function is only supposed to be called by specific object source
+ * implementations.
+ */
+void odb_source_release(struct odb_source *source);
+
 #endif
index 26b0a1a0f5ad05ec78368c25eef07d43198d90c3..19cda9407d1ce3d3a915065df32eda3176f3af6d 100644 (file)
@@ -187,7 +187,8 @@ static int istream_source(struct odb_read_stream **out,
 
        odb_prepare_alternates(odb);
        for (source = odb->sources; source; source = source->next) {
-               if (!packfile_store_read_object_stream(out, source->files->packed, oid) ||
+               struct odb_source_files *files = odb_source_files_downcast(source);
+               if (!packfile_store_read_object_stream(out, files->packed, oid) ||
                    !odb_source_loose_read_object_stream(out, source, oid))
                        return 0;
        }
index 4e1f6087eda1f37b63f112661d6c1389c4f19ae9..da1c0dfa3995d02fa8c71d979c04559c830039c8 100644 (file)
@@ -362,9 +362,11 @@ static int unuse_one_window(struct object_database *odb)
        struct packed_git *lru_p = NULL;
        struct pack_window *lru_w = NULL, *lru_l = NULL;
 
-       for (source = odb->sources; source; source = source->next)
-               for (e = source->files->packed->packs.head; e; e = e->next)
+       for (source = odb->sources; source; source = source->next) {
+               struct odb_source_files *files = odb_source_files_downcast(source);
+               for (e = files->packed->packs.head; e; e = e->next)
                        scan_windows(e->pack, &lru_p, &lru_w, &lru_l);
+       }
 
        if (lru_p) {
                munmap(lru_w->base, lru_w->len);
@@ -537,7 +539,8 @@ static int close_one_pack(struct repository *r)
        int accept_windows_inuse = 1;
 
        for (source = r->objects->sources; source; source = source->next) {
-               for (e = source->files->packed->packs.head; e; e = e->next) {
+               struct odb_source_files *files = odb_source_files_downcast(source);
+               for (e = files->packed->packs.head; e; e = e->next) {
                        if (e->pack->pack_fd == -1)
                                continue;
                        find_lru_pack(e->pack, &lru_p, &mru_w, &accept_windows_inuse);
@@ -987,13 +990,14 @@ static void prepare_pack(const char *full_name, size_t full_name_len,
                         const char *file_name, void *_data)
 {
        struct prepare_pack_data *data = (struct prepare_pack_data *)_data;
+       struct odb_source_files *files = odb_source_files_downcast(data->source);
        size_t base_len = full_name_len;
 
        if (strip_suffix_mem(full_name, &base_len, ".idx") &&
-           !(data->source->files->packed->midx &&
-             midx_contains_pack(data->source->files->packed->midx, file_name))) {
+           !(files->packed->midx &&
+             midx_contains_pack(files->packed->midx, file_name))) {
                char *trimmed_path = xstrndup(full_name, full_name_len);
-               packfile_store_load_pack(data->source->files->packed,
+               packfile_store_load_pack(files->packed,
                                         trimmed_path, data->source->local);
                free(trimmed_path);
        }
@@ -1247,8 +1251,10 @@ const struct packed_git *has_packed_and_bad(struct repository *r,
        struct odb_source *source;
 
        for (source = r->objects->sources; source; source = source->next) {
+               struct odb_source_files *files = odb_source_files_downcast(source);
                struct packfile_list_entry *e;
-               for (e = source->files->packed->packs.head; e; e = e->next)
+
+               for (e = files->packed->packs.head; e; e = e->next)
                        if (oidset_contains(&e->pack->bad_objects, oid))
                                return e->pack;
        }
@@ -2254,7 +2260,8 @@ int has_object_pack(struct repository *r, const struct object_id *oid)
 
        odb_prepare_alternates(r->objects);
        for (source = r->objects->sources; source; source = source->next) {
-               int ret = find_pack_entry(source->files->packed, oid, &e);
+               struct odb_source_files *files = odb_source_files_downcast(source);
+               int ret = find_pack_entry(files->packed, oid, &e);
                if (ret)
                        return ret;
        }
@@ -2269,9 +2276,10 @@ int has_object_kept_pack(struct repository *r, const struct object_id *oid,
        struct pack_entry e;
 
        for (source = r->objects->sources; source; source = source->next) {
+               struct odb_source_files *files = odb_source_files_downcast(source);
                struct packed_git **cache;
 
-               cache = packfile_store_get_kept_pack_cache(source->files->packed, flags);
+               cache = packfile_store_get_kept_pack_cache(files->packed, flags);
 
                for (; *cache; cache++) {
                        struct packed_git *p = *cache;
index e8de06ee86cdae57b0f354b2472a047501a1be44..64a31738c0f36f5e5d24dafe05ef5654d0c474c3 100644 (file)
@@ -4,6 +4,7 @@
 #include "list.h"
 #include "object.h"
 #include "odb.h"
+#include "odb/source-files.h"
 #include "oidset.h"
 #include "repository.h"
 #include "strmap.h"
@@ -192,7 +193,8 @@ static inline struct repo_for_each_pack_data repo_for_eack_pack_data_init(struct
        odb_prepare_alternates(repo->objects);
 
        for (struct odb_source *source = repo->objects->sources; source; source = source->next) {
-               struct packfile_list_entry *entry = packfile_store_get_packs(source->files->packed);
+               struct odb_source_files *files = odb_source_files_downcast(source);
+               struct packfile_list_entry *entry = packfile_store_get_packs(files->packed);
                if (!entry)
                        continue;
                data.source = source;
@@ -212,7 +214,8 @@ static inline void repo_for_each_pack_data_next(struct repo_for_each_pack_data *
                return;
 
        for (source = data->source->next; source; source = source->next) {
-               struct packfile_list_entry *entry = packfile_store_get_packs(source->files->packed);
+               struct odb_source_files *files = odb_source_files_downcast(source);
+               struct packfile_list_entry *entry = packfile_store_get_packs(files->packed);
                if (!entry)
                        continue;
                data->source = source;