* size is easily available by examining the pack entry header). It is
* also rather expensive to find the sha1 for an object given its offset.
*
- * We build a hashtable of existing packs (pack_revindex), and keep reverse
- * index here -- pack index file is sorted by object name mapping to offset;
- * this pack_revindex[].revindex array is a list of offset/index_nr pairs
+ * The pack index file is sorted by object name mapping to offset;
+ * this revindex array is a list of offset/index_nr pairs
* ordered by offset, so if you know the offset of an object, next offset
* is where its packed representation ends and the index_nr can be used to
* get the object sha1 from the main index.
*/
-static struct pack_revindex *pack_revindex;
-static int pack_revindex_hashsz;
-
-static int pack_revindex_ix(struct packed_git *p)
-{
- unsigned long ui = (unsigned long)(intptr_t)p;
- int i;
-
- ui = ui ^ (ui >> 16); /* defeat structure alignment */
- i = (int)(ui % pack_revindex_hashsz);
- while (pack_revindex[i].p) {
- if (pack_revindex[i].p == p)
- return i;
- if (++i == pack_revindex_hashsz)
- i = 0;
- }
- return -1 - i;
-}
-
-static void init_pack_revindex(void)
-{
- int num;
- struct packed_git *p;
-
- for (num = 0, p = packed_git; p; p = p->next)
- num++;
- if (!num)
- return;
- pack_revindex_hashsz = num * 11;
- pack_revindex = xcalloc(pack_revindex_hashsz, sizeof(*pack_revindex));
- for (p = packed_git; p; p = p->next) {
- num = pack_revindex_ix(p);
- num = - 1 - num;
- pack_revindex[num].p = p;
- }
- /* revindex elements are lazily initialized */
-}
-
/*
* This is a least-significant-digit radix sort.
*
* keep track of them with alias pointers, always sorting from "from"
* to "to".
*/
- struct revindex_entry *tmp = xmalloc(n * sizeof(*tmp));
- struct revindex_entry *from = entries, *to = tmp;
+ struct revindex_entry *tmp, *from, *to;
int bits;
- unsigned *pos = xmalloc(BUCKETS * sizeof(*pos));
+ unsigned *pos;
+
+ ALLOC_ARRAY(pos, BUCKETS);
+ ALLOC_ARRAY(tmp, n);
+ from = entries;
+ to = tmp;
/*
* If (max >> bits) is zero, then we know that the radix digit we are
* be a no-op, as everybody lands in the same zero-th bucket.
*/
for (bits = 0; max >> bits; bits += DIGIT_SIZE) {
- struct revindex_entry *swap;
unsigned i;
memset(pos, 0, BUCKETS * sizeof(*pos));
* Now "to" contains the most sorted list, so we swap "from" and
* "to" for the next iteration.
*/
- swap = from;
- from = to;
- to = swap;
+ SWAP(from, to);
}
/*
* we have to move it back from the temporary storage.
*/
if (from != entries)
- memcpy(entries, tmp, n * sizeof(*entries));
+ COPY_ARRAY(entries, tmp, n);
free(tmp);
free(pos);
/*
* Ordered list of offsets of objects in the pack.
*/
-static void create_pack_revindex(struct pack_revindex *rix)
+static void create_pack_revindex(struct packed_git *p)
{
- struct packed_git *p = rix->p;
unsigned num_ent = p->num_objects;
unsigned i;
const char *index = p->index_data;
- rix->revindex = xmalloc(sizeof(*rix->revindex) * (num_ent + 1));
+ ALLOC_ARRAY(p->revindex, num_ent + 1);
index += 4 * 256;
if (p->index_version > 1) {
for (i = 0; i < num_ent; i++) {
uint32_t off = ntohl(*off_32++);
if (!(off & 0x80000000)) {
- rix->revindex[i].offset = off;
+ p->revindex[i].offset = off;
} else {
- rix->revindex[i].offset =
+ p->revindex[i].offset =
((uint64_t)ntohl(*off_64++)) << 32;
- rix->revindex[i].offset |=
+ p->revindex[i].offset |=
ntohl(*off_64++);
}
- rix->revindex[i].nr = i;
+ p->revindex[i].nr = i;
}
} else {
for (i = 0; i < num_ent; i++) {
uint32_t hl = *((uint32_t *)(index + 24 * i));
- rix->revindex[i].offset = ntohl(hl);
- rix->revindex[i].nr = i;
+ p->revindex[i].offset = ntohl(hl);
+ p->revindex[i].nr = i;
}
}
/* This knows the pack format -- the 20-byte trailer
* follows immediately after the last object data.
*/
- rix->revindex[num_ent].offset = p->pack_size - 20;
- rix->revindex[num_ent].nr = -1;
- sort_revindex(rix->revindex, num_ent, p->pack_size);
+ p->revindex[num_ent].offset = p->pack_size - 20;
+ p->revindex[num_ent].nr = -1;
+ sort_revindex(p->revindex, num_ent, p->pack_size);
}
-struct pack_revindex *revindex_for_pack(struct packed_git *p)
+void load_pack_revindex(struct packed_git *p)
{
- int num;
- struct pack_revindex *rix;
-
- if (!pack_revindex_hashsz)
- init_pack_revindex();
-
- num = pack_revindex_ix(p);
- if (num < 0)
- die("internal error: pack revindex fubar");
-
- rix = &pack_revindex[num];
- if (!rix->revindex)
- create_pack_revindex(rix);
-
- return rix;
+ if (!p->revindex)
+ create_pack_revindex(p);
}
-int find_revindex_position(struct pack_revindex *pridx, off_t ofs)
+int find_revindex_position(struct packed_git *p, off_t ofs)
{
int lo = 0;
- int hi = pridx->p->num_objects + 1;
- struct revindex_entry *revindex = pridx->revindex;
+ int hi = p->num_objects + 1;
+ struct revindex_entry *revindex = p->revindex;
do {
unsigned mi = lo + (hi - lo) / 2;
struct revindex_entry *find_pack_revindex(struct packed_git *p, off_t ofs)
{
- struct pack_revindex *pridx = revindex_for_pack(p);
- int pos = find_revindex_position(pridx, ofs);
+ int pos;
+
+ load_pack_revindex(p);
+ pos = find_revindex_position(p, ofs);
if (pos < 0)
return NULL;
- return pridx->revindex + pos;
+ return p->revindex + pos;
}