[MAKESHIFT PATCH] Cope better with a _lot_ of packs
You might end up with a situation where you have tons of pack files, e.g. when using hg2git. In this situation, all kinds of operations may end up with a "too many files open" error. Let's recover gracefully from that.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
On Fri, 15 May 2009, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > if you need a chuckle, like me, you might appreciate this
> > story: in one of my repositories, "git gc" dies with
> >
> > unable to open object pack directory: ...: Too many open files
> >
> > turns out that there are a whopping 1088 packs in that
> > repository...
>
> Isn't it a more serious problem than a mere chuckle?
Well, it was kind of morbid humor, I guess. So much so that I
just had to send off that mail when I encountered the problem.
> How would one recover from such a situation (other than
> "mv .git/objects/pack-*; for p in pack-*.pack; do git unpack-objects
> <$p; done")?
Very easy: one writes a patch.
I am sure that I did not catch all problematic sites, but this
patch works almost, at least.
Another issue is how to include a test for this... I cannot think
of a non-expensive way.
sha1_file.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/sha1_file.c b/sha1_file.c
index 28bd908..bd5edd8 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -720,6 +720,8 @@ static int open_packed_git_1(struct packed_git *p)
return error("packfile %s index unavailable", p->pack_name);
p->pack_fd = open(p->pack_name, O_RDONLY);
+ while (p->pack_fd < 0 && errno == EMFILE && unuse_one_window(p, -1))
+ p->pack_fd = open(p->pack_name, O_RDONLY);
if (p->pack_fd < 0 || fstat(p->pack_fd, &st))
return -1;
@@ -937,6 +939,8 @@ static void prepare_packed_git_one(char *objdir, int local)
sprintf(path, "%s/pack", objdir);
len = strlen(path);
dir = opendir(path);
+ while (!dir && errno == EMFILE && unuse_one_window(packed_git, -1))
+ dir = opendir(path);
if (!dir) {
if (errno != ENOENT)
error("unable to open object pack directory: %s: %s",
@@ -2339,6 +2343,8 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
filename = sha1_file_name(sha1);
fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
+ while (fd < 0 && errno == EMFILE && unuse_one_window(packed_git, -1))
+ fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
if (fd < 0) {
if (errno == EACCES)
return error("insufficient permission for adding an object to repository database %s\n", get_object_directory());
--
1.6.3.1.10.g12b3.dirty