aboutsummaryrefslogtreecommitdiff
path: root/odb
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2026-03-05 15:19:43 +0100
committerJunio C Hamano <gitster@pobox.com>2026-03-05 11:45:15 -0800
commitd9ecf268ef3f69130fa269012318470d908978f6 (patch)
tree66550ddc707f4f2c1a562201b33a89140f581bc5 /odb
parentcb506a8a69c953f7b87bb3ae099e0bed8218d3ab (diff)
downloadgit-d9ecf268ef3f69130fa269012318470d908978f6.tar.xz
odb: embed base source in the "files" backend
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>
Diffstat (limited to 'odb')
-rw-r--r--odb/source-files.c14
-rw-r--r--odb/source-files.h17
-rw-r--r--odb/source.c26
-rw-r--r--odb/source.h31
-rw-r--r--odb/streaming.c3
5 files changed, 70 insertions, 21 deletions
diff --git a/odb/source-files.c b/odb/source-files.c
index cbdaa6850f..a43a197157 100644
--- a/odb/source-files.c
+++ b/odb/source-files.c
@@ -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;
}
diff --git a/odb/source-files.h b/odb/source-files.h
index 0b8bf773ca..859a8f518a 100644
--- a/odb/source-files.h
+++ b/odb/source-files.h
@@ -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
diff --git a/odb/source.c b/odb/source.c
index 9d7fd19f45..d8b2176a94 100644
--- a/odb/source.c
+++ b/odb/source.c
@@ -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);
}
diff --git a/odb/source.h b/odb/source.h
index 1c34265189..e6698b73a3 100644
--- a/odb/source.h
+++ b/odb/source.h
@@ -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
diff --git a/odb/streaming.c b/odb/streaming.c
index 26b0a1a0f5..19cda9407d 100644
--- a/odb/streaming.c
+++ b/odb/streaming.c
@@ -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;
}