Skip to content

Commit 0d41b18

Browse files
ttaylorrgitster
authored andcommitted
pack-bitmap-write: support storing pseudo-merge commits
Prepare to write pseudo-merge bitmaps by annotating individual bitmapped commits (which are represented by the `bitmapped_commit` structure) with an extra bit indicating whether or not they are a pseudo-merge. In subsequent commits, pseudo-merge bitmaps will be generated by allocating a fake commit node with parents covering the full set of commits represented by the pseudo-merge bitmap. These commits will be added to the set of "selected" commits as usual, but will be written specially instead of being included with the rest of the selected commits. Mechanically speaking, there are two parts of this change: - The bitmapped_commit struct gets a new bit indicating whether it is a pseudo-merge, or an ordinary commit selected for bitmaps. - A handful of changes to only write out the non-pseudo-merge commits when enumerating through the selected array (see the new `bitmap_writer_selected_nr()` function). Pseudo-merge commits appear after all non-pseudo-merge commits, so it is safe to enumerate through the selected array like so: for (i = 0; i < bitmap_writer_selected_nr(); i++) if (writer.selected[i].pseudo_merge) BUG("unexpected pseudo-merge"); without encountering the BUG(). Signed-off-by: Taylor Blau <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 89f47c4 commit 0d41b18

File tree

3 files changed

+67
-34
lines changed

3 files changed

+67
-34
lines changed

object.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ void object_array_init(struct object_array *array);
8181
* reflog.c: 10--12
8282
* builtin/show-branch.c: 0-------------------------------------------26
8383
* builtin/unpack-objects.c: 2021
84-
* pack-bitmap.h: 22
84+
* pack-bitmap.h: 2122
8585
*/
8686
#define FLAG_BITS 28
8787

pack-bitmap-write.c

Lines changed: 63 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,14 @@ struct bitmapped_commit {
2525
int flags;
2626
int xor_offset;
2727
uint32_t commit_pos;
28+
unsigned pseudo_merge : 1;
2829
};
2930

