mirror of
https://github.com/git/git.git
synced 2024-10-30 13:57:54 +01:00
index-pack: factor out unpack core from get_data_from_pack
This allows caller to consume large inflated object with a fixed amount of memory. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
9ec2dde9f3
commit
8a2e163ccd
1 changed files with 24 additions and 3 deletions
|
@ -504,7 +504,9 @@ static void *unpack_raw_entry(struct object_entry *obj,
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *get_data_from_pack(struct object_entry *obj)
|
static void *unpack_data(struct object_entry *obj,
|
||||||
|
int (*consume)(const unsigned char *, unsigned long, void *),
|
||||||
|
void *cb_data)
|
||||||
{
|
{
|
||||||
off_t from = obj[0].idx.offset + obj[0].hdr_size;
|
off_t from = obj[0].idx.offset + obj[0].hdr_size;
|
||||||
unsigned long len = obj[1].idx.offset - from;
|
unsigned long len = obj[1].idx.offset - from;
|
||||||
|
@ -512,15 +514,16 @@ static void *get_data_from_pack(struct object_entry *obj)
|
||||||
git_zstream stream;
|
git_zstream stream;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
data = xmalloc(obj->size);
|
data = xmalloc(consume ? 64*1024 : obj->size);
|
||||||
inbuf = xmalloc((len < 64*1024) ? len : 64*1024);
|
inbuf = xmalloc((len < 64*1024) ? len : 64*1024);
|
||||||
|
|
||||||
memset(&stream, 0, sizeof(stream));
|
memset(&stream, 0, sizeof(stream));
|
||||||
git_inflate_init(&stream);
|
git_inflate_init(&stream);
|
||||||
stream.next_out = data;
|
stream.next_out = data;
|
||||||
stream.avail_out = obj->size;
|
stream.avail_out = consume ? 64*1024 : obj->size;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
unsigned char *last_out = stream.next_out;
|
||||||
ssize_t n = (len < 64*1024) ? len : 64*1024;
|
ssize_t n = (len < 64*1024) ? len : 64*1024;
|
||||||
n = pread(pack_fd, inbuf, n, from);
|
n = pread(pack_fd, inbuf, n, from);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
|
@ -535,6 +538,15 @@ static void *get_data_from_pack(struct object_entry *obj)
|
||||||
stream.next_in = inbuf;
|
stream.next_in = inbuf;
|
||||||
stream.avail_in = n;
|
stream.avail_in = n;
|
||||||
status = git_inflate(&stream, 0);
|
status = git_inflate(&stream, 0);
|
||||||
|
if (consume) {
|
||||||
|
if (consume(last_out, stream.next_out - last_out, cb_data)) {
|
||||||
|
free(inbuf);
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
stream.next_out = data;
|
||||||
|
stream.avail_out = 64*1024;
|
||||||
|
}
|
||||||
} while (len && status == Z_OK && !stream.avail_in);
|
} while (len && status == Z_OK && !stream.avail_in);
|
||||||
|
|
||||||
/* This has been inflated OK when first encountered, so... */
|
/* This has been inflated OK when first encountered, so... */
|
||||||
|
@ -543,9 +555,18 @@ static void *get_data_from_pack(struct object_entry *obj)
|
||||||
|
|
||||||
git_inflate_end(&stream);
|
git_inflate_end(&stream);
|
||||||
free(inbuf);
|
free(inbuf);
|
||||||
|
if (consume) {
|
||||||
|
free(data);
|
||||||
|
data = NULL;
|
||||||
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *get_data_from_pack(struct object_entry *obj)
|
||||||
|
{
|
||||||
|
return unpack_data(obj, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static int compare_delta_bases(const union delta_base *base1,
|
static int compare_delta_bases(const union delta_base *base1,
|
||||||
const union delta_base *base2,
|
const union delta_base *base2,
|
||||||
enum object_type type1,
|
enum object_type type1,
|
||||||
|
|
Loading…
Reference in a new issue