mirror of
https://github.com/git-for-windows/git.git
synced 2026-04-10 16:54:08 -05:00
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>
This commit is contained in:
committed by
Junio C Hamano
parent
ee610b535c
commit
2603ba2286
@@ -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)
|
||||
@@ -86,7 +95,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)
|
||||
@@ -111,17 +120,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;
|
||||
}
|
||||
@@ -165,12 +180,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);
|
||||
}
|
||||
|
||||
@@ -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 inmemory 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. */
|
||||
|
||||
Reference in New Issue
Block a user