Skip to content

Commit 6801ffd

Browse files
pks-tgitster
authored andcommitted
odb: introduce generic object counting
Similar to the preceding commit, introduce counting of objects on the object database level, replacing the logic that we have in `repo_approximate_object_count()`. Note that the function knows to cache the object count. It's unclear whether this cache is really required as we shouldn't have that many cases where we count objects repeatedly. But to be on the safe side the caching mechanism is retained, with the only excepting being that we also have to use the passed flags as caching key. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent b259f21 commit 6801ffd

File tree

7 files changed

+64
-40
lines changed

7 files changed

+64
-40
lines changed

builtin/gc.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,9 +574,13 @@ static uint64_t total_ram(void)
574574
static uint64_t estimate_repack_memory(struct gc_config *cfg,
575575
struct packed_git *pack)
576576
{
577-
unsigned long nr_objects = repo_approximate_object_count(the_repository);
577+
unsigned long nr_objects;
578578
size_t os_cache, heap;
579579

580+
if (odb_count_objects(the_repository->objects,
581+
ODB_COUNT_OBJECTS_APPROXIMATE, &nr_objects) < 0)
582+
return 0;
583+
580584
if (!pack || !nr_objects)
581585
return 0;
582586

commit-graph.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2607,7 +2607,8 @@ int write_commit_graph(struct odb_source *source,
26072607
replace = ctx.opts->split_flags & COMMIT_GRAPH_SPLIT_REPLACE;
26082608
}
26092609

2610-
ctx.approx_nr_objects = repo_approximate_object_count(r);
2610+
if (odb_count_objects(r->objects, ODB_COUNT_OBJECTS_APPROXIMATE, &ctx.approx_nr_objects) < 0)
2611+
ctx.approx_nr_objects = 0;
26112612

26122613
if (ctx.append && g) {
26132614
for (i = 0; i < g->num_commits; i++) {

object-name.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,11 @@ int repo_find_unique_abbrev_r(struct repository *r, char *hex,
837837
const unsigned hexsz = algo->hexsz;
838838

839839
if (len < 0) {
840-
unsigned long count = repo_approximate_object_count(r);
840+
unsigned long count;
841+
842+
if (odb_count_objects(r->objects, ODB_COUNT_OBJECTS_APPROXIMATE, &count) < 0)
843+
count = 0;
844+
841845
/*
842846
* Add one because the MSB only tells us the highest bit set,
843847
* not including the value of all the _other_ bits (so "15"

odb.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,41 @@ int odb_for_each_object(struct object_database *odb,
917917
return 0;
918918
}
919919

920+
int odb_count_objects(struct object_database *odb,
921+
enum odb_count_objects_flags flags,
922+
unsigned long *out)
923+
{
924+
struct odb_source *source;
925+
unsigned long count = 0;
926+
int ret;
927+
928+
if (odb->object_count_valid && odb->object_count_flags == flags) {
929+
*out = odb->object_count;
930+
return 0;
931+
}
932+
933+
odb_prepare_alternates(odb);
934+
for (source = odb->sources; source; source = source->next) {
935+
unsigned long c;
936+
937+
ret = odb_source_count_objects(source, flags, &c);
938+
if (ret < 0)
939+
goto out;
940+
941+
count += c;
942+
}
943+
944+
odb->object_count = count;
945+
odb->object_count_valid = 1;
946+
odb->object_count_flags = flags;
947+
948+
*out = count;
949+
ret = 0;
950+
951+
out:
952+
return ret;
953+
}
954+
920955
void odb_assert_oid_type(struct object_database *odb,
921956
const struct object_id *oid, enum object_type expect)
922957
{
@@ -1030,7 +1065,7 @@ void odb_reprepare(struct object_database *o)
10301065
for (source = o->sources; source; source = source->next)
10311066
odb_source_reprepare(source);
10321067

1033-
o->approximate_object_count_valid = 0;
1068+
o->object_count_valid = 0;
10341069

10351070
obj_read_unlock();
10361071
}

odb.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,11 @@ struct object_database {
110110
/*
111111
* A fast, rough count of the number of objects in the repository.
112112
* These two fields are not meant for direct access. Use
113-
* repo_approximate_object_count() instead.
113+
* odb_count_objects() instead.
114114
*/
115-
unsigned long approximate_object_count;
116-
unsigned approximate_object_count_valid : 1;
115+
unsigned long object_count;
116+
unsigned object_count_flags;
117+
unsigned object_count_valid : 1;
117118

118119
/*
119120
* Submodule source paths that will be added as additional sources to
@@ -509,6 +510,18 @@ enum odb_count_objects_flags {
509510
ODB_COUNT_OBJECTS_APPROXIMATE = (1 << 0),
510511
};
511512

513+
/*
514+
* Count the number of objects in the given object database. This object count
515+
* may double-count objects that are stored in multiple backends, or which are
516+
* stored multiple times in a single backend.
517+
*
518+
* Returns 0 on success, a negative error code otherwise. The number of objects
519+
* will be assigned to the `out` pointer on success.
520+
*/
521+
int odb_count_objects(struct object_database *odb,
522+
enum odb_count_objects_flags flags,
523+
unsigned long *out);
524+
512525
enum {
513526
/*
514527
* By default, `odb_write_object()` does not actually write anything

packfile.c

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,33 +1132,6 @@ int packfile_store_count_objects(struct packfile_store *store,
11321132
return ret;
11331133
}
11341134

1135-
/*
1136-
* Give a fast, rough count of the number of objects in the repository. This
1137-
* ignores loose objects completely. If you have a lot of them, then either
1138-
* you should repack because your performance will be awful, or they are
1139-
* all unreachable objects about to be pruned, in which case they're not really
1140-
* interesting as a measure of repo size in the first place.
1141-
*/
1142-
unsigned long repo_approximate_object_count(struct repository *r)
1143-
{
1144-
if (!r->objects->approximate_object_count_valid) {
1145-
struct odb_source *source;
1146-
unsigned long count = 0;
1147-
1148-
odb_prepare_alternates(r->objects);
1149-
for (source = r->objects->sources; source; source = source->next) {
1150-
unsigned long c;
1151-
1152-
if (!odb_source_count_objects(source, ODB_COUNT_OBJECTS_APPROXIMATE, &c))
1153-
count += c;
1154-
}
1155-
1156-
r->objects->approximate_object_count = count;
1157-
r->objects->approximate_object_count_valid = 1;
1158-
}
1159-
return r->objects->approximate_object_count;
1160-
}
1161-
11621135
unsigned long unpack_object_header_buffer(const unsigned char *buf,
11631136
unsigned long len, enum object_type *type, unsigned long *sizep)
11641137
{

packfile.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -375,12 +375,6 @@ int packfile_store_for_each_object(struct packfile_store *store,
375375
#define PACKDIR_FILE_GARBAGE 4
376376
extern void (*report_garbage)(unsigned seen_bits, const char *path);
377377

378-
/*
379-
* Give a rough count of objects in the repository. This sacrifices accuracy
380-
* for speed.
381-
*/
382-
unsigned long repo_approximate_object_count(struct repository *r);
383-
384378
void pack_report(struct repository *repo);
385379

386380
/*

0 commit comments

Comments
 (0)