Skip to content

Commit 5946a56

Browse files
pks-tgitster
authored andcommitted
odb/source: make read_object_info() function pluggable
Introduce a new callback function in `struct odb_source` to make the function pluggable. Note that this function is a bit less straight-forward to convert compared to the other functions. The reason here is that the logic to read an object is: 1. We try to read the object. If it exists we return it. 2. If the object does not exist we reprepare the object database source. 3. We then try reading the object info a second time in case the reprepare caused it to appear. The second read is only supposed to happen for the packfile store though, as reading loose objects is not impacted by repreparing the object database. Ideally, we'd just move this whole logic into the ODB source. But that's not easily possible because we try to avoid the reprepare unless really required, which is after we have found out that no other ODB source contains the object, either. So the logic spans across multiple ODB sources, and consequently we cannot move it into an individual source. Instead, introduce a new flag `OBJECT_INFO_SECOND_READ` that tells the backend that we already tried to look up the object once, and that this time around the ODB source should try to find any new objects that may have surfaced due to an on-disk change. With this flag, the "files" backend can trivially skip trying to re-read the object as a loose object. Furthermore, as we know that we only try the second read via the packfile store, we can skip repreparing loose objects and only reprepare the packfile store. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 3bc3177 commit 5946a56

6 files changed

Lines changed: 122 additions & 37 deletions

File tree

object-file.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,16 @@ int odb_source_loose_read_object_info(struct odb_source *source,
546546
enum object_info_flags flags)
547547
{
548548
static struct strbuf buf = STRBUF_INIT;
549+
550+
/*
551+
* The second read shouldn't cause new loose objects to show up, unless
552+
* there was a race condition with a secondary process. We don't care
553+
* about this case though, so we simply skip reading loose objects a
554+
* second time.
555+
*/
556+
if (flags & OBJECT_INFO_SECOND_READ)
557+
return -1;
558+
549559
odb_loose_path(source, &buf, oid);
550560
return read_object_info_from_path(source, buf.buf, oid, oi, flags);
551561
}

