]> git.ipfire.org Git - thirdparty/git.git/commitdiff
odb/source-inmemory: convert to use oidtree
authorPatrick Steinhardt <ps@pks.im>
Fri, 10 Apr 2026 12:12:40 +0000 (14:12 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 14 May 2026 19:50:45 +0000 (04:50 +0900)
The in-memory source stores its objects in a simple array that we grow as
needed. This has a couple of downsides:

  - The object lookup is O(n). This doesn't matter in practice because
    we only store a small number of objects.

  - We don't have an easy way to iterate over all objects in
    lexicographic order.

  - We don't have an easy way to compute unique object ID prefixes.

Refactor the code to use an oidtree instead. This is the same data
structure used by our loose object source, and thus it means we get a
bunch of functionality for free.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
odb/source-inmemory.c
odb/source-inmemory.h

index d05a13df45ea5f6ce884d100d257e6f354e582ea..3b51cc7fefd86bdd30fdf98e7c432c135c3b9b5a 100644 (file)
@@ -3,20 +3,29 @@
 #include "odb.h"
 #include "odb/source-inmemory.h"
 #include "odb/streaming.h"
+#include "oidtree.h"
 #include "repository.h"
 
-static const struct cached_object *find_cached_object(struct odb_source_inmemory *source,
-                                                     const struct object_id *oid)
+struct inmemory_object {
+       enum object_type type;
+       const void *buf;
+       unsigned long size;
+};
+
+static const struct inmemory_object *find_cached_object(struct odb_source_inmemory *source,
+                                                       const struct object_id *oid)
 {
-       static const struct cached_object empty_tree = {
+       static const struct inmemory_object empty_tree = {
                .type = OBJ_TREE,
                .buf = "",
        };
-       const struct cached_object_entry *co = source->objects;
+       const struct inmemory_object *object;
 
-       for (size_t i = 0; i < source->objects_nr; i++, co++)
-               if (oideq(&co->oid, oid))
-                       return &co->value;
+       if (source->objects) {
+               object = oidtree_get(source->objects, oid);
+               if (object)
+                       return object;
+       }
 
        if (oid->algo && oideq(oid, hash_algos[oid->algo].empty_tree))
                return &empty_tree;
@@ -30,7 +39,7 @@ static int odb_source_inmemory_read_object_info(struct odb_source *source,
                                                enum object_info_flags flags UNUSED)
 {
        struct odb_source_inmemory *inmemory = odb_source_inmemory_downcast(source);
-       const struct cached_object *object;
+       const struct inmemory_object *object;
 
        object = find_cached_object(inmemory, oid);
        if (!object)
@@ -88,7 +97,7 @@ static int odb_source_inmemory_read_object_stream(struct odb_read_stream **out,
 {
        struct odb_source_inmemory *inmemory = odb_source_inmemory_downcast(source);
        struct odb_read_stream_inmemory *stream;
-       const struct cached_object *object;
+       const struct inmemory_object *object;
 
        object = find_cached_object(inmemory, oid);
        if (!object)
@@ -113,17 +122,23 @@ static int odb_source_inmemory_write_object(struct odb_source *source,
                                            enum odb_write_object_flags flags UNUSED)
 {
        struct odb_source_inmemory *inmemory = odb_source_inmemory_downcast(source);
-       struct cached_object_entry *object;
+       struct inmemory_object *object;
 
        hash_object_file(source->odb->repo->hash_algo, buf, len, type, oid);
 
-       ALLOC_GROW(inmemory->objects, inmemory->objects_nr + 1,
-                  inmemory->objects_alloc);
-       object = &inmemory->objects[inmemory->objects_nr++];
-       object->value.size = len;
-       object->value.type = type;
-       object->value.buf = xmemdupz(buf, len);
-       oidcpy(&object->oid, oid);
+       if (!inmemory->objects) {
+               CALLOC_ARRAY(inmemory->objects, 1);
+               oidtree_init(inmemory->objects);
+       } else if (oidtree_contains(inmemory->objects, oid)) {
+               return 0;
+       }
+
+       CALLOC_ARRAY(object, 1);
+       object->size = len;
+       object->type = type;
+       object->buf = xmemdupz(buf, len);
+
+       oidtree_insert(inmemory->objects, oid, object);
 
        return 0;
 }
@@ -167,12 +182,29 @@ out:
        return ret;
 }
 
+static int inmemory_object_free(const struct object_id *oid UNUSED,
+                               void *node_data,
+                               void *cb_data UNUSED)
+{
+       struct inmemory_object *object = node_data;
+       free((void *) object->buf);
+       free(object);
+       return 0;
+}
+
 static void odb_source_inmemory_free(struct odb_source *source)
 {
        struct odb_source_inmemory *inmemory = odb_source_inmemory_downcast(source);
-       for (size_t i = 0; i < inmemory->objects_nr; i++)
-               free((char *) inmemory->objects[i].value.buf);
-       free(inmemory->objects);
+
+       if (inmemory->objects) {
+               struct object_id null_oid = { 0 };
+
+               oidtree_each(inmemory->objects, &null_oid, 0,
+                            inmemory_object_free, NULL);
+               oidtree_clear(inmemory->objects);
+               free(inmemory->objects);
+       }
+
        free(inmemory->base.path);
        free(inmemory);
 }
index d1b05a3996468a56fd5c18f28c52209ca8201286..a88fc2e320ed5cd907b9307ff176040b7ace8e7d 100644 (file)
@@ -3,14 +3,7 @@
 
 #include "odb/source.h"
 
-struct cached_object_entry {
-       struct object_id oid;
-       struct cached_object {
-               enum object_type type;
-               const void *buf;
-               unsigned long size;
-       } value;
-};
+struct oidtree;
 
 /*
  * An in-memory source that you can write objects to that shall be made
@@ -20,9 +13,7 @@ struct cached_object_entry {
  */
 struct odb_source_inmemory {
        struct odb_source base;
-
-       struct cached_object_entry *objects;
-       size_t objects_nr, objects_alloc;
+       struct oidtree *objects;
 };
 
 /* Create a new in-memory object database source. */