From 5bc35b5f4089d19f04e7efbba4812ad259a84a8b Mon Sep 17 00:00:00 2001 From: phk Date: Fri, 25 Jul 2008 16:33:04 +0000 Subject: [PATCH] Add a facility to constructing a synthetic object from VCL. This is just the initial version and it doesn't quite work the way we need it to yet, but the idea is to be able to say: sub vcl_fetch { if (obj.status == 503) { synthetic {"

Sorry, could not contact the backend server

Try again later.


			URL: "}  req.url {"
			User Agnet: "} req.http.user-agent {"
		    
"}; } } A new VCL syntactic element have been introduced to do this: "the long string". A long string is anything from {" to "}, newlines, controlcharacters and all. (Normal "..." strings cannot contain control characters. Technical details: Don't NULL terminate string sequences in VRT context, we may have NULL cropping up as a legal value if a header is missing, add the magic "vrt_magic_string_end" for terminating string contactenation. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@3026 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/cache.h | 5 +++ varnish-cache/bin/varnishd/cache_hash.c | 2 +- varnish-cache/bin/varnishd/cache_vrt.c | 39 +++++++++++++++++++++- varnish-cache/include/stat_field.h | 6 ++++ varnish-cache/include/vrt.h | 5 +++ varnish-cache/lib/libvcl/vcc_action.c | 23 +++++++++++-- varnish-cache/lib/libvcl/vcc_fixed_token.c | 5 +++ varnish-cache/lib/libvcl/vcc_token.c | 23 +++++++++++++ 8 files changed, 104 insertions(+), 4 deletions(-) diff --git a/varnish-cache/bin/varnishd/cache.h b/varnish-cache/bin/varnishd/cache.h index 43429e1b..aa09f6b2 100644 --- a/varnish-cache/bin/varnishd/cache.h +++ b/varnish-cache/bin/varnishd/cache.h @@ -461,6 +461,7 @@ void Fetch_Init(void); /* cache_hash.c */ void HSH_Prealloc(struct sess *sp); +void HSH_Freestore(struct object *o); int HSH_Compare(const struct sess *sp, const struct objhead *o); void HSH_Copy(const struct sess *sp, const struct objhead *o); struct object *HSH_Lookup(struct sess *sp); @@ -612,6 +613,10 @@ unsigned WS_Free(const struct ws *ws); /* rfc2616.c */ int RFC2616_cache_policy(const struct sess *sp, const struct http *hp); +/* storage_synth.c */ +struct vsb *SMS_Makesynth(struct object *obj); +void SMS_Finish(struct object *obj); + #define MTX pthread_mutex_t #define MTX_INIT(foo) AZ(pthread_mutex_init(foo, NULL)) #define MTX_DESTROY(foo) AZ(pthread_mutex_destroy(foo)) diff --git a/varnish-cache/bin/varnishd/cache_hash.c b/varnish-cache/bin/varnishd/cache_hash.c index cfd03e0c..6eba5876 100644 --- a/varnish-cache/bin/varnishd/cache_hash.c +++ b/varnish-cache/bin/varnishd/cache_hash.c @@ -116,7 +116,7 @@ HSH_Prealloc(struct sess *sp) CHECK_OBJ_NOTNULL(w->nobj, OBJECT_MAGIC); } -static void +void HSH_Freestore(struct object *o) { struct storage *st, *stn; diff --git a/varnish-cache/bin/varnishd/cache_vrt.c b/varnish-cache/bin/varnishd/cache_vrt.c index 2bc01609..cf5919a5 100644 --- a/varnish-cache/bin/varnishd/cache_vrt.c +++ b/varnish-cache/bin/varnishd/cache_vrt.c @@ -51,6 +51,9 @@ #include "vcl.h" #include "cache.h" + +void *vrt_magic_string_end = &vrt_magic_string_end; + /*--------------------------------------------------------------------*/ void @@ -136,7 +139,9 @@ vrt_assemble_string(struct http *hp, const char *h, const char *p, va_list ap) if (b + 1 < e) *b++ = ' '; } - while (p != NULL) { + while (p != vrt_magic_string_end) { + if (p == NULL) + p = "(null)"; x = strlen(p); if (b + x < e) memcpy(b, p, x); @@ -644,6 +649,38 @@ VRT_panic(struct sess *sp, const char *str, ...) /*--------------------------------------------------------------------*/ +/*lint -e{818} sp could be const */ +void +VRT_synth_page(struct sess *sp, unsigned flags, const char *str, ...) +{ + va_list ap; + const char *p; + struct vsb *vsb; + + (void)flags; + CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); + CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC); + vsb = SMS_Makesynth(sp->obj); + AN(vsb); + + vsb_cat(vsb, str); + va_start(ap, str); + p = va_arg(ap, const char *); + while (p != vrt_magic_string_end) { + if (p == NULL) + p = "(null)"; + vsb_cat(vsb, p); + p = va_arg(ap, const char *); + } + va_end(ap); + SMS_Finish(sp->obj); + http_Unset(sp->obj->http, H_Content_Length); + http_PrintfHeader(sp->wrk, sp->fd, sp->obj->http, + "Content-Length: %d", sp->obj->len); +} + +/*--------------------------------------------------------------------*/ + void VRT_purge(const char *regexp, int hash) { diff --git a/varnish-cache/include/stat_field.h b/varnish-cache/include/stat_field.h index 217d2305..8cc050f2 100644 --- a/varnish-cache/include/stat_field.h +++ b/varnish-cache/include/stat_field.h @@ -105,6 +105,12 @@ MAC_STAT(sma_nbytes, uint64_t, 'i', "SMA outstanding bytes") MAC_STAT(sma_balloc, uint64_t, 'i', "SMA bytes allocated") MAC_STAT(sma_bfree, uint64_t, 'i', "SMA bytes free") +MAC_STAT(sms_nreq, uint64_t, 'a', "SMS allocator requests") +MAC_STAT(sms_nobj, uint64_t, 'i', "SMS outstanding allocations") +MAC_STAT(sms_nbytes, uint64_t, 'i', "SMS outstanding bytes") +MAC_STAT(sms_balloc, uint64_t, 'i', "SMS bytes allocated") +MAC_STAT(sms_bfree, uint64_t, 'i', "SMS bytes free") + MAC_STAT(backend_req, uint64_t, 'a', "Backend requests made") MAC_STAT(n_vcl, uint64_t, 'a', "N vcl total") diff --git a/varnish-cache/include/vrt.h b/varnish-cache/include/vrt.h index 756c73bb..d9b77cc1 100644 --- a/varnish-cache/include/vrt.h +++ b/varnish-cache/include/vrt.h @@ -45,6 +45,8 @@ struct sockaddr; * A backend probe specification */ +extern void *vrt_magic_string_end; + struct vrt_backend_probe { char *request; double timeout; @@ -151,6 +153,9 @@ int VRT_strcmp(const char *s1, const char *s2); void VRT_ESI(struct sess *sp); void VRT_Rollback(struct sess *sp); +/* Synthetic pages */ +void VRT_synth_page(struct sess *sp, unsigned flags, const char *, ...); + /* Backend related */ void VRT_init_dir_simple(struct cli *, struct director **, const struct vrt_dir_simple *); void VRT_init_dir_random(struct cli *, struct director **, const struct vrt_dir_random *); diff --git a/varnish-cache/lib/libvcl/vcc_action.c b/varnish-cache/lib/libvcl/vcc_action.c index 2b02502f..05dcdddb 100644 --- a/varnish-cache/lib/libvcl/vcc_action.c +++ b/varnish-cache/lib/libvcl/vcc_action.c @@ -269,7 +269,7 @@ parse_set(struct tokenlist *tl) vcc_ErrWhere(tl, tl->t); return; } - Fb(tl, 0, "0);\n"); + Fb(tl, 0, "vrt_magic_string_end);\n"); break; default: vsb_printf(tl->sb, @@ -372,7 +372,25 @@ parse_panic(struct tokenlist *tl) do Fb(tl, 0, ", "); while (vcc_StringVal(tl)); - Fb(tl, 0, " 0);\n"); + Fb(tl, 0, " vrt_magic_string_end);\n"); +} + +/*--------------------------------------------------------------------*/ + +static void +parse_synthetic(struct tokenlist *tl) +{ + vcc_NextToken(tl); + + Fb(tl, 1, "VRT_synth_page(sp, 0, "); + if (!vcc_StringVal(tl)) { + vcc_ExpectedStringval(tl); + return; + } + do + Fb(tl, 0, ", "); + while (vcc_StringVal(tl)); + Fb(tl, 0, " vrt_magic_string_end);\n"); } /*--------------------------------------------------------------------*/ @@ -398,6 +416,7 @@ static struct action_table { { "purge_url", parse_purge_url }, { "remove", parse_unset }, /* backward compatibility */ { "set", parse_set }, + { "synthetic", parse_synthetic }, { "unset", parse_unset }, { NULL, NULL } }; diff --git a/varnish-cache/lib/libvcl/vcc_fixed_token.c b/varnish-cache/lib/libvcl/vcc_fixed_token.c index 52c289fd..89a5cb04 100644 --- a/varnish-cache/lib/libvcl/vcc_fixed_token.c +++ b/varnish-cache/lib/libvcl/vcc_fixed_token.c @@ -326,6 +326,8 @@ vcl_output_lang_h(struct vsb *sb) vsb_cat(sb, " * A backend probe specification\n"); vsb_cat(sb, " */\n"); vsb_cat(sb, "\n"); + vsb_cat(sb, "extern void *vrt_magic_string_end;\n"); + vsb_cat(sb, "\n"); vsb_cat(sb, "struct vrt_backend_probe {\n"); vsb_cat(sb, " char *request;\n"); vsb_cat(sb, " double timeout;\n"); @@ -432,6 +434,9 @@ vcl_output_lang_h(struct vsb *sb) vsb_cat(sb, "void VRT_ESI(struct sess *sp);\n"); vsb_cat(sb, "void VRT_Rollback(struct sess *sp);\n"); vsb_cat(sb, "\n"); + vsb_cat(sb, "/* Synthetic pages */\n"); + vsb_cat(sb, "void VRT_synth_page(struct sess *sp, unsigned flags, const char *, ...);\n"); + vsb_cat(sb, "\n"); vsb_cat(sb, "/* Backend related */\n"); vsb_cat(sb, "void VRT_init_dir_simple(struct cli *, struct director **, const struct vrt_dir_simple *);\n"); vsb_cat(sb, "void VRT_init_dir_random(struct cli *, struct director **, const struct vrt_dir_random *);\n"); diff --git a/varnish-cache/lib/libvcl/vcc_token.c b/varnish-cache/lib/libvcl/vcc_token.c index 5e20e965..e9ac739c 100644 --- a/varnish-cache/lib/libvcl/vcc_token.c +++ b/varnish-cache/lib/libvcl/vcc_token.c @@ -371,6 +371,29 @@ vcc_Lexer(struct tokenlist *tl, struct source *sp) return; } + /* Recognize long-strings */ + if (*p == '{' && p[1] == '"') { + for (q = p + 2; q < sp->e; q++) { + if (*q == '"' && q[1] == '}') { + vcc_AddToken(tl, CSTR, p, q + 2); + p = q + 2; + break; + } + } + u = tl->t->e - tl->t->b; + u -= 4; /* {" ... "} */ + tl->t->dec = TlAlloc(tl, u + 1 ); + AN(tl->t->dec); + memcpy(tl->t->dec, tl->t->b + 2, u); + tl->t->dec[u] = '\0'; + if (q < sp->e) + continue; + vcc_AddToken(tl, EOI, p, p + 2); + vsb_printf(tl->sb, + "Unterminated long-string, starting at\n"); + vcc_ErrWhere(tl, tl->t); + return; + } /* Match for the fixed tokens (see token.tcl) */ u = vcl_fixed_token(p, &q); -- 2.39.5