streaming: read loose objects incrementally
Helped-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano committed
May 14, 2011 at 19:17 UTC
93aa7bd595d37aec09b96da7ea9da89d9f659ebd
1 file changed
+82
-3
streaming.c
+82
-3
@@ -61,8 +61,11 @@ struct git_istream {
61
} incore;
62
63
struct {
64
- int fd; /* open for reading */
65
- /* NEEDSWORK: what else? */
64
+ void *mapped;
65
+ unsigned long mapsize;
66
+ char hdr[32];
67
+ int hdr_avail;
68
+ int hdr_used;
69
} loose;
70
71
struct {
@@ -150,9 +153,85 @@ static void close_deflated_stream(struct git_istream *st)
153
*
154
*****************************************************************/
155
156
+static read_method_decl(loose)
157
+{
158
+ size_t total_read = 0;
159
+
160
+ switch (st->z_state) {
161
+ case z_done:
162
+ return 0;
163
+ case z_error:
164
+ return -1;
165
+ default:
166
+ break;
167
+ }
168
+
169
+ if (st->u.loose.hdr_used < st->u.loose.hdr_avail) {
170
+ size_t to_copy = st->u.loose.hdr_avail - st->u.loose.hdr_used;
171
+ if (sz < to_copy)
172
+ to_copy = sz;
173
+ memcpy(buf, st->u.loose.hdr + st->u.loose.hdr_used, to_copy);
174
+ st->u.loose.hdr_used += to_copy;
175
+ total_read += to_copy;
176
+ }
177
+
178
+ while (total_read < sz) {
179
+ int status;
180
+
181
+ st->z.next_out = (unsigned char *)buf + total_read;
182
+ st->z.avail_out = sz - total_read;
183
+ status = git_inflate(&st->z, Z_FINISH);
184
+
185
+ total_read = st->z.next_out - (unsigned char *)buf;
186
+
187
+ if (status == Z_STREAM_END) {
188
+ git_inflate_end(&st->z);
189
+ st->z_state = z_done;
190
+ break;
191
+ }
192
+ if (status != Z_OK && status != Z_BUF_ERROR) {
193
+ git_inflate_end(&st->z);
194
+ st->z_state = z_error;
195
+ return -1;
196
+ }
197
+ }
198
+ return total_read;
199
+}
200
+
201
+static close_method_decl(loose)
202
+{
203
+ close_deflated_stream(st);
204
+ munmap(st->u.loose.mapped, st->u.loose.mapsize);
205
+ return 0;
206
+}
207
+
208
+static struct stream_vtbl loose_vtbl = {
209
+ close_istream_loose,
210
+ read_istream_loose,
211
+};
212
+
213
static open_method_decl(loose)
214
{
155
- return -1; /* for now */
215
+ st->u.loose.mapped = map_sha1_file(sha1, &st->u.loose.mapsize);
216
+ if (!st->u.loose.mapped)
217
+ return -1;
218
+ if (unpack_sha1_header(&st->z,
219
+ st->u.loose.mapped,
220
+ st->u.loose.mapsize,
221
+ st->u.loose.hdr,
222
+ sizeof(st->u.loose.hdr)) < 0) {
223
+ git_inflate_end(&st->z);
224
+ munmap(st->u.loose.mapped, st->u.loose.mapsize);
225
+ return -1;
226
+ }
227
+
228
+ parse_sha1_header(st->u.loose.hdr, &st->size);
229
+ st->u.loose.hdr_used = strlen(st->u.loose.hdr) + 1;
230
+ st->u.loose.hdr_avail = st->z.total_out;
231
+ st->z_state = z_used;
232
+
233
+ st->vtbl = &loose_vtbl;
234
+ return 0;
235
}
236
237