Skip to content

Commit d56cdfe

Browse files
pks-tgitster
authored andcommitted
streaming: move logic to read packed objects streams into backend
Move the logic to read packed object streams into the respective subsystem. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent cd12826 commit d56cdfe

File tree

3 files changed

+134
-135
lines changed

3 files changed

+134
-135
lines changed

packfile.c

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "tree.h"
2121
#include "object-file.h"
2222
#include "odb.h"
23+
#include "streaming.h"
2324
#include "midx.h"
2425
#include "commit-graph.h"
2526
#include "pack-revindex.h"
@@ -2406,3 +2407,130 @@ void packfile_store_close(struct packfile_store *store)
24062407
close_pack(p);
24072408
}
24082409
}
2410+
2411+
struct odb_packed_read_stream {
2412+
struct odb_read_stream base;
2413+
struct packed_git *pack;
2414+
git_zstream z;
2415+
enum {
2416+
ODB_PACKED_READ_STREAM_UNINITIALIZED,
2417+
ODB_PACKED_READ_STREAM_INUSE,
2418+
ODB_PACKED_READ_STREAM_DONE,
2419+
ODB_PACKED_READ_STREAM_ERROR,
2420+
} z_state;
2421+
off_t pos;
2422+
};
2423+
2424+
static ssize_t read_istream_pack_non_delta(struct odb_read_stream *_st, char *buf,
2425+
size_t sz)
2426+
{
2427+
struct odb_packed_read_stream *st = (struct odb_packed_read_stream *)_st;
2428+
size_t total_read = 0;
2429+
2430+
switch (st->z_state) {
2431+
case ODB_PACKED_READ_STREAM_UNINITIALIZED:
2432+
memset(&st->z, 0, sizeof(st->z));
2433+
git_inflate_init(&st->z);
2434+
st->z_state = ODB_PACKED_READ_STREAM_INUSE;
2435+
break;
2436+
case ODB_PACKED_READ_STREAM_DONE:
2437+
return 0;
2438+
case ODB_PACKED_READ_STREAM_ERROR:
2439+
return -1;
2440+
case ODB_PACKED_READ_STREAM_INUSE:
2441+
break;
2442+
}
2443+
2444+
while (total_read < sz) {
2445+
int status;
2446+
struct pack_window *window = NULL;
2447+
unsigned char *mapped;
2448+
2449+
mapped = use_pack(st->pack, &window,
2450+
st->pos, &st->z.avail_in);
2451+
2452+
st->z.next_out = (unsigned char *)buf + total_read;
2453+
st->z.avail_out = sz - total_read;
2454+
st->z.next_in = mapped;
2455+
status = git_inflate(&st->z, Z_FINISH);
2456+
2457+
st->pos += st->z.next_in - mapped;
2458+
total_read = st->z.next_out - (unsigned char *)buf;
2459+
unuse_pack(&window);
2460+
2461+
if (status == Z_STREAM_END) {
2462+
git_inflate_end(&st->z);
2463+
st->z_state = ODB_PACKED_READ_STREAM_DONE;
2464+
break;
2465+
}
2466+
2467+
/*
2468+
* Unlike the loose object case, we do not have to worry here
2469+
* about running out of input bytes and spinning infinitely. If
2470+
* we get Z_BUF_ERROR due to too few input bytes, then we'll
2471+
* replenish them in the next use_pack() call when we loop. If
2472+
* we truly hit the end of the pack (i.e., because it's corrupt
2473+
* or truncated), then use_pack() catches that and will die().
2474+
*/
2475+
if (status != Z_OK && status != Z_BUF_ERROR) {
2476+
git_inflate_end(&st->z);
2477+
st->z_state = ODB_PACKED_READ_STREAM_ERROR;
2478+
return -1;
2479+
}
2480+
}
2481+
return total_read;
2482+
}
2483+
2484+
static int close_istream_pack_non_delta(struct odb_read_stream *_st)
2485+
{
2486+
struct odb_packed_read_stream *st = (struct odb_packed_read_stream *)_st;
2487+
if (st->z_state == ODB_PACKED_READ_STREAM_INUSE)
2488+
git_inflate_end(&st->z);
2489+
return 0;
2490+
}
2491+
2492+
int packfile_store_read_object_stream(struct odb_read_stream **out,
2493+
struct packfile_store *store,
2494+
const struct object_id *oid)
2495+
{
2496+
struct odb_packed_read_stream *stream;
2497+
struct pack_window *window = NULL;
2498+
struct object_info oi = OBJECT_INFO_INIT;
2499+
enum object_type in_pack_type;
2500+
unsigned long size;
2501+
2502+
oi.sizep = &size;
2503+
2504+
if (packfile_store_read_object_info(store, oid, &oi, 0) ||
2505+
oi.u.packed.is_delta ||
2506+
repo_settings_get_big_file_threshold(store->odb->repo) >= size)
2507+
return -1;
2508+
2509+
in_pack_type = unpack_object_header(oi.u.packed.pack,
2510+
&window,
2511+
&oi.u.packed.offset,
2512+
&size);
2513+
unuse_pack(&window);
2514+
switch (in_pack_type) {
2515+
default:
2516+
return -1; /* we do not do deltas for now */
2517+
case OBJ_COMMIT:
2518+
case OBJ_TREE:
2519+
case OBJ_BLOB:
2520+
case OBJ_TAG:
2521+
break;
2522+
}
2523+
2524+
CALLOC_ARRAY(stream, 1);
2525+
stream->base.close = close_istream_pack_non_delta;
2526+
stream->base.read = read_istream_pack_non_delta;
2527+
stream->base.type = in_pack_type;
2528+
stream->base.size = size;
2529+
stream->z_state = ODB_PACKED_READ_STREAM_UNINITIALIZED;
2530+
stream->pack = oi.u.packed.pack;
2531+
stream->pos = oi.u.packed.offset;
2532+
2533+
*out = &stream->base;
2534+
2535+
return 0;
2536+
}

