Skip to content

Commit 4c89d31

Browse files
pks-tgitster
authored andcommitted
streaming: rely on object sources to create object stream
When creating an object stream we first look up the object info and, if it's present, we call into the respective backend that contains the object to create a new stream for it. This has the consequence that, for loose object source, we basically iterate through the object sources twice: we first discover that the file exists as a loose object in the first place by iterating through all sources. And, once we have discovered it, we again walk through all sources to try and map the object. The same issue will eventually also surface once the packfile store becomes per-object-source. Furthermore, it feels rather pointless to first look up the object only to then try and read it. Refactor the logic to be centered around sources instead. Instead of first reading the object, we immediately ask the source to create the object stream for us. If the object exists we get stream, otherwise we'll try the next source. Like this we only have to iterate through sources once. But even more importantly, this change also helps us to make the whole logic pluggable. The object read stream subsystem does not need to be aware of the different source backends anymore, but eventually it'll only have to call the source's callback function. Note that at the current point in time we aren't fully there yet: - The packfile store still sits on the object database level and is thus agnostic of the sources. - We still have to call into both the packfile store and the loose object source. But both of these issues will soon be addressed. This refactoring results in a slight change to semantics: previously, it was `odb_read_object_info_extended()` that picked the source for us, and it would have favored packed (non-deltified) objects over loose objects. And while we still favor packed over loose objects for a single source with the new logic, we'll now favor a loose object from an earlier source over a packed object from a later source. Ultimately this shouldn't matter though: the stream doesn't indicate to the caller which source it is from and whether it was created from a packed or loose object, so such details are opaque to the caller. And other than that we should be able to assume that two objects with the same object ID should refer to the same content, so the streamed data would be the same, too. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 385e188 commit 4c89d31

1 file changed

Lines changed: 24 additions & 41 deletions

File tree

streaming.c

Lines changed: 24 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -204,21 +204,15 @@ static int close_istream_loose(struct odb_read_stream *_st)
204204
}
205205

206206
static int open_istream_loose(struct odb_read_stream **out,
207-
struct repository *r,
207+
struct odb_source *source,
208208
const struct object_id *oid)
209209
{
210210
struct object_info oi = OBJECT_INFO_INIT;
211211
struct odb_loose_read_stream *st;
212-
struct odb_source *source;
213212
unsigned long mapsize;
214213
void *mapped;
215214

216-
odb_prepare_alternates(r->objects);
217-
for (source = r->objects->sources; source; source = source->next) {
218-
mapped = odb_source_loose_map_object(source, oid, &mapsize);
219-
if (mapped)
220-
break;
221-
}
215+
mapped = odb_source_loose_map_object(source, oid, &mapsize);
222216
if (!mapped)
223217
return -1;
224218

@@ -352,21 +346,25 @@ static int close_istream_pack_non_delta(struct odb_read_stream *_st)
352346
}
353347

354348
static int open_istream_pack_non_delta(struct odb_read_stream **out,
355-
struct repository *r UNUSED,
356-
const struct object_id *oid UNUSED,
357-
struct packed_git *pack,
358-
off_t offset)
349+
struct object_database *odb,
350+
const struct object_id *oid)
359351
{
360352
struct odb_packed_read_stream *stream;
361-
struct pack_window *window;
353+
struct pack_window *window = NULL;
354+
struct object_info oi = OBJECT_INFO_INIT;
362355
enum object_type in_pack_type;
363-
size_t size;
356+
unsigned long size;
364357

365-
window = NULL;
358+
oi.sizep = &size;
359+
360+
if (packfile_store_read_object_info(odb->packfiles, oid, &oi, 0) ||
361+
oi.u.packed.is_delta ||
362+
repo_settings_get_big_file_threshold(the_repository) >= size)
363+
return -1;
366364

367-
in_pack_type = unpack_object_header(pack,
365+
in_pack_type = unpack_object_header(oi.u.packed.pack,
368366
&window,
369-
&offset,
367+
&oi.u.packed.offset,
370368
&size);
371369
unuse_pack(&window);
372370
switch (in_pack_type) {
@@ -385,8 +383,8 @@ static int open_istream_pack_non_delta(struct odb_read_stream **out,
385383
stream->base.type = in_pack_type;
386384
stream->base.size = size;
387385
stream->z_state = ODB_PACKED_READ_STREAM_UNINITIALIZED;
388-
stream->pack = pack;
389-
stream->pos = offset;
386+
stream->pack = oi.u.packed.pack;
387+
stream->pos = oi.u.packed.offset;
390388

391389
*out = &stream->base;
392390

@@ -463,30 +461,15 @@ static int istream_source(struct odb_read_stream **out,
463461
struct repository *r,
464462
const struct object_id *oid)
465463
{
466-
unsigned long size;
467-
int status;
468-
struct object_info oi = OBJECT_INFO_INIT;
469-
470-
oi.sizep = &size;
471-
status = odb_read_object_info_extended(r->objects, oid, &oi, 0);
472-
if (status < 0)
473-
return status;
464+
struct odb_source *source;
474465

475-
switch (oi.whence) {
476-
case OI_LOOSE:
477-
if (open_istream_loose(out, r, oid) < 0)
478-
break;
479-
return 0;
480-
case OI_PACKED:
481-
if (oi.u.packed.is_delta ||
482-
repo_settings_get_big_file_threshold(the_repository) >= size ||
483-
open_istream_pack_non_delta(out, r, oid, oi.u.packed.pack,
484-
oi.u.packed.offset) < 0)
485-
break;
466+
if (!open_istream_pack_non_delta(out, r->objects, oid))
486467
return 0;
487-
default:
488-
break;
489-
}
468+
469+
odb_prepare_alternates(r->objects);
470+
for (source = r->objects->sources; source; source = source->next)
471+
if (!open_istream_loose(out, source, oid))
472+
return 0;
490473

491474
return open_istream_incore(out, r, oid);
492475
}

0 commit comments

Comments
 (0)