odb.c

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -688,22 +688,20 @@ static int do_oid_object_info_extended(struct object_database *odb,
688688
while (1) {
689689
struct odb_source *source;
690690

691-
/* Most likely it's a loose object. */
692-
for (source = odb->sources; source; source = source->next) {
693-
struct odb_source_files *files = odb_source_files_downcast(source);
694-
if (!packfile_store_read_object_info(files->packed, real, oi, flags) ||
695-
!odb_source_loose_read_object_info(source, real, oi, flags))
691+
for (source = odb->sources; source; source = source->next)
692+
if (!odb_source_read_object_info(source, real, oi, flags))
696693
return 0;
697-
}
698694

699-
/* Not a loose object; someone else may have just packed it. */
695+
/*
696+
* When the object hasn't been found we try a second read and
697+
* tell the sources so. This may cause them to invalidate
698+
* caches or reload on-disk state.
699+
*/
700700
if (!(flags & OBJECT_INFO_QUICK)) {
701-
odb_reprepare(odb->repo->objects);
702-
for (source = odb->sources; source; source = source->next) {
703-
struct odb_source_files *files = odb_source_files_downcast(source);
704-
if (!packfile_store_read_object_info(files->packed, real, oi, flags))
701+
for (source = odb->sources; source; source = source->next)
702+
if (!odb_source_read_object_info(source, real, oi,
703+
flags | OBJECT_INFO_SECOND_READ))
705704
return 0;
706-
}
707705
}
708706

709707
/*

odb.h

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -339,30 +339,6 @@ struct object_info {
339339
*/
340340
#define OBJECT_INFO_INIT { 0 }
341341

342-
/* Flags that can be passed to `odb_read_object_info_extended()`. */
343-
enum object_info_flags {
344-
/* Invoke lookup_replace_object() on the given hash. */
345-
OBJECT_INFO_LOOKUP_REPLACE = (1 << 0),
346-
347-
/* Do not reprepare object sources when the first lookup has failed. */
348-
OBJECT_INFO_QUICK = (1 << 1),
349-
350-
/*
351-
* Do not attempt to fetch the object if missing (even if fetch_is_missing is
352-
* nonzero).
353-
*/
354-
OBJECT_INFO_SKIP_FETCH_OBJECT = (1 << 2),
355-
356-
/* Die if object corruption (not just an object being missing) was detected. */
357-
OBJECT_INFO_DIE_IF_CORRUPT = (1 << 3),
358-
359-
/*
360-
* This is meant for bulk prefetching of missing blobs in a partial
361-
* clone. Implies OBJECT_INFO_SKIP_FETCH_OBJECT and OBJECT_INFO_QUICK.
362-
*/
363-
OBJECT_INFO_FOR_PREFETCH = (OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK),
364-
};
365-
366342
/*
367343
* Read object info from the object database and populate the `object_info`
368344
* structure. Returns 0 on success, a negative error code otherwise.

odb/source-files.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,20 @@ static void odb_source_files_reprepare(struct odb_source *source)
4141
packfile_store_reprepare(files->packed);
4242
}
4343

44+
static int odb_source_files_read_object_info(struct odb_source *source,
45+
const struct object_id *oid,
46+
struct object_info *oi,
47+
enum object_info_flags flags)
48+
{
49+
struct odb_source_files *files = odb_source_files_downcast(source);
50+
51+
if (!packfile_store_read_object_info(files->packed, oid, oi, flags) ||
52+
!odb_source_loose_read_object_info(source, oid, oi, flags))
53+
return 0;
54+
55+
return -1;
56+
}
57+
4458
struct odb_source_files *odb_source_files_new(struct object_database *odb,
4559
const char *path,
4660
bool local)
@@ -55,6 +69,7 @@ struct odb_source_files *odb_source_files_new(struct object_database *odb,
5569
files->base.free = odb_source_files_free;
5670
files->base.close = odb_source_files_close;
5771
files->base.reprepare = odb_source_files_reprepare;
72+
files->base.read_object_info = odb_source_files_read_object_info;
5873

5974
/*
6075
* Ideally, we would only ever store absolute paths in the source. This

odb/source.h

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,45 @@ enum odb_source_type {
1212
ODB_SOURCE_FILES,
1313
};
1414

15+
/* Flags that can be passed to `odb_read_object_info_extended()`. */
16+
enum object_info_flags {
17+
/* Invoke lookup_replace_object() on the given hash. */
18+
OBJECT_INFO_LOOKUP_REPLACE = (1 << 0),
19+
20+
/* Do not reprepare object sources when the first lookup has failed. */
21+
OBJECT_INFO_QUICK = (1 << 1),
22+
23+
/*
24+
* Do not attempt to fetch the object if missing (even if fetch_is_missing is
25+
* nonzero).
26+
*/
27+
OBJECT_INFO_SKIP_FETCH_OBJECT = (1 << 2),
28+
29+
/* Die if object corruption (not just an object being missing) was detected. */
30+
OBJECT_INFO_DIE_IF_CORRUPT = (1 << 3),
31+
32+
/*
33+
* We have already tried reading the object, but it couldn't be found
34+
* via any of the attached sources, and are now doing a second read.
35+
* This second read asks the individual sources to also evaluate
36+
* whether any on-disk state may have changed that may have caused the
37+
* object to appear.
38+
*
39+
* This flag is for internal use, only. The second read only occurs
40+
* when `OBJECT_INFO_QUICK` was not passed.
41+
*/
42+
OBJECT_INFO_SECOND_READ = (1 << 4),
43+
44+
/*
45+
* This is meant for bulk prefetching of missing blobs in a partial
46+
* clone. Implies OBJECT_INFO_SKIP_FETCH_OBJECT and OBJECT_INFO_QUICK.
47+
*/
48+
OBJECT_INFO_FOR_PREFETCH = (OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK),
49+
};
50+
51+
struct object_id;
52+
struct object_info;
53+
1554
/*
1655
* The source is the part of the object database that stores the actual
1756
* objects. It thus encapsulates the logic to read and write the specific
@@ -72,6 +111,33 @@ struct odb_source {
72111
* example just been repacked so that new objects will become visible.
73112
*/
74113
void (*reprepare)(struct odb_source *source);
114+
115+
/*
116+
* This callback is expected to read object information from the object
117+
* database source. The object info will be partially populated with
118+
* pointers for each bit of information that was requested by the
119+
* caller.
120+
*
121+
* The flags field is a combination of `OBJECT_INFO` flags. Only the
122+
* following fields need to be handled by the backend:
123+
*
124+
* - `OBJECT_INFO_QUICK` indicates it is fine to use caches without
125+
* re-verifying the data.
126+
*
127+
* - `OBJECT_INFO_SECOND_READ` indicates that the initial object
128+
* lookup has failed and that the object sources should check
129+
* whether any of its on-disk state has changed that may have
130+
* caused the object to appear. Sources are free to ignore the
131+
* second read in case they know that the first read would have
132+
* already surfaced the object without reloading any on-disk state.
133+
*
134+
* The callback is expected to return a negative error code in case
135+
* reading the object has failed, 0 otherwise.
136+
*/
137+
int (*read_object_info)(struct odb_source *source,
138+
const struct object_id *oid,
139+
struct object_info *oi,
140+
enum object_info_flags flags);
75141
};
76142

77143
/*
@@ -131,4 +197,16 @@ static inline void odb_source_reprepare(struct odb_source *source)
131197
source->reprepare(source);
132198
}
133199

200+
/*
201+
* Read an object from the object database source identified by its object ID.
202+
* Returns 0 on success, a negative error code otherwise.
203+
*/
204+
static inline int odb_source_read_object_info(struct odb_source *source,
205+
const struct object_id *oid,
206+
struct object_info *oi,
207+
enum object_info_flags flags)
208+
{
209+
return source->read_object_info(source, oid, oi, flags);
210+
}
211+
134212
#endif

packfile.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2181,11 +2181,19 @@ int packfile_store_freshen_object(struct packfile_store *store,
21812181
int packfile_store_read_object_info(struct packfile_store *store,
21822182
const struct object_id *oid,
21832183
struct object_info *oi,
2184-
enum object_info_flags flags UNUSED)
2184+
enum object_info_flags flags)
21852185
{
21862186
struct pack_entry e;
21872187
int ret;
21882188

2189+
/*
2190+
* In case the first read didn't surface the object, we have to reload
2191+
* packfiles. This may cause us to discover new packfiles that have
2192+
* been added since the last time we have prepared the packfile store.
2193+
*/
2194+
if (flags & OBJECT_INFO_SECOND_READ)
2195+
packfile_store_reprepare(store);
2196+
21892197
if (!find_pack_entry(store, oid, &e))
21902198
return 1;
21912199

0 commit comments

Comments
 (0)