[MAKESHIFT PATCH] Cope better with a _lot_ of packs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxx>
---

	On Fri, 15 May 2009, Junio C Hamano wrote:

	> Johannes Schindelin <Johannes.Schindelin@xxxxxx> 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

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]