Commit Diff


commit - d52aad142172d4a9c6219ac2f685a90832fa0838
commit + b5c757f5f816a8061f4879da9e68a39141148e40
blob - c9025f9b0c09acff3245e5476c5242711a24a7b7
blob + 7520e71fd4327bf9eb5df008f47f25845a44564e
--- gotwebd/gotweb.c
+++ gotwebd/gotweb.c
@@ -292,8 +292,6 @@ err:
 	if (html && fcgi_printf(c, "</div>\n") == -1)
 		return;
 done:
-	if (c->t->repo != NULL && qs && qs->action != INDEX)
-		got_repo_close(c->t->repo);
 	if (html && srv != NULL)
 		gotweb_render_footer(c);
 }
@@ -1096,9 +1094,6 @@ render:
 
 		gotweb_free_repo_dir(repo_dir);
 		repo_dir = NULL;
-		error = got_repo_close(t->repo);
-		if (error)
-			goto done;
 		t->next_disp++;
 		if (d_disp == srv->max_repos_display)
 			break;
@@ -1913,13 +1908,75 @@ done:
 	return error;
 }
 
+static struct got_repository *
+find_cached_repo(struct server *srv, const char *path)
+{
+	int i;
+
+	for (i = 0; i < srv->ncached_repos; i++) {
+		if (strcmp(srv->cached_repos[i].path, path) == 0)
+			return srv->cached_repos[i].repo;
+	}
+
+	return NULL;
+}
+
 static const struct got_error *
+cache_repo(struct got_repository **new, struct server *srv,
+    struct repo_dir *repo_dir, struct socket *sock)
+{
+	const struct got_error *error = NULL;
+	struct got_repository *repo;
+	struct cached_repo *cr;
+	int evicted = 0;
+
+	if (srv->ncached_repos >= nitems(srv->cached_repos)) {
+		cr = &srv->cached_repos[srv->ncached_repos - 1];
+		error = got_repo_close(cr->repo);
+		memset(cr, 0, sizeof(*cr));
+		srv->ncached_repos--;
+		if (error)
+			return error;
+		memmove(&srv->cached_repos[1], &srv->cached_repos[0],
+		    srv->ncached_repos * sizeof(srv->cached_repos[0]));
+		cr = &srv->cached_repos[0];
+		evicted = 1;
+	} else {
+		cr = &srv->cached_repos[srv->ncached_repos];
+	}
+
+	error = got_repo_open(&repo, repo_dir->path, NULL, sock->pack_fds);
+	if (error) {
+		if (evicted) {
+			memmove(&srv->cached_repos[0], &srv->cached_repos[1],
+			    srv->ncached_repos * sizeof(srv->cached_repos[0]));
+		}
+		return error;
+	}
+
+	if (strlcpy(cr->path, repo_dir->path, sizeof(cr->path))
+	    >= sizeof(cr->path)) {
+		if (evicted) {
+			memmove(&srv->cached_repos[0], &srv->cached_repos[1],
+			    srv->ncached_repos * sizeof(srv->cached_repos[0]));
+		}
+		return got_error(GOT_ERR_NO_SPACE);
+	}
+
+	cr->repo = repo;
+	srv->ncached_repos++;
+	*new = repo;
+	return NULL;
+}
+
+static const struct got_error *
 gotweb_load_got_path(struct request *c, struct repo_dir *repo_dir)
 {
 	const struct got_error *error = NULL;
 	struct socket *sock = c->sock;
 	struct server *srv = c->srv;
 	struct transport *t = c->t;
+	struct got_repository *repo = NULL;
 	DIR *dt;
 	char *dir_test;
 	int opened = 0;
@@ -1979,9 +2036,13 @@ gotweb_load_got_path(struct request *c, struct repo_di
 	} else
 		opened = 1;
 done:
-	error = got_repo_open(&t->repo, repo_dir->path, NULL, sock->pack_fds);
-	if (error)
-		goto err;
+	repo = find_cached_repo(srv, repo_dir->path);
+	if (repo == NULL) {
+		error = cache_repo(&repo, srv, repo_dir, sock);
+		if (error)
+			goto err;
+	}
+	t->repo = repo;
 	error = gotweb_get_repo_description(&repo_dir->description, srv,
 	    repo_dir->path);
 	if (error)
blob - ae08f3df1ae9fb58a5fac19a6fcfd02a1aad9247
blob + 74ee67ae6734f6af0af3ab58f3276ceeccc8863a
--- gotwebd/gotwebd.h
+++ gotwebd/gotwebd.h
@@ -46,6 +46,7 @@
 #define GOTWEBD_MAXPORT		 6
 #define GOTWEBD_NUMPROC		 3
 #define GOTWEBD_MAXIFACE	 16
+#define GOTWEBD_REPO_CACHESIZE	 4
 
 /* GOTWEB DEFAULTS */
 #define MAX_QUERYSTRING		 2048
@@ -250,10 +251,18 @@ struct address {
 };
 TAILQ_HEAD(addresslist, address);
 
+struct cached_repo {
+	char path[PATH_MAX];
+	struct got_repository *repo;
+};
+
 struct server {
 	TAILQ_ENTRY(server)	 entry;
 	struct addresslist	al;
 
+	struct cached_repo	cached_repos[GOTWEBD_REPO_CACHESIZE];
+	int		 ncached_repos;
+
 	char		 name[GOTWEBD_MAXTEXT];
 
 	char		 repos_path[PATH_MAX];
blob - 7e510af9c4ae6f2609874519758443d006c1afc3
blob + c0691c5575dca8c931af0e8e30d9e086b5a5bccc
--- gotwebd/sockets.c
+++ gotwebd/sockets.c
@@ -51,6 +51,7 @@
 
 #include "got_error.h"
 #include "got_opentemp.h"
+#include "got_repository.h"
 
 #include "proc.h"
 #include "gotwebd.h"
@@ -351,6 +352,7 @@ sockets_shutdown(void)
 {
 	struct server *srv, *tsrv;
 	struct socket *sock, *tsock;
+	int i;
 
 	sockets_purge(gotwebd_env);
 
@@ -362,8 +364,11 @@ sockets_shutdown(void)
 	}
 
 	/* clean servers */
-	TAILQ_FOREACH_SAFE(srv, &gotwebd_env->servers, entry, tsrv)
+	TAILQ_FOREACH_SAFE(srv, &gotwebd_env->servers, entry, tsrv) {
+		for (i = 0; i < srv->ncached_repos; i++)
+			got_repo_close(srv->cached_repos[i].repo);
 		free(srv);
+	}
 
 	free(gotwebd_env);
 }