summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Shawn O. Pearce <spearce@spearce.org>2006-12-23 02:34:23 -0500
committerLibravatar Junio C Hamano <junkio@cox.net>2006-12-29 11:36:44 -0800
commit54044bf825d311751e30552248be1e0cac99a5a3 (patch)
tree0c4081a9a2a9fe118bf4cb49d610f5e226c67846
parentDocument why header parsing won't exceed a window. (diff)
downloadtgif-54044bf825d311751e30552248be1e0cac99a5a3.tar.xz
Unmap individual windows rather than entire files.
To support multiple windows per packfile we need to unmap only one window at a time from that packfile, leaving any other windows in place and available for reference. We treat all windows from all packfiles equally; the least recently used, not-in-use window across all packfiles will always be closed first. If we have unmapped all windows in a packfile then we can also close the packfile's file descriptor as its possible we won't need to map any window from that file in the near future. This decision about when to close the pack file descriptor may need to be revisited in the future after additional testing on several different platforms can be performed. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
-rw-r--r--sha1_file.c45
1 files changed, 30 insertions, 15 deletions
diff --git a/sha1_file.c b/sha1_file.c
index 3466969344..8e14a5a882 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -450,24 +450,39 @@ static int check_packed_git_idx(const char *path, unsigned long *idx_size_,
return 0;
}
-static int unuse_one_packed_git(void)
+static int unuse_one_window(void)
{
- struct packed_git *p, *lru = NULL;
+ struct packed_git *p, *lru_p = NULL;
+ struct pack_window *w, *w_l, *lru_w = NULL, *lru_l = NULL;
for (p = packed_git; p; p = p->next) {
- if (!p->windows || p->windows->inuse_cnt)
- continue;
- if (!lru || p->windows->last_used < lru->windows->last_used)
- lru = p;
+ for (w_l = NULL, w = p->windows; w; w = w->next) {
+ if (!w->inuse_cnt) {
+ if (!lru_w || w->last_used < lru_w->last_used) {
+ lru_p = p;
+ lru_w = w;
+ lru_l = w_l;
+ }
+ }
+ w_l = w;
+ }
}
- if (!lru)
- return 0;
- munmap(lru->windows->base, lru->windows->len);
- free(lru->windows);
- lru->windows = NULL;
- close(p->pack_fd);
- p->pack_fd = -1;
- return 1;
+ if (lru_p) {
+ munmap(lru_w->base, lru_w->len);
+ pack_mapped -= lru_w->len;
+ if (lru_l)
+ lru_l->next = lru_w->next;
+ else {
+ lru_p->windows = lru_w->next;
+ if (!lru_p->windows) {
+ close(lru_p->pack_fd);
+ lru_p->pack_fd = -1;
+ }
+ }
+ free(lru_w);
+ return 1;
+ }
+ return 0;
}
void unuse_pack(struct pack_window **w_cursor)
@@ -532,7 +547,7 @@ unsigned char* use_pack(struct packed_git *p,
open_packed_git(p);
if (!win) {
pack_mapped += p->pack_size;
- while (packed_git_limit < pack_mapped && unuse_one_packed_git())
+ while (packed_git_limit < pack_mapped && unuse_one_window())
; /* nothing */
win = xcalloc(1, sizeof(*win));
win->len = p->pack_size;