packfile: use oidset for bad objects
Store the object ID of broken pack entries in an oidset instead of keeping only their hashes in an unsorted array. The resulting code is shorter and easier to read. It also handles the (hopefully) very rare case of having a high number of bad objects better. Helped-by: Jeff King <peff@peff.net> Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
René Scharfe committed
Sep 11, 2021 at 22:43 UTC
09ef66179b943d03cbe0bea0603e5f40574695a1
3 files changed
+11
-31
midx.c
+3
-7
@@ -307,13 +307,9 @@ int fill_midx_entry(struct repository * r,
307
if (!is_pack_valid(p))
308
return 0;
309
310
- if (p->num_bad_objects) {
311
- uint32_t i;
312
- for (i = 0; i < p->num_bad_objects; i++)
313
- if (hasheq(oid->hash,
314
- p->bad_object_sha1 + the_hash_algo->rawsz * i))
315
- return 0;
316
- }
310
+ if (oidset_size(&p->bad_objects) &&
311
+ oidset_contains(&p->bad_objects, oid))
312
+ return 0;
313
314
e->offset = nth_midxed_offset(m, pos);
315
e->p = p;
object-store.h
+2
-2
@@ -10,6 +10,7 @@
10
#include "khash.h"
11
#include "dir.h"
12
#include "oidtree.h"
13
+#include "oidset.h"
14
15
struct object_directory {
16
struct object_directory *next;
@@ -75,9 +76,8 @@ struct packed_git {
76
const void *index_data;
77
size_t index_size;
78
uint32_t num_objects;
78
- uint32_t num_bad_objects;
79
uint32_t crc_offset;
80
- unsigned char *bad_object_sha1;
80
+ struct oidset bad_objects;
81
int index_version;
82
time_t mtime;
83
int pack_fd;
packfile.c
+6
-22
@@ -1163,29 +1163,17 @@ int unpack_object_header(struct packed_git *p,
1163
1164
void mark_bad_packed_object(struct packed_git *p, const struct object_id *oid)
1165
{
1166
- unsigned i;
1167
- const unsigned hashsz = the_hash_algo->rawsz;
1168
- for (i = 0; i < p->num_bad_objects; i++)
1169
- if (hasheq(oid->hash, p->bad_object_sha1 + hashsz * i))
1170
- return;
1171
- p->bad_object_sha1 = xrealloc(p->bad_object_sha1,
1172
- st_mult(GIT_MAX_RAWSZ,
1173
- st_add(p->num_bad_objects, 1)));
1174
- hashcpy(p->bad_object_sha1 + hashsz * p->num_bad_objects, oid->hash);
1175
- p->num_bad_objects++;
1166
+ oidset_insert(&p->bad_objects, oid);
1167
}
1168
1169
const struct packed_git *has_packed_and_bad(struct repository *r,
1170
const struct object_id *oid)
1171
{
1172
struct packed_git *p;
1182
- unsigned i;
1173
1174
for (p = r->objects->packed_git; p; p = p->next)
1185
- for (i = 0; i < p->num_bad_objects; i++)
1186
- if (hasheq(oid->hash,
1187
- p->bad_object_sha1 + the_hash_algo->rawsz * i))
1188
- return p;
1175
+ if (oidset_contains(&p->bad_objects, oid))
1176
+ return p;
1177
return NULL;
1178
}
1179
@@ -2016,13 +2004,9 @@ static int fill_pack_entry(const struct object_id *oid,
2004
{
2005
off_t offset;
2006
2019
- if (p->num_bad_objects) {
2020
- unsigned i;
2021
- for (i = 0; i < p->num_bad_objects; i++)
2022
- if (hasheq(oid->hash,
2023
- p->bad_object_sha1 + the_hash_algo->rawsz * i))
2024
- return 0;
2025
- }
2007
+ if (oidset_size(&p->bad_objects) &&
2008
+ oidset_contains(&p->bad_objects, oid))
2009
+ return 0;
2010
2011
offset = find_pack_entry_one(oid->hash, p);
2012
if (!offset)