31+
static inline int bitmap_writer_nr_selected_commits(struct bitmap_writer *writer)
32+
{
33+
return writer->selected_nr - writer->pseudo_merges_nr;
34+
}
35+
3036
void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r)
3137
{
3238
memset(writer, 0, sizeof(struct bitmap_writer));
@@ -129,27 +135,31 @@ void bitmap_writer_build_type_index(struct bitmap_writer *writer,
129135
*/
130136

131137
static inline void push_bitmapped_commit(struct bitmap_writer *writer,
132-
struct commit *commit)
138+
struct commit *commit,
139+
unsigned pseudo_merge)
133140
{
134-
int hash_ret;
135-
khiter_t hash_pos;
136-
137141
if (writer->selected_nr >= writer->selected_alloc) {
138142
writer->selected_alloc = (writer->selected_alloc + 32) * 2;
139143
REALLOC_ARRAY(writer->selected, writer->selected_alloc);
140144
}
141145

142-
hash_pos = kh_put_oid_map(writer->bitmaps, commit->object.oid,
143-
&hash_ret);
144-
if (!hash_ret)
145-
die(_("duplicate entry when writing bitmap index: %s"),
146-
oid_to_hex(&commit->object.oid));
147-
kh_value(writer->bitmaps, hash_pos) = NULL;
146+
if (!pseudo_merge) {
147+
int hash_ret;
148+
khiter_t hash_pos = kh_put_oid_map(writer->bitmaps,
149+
commit->object.oid,
150+
&hash_ret);
151+
152+
if (!hash_ret)
153+
die(_("duplicate entry when writing bitmap index: %s"),
154+
oid_to_hex(&commit->object.oid));
155+
kh_value(writer->bitmaps, hash_pos) = NULL;
156+
}
148157

149158
writer->selected[writer->selected_nr].commit = commit;
150159
writer->selected[writer->selected_nr].bitmap = NULL;
151160
writer->selected[writer->selected_nr].write_as = NULL;
152161
writer->selected[writer->selected_nr].flags = 0;
162+
writer->selected[writer->selected_nr].pseudo_merge = pseudo_merge;
153163

154164
writer->selected_nr++;
155165
}
@@ -180,16 +190,20 @@ static void compute_xor_offsets(struct bitmap_writer *writer)
180190

181191
while (next < writer->selected_nr) {
182192
struct bitmapped_commit *stored = &writer->selected[next];
183-
184193
int best_offset = 0;
185194
struct ewah_bitmap *best_bitmap = stored->bitmap;
186195
struct ewah_bitmap *test_xor;
187196

197+
if (stored->pseudo_merge)
198+
goto next;
199+
188200
for (i = 1; i <= MAX_XOR_OFFSET_SEARCH; ++i) {
189201
int curr = next - i;
190202

191203
if (curr < 0)
192204
break;
205+
if (writer->selected[curr].pseudo_merge)
206+
continue;
193207

194208
test_xor = ewah_pool_new();
195209
ewah_xor(writer->selected[curr].bitmap, stored->bitmap, test_xor);
@@ -205,6 +219,7 @@ static void compute_xor_offsets(struct bitmap_writer *writer)
205219
}
206220
}
207221

222+
next:
208223
stored->xor_offset = best_offset;
209224
stored->write_as = best_bitmap;
210225

@@ -217,7 +232,8 @@ struct bb_commit {
217232
struct bitmap *commit_mask;
218233
struct bitmap *bitmap;
219234
unsigned selected:1,
220-
maximal:1;
235+
maximal:1,
236+
pseudo_merge:1;
221237
unsigned idx; /* within selected array */
222238
};
223239

@@ -255,17 +271,18 @@ static void bitmap_builder_init(struct bitmap_builder *bb,
255271
revs.first_parent_only = 1;
256272

257273
for (i = 0; i < writer->selected_nr; i++) {
258-
struct commit *c = writer->selected[i].commit;
259-
struct bb_commit *ent = bb_data_at(&bb->data, c);
274+
struct bitmapped_commit *bc = &writer->selected[i];
275+
struct bb_commit *ent = bb_data_at(&bb->data, bc->commit);
260276

261277
ent->selected = 1;
262278
ent->maximal = 1;
279+
ent->pseudo_merge = bc->pseudo_merge;
263280
ent->idx = i;
264281

265282
ent->commit_mask = bitmap_new();
266283
bitmap_set(ent->commit_mask, i);
267284

268-
add_pending_object(&revs, &c->object, "");
285+
add_pending_object(&revs, &bc->commit->object, "");
269286
}
270287

271288
if (prepare_revision_walk(&revs))
@@ -444,8 +461,13 @@ static int fill_bitmap_commit(struct bitmap_writer *writer,
444461
struct commit *c = prio_queue_get(queue);
445462

446463
if (old_bitmap && mapping) {
447-
struct ewah_bitmap *old = bitmap_for_commit(old_bitmap, c);
464+
struct ewah_bitmap *old;
448465
struct bitmap *remapped = bitmap_new();
466+
467+
if (commit->object.flags & BITMAP_PSEUDO_MERGE)
468+
old = NULL;
469+
else
470+
old = bitmap_for_commit(old_bitmap, c);
449471
/*
450472
* If this commit has an old bitmap, then translate that
451473
* bitmap and add its bits to this one. No need to walk
@@ -464,12 +486,14 @@ static int fill_bitmap_commit(struct bitmap_writer *writer,
464486
* Mark ourselves and queue our tree. The commit
465487
* walk ensures we cover all parents.
466488
*/
467-
pos = find_object_pos(writer, &c->object.oid, &found);
468-
if (!found)
469-
return -1;
470-
bitmap_set(ent->bitmap, pos);
471-
prio_queue_put(tree_queue,
472-
repo_get_commit_tree(the_repository, c));
489+
if (!(c->object.flags & BITMAP_PSEUDO_MERGE)) {
490+
pos = find_object_pos(writer, &c->object.oid, &found);
491+
if (!found)
492+
return -1;
493+
bitmap_set(ent->bitmap, pos);
494+
prio_queue_put(tree_queue,
495+
repo_get_commit_tree(the_repository, c));
496+
}
473497

474498
for (p = c->parents; p; p = p->next) {
475499
pos = find_object_pos(writer, &p->item->object.oid,
@@ -499,6 +523,9 @@ static void store_selected(struct bitmap_writer *writer,
499523

500524
stored->bitmap = bitmap_to_ewah(ent->bitmap);
501525

526+
if (ent->pseudo_merge)
527+
return;
528+
502529
hash_pos = kh_get_oid_map(writer->bitmaps, commit->object.oid);
503530
if (hash_pos == kh_end(writer->bitmaps))
504531
die(_("attempted to store non-selected commit: '%s'"),
@@ -631,7 +658,7 @@ void bitmap_writer_select_commits(struct bitmap_writer *writer,
631658

632659
if (indexed_commits_nr < 100) {
633660
for (i = 0; i < indexed_commits_nr; ++i)
634-
push_bitmapped_commit(writer, indexed_commits[i]);
661+
push_bitmapped_commit(writer, indexed_commits[i], 0);
635662
return;
636663
}
637664

@@ -664,7 +691,7 @@ void bitmap_writer_select_commits(struct bitmap_writer *writer,
664691
}
665692
}
666693

667-
push_bitmapped_commit(writer, chosen);
694+
push_bitmapped_commit(writer, chosen, 0);
668695

669696
i += next + 1;
670697
display_progress(writer->progress, i);
@@ -701,8 +728,11 @@ static void write_selected_commits_v1(struct bitmap_writer *writer,
701728
{
702729
int i;
703730

704-
for (i = 0; i < writer->selected_nr; ++i) {
731+
for (i = 0; i < bitmap_writer_nr_selected_commits(writer); ++i) {
705732
struct bitmapped_commit *stored = &writer->selected[i];
733+
if (stored->pseudo_merge)
734+
BUG("unexpected pseudo-merge among selected: %s",
735+
oid_to_hex(&stored->commit->object.oid));
706736

707737
if (offsets)
708738
offsets[i] = hashfile_total(f);
@@ -735,27 +765,27 @@ static void write_lookup_table(struct bitmap_writer *writer, struct hashfile *f,
735765
uint32_t i;
736766
uint32_t *table, *table_inv;
737767

738-
ALLOC_ARRAY(table, writer->selected_nr);
739-
ALLOC_ARRAY(table_inv, writer->selected_nr);
768+
ALLOC_ARRAY(table, bitmap_writer_nr_selected_commits(writer));
769+
ALLOC_ARRAY(table_inv, bitmap_writer_nr_selected_commits(writer));
740770

741-
for (i = 0; i < writer->selected_nr; i++)
771+
for (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++)
742772
table[i] = i;
743773

744774
/*
745775
* At the end of this sort table[j] = i means that the i'th
746776
* bitmap corresponds to j'th bitmapped commit (among the selected
747777
* commits) in lex order of OIDs.
748778
*/
749-
QSORT_S(table, writer->selected_nr, table_cmp, writer);
779+
QSORT_S(table, bitmap_writer_nr_selected_commits(writer), table_cmp, writer);
750780

751781
/* table_inv helps us discover that relationship (i'th bitmap
752782
* to j'th commit by j = table_inv[i])
753783
*/
754-
for (i = 0; i < writer->selected_nr; i++)
784+
for (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++)
755785
table_inv[table[i]] = i;
756786

757787
trace2_region_enter("pack-bitmap-write", "writing_lookup_table", the_repository);
758-
for (i = 0; i < writer->selected_nr; i++) {
788+
for (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++) {
759789
struct bitmapped_commit *selected = &writer->selected[table[i]];
760790
uint32_t xor_offset = selected->xor_offset;
761791
uint32_t xor_row;
@@ -827,7 +857,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer,
827857
memcpy(header.magic, BITMAP_IDX_SIGNATURE, sizeof(BITMAP_IDX_SIGNATURE));
828858
header.version = htons(default_version);
829859
header.options = htons(flags | options);
830-
header.entry_count = htonl(writer->selected_nr);
860+
header.entry_count = htonl(bitmap_writer_nr_selected_commits(writer));
831861
hashcpy(header.checksum, writer->pack_checksum);
832862

833863
hashwrite(f, &header, sizeof(header) - GIT_MAX_RAWSZ + the_hash_algo->rawsz);
@@ -839,7 +869,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer,
839869
if (options & BITMAP_OPT_LOOKUP_TABLE)
840870
CALLOC_ARRAY(offsets, index_nr);
841871

842-
for (i = 0; i < writer->selected_nr; i++) {
872+
for (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++) {
843873
struct bitmapped_commit *stored = &writer->selected[i];
844874
int commit_pos = oid_pos(&stored->commit->object.oid, index,
845875
index_nr, oid_access);

pack-bitmap.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ struct bitmap_disk_header {
2121
unsigned char checksum[GIT_MAX_RAWSZ];
2222
};
2323

24+
#define BITMAP_PSEUDO_MERGE (1u<<21)
2425
#define NEEDS_BITMAP (1u<<22)
2526

2627
/*
@@ -109,6 +110,8 @@ struct bitmap_writer {
109110
struct bitmapped_commit *selected;
110111
unsigned int selected_nr, selected_alloc;
111112

113+
uint32_t pseudo_merges_nr;
114+
112115
struct progress *progress;
113116
int show_progress;
114117
unsigned char pack_checksum[GIT_MAX_RAWSZ];

0 commit comments

Comments
 (0)