From b51f3215a547f7d16d58dc394f652b9dfe8741f1 Mon Sep 17 00:00:00 2001 From: phk Date: Thu, 30 Mar 2006 07:05:10 +0000 Subject: [PATCH] Integrate the VCL code closer in the cache process: The passed argument will be the session structure. Add the pool of worker threads (cache_pool). With a unitary nature of the VCL code, the HTTP parsing can be postponed to the worker thread. This actually helps us with CPU cache locality as it will reduce the amount of memory allocated on one CPU but freed on another. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@84 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/Makefile.am | 1 + varnish-cache/bin/varnishd/cache.h | 38 ++--------- varnish-cache/bin/varnishd/cache_acceptor.c | 6 +- varnish-cache/bin/varnishd/cache_httpd.c | 21 ++---- varnish-cache/bin/varnishd/cache_main.c | 2 + varnish-cache/bin/varnishd/cache_pool.c | 61 +++++++++++++++++ varnish-cache/bin/varnishd/cache_vcl.c | 10 +++ varnish-cache/bin/varnishd/varnishd.c | 19 +++++- varnish-cache/include/vcl_lang.h | 63 +++++++++++------ varnish-cache/lib/libvcl/vcl_compile.c | 10 ++- varnish-cache/lib/libvcl/vcl_fixed_token.c | 67 +++++++++++++------ .../lib/libvcl/vcl_gen_fixed_token.tcl | 1 + varnish-cache/lib/libvcl/vcl_token_defs.h | 55 +++++++-------- 13 files changed, 225 insertions(+), 129 deletions(-) create mode 100644 varnish-cache/bin/varnishd/cache_pool.c diff --git a/varnish-cache/bin/varnishd/Makefile.am b/varnish-cache/bin/varnishd/Makefile.am index 72654aed..a822cc26 100644 --- a/varnish-cache/bin/varnishd/Makefile.am +++ b/varnish-cache/bin/varnishd/Makefile.am @@ -8,6 +8,7 @@ varnishd_SOURCES = \ cache_acceptor.c \ cache_httpd.c \ cache_main.c \ + cache_pool.c \ cache_shmlog.c \ cache_vcl.c \ cli_event.c \ diff --git a/varnish-cache/bin/varnishd/cache.h b/varnish-cache/bin/varnishd/cache.h index cdf878d0..cb530c72 100644 --- a/varnish-cache/bin/varnishd/cache.h +++ b/varnish-cache/bin/varnishd/cache.h @@ -2,46 +2,16 @@ * $Id$ */ -#define VCA_RXBUFSIZE 1024 -#define VCA_ADDRBUFSIZE 32 - -struct sess { - int fd; - - /* formatted ascii client address */ - char addr[VCA_ADDRBUFSIZE]; - - /* Receive buffer for HTTP header */ - char rcv[VCA_RXBUFSIZE + 1]; - unsigned rcv_len; - - /* HTTP request info, points into rcv */ - const char *req_b; - const char *req_e; - const char *url_b; - const char *url_e; - const char *proto_b; - const char *proto_e; - const char *hdr_b; - const char *hdr_e; - - enum { - HND_Unclass, - HND_Handle, - HND_Pass - } handling; - - /* Various internal stuff */ - struct event *rd_e; - struct sessmem *mem; -}; - /* cache_acceptor.c */ void *vca_main(void *arg); /* cache_httpd.c */ void HttpdAnalyze(struct sess *sp); +/* cache_pool.c */ +void CacheInitPool(void); +void DealWithSession(struct sess *sp); + /* cache_shmlog.c */ void VSL_Init(void); #ifdef SHMLOGHEAD_MAGIC diff --git a/varnish-cache/bin/varnishd/cache_acceptor.c b/varnish-cache/bin/varnishd/cache_acceptor.c index ae46f4f6..5a66371d 100644 --- a/varnish-cache/bin/varnishd/cache_acceptor.c +++ b/varnish-cache/bin/varnishd/cache_acceptor.c @@ -17,6 +17,7 @@ #include #include "libvarnish.h" +#include "vcl_lang.h" #include "heritage.h" #include "shmlog.h" #include "cache.h" @@ -65,10 +66,7 @@ http_read_f(int fd, short event, void *arg) } sp->hdr_e = p; event_del(sp->rd_e); - HttpdAnalyze(sp); - - /* XXX: for now, pass everything */ - sp->handling = HND_Pass; + DealWithSession(sp); } static void diff --git a/varnish-cache/bin/varnishd/cache_httpd.c b/varnish-cache/bin/varnishd/cache_httpd.c index 576f25bb..1ed4f7eb 100644 --- a/varnish-cache/bin/varnishd/cache_httpd.c +++ b/varnish-cache/bin/varnishd/cache_httpd.c @@ -9,6 +9,7 @@ #include "libvarnish.h" #include "shmlog.h" +#include "vcl_lang.h" #include "cache.h" void @@ -20,23 +21,9 @@ HttpdAnalyze(struct sess *sp) /* First, isolate and possibly identify request type */ p = sp->req_b = sp->rcv; - if (p[0] == 'G' && p[1] == 'E' && p[2] == 'T' && p[3] == ' ') { - p = sp->req_e = p + 4; - sp->handling = HND_Handle; - } else if (p[0] == 'H' && p[1] == 'E' && p[2] == 'A' && p[3] == 'D' - && p[4] == ' ') { - p = sp->req_e = p + 5; - sp->handling = HND_Handle; - } else { - /* - * We don't bother to identify the rest, we won't handle - * them in any case - */ - for (q = p; isalpha(*q); q++) - ; - p = sp->req_e = q; - sp->handling = HND_Pass; - } + for (q = p; isalpha(*q); q++) + ; + p = sp->req_e = q; VSLR(SLT_Request, sp->fd, sp->req_b, sp->req_e); /* Next find the URI */ diff --git a/varnish-cache/bin/varnishd/cache_main.c b/varnish-cache/bin/varnishd/cache_main.c index 3b8d88ca..98e57126 100644 --- a/varnish-cache/bin/varnishd/cache_main.c +++ b/varnish-cache/bin/varnishd/cache_main.c @@ -18,6 +18,7 @@ #include "libvarnish.h" #include "heritage.h" #include "shmlog.h" +#include "vcl_lang.h" #include "cache.h" #include "cli_event.h" @@ -100,6 +101,7 @@ child_main(void) printf("Child starts\n"); VSL_Init(); + CacheInitPool(); AZ(pthread_create(&vca_thread, NULL, vca_main, NULL)); diff --git a/varnish-cache/bin/varnishd/cache_pool.c b/varnish-cache/bin/varnishd/cache_pool.c new file mode 100644 index 00000000..769435d0 --- /dev/null +++ b/varnish-cache/bin/varnishd/cache_pool.c @@ -0,0 +1,61 @@ +/* + * $Id$ + */ + +#include +#include +#include + +#include "libvarnish.h" +#include "vcl_lang.h" +#include "cache.h" + +static TAILQ_HEAD(, sess) shd = TAILQ_HEAD_INITIALIZER(shd); + +static pthread_mutex_t shdmtx; +static pthread_cond_t shdcnd; + +static void * +CacheWorker(void *priv __unused) +{ + struct sess *sp; + + while (1) { + AZ(pthread_mutex_lock(&shdmtx)); + while (1) { + sp = TAILQ_FIRST(&shd); + if (sp != NULL) + break; + AZ(pthread_cond_wait(&shdcnd, &shdmtx)); + } + TAILQ_REMOVE(&shd, sp, list); + AZ(pthread_mutex_unlock(&shdmtx)); + + HttpdAnalyze(sp); + + /* + * XXX send session to acceptor for reuse/disposal + */ + } +} + +void +DealWithSession(struct sess *sp) +{ + AZ(pthread_mutex_lock(&shdmtx)); + TAILQ_INSERT_TAIL(&shd, sp, list); + AZ(pthread_mutex_unlock(&shdmtx)); + AZ(pthread_cond_signal(&shdcnd)); +} + +void +CacheInitPool(void) +{ + pthread_t tp; + + AZ(pthread_mutex_init(&shdmtx, NULL)); + AZ(pthread_cond_init(&shdcnd, NULL)); + + AZ(pthread_create(&tp, NULL, CacheWorker, NULL)); + AZ(pthread_detach(tp)); +} diff --git a/varnish-cache/bin/varnishd/cache_vcl.c b/varnish-cache/bin/varnishd/cache_vcl.c index 3c229824..e69c8e79 100644 --- a/varnish-cache/bin/varnishd/cache_vcl.c +++ b/varnish-cache/bin/varnishd/cache_vcl.c @@ -142,3 +142,13 @@ cli_func_config_use(struct cli *cli, char **av, void *priv) } active_vcl = vcl; } + +/*--------------------------------------------------------------------*/ + +void +VCL_pass(VCL_FARGS) +{ + + sess->handling = HND_Pass; + sess->done++; +} diff --git a/varnish-cache/bin/varnishd/varnishd.c b/varnish-cache/bin/varnishd/varnishd.c index 747648c6..6266f638 100644 --- a/varnish-cache/bin/varnishd/varnishd.c +++ b/varnish-cache/bin/varnishd/varnishd.c @@ -68,8 +68,23 @@ vcl_default(const char *bflag) buf = NULL; asprintf(&buf, - "backend default { set backend.ip = %s; }", - bflag); + "backend default { set backend.ip = %s; }\n" + "sub main {\n" + " pass;\n" +#if 0 + " if (req.request != \"GET\" && req.request != \"HEAD\") {\n" + " pass;\n" + " }\n" + " lookup;\n" + " if (!obj.valid) {\n" + " fetch;\n" + " if (obj.cacheable) {\n" + " insert;\n" + " }\n" + " }\n" +#endif + "}\n" + "", bflag); assert(buf != NULL); sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); assert(sb != NULL); diff --git a/varnish-cache/include/vcl_lang.h b/varnish-cache/include/vcl_lang.h index 4e74e474..3d400688 100644 --- a/varnish-cache/include/vcl_lang.h +++ b/varnish-cache/include/vcl_lang.h @@ -5,6 +5,7 @@ * XXX: *MUST* be rerun. */ +#include struct vcl_ref { unsigned line; @@ -18,19 +19,42 @@ struct vcl_acl { unsigned mask; }; -struct client { - unsigned ip; -}; +#define VCA_RXBUFSIZE 1024 +#define VCA_ADDRBUFSIZE 32 + +struct sess { + int fd; + + /* formatted ascii client address */ + char addr[VCA_ADDRBUFSIZE]; + + /* Receive buffer for HTTP header */ + char rcv[VCA_RXBUFSIZE + 1]; + unsigned rcv_len; + + /* HTTP request info, points into rcv */ + const char *req_b; + const char *req_e; + const char *url_b; + const char *url_e; + const char *proto_b; + const char *proto_e; + const char *hdr_b; + const char *hdr_e; -struct req { - char *req; - char *useragent; - struct { - char *path; - char *host; - } url; - double ttlfactor; - struct backend *backend; + enum { + HND_Unclass, + HND_Handle, + HND_Pass + } handling; + + char done; + + TAILQ_ENTRY(sess) list; + + /* Various internal stuff */ + struct event *rd_e; + struct sessmem *mem; }; struct backend { @@ -41,16 +65,8 @@ struct backend { int down; }; -struct obj { - int exists; - double ttl; - unsigned result; - unsigned size; - unsigned usage; -}; - -#define VCL_FARGS struct client *client, struct obj *obj, struct req *req, struct backend *backend -#define VCL_PASS_ARGS client, obj, req, backend +#define VCL_FARGS struct sess *sess +#define VCL_PASS_ARGS sess void VCL_count(unsigned); void VCL_no_cache(); @@ -59,15 +75,18 @@ int ip_match(unsigned, struct vcl_acl *); int string_match(const char *, const char *); int VCL_rewrite(const char *, const char *); int VCL_error(unsigned, const char *); +void VCL_pass(VCL_FARGS); int VCL_fetch(void); int VCL_switch_config(const char *); typedef void vcl_init_f(void); +typedef void vcl_func_f(VCL_FARGS); struct VCL_conf { unsigned magic; #define VCL_CONF_MAGIC 0x7406c509 /* from /dev/random */ vcl_init_f *init_func; + vcl_func_f *main_func; struct backend *default_backend; struct vcl_ref *ref; unsigned nref; diff --git a/varnish-cache/lib/libvcl/vcl_compile.c b/varnish-cache/lib/libvcl/vcl_compile.c index 1ea98388..eeb31b33 100644 --- a/varnish-cache/lib/libvcl/vcl_compile.c +++ b/varnish-cache/lib/libvcl/vcl_compile.c @@ -818,6 +818,11 @@ Action(struct tokenlist *tl) I(tl); sbuf_printf(tl->fc, "return;\n"); return; + case T_PASS: + I(tl); + sbuf_printf(tl->fc, "VCL_pass(VCL_PASS_ARGS);\n"); + sbuf_printf(tl->fc, "return;\n"); + return; case T_FETCH: I(tl); sbuf_printf(tl->fc, "VCL_fetch();\n"); @@ -849,7 +854,8 @@ Action(struct tokenlist *tl) sbuf_printf(tl->fc, "VCL_function_%*.*s(VCL_PASS_ARGS);\n", tl->t->e - tl->t->b, tl->t->e - tl->t->b, tl->t->b); - /* XXX: check if function finished request */ + I(tl); sbuf_printf(tl->fc, "if (sess->done)\n"); + I(tl); sbuf_printf(tl->fc, "\treturn;\n"); NextToken(tl); return; case T_REWRITE: @@ -1363,6 +1369,8 @@ EmitStruct(struct tokenlist *tl) "\t.magic = VCL_CONF_MAGIC,\n"); sbuf_printf(tl->fc, "\t.init_func = VCL_Init,\n"); + sbuf_printf(tl->fc, + "\t.main_func = VCL_function_main,\n"); sbuf_printf(tl->fc, "\t.default_backend = &VCL_backend_default,\n"); sbuf_printf(tl->fc, diff --git a/varnish-cache/lib/libvcl/vcl_fixed_token.c b/varnish-cache/lib/libvcl/vcl_fixed_token.c index 548e0028..3f2f4bbd 100644 --- a/varnish-cache/lib/libvcl/vcl_fixed_token.c +++ b/varnish-cache/lib/libvcl/vcl_fixed_token.c @@ -245,6 +245,11 @@ vcl_fixed_token(const char *p, const char **q) *q = p + 4; return (T_PROC); } + if (p[0] == 'p' && p[1] == 'a' && p[2] == 's' && + p[3] == 's' && !isvar(p[4])) { + *q = p + 4; + return (T_PASS); + } return (0); case 'r': if (p[0] == 'r' && p[1] == 'e' && p[2] == 'w' && @@ -360,6 +365,7 @@ vcl_init_tnames(void) vcl_tnames[T_NEQ] = "!="; vcl_tnames[T_NO_CACHE] = "no_cache"; vcl_tnames[T_NO_NEW_CACHE] = "no_new_cache"; + vcl_tnames[T_PASS] = "pass"; vcl_tnames[T_PROC] = "proc"; vcl_tnames[T_REWRITE] = "rewrite"; vcl_tnames[T_SET] = "set"; @@ -380,6 +386,7 @@ vcl_output_lang_h(FILE *f) fputs(" * XXX: *MUST* be rerun.\n", f); fputs(" */\n", f); fputs("\n", f); + fputs("#include \n", f); fputs("\n", f); fputs("struct vcl_ref {\n", f); fputs(" unsigned line;\n", f); @@ -393,19 +400,40 @@ vcl_output_lang_h(FILE *f) fputs(" unsigned mask;\n", f); fputs("};\n", f); fputs("\n", f); - fputs("struct client {\n", f); - fputs(" unsigned ip;\n", f); - fputs("};\n", f); + fputs("#define VCA_RXBUFSIZE 1024\n", f); + fputs("#define VCA_ADDRBUFSIZE 32\n", f); + fputs("\n", f); + fputs("struct sess {\n", f); + fputs(" int fd;\n", f); + fputs("\n", f); + fputs(" /* formatted ascii client address */\n", f); + fputs(" char addr[VCA_ADDRBUFSIZE];\n", f); fputs("\n", f); - fputs("struct req {\n", f); - fputs(" char *req;\n", f); - fputs(" char *useragent;\n", f); - fputs(" struct {\n", f); - fputs(" char *path;\n", f); - fputs(" char *host;\n", f); - fputs(" } url;\n", f); - fputs(" double ttlfactor;\n", f); - fputs(" struct backend *backend;\n", f); + fputs(" /* Receive buffer for HTTP header */\n", f); + fputs(" char rcv[VCA_RXBUFSIZE + 1];\n", f); + fputs(" unsigned rcv_len;\n", f); + fputs("\n", f); + fputs(" /* HTTP request info, points into rcv */\n", f); + fputs(" const char *req_b;\n", f); + fputs(" const char *req_e;\n", f); + fputs(" const char *url_b;\n", f); + fputs(" const char *url_e;\n", f); + fputs(" const char *proto_b;\n", f); + fputs(" const char *proto_e;\n", f); + fputs(" const char *hdr_b;\n", f); + fputs(" const char *hdr_e;\n", f); + fputs("\n", f); + fputs(" enum {\n", f); + fputs(" HND_Unclass,\n", f); + fputs(" HND_Handle,\n", f); + fputs(" HND_Pass\n", f); + fputs(" } handling;\n", f); + fputs("\n", f); + fputs(" char done;\n", f); + fputs("\n", f); + fputs(" /* Various internal stuff */\n", f); + fputs(" struct event *rd_e;\n", f); + fputs(" struct sessmem *mem;\n", f); fputs("};\n", f); fputs("\n", f); fputs("struct backend {\n", f); @@ -416,16 +444,8 @@ vcl_output_lang_h(FILE *f) fputs(" int down;\n", f); fputs("};\n", f); fputs("\n", f); - fputs("struct obj {\n", f); - fputs(" int exists;\n", f); - fputs(" double ttl;\n", f); - fputs(" unsigned result;\n", f); - fputs(" unsigned size;\n", f); - fputs(" unsigned usage;\n", f); - fputs("};\n", f); - fputs("\n", f); - fputs("#define VCL_FARGS struct client *client, struct obj *obj, struct req *req, struct backend *backend\n", f); - fputs("#define VCL_PASS_ARGS client, obj, req, backend\n", f); + fputs("#define VCL_FARGS struct sess *sess\n", f); + fputs("#define VCL_PASS_ARGS sess\n", f); fputs("\n", f); fputs("void VCL_count(unsigned);\n", f); fputs("void VCL_no_cache();\n", f); @@ -434,15 +454,18 @@ vcl_output_lang_h(FILE *f) fputs("int string_match(const char *, const char *);\n", f); fputs("int VCL_rewrite(const char *, const char *);\n", f); fputs("int VCL_error(unsigned, const char *);\n", f); + fputs("void VCL_pass(VCL_FARGS);\n", f); fputs("int VCL_fetch(void);\n", f); fputs("int VCL_switch_config(const char *);\n", f); fputs("\n", f); fputs("typedef void vcl_init_f(void);\n", f); + fputs("typedef void vcl_func_f(VCL_FARGS);\n", f); fputs("\n", f); fputs("struct VCL_conf {\n", f); fputs(" unsigned magic;\n", f); fputs("#define VCL_CONF_MAGIC 0x7406c509 /* from /dev/random */\n", f); fputs(" vcl_init_f *init_func;\n", f); + fputs(" vcl_func_f *main_func;\n", f); fputs(" struct backend *default_backend;\n", f); fputs(" struct vcl_ref *ref;\n", f); fputs(" unsigned nref;\n", f); diff --git a/varnish-cache/lib/libvcl/vcl_gen_fixed_token.tcl b/varnish-cache/lib/libvcl/vcl_gen_fixed_token.tcl index 60fbf0f5..4a06af59 100755 --- a/varnish-cache/lib/libvcl/vcl_gen_fixed_token.tcl +++ b/varnish-cache/lib/libvcl/vcl_gen_fixed_token.tcl @@ -13,6 +13,7 @@ set keywords { backend error + pass fetch call no_cache diff --git a/varnish-cache/lib/libvcl/vcl_token_defs.h b/varnish-cache/lib/libvcl/vcl_token_defs.h index 29655dc9..760f921f 100644 --- a/varnish-cache/lib/libvcl/vcl_token_defs.h +++ b/varnish-cache/lib/libvcl/vcl_token_defs.h @@ -14,30 +14,31 @@ #define T_ACL 135 #define T_BACKEND 136 #define T_ERROR 137 -#define T_FETCH 138 -#define T_CALL 139 -#define T_NO_CACHE 140 -#define T_NO_NEW_CACHE 141 -#define T_SET 142 -#define T_REWRITE 143 -#define T_FINISH 144 -#define T_SWITCH_CONFIG 145 -#define T_INC 146 -#define T_DEC 147 -#define T_CAND 148 -#define T_COR 149 -#define T_LEQ 150 -#define T_EQ 151 -#define T_NEQ 152 -#define T_GEQ 153 -#define T_SHR 154 -#define T_SHL 155 -#define T_INCR 156 -#define T_DECR 157 -#define T_MUL 158 -#define T_DIV 159 -#define ID 160 -#define VAR 161 -#define CNUM 162 -#define CSTR 163 -#define EOI 164 +#define T_PASS 138 +#define T_FETCH 139 +#define T_CALL 140 +#define T_NO_CACHE 141 +#define T_NO_NEW_CACHE 142 +#define T_SET 143 +#define T_REWRITE 144 +#define T_FINISH 145 +#define T_SWITCH_CONFIG 146 +#define T_INC 147 +#define T_DEC 148 +#define T_CAND 149 +#define T_COR 150 +#define T_LEQ 151 +#define T_EQ 152 +#define T_NEQ 153 +#define T_GEQ 154 +#define T_SHR 155 +#define T_SHL 156 +#define T_INCR 157 +#define T_DECR 158 +#define T_MUL 159 +#define T_DIV 160 +#define ID 161 +#define VAR 162 +#define CNUM 163 +#define CSTR 164 +#define EOI 165 -- 2.39.5