streaming: move zlib stream into backends
While all backend-specific data is now contained in a backend-specific structure, we still share the zlib stream across the loose and packed objects. Refactor the code and move it into the specific structures so that we fully detangle the different backends from one another. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Nov 23, 2025 at 19:59 UTC
eb5abbb4e6a8c06f5c6275bbb541bf7d736171c5
1 file changed
+52
-52
streaming.c
+52
-52
@@ -25,23 +25,8 @@ struct odb_read_stream {
25
26
enum object_type type;
27
unsigned long size; /* inflated size of full object */
28
- git_zstream z;
29
- enum { z_unused, z_used, z_done, z_error } z_state;
28
};
29
32
-/*****************************************************************
33
- *
34
- * Common helpers
35
- *
36
- *****************************************************************/
37
-
38
-static void close_deflated_stream(struct odb_read_stream *st)
39
-{
40
- if (st->z_state == z_used)
41
- git_inflate_end(&st->z);
42
-}
43
-
44
-
30
/*****************************************************************
31
*
32
* Filtered stream
@@ -150,6 +135,12 @@ static struct odb_read_stream *attach_stream_filter(struct odb_read_stream *st,
135
136
struct odb_loose_read_stream {
137
struct odb_read_stream base;
138
+ git_zstream z;
139
+ enum {
140
+ ODB_LOOSE_READ_STREAM_INUSE,
141
+ ODB_LOOSE_READ_STREAM_DONE,
142
+ ODB_LOOSE_READ_STREAM_ERROR,
143
+ } z_state;
144
void *mapped;
145
unsigned long mapsize;
146
char hdr[32];
@@ -162,10 +153,10 @@ static ssize_t read_istream_loose(struct odb_read_stream *_st, char *buf, size_t
153
struct odb_loose_read_stream *st = (struct odb_loose_read_stream *)_st;
154
size_t total_read = 0;
155
165
- switch (st->base.z_state) {
166
- case z_done:
156
+ switch (st->z_state) {
157
+ case ODB_LOOSE_READ_STREAM_DONE:
158
return 0;
168
- case z_error:
159
+ case ODB_LOOSE_READ_STREAM_ERROR:
160
return -1;
161
default:
162
break;
@@ -183,20 +174,20 @@ static ssize_t read_istream_loose(struct odb_read_stream *_st, char *buf, size_t
174
while (total_read < sz) {
175
int status;
176
186
- st->base.z.next_out = (unsigned char *)buf + total_read;
187
- st->base.z.avail_out = sz - total_read;
188
- status = git_inflate(&st->base.z, Z_FINISH);
177
+ st->z.next_out = (unsigned char *)buf + total_read;
178
+ st->z.avail_out = sz - total_read;
179
+ status = git_inflate(&st->z, Z_FINISH);
180
190
- total_read = st->base.z.next_out - (unsigned char *)buf;
181
+ total_read = st->z.next_out - (unsigned char *)buf;
182
183
if (status == Z_STREAM_END) {
193
- git_inflate_end(&st->base.z);
194
- st->base.z_state = z_done;
184
+ git_inflate_end(&st->z);
185
+ st->z_state = ODB_LOOSE_READ_STREAM_DONE;
186
break;
187
}
188
if (status != Z_OK && (status != Z_BUF_ERROR || total_read < sz)) {
198
- git_inflate_end(&st->base.z);
199
- st->base.z_state = z_error;
189
+ git_inflate_end(&st->z);
190
+ st->z_state = ODB_LOOSE_READ_STREAM_ERROR;
191
return -1;
192
}
193
}
@@ -206,7 +197,8 @@ static ssize_t read_istream_loose(struct odb_read_stream *_st, char *buf, size_t
197
static int close_istream_loose(struct odb_read_stream *_st)
198
{
199
struct odb_loose_read_stream *st = (struct odb_loose_read_stream *)_st;
209
- close_deflated_stream(&st->base);
200
+ if (st->z_state == ODB_LOOSE_READ_STREAM_INUSE)
201
+ git_inflate_end(&st->z);
202
munmap(st->mapped, st->mapsize);
203
return 0;
204
}
@@ -238,7 +230,7 @@ static int open_istream_loose(struct odb_read_stream **out,
230
*/
231
CALLOC_ARRAY(st, 1);
232
241
- switch (unpack_loose_header(&st->base.z, mapped, mapsize, st->hdr,
233
+ switch (unpack_loose_header(&st->z, mapped, mapsize, st->hdr,
234
sizeof(st->hdr))) {
235
case ULHR_OK:
236
break;
@@ -256,8 +248,8 @@ static int open_istream_loose(struct odb_read_stream **out,
248
st->mapped = mapped;
249
st->mapsize = mapsize;
250
st->hdr_used = strlen(st->hdr) + 1;
259
- st->hdr_avail = st->base.z.total_out;
260
- st->base.z_state = z_used;
251
+ st->hdr_avail = st->z.total_out;
252
+ st->z_state = ODB_LOOSE_READ_STREAM_INUSE;
253
st->base.close = close_istream_loose;
254
st->base.read = read_istream_loose;
255
@@ -265,7 +257,7 @@ static int open_istream_loose(struct odb_read_stream **out,
257
258
return 0;
259
error:
268
- git_inflate_end(&st->base.z);
260
+ git_inflate_end(&st->z);
261
munmap(st->mapped, st->mapsize);
262
free(st);
263
return -1;
@@ -281,6 +273,13 @@ error:
273
struct odb_packed_read_stream {
274
struct odb_read_stream base;
275
struct packed_git *pack;
276
+ git_zstream z;
277
+ enum {
278
+ ODB_PACKED_READ_STREAM_UNINITIALIZED,
279
+ ODB_PACKED_READ_STREAM_INUSE,
280
+ ODB_PACKED_READ_STREAM_DONE,
281
+ ODB_PACKED_READ_STREAM_ERROR,
282
+ } z_state;
283
off_t pos;
284
};
285
@@ -290,17 +289,17 @@ static ssize_t read_istream_pack_non_delta(struct odb_read_stream *_st, char *bu
289
struct odb_packed_read_stream *st = (struct odb_packed_read_stream *)_st;
290
size_t total_read = 0;
291
293
- switch (st->base.z_state) {
294
- case z_unused:
295
- memset(&st->base.z, 0, sizeof(st->base.z));
296
- git_inflate_init(&st->base.z);
297
- st->base.z_state = z_used;
292
+ switch (st->z_state) {
293
+ case ODB_PACKED_READ_STREAM_UNINITIALIZED:
294
+ memset(&st->z, 0, sizeof(st->z));
295
+ git_inflate_init(&st->z);
296
+ st->z_state = ODB_PACKED_READ_STREAM_INUSE;
297
break;
299
- case z_done:
298
+ case ODB_PACKED_READ_STREAM_DONE:
299
return 0;
301
- case z_error:
300
+ case ODB_PACKED_READ_STREAM_ERROR:
301
return -1;
303
- case z_used:
302
+ case ODB_PACKED_READ_STREAM_INUSE:
303
break;
304
}
305
@@ -310,20 +309,20 @@ static ssize_t read_istream_pack_non_delta(struct odb_read_stream *_st, char *bu
309
unsigned char *mapped;
310
311
mapped = use_pack(st->pack, &window,
313
- st->pos, &st->base.z.avail_in);
312
+ st->pos, &st->z.avail_in);
313
315
- st->base.z.next_out = (unsigned char *)buf + total_read;
316
- st->base.z.avail_out = sz - total_read;
317
- st->base.z.next_in = mapped;
318
- status = git_inflate(&st->base.z, Z_FINISH);
314
+ st->z.next_out = (unsigned char *)buf + total_read;
315
+ st->z.avail_out = sz - total_read;
316
+ st->z.next_in = mapped;
317
+ status = git_inflate(&st->z, Z_FINISH);
318
320
- st->pos += st->base.z.next_in - mapped;
321
- total_read = st->base.z.next_out - (unsigned char *)buf;
319
+ st->pos += st->z.next_in - mapped;
320
+ total_read = st->z.next_out - (unsigned char *)buf;
321
unuse_pack(&window);
322
323
if (status == Z_STREAM_END) {
325
- git_inflate_end(&st->base.z);
326
- st->base.z_state = z_done;
324
+ git_inflate_end(&st->z);
325
+ st->z_state = ODB_PACKED_READ_STREAM_DONE;
326
break;
327
}
328
@@ -336,8 +335,8 @@ static ssize_t read_istream_pack_non_delta(struct odb_read_stream *_st, char *bu
335
* or truncated), then use_pack() catches that and will die().
336
*/
337
if (status != Z_OK && status != Z_BUF_ERROR) {
339
- git_inflate_end(&st->base.z);
340
- st->base.z_state = z_error;
338
+ git_inflate_end(&st->z);
339
+ st->z_state = ODB_PACKED_READ_STREAM_ERROR;
340
return -1;
341
}
342
}
@@ -347,7 +346,8 @@ static ssize_t read_istream_pack_non_delta(struct odb_read_stream *_st, char *bu
346
static int close_istream_pack_non_delta(struct odb_read_stream *_st)
347
{
348
struct odb_packed_read_stream *st = (struct odb_packed_read_stream *)_st;
350
- close_deflated_stream(&st->base);
349
+ if (st->z_state == ODB_PACKED_READ_STREAM_INUSE)
350
+ git_inflate_end(&st->z);
351
return 0;
352
}
353
@@ -384,7 +384,7 @@ static int open_istream_pack_non_delta(struct odb_read_stream **out,
384
stream->base.read = read_istream_pack_non_delta;
385
stream->base.type = in_pack_type;
386
stream->base.size = size;
387
- stream->base.z_state = z_unused;
387
+ stream->z_state = ODB_PACKED_READ_STREAM_UNINITIALIZED;
388
stream->pack = pack;
389
stream->pos = offset;
390