summaryrefslogtreecommitdiff
path: root/pack-bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'pack-bitmap.c')
-rw-r--r--pack-bitmap.c494
1 files changed, 353 insertions, 141 deletions
diff --git a/pack-bitmap.c b/pack-bitmap.c
index 9d9b8c4bfb..aa67cb40ab 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -1,4 +1,4 @@
-#define USE_THE_REPOSITORY_VARIABLE
+#define DISABLE_SIGN_COMPARE_WARNINGS
#include "git-compat-util.h"
#include "commit.h"
@@ -54,6 +54,16 @@ struct bitmap_index {
struct packed_git *pack;
struct multi_pack_index *midx;
+ /*
+ * If using a multi-pack index chain, 'base' points to the
+ * bitmap index corresponding to this bitmap's midx->base_midx.
+ *
+ * base_nr indicates how many layers precede this one, and is
+ * zero when base is NULL.
+ */
+ struct bitmap_index *base;
+ uint32_t base_nr;
+
/* mmapped buffer of the whole bitmap index */
unsigned char *map;
size_t map_size; /* size of the mmaped buffer */
@@ -71,6 +81,23 @@ struct bitmap_index {
struct ewah_bitmap *blobs;
struct ewah_bitmap *tags;
+ /*
+ * Type index arrays when this bitmap is associated with an
+ * incremental multi-pack index chain.
+ *
+ * If n is the number of unique layers in the MIDX chain, then
+ * commits_all[n-1] is this structs 'commits' field,
+ * commits_all[n-2] is the commits field of this bitmap's
+ * 'base', and so on.
+ *
+ * When associated either with a non-incremental MIDX or a
+ * single packfile, these arrays each contain a single element.
+ */
+ struct ewah_bitmap **commits_all;
+ struct ewah_bitmap **trees_all;
+ struct ewah_bitmap **blobs_all;
+ struct ewah_bitmap **tags_all;
+
/* Map from object ID -> `stored_bitmap` for all the bitmapped commits */
kh_oid_map_t *bitmaps;
@@ -170,6 +197,15 @@ static struct ewah_bitmap *read_bitmap_1(struct bitmap_index *index)
return read_bitmap(index->map, index->map_size, &index->map_pos);
}
+static uint32_t bitmap_num_objects_total(struct bitmap_index *index)
+{
+ if (index->midx) {
+ struct multi_pack_index *m = index->midx;
+ return m->num_objects + m->num_objects_in_base;
+ }
+ return index->pack->num_objects;
+}
+
static uint32_t bitmap_num_objects(struct bitmap_index *index)
{
if (index->midx)
@@ -177,12 +213,21 @@ static uint32_t bitmap_num_objects(struct bitmap_index *index)
return index->pack->num_objects;
}
+static struct repository *bitmap_repo(struct bitmap_index *bitmap_git)
+{
+ if (bitmap_is_midx(bitmap_git))
+ return bitmap_git->midx->repo;
+ return bitmap_git->pack->repo;
+}
+
static int load_bitmap_header(struct bitmap_index *index)
{
struct bitmap_disk_header *header = (void *)index->map;
- size_t header_size = sizeof(*header) - GIT_MAX_RAWSZ + the_hash_algo->rawsz;
+ const struct git_hash_algo *hash_algo = bitmap_repo(index)->hash_algo;
+
+ size_t header_size = sizeof(*header) - GIT_MAX_RAWSZ + hash_algo->rawsz;
- if (index->map_size < header_size + the_hash_algo->rawsz)
+ if (index->map_size < header_size + hash_algo->rawsz)
return error(_("corrupted bitmap index (too small)"));
if (memcmp(header->magic, BITMAP_IDX_SIGNATURE, sizeof(BITMAP_IDX_SIGNATURE)) != 0)
@@ -196,7 +241,7 @@ static int load_bitmap_header(struct bitmap_index *index)
{
uint32_t flags = ntohs(header->options);
size_t cache_size = st_mult(bitmap_num_objects(index), sizeof(uint32_t));
- unsigned char *index_end = index->map + index->map_size - the_hash_algo->rawsz;
+ unsigned char *index_end = index->map + index->map_size - hash_algo->rawsz;
if ((flags & BITMAP_OPT_FULL_DAG) == 0)
BUG("unsupported options for bitmap index file "
@@ -368,8 +413,15 @@ static int load_bitmap_entries_v1(struct bitmap_index *index)
char *midx_bitmap_filename(struct multi_pack_index *midx)
{
struct strbuf buf = STRBUF_INIT;
- get_midx_filename_ext(&buf, midx->object_dir, get_midx_checksum(midx),
- MIDX_EXT_BITMAP);
+ if (midx->has_chain)
+ get_split_midx_filename_ext(midx->repo->hash_algo, &buf,
+ midx->object_dir,
+ get_midx_checksum(midx),
+ MIDX_EXT_BITMAP);
+ else
+ get_midx_filename_ext(midx->repo->hash_algo, &buf,
+ midx->object_dir, get_midx_checksum(midx),
+ MIDX_EXT_BITMAP);
return strbuf_detach(&buf, NULL);
}
@@ -389,8 +441,7 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git,
struct stat st;
char *bitmap_name = midx_bitmap_filename(midx);
int fd = git_open(bitmap_name);
- uint32_t i, preferred_pack;
- struct packed_git *preferred;
+ uint32_t i;
if (fd < 0) {
if (errno != ENOENT)
@@ -408,8 +459,8 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git,
if (bitmap_git->pack || bitmap_git->midx) {
struct strbuf buf = STRBUF_INIT;
- get_midx_filename(&buf, midx->object_dir);
- trace2_data_string("bitmap", the_repository,
+ get_midx_filename(midx->repo->hash_algo, &buf, midx->object_dir);
+ trace2_data_string("bitmap", bitmap_repo(bitmap_git),
"ignoring extra midx bitmap file", buf.buf);
close(fd);
strbuf_release(&buf);
@@ -427,7 +478,7 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git,
goto cleanup;
if (!hasheq(get_midx_checksum(bitmap_git->midx), bitmap_git->checksum,
- the_repository->hash_algo)) {
+ bitmap_repo(bitmap_git)->hash_algo)) {
error(_("checksum doesn't match in MIDX and bitmap"));
goto cleanup;
}
@@ -437,24 +488,19 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git,
goto cleanup;
}
- for (i = 0; i < bitmap_git->midx->num_packs; i++) {
- if (prepare_midx_pack(the_repository, bitmap_git->midx, i)) {
+ for (i = 0; i < bitmap_git->midx->num_packs + bitmap_git->midx->num_packs_in_base; i++) {
+ if (prepare_midx_pack(bitmap_repo(bitmap_git), bitmap_git->midx, i)) {
warning(_("could not open pack %s"),
bitmap_git->midx->pack_names[i]);
goto cleanup;
}
}
- if (midx_preferred_pack(bitmap_git->midx, &preferred_pack) < 0) {
- warning(_("could not determine MIDX preferred pack"));
- goto cleanup;
- }
-
- preferred = bitmap_git->midx->packs[preferred_pack];
- if (!is_pack_valid(preferred)) {
- warning(_("preferred pack (%s) is invalid"),
- preferred->pack_name);
- goto cleanup;
+ if (midx->base_midx) {
+ bitmap_git->base = prepare_midx_bitmap_git(midx->base_midx);
+ bitmap_git->base_nr = bitmap_git->base->base_nr + 1;
+ } else {
+ bitmap_git->base_nr = 0;
}
return 0;
@@ -492,8 +538,9 @@ static int open_pack_bitmap_1(struct bitmap_index *bitmap_git, struct packed_git
}
if (bitmap_git->pack || bitmap_git->midx) {
- trace2_data_string("bitmap", the_repository,
- "ignoring extra bitmap file", packfile->pack_name);
+ trace2_data_string("bitmap", bitmap_repo(bitmap_git),
+ "ignoring extra bitmap file",
+ packfile->pack_name);
close(fd);
return -1;
}
@@ -507,6 +554,7 @@ static int open_pack_bitmap_1(struct bitmap_index *bitmap_git, struct packed_git
bitmap_git->map_size = xsize_t(st.st_size);
bitmap_git->map = xmmap(NULL, bitmap_git->map_size, PROT_READ, MAP_PRIVATE, fd, 0);
bitmap_git->map_pos = 0;
+ bitmap_git->base_nr = 0;
close(fd);
if (load_bitmap_header(bitmap_git) < 0) {
@@ -518,16 +566,15 @@ static int open_pack_bitmap_1(struct bitmap_index *bitmap_git, struct packed_git
return -1;
}
- trace2_data_string("bitmap", the_repository, "opened bitmap file",
- packfile->pack_name);
+ trace2_data_string("bitmap", bitmap_repo(bitmap_git),
+ "opened bitmap file", packfile->pack_name);
return 0;
}
static int load_reverse_index(struct repository *r, struct bitmap_index *bitmap_git)
{
if (bitmap_is_midx(bitmap_git)) {
- uint32_t i;
- int ret;
+ struct multi_pack_index *m;
/*
* The multi-pack-index's .rev file is already loaded via
@@ -536,17 +583,47 @@ static int load_reverse_index(struct repository *r, struct bitmap_index *bitmap_
* But we still need to open the individual pack .rev files,
* since we will need to make use of them in pack-objects.
*/
- for (i = 0; i < bitmap_git->midx->num_packs; i++) {
- ret = load_pack_revindex(r, bitmap_git->midx->packs[i]);
- if (ret)
- return ret;
+ for (m = bitmap_git->midx; m; m = m->base_midx) {
+ uint32_t i;
+ int ret;
+
+ for (i = 0; i < m->num_packs; i++) {
+ ret = load_pack_revindex(r, m->packs[i]);
+ if (ret)
+ return ret;
+ }
}
return 0;
}
return load_pack_revindex(r, bitmap_git->pack);
}
-static int load_bitmap(struct repository *r, struct bitmap_index *bitmap_git)
+static void load_all_type_bitmaps(struct bitmap_index *bitmap_git)
+{
+ struct bitmap_index *curr = bitmap_git;
+ size_t i = bitmap_git->base_nr;
+
+ ALLOC_ARRAY(bitmap_git->commits_all, bitmap_git->base_nr + 1);
+ ALLOC_ARRAY(bitmap_git->trees_all, bitmap_git->base_nr + 1);
+ ALLOC_ARRAY(bitmap_git->blobs_all, bitmap_git->base_nr + 1);
+ ALLOC_ARRAY(bitmap_git->tags_all, bitmap_git->base_nr + 1);
+
+ while (curr) {
+ bitmap_git->commits_all[i] = curr->commits;
+ bitmap_git->trees_all[i] = curr->trees;
+ bitmap_git->blobs_all[i] = curr->blobs;
+ bitmap_git->tags_all[i] = curr->tags;
+
+ curr = curr->base;
+ if (curr && !i)
+ BUG("unexpected number of bitmap layers, expected %"PRIu32,
+ bitmap_git->base_nr + 1);
+ i -= 1;
+ }
+}
+
+static int load_bitmap(struct repository *r, struct bitmap_index *bitmap_git,
+ int recursing)
{
assert(bitmap_git->map);
@@ -565,6 +642,16 @@ static int load_bitmap(struct repository *r, struct bitmap_index *bitmap_git)
if (!bitmap_git->table_lookup && load_bitmap_entries_v1(bitmap_git) < 0)
goto failed;
+ if (bitmap_git->base) {
+ if (!bitmap_is_midx(bitmap_git))
+ BUG("non-MIDX bitmap has non-NULL base bitmap index");
+ if (load_bitmap(r, bitmap_git->base, 1) < 0)
+ goto failed;
+ }
+
+ if (!recursing)
+ load_all_type_bitmaps(bitmap_git);
+
return 0;
failed:
@@ -640,7 +727,7 @@ struct bitmap_index *prepare_bitmap_git(struct repository *r)
{
struct bitmap_index *bitmap_git = xcalloc(1, sizeof(*bitmap_git));
- if (!open_bitmap(r, bitmap_git) && !load_bitmap(r, bitmap_git))
+ if (!open_bitmap(r, bitmap_git) && !load_bitmap(r, bitmap_git, 0))
return bitmap_git;
free_bitmap_index(bitmap_git);
@@ -649,10 +736,9 @@ struct bitmap_index *prepare_bitmap_git(struct repository *r)
struct bitmap_index *prepare_midx_bitmap_git(struct multi_pack_index *midx)
{
- struct repository *r = the_repository;
struct bitmap_index *bitmap_git = xcalloc(1, sizeof(*bitmap_git));
- if (!open_midx_bitmap_1(bitmap_git, midx) && !load_bitmap(r, bitmap_git))
+ if (!open_midx_bitmap_1(bitmap_git, midx))
return bitmap_git;
free_bitmap_index(bitmap_git);
@@ -897,26 +983,42 @@ corrupt:
return NULL;
}
-struct ewah_bitmap *bitmap_for_commit(struct bitmap_index *bitmap_git,
- struct commit *commit)
+static struct ewah_bitmap *find_bitmap_for_commit(struct bitmap_index *bitmap_git,
+ struct commit *commit,
+ struct bitmap_index **found)
{
- khiter_t hash_pos = kh_get_oid_map(bitmap_git->bitmaps,
- commit->object.oid);
+ khiter_t hash_pos;
+ if (!bitmap_git)
+ return NULL;
+
+ hash_pos = kh_get_oid_map(bitmap_git->bitmaps, commit->object.oid);
if (hash_pos >= kh_end(bitmap_git->bitmaps)) {
struct stored_bitmap *bitmap = NULL;
if (!bitmap_git->table_lookup)
- return NULL;
+ return find_bitmap_for_commit(bitmap_git->base, commit,
+ found);
/* this is a fairly hot codepath - no trace2_region please */
/* NEEDSWORK: cache misses aren't recorded */
bitmap = lazy_bitmap_for_commit(bitmap_git, commit);
if (!bitmap)
- return NULL;
+ return find_bitmap_for_commit(bitmap_git->base, commit,
+ found);
+ if (found)
+ *found = bitmap_git;
return lookup_stored_bitmap(bitmap);
}
+ if (found)
+ *found = bitmap_git;
return lookup_stored_bitmap(kh_value(bitmap_git->bitmaps, hash_pos));
}
+struct ewah_bitmap *bitmap_for_commit(struct bitmap_index *bitmap_git,
+ struct commit *commit)
+{
+ return find_bitmap_for_commit(bitmap_git, commit, NULL);
+}
+
static inline int bitmap_position_extended(struct bitmap_index *bitmap_git,
const struct object_id *oid)
{
@@ -925,7 +1027,7 @@ static inline int bitmap_position_extended(struct bitmap_index *bitmap_git,
if (pos < kh_end(positions)) {
int bitmap_pos = kh_value(positions, pos);
- return bitmap_pos + bitmap_num_objects(bitmap_git);
+ return bitmap_pos + bitmap_num_objects_total(bitmap_git);
}
return -1;
@@ -935,7 +1037,7 @@ static inline int bitmap_position_packfile(struct bitmap_index *bitmap_git,
const struct object_id *oid)
{
uint32_t pos;
- off_t offset = find_pack_entry_one(oid->hash, bitmap_git->pack);
+ off_t offset = find_pack_entry_one(oid, bitmap_git->pack);
if (!offset)
return -1;
@@ -993,7 +1095,7 @@ static int ext_index_add_object(struct bitmap_index *bitmap_git,
bitmap_pos = kh_value(eindex->positions, hash_pos);
}
- return bitmap_pos + bitmap_num_objects(bitmap_git);
+ return bitmap_pos + bitmap_num_objects_total(bitmap_git);
}
struct bitmap_show_data {
@@ -1025,10 +1127,15 @@ static unsigned apply_pseudo_merges_for_commit_1(struct bitmap_index *bitmap_git
struct commit *commit,
uint32_t commit_pos)
{
- int ret;
+ struct bitmap_index *curr = bitmap_git;
+ int ret = 0;
- ret = apply_pseudo_merges_for_commit(&bitmap_git->pseudo_merges,
- result, commit, commit_pos);
+ while (curr) {
+ ret += apply_pseudo_merges_for_commit(&curr->pseudo_merges,
+ result, commit,
+ commit_pos);
+ curr = curr->base;
+ }
if (ret)
pseudo_merges_satisfied_nr += ret;
@@ -1213,6 +1320,7 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git,
{
struct bitmap_boundary_cb cb;
struct object_list *root;
+ struct repository *repo;
unsigned int i;
unsigned int tmp_blobs, tmp_trees, tmp_tags;
int any_missing = 0;
@@ -1222,6 +1330,8 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git,
cb.base = bitmap_new();
object_array_init(&cb.boundary);
+ repo = bitmap_repo(bitmap_git);
+
revs->ignore_missing_links = 1;
if (bitmap_git->pseudo_merges.nr) {
@@ -1270,7 +1380,7 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git,
tmp_blobs = revs->blob_objects;
tmp_trees = revs->tree_objects;
- tmp_tags = revs->blob_objects;
+ tmp_tags = revs->tag_objects;
revs->blob_objects = 0;
revs->tree_objects = 0;
revs->tag_objects = 0;
@@ -1280,31 +1390,31 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git,
* revision walk to (a) OR in any bitmaps that are UNINTERESTING
* between the tips and boundary, and (b) record the boundary.
*/
- trace2_region_enter("pack-bitmap", "boundary-prepare", the_repository);
+ trace2_region_enter("pack-bitmap", "boundary-prepare", repo);
if (prepare_revision_walk(revs))
die("revision walk setup failed");
- trace2_region_leave("pack-bitmap", "boundary-prepare", the_repository);
+ trace2_region_leave("pack-bitmap", "boundary-prepare", repo);
- trace2_region_enter("pack-bitmap", "boundary-traverse", the_repository);
+ trace2_region_enter("pack-bitmap", "boundary-traverse", repo);
revs->boundary = 1;
traverse_commit_list_filtered(revs,
show_boundary_commit,
show_boundary_object,
&cb, NULL);
revs->boundary = 0;
- trace2_region_leave("pack-bitmap", "boundary-traverse", the_repository);
+ trace2_region_leave("pack-bitmap", "boundary-traverse", repo);
revs->blob_objects = tmp_blobs;
revs->tree_objects = tmp_trees;
revs->tag_objects = tmp_tags;
reset_revision_walk();
- clear_object_flags(UNINTERESTING);
+ clear_object_flags(repo, UNINTERESTING);
/*
* Then add the boundary commit(s) as fill-in traversal tips.
*/
- trace2_region_enter("pack-bitmap", "boundary-fill-in", the_repository);
+ trace2_region_enter("pack-bitmap", "boundary-fill-in", repo);
for (i = 0; i < cb.boundary.nr; i++) {
struct object *obj = cb.boundary.objects[i].item;
if (bitmap_walk_contains(bitmap_git, cb.base, &obj->oid))
@@ -1314,7 +1424,7 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git,
}
if (revs->pending.nr)
cb.base = fill_in_bitmap(bitmap_git, revs, cb.base, NULL);
- trace2_region_leave("pack-bitmap", "boundary-fill-in", the_repository);
+ trace2_region_leave("pack-bitmap", "boundary-fill-in", repo);
cleanup:
object_array_clear(&cb.boundary);
@@ -1340,11 +1450,17 @@ struct ewah_bitmap *pseudo_merge_bitmap_for_commit(struct bitmap_index *bitmap_g
if (pos < 0 || pos >= bitmap_num_objects(bitmap_git))
goto done;
+ /*
+ * Use bitmap-relative positions instead of offsetting
+ * by bitmap_git->num_objects_in_base because we use
+ * this to find a match in pseudo_merge_for_parents(),
+ * and pseudo-merge groups cannot span multiple bitmap
+ * layers.
+ */
bitmap_set(parents, pos);
}
- match = pseudo_merge_for_parents(&bitmap_git->pseudo_merges,
- parents);
+ match = pseudo_merge_for_parents(&bitmap_git->pseudo_merges, parents);
done:
bitmap_free(parents);
@@ -1390,8 +1506,8 @@ static struct bitmap *find_objects(struct bitmap_index *bitmap_git,
}
base = bitmap_new();
- if (!cascade_pseudo_merges_1(bitmap_git, base, roots_bitmap))
- bitmap_free(roots_bitmap);
+ cascade_pseudo_merges_1(bitmap_git, base, roots_bitmap);
+ bitmap_free(roots_bitmap);
}
/*
@@ -1498,7 +1614,9 @@ static void show_extended_objects(struct bitmap_index *bitmap_git,
for (i = 0; i < eindex->count; ++i) {
struct object *obj;
- if (!bitmap_get(objects, st_add(bitmap_num_objects(bitmap_git), i)))
+ if (!bitmap_get(objects,
+ st_add(bitmap_num_objects_total(bitmap_git),
+ i)))
continue;
obj = eindex->objects[i];
@@ -1511,25 +1629,29 @@ static void show_extended_objects(struct bitmap_index *bitmap_git,
}
}
-static void init_type_iterator(struct ewah_iterator *it,
+static void init_type_iterator(struct ewah_or_iterator *it,
struct bitmap_index *bitmap_git,
enum object_type type)
{
switch (type) {
case OBJ_COMMIT:
- ewah_iterator_init(it, bitmap_git->commits);
+ ewah_or_iterator_init(it, bitmap_git->commits_all,
+ bitmap_git->base_nr + 1);
break;
case OBJ_TREE:
- ewah_iterator_init(it, bitmap_git->trees);
+ ewah_or_iterator_init(it, bitmap_git->trees_all,
+ bitmap_git->base_nr + 1);
break;
case OBJ_BLOB:
- ewah_iterator_init(it, bitmap_git->blobs);
+ ewah_or_iterator_init(it, bitmap_git->blobs_all,
+ bitmap_git->base_nr + 1);
break;
case OBJ_TAG:
- ewah_iterator_init(it, bitmap_git->tags);
+ ewah_or_iterator_init(it, bitmap_git->tags_all,
+ bitmap_git->base_nr + 1);
break;
default:
@@ -1546,7 +1668,7 @@ static void show_objects_for_type(
size_t i = 0;
uint32_t offset;
- struct ewah_iterator it;
+ struct ewah_or_iterator it;
eword_t filter;
struct bitmap *objects = bitmap_git->result;
@@ -1554,7 +1676,7 @@ static void show_objects_for_type(
init_type_iterator(&it, bitmap_git, object_type);
for (i = 0; i < objects->word_alloc &&
- ewah_iterator_next(&filter, &it); i++) {
+ ewah_or_iterator_next(&filter, &it); i++) {
eword_t word = objects->words[i] & filter;
size_t pos = (i * BITS_IN_EWORD);
@@ -1581,7 +1703,7 @@ static void show_objects_for_type(
nth_midxed_object_oid(&oid, m, index_pos);
pack_id = nth_midxed_pack_int_id(m, index_pos);
- pack = bitmap_git->midx->packs[pack_id];
+ pack = nth_midxed_pack(bitmap_git->midx, pack_id);
} else {
index_pos = pack_pos_to_index(bitmap_git->pack, pos + offset);
ofs = pack_pos_to_offset(bitmap_git->pack, pos + offset);
@@ -1596,6 +1718,8 @@ static void show_objects_for_type(
show_reach(&oid, object_type, 0, hash, pack, ofs);
}
}
+
+ ewah_or_iterator_release(&it);
}
static int in_bitmapped_pack(struct bitmap_index *bitmap_git,
@@ -1609,7 +1733,7 @@ static int in_bitmapped_pack(struct bitmap_index *bitmap_git,
if (bsearch_midx(&object->oid, bitmap_git->midx, NULL))
return 1;
} else {
- if (find_pack_entry_one(object->oid.hash, bitmap_git->pack) > 0)
+ if (find_pack_entry_one(&object->oid, bitmap_git->pack) > 0)
return 1;
}
}
@@ -1647,7 +1771,7 @@ static void filter_bitmap_exclude_type(struct bitmap_index *bitmap_git,
{
struct eindex *eindex = &bitmap_git->ext_index;
struct bitmap *tips;
- struct ewah_iterator it;
+ struct ewah_or_iterator it;
eword_t mask;
uint32_t i;
@@ -1664,7 +1788,7 @@ static void filter_bitmap_exclude_type(struct bitmap_index *bitmap_git,
* packfile.
*/
for (i = 0, init_type_iterator(&it, bitmap_git, type);
- i < to_filter->word_alloc && ewah_iterator_next(&mask, &it);
+ i < to_filter->word_alloc && ewah_or_iterator_next(&mask, &it);
i++) {
if (i < tips->word_alloc)
mask &= ~tips->words[i];
@@ -1677,13 +1801,14 @@ static void filter_bitmap_exclude_type(struct bitmap_index *bitmap_git,
* them individually.
*/
for (i = 0; i < eindex->count; i++) {
- size_t pos = st_add(i, bitmap_num_objects(bitmap_git));
+ size_t pos = st_add(i, bitmap_num_objects_total(bitmap_git));
if (eindex->objects[i]->type == type &&
bitmap_get(to_filter, pos) &&
!bitmap_get(tips, pos))
bitmap_unset(to_filter, pos);
}
+ ewah_or_iterator_release(&it);
bitmap_free(tips);
}
@@ -1703,7 +1828,7 @@ static unsigned long get_size_by_pos(struct bitmap_index *bitmap_git,
oi.sizep = &size;
- if (pos < bitmap_num_objects(bitmap_git)) {
+ if (pos < bitmap_num_objects_total(bitmap_git)) {
struct packed_git *pack;
off_t ofs;
@@ -1711,23 +1836,26 @@ static unsigned long get_size_by_pos(struct bitmap_index *bitmap_git,
uint32_t midx_pos = pack_pos_to_midx(bitmap_git->midx, pos);
uint32_t pack_id = nth_midxed_pack_int_id(bitmap_git->midx, midx_pos);
- pack = bitmap_git->midx->packs[pack_id];
+ pack = nth_midxed_pack(bitmap_git->midx, pack_id);
ofs = nth_midxed_offset(bitmap_git->midx, midx_pos);
} else {
pack = bitmap_git->pack;
ofs = pack_pos_to_offset(pack, pos);
}
- if (packed_object_info(the_repository, pack, ofs, &oi) < 0) {
+ if (packed_object_info(bitmap_repo(bitmap_git), pack, ofs,
+ &oi) < 0) {
struct object_id oid;
nth_bitmap_object_oid(bitmap_git, &oid,
pack_pos_to_index(pack, pos));
die(_("unable to get size of %s"), oid_to_hex(&oid));
}
} else {
+ size_t eindex_pos = pos - bitmap_num_objects_total(bitmap_git);
struct eindex *eindex = &bitmap_git->ext_index;
- struct object *obj = eindex->objects[pos - bitmap_num_objects(bitmap_git)];
- if (oid_object_info_extended(the_repository, &obj->oid, &oi, 0) < 0)
+ struct object *obj = eindex->objects[eindex_pos];
+ if (oid_object_info_extended(bitmap_repo(bitmap_git), &obj->oid,
+ &oi, 0) < 0)
die(_("unable to get size of %s"), oid_to_hex(&obj->oid));
}
@@ -1741,14 +1869,14 @@ static void filter_bitmap_blob_limit(struct bitmap_index *bitmap_git,
{
struct eindex *eindex = &bitmap_git->ext_index;
struct bitmap *tips;
- struct ewah_iterator it;
+ struct ewah_or_iterator it;
eword_t mask;
uint32_t i;
tips = find_tip_objects(bitmap_git, tip_objects, OBJ_BLOB);
for (i = 0, init_type_iterator(&it, bitmap_git, OBJ_BLOB);
- i < to_filter->word_alloc && ewah_iterator_next(&mask, &it);
+ i < to_filter->word_alloc && ewah_or_iterator_next(&mask, &it);
i++) {
eword_t word = to_filter->words[i] & mask;
unsigned offset;
@@ -1776,6 +1904,7 @@ static void filter_bitmap_blob_limit(struct bitmap_index *bitmap_git,
bitmap_unset(to_filter, pos);
}
+ ewah_or_iterator_release(&it);
bitmap_free(tips);
}
@@ -1878,7 +2007,7 @@ static void filter_packed_objects_from_bitmap(struct bitmap_index *bitmap_git,
uint32_t objects_nr;
size_t i, pos;
- objects_nr = bitmap_num_objects(bitmap_git);
+ objects_nr = bitmap_num_objects_total(bitmap_git);
pos = objects_nr / BITS_IN_EWORD;
if (pos > result->word_alloc)
@@ -1889,7 +2018,8 @@ static void filter_packed_objects_from_bitmap(struct bitmap_index *bitmap_git,
bitmap_unset(result, i);
for (i = 0; i < eindex->count; ++i) {
- if (has_object_pack(&eindex->objects[i]->oid))
+ if (has_object_pack(bitmap_repo(bitmap_git),
+ &eindex->objects[i]->oid))
bitmap_unset(result, objects_nr + i);
}
}
@@ -1907,6 +2037,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
struct bitmap *haves_bitmap = NULL;
struct bitmap_index *bitmap_git;
+ struct repository *repo;
/*
* We can't do pathspec limiting with bitmaps, because we don't know
@@ -1929,7 +2060,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
struct object *object = revs->pending.objects[i].item;
if (object->type == OBJ_NONE)
- parse_object_or_die(&object->oid, NULL);
+ parse_object_or_die(revs->repo, &object->oid, NULL);
while (object->type == OBJ_TAG) {
struct tag *tag = (struct tag *) object;
@@ -1939,7 +2070,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
else
object_list_insert(object, &wants);
- object = parse_object_or_die(get_tagged_oid(tag), NULL);
+ object = parse_object_or_die(revs->repo, get_tagged_oid(tag), NULL);
object->flags |= (tag->object.flags & UNINTERESTING);
}
@@ -1974,24 +2105,26 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
* from disk. this is the point of no return; after this the rev_list
* becomes invalidated and we must perform the revwalk through bitmaps
*/
- if (load_bitmap(revs->repo, bitmap_git) < 0)
+ if (load_bitmap(revs->repo, bitmap_git, 0) < 0)
goto cleanup;
if (!use_boundary_traversal)
object_array_clear(&revs->pending);
+ repo = bitmap_repo(bitmap_git);
+
if (haves) {
if (use_boundary_traversal) {
- trace2_region_enter("pack-bitmap", "haves/boundary", the_repository);
+ trace2_region_enter("pack-bitmap", "haves/boundary", repo);
haves_bitmap = find_boundary_objects(bitmap_git, revs, haves);
- trace2_region_leave("pack-bitmap", "haves/boundary", the_repository);
+ trace2_region_leave("pack-bitmap", "haves/boundary", repo);
} else {
- trace2_region_enter("pack-bitmap", "haves/classic", the_repository);
+ trace2_region_enter("pack-bitmap", "haves/classic", repo);
revs->ignore_missing_links = 1;
haves_bitmap = find_objects(bitmap_git, revs, haves, NULL);
reset_revision_walk();
revs->ignore_missing_links = 0;
- trace2_region_leave("pack-bitmap", "haves/classic", the_repository);
+ trace2_region_leave("pack-bitmap", "haves/classic", repo);
}
if (!haves_bitmap)
@@ -2025,17 +2158,17 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
object_list_free(&wants);
object_list_free(&haves);
- trace2_data_intmax("bitmap", the_repository, "pseudo_merges_satisfied",
+ trace2_data_intmax("bitmap", repo, "pseudo_merges_satisfied",
pseudo_merges_satisfied_nr);
- trace2_data_intmax("bitmap", the_repository, "pseudo_merges_cascades",
+ trace2_data_intmax("bitmap", repo, "pseudo_merges_cascades",
pseudo_merges_cascades_nr);
- trace2_data_intmax("bitmap", the_repository, "bitmap/hits",
+ trace2_data_intmax("bitmap", repo, "bitmap/hits",
existing_bitmaps_hits_nr);
- trace2_data_intmax("bitmap", the_repository, "bitmap/misses",
+ trace2_data_intmax("bitmap", repo, "bitmap/misses",
existing_bitmaps_misses_nr);
- trace2_data_intmax("bitmap", the_repository, "bitmap/roots_with_bitmap",
+ trace2_data_intmax("bitmap", repo, "bitmap/roots_with_bitmap",
roots_with_bitmaps_nr);
- trace2_data_intmax("bitmap", the_repository, "bitmap/roots_without_bitmap",
+ trace2_data_intmax("bitmap", repo, "bitmap/roots_without_bitmap",
roots_without_bitmaps_nr);
return bitmap_git;
@@ -2256,7 +2389,7 @@ void reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
struct bitmap **reuse_out,
int multi_pack_reuse)
{
- struct repository *r = the_repository;
+ struct repository *r = bitmap_repo(bitmap_git);
struct bitmapped_pack *packs = NULL;
struct bitmap *result = bitmap_git->result;
struct bitmap *reuse;
@@ -2273,7 +2406,8 @@ void reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
multi_pack_reuse = 0;
if (multi_pack_reuse) {
- for (i = 0; i < bitmap_git->midx->num_packs; i++) {
+ struct multi_pack_index *m = bitmap_git->midx;
+ for (i = 0; i < m->num_packs + m->num_packs_in_base; i++) {
struct bitmapped_pack pack;
if (nth_bitmapped_pack(r, bitmap_git->midx, &pack, i) < 0) {
warning(_("unable to load pack: '%s', disabling pack-reuse"),
@@ -2285,8 +2419,10 @@ void reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
if (!pack.bitmap_nr)
continue;
- ALLOC_GROW(packs, packs_nr + 1, packs_alloc);
- memcpy(&packs[packs_nr++], &pack, sizeof(pack));
+ if (is_pack_valid(pack.p)) {
+ ALLOC_GROW(packs, packs_nr + 1, packs_alloc);
+ memcpy(&packs[packs_nr++], &pack, sizeof(pack));
+ }
objects_nr += pack.p->num_objects;
}
@@ -2297,14 +2433,18 @@ void reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
uint32_t pack_int_id;
if (bitmap_is_midx(bitmap_git)) {
+ struct multi_pack_index *m = bitmap_git->midx;
uint32_t preferred_pack_pos;
- if (midx_preferred_pack(bitmap_git->midx, &preferred_pack_pos) < 0) {
+ while (m->base_midx)
+ m = m->base_midx;
+
+ if (midx_preferred_pack(m, &preferred_pack_pos) < 0) {
warning(_("unable to compute preferred pack, disabling pack-reuse"));
return;
}
- pack = bitmap_git->midx->packs[preferred_pack_pos];
+ pack = nth_midxed_pack(m, preferred_pack_pos);
pack_int_id = preferred_pack_pos;
} else {
pack = bitmap_git->pack;
@@ -2320,16 +2460,22 @@ void reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
pack_int_id = -1;
}
- ALLOC_GROW(packs, packs_nr + 1, packs_alloc);
- packs[packs_nr].p = pack;
- packs[packs_nr].pack_int_id = pack_int_id;
- packs[packs_nr].bitmap_nr = pack->num_objects;
- packs[packs_nr].bitmap_pos = 0;
- packs[packs_nr].from_midx = bitmap_git->midx;
+ if (is_pack_valid(pack)) {
+ ALLOC_GROW(packs, packs_nr + 1, packs_alloc);
+ packs[packs_nr].p = pack;
+ packs[packs_nr].pack_int_id = pack_int_id;
+ packs[packs_nr].bitmap_nr = pack->num_objects;
+ packs[packs_nr].bitmap_pos = 0;
+ packs[packs_nr].from_midx = bitmap_git->midx;
+ packs_nr++;
+ }
- objects_nr = packs[packs_nr++].bitmap_nr;
+ objects_nr = pack->num_objects;
}
+ if (!packs_nr)
+ return;
+
word_alloc = objects_nr / BITS_IN_EWORD;
if (objects_nr % BITS_IN_EWORD)
word_alloc++;
@@ -2390,12 +2536,12 @@ static uint32_t count_object_type(struct bitmap_index *bitmap_git,
struct eindex *eindex = &bitmap_git->ext_index;
uint32_t i = 0, count = 0;
- struct ewah_iterator it;
+ struct ewah_or_iterator it;
eword_t filter;
init_type_iterator(&it, bitmap_git, type);
- while (i < objects->word_alloc && ewah_iterator_next(&filter, &it)) {
+ while (i < objects->word_alloc && ewah_or_iterator_next(&filter, &it)) {
eword_t word = objects->words[i++] & filter;
count += ewah_bit_popcount64(word);
}
@@ -2403,10 +2549,12 @@ static uint32_t count_object_type(struct bitmap_index *bitmap_git,
for (i = 0; i < eindex->count; ++i) {
if (eindex->objects[i]->type == type &&
bitmap_get(objects,
- st_add(bitmap_num_objects(bitmap_git), i)))
+ st_add(bitmap_num_objects_total(bitmap_git), i)))
count++;
}
+ ewah_or_iterator_release(&it);
+
return count;
}
@@ -2438,6 +2586,8 @@ struct bitmap_test_data {
struct bitmap *tags;
struct progress *prg;
size_t seen;
+
+ struct bitmap_test_data *base_tdata;
};
static void test_bitmap_type(struct bitmap_test_data *tdata,
@@ -2446,6 +2596,11 @@ static void test_bitmap_type(struct bitmap_test_data *tdata,
enum object_type bitmap_type = OBJ_NONE;
int bitmaps_nr = 0;
+ if (bitmap_is_midx(tdata->bitmap_git)) {
+ while (pos < tdata->bitmap_git->midx->num_objects_in_base)
+ tdata = tdata->base_tdata;
+ }
+
if (bitmap_get(tdata->commits, pos)) {
bitmap_type = OBJ_COMMIT;
bitmaps_nr++;
@@ -2509,13 +2664,57 @@ static void test_show_commit(struct commit *commit, void *data)
display_progress(tdata->prg, ++tdata->seen);
}
+static uint32_t bitmap_total_entry_count(struct bitmap_index *bitmap_git)
+{
+ uint32_t total = 0;
+ do {
+ total = st_add(total, bitmap_git->entry_count);
+ bitmap_git = bitmap_git->base;
+ } while (bitmap_git);
+
+ return total;
+}
+
+static void bitmap_test_data_prepare(struct bitmap_test_data *tdata,
+ struct bitmap_index *bitmap_git)
+{
+ memset(tdata, 0, sizeof(struct bitmap_test_data));
+
+ tdata->bitmap_git = bitmap_git;
+ tdata->base = bitmap_new();
+ tdata->commits = ewah_to_bitmap(bitmap_git->commits);
+ tdata->trees = ewah_to_bitmap(bitmap_git->trees);
+ tdata->blobs = ewah_to_bitmap(bitmap_git->blobs);
+ tdata->tags = ewah_to_bitmap(bitmap_git->tags);
+
+ if (bitmap_git->base) {
+ tdata->base_tdata = xmalloc(sizeof(struct bitmap_test_data));
+ bitmap_test_data_prepare(tdata->base_tdata, bitmap_git->base);
+ }
+}
+
+static void bitmap_test_data_release(struct bitmap_test_data *tdata)
+{
+ if (!tdata)
+ return;
+
+ bitmap_test_data_release(tdata->base_tdata);
+ free(tdata->base_tdata);
+
+ bitmap_free(tdata->base);
+ bitmap_free(tdata->commits);
+ bitmap_free(tdata->trees);
+ bitmap_free(tdata->blobs);
+ bitmap_free(tdata->tags);
+}
+
void test_bitmap_walk(struct rev_info *revs)
{
struct object *root;
struct bitmap *result = NULL;
size_t result_popcnt;
struct bitmap_test_data tdata;
- struct bitmap_index *bitmap_git;
+ struct bitmap_index *bitmap_git, *found;
struct ewah_bitmap *bm;
if (!(bitmap_git = prepare_bitmap_git(revs->repo)))
@@ -2524,17 +2723,28 @@ void test_bitmap_walk(struct rev_info *revs)
if (revs->pending.nr != 1)
die(_("you must specify exactly one commit to test"));
- fprintf_ln(stderr, "Bitmap v%d test (%d entries%s)",
+ fprintf_ln(stderr, "Bitmap v%d test (%d entries%s, %d total)",
bitmap_git->version,
bitmap_git->entry_count,
- bitmap_git->table_lookup ? "" : " loaded");
+ bitmap_git->table_lookup ? "" : " loaded",
+ bitmap_total_entry_count(bitmap_git));
root = revs->pending.objects[0].item;
- bm = bitmap_for_commit(bitmap_git, (struct commit *)root);
+ bm = find_bitmap_for_commit(bitmap_git, (struct commit *)root, &found);
if (bm) {
fprintf_ln(stderr, "Found bitmap for '%s'. %d bits / %08x checksum",
- oid_to_hex(&root->oid), (int)bm->bit_size, ewah_checksum(bm));
+ oid_to_hex(&root->oid),
+ (int)bm->bit_size, ewah_checksum(bm));
+
+ if (bitmap_is_midx(found))
+ fprintf_ln(stderr, "Located via MIDX '%s'.",
+ hash_to_hex_algop(get_midx_checksum(found->midx),
+ revs->repo->hash_algo));
+ else
+ fprintf_ln(stderr, "Located via pack '%s'.",
+ hash_to_hex_algop(found->pack->hash,
+ revs->repo->hash_algo));
result = ewah_to_bitmap(bm);
}
@@ -2551,14 +2761,10 @@ void test_bitmap_walk(struct rev_info *revs)
if (prepare_revision_walk(revs))
die(_("revision walk setup failed"));
- tdata.bitmap_git = bitmap_git;
- tdata.base = bitmap_new();
- tdata.commits = ewah_to_bitmap(bitmap_git->commits);
- tdata.trees = ewah_to_bitmap(bitmap_git->trees);
- tdata.blobs = ewah_to_bitmap(bitmap_git->blobs);
- tdata.tags = ewah_to_bitmap(bitmap_git->tags);
- tdata.prg = start_progress("Verifying bitmap entries", result_popcnt);
- tdata.seen = 0;
+ bitmap_test_data_prepare(&tdata, bitmap_git);
+ tdata.prg = start_progress(revs->repo,
+ "Verifying bitmap entries",
+ result_popcnt);
traverse_commit_list(revs, &test_show_commit, &test_show_object, &tdata);
@@ -2570,11 +2776,7 @@ void test_bitmap_walk(struct rev_info *revs)
die(_("mismatch in bitmap results"));
bitmap_free(result);
- bitmap_free(tdata.base);
- bitmap_free(tdata.commits);
- bitmap_free(tdata.trees);
- bitmap_free(tdata.blobs);
- bitmap_free(tdata.tags);
+ bitmap_test_data_release(&tdata);
free_bitmap_index(bitmap_git);
}
@@ -2792,7 +2994,7 @@ int rebuild_bitmap(const uint32_t *reposition,
uint32_t *create_bitmap_mapping(struct bitmap_index *bitmap_git,
struct packing_data *mapping)
{
- struct repository *r = the_repository;
+ struct repository *r = bitmap_repo(bitmap_git);
uint32_t i, num_objects;
uint32_t *reposition;
@@ -2802,7 +3004,7 @@ uint32_t *create_bitmap_mapping(struct bitmap_index *bitmap_git,
BUG("rebuild_existing_bitmaps: missing required rev-cache "
"extension");
- num_objects = bitmap_num_objects(bitmap_git);
+ num_objects = bitmap_num_objects_total(bitmap_git);
CALLOC_ARRAY(reposition, num_objects);
for (i = 0; i < num_objects; ++i) {
@@ -2838,6 +3040,10 @@ void free_bitmap_index(struct bitmap_index *b)
ewah_pool_free(b->trees);
ewah_pool_free(b->blobs);
ewah_pool_free(b->tags);
+ free(b->commits_all);
+ free(b->trees_all);
+ free(b->blobs_all);
+ free(b->tags_all);
if (b->bitmaps) {
struct stored_bitmap *sb;
kh_foreach_value(b->bitmaps, sb, {
@@ -2865,6 +3071,7 @@ void free_bitmap_index(struct bitmap_index *b)
close_midx_revindex(b->midx);
}
free_pseudo_merge_map(&b->pseudo_merges);
+ free_bitmap_index(b->base);
free(b);
}
@@ -2880,13 +3087,13 @@ static off_t get_disk_usage_for_type(struct bitmap_index *bitmap_git,
{
struct bitmap *result = bitmap_git->result;
off_t total = 0;
- struct ewah_iterator it;
+ struct ewah_or_iterator it;
eword_t filter;
size_t i;
init_type_iterator(&it, bitmap_git, object_type);
for (i = 0; i < result->word_alloc &&
- ewah_iterator_next(&filter, &it); i++) {
+ ewah_or_iterator_next(&filter, &it); i++) {
eword_t word = result->words[i] & filter;
size_t base = (i * BITS_IN_EWORD);
unsigned offset;
@@ -2906,7 +3113,7 @@ static off_t get_disk_usage_for_type(struct bitmap_index *bitmap_git,
off_t offset = nth_midxed_offset(bitmap_git->midx, midx_pos);
uint32_t pack_id = nth_midxed_pack_int_id(bitmap_git->midx, midx_pos);
- struct packed_git *pack = bitmap_git->midx->packs[pack_id];
+ struct packed_git *pack = nth_midxed_pack(bitmap_git->midx, pack_id);
if (offset_to_pack_pos(pack, offset, &pack_pos) < 0) {
struct object_id oid;
@@ -2927,6 +3134,8 @@ static off_t get_disk_usage_for_type(struct bitmap_index *bitmap_git,
}
}
+ ewah_or_iterator_release(&it);
+
return total;
}
@@ -2945,10 +3154,12 @@ static off_t get_disk_usage_for_extended(struct bitmap_index *bitmap_git)
struct object *obj = eindex->objects[i];
if (!bitmap_get(result,
- st_add(bitmap_num_objects(bitmap_git), i)))
+ st_add(bitmap_num_objects_total(bitmap_git),
+ i)))
continue;
- if (oid_object_info_extended(the_repository, &obj->oid, &oi, 0) < 0)
+ if (oid_object_info_extended(bitmap_repo(bitmap_git), &obj->oid,
+ &oi, 0) < 0)
die(_("unable to get disk usage of '%s'"),
oid_to_hex(&obj->oid));
@@ -3005,7 +3216,8 @@ int bitmap_is_preferred_refname(struct repository *r, const char *refname)
return 0;
}
-static int verify_bitmap_file(const char *name)
+static int verify_bitmap_file(const struct git_hash_algo *algop,
+ const char *name)
{
struct stat st;
unsigned char *data;
@@ -3021,7 +3233,7 @@ static int verify_bitmap_file(const char *name)
data = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
- if (!hashfile_checksum_valid(data, st.st_size))
+ if (!hashfile_checksum_valid(algop, data, st.st_size))
res = error(_("bitmap file '%s' has invalid checksum"),
name);
@@ -3036,14 +3248,14 @@ int verify_bitmap_files(struct repository *r)
for (struct multi_pack_index *m = get_multi_pack_index(r);
m; m = m->next) {
char *midx_bitmap_name = midx_bitmap_filename(m);
- res |= verify_bitmap_file(midx_bitmap_name);
+ res |= verify_bitmap_file(r->hash_algo, midx_bitmap_name);
free(midx_bitmap_name);
}
for (struct packed_git *p = get_all_packs(r);
p; p = p->next) {
char *pack_bitmap_name = pack_bitmap_filename(p);
- res |= verify_bitmap_file(pack_bitmap_name);
+ res |= verify_bitmap_file(r->hash_algo, pack_bitmap_name);
free(pack_bitmap_name);
}