зеркало из https://github.com/microsoft/git.git
pack-bitmap: remove bitmap_git global variable
Remove the bitmap_git global variable. Instead, generate on demand an instance of struct bitmap_index for code that needs to access it. This allows us significant control over the lifetime of instances of struct bitmap_index. In particular, packs can now be closed without worrying if an unnecessarily long-lived "pack" field in struct bitmap_index still points to it. The bitmap API is also clearer in that we need to first obtain a struct bitmap_index, then we use it. This patch raises two potential issues: (1) memory for the struct bitmap_index is allocated without being freed, and (2) prepare_bitmap_git() and prepare_bitmap_walk() can reuse a previously loaded bitmap. For (1), this will be dealt with in a subsequent patch in this patch set that also deals with freeing the contents of the struct bitmap_index (which were not freed previously, because they have global scope). For (2), current bitmap users only load the bitmap once at most (note that pack-objects can use bitmaps or write bitmaps, but not both at the same time), so support for reuse has no effect - and future users can pass around the struct bitmap_index * obtained if they need to do 2 or more things with the same bitmap. Helped-by: Stefan Beller <sbeller@google.com> Signed-off-by: Jonathan Tan <jonathantanmy@google.com> Helped-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
53f9a3e157
Коммит
3ae5fa0768
|
@ -2929,11 +2929,13 @@ static int pack_options_allow_reuse(void)
|
|||
|
||||
static int get_object_list_from_bitmap(struct rev_info *revs)
|
||||
{
|
||||
if (prepare_bitmap_walk(revs) < 0)
|
||||
struct bitmap_index *bitmap_git;
|
||||
if (!(bitmap_git = prepare_bitmap_walk(revs)))
|
||||
return -1;
|
||||
|
||||
if (pack_options_allow_reuse() &&
|
||||
!reuse_partial_packfile_from_bitmap(
|
||||
bitmap_git,
|
||||
&reuse_packfile,
|
||||
&reuse_packfile_objects,
|
||||
&reuse_packfile_offset)) {
|
||||
|
@ -2942,7 +2944,7 @@ static int get_object_list_from_bitmap(struct rev_info *revs)
|
|||
display_progress(progress_state, nr_result);
|
||||
}
|
||||
|
||||
traverse_bitmap_commit_list(&add_object_entry_from_bitmap);
|
||||
traverse_bitmap_commit_list(bitmap_git, &add_object_entry_from_bitmap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "reflog-walk.h"
|
||||
#include "oidset.h"
|
||||
#include "packfile.h"
|
||||
#include "object-store.h"
|
||||
|
||||
static const char rev_list_usage[] =
|
||||
"git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
|
||||
|
@ -514,8 +515,9 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
|||
if (revs.count && !revs.left_right && !revs.cherry_mark) {
|
||||
uint32_t commit_count;
|
||||
int max_count = revs.max_count;
|
||||
if (!prepare_bitmap_walk(&revs)) {
|
||||
count_bitmap_commit_list(&commit_count, NULL, NULL, NULL);
|
||||
struct bitmap_index *bitmap_git;
|
||||
if ((bitmap_git = prepare_bitmap_walk(&revs))) {
|
||||
count_bitmap_commit_list(bitmap_git, &commit_count, NULL, NULL, NULL);
|
||||
if (max_count >= 0 && max_count < commit_count)
|
||||
commit_count = max_count;
|
||||
printf("%d\n", commit_count);
|
||||
|
@ -523,8 +525,9 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
|||
}
|
||||
} else if (revs.max_count < 0 &&
|
||||
revs.tag_objects && revs.tree_objects && revs.blob_objects) {
|
||||
if (!prepare_bitmap_walk(&revs)) {
|
||||
traverse_bitmap_commit_list(&show_object_fast);
|
||||
struct bitmap_index *bitmap_git;
|
||||
if ((bitmap_git = prepare_bitmap_walk(&revs))) {
|
||||
traverse_bitmap_commit_list(bitmap_git, &show_object_fast);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -360,11 +360,13 @@ static int date_compare(const void *_a, const void *_b)
|
|||
|
||||
void bitmap_writer_reuse_bitmaps(struct packing_data *to_pack)
|
||||
{
|
||||
if (prepare_bitmap_git() < 0)
|
||||
struct bitmap_index *bitmap_git;
|
||||
if (!(bitmap_git = prepare_bitmap_git()))
|
||||
return;
|
||||
|
||||
writer.reused = kh_init_sha1();
|
||||
rebuild_existing_bitmaps(to_pack, writer.reused, writer.show_progress);
|
||||
rebuild_existing_bitmaps(bitmap_git, to_pack, writer.reused,
|
||||
writer.show_progress);
|
||||
}
|
||||
|
||||
static struct ewah_bitmap *find_reused_bitmap(const unsigned char *sha1)
|
||||
|
|
317
pack-bitmap.c
317
pack-bitmap.c
|
@ -25,14 +25,14 @@ struct stored_bitmap {
|
|||
};
|
||||
|
||||
/*
|
||||
* The currently active bitmap index. By design, repositories only have
|
||||
* The active bitmap index for a repository. By design, repositories only have
|
||||
* a single bitmap index available (the index for the biggest packfile in
|
||||
* the repository), since bitmap indexes need full closure.
|
||||
*
|
||||
* If there is more than one bitmap index available (e.g. because of alternates),
|
||||
* the active bitmap index is the largest one.
|
||||
*/
|
||||
static struct bitmap_index {
|
||||
struct bitmap_index {
|
||||
/* Packfile to which this bitmap index belongs to */
|
||||
struct packed_git *pack;
|
||||
|
||||
|
@ -90,8 +90,7 @@ static struct bitmap_index {
|
|||
unsigned int version;
|
||||
|
||||
unsigned loaded : 1;
|
||||
|
||||
} bitmap_git;
|
||||
};
|
||||
|
||||
static struct ewah_bitmap *lookup_stored_bitmap(struct stored_bitmap *st)
|
||||
{
|
||||
|
@ -259,7 +258,7 @@ static char *pack_bitmap_filename(struct packed_git *p)
|
|||
return xstrfmt("%.*s.bitmap", (int)len, p->pack_name);
|
||||
}
|
||||
|
||||
static int open_pack_bitmap_1(struct packed_git *packfile)
|
||||
static int open_pack_bitmap_1(struct bitmap_index *bitmap_git, struct packed_git *packfile)
|
||||
{
|
||||
int fd;
|
||||
struct stat st;
|
||||
|
@ -280,117 +279,121 @@ static int open_pack_bitmap_1(struct packed_git *packfile)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (bitmap_git.pack) {
|
||||
if (bitmap_git->pack) {
|
||||
warning("ignoring extra bitmap file: %s", packfile->pack_name);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bitmap_git.pack = packfile;
|
||||
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->pack = packfile;
|
||||
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;
|
||||
close(fd);
|
||||
|
||||
if (load_bitmap_header(&bitmap_git) < 0) {
|
||||
munmap(bitmap_git.map, bitmap_git.map_size);
|
||||
bitmap_git.map = NULL;
|
||||
bitmap_git.map_size = 0;
|
||||
if (load_bitmap_header(bitmap_git) < 0) {
|
||||
munmap(bitmap_git->map, bitmap_git->map_size);
|
||||
bitmap_git->map = NULL;
|
||||
bitmap_git->map_size = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_pack_bitmap(void)
|
||||
static int load_pack_bitmap(struct bitmap_index *bitmap_git)
|
||||
{
|
||||
assert(bitmap_git.map && !bitmap_git.loaded);
|
||||
assert(bitmap_git->map && !bitmap_git->loaded);
|
||||
|
||||
bitmap_git.bitmaps = kh_init_sha1();
|
||||
bitmap_git.ext_index.positions = kh_init_sha1_pos();
|
||||
load_pack_revindex(bitmap_git.pack);
|
||||
bitmap_git->bitmaps = kh_init_sha1();
|
||||
bitmap_git->ext_index.positions = kh_init_sha1_pos();
|
||||
load_pack_revindex(bitmap_git->pack);
|
||||
|
||||
if (!(bitmap_git.commits = read_bitmap_1(&bitmap_git)) ||
|
||||
!(bitmap_git.trees = read_bitmap_1(&bitmap_git)) ||
|
||||
!(bitmap_git.blobs = read_bitmap_1(&bitmap_git)) ||
|
||||
!(bitmap_git.tags = read_bitmap_1(&bitmap_git)))
|
||||
if (!(bitmap_git->commits = read_bitmap_1(bitmap_git)) ||
|
||||
!(bitmap_git->trees = read_bitmap_1(bitmap_git)) ||
|
||||
!(bitmap_git->blobs = read_bitmap_1(bitmap_git)) ||
|
||||
!(bitmap_git->tags = read_bitmap_1(bitmap_git)))
|
||||
goto failed;
|
||||
|
||||
if (load_bitmap_entries_v1(&bitmap_git) < 0)
|
||||
if (load_bitmap_entries_v1(bitmap_git) < 0)
|
||||
goto failed;
|
||||
|
||||
bitmap_git.loaded = 1;
|
||||
bitmap_git->loaded = 1;
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
munmap(bitmap_git.map, bitmap_git.map_size);
|
||||
bitmap_git.map = NULL;
|
||||
bitmap_git.map_size = 0;
|
||||
munmap(bitmap_git->map, bitmap_git->map_size);
|
||||
bitmap_git->map = NULL;
|
||||
bitmap_git->map_size = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int open_pack_bitmap(void)
|
||||
static int open_pack_bitmap(struct bitmap_index *bitmap_git)
|
||||
{
|
||||
struct packed_git *p;
|
||||
int ret = -1;
|
||||
|
||||
assert(!bitmap_git.map && !bitmap_git.loaded);
|
||||
assert(!bitmap_git->map && !bitmap_git->loaded);
|
||||
|
||||
for (p = get_packed_git(the_repository); p; p = p->next) {
|
||||
if (open_pack_bitmap_1(p) == 0)
|
||||
if (open_pack_bitmap_1(bitmap_git, p) == 0)
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int prepare_bitmap_git(void)
|
||||
struct bitmap_index *prepare_bitmap_git(void)
|
||||
{
|
||||
if (bitmap_git.loaded)
|
||||
return 0;
|
||||
struct bitmap_index *bitmap_git = xcalloc(1, sizeof(*bitmap_git));
|
||||
|
||||
if (!open_pack_bitmap())
|
||||
return load_pack_bitmap();
|
||||
if (!open_pack_bitmap(bitmap_git) && !load_pack_bitmap(bitmap_git))
|
||||
return bitmap_git;
|
||||
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct include_data {
|
||||
struct bitmap_index *bitmap_git;
|
||||
struct bitmap *base;
|
||||
struct bitmap *seen;
|
||||
};
|
||||
|
||||
static inline int bitmap_position_extended(const unsigned char *sha1)
|
||||
static inline int bitmap_position_extended(struct bitmap_index *bitmap_git,
|
||||
const unsigned char *sha1)
|
||||
{
|
||||
khash_sha1_pos *positions = bitmap_git.ext_index.positions;
|
||||
khash_sha1_pos *positions = bitmap_git->ext_index.positions;
|
||||
khiter_t pos = kh_get_sha1_pos(positions, sha1);
|
||||
|
||||
if (pos < kh_end(positions)) {
|
||||
int bitmap_pos = kh_value(positions, pos);
|
||||
return bitmap_pos + bitmap_git.pack->num_objects;
|
||||
return bitmap_pos + bitmap_git->pack->num_objects;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int bitmap_position_packfile(const unsigned char *sha1)
|
||||
static inline int bitmap_position_packfile(struct bitmap_index *bitmap_git,
|
||||
const unsigned char *sha1)
|
||||
{
|
||||
off_t offset = find_pack_entry_one(sha1, bitmap_git.pack);
|
||||
off_t offset = find_pack_entry_one(sha1, bitmap_git->pack);
|
||||
if (!offset)
|
||||
return -1;
|
||||
|
||||
return find_revindex_position(bitmap_git.pack, offset);
|
||||
return find_revindex_position(bitmap_git->pack, offset);
|
||||
}
|
||||
|
||||
static int bitmap_position(const unsigned char *sha1)
|
||||
static int bitmap_position(struct bitmap_index *bitmap_git,
|
||||
const unsigned char *sha1)
|
||||
{
|
||||
int pos = bitmap_position_packfile(sha1);
|
||||
return (pos >= 0) ? pos : bitmap_position_extended(sha1);
|
||||
int pos = bitmap_position_packfile(bitmap_git, sha1);
|
||||
return (pos >= 0) ? pos : bitmap_position_extended(bitmap_git, sha1);
|
||||
}
|
||||
|
||||
static int ext_index_add_object(struct object *object, const char *name)
|
||||
static int ext_index_add_object(struct bitmap_index *bitmap_git,
|
||||
struct object *object, const char *name)
|
||||
{
|
||||
struct eindex *eindex = &bitmap_git.ext_index;
|
||||
struct eindex *eindex = &bitmap_git->ext_index;
|
||||
|
||||
khiter_t hash_pos;
|
||||
int hash_ret;
|
||||
|
@ -413,27 +416,34 @@ static int ext_index_add_object(struct object *object, const char *name)
|
|||
bitmap_pos = kh_value(eindex->positions, hash_pos);
|
||||
}
|
||||
|
||||
return bitmap_pos + bitmap_git.pack->num_objects;
|
||||
return bitmap_pos + bitmap_git->pack->num_objects;
|
||||
}
|
||||
|
||||
static void show_object(struct object *object, const char *name, void *data)
|
||||
struct bitmap_show_data {
|
||||
struct bitmap_index *bitmap_git;
|
||||
struct bitmap *base;
|
||||
};
|
||||
|
||||
static void show_object(struct object *object, const char *name, void *data_)
|
||||
{
|
||||
struct bitmap *base = data;
|
||||
struct bitmap_show_data *data = data_;
|
||||
int bitmap_pos;
|
||||
|
||||
bitmap_pos = bitmap_position(object->oid.hash);
|
||||
bitmap_pos = bitmap_position(data->bitmap_git, object->oid.hash);
|
||||
|
||||
if (bitmap_pos < 0)
|
||||
bitmap_pos = ext_index_add_object(object, name);
|
||||
bitmap_pos = ext_index_add_object(data->bitmap_git, object,
|
||||
name);
|
||||
|
||||
bitmap_set(base, bitmap_pos);
|
||||
bitmap_set(data->base, bitmap_pos);
|
||||
}
|
||||
|
||||
static void show_commit(struct commit *commit, void *data)
|
||||
{
|
||||
}
|
||||
|
||||
static int add_to_include_set(struct include_data *data,
|
||||
static int add_to_include_set(struct bitmap_index *bitmap_git,
|
||||
struct include_data *data,
|
||||
const unsigned char *sha1,
|
||||
int bitmap_pos)
|
||||
{
|
||||
|
@ -445,9 +455,9 @@ static int add_to_include_set(struct include_data *data,
|
|||
if (bitmap_get(data->base, bitmap_pos))
|
||||
return 0;
|
||||
|
||||
hash_pos = kh_get_sha1(bitmap_git.bitmaps, sha1);
|
||||
if (hash_pos < kh_end(bitmap_git.bitmaps)) {
|
||||
struct stored_bitmap *st = kh_value(bitmap_git.bitmaps, hash_pos);
|
||||
hash_pos = kh_get_sha1(bitmap_git->bitmaps, sha1);
|
||||
if (hash_pos < kh_end(bitmap_git->bitmaps)) {
|
||||
struct stored_bitmap *st = kh_value(bitmap_git->bitmaps, hash_pos);
|
||||
bitmap_or_ewah(data->base, lookup_stored_bitmap(st));
|
||||
return 0;
|
||||
}
|
||||
|
@ -461,11 +471,14 @@ static int should_include(struct commit *commit, void *_data)
|
|||
struct include_data *data = _data;
|
||||
int bitmap_pos;
|
||||
|
||||
bitmap_pos = bitmap_position(commit->object.oid.hash);
|
||||
bitmap_pos = bitmap_position(data->bitmap_git, commit->object.oid.hash);
|
||||
if (bitmap_pos < 0)
|
||||
bitmap_pos = ext_index_add_object((struct object *)commit, NULL);
|
||||
bitmap_pos = ext_index_add_object(data->bitmap_git,
|
||||
(struct object *)commit,
|
||||
NULL);
|
||||
|
||||
if (!add_to_include_set(data, commit->object.oid.hash, bitmap_pos)) {
|
||||
if (!add_to_include_set(data->bitmap_git, data, commit->object.oid.hash,
|
||||
bitmap_pos)) {
|
||||
struct commit_list *parent = commit->parents;
|
||||
|
||||
while (parent) {
|
||||
|
@ -479,7 +492,8 @@ static int should_include(struct commit *commit, void *_data)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static struct bitmap *find_objects(struct rev_info *revs,
|
||||
static struct bitmap *find_objects(struct bitmap_index *bitmap_git,
|
||||
struct rev_info *revs,
|
||||
struct object_list *roots,
|
||||
struct bitmap *seen)
|
||||
{
|
||||
|
@ -501,10 +515,10 @@ static struct bitmap *find_objects(struct rev_info *revs,
|
|||
roots = roots->next;
|
||||
|
||||
if (object->type == OBJ_COMMIT) {
|
||||
khiter_t pos = kh_get_sha1(bitmap_git.bitmaps, object->oid.hash);
|
||||
khiter_t pos = kh_get_sha1(bitmap_git->bitmaps, object->oid.hash);
|
||||
|
||||
if (pos < kh_end(bitmap_git.bitmaps)) {
|
||||
struct stored_bitmap *st = kh_value(bitmap_git.bitmaps, pos);
|
||||
if (pos < kh_end(bitmap_git->bitmaps)) {
|
||||
struct stored_bitmap *st = kh_value(bitmap_git->bitmaps, pos);
|
||||
struct ewah_bitmap *or_with = lookup_stored_bitmap(st);
|
||||
|
||||
if (base == NULL)
|
||||
|
@ -543,7 +557,7 @@ static struct bitmap *find_objects(struct rev_info *revs,
|
|||
int pos;
|
||||
|
||||
roots = roots->next;
|
||||
pos = bitmap_position(object->oid.hash);
|
||||
pos = bitmap_position(bitmap_git, object->oid.hash);
|
||||
|
||||
if (pos < 0 || base == NULL || !bitmap_get(base, pos)) {
|
||||
object->flags &= ~UNINTERESTING;
|
||||
|
@ -556,10 +570,12 @@ static struct bitmap *find_objects(struct rev_info *revs,
|
|||
|
||||
if (needs_walk) {
|
||||
struct include_data incdata;
|
||||
struct bitmap_show_data show_data;
|
||||
|
||||
if (base == NULL)
|
||||
base = bitmap_new();
|
||||
|
||||
incdata.bitmap_git = bitmap_git;
|
||||
incdata.base = base;
|
||||
incdata.seen = seen;
|
||||
|
||||
|
@ -569,22 +585,27 @@ static struct bitmap *find_objects(struct rev_info *revs,
|
|||
if (prepare_revision_walk(revs))
|
||||
die("revision walk setup failed");
|
||||
|
||||
traverse_commit_list(revs, show_commit, show_object, base);
|
||||
show_data.bitmap_git = bitmap_git;
|
||||
show_data.base = base;
|
||||
|
||||
traverse_commit_list(revs, show_commit, show_object,
|
||||
&show_data);
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
static void show_extended_objects(struct bitmap *objects,
|
||||
static void show_extended_objects(struct bitmap_index *bitmap_git,
|
||||
show_reachable_fn show_reach)
|
||||
{
|
||||
struct eindex *eindex = &bitmap_git.ext_index;
|
||||
struct bitmap *objects = bitmap_git->result;
|
||||
struct eindex *eindex = &bitmap_git->ext_index;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < eindex->count; ++i) {
|
||||
struct object *obj;
|
||||
|
||||
if (!bitmap_get(objects, bitmap_git.pack->num_objects + i))
|
||||
if (!bitmap_get(objects, bitmap_git->pack->num_objects + i))
|
||||
continue;
|
||||
|
||||
obj = eindex->objects[i];
|
||||
|
@ -593,7 +614,7 @@ static void show_extended_objects(struct bitmap *objects,
|
|||
}
|
||||
|
||||
static void show_objects_for_type(
|
||||
struct bitmap *objects,
|
||||
struct bitmap_index *bitmap_git,
|
||||
struct ewah_bitmap *type_filter,
|
||||
enum object_type object_type,
|
||||
show_reachable_fn show_reach)
|
||||
|
@ -604,7 +625,9 @@ static void show_objects_for_type(
|
|||
struct ewah_iterator it;
|
||||
eword_t filter;
|
||||
|
||||
if (bitmap_git.reuse_objects == bitmap_git.pack->num_objects)
|
||||
struct bitmap *objects = bitmap_git->result;
|
||||
|
||||
if (bitmap_git->reuse_objects == bitmap_git->pack->num_objects)
|
||||
return;
|
||||
|
||||
ewah_iterator_init(&it, type_filter);
|
||||
|
@ -622,16 +645,16 @@ static void show_objects_for_type(
|
|||
|
||||
offset += ewah_bit_ctz64(word >> offset);
|
||||
|
||||
if (pos + offset < bitmap_git.reuse_objects)
|
||||
if (pos + offset < bitmap_git->reuse_objects)
|
||||
continue;
|
||||
|
||||
entry = &bitmap_git.pack->revindex[pos + offset];
|
||||
nth_packed_object_oid(&oid, bitmap_git.pack, entry->nr);
|
||||
entry = &bitmap_git->pack->revindex[pos + offset];
|
||||
nth_packed_object_oid(&oid, bitmap_git->pack, entry->nr);
|
||||
|
||||
if (bitmap_git.hashes)
|
||||
hash = get_be32(bitmap_git.hashes + entry->nr);
|
||||
if (bitmap_git->hashes)
|
||||
hash = get_be32(bitmap_git->hashes + entry->nr);
|
||||
|
||||
show_reach(&oid, object_type, 0, hash, bitmap_git.pack, entry->offset);
|
||||
show_reach(&oid, object_type, 0, hash, bitmap_git->pack, entry->offset);
|
||||
}
|
||||
|
||||
pos += BITS_IN_EWORD;
|
||||
|
@ -639,20 +662,21 @@ static void show_objects_for_type(
|
|||
}
|
||||
}
|
||||
|
||||
static int in_bitmapped_pack(struct object_list *roots)
|
||||
static int in_bitmapped_pack(struct bitmap_index *bitmap_git,
|
||||
struct object_list *roots)
|
||||
{
|
||||
while (roots) {
|
||||
struct object *object = roots->item;
|
||||
roots = roots->next;
|
||||
|
||||
if (find_pack_entry_one(object->oid.hash, bitmap_git.pack) > 0)
|
||||
if (find_pack_entry_one(object->oid.hash, bitmap_git->pack) > 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int prepare_bitmap_walk(struct rev_info *revs)
|
||||
struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
|
@ -662,12 +686,11 @@ int prepare_bitmap_walk(struct rev_info *revs)
|
|||
struct bitmap *wants_bitmap = NULL;
|
||||
struct bitmap *haves_bitmap = NULL;
|
||||
|
||||
if (!bitmap_git.loaded) {
|
||||
/* try to open a bitmapped pack, but don't parse it yet
|
||||
* because we may not need to use it */
|
||||
if (open_pack_bitmap() < 0)
|
||||
return -1;
|
||||
}
|
||||
struct bitmap_index *bitmap_git = xcalloc(1, sizeof(*bitmap_git));
|
||||
/* try to open a bitmapped pack, but don't parse it yet
|
||||
* because we may not need to use it */
|
||||
if (open_pack_bitmap(bitmap_git) < 0)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < revs->pending.nr; ++i) {
|
||||
struct object *object = revs->pending.objects[i].item;
|
||||
|
@ -699,26 +722,26 @@ int prepare_bitmap_walk(struct rev_info *revs)
|
|||
* in the packfile that has a bitmap, we don't have anything to
|
||||
* optimize here
|
||||
*/
|
||||
if (haves && !in_bitmapped_pack(haves))
|
||||
return -1;
|
||||
if (haves && !in_bitmapped_pack(bitmap_git, haves))
|
||||
return NULL;
|
||||
|
||||
/* if we don't want anything, we're done here */
|
||||
if (!wants)
|
||||
return -1;
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* now we're going to use bitmaps, so load the actual bitmap entries
|
||||
* 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 (!bitmap_git.loaded && load_pack_bitmap() < 0)
|
||||
return -1;
|
||||
if (!bitmap_git->loaded && load_pack_bitmap(bitmap_git) < 0)
|
||||
return NULL;
|
||||
|
||||
object_array_clear(&revs->pending);
|
||||
|
||||
if (haves) {
|
||||
revs->ignore_missing_links = 1;
|
||||
haves_bitmap = find_objects(revs, haves, NULL);
|
||||
haves_bitmap = find_objects(bitmap_git, revs, haves, NULL);
|
||||
reset_revision_walk();
|
||||
revs->ignore_missing_links = 0;
|
||||
|
||||
|
@ -726,7 +749,7 @@ int prepare_bitmap_walk(struct rev_info *revs)
|
|||
BUG("failed to perform bitmap walk");
|
||||
}
|
||||
|
||||
wants_bitmap = find_objects(revs, wants, haves_bitmap);
|
||||
wants_bitmap = find_objects(bitmap_git, revs, wants, haves_bitmap);
|
||||
|
||||
if (!wants_bitmap)
|
||||
BUG("failed to perform bitmap walk");
|
||||
|
@ -734,13 +757,14 @@ int prepare_bitmap_walk(struct rev_info *revs)
|
|||
if (haves_bitmap)
|
||||
bitmap_and_not(wants_bitmap, haves_bitmap);
|
||||
|
||||
bitmap_git.result = wants_bitmap;
|
||||
bitmap_git->result = wants_bitmap;
|
||||
|
||||
bitmap_free(haves_bitmap);
|
||||
return 0;
|
||||
return bitmap_git;
|
||||
}
|
||||
|
||||
int reuse_partial_packfile_from_bitmap(struct packed_git **packfile,
|
||||
int reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
|
||||
struct packed_git **packfile,
|
||||
uint32_t *entries,
|
||||
off_t *up_to)
|
||||
{
|
||||
|
@ -750,7 +774,7 @@ int reuse_partial_packfile_from_bitmap(struct packed_git **packfile,
|
|||
*/
|
||||
static const double REUSE_PERCENT = 0.9;
|
||||
|
||||
struct bitmap *result = bitmap_git.result;
|
||||
struct bitmap *result = bitmap_git->result;
|
||||
uint32_t reuse_threshold;
|
||||
uint32_t i, reuse_objects = 0;
|
||||
|
||||
|
@ -770,8 +794,8 @@ int reuse_partial_packfile_from_bitmap(struct packed_git **packfile,
|
|||
const unsigned char *sha1;
|
||||
struct revindex_entry *entry;
|
||||
|
||||
entry = &bitmap_git.reverse_index->revindex[reuse_objects];
|
||||
sha1 = nth_packed_object_sha1(bitmap_git.pack, entry->nr);
|
||||
entry = &bitmap_git->reverse_index->revindex[reuse_objects];
|
||||
sha1 = nth_packed_object_sha1(bitmap_git->pack, entry->nr);
|
||||
|
||||
fprintf(stderr, "Failed to reuse at %d (%016llx)\n",
|
||||
reuse_objects, result->words[i]);
|
||||
|
@ -782,48 +806,50 @@ int reuse_partial_packfile_from_bitmap(struct packed_git **packfile,
|
|||
if (!reuse_objects)
|
||||
return -1;
|
||||
|
||||
if (reuse_objects >= bitmap_git.pack->num_objects) {
|
||||
bitmap_git.reuse_objects = *entries = bitmap_git.pack->num_objects;
|
||||
if (reuse_objects >= bitmap_git->pack->num_objects) {
|
||||
bitmap_git->reuse_objects = *entries = bitmap_git->pack->num_objects;
|
||||
*up_to = -1; /* reuse the full pack */
|
||||
*packfile = bitmap_git.pack;
|
||||
*packfile = bitmap_git->pack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
reuse_threshold = bitmap_popcount(bitmap_git.result) * REUSE_PERCENT;
|
||||
reuse_threshold = bitmap_popcount(bitmap_git->result) * REUSE_PERCENT;
|
||||
|
||||
if (reuse_objects < reuse_threshold)
|
||||
return -1;
|
||||
|
||||
bitmap_git.reuse_objects = *entries = reuse_objects;
|
||||
*up_to = bitmap_git.pack->revindex[reuse_objects].offset;
|
||||
*packfile = bitmap_git.pack;
|
||||
bitmap_git->reuse_objects = *entries = reuse_objects;
|
||||
*up_to = bitmap_git->pack->revindex[reuse_objects].offset;
|
||||
*packfile = bitmap_git->pack;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void traverse_bitmap_commit_list(show_reachable_fn show_reachable)
|
||||
void traverse_bitmap_commit_list(struct bitmap_index *bitmap_git,
|
||||
show_reachable_fn show_reachable)
|
||||
{
|
||||
assert(bitmap_git.result);
|
||||
assert(bitmap_git->result);
|
||||
|
||||
show_objects_for_type(bitmap_git.result, bitmap_git.commits,
|
||||
show_objects_for_type(bitmap_git, bitmap_git->commits,
|
||||
OBJ_COMMIT, show_reachable);
|
||||
show_objects_for_type(bitmap_git.result, bitmap_git.trees,
|
||||
show_objects_for_type(bitmap_git, bitmap_git->trees,
|
||||
OBJ_TREE, show_reachable);
|
||||
show_objects_for_type(bitmap_git.result, bitmap_git.blobs,
|
||||
show_objects_for_type(bitmap_git, bitmap_git->blobs,
|
||||
OBJ_BLOB, show_reachable);
|
||||
show_objects_for_type(bitmap_git.result, bitmap_git.tags,
|
||||
show_objects_for_type(bitmap_git, bitmap_git->tags,
|
||||
OBJ_TAG, show_reachable);
|
||||
|
||||
show_extended_objects(bitmap_git.result, show_reachable);
|
||||
show_extended_objects(bitmap_git, show_reachable);
|
||||
|
||||
bitmap_free(bitmap_git.result);
|
||||
bitmap_git.result = NULL;
|
||||
bitmap_free(bitmap_git->result);
|
||||
bitmap_git->result = NULL;
|
||||
}
|
||||
|
||||
static uint32_t count_object_type(struct bitmap *objects,
|
||||
static uint32_t count_object_type(struct bitmap_index *bitmap_git,
|
||||
enum object_type type)
|
||||
{
|
||||
struct eindex *eindex = &bitmap_git.ext_index;
|
||||
struct bitmap *objects = bitmap_git->result;
|
||||
struct eindex *eindex = &bitmap_git->ext_index;
|
||||
|
||||
uint32_t i = 0, count = 0;
|
||||
struct ewah_iterator it;
|
||||
|
@ -831,19 +857,19 @@ static uint32_t count_object_type(struct bitmap *objects,
|
|||
|
||||
switch (type) {
|
||||
case OBJ_COMMIT:
|
||||
ewah_iterator_init(&it, bitmap_git.commits);
|
||||
ewah_iterator_init(&it, bitmap_git->commits);
|
||||
break;
|
||||
|
||||
case OBJ_TREE:
|
||||
ewah_iterator_init(&it, bitmap_git.trees);
|
||||
ewah_iterator_init(&it, bitmap_git->trees);
|
||||
break;
|
||||
|
||||
case OBJ_BLOB:
|
||||
ewah_iterator_init(&it, bitmap_git.blobs);
|
||||
ewah_iterator_init(&it, bitmap_git->blobs);
|
||||
break;
|
||||
|
||||
case OBJ_TAG:
|
||||
ewah_iterator_init(&it, bitmap_git.tags);
|
||||
ewah_iterator_init(&it, bitmap_git->tags);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -857,32 +883,34 @@ static uint32_t count_object_type(struct bitmap *objects,
|
|||
|
||||
for (i = 0; i < eindex->count; ++i) {
|
||||
if (eindex->objects[i]->type == type &&
|
||||
bitmap_get(objects, bitmap_git.pack->num_objects + i))
|
||||
bitmap_get(objects, bitmap_git->pack->num_objects + i))
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void count_bitmap_commit_list(uint32_t *commits, uint32_t *trees,
|
||||
void count_bitmap_commit_list(struct bitmap_index *bitmap_git,
|
||||
uint32_t *commits, uint32_t *trees,
|
||||
uint32_t *blobs, uint32_t *tags)
|
||||
{
|
||||
assert(bitmap_git.result);
|
||||
assert(bitmap_git->result);
|
||||
|
||||
if (commits)
|
||||
*commits = count_object_type(bitmap_git.result, OBJ_COMMIT);
|
||||
*commits = count_object_type(bitmap_git, OBJ_COMMIT);
|
||||
|
||||
if (trees)
|
||||
*trees = count_object_type(bitmap_git.result, OBJ_TREE);
|
||||
*trees = count_object_type(bitmap_git, OBJ_TREE);
|
||||
|
||||
if (blobs)
|
||||
*blobs = count_object_type(bitmap_git.result, OBJ_BLOB);
|
||||
*blobs = count_object_type(bitmap_git, OBJ_BLOB);
|
||||
|
||||
if (tags)
|
||||
*tags = count_object_type(bitmap_git.result, OBJ_TAG);
|
||||
*tags = count_object_type(bitmap_git, OBJ_TAG);
|
||||
}
|
||||
|
||||
struct bitmap_test_data {
|
||||
struct bitmap_index *bitmap_git;
|
||||
struct bitmap *base;
|
||||
struct progress *prg;
|
||||
size_t seen;
|
||||
|
@ -894,7 +922,7 @@ static void test_show_object(struct object *object, const char *name,
|
|||
struct bitmap_test_data *tdata = data;
|
||||
int bitmap_pos;
|
||||
|
||||
bitmap_pos = bitmap_position(object->oid.hash);
|
||||
bitmap_pos = bitmap_position(tdata->bitmap_git, object->oid.hash);
|
||||
if (bitmap_pos < 0)
|
||||
die("Object not in bitmap: %s\n", oid_to_hex(&object->oid));
|
||||
|
||||
|
@ -907,7 +935,8 @@ static void test_show_commit(struct commit *commit, void *data)
|
|||
struct bitmap_test_data *tdata = data;
|
||||
int bitmap_pos;
|
||||
|
||||
bitmap_pos = bitmap_position(commit->object.oid.hash);
|
||||
bitmap_pos = bitmap_position(tdata->bitmap_git,
|
||||
commit->object.oid.hash);
|
||||
if (bitmap_pos < 0)
|
||||
die("Object not in bitmap: %s\n", oid_to_hex(&commit->object.oid));
|
||||
|
||||
|
@ -922,21 +951,22 @@ void test_bitmap_walk(struct rev_info *revs)
|
|||
khiter_t pos;
|
||||
size_t result_popcnt;
|
||||
struct bitmap_test_data tdata;
|
||||
struct bitmap_index *bitmap_git;
|
||||
|
||||
if (prepare_bitmap_git())
|
||||
if (!(bitmap_git = prepare_bitmap_git()))
|
||||
die("failed to load bitmap indexes");
|
||||
|
||||
if (revs->pending.nr != 1)
|
||||
die("you must specify exactly one commit to test");
|
||||
|
||||
fprintf(stderr, "Bitmap v%d test (%d entries loaded)\n",
|
||||
bitmap_git.version, bitmap_git.entry_count);
|
||||
bitmap_git->version, bitmap_git->entry_count);
|
||||
|
||||
root = revs->pending.objects[0].item;
|
||||
pos = kh_get_sha1(bitmap_git.bitmaps, root->oid.hash);
|
||||
pos = kh_get_sha1(bitmap_git->bitmaps, root->oid.hash);
|
||||
|
||||
if (pos < kh_end(bitmap_git.bitmaps)) {
|
||||
struct stored_bitmap *st = kh_value(bitmap_git.bitmaps, pos);
|
||||
if (pos < kh_end(bitmap_git->bitmaps)) {
|
||||
struct stored_bitmap *st = kh_value(bitmap_git->bitmaps, pos);
|
||||
struct ewah_bitmap *bm = lookup_stored_bitmap(st);
|
||||
|
||||
fprintf(stderr, "Found bitmap for %s. %d bits / %08x checksum\n",
|
||||
|
@ -957,6 +987,7 @@ 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.prg = start_progress("Verifying bitmap entries", result_popcnt);
|
||||
tdata.seen = 0;
|
||||
|
@ -1004,7 +1035,8 @@ static int rebuild_bitmap(uint32_t *reposition,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int rebuild_existing_bitmaps(struct packing_data *mapping,
|
||||
int rebuild_existing_bitmaps(struct bitmap_index *bitmap_git,
|
||||
struct packing_data *mapping,
|
||||
khash_sha1 *reused_bitmaps,
|
||||
int show_progress)
|
||||
{
|
||||
|
@ -1017,10 +1049,7 @@ int rebuild_existing_bitmaps(struct packing_data *mapping,
|
|||
khiter_t hash_pos;
|
||||
int hash_ret;
|
||||
|
||||
if (prepare_bitmap_git() < 0)
|
||||
return -1;
|
||||
|
||||
num_objects = bitmap_git.pack->num_objects;
|
||||
num_objects = bitmap_git->pack->num_objects;
|
||||
reposition = xcalloc(num_objects, sizeof(uint32_t));
|
||||
|
||||
for (i = 0; i < num_objects; ++i) {
|
||||
|
@ -1028,8 +1057,8 @@ int rebuild_existing_bitmaps(struct packing_data *mapping,
|
|||
struct revindex_entry *entry;
|
||||
struct object_entry *oe;
|
||||
|
||||
entry = &bitmap_git.pack->revindex[i];
|
||||
sha1 = nth_packed_object_sha1(bitmap_git.pack, entry->nr);
|
||||
entry = &bitmap_git->pack->revindex[i];
|
||||
sha1 = nth_packed_object_sha1(bitmap_git->pack, entry->nr);
|
||||
oe = packlist_find(mapping, sha1, NULL);
|
||||
|
||||
if (oe)
|
||||
|
@ -1042,7 +1071,7 @@ int rebuild_existing_bitmaps(struct packing_data *mapping,
|
|||
if (show_progress)
|
||||
progress = start_progress("Reusing bitmaps", 0);
|
||||
|
||||
kh_foreach_value(bitmap_git.bitmaps, stored, {
|
||||
kh_foreach_value(bitmap_git->bitmaps, stored, {
|
||||
if (stored->flags & BITMAP_FLAG_REUSE) {
|
||||
if (!rebuild_bitmap(reposition,
|
||||
lookup_stored_bitmap(stored),
|
||||
|
|
|
@ -34,13 +34,20 @@ typedef int (*show_reachable_fn)(
|
|||
struct packed_git *found_pack,
|
||||
off_t found_offset);
|
||||
|
||||
int prepare_bitmap_git(void);
|
||||
void count_bitmap_commit_list(uint32_t *commits, uint32_t *trees, uint32_t *blobs, uint32_t *tags);
|
||||
void traverse_bitmap_commit_list(show_reachable_fn show_reachable);
|
||||
struct bitmap_index;
|
||||
|
||||
struct bitmap_index *prepare_bitmap_git(void);
|
||||
void count_bitmap_commit_list(struct bitmap_index *, uint32_t *commits,
|
||||
uint32_t *trees, uint32_t *blobs, uint32_t *tags);
|
||||
void traverse_bitmap_commit_list(struct bitmap_index *,
|
||||
show_reachable_fn show_reachable);
|
||||
void test_bitmap_walk(struct rev_info *revs);
|
||||
int prepare_bitmap_walk(struct rev_info *revs);
|
||||
int reuse_partial_packfile_from_bitmap(struct packed_git **packfile, uint32_t *entries, off_t *up_to);
|
||||
int rebuild_existing_bitmaps(struct packing_data *mapping, khash_sha1 *reused_bitmaps, int show_progress);
|
||||
struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs);
|
||||
int reuse_partial_packfile_from_bitmap(struct bitmap_index *,
|
||||
struct packed_git **packfile,
|
||||
uint32_t *entries, off_t *up_to);
|
||||
int rebuild_existing_bitmaps(struct bitmap_index *, struct packing_data *mapping,
|
||||
khash_sha1 *reused_bitmaps, int show_progress);
|
||||
|
||||
void bitmap_writer_show_progress(int show);
|
||||
void bitmap_writer_set_checksum(unsigned char *sha1);
|
||||
|
|
Загрузка…
Ссылка в новой задаче