Skip to content

Commit 668e8c8

Browse files
ttaylorrgitster
authored andcommitted
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]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 077cadd commit 668e8c8

File tree

5 files changed

+171
-34
lines changed

5 files changed

+171
-34
lines changed

builtin/pack-objects.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1342,7 +1342,8 @@ static void write_pack_file(void)
13421342

13431343
if (write_bitmap_index) {
13441344
bitmap_writer_init(&bitmap_writer,
1345-
the_repository, &to_pack);
1345+
the_repository, &to_pack,
1346+
NULL);
13461347
bitmap_writer_set_checksum(&bitmap_writer, hash);
13471348
bitmap_writer_build_type_index(&bitmap_writer,
13481349
written_list);

midx-write.c

Lines changed: 33 additions & 16 deletions
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
const 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);
@@ -826,20 +832,26 @@ static struct commit **find_commits_for_midx_bitmap(uint32_t *indexed_commits_nr
826832
return cb.commits;
827833
}
828834

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

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

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

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

@@ -876,19 +889,19 @@ static int write_midx_bitmap(const char *midx_name,
876889
* bitmap_writer_finish().
877890
*/
878891
for (i = 0; i < pdata->nr_objects; i++)
879-
index[pack_order[i]] = &pdata->objects[i].idx;
892+
index[ctx->pack_order[i]] = &pdata->objects[i].idx;
880893

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

886899
bitmap_writer_set_checksum(&writer, midx_hash);
887-
bitmap_writer_finish(&writer, index, bitmap_name, options);
900+
bitmap_writer_finish(&writer, index, bitmap_name.buf, options);
888901

889902
cleanup:
890903
free(index);
891-
free(bitmap_name);
904+
strbuf_release(&bitmap_name);
892905
bitmap_writer_free(&writer);
893906

894907
trace2_region_leave("midx", "write_midx_bitmap", the_repository);
@@ -1072,8 +1085,6 @@ static int write_midx_internal(const char *object_dir,
10721085
trace2_region_enter("midx", "write_midx_internal", the_repository);
10731086

10741087
ctx.incremental = !!(flags & MIDX_WRITE_INCREMENTAL);
1075-
if (ctx.incremental && (flags & MIDX_WRITE_BITMAP))
1076-
die(_("cannot write incremental MIDX with bitmap"));
10771088

10781089
if (ctx.incremental)
10791090
strbuf_addf(&midx_name,
@@ -1115,6 +1126,12 @@ static int write_midx_internal(const char *object_dir,
11151126
if (ctx.incremental) {
11161127
struct multi_pack_index *m = ctx.base_midx;
11171128
while (m) {
1129+
if (flags & MIDX_WRITE_BITMAP && load_midx_revindex(m)) {
1130+
error(_("could not load reverse index for MIDX %s"),
1131+
hash_to_hex(get_midx_checksum(m)));
1132+
result = 1;
1133+
goto cleanup;
1134+
}
11181135
ctx.num_multi_pack_indexes_before++;
11191136
m = m->base_midx;
11201137
}
@@ -1381,7 +1398,7 @@ static int write_midx_internal(const char *object_dir,
13811398

13821399
if (flags & MIDX_WRITE_REV_INDEX &&
13831400
git_env_bool("GIT_TEST_MIDX_WRITE_REV", 0))
1384-
write_midx_reverse_index(midx_name.buf, midx_hash, &ctx);
1401+
write_midx_reverse_index(&ctx, object_dir, midx_hash);
13851402

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

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

pack-bitmap-write.c

Lines changed: 49 additions & 16 deletions
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

@@ -104,6 +108,11 @@ void bitmap_writer_build_type_index(struct bitmap_writer *writer,
104108
struct pack_idx_entry **index)
105109
{
106110
uint32_t i;
111+
uint32_t base_objects = 0;
112+
113+
if (writer->midx)
114+
base_objects = writer->midx->num_objects +
115+
writer->midx->num_objects_in_base;
107116

108117
writer->commits = ewah_new();
109118
writer->trees = ewah_new();
@@ -133,19 +142,19 @@ void bitmap_writer_build_type_index(struct bitmap_writer *writer,
133142

134143
switch (real_type) {
135144
case OBJ_COMMIT:
136-
ewah_set(writer->commits, i);
145+
ewah_set(writer->commits, i + base_objects);
137146
break;
138147

139148
case OBJ_TREE:
140-
ewah_set(writer->trees, i);
149+
ewah_set(writer->trees, i + base_objects);
141150
break;
142151

143152
case OBJ_BLOB:
144-
ewah_set(writer->blobs, i);
153+
ewah_set(writer->blobs, i + base_objects);
145154
break;
146155

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

151160
default:
@@ -198,19 +207,37 @@ void bitmap_writer_push_commit(struct bitmap_writer *writer,
198207
static uint32_t find_object_pos(struct bitmap_writer *writer,
199208
const struct object_id *oid, int *found)
200209
{
201-
struct object_entry *entry = packlist_find(writer->to_pack, oid);
210+
struct object_entry *entry;
211+
212+
entry = packlist_find(writer->to_pack, oid);
213+
if (entry) {
214+
uint32_t base_objects = 0;
215+
if (writer->midx)
216+
base_objects = writer->midx->num_objects +
217+
writer->midx->num_objects_in_base;
202218

203-
if (!entry) {
204219
if (found)
205-
*found = 0;
206-
warning("Failed to write bitmap index. Packfile doesn't have full closure "
207-
"(object %s is missing)", oid_to_hex(oid));
208-
return 0;
220+
*found = 1;
221+
return oe_in_pack_pos(writer->to_pack, entry) + base_objects;
222+
} else if (writer->midx) {
223+
uint32_t at, pos;
224+
225+
if (!bsearch_midx(oid, writer->midx, &at))
226+
goto missing;
227+
if (midx_to_pack_pos(writer->midx, at, &pos) < 0)
228+
goto missing;
229+
230+
if (found)
231+
*found = 1;
232+
return pos;
209233
}
210234

235+
missing:
211236
if (found)
212-
*found = 1;
213-
return oe_in_pack_pos(writer->to_pack, entry);
237+
*found = 0;
238+
warning("Failed to write bitmap index. Packfile doesn't have full closure "
239+
"(object %s is missing)", oid_to_hex(oid));
240+
return 0;
214241
}
215242

216243
static void compute_xor_offsets(struct bitmap_writer *writer)
@@ -577,7 +604,7 @@ int bitmap_writer_build(struct bitmap_writer *writer)
577604
struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
578605
struct prio_queue tree_queue = { NULL };
579606
struct bitmap_index *old_bitmap;
580-
uint32_t *mapping;
607+
uint32_t *mapping = NULL;
581608
int closed = 1; /* until proven otherwise */
582609

583610
if (writer->show_progress)
@@ -1010,7 +1037,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer,
10101037
struct strbuf tmp_file = STRBUF_INIT;
10111038
struct hashfile *f;
10121039
off_t *offsets = NULL;
1013-
uint32_t i;
1040+
uint32_t i, base_objects;
10141041

10151042
struct bitmap_disk_header header;
10161043

@@ -1036,6 +1063,12 @@ void bitmap_writer_finish(struct bitmap_writer *writer,
10361063
if (options & BITMAP_OPT_LOOKUP_TABLE)
10371064
CALLOC_ARRAY(offsets, writer->to_pack->nr_objects);
10381065

1066+
if (writer->midx)
1067+
base_objects = writer->midx->num_objects +
1068+
writer->midx->num_objects_in_base;
1069+
else
1070+
base_objects = 0;
1071+
10391072
for (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++) {
10401073
struct bitmapped_commit *stored = &writer->selected[i];
10411074
int commit_pos = oid_pos(&stored->commit->object.oid, index,
@@ -1044,7 +1077,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer,
10441077

10451078
if (commit_pos < 0)
10461079
BUG(_("trying to write commit not in index"));
1047-
stored->commit_pos = commit_pos;
1080+
stored->commit_pos = commit_pos + base_objects;
10481081
}
10491082

10501083
write_selected_commits_v1(writer, f, offsets);

pack-bitmap.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ struct bitmap_writer {
110110

111111
kh_oid_map_t *bitmaps;
112112
struct packing_data *to_pack;
113+
struct multi_pack_index *midx; /* if appending to a MIDX chain */
113114

114115
struct bitmapped_commit *selected;
115116
unsigned int selected_nr, selected_alloc;
@@ -124,7 +125,8 @@ struct bitmap_writer {
124125
};
125126

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

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

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,88 @@ test_expect_success 'convert incremental to non-incremental' '
4343

4444
compare_results_with_midx 'non-incremental MIDX conversion'
4545

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

0 commit comments

Comments
 (0)