Skip to content

Commit

Permalink
index-pack: factor out unpack core from get_data_from_pack
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Nguyễn Thái Ngọc Duy authored and Junio C Hamano committed May 23, 2012
1 parent 9ec2dde commit 8a2e163
Showing 1 changed file with 24 additions and 3 deletions.
27 changes: 24 additions & 3 deletions builtin/index-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -504,23 +504,26 @@ static void *unpack_raw_entry(struct object_entry *obj,
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;
unsigned long len = obj[1].idx.offset - from;
unsigned char *data, *inbuf;
git_zstream stream;
int status;

data = xmalloc(obj->size);
data = xmalloc(consume ? 64*1024 : obj->size);
inbuf = xmalloc((len < 64*1024) ? len : 64*1024);

memset(&stream, 0, sizeof(stream));
git_inflate_init(&stream);
stream.next_out = data;
stream.avail_out = obj->size;
stream.avail_out = consume ? 64*1024 : obj->size;

do {
unsigned char *last_out = stream.next_out;
ssize_t n = (len < 64*1024) ? len : 64*1024;
n = pread(pack_fd, inbuf, n, from);
if (n < 0)
Expand All @@ -535,6 +538,15 @@ static void *get_data_from_pack(struct object_entry *obj)
stream.next_in = inbuf;
stream.avail_in = n;
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);

/* This has been inflated OK when first encountered, so... */
Expand All @@ -543,9 +555,18 @@ static void *get_data_from_pack(struct object_entry *obj)

git_inflate_end(&stream);
free(inbuf);
if (consume) {
free(data);
data = NULL;
}
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,
const union delta_base *base2,
enum object_type type1,
Expand Down

0 comments on commit 8a2e163

Please sign in to comment.