Skip to content

Commit 3611f69

Browse files
pks-tgitster
authored andcommitted
odb/source-inmemory: convert to use oidtree
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>
1 parent d960bd0 commit 3611f69

2 files changed

Lines changed: 54 additions & 31 deletions

File tree

odb/source-inmemory.c

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,29 @@
33
#include "odb.h"
44
#include "odb/source-inmemory.h"
55
#include "odb/streaming.h"
6+
#include "oidtree.h"
67
#include "repository.h"
78

8-
static const struct cached_object *find_cached_object(struct odb_source_inmemory *source,
9-
const struct object_id *oid)
9+
struct inmemory_object {
10+
enum object_type type;
11+
const void *buf;
12+
unsigned long size;
13+
};
14+
15+
static const struct inmemory_object *find_cached_object(struct odb_source_inmemory *source,
16+
const struct object_id *oid)
1017
{
11-
static const struct cached_object empty_tree = {
18+
static const struct inmemory_object empty_tree = {
1219
.type = OBJ_TREE,
1320
.buf = "",
1421
};
15-
const struct cached_object_entry *co = source->objects;
22+
const struct inmemory_object *object;
1623

17-
for (size_t i = 0; i < source->objects_nr; i++, co++)
18-
if (oideq(&co->oid, oid))
19-
return &co->value;
24+
if (source->objects) {
25+
object = oidtree_get(source->objects, oid);
26+
if (object)
27+
return object;
28+
}
2029

2130
if (oid->algo && oideq(oid, hash_algos[oid->algo].empty_tree))
2231
return &empty_tree;
@@ -30,7 +39,7 @@ static int odb_source_inmemory_read_object_info(struct odb_source *source,
3039
enum object_info_flags flags UNUSED)
3140
{
3241
struct odb_source_inmemory *inmemory = odb_source_inmemory_downcast(source);
33-
const struct cached_object *object;
42+
const struct inmemory_object *object;
3443

3544
object = find_cached_object(inmemory, oid);
3645
if (!object)
@@ -88,7 +97,7 @@ static int odb_source_inmemory_read_object_stream(struct odb_read_stream **out,
8897
{
8998
struct odb_source_inmemory *inmemory = odb_source_inmemory_downcast(source);
9099
struct odb_read_stream_inmemory *stream;
91-
const struct cached_object *object;
100+
const struct inmemory_object *object;
92101

93102
object = find_cached_object(inmemory, oid);
94103
if (!object)
@@ -113,17 +122,23 @@ static int odb_source_inmemory_write_object(struct odb_source *source,
113122
enum odb_write_object_flags flags UNUSED)
114123
{
115124
struct odb_source_inmemory *inmemory = odb_source_inmemory_downcast(source);
116-
struct cached_object_entry *object;
125+
struct inmemory_object *object;
117126

118127
hash_object_file(source->odb->repo->hash_algo, buf, len, type, oid);
119128

120-
ALLOC_GROW(inmemory->objects, inmemory->objects_nr + 1,
121-
inmemory->objects_alloc);
122-
object = &inmemory->objects[inmemory->objects_nr++];
123-
object->value.size = len;
124-
object->value.type = type;
125-
object->value.buf = xmemdupz(buf, len);
126-
oidcpy(&object->oid, oid);
129+
if (!inmemory->objects) {
130+
CALLOC_ARRAY(inmemory->objects, 1);
131+
oidtree_init(inmemory->objects);
132+
} else if (oidtree_contains(inmemory->objects, oid)) {
133+
return 0;
134+
}
135+
136+
CALLOC_ARRAY(object, 1);
137+
object->size = len;
138+
object->type = type;
139+
object->buf = xmemdupz(buf, len);
140+
141+
oidtree_insert(inmemory->objects, oid, object);
127142

128143
return 0;
129144
}
@@ -167,12 +182,29 @@ static int odb_source_inmemory_write_object_stream(struct odb_source *source,
167182
return ret;
168183
}
169184

185+
static int inmemory_object_free(const struct object_id *oid UNUSED,
186+
void *node_data,
187+
void *cb_data UNUSED)
188+
{
189+
struct inmemory_object *object = node_data;
190+
free((void *) object->buf);
191+
free(object);
192+
return 0;
193+
}
194+
170195
static void odb_source_inmemory_free(struct odb_source *source)
171196
{
172197
struct odb_source_inmemory *inmemory = odb_source_inmemory_downcast(source);
173-
for (size_t i = 0; i < inmemory->objects_nr; i++)
174-
free((char *) inmemory->objects[i].value.buf);
175-
free(inmemory->objects);
198+
199+
if (inmemory->objects) {
200+
struct object_id null_oid = { 0 };
201+
202+
oidtree_each(inmemory->objects, &null_oid, 0,
203+
inmemory_object_free, NULL);
204+
oidtree_clear(inmemory->objects);
205+
free(inmemory->objects);
206+
}
207+
176208
free(inmemory->base.path);
177209
free(inmemory);
178210
}

odb/source-inmemory.h

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,7 @@
33

44
#include "odb/source.h"
55

6-
struct cached_object_entry {
7-
struct object_id oid;
8-
struct cached_object {
9-
enum object_type type;
10-
const void *buf;
11-
unsigned long size;
12-
} value;
13-
};
6+
struct oidtree;
147

158
/*
169
* An in-memory source that you can write objects to that shall be made
@@ -20,9 +13,7 @@ struct cached_object_entry {
2013
*/
2114
struct odb_source_inmemory {
2215
struct odb_source base;
23-
24-
struct cached_object_entry *objects;
25-
size_t objects_nr, objects_alloc;
16+
struct oidtree *objects;
2617
};
2718

2819
/* Create a new in-memory object database source. */

0 commit comments

Comments
 (0)