From: Junio C Hamano Date: Mon, 13 Feb 2012 06:43:03 +0000 (-0800) Subject: Merge branch 'nd/find-pack-entry-recent-cache-invalidation' X-Git-Tag: v1.7.10-rc0~95 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/dd5253b4bd440d2472ac01bd3821ac96c2d26ff0?ds=inline;hp=-c Merge branch 'nd/find-pack-entry-recent-cache-invalidation' * nd/find-pack-entry-recent-cache-invalidation: find_pack_entry(): do not keep packed_git pointer locally sha1_file.c: move the core logic of find_pack_entry() into fill_pack_entry() --- dd5253b4bd440d2472ac01bd3821ac96c2d26ff0 diff --combined sha1_file.c index d9aa0e0a2c,6b1b5125c8..f9f8d5e91c --- a/sha1_file.c +++ b/sha1_file.c @@@ -54,6 -54,8 +54,8 @@@ static struct cached_object empty_tree 0 }; + static struct packed_git *last_found_pack; + static struct cached_object *find_cached_object(const unsigned char *sha1) { int i; @@@ -720,6 -722,8 +722,8 @@@ void free_pack_by_name(const char *pack close_pack_index(p); free(p->bad_object_sha1); *pp = p->next; + if (last_found_pack == p) + last_found_pack = NULL; free(p); return; } @@@ -1202,11 -1206,6 +1206,11 @@@ void *map_sha1_file(const unsigned cha if (!fstat(fd, &st)) { *size = xsize_t(st.st_size); + if (!*size) { + /* mmap() is forbidden on empty files */ + error("object file %s is empty", sha1_file_name(sha1)); + return NULL; + } map = xmmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0); } close(fd); @@@ -2015,54 -2014,58 +2019,58 @@@ int is_pack_valid(struct packed_git *p return !open_packed_git(p); } + static int fill_pack_entry(const unsigned char *sha1, + struct pack_entry *e, + struct packed_git *p) + { + off_t offset; + + if (p->num_bad_objects) { + unsigned i; + for (i = 0; i < p->num_bad_objects; i++) + if (!hashcmp(sha1, p->bad_object_sha1 + 20 * i)) + return 0; + } + + offset = find_pack_entry_one(sha1, p); + if (!offset) + return 0; + + /* + * We are about to tell the caller where they can locate the + * requested object. We better make sure the packfile is + * still here and can be accessed before supplying that + * answer, as it may have been deleted since the index was + * loaded! + */ + if (!is_pack_valid(p)) { + warning("packfile %s cannot be accessed", p->pack_name); + return 0; + } + e->offset = offset; + e->p = p; + hashcpy(e->sha1, sha1); + return 1; + } + static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e) { - static struct packed_git *last_found = (void *)1; struct packed_git *p; - off_t offset; prepare_packed_git(); if (!packed_git) return 0; - p = (last_found == (void *)1) ? packed_git : last_found; - do { - if (p->num_bad_objects) { - unsigned i; - for (i = 0; i < p->num_bad_objects; i++) - if (!hashcmp(sha1, p->bad_object_sha1 + 20 * i)) - goto next; - } + if (last_found_pack && fill_pack_entry(sha1, e, last_found_pack)) + return 1; - offset = find_pack_entry_one(sha1, p); - if (offset) { - /* - * We are about to tell the caller where they can - * locate the requested object. We better make - * sure the packfile is still here and can be - * accessed before supplying that answer, as - * it may have been deleted since the index - * was loaded! - */ - if (!is_pack_valid(p)) { - warning("packfile %s cannot be accessed", p->pack_name); - goto next; - } - e->offset = offset; - e->p = p; - hashcpy(e->sha1, sha1); - last_found = p; - return 1; - } + for (p = packed_git; p; p = p->next) { + if (p == last_found_pack || !fill_pack_entry(sha1, e, p)) + continue; - next: - if (p == last_found) - p = packed_git; - else - p = p->next; - if (p == last_found) - p = p->next; - } while (p); + last_found_pack = p; + return 1; + } return 0; }