summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 77ccc5b)
raw | patch | inline | side by side (parent: 77ccc5b)
author | Shawn O. Pearce <spearce@spearce.org> | |
Sat, 23 Dec 2006 07:33:44 +0000 (02:33 -0500) | ||
committer | Junio C Hamano <junkio@cox.net> | |
Fri, 29 Dec 2006 19:36:44 +0000 (11:36 -0800) |
The idea behind the sliding mmap window pack reader implementation
is to have multiple mmap regions active against the same pack file,
thereby allowing the process to mmap in only the active/hot sections
of the pack and reduce overall virtual address space usage.
To implement this we need to refactor the mmap related data
(pack_base, pack_use_cnt) out of struct packed_git and move them
into a new struct pack_window.
We are refactoring the code to support a single struct pack_window
per packfile, thereby emulating the prior behavior of mmap'ing the
entire pack file.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
is to have multiple mmap regions active against the same pack file,
thereby allowing the process to mmap in only the active/hot sections
of the pack and reduce overall virtual address space usage.
To implement this we need to refactor the mmap related data
(pack_base, pack_use_cnt) out of struct packed_git and move them
into a new struct pack_window.
We are refactoring the code to support a single struct pack_window
per packfile, thereby emulating the prior behavior of mmap'ing the
entire pack file.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
builtin-pack-objects.c | patch | blob | history | |
cache.h | patch | blob | history | |
pack-check.c | patch | blob | history | |
sha1_file.c | patch | blob | history |
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 9e15beb3ba1e66987bd1fec51ed864414ffbf07c..4a00a1206fabcb9a930e984ba26ed00fa1cc65b3 100644 (file)
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
}
use_packed_git(p);
- buf = (char *) p->pack_base
+ buf = p->windows->base
+ entry->in_pack_offset
+ entry->in_pack_header_size;
datalen = find_packed_object_size(p, entry->in_pack_offset)
struct object_entry *base_entry = NULL;
use_packed_git(p);
- buf = p->pack_base;
+ buf = p->windows->base;
buf += entry->in_pack_offset;
/* We want in_pack_type even if we do not reuse delta.
index 816239bea0fbf53852efcb3575995cd5aef7e445..ae7bceca502f33723a5ff5c051b6c8167835c6b8 100644 (file)
--- a/cache.h
+++ b/cache.h
} *alt_odb_list;
extern void prepare_alt_odb(void);
+struct pack_window {
+ struct pack_window *next;
+ unsigned char *base;
+ off_t offset;
+ size_t len;
+ unsigned int last_used;
+ unsigned int inuse_cnt;
+};
+
extern struct packed_git {
struct packed_git *next;
unsigned long index_size;
unsigned long pack_size;
+ struct pack_window *windows;
unsigned int *index_base;
- void *pack_base;
- unsigned int pack_last_used;
- unsigned int pack_use_cnt;
int pack_local;
unsigned char sha1[20];
/* something like ".git/objects/pack/xxxxx.pack" */
diff --git a/pack-check.c b/pack-check.c
index 491bad2ae4c048c7781e9add1e9ff0a6429a20bc..761cc852e9f640827a5fbfe01c2d08eb2725f0c1 100644 (file)
--- a/pack-check.c
+++ b/pack-check.c
int nr_objects, err, i;
/* Header consistency check */
- hdr = p->pack_base;
+ pack_base = p->windows->base;
+ hdr = (struct pack_header*)pack_base;
if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
return error("Packfile %s signature mismatch", p->pack_name);
if (!pack_version_ok(hdr->hdr_version))
num_packed_objects(p));
SHA1_Init(&ctx);
- pack_base = p->pack_base;
SHA1_Update(&ctx, pack_base, pack_size - 20);
SHA1_Final(sha1, &ctx);
if (hashcmp(sha1, (unsigned char *)pack_base + pack_size - 20))
int nr_objects, i;
unsigned int chain_histogram[MAX_CHAIN];
- hdr = p->pack_base;
+ hdr = (struct pack_header*)p->windows->base;
nr_objects = ntohl(hdr->hdr_entries);
memset(chain_histogram, 0, sizeof(chain_histogram));
diff --git a/sha1_file.c b/sha1_file.c
index 4183f595edfe6086f5097a430cb48202db00c5c1..a9f374e60ad214ca54b79116e23c4ab7ead356d9 100644 (file)
--- a/sha1_file.c
+++ b/sha1_file.c
struct packed_git *p, *lru = NULL;
for (p = packed_git; p; p = p->next) {
- if (p->pack_use_cnt || !p->pack_base)
+ if (!p->windows || p->windows->inuse_cnt)
continue;
- if (!lru || p->pack_last_used < lru->pack_last_used)
+ if (!lru || p->windows->last_used < lru->windows->last_used)
lru = p;
}
if (!lru)
return 0;
- munmap(lru->pack_base, lru->pack_size);
- lru->pack_base = NULL;
+ munmap(lru->windows->base, lru->windows->len);
+ free(lru->windows);
+ lru->windows = NULL;
return 1;
}
void unuse_packed_git(struct packed_git *p)
{
- p->pack_use_cnt--;
+ if (p->windows)
+ p->windows->inuse_cnt--;
}
int use_packed_git(struct packed_git *p)
die("packfile %s not a regular file", p->pack_name);
p->pack_size = st.st_size;
}
- if (!p->pack_base) {
+ if (!p->windows) {
int fd;
struct stat st;
- void *map;
+ struct pack_window *win;
struct pack_header *hdr;
pack_mapped += p->pack_size;
}
if (st.st_size != p->pack_size)
die("packfile %s size mismatch.", p->pack_name);
- map = mmap(NULL, p->pack_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ win = xcalloc(1, sizeof(*win));
+ win->len = p->pack_size;
+ win->base = mmap(NULL, p->pack_size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
- if (map == MAP_FAILED)
+ if (win->base == MAP_FAILED)
die("packfile %s cannot be mapped.", p->pack_name);
- p->pack_base = map;
+ p->windows = win;
/* Check if we understand this pack file. If we don't we're
* likely too old to handle it.
*/
- hdr = map;
+ hdr = (struct pack_header*)win->base;
if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
die("packfile %s isn't actually a pack.", p->pack_name);
if (!pack_version_ok(hdr->hdr_version))
*/
if (hashcmp((unsigned char *)(p->index_base) +
p->index_size - 40,
- (unsigned char *)p->pack_base +
+ p->windows->base +
p->pack_size - 20)) {
die("packfile %s does not match index.", p->pack_name);
}
}
- p->pack_last_used = pack_used_ctr++;
- p->pack_use_cnt++;
+ p->windows->last_used = pack_used_ctr++;
+ p->windows->inuse_cnt++;
return 0;
}
p->pack_size = st.st_size;
p->index_base = idx_map;
p->next = NULL;
- p->pack_base = NULL;
- p->pack_last_used = 0;
- p->pack_use_cnt = 0;
+ p->windows = NULL;
p->pack_local = local;
if ((path_len > 44) && !get_sha1_hex(path + path_len - 44, sha1))
hashcpy(p->sha1, sha1);
@@ -591,9 +593,7 @@ struct packed_git *parse_pack_index_file(const unsigned char *sha1, char *idx_pa
p->pack_size = 0;
p->index_base = idx_map;
p->next = NULL;
- p->pack_base = NULL;
- p->pack_last_used = 0;
- p->pack_use_cnt = 0;
+ p->windows = NULL;
hashcpy(p->sha1, sha1);
return p;
}
unsigned long delta_obj_offset,
unsigned long *base_obj_offset)
{
- unsigned char *base_info = (unsigned char *) p->pack_base + offset;
+ unsigned char *base_info = p->windows->base + offset;
unsigned long base_offset;
/* there must be at least 20 bytes left regardless of delta type */
memset(&stream, 0, sizeof(stream));
- stream.next_in = (unsigned char *) p->pack_base + offset;
+ stream.next_in = p->windows->base + offset;
stream.avail_in = p->pack_size - offset;
stream.next_out = delta_head;
stream.avail_out = sizeof(delta_head);
@@ -984,8 +984,7 @@ static unsigned long unpack_object_header(struct packed_git *p, unsigned long of
if (p->pack_size <= offset)
die("object offset outside of pack file");
- used = unpack_object_header_gently((unsigned char *)p->pack_base +
- offset,
+ used = unpack_object_header_gently(p->windows->base + offset,
p->pack_size - offset, type, sizep);
if (!used)
die("object offset outside of pack file");
if (p->pack_size <= offset + 20)
die("pack file %s records an incomplete delta base",
p->pack_name);
- next_sha1 = (unsigned char *) p->pack_base + offset;
+ next_sha1 = p->windows->base + offset;
if (*delta_chain_length == 0)
hashcpy(base_sha1, next_sha1);
offset = find_pack_entry_one(next_sha1, p);
buffer = xmalloc(size + 1);
buffer[size] = 0;
memset(&stream, 0, sizeof(stream));
- stream.next_in = (unsigned char*)p->pack_base + offset;
+ stream.next_in = p->windows->base + offset;
stream.avail_in = p->pack_size - offset;
stream.next_out = buffer;
stream.avail_out = size;