577
entry->preferred = !!preferred;
578
}
579
580
+struct midx_fanout {
581
+ struct pack_midx_entry *entries;
582
+ uint32_t nr;
583
+ uint32_t alloc;
584
+};
585
+
586
+static void midx_fanout_grow(struct midx_fanout *fanout, uint32_t nr)
587
+{
588
+ ALLOC_GROW(fanout->entries, nr, fanout->alloc);
589
+}
590
+
591
+static void midx_fanout_sort(struct midx_fanout *fanout)
592
+{
593
+ QSORT(fanout->entries, fanout->nr, midx_oid_compare);
594
+}
595
+
596
/*
597
* It is possible to artificially get into a state where there are many
598
* duplicate copies of objects. That can create high memory pressure if
611
int preferred_pack)
612
{
613
uint32_t cur_fanout, cur_pack, cur_object;
598
- uint32_t alloc_fanout, alloc_objects, total_objects = 0;
599
- struct pack_midx_entry *entries_by_fanout = NULL;
614
+ uint32_t alloc_objects, total_objects = 0;
615
+ struct midx_fanout fanout = { 0 };
616
struct pack_midx_entry *deduplicated_entries = NULL;
617
uint32_t start_pack = m ? m->num_packs : 0;
618
624
* slices to be evenly distributed, with some noise. Hence,
625
* allocate slightly more than one 256th.
626
*/
611
- alloc_objects = alloc_fanout = total_objects > 3200 ? total_objects / 200 : 16;
627
+ alloc_objects = fanout.alloc = total_objects > 3200 ? total_objects / 200 : 16;
628
613
- ALLOC_ARRAY(entries_by_fanout, alloc_fanout);
629
+ ALLOC_ARRAY(fanout.entries, fanout.alloc);
630
ALLOC_ARRAY(deduplicated_entries, alloc_objects);
631
*nr_objects = 0;
632
633
for (cur_fanout = 0; cur_fanout < 256; cur_fanout++) {
618
- uint32_t nr_fanout = 0;
634
+ fanout.nr = 0;
635
636
if (m) {
637
uint32_t start = 0, end;
641
end = ntohl(m->chunk_oid_fanout[cur_fanout]);
642
643
for (cur_object = start; cur_object < end; cur_object++) {
628
- ALLOC_GROW(entries_by_fanout, nr_fanout + 1, alloc_fanout);
644
+ midx_fanout_grow(&fanout, fanout.nr + 1);
645
nth_midxed_pack_midx_entry(m,
630
- &entries_by_fanout[nr_fanout],
646
+ &fanout.entries[fanout.nr],
647
cur_object);
648
if (nth_midxed_pack_int_id(m, cur_object) == preferred_pack)
633
- entries_by_fanout[nr_fanout].preferred = 1;
649
+ fanout.entries[fanout.nr].preferred = 1;
650
else
635
- entries_by_fanout[nr_fanout].preferred = 0;
636
- nr_fanout++;
651
+ fanout.entries[fanout.nr].preferred = 0;
652
+ fanout.nr++;
653
}
654
}
655
662
end = get_pack_fanout(info[cur_pack].p, cur_fanout);
663
664
for (cur_object = start; cur_object < end; cur_object++) {
649
- ALLOC_GROW(entries_by_fanout, nr_fanout + 1, alloc_fanout);
665
+ midx_fanout_grow(&fanout, fanout.nr + 1);
666
fill_pack_entry(cur_pack,
667
info[cur_pack].p,
668
cur_object,
653
- &entries_by_fanout[nr_fanout],
669
+ &fanout.entries[fanout.nr],
670
preferred);
655
- nr_fanout++;
671
+ fanout.nr++;
672
}
673
}
674
659
- QSORT(entries_by_fanout, nr_fanout, midx_oid_compare);
675
+ midx_fanout_sort(&fanout);
676
677
/*
678
* The batch is now sorted by OID and then mtime (descending).
679
* Take only the first duplicate.
680
*/
665
- for (cur_object = 0; cur_object < nr_fanout; cur_object++) {
666
- if (cur_object && oideq(&entries_by_fanout[cur_object - 1].oid,
667
- &entries_by_fanout[cur_object].oid))
681
+ for (cur_object = 0; cur_object < fanout.nr; cur_object++) {
682
+ if (cur_object && oideq(&fanout.entries[cur_object - 1].oid,
683
+ &fanout.entries[cur_object].oid))
684
continue;
685
686
ALLOC_GROW(deduplicated_entries, *nr_objects + 1, alloc_objects);
687
memcpy(&deduplicated_entries[*nr_objects],
672
- &entries_by_fanout[cur_object],
688
+ &fanout.entries[cur_object],
689
sizeof(struct pack_midx_entry));
690
(*nr_objects)++;
691
}
692
}
693
678
- free(entries_by_fanout);
694
+ free(fanout.entries);
695
return deduplicated_entries;
696
}
697