packfile.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
/* in odb.h */
1010
struct object_info;
11+
struct odb_read_stream;
1112

1213
struct packed_git {
1314
struct hashmap_entry packmap_ent;
@@ -144,6 +145,10 @@ void packfile_store_add_pack(struct packfile_store *store,
144145
#define repo_for_each_pack(repo, p) \
145146
for (p = packfile_store_get_packs(repo->objects->packfiles); p; p = p->next)
146147

148+
int packfile_store_read_object_stream(struct odb_read_stream **out,
149+
struct packfile_store *store,
150+
const struct object_id *oid);
151+
147152
/*
148153
* Try to read the object identified by its ID from the object store and
149154
* populate the object info with its data. Returns 1 in case the object was

streaming.c

Lines changed: 1 addition & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -114,140 +114,6 @@ static struct odb_read_stream *attach_stream_filter(struct odb_read_stream *st,
114114
return &fs->base;
115115
}
116116

117-
/*****************************************************************
118-
*
119-
* Non-delta packed object stream
120-
*
121-
*****************************************************************/
122-
123-
struct odb_packed_read_stream {
124-
struct odb_read_stream base;
125-
struct packed_git *pack;
126-
git_zstream z;
127-
enum {
128-
ODB_PACKED_READ_STREAM_UNINITIALIZED,
129-
ODB_PACKED_READ_STREAM_INUSE,
130-
ODB_PACKED_READ_STREAM_DONE,
131-
ODB_PACKED_READ_STREAM_ERROR,
132-
} z_state;
133-
off_t pos;
134-
};
135-
136-
static ssize_t read_istream_pack_non_delta(struct odb_read_stream *_st, char *buf,
137-
size_t sz)
138-
{
139-
struct odb_packed_read_stream *st = (struct odb_packed_read_stream *)_st;
140-
size_t total_read = 0;
141-
142-
switch (st->z_state) {
143-
case ODB_PACKED_READ_STREAM_UNINITIALIZED:
144-
memset(&st->z, 0, sizeof(st->z));
145-
git_inflate_init(&st->z);
146-
st->z_state = ODB_PACKED_READ_STREAM_INUSE;
147-
break;
148-
case ODB_PACKED_READ_STREAM_DONE:
149-
return 0;
150-
case ODB_PACKED_READ_STREAM_ERROR:
151-
return -1;
152-
case ODB_PACKED_READ_STREAM_INUSE:
153-
break;
154-
}
155-
156-
while (total_read < sz) {
157-
int status;
158-
struct pack_window *window = NULL;
159-
unsigned char *mapped;
160-
161-
mapped = use_pack(st->pack, &window,
162-
st->pos, &st->z.avail_in);
163-
164-
st->z.next_out = (unsigned char *)buf + total_read;
165-
st->z.avail_out = sz - total_read;
166-
st->z.next_in = mapped;
167-
status = git_inflate(&st->z, Z_FINISH);
168-
169-
st->pos += st->z.next_in - mapped;
170-
total_read = st->z.next_out - (unsigned char *)buf;
171-
unuse_pack(&window);
172-
173-
if (status == Z_STREAM_END) {
174-
git_inflate_end(&st->z);
175-
st->z_state = ODB_PACKED_READ_STREAM_DONE;
176-
break;
177-
}
178-
179-
/*
180-
* Unlike the loose object case, we do not have to worry here
181-
* about running out of input bytes and spinning infinitely. If
182-
* we get Z_BUF_ERROR due to too few input bytes, then we'll
183-
* replenish them in the next use_pack() call when we loop. If
184-
* we truly hit the end of the pack (i.e., because it's corrupt
185-
* or truncated), then use_pack() catches that and will die().
186-
*/
187-
if (status != Z_OK && status != Z_BUF_ERROR) {
188-
git_inflate_end(&st->z);
189-
st->z_state = ODB_PACKED_READ_STREAM_ERROR;
190-
return -1;
191-
}
192-
}
193-
return total_read;
194-
}
195-
196-
static int close_istream_pack_non_delta(struct odb_read_stream *_st)
197-
{
198-
struct odb_packed_read_stream *st = (struct odb_packed_read_stream *)_st;
199-
if (st->z_state == ODB_PACKED_READ_STREAM_INUSE)
200-
git_inflate_end(&st->z);
201-
return 0;
202-
}
203-
204-
static int open_istream_pack_non_delta(struct odb_read_stream **out,
205-
struct object_database *odb,
206-
const struct object_id *oid)
207-
{
208-
struct odb_packed_read_stream *stream;
209-
struct pack_window *window = NULL;
210-
struct object_info oi = OBJECT_INFO_INIT;
211-
enum object_type in_pack_type;
212-
unsigned long size;
213-
214-
oi.sizep = &size;
215-
216-
if (packfile_store_read_object_info(odb->packfiles, oid, &oi, 0) ||
217-
oi.u.packed.is_delta ||
218-
repo_settings_get_big_file_threshold(odb->repo) >= size)
219-
return -1;
220-
221-
in_pack_type = unpack_object_header(oi.u.packed.pack,
222-
&window,
223-
&oi.u.packed.offset,
224-
&size);
225-
unuse_pack(&window);
226-
switch (in_pack_type) {
227-
default:
228-
return -1; /* we do not do deltas for now */
229-
case OBJ_COMMIT:
230-
case OBJ_TREE:
231-
case OBJ_BLOB:
232-
case OBJ_TAG:
233-
break;
234-
}
235-
236-
CALLOC_ARRAY(stream, 1);
237-
stream->base.close = close_istream_pack_non_delta;
238-
stream->base.read = read_istream_pack_non_delta;
239-
stream->base.type = in_pack_type;
240-
stream->base.size = size;
241-
stream->z_state = ODB_PACKED_READ_STREAM_UNINITIALIZED;
242-
stream->pack = oi.u.packed.pack;
243-
stream->pos = oi.u.packed.offset;
244-
245-
*out = &stream->base;
246-
247-
return 0;
248-
}
249-
250-
251117
/*****************************************************************
252118
*
253119
* In-core stream
@@ -319,7 +185,7 @@ static int istream_source(struct odb_read_stream **out,
319185
{
320186
struct odb_source *source;
321187

322-
if (!open_istream_pack_non_delta(out, r->objects, oid))
188+
if (!packfile_store_read_object_stream(out, r->objects->packfiles, oid))
323189
return 0;
324190

325191
odb_prepare_alternates(r->objects);

0 commit comments

Comments
 (0)