Skip to content

Commit 77ddd11

Browse files
committed
midx: implement writing incremental MIDX bitmaps
Now that the pack-bitmap machinery has learned how to read and interact with an incremental MIDX bitmap, teach the pack-bitmap-write.c machinery (and relevant callers from within the MIDX machinery) to write such bitmaps. The details for doing so are mostly straightforward. The main changes are as follows: - find_object_pos() now makes use of an extra MIDX parameter which is used to locate the bit positions of objects which are from previous layers (and thus do not exist in the current layer's pack_order field). (Note also that the pack_order field is moved into struct write_midx_context to further simplify the callers for write_midx_bitmap()). - bitmap_writer_build_type_index() first determines how many objects precede the current bitmap layer and offsets the bits it sets in each respective type-level bitmap by that amount so they can be OR'd together. Signed-off-by: Taylor Blau <[email protected]>
1 parent 87cb011 commit 77ddd11

5 files changed

+171
-34
lines changed

builtin/pack-objects.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -1370,7 +1370,8 @@ static void write_pack_file(void)
13701370

13711371
if (write_bitmap_index) {
13721372
bitmap_writer_init(&bitmap_writer,
1373-
the_repository, &to_pack);
1373+
the_repository, &to_pack,
1374+
NULL);
13741375
bitmap_writer_set_checksum(&bitmap_writer, hash);
13751376
bitmap_writer_build_type_index(&bitmap_writer,
13761377
written_list);

midx-write.c

+33-16
Original file line numberDiff line numberDiff line change
@@ -645,15 +645,21 @@ static uint32_t *midx_pack_order(struct write_midx_context *ctx)
645645
return pack_order;
646646
}
647647

648-
static void write_midx_reverse_index(char *midx_name, unsigned char *midx_hash,
649-
struct write_midx_context *ctx)
648+
static void write_midx_reverse_index(struct write_midx_context *ctx,
649+
const char *object_dir,
650+
unsigned char *midx_hash)
650651
{
651652
struct strbuf buf = STRBUF_INIT;
652653
char *tmp_file;
653654

654655
trace2_region_enter("midx", "write_midx_reverse_index", the_repository);
655656

656-
strbuf_addf(&buf, "%s-%s.rev", midx_name, hash_to_hex(midx_hash));
657+
if (ctx->incremental)
658+
get_split_midx_filename_ext(&buf, object_dir, midx_hash,
659+
MIDX_EXT_REV);
660+
else
661+
get_midx_filename_ext(&buf, object_dir, midx_hash,
662+
MIDX_EXT_REV);
657663

658664
tmp_file = write_rev_file_order(NULL, ctx->pack_order, ctx->entries_nr,
659665
midx_hash, WRITE_REV);
@@ -827,20 +833,26 @@ static struct commit **find_commits_for_midx_bitmap(uint32_t *indexed_commits_nr
827833
return cb.commits;
828834
}
829835

830-
static int write_midx_bitmap(const char *midx_name,
836+
static int write_midx_bitmap(struct write_midx_context *ctx,
837+
const char *object_dir,
831838
const unsigned char *midx_hash,
832839
struct packing_data *pdata,
833840
struct commit **commits,
834841
uint32_t commits_nr,
835-
uint32_t *pack_order,
836842
unsigned flags)
837843
{
838844
int ret, i;
839845
uint16_t options = 0;
840846
struct bitmap_writer writer;
841847
struct pack_idx_entry **index;
842-
char *bitmap_name = xstrfmt("%s-%s.bitmap", midx_name,
843-
hash_to_hex(midx_hash));
848+
struct strbuf bitmap_name = STRBUF_INIT;
849+
850+
if (ctx->incremental)
851+
get_split_midx_filename_ext(&bitmap_name, object_dir, midx_hash,
852+
MIDX_EXT_BITMAP);
853+
else
854+
get_midx_filename_ext(&bitmap_name, object_dir, midx_hash,
855+
MIDX_EXT_BITMAP);
844856

845857
trace2_region_enter("midx", "write_midx_bitmap", the_repository);
846858

@@ -859,7 +871,8 @@ static int write_midx_bitmap(const char *midx_name,
859871
for (i = 0; i < pdata->nr_objects; i++)
860872
index[i] = &pdata->objects[i].idx;
861873

862-
bitmap_writer_init(&writer, the_repository, pdata);
874+
bitmap_writer_init(&writer, the_repository, pdata,
875+
ctx->incremental ? ctx->base_midx : NULL);
863876
bitmap_writer_show_progress(&writer, flags & MIDX_PROGRESS);
864877
bitmap_writer_build_type_index(&writer, index);
865878

@@ -877,19 +890,19 @@ static int write_midx_bitmap(const char *midx_name,
877890
* bitmap_writer_finish().
878891
*/
879892
for (i = 0; i < pdata->nr_objects; i++)
880-
index[pack_order[i]] = &pdata->objects[i].idx;
893+
index[ctx->pack_order[i]] = &pdata->objects[i].idx;
881894

882895
bitmap_writer_select_commits(&writer, commits, commits_nr);
883896
ret = bitmap_writer_build(&writer);
884897
if (ret < 0)
885898
goto cleanup;
886899

887900
bitmap_writer_set_checksum(&writer, midx_hash);
888-
bitmap_writer_finish(&writer, index, bitmap_name, options);
901+
bitmap_writer_finish(&writer, index, bitmap_name.buf, options);
889902

890903
cleanup:
891904
free(index);
892-
free(bitmap_name);
905+
strbuf_release(&bitmap_name);
893906
bitmap_writer_free(&writer);
894907

895908
trace2_region_leave("midx", "write_midx_bitmap", the_repository);
@@ -1073,8 +1086,6 @@ static int write_midx_internal(const char *object_dir,
10731086
trace2_region_enter("midx", "write_midx_internal", the_repository);
10741087

10751088
ctx.incremental = !!(flags & MIDX_WRITE_INCREMENTAL);
1076-
if (ctx.incremental && (flags & MIDX_WRITE_BITMAP))
1077-
die(_("cannot write incremental MIDX with bitmap"));
10781089

10791090
if (ctx.incremental)
10801091
strbuf_addf(&midx_name,
@@ -1116,6 +1127,12 @@ static int write_midx_internal(const char *object_dir,
11161127
if (ctx.incremental) {
11171128
struct multi_pack_index *m = ctx.base_midx;
11181129
while (m) {
1130+
if (flags & MIDX_WRITE_BITMAP && load_midx_revindex(m)) {
1131+
error(_("could not load reverse index for MIDX %s"),
1132+
hash_to_hex(get_midx_checksum(m)));
1133+
result = 1;
1134+
goto cleanup;
1135+
}
11191136
ctx.num_multi_pack_indexes_before++;
11201137
m = m->base_midx;
11211138
}
@@ -1382,7 +1399,7 @@ static int write_midx_internal(const char *object_dir,
13821399

13831400
if (flags & MIDX_WRITE_REV_INDEX &&
13841401
git_env_bool("GIT_TEST_MIDX_WRITE_REV", 0))
1385-
write_midx_reverse_index(midx_name.buf, midx_hash, &ctx);
1402+
write_midx_reverse_index(&ctx, object_dir, midx_hash);
13861403

13871404
if (flags & MIDX_WRITE_BITMAP) {
13881405
struct packing_data pdata;
@@ -1405,8 +1422,8 @@ static int write_midx_internal(const char *object_dir,
14051422
FREE_AND_NULL(ctx.entries);
14061423
ctx.entries_nr = 0;
14071424

1408-
if (write_midx_bitmap(midx_name.buf, midx_hash, &pdata,
1409-
commits, commits_nr, ctx.pack_order,
1425+
if (write_midx_bitmap(&ctx, object_dir,
1426+
midx_hash, &pdata, commits, commits_nr,
14101427
flags) < 0) {
14111428
error(_("could not write multi-pack bitmap"));
14121429
result = 1;

pack-bitmap-write.c

+49-16
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "alloc.h"
2626
#include "refs.h"
2727
#include "strmap.h"
28+
#include "midx.h"
29+
#include "pack-revindex.h"
2830

2931
struct bitmapped_commit {
3032
struct commit *commit;
@@ -42,14 +44,16 @@ static inline int bitmap_writer_nr_selected_commits(struct bitmap_writer *writer
4244
}
4345

4446
void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r,
45-
struct packing_data *pdata)
47+
struct packing_data *pdata,
48+
struct multi_pack_index *midx)
4649
{
4750
memset(writer, 0, sizeof(struct bitmap_writer));
4851
if (writer->bitmaps)
4952
BUG("bitmap writer already initialized");
5053
writer->bitmaps = kh_init_oid_map();
5154
writer->pseudo_merge_commits = kh_init_oid_map();
5255
writer->to_pack = pdata;
56+
writer->midx = midx;
5357

5458
string_list_init_dup(&writer->pseudo_merge_groups);
5559

@@ -112,6 +116,11 @@ void bitmap_writer_build_type_index(struct bitmap_writer *writer,
112116
struct pack_idx_entry **index)
113117
{
114118
uint32_t i;
119+
uint32_t base_objects = 0;
120+
121+
if (writer->midx)
122+
base_objects = writer->midx->num_objects +
123+
writer->midx->num_objects_in_base;
115124

116125
writer->commits = ewah_new();
117126
writer->trees = ewah_new();
@@ -141,19 +150,19 @@ void bitmap_writer_build_type_index(struct bitmap_writer *writer,
141150

142151
switch (real_type) {
143152
case OBJ_COMMIT:
144-
ewah_set(writer->commits, i);
153+
ewah_set(writer->commits, i + base_objects);
145154
break;
146155

147156
case OBJ_TREE:
148-
ewah_set(writer->trees, i);
157+
ewah_set(writer->trees, i + base_objects);
149158
break;
150159

151160
case OBJ_BLOB:
152-
ewah_set(writer->blobs, i);
161+
ewah_set(writer->blobs, i + base_objects);
153162
break;
154163

155164
case OBJ_TAG:
156-
ewah_set(writer->tags, i);
165+
ewah_set(writer->tags, i + base_objects);
157166
break;
158167

159168
default:
@@ -206,19 +215,37 @@ void bitmap_writer_push_commit(struct bitmap_writer *writer,
206215
static uint32_t find_object_pos(struct bitmap_writer *writer,
207216
const struct object_id *oid, int *found)
208217
{
209-
struct object_entry *entry = packlist_find(writer->to_pack, oid);
218+
struct object_entry *entry;
219+
220+
entry = packlist_find(writer->to_pack, oid);
221+
if (entry) {
222+
uint32_t base_objects = 0;
223+
if (writer->midx)
224+
base_objects = writer->midx->num_objects +
225+
writer->midx->num_objects_in_base;
210226

211-
if (!entry) {
212227
if (found)
213-
*found = 0;
214-
warning("Failed to write bitmap index. Packfile doesn't have full closure "
215-
"(object %s is missing)", oid_to_hex(oid));
216-
return 0;
228+
*found = 1;
229+
return oe_in_pack_pos(writer->to_pack, entry) + base_objects;
230+
} else if (writer->midx) {
231+
uint32_t at, pos;
232+
233+
if (!bsearch_midx(oid, writer->midx, &at))
234+
goto missing;
235+
if (midx_to_pack_pos(writer->midx, at, &pos) < 0)
236+
goto missing;
237+
238+
if (found)
239+
*found = 1;
240+
return pos;
217241
}
218242

243+
missing:
219244
if (found)
220-
*found = 1;
221-
return oe_in_pack_pos(writer->to_pack, entry);
245+
*found = 0;
246+
warning("Failed to write bitmap index. Packfile doesn't have full closure "
247+
"(object %s is missing)", oid_to_hex(oid));
248+
return 0;
222249
}
223250

224251
static void compute_xor_offsets(struct bitmap_writer *writer)
@@ -585,7 +612,7 @@ int bitmap_writer_build(struct bitmap_writer *writer)
585612
struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
586613
struct prio_queue tree_queue = { NULL };
587614
struct bitmap_index *old_bitmap;
588-
uint32_t *mapping;
615+
uint32_t *mapping = NULL;
589616
int closed = 1; /* until proven otherwise */
590617

591618
if (writer->show_progress)
@@ -1018,7 +1045,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer,
10181045
struct strbuf tmp_file = STRBUF_INIT;
10191046
struct hashfile *f;
10201047
off_t *offsets = NULL;
1021-
uint32_t i;
1048+
uint32_t i, base_objects;
10221049

10231050
struct bitmap_disk_header header;
10241051

@@ -1044,6 +1071,12 @@ void bitmap_writer_finish(struct bitmap_writer *writer,
10441071
if (options & BITMAP_OPT_LOOKUP_TABLE)
10451072
CALLOC_ARRAY(offsets, writer->to_pack->nr_objects);
10461073

1074+
if (writer->midx)
1075+
base_objects = writer->midx->num_objects +
1076+
writer->midx->num_objects_in_base;
1077+
else
1078+
base_objects = 0;
1079+
10471080
for (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++) {
10481081
struct bitmapped_commit *stored = &writer->selected[i];
10491082
int commit_pos = oid_pos(&stored->commit->object.oid, index,
@@ -1052,7 +1085,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer,
10521085

10531086
if (commit_pos < 0)
10541087
BUG(_("trying to write commit not in index"));
1055-
stored->commit_pos = commit_pos;
1088+
stored->commit_pos = commit_pos + base_objects;
10561089
}
10571090

10581091
write_selected_commits_v1(writer, f, offsets);

pack-bitmap.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ struct bitmap_writer {
111111

112112
kh_oid_map_t *bitmaps;
113113
struct packing_data *to_pack;
114+
struct multi_pack_index *midx; /* if appending to a MIDX chain */
114115

115116
struct bitmapped_commit *selected;
116117
unsigned int selected_nr, selected_alloc;
@@ -125,7 +126,8 @@ struct bitmap_writer {
125126
};
126127

127128
void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r,
128-
struct packing_data *pdata);
129+
struct packing_data *pdata,
130+
struct multi_pack_index *midx);
129131
void bitmap_writer_show_progress(struct bitmap_writer *writer, int show);
130132
void bitmap_writer_set_checksum(struct bitmap_writer *writer,
131133
const unsigned char *sha1);

t/t5334-incremental-multi-pack-index.sh

+84
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,88 @@ test_expect_success 'convert incremental to non-incremental' '
4545

4646
compare_results_with_midx 'non-incremental MIDX conversion'
4747

48+
write_midx_layer () {
49+
n=1
50+
if test -f $midx_chain
51+
then
52+
n="$(($(wc -l <$midx_chain) + 1))"
53+
fi
54+
55+
for i in 1 2
56+
do
57+
test_commit $n.$i &&
58+
git repack -d || return 1
59+
done &&
60+
git multi-pack-index write --bitmap --incremental
61+
}
62+
63+
test_expect_success 'write initial MIDX layer' '
64+
git repack -ad &&
65+
write_midx_layer
66+
'
67+
68+
test_expect_success 'read bitmap from first MIDX layer' '
69+
git rev-list --test-bitmap 1.2
70+
'
71+
72+
test_expect_success 'write another MIDX layer' '
73+
write_midx_layer
74+
'
75+
76+
test_expect_success 'midx verify with multiple layers' '
77+
git multi-pack-index verify
78+
'
79+
80+
test_expect_success 'read bitmap from second MIDX layer' '
81+
git rev-list --test-bitmap 2.2
82+
'
83+
84+
test_expect_success 'read earlier bitmap from second MIDX layer' '
85+
git rev-list --test-bitmap 1.2
86+
'
87+
88+
test_expect_success 'show object from first pack' '
89+
git cat-file -p 1.1
90+
'
91+
92+
test_expect_success 'show object from second pack' '
93+
git cat-file -p 2.2
94+
'
95+
96+
for reuse in false single multi
97+
do
98+
test_expect_success "full clone (pack.allowPackReuse=$reuse)" '
99+
rm -fr clone.git &&
100+
101+
git config pack.allowPackReuse $reuse &&
102+
git clone --no-local --bare . clone.git
103+
'
104+
done
105+
106+
test_expect_success 'relink existing MIDX layer' '
107+
rm -fr "$midxdir" &&
108+
109+
GIT_TEST_MIDX_WRITE_REV=1 git multi-pack-index write --bitmap &&
110+
111+
midx_hash="$(test-tool read-midx --checksum $objdir)" &&
112+
113+
test_path_is_file "$packdir/multi-pack-index" &&
114+
test_path_is_file "$packdir/multi-pack-index-$midx_hash.bitmap" &&
115+
test_path_is_file "$packdir/multi-pack-index-$midx_hash.rev" &&
116+
117+
test_commit another &&
118+
git repack -d &&
119+
git multi-pack-index write --bitmap --incremental &&
120+
121+
test_path_is_missing "$packdir/multi-pack-index" &&
122+
test_path_is_missing "$packdir/multi-pack-index-$midx_hash.bitmap" &&
123+
test_path_is_missing "$packdir/multi-pack-index-$midx_hash.rev" &&
124+
125+
test_path_is_file "$midxdir/multi-pack-index-$midx_hash.midx" &&
126+
test_path_is_file "$midxdir/multi-pack-index-$midx_hash.bitmap" &&
127+
test_path_is_file "$midxdir/multi-pack-index-$midx_hash.rev" &&
128+
test_line_count = 2 "$midx_chain"
129+
130+
'
131+
48132
test_done

0 commit comments

Comments
 (0)