cgit

commit 8813170390f3c3a0f4743afbc92ede42953fa3b0

Author: Lars Hjemli <hjemli@gmail.com>

ui-repolist: implement lazy caching of repo->mtime

When sorting the list of repositories by their last modification time,
cgit would (in the worst case) invoke fstat(3) four times and open(3)
twice for each callback from qsort(3). This obviously scales very badly.

Now, the calculated modtime for each repo is saved in repo->mtime, thus
keeping the number of stat/open invocations identical for sorted and
unsorted repo-listings.

Signed-off-by: Lars Hjemli <hjemli@gmail.com>

 cgit.h | 1 +
 shared.c | 1 +
 ui-repolist.c | 16 ++++++++++++----


diff --git a/cgit.h b/cgit.h
index ea90833e923c4ee2faaa49ae8ed1788f47dcbe6a..c99d3377b8f962402b10b6aebd5230f77ff1ec2d 100644
--- a/cgit.h
+++ b/cgit.h
@@ -61,6 +61,7 @@ 	char *clone_url;
 	int snapshots;
 	int enable_log_filecount;
 	int enable_log_linecount;
+	time_t mtime;
 };
 
 struct cgit_repolist {




diff --git a/shared.c b/shared.c
index f5875e4273d55d6380dedd3310ebac08a9b636d7..89d1bab90f9e6d4f53ee873dfffb4fb9515bedbd 100644
--- a/shared.c
+++ b/shared.c
@@ -60,6 +60,7 @@ 	ret->enable_log_filecount = ctx.cfg.enable_log_filecount;
 	ret->enable_log_linecount = ctx.cfg.enable_log_linecount;
 	ret->module_link = ctx.cfg.module_link;
 	ret->readme = NULL;
+	ret->mtime = -1;
 	return ret;
 }
 




diff --git a/ui-repolist.c b/ui-repolist.c
index cf27cb3072a2cca564bac95f733fe5bfe489f901..aa743bf7885ab683e1b1e1b668d73d2477d7dd71 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -32,19 +32,27 @@ static int get_repo_modtime(const struct cgit_repo *repo, time_t *mtime)
 {
 	char *path;
 	struct stat s;
+	struct cgit_repo *r = (struct cgit_repo *)repo;
 
+	if (repo->mtime != -1) {
+		*mtime = repo->mtime;
+		return 1;
+	}
 	path = fmt("%s/%s", repo->path, ctx.cfg.agefile);
 	if (stat(path, &s) == 0) {
 		*mtime = read_agefile(path);
+		r->mtime = *mtime;
 		return 1;
 	}
 
 	path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch);
-	if (stat(path, &s) == 0) {
+	if (stat(path, &s) == 0)
 		*mtime = s.st_mtime;
-		return 1;
-	}
-	return 0;
+	else
+		*mtime = 0;
+
+	r->mtime = *mtime;
+	return (r->mtime != 0);
 }
 
 static void print_modtime(struct cgit_repo *repo)