@matheusbsbs / matheus-bagliano / commits / 3449f8c4cb
Fork 0

factorize revindex code out of builtin-pack-objects.c

No functional change. This is needed to fix verify-pack in a later patch. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nicolas Pitre committed Feb 28, 2008 at 00:25 UTC 3449f8c4cb93a0ec445db22ee7549d0b051446d6
4 files changed +167 -152
Makefile
+3 -2
@@ -304,7 +304,8 @@ LIB_H = \
304 run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
305 tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
306 utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \
307 - mailmap.h remote.h parse-options.h transport.h diffcore.h hash.h
307 + mailmap.h remote.h parse-options.h transport.h diffcore.h hash.h \
308 + pack-revindex.h
309
310 DIFF_OBJS = \
311 diff.o diff-lib.o diffcore-break.o diffcore-order.o \
@@ -328,7 +329,7 @@ LIB_OBJS = \
329 color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
330 convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \
331 transport.o bundle.o walker.o parse-options.o ws.o archive.o branch.o \
331 - alias.o
332 + alias.o pack-revindex.o
333
334 BUILTIN_OBJS = \
335 builtin-add.o \
builtin-pack-objects.c
+10 -150
@@ -8,6 +8,7 @@
8 #include "tree.h"
9 #include "delta.h"
10 #include "pack.h"
11 +#include "pack-revindex.h"
12 #include "csum-file.h"
13 #include "tree-walk.h"
14 #include "diff.h"
@@ -92,158 +93,12 @@ static unsigned long window_memory_limit = 0;
93 static int *object_ix;
94 static int object_ix_hashsz;
95
95 -/*
96 - * Pack index for existing packs give us easy access to the offsets into
97 - * corresponding pack file where each object's data starts, but the entries
98 - * do not store the size of the compressed representation (uncompressed
99 - * size is easily available by examining the pack entry header). It is
100 - * also rather expensive to find the sha1 for an object given its offset.
101 - *
102 - * We build a hashtable of existing packs (pack_revindex), and keep reverse
103 - * index here -- pack index file is sorted by object name mapping to offset;
104 - * this pack_revindex[].revindex array is a list of offset/index_nr pairs
105 - * ordered by offset, so if you know the offset of an object, next offset
106 - * is where its packed representation ends and the index_nr can be used to
107 - * get the object sha1 from the main index.
108 - */
109 -struct revindex_entry {
110 - off_t offset;
111 - unsigned int nr;
112 -};
113 -struct pack_revindex {
114 - struct packed_git *p;
115 - struct revindex_entry *revindex;
116 -};
117 -static struct pack_revindex *pack_revindex;
118 -static int pack_revindex_hashsz;
119 -
96 /*
97 * stats
98 */
99 static uint32_t written, written_delta;
100 static uint32_t reused, reused_delta;
101
126 -static int pack_revindex_ix(struct packed_git *p)
127 -{
128 - unsigned long ui = (unsigned long)p;
129 - int i;
130 -
131 - ui = ui ^ (ui >> 16); /* defeat structure alignment */
132 - i = (int)(ui % pack_revindex_hashsz);
133 - while (pack_revindex[i].p) {
134 - if (pack_revindex[i].p == p)
135 - return i;
136 - if (++i == pack_revindex_hashsz)
137 - i = 0;
138 - }
139 - return -1 - i;
140 -}
141 -
142 -static void prepare_pack_ix(void)
143 -{
144 - int num;
145 - struct packed_git *p;
146 - for (num = 0, p = packed_git; p; p = p->next)
147 - num++;
148 - if (!num)
149 - return;
150 - pack_revindex_hashsz = num * 11;
151 - pack_revindex = xcalloc(sizeof(*pack_revindex), pack_revindex_hashsz);
152 - for (p = packed_git; p; p = p->next) {
153 - num = pack_revindex_ix(p);
154 - num = - 1 - num;
155 - pack_revindex[num].p = p;
156 - }
157 - /* revindex elements are lazily initialized */
158 -}
159 -
160 -static int cmp_offset(const void *a_, const void *b_)
161 -{
162 - const struct revindex_entry *a = a_;
163 - const struct revindex_entry *b = b_;
164 - return (a->offset < b->offset) ? -1 : (a->offset > b->offset) ? 1 : 0;
165 -}
166 -
167 -/*
168 - * Ordered list of offsets of objects in the pack.
169 - */
170 -static void prepare_pack_revindex(struct pack_revindex *rix)
171 -{
172 - struct packed_git *p = rix->p;
173 - int num_ent = p->num_objects;
174 - int i;
175 - const char *index = p->index_data;
176 -
177 - rix->revindex = xmalloc(sizeof(*rix->revindex) * (num_ent + 1));
178 - index += 4 * 256;
179 -
180 - if (p->index_version > 1) {
181 - const uint32_t *off_32 =
182 - (uint32_t *)(index + 8 + p->num_objects * (20 + 4));
183 - const uint32_t *off_64 = off_32 + p->num_objects;
184 - for (i = 0; i < num_ent; i++) {
185 - uint32_t off = ntohl(*off_32++);
186 - if (!(off & 0x80000000)) {
187 - rix->revindex[i].offset = off;
188 - } else {
189 - rix->revindex[i].offset =
190 - ((uint64_t)ntohl(*off_64++)) << 32;
191 - rix->revindex[i].offset |=
192 - ntohl(*off_64++);
193 - }
194 - rix->revindex[i].nr = i;
195 - }
196 - } else {
197 - for (i = 0; i < num_ent; i++) {
198 - uint32_t hl = *((uint32_t *)(index + 24 * i));
199 - rix->revindex[i].offset = ntohl(hl);
200 - rix->revindex[i].nr = i;
201 - }
202 - }
203 -
204 - /* This knows the pack format -- the 20-byte trailer
205 - * follows immediately after the last object data.
206 - */
207 - rix->revindex[num_ent].offset = p->pack_size - 20;
208 - rix->revindex[num_ent].nr = -1;
209 - qsort(rix->revindex, num_ent, sizeof(*rix->revindex), cmp_offset);
210 -}
211 -
212 -static struct revindex_entry * find_packed_object(struct packed_git *p,
213 - off_t ofs)
214 -{
215 - int num;
216 - int lo, hi;
217 - struct pack_revindex *rix;
218 - struct revindex_entry *revindex;
219 - num = pack_revindex_ix(p);
220 - if (num < 0)
221 - die("internal error: pack revindex uninitialized");
222 - rix = &pack_revindex[num];
223 - if (!rix->revindex)
224 - prepare_pack_revindex(rix);
225 - revindex = rix->revindex;
226 - lo = 0;
227 - hi = p->num_objects + 1;
228 - do {
229 - int mi = (lo + hi) / 2;
230 - if (revindex[mi].offset == ofs) {
231 - return revindex + mi;
232 - }
233 - else if (ofs < revindex[mi].offset)
234 - hi = mi;
235 - else
236 - lo = mi + 1;
237 - } while (lo < hi);
238 - die("internal error: pack revindex corrupt");
239 -}
240 -
241 -static const unsigned char *find_packed_object_name(struct packed_git *p,
242 - off_t ofs)
243 -{
244 - struct revindex_entry *entry = find_packed_object(p, ofs);
245 - return nth_packed_object_sha1(p, entry->nr);
246 -}
102
103 static void *delta_against(void *buf, unsigned long size, struct object_entry *entry)
104 {
@@ -510,7 +365,7 @@ static unsigned long write_object(struct sha1file *f,
365 }
366 hdrlen = encode_header(obj_type, entry->size, header);
367 offset = entry->in_pack_offset;
513 - revidx = find_packed_object(p, offset);
368 + revidx = find_pack_revindex(p, offset);
369 datalen = revidx[1].offset - offset;
370 if (!pack_to_stdout && p->index_version > 1 &&
371 check_pack_crc(p, &w_curs, offset, datalen, revidx->nr))
@@ -1162,8 +1017,11 @@ static void check_object(struct object_entry *entry)
1017 die("delta base offset out of bound for %s",
1018 sha1_to_hex(entry->idx.sha1));
1019 ofs = entry->in_pack_offset - ofs;
1165 - if (!no_reuse_delta && !entry->preferred_base)
1166 - base_ref = find_packed_object_name(p, ofs);
1020 + if (!no_reuse_delta && !entry->preferred_base) {
1021 + struct revindex_entry *revidx;
1022 + revidx = find_pack_revindex(p, ofs);
1023 + base_ref = nth_packed_object_sha1(p, revidx->nr);
1024 + }
1025 entry->in_pack_header_size = used + used_0;
1026 break;
1027 }
@@ -1240,9 +1098,11 @@ static void get_object_details(void)
1098 sorted_by_offset[i] = objects + i;
1099 qsort(sorted_by_offset, nr_objects, sizeof(*sorted_by_offset), pack_offset_sort);
1100
1243 - prepare_pack_ix();
1101 + init_pack_revindex();
1102 +
1103 for (i = 0; i < nr_objects; i++)
1104 check_object(sorted_by_offset[i]);
1105 +
1106 free(sorted_by_offset);
1107 }
1108
pack-revindex.c new
+142
@@ -0,0 +1,142 @@
1 +#include "cache.h"
2 +#include "pack-revindex.h"
3 +
4 +/*
5 + * Pack index for existing packs give us easy access to the offsets into
6 + * corresponding pack file where each object's data starts, but the entries
7 + * do not store the size of the compressed representation (uncompressed
8 + * size is easily available by examining the pack entry header). It is
9 + * also rather expensive to find the sha1 for an object given its offset.
10 + *
11 + * We build a hashtable of existing packs (pack_revindex), and keep reverse
12 + * index here -- pack index file is sorted by object name mapping to offset;
13 + * this pack_revindex[].revindex array is a list of offset/index_nr pairs
14 + * ordered by offset, so if you know the offset of an object, next offset
15 + * is where its packed representation ends and the index_nr can be used to
16 + * get the object sha1 from the main index.
17 + */
18 +
19 +struct pack_revindex {
20 + struct packed_git *p;
21 + struct revindex_entry *revindex;
22 +};
23 +
24 +static struct pack_revindex *pack_revindex;
25 +static int pack_revindex_hashsz;
26 +
27 +static int pack_revindex_ix(struct packed_git *p)
28 +{
29 + unsigned long ui = (unsigned long)p;
30 + int i;
31 +
32 + ui = ui ^ (ui >> 16); /* defeat structure alignment */
33 + i = (int)(ui % pack_revindex_hashsz);
34 + while (pack_revindex[i].p) {
35 + if (pack_revindex[i].p == p)
36 + return i;
37 + if (++i == pack_revindex_hashsz)
38 + i = 0;
39 + }
40 + return -1 - i;
41 +}
42 +
43 +void init_pack_revindex(void)
44 +{
45 + int num;
46 + struct packed_git *p;
47 +
48 + for (num = 0, p = packed_git; p; p = p->next)
49 + num++;
50 + if (!num)
51 + return;
52 + pack_revindex_hashsz = num * 11;
53 + pack_revindex = xcalloc(sizeof(*pack_revindex), pack_revindex_hashsz);
54 + for (p = packed_git; p; p = p->next) {
55 + num = pack_revindex_ix(p);
56 + num = - 1 - num;
57 + pack_revindex[num].p = p;
58 + }
59 + /* revindex elements are lazily initialized */
60 +}
61 +
62 +static int cmp_offset(const void *a_, const void *b_)
63 +{
64 + const struct revindex_entry *a = a_;
65 + const struct revindex_entry *b = b_;
66 + return (a->offset < b->offset) ? -1 : (a->offset > b->offset) ? 1 : 0;
67 +}
68 +
69 +/*
70 + * Ordered list of offsets of objects in the pack.
71 + */
72 +static void create_pack_revindex(struct pack_revindex *rix)
73 +{
74 + struct packed_git *p = rix->p;
75 + int num_ent = p->num_objects;
76 + int i;
77 + const char *index = p->index_data;
78 +
79 + rix->revindex = xmalloc(sizeof(*rix->revindex) * (num_ent + 1));
80 + index += 4 * 256;
81 +
82 + if (p->index_version > 1) {
83 + const uint32_t *off_32 =
84 + (uint32_t *)(index + 8 + p->num_objects * (20 + 4));
85 + const uint32_t *off_64 = off_32 + p->num_objects;
86 + for (i = 0; i < num_ent; i++) {
87 + uint32_t off = ntohl(*off_32++);
88 + if (!(off & 0x80000000)) {
89 + rix->revindex[i].offset = off;
90 + } else {
91 + rix->revindex[i].offset =
92 + ((uint64_t)ntohl(*off_64++)) << 32;
93 + rix->revindex[i].offset |=
94 + ntohl(*off_64++);
95 + }
96 + rix->revindex[i].nr = i;
97 + }
98 + } else {
99 + for (i = 0; i < num_ent; i++) {
100 + uint32_t hl = *((uint32_t *)(index + 24 * i));
101 + rix->revindex[i].offset = ntohl(hl);
102 + rix->revindex[i].nr = i;
103 + }
104 + }
105 +
106 + /* This knows the pack format -- the 20-byte trailer
107 + * follows immediately after the last object data.
108 + */
109 + rix->revindex[num_ent].offset = p->pack_size - 20;
110 + rix->revindex[num_ent].nr = -1;
111 + qsort(rix->revindex, num_ent, sizeof(*rix->revindex), cmp_offset);
112 +}
113 +
114 +struct revindex_entry *find_pack_revindex(struct packed_git *p, off_t ofs)
115 +{
116 + int num;
117 + int lo, hi;
118 + struct pack_revindex *rix;
119 + struct revindex_entry *revindex;
120 +
121 + num = pack_revindex_ix(p);
122 + if (num < 0)
123 + die("internal error: pack revindex uninitialized");
124 +
125 + rix = &pack_revindex[num];
126 + if (!rix->revindex)
127 + create_pack_revindex(rix);
128 + revindex = rix->revindex;
129 +
130 + lo = 0;
131 + hi = p->num_objects + 1;
132 + do {
133 + int mi = (lo + hi) / 2;
134 + if (revindex[mi].offset == ofs) {
135 + return revindex + mi;
136 + } else if (ofs < revindex[mi].offset)
137 + hi = mi;
138 + else
139 + lo = mi + 1;
140 + } while (lo < hi);
141 + die("internal error: pack revindex corrupt");
142 +}
pack-revindex.h new
+12
@@ -0,0 +1,12 @@
1 +#ifndef PACK_REVINDEX_H
2 +#define PACK_REVINDEX_H
3 +
4 +struct revindex_entry {
5 + off_t offset;
6 + unsigned int nr;
7 +};
8 +
9 +void init_pack_revindex(void);
10 +struct revindex_entry *find_pack_revindex(struct packed_git *p, off_t ofs);
11 +
12 +#endif