@matheusbsbs / matheus-bagliano / commits / 4a438cabac
Fork 0

index-pack: Chain the struct base_data on the stack for traversal

We need to release earlier inflated base objects when memory gets low, which means we need to be able to walk up or down the stack to locate the objects we want to release, and free their data. The new link/unlink routines allow inserting and removing the struct base_data during recursion inside resolve_delta, and the global base_cache gives us the head of the chain (bottom of the stack) so we can traverse it. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Shawn O. Pearce committed Jul 13, 2008 at 22:07 UTC 4a438cabacdbfa71f59dad127d436bbb49a86f35
1 file changed +31 -3
index-pack.c
+31 -3
@@ -27,6 +27,8 @@ union delta_base {
27 };
28
29 struct base_data {
30 + struct base_data *base;
31 + struct base_data *child;
32 void *data;
33 unsigned long size;
34 };
@@ -48,6 +50,7 @@ struct delta_entry
50
51 static struct object_entry *objects;
52 static struct delta_entry *deltas;
53 +static struct base_data *base_cache;
54 static int nr_objects;
55 static int nr_deltas;
56 static int nr_resolved_deltas;
@@ -215,6 +218,27 @@ static void bad_object(unsigned long offset, const char *format, ...)
218 die("pack has bad object at offset %lu: %s", offset, buf);
219 }
220
221 +static void link_base_data(struct base_data *base, struct base_data *c)
222 +{
223 + if (base)
224 + base->child = c;
225 + else
226 + base_cache = c;
227 +
228 + c->base = base;
229 + c->child = NULL;
230 +}
231 +
232 +static void unlink_base_data(struct base_data *c)
233 +{
234 + struct base_data *base = c->base;
235 + if (base)
236 + base->child = NULL;
237 + else
238 + base_cache = NULL;
239 + free(c->data);
240 +}
241 +
242 static void *unpack_entry_data(unsigned long offset, unsigned long size)
243 {
244 z_stream stream;
@@ -451,6 +475,8 @@ static void resolve_delta(struct object_entry *delta_obj,
475 sha1_object(result.data, result.size, type, delta_obj->idx.sha1);
476 nr_resolved_deltas++;
477
478 + link_base_data(base_obj, &result);
479 +
480 hashcpy(delta_base.sha1, delta_obj->idx.sha1);
481 if (!find_delta_children(&delta_base, &first, &last)) {
482 for (j = first; j <= last; j++) {
@@ -470,7 +496,7 @@ static void resolve_delta(struct object_entry *delta_obj,
496 }
497 }
498
473 - free(result.data);
499 + unlink_base_data(&result);
500 }
501
502 static int compare_delta_entry(const void *a, const void *b)
@@ -561,6 +587,7 @@ static void parse_pack_objects(unsigned char *sha1)
587 continue;
588 base_obj.data = get_data_from_pack(obj);
589 base_obj.size = obj->size;
590 + link_base_data(NULL, &base_obj);
591
592 if (ref)
593 for (j = ref_first; j <= ref_last; j++) {
@@ -574,7 +601,7 @@ static void parse_pack_objects(unsigned char *sha1)
601 if (child->real_type == OBJ_OFS_DELTA)
602 resolve_delta(child, &base_obj, obj->type);
603 }
577 - free(base_obj.data);
604 + unlink_base_data(&base_obj);
605 display_progress(progress, nr_resolved_deltas);
606 }
607 }
@@ -669,6 +696,7 @@ static void fix_unresolved_deltas(int nr_unresolved)
696 base_obj.data = read_sha1_file(d->base.sha1, &type, &base_obj.size);
697 if (!base_obj.data)
698 continue;
699 + link_base_data(NULL, &base_obj);
700
701 find_delta_children(&d->base, &first, &last);
702 for (j = first; j <= last; j++) {
@@ -682,7 +710,7 @@ static void fix_unresolved_deltas(int nr_unresolved)
710 die("local object %s is corrupt", sha1_to_hex(d->base.sha1));
711 append_obj_to_pack(d->base.sha1, base_obj.data,
712 base_obj.size, type);
685 - free(base_obj.data);
713 + unlink_base_data(&base_obj);
714 display_progress(progress, nr_resolved_deltas);
715 }
716 free(sorted_by_pos);