[PATCH 1/6] Open the pack file and keep a map on it.
On the same model than the idx file.
Signed-off-by: Hervé Cauwelier <herve@itaapy.com>
---
src/odb.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
src/odb.h | 1 +
2 files changed, 65 insertions(+), 1 deletions(-)
diff --git a/src/odb.c b/src/odb.c
index 6d646a4..2319998 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -64,6 +64,10 @@ struct git_pack {
/** Name of the pack file(s), without extension ("pack-abc"). */
char pack_name[GIT_PACK_NAME_MAX];
+
+ /** The .pack file, mapped into memory. */
+ git_file pack_fd;
+ git_map pack_map;
};
typedef struct git_pack git_pack;
@@ -809,6 +813,59 @@ unlock_fail:
return GIT_ERROR;
}
+static int pack_openpack_map(git_pack *p)
+{
+ char pb[GIT_PATH_MAX];
+ off_t len;
+
+ if (git__fmt(pb, sizeof(pb), "%s/pack/%s.pack",
+ p->db->objects_dir,
+ p->pack_name) < 0)
+ return GIT_ERROR;
+
+ if ((p->pack_fd = gitfo_open(pb, O_RDONLY)) < 0)
+ return GIT_ERROR;
+
+ if ((len = gitfo_size(p->pack_fd)) < 0
+ || !git__is_sizet(len)
+ || gitfo_map_ro(&p->pack_map, p->pack_fd, 0, (size_t)len)) {
+ gitfo_close(p->pack_fd);
+ return GIT_ERROR;
+ }
+
+ return GIT_SUCCESS;
+}
+
+static int pack_openpack(git_pack *p)
+{
+ gitlck_lock(&p->lock);
+ if (p->invalid)
+ goto unlock_fail;
+ if (p->pack_fd < 0) {
+ uint32_t *data;
+
+ if (pack_openpack_map(p))
+ goto invalid_fail;
+ data = p->pack_map.data;
+
+ if (decode32(&data[0]) != PACK_HDR)
+ goto unmap_fail;
+ }
+ gitlck_unlock(&p->lock);
+ return GIT_SUCCESS;
+
+unmap_fail:
+ gitfo_free_map(&p->pack_map);
+
+invalid_fail:
+ p->invalid = 1;
+ p->pack_fd = -1;
+
+unlock_fail:
+ gitlck_unlock(&p->lock);
+ return GIT_ERROR;
+}
+
static void pack_decidx(git_pack *p)
{
gitlck_lock(&p->lock);
@@ -830,6 +887,11 @@ static void pack_dec(git_pack *p)
gitfo_close(p->idx_fd);
free(p->im_fanout);
}
+ if (p->pack_fd >= 0) {
+ gitfo_free_map(&p->pack_map);
+ gitfo_close(p->pack_fd);
+ p->pack_fd = -1;
+ }
gitlck_free(&p->lock);
free(p);
@@ -861,6 +923,7 @@ static git_pack *alloc_pack(const char *pack_name)
gitlck_init(&p->lock);
strcpy(p->pack_name, pack_name);
p->refcnt = 1;
+ p->pack_fd = -1;
return p;
}
@@ -895,7 +958,7 @@ static int scan_one_pack(void *state, char *name)
r->next = *ret;
*ret = r;
- return 0;
+ return GIT_SUCCESS;
}
static git_packlist* scan_packs(git_odb *db)
diff --git a/src/odb.h b/src/odb.h
index 2f205b2..121583f 100644
--- a/src/odb.h
+++ b/src/odb.h
@@ -15,5 +15,6 @@
* cannot be true for an idx v1 file.
*/
#define PACK_TOC 0xff744f63 /* -1tOc */
+#define PACK_HDR 0x5041434b /* PACK */
#endif
--
1.6.5