mirror of
https://git.proxmox.com/git/libgit2
synced 2025-08-06 08:47:46 +00:00
pack: refcount entries and add a mutex around cache access
This commit is contained in:
parent
c0f4a0118d
commit
525d961c24
42
src/pack.c
42
src/pack.c
@ -47,13 +47,13 @@ static int packfile_error(const char *message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static git_pack_cache_entry *new_cache_object(git_off_t off, git_rawobj *source)
|
static git_pack_cache_entry *new_cache_object(git_rawobj *source)
|
||||||
{
|
{
|
||||||
git_pack_cache_entry *e = git__malloc(sizeof(git_pack_cache_entry));
|
git_pack_cache_entry *e = git__malloc(sizeof(git_pack_cache_entry));
|
||||||
if (!e)
|
if (!e)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
e->off = off;
|
e->refcount.val = 0;
|
||||||
memcpy(&e->raw, source, sizeof(git_rawobj));
|
memcpy(&e->raw, source, sizeof(git_rawobj));
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
@ -63,6 +63,7 @@ static void free_cache_object(void *o)
|
|||||||
{
|
{
|
||||||
git_pack_cache_entry *e = (git_pack_cache_entry *)o;
|
git_pack_cache_entry *e = (git_pack_cache_entry *)o;
|
||||||
|
|
||||||
|
assert(e->refcount.val == 0);
|
||||||
if (e != NULL) {
|
if (e != NULL) {
|
||||||
git__free(e->raw.data);
|
git__free(e->raw.data);
|
||||||
git__free(e);
|
git__free(e);
|
||||||
@ -361,7 +362,7 @@ static int packfile_unpack_delta(
|
|||||||
{
|
{
|
||||||
git_off_t base_offset, base_key;
|
git_off_t base_offset, base_key;
|
||||||
git_rawobj base, delta;
|
git_rawobj base, delta;
|
||||||
git_pack_cache_entry *cached;
|
git_pack_cache_entry *cached = NULL;
|
||||||
int error, found_base = 0;
|
int error, found_base = 0;
|
||||||
khiter_t k;
|
khiter_t k;
|
||||||
|
|
||||||
@ -375,15 +376,21 @@ static int packfile_unpack_delta(
|
|||||||
if (!p->bases) {
|
if (!p->bases) {
|
||||||
p->bases = git_offmap_alloc();
|
p->bases = git_offmap_alloc();
|
||||||
GITERR_CHECK_ALLOC(p->bases);
|
GITERR_CHECK_ALLOC(p->bases);
|
||||||
|
git_mutex_init(&p->bases_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
base_key = base_offset; /* git_packfile_unpack modifies base_offset */
|
base_key = base_offset; /* git_packfile_unpack modifies base_offset */
|
||||||
|
git_mutex_lock(&p->bases_lock);
|
||||||
k = kh_get(off, p->bases, base_offset);
|
k = kh_get(off, p->bases, base_offset);
|
||||||
if (k != kh_end(p->bases)) { /* found it */
|
if (k != kh_end(p->bases)) { /* found it */
|
||||||
cached = kh_value(p->bases, k);
|
cached = kh_value(p->bases, k);
|
||||||
|
git_atomic_inc(&cached->refcount);
|
||||||
found_base = 1;
|
found_base = 1;
|
||||||
memcpy(&base, &cached->raw, sizeof(git_rawobj));
|
memcpy(&base, &cached->raw, sizeof(git_rawobj));
|
||||||
} else { /* have to inflate it */
|
}
|
||||||
|
git_mutex_unlock(&p->bases_lock);
|
||||||
|
|
||||||
|
if (!cached) { /* have to inflate it */
|
||||||
error = git_packfile_unpack(&base, p, &base_offset);
|
error = git_packfile_unpack(&base, p, &base_offset);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -410,12 +417,27 @@ static int packfile_unpack_delta(
|
|||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
if (!found_base) {
|
if (found_base) {
|
||||||
cached = new_cache_object(base_key, &base);
|
git_atomic_dec(&cached->refcount);
|
||||||
|
} else {
|
||||||
|
cached = new_cache_object(&base);
|
||||||
if (cached) {
|
if (cached) {
|
||||||
k = kh_put(off, p->bases, base_key, &error);
|
int exists;
|
||||||
assert(error != 0);
|
|
||||||
kh_value(p->bases, k) = cached;
|
git_mutex_lock(&p->bases_lock);
|
||||||
|
/* Add it to the cache if nobody else has */
|
||||||
|
exists = kh_exist(p->bases, kh_get(off, p->bases, base_key));
|
||||||
|
if (!exists) {
|
||||||
|
k = kh_put(off, p->bases, base_key, &error);
|
||||||
|
assert(error != 0);
|
||||||
|
kh_value(p->bases, k) = cached;
|
||||||
|
}
|
||||||
|
git_mutex_unlock(&p->bases_lock);
|
||||||
|
/* Somebody beat us to adding it into the cache */
|
||||||
|
if (exists) {
|
||||||
|
free_cache_object(cached);
|
||||||
|
git__free(base.data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -738,6 +760,8 @@ static int packfile_open(struct git_pack_file *p)
|
|||||||
|
|
||||||
p->bases = git_offmap_alloc();
|
p->bases = git_offmap_alloc();
|
||||||
GITERR_CHECK_ALLOC(p->bases);
|
GITERR_CHECK_ALLOC(p->bases);
|
||||||
|
git_mutex_init(&p->bases_lock);
|
||||||
|
|
||||||
|
|
||||||
/* TODO: open with noatime */
|
/* TODO: open with noatime */
|
||||||
p->mwf.fd = git_futils_open_ro(p->pack_name);
|
p->mwf.fd = git_futils_open_ro(p->pack_name);
|
||||||
|
@ -54,7 +54,7 @@ struct git_pack_idx_header {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef struct git_pack_cache_entry {
|
typedef struct git_pack_cache_entry {
|
||||||
git_off_t off;
|
git_atomic refcount;
|
||||||
git_rawobj raw;
|
git_rawobj raw;
|
||||||
} git_pack_cache_entry;
|
} git_pack_cache_entry;
|
||||||
|
|
||||||
@ -77,6 +77,7 @@ struct git_pack_file {
|
|||||||
git_vector cache;
|
git_vector cache;
|
||||||
git_oid **oids;
|
git_oid **oids;
|
||||||
|
|
||||||
|
git_mutex bases_lock;
|
||||||
git_offmap *bases; /* delta base cache */
|
git_offmap *bases; /* delta base cache */
|
||||||
|
|
||||||
/* something like ".git/objects/pack/xxxxx.pack" */
|
/* something like ".git/objects/pack/xxxxx.pack" */
|
||||||
|
Loading…
Reference in New Issue
Block a user