aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Jason A. Donenfeld <Jason@zx2c4.com>2014-01-13 04:58:21 (JST)
committerGravatar Jason A. Donenfeld <Jason@zx2c4.com>2014-01-14 10:00:07 (JST)
commitd750c7a2c9bb83cfc47c0d74fcee61f0a5042aa9 (patch)
tree51697a3a35b56957e827682d3119bdca4e2684bc
parent4bb87cbf17588ec91b46bf0ef0be01672e9be787 (diff)
downloadcgit-d750c7a2c9bb83cfc47c0d74fcee61f0a5042aa9.zip
cgit-d750c7a2c9bb83cfc47c0d74fcee61f0a5042aa9.tar.gz
filter: allow for cleanup hook for filter types
At some point, we're going to want to do lazy deallocation of filters. For example, if we implement lua, we'll want to load the lua runtime once for each filter, even if that filter is called many times. Similarly, for persistent exec filters, we'll want to load it once, despite many open_filter and close_filter calls, and only reap the child process at the end of the cgit process. For this reason, we add here a cleanup function that is called at the end of cgit's main(). Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--cgit.c1
-rw-r--r--cgit.h2
-rw-r--r--filter.c90
3 files changed, 66 insertions, 27 deletions
diff --git a/cgit.c b/cgit.c
index 29b658e..4f31e58 100644
--- a/cgit.c
+++ b/cgit.c
@@ -951,6 +951,7 @@ int main(int argc, const char **argv)
951 ctx.cfg.cache_size = 0; 951 ctx.cfg.cache_size = 0;
952 err = cache_process(ctx.cfg.cache_size, ctx.cfg.cache_root, 952 err = cache_process(ctx.cfg.cache_size, ctx.cfg.cache_root,
953 ctx.qry.raw, ttl, process_request, &ctx); 953 ctx.qry.raw, ttl, process_request, &ctx);
954 cgit_cleanup_filters();
954 if (err) 955 if (err)
955 cgit_print_error("Error processing page: %s (%d)", 956 cgit_print_error("Error processing page: %s (%d)",
956 strerror(err), err); 957 strerror(err), err);
diff --git a/cgit.h b/cgit.h
index 92e8c55..893c38f 100644
--- a/cgit.h
+++ b/cgit.h
@@ -60,6 +60,7 @@ struct cgit_filter {
60 int (*open)(struct cgit_filter *, va_list ap); 60 int (*open)(struct cgit_filter *, va_list ap);
61 int (*close)(struct cgit_filter *); 61 int (*close)(struct cgit_filter *);
62 void (*fprintf)(struct cgit_filter *, FILE *, const char *prefix); 62 void (*fprintf)(struct cgit_filter *, FILE *, const char *prefix);
63 void (*cleanup)(struct cgit_filter *);
63}; 64};
64 65
65struct cgit_exec_filter { 66struct cgit_exec_filter {
@@ -355,6 +356,7 @@ extern int cgit_close_filter(struct cgit_filter *filter);
355extern void cgit_fprintf_filter(struct cgit_filter *filter, FILE *f, const char *prefix); 356extern void cgit_fprintf_filter(struct cgit_filter *filter, FILE *f, const char *prefix);
356extern void cgit_exec_filter_init(struct cgit_exec_filter *filter, char *cmd, char **argv); 357extern void cgit_exec_filter_init(struct cgit_exec_filter *filter, char *cmd, char **argv);
357extern struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype); 358extern struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype);
359extern void cgit_cleanup_filters(void);
358 360
359extern void cgit_prepare_repo_env(struct cgit_repo * repo); 361extern void cgit_prepare_repo_env(struct cgit_repo * repo);
360 362
diff --git a/filter.c b/filter.c
index ba66e46..30bc74b 100644
--- a/filter.c
+++ b/filter.c
@@ -13,6 +13,25 @@
13#include <string.h> 13#include <string.h>
14#include <stdlib.h> 14#include <stdlib.h>
15 15
16static inline void reap_filter(struct cgit_filter *filter)
17{
18 if (filter && filter->cleanup)
19 filter->cleanup(filter);
20}
21
22void cgit_cleanup_filters(void)
23{
24 int i;
25 reap_filter(ctx.cfg.about_filter);
26 reap_filter(ctx.cfg.commit_filter);
27 reap_filter(ctx.cfg.source_filter);
28 for (i = 0; i < cgit_repolist.count; ++i) {
29 reap_filter(cgit_repolist.repos[i].about_filter);
30 reap_filter(cgit_repolist.repos[i].commit_filter);
31 reap_filter(cgit_repolist.repos[i].source_filter);
32 }
33}
34
16static int open_exec_filter(struct cgit_filter *base, va_list ap) 35static int open_exec_filter(struct cgit_filter *base, va_list ap)
17{ 36{
18 struct cgit_exec_filter *filter = (struct cgit_exec_filter *) base; 37 struct cgit_exec_filter *filter = (struct cgit_exec_filter *) base;
@@ -67,34 +86,17 @@ static void fprintf_exec_filter(struct cgit_filter *base, FILE *f, const char *p
67 fprintf(f, "%sexec:%s\n", prefix, filter->cmd); 86 fprintf(f, "%sexec:%s\n", prefix, filter->cmd);
68} 87}
69 88
70int cgit_open_filter(struct cgit_filter *filter, ...) 89static void cleanup_exec_filter(struct cgit_filter *base)
71{
72 int result;
73 va_list ap;
74 va_start(ap, filter);
75 result = filter->open(filter, ap);
76 va_end(ap);
77 return result;
78}
79
80int cgit_close_filter(struct cgit_filter *filter)
81{
82 return filter->close(filter);
83}
84
85void cgit_fprintf_filter(struct cgit_filter *filter, FILE *f, const char *prefix)
86{
87 filter->fprintf(filter, f, prefix);
88}
89
90void cgit_exec_filter_init(struct cgit_exec_filter *filter, char *cmd, char **argv)
91{ 90{
92 memset(filter, 0, sizeof(*filter)); 91 struct cgit_exec_filter *filter = (struct cgit_exec_filter *) base;
93 filter->base.open = open_exec_filter; 92 if (filter->argv) {
94 filter->base.close = close_exec_filter; 93 free(filter->argv);
95 filter->base.fprintf = fprintf_exec_filter; 94 filter->argv = NULL;
96 filter->cmd = cmd; 95 }
97 filter->argv = argv; 96 if (filter->cmd) {
97 free(filter->cmd);
98 filter->cmd = NULL;
99 }
98} 100}
99 101
100static struct cgit_filter *new_exec_filter(const char *cmd, filter_type filtertype) 102static struct cgit_filter *new_exec_filter(const char *cmd, filter_type filtertype)
@@ -125,6 +127,39 @@ static struct cgit_filter *new_exec_filter(const char *cmd, filter_type filterty
125 return &f->base; 127 return &f->base;
126} 128}
127 129
130void cgit_exec_filter_init(struct cgit_exec_filter *filter, char *cmd, char **argv)
131{
132 memset(filter, 0, sizeof(*filter));
133 filter->base.open = open_exec_filter;
134 filter->base.close = close_exec_filter;
135 filter->base.fprintf = fprintf_exec_filter;
136 filter->base.cleanup = cleanup_exec_filter;
137 filter->cmd = cmd;
138 filter->argv = argv;
139}
140
141int cgit_open_filter(struct cgit_filter *filter, ...)
142{
143 int result;
144 va_list ap;
145 va_start(ap, filter);
146 result = filter->open(filter, ap);
147 va_end(ap);
148 return result;
149}
150
151int cgit_close_filter(struct cgit_filter *filter)
152{
153 return filter->close(filter);
154}
155
156void cgit_fprintf_filter(struct cgit_filter *filter, FILE *f, const char *prefix)
157{
158 filter->fprintf(filter, f, prefix);
159}
160
161
162
128static const struct { 163static const struct {
129 const char *prefix; 164 const char *prefix;
130 struct cgit_filter *(*ctor)(const char *cmd, filter_type filtertype); 165 struct cgit_filter *(*ctor)(const char *cmd, filter_type filtertype);
@@ -161,3 +196,4 @@ struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype)
161 196
162 die("Invalid filter type: %.*s", (int) len, cmd); 197 die("Invalid filter type: %.*s", (int) len, cmd);
163} 198}
199