Commit f2fb353a authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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 {"
		    <HTML>
		    <H1>Sorry, could not contact the backend server</H1>
		    <P>
			Try again later.
		    </P>
		    <HR>
		    <PRE>
			URL: "}  req.url {"
			User Agnet: "} req.http.user-agent {"
		    </PRE>
		    </HTML>
		"};
	    }
	}

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: http://www.varnish-cache.org/svn/trunk/varnish-cache@3026 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent d45b49f4
...@@ -461,6 +461,7 @@ void Fetch_Init(void); ...@@ -461,6 +461,7 @@ void Fetch_Init(void);
/* cache_hash.c */ /* cache_hash.c */
void HSH_Prealloc(struct sess *sp); void HSH_Prealloc(struct sess *sp);
void HSH_Freestore(struct object *o);
int HSH_Compare(const struct sess *sp, const struct objhead *o); int HSH_Compare(const struct sess *sp, const struct objhead *o);
void HSH_Copy(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); struct object *HSH_Lookup(struct sess *sp);
...@@ -612,6 +613,10 @@ unsigned WS_Free(const struct ws *ws); ...@@ -612,6 +613,10 @@ unsigned WS_Free(const struct ws *ws);
/* rfc2616.c */ /* rfc2616.c */
int RFC2616_cache_policy(const struct sess *sp, const struct http *hp); 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 pthread_mutex_t
#define MTX_INIT(foo) AZ(pthread_mutex_init(foo, NULL)) #define MTX_INIT(foo) AZ(pthread_mutex_init(foo, NULL))
#define MTX_DESTROY(foo) AZ(pthread_mutex_destroy(foo)) #define MTX_DESTROY(foo) AZ(pthread_mutex_destroy(foo))
......
...@@ -116,7 +116,7 @@ HSH_Prealloc(struct sess *sp) ...@@ -116,7 +116,7 @@ HSH_Prealloc(struct sess *sp)
CHECK_OBJ_NOTNULL(w->nobj, OBJECT_MAGIC); CHECK_OBJ_NOTNULL(w->nobj, OBJECT_MAGIC);
} }
static void void
HSH_Freestore(struct object *o) HSH_Freestore(struct object *o)
{ {
struct storage *st, *stn; struct storage *st, *stn;
......
...@@ -51,6 +51,9 @@ ...@@ -51,6 +51,9 @@
#include "vcl.h" #include "vcl.h"
#include "cache.h" #include "cache.h"
void *vrt_magic_string_end = &vrt_magic_string_end;
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
void void
...@@ -136,7 +139,9 @@ vrt_assemble_string(struct http *hp, const char *h, const char *p, va_list ap) ...@@ -136,7 +139,9 @@ vrt_assemble_string(struct http *hp, const char *h, const char *p, va_list ap)
if (b + 1 < e) if (b + 1 < e)
*b++ = ' '; *b++ = ' ';
} }
while (p != NULL) { while (p != vrt_magic_string_end) {
if (p == NULL)
p = "(null)";
x = strlen(p); x = strlen(p);
if (b + x < e) if (b + x < e)
memcpy(b, p, x); memcpy(b, p, x);
...@@ -644,6 +649,38 @@ VRT_panic(struct sess *sp, const char *str, ...) ...@@ -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 void
VRT_purge(const char *regexp, int hash) VRT_purge(const char *regexp, int hash)
{ {
......
...@@ -105,6 +105,12 @@ MAC_STAT(sma_nbytes, uint64_t, 'i', "SMA outstanding bytes") ...@@ -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_balloc, uint64_t, 'i', "SMA bytes allocated")
MAC_STAT(sma_bfree, uint64_t, 'i', "SMA bytes free") 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(backend_req, uint64_t, 'a', "Backend requests made")
MAC_STAT(n_vcl, uint64_t, 'a', "N vcl total") MAC_STAT(n_vcl, uint64_t, 'a', "N vcl total")
......
...@@ -45,6 +45,8 @@ struct sockaddr; ...@@ -45,6 +45,8 @@ struct sockaddr;
* A backend probe specification * A backend probe specification
*/ */
extern void *vrt_magic_string_end;
struct vrt_backend_probe { struct vrt_backend_probe {
char *request; char *request;
double timeout; double timeout;
...@@ -151,6 +153,9 @@ int VRT_strcmp(const char *s1, const char *s2); ...@@ -151,6 +153,9 @@ int VRT_strcmp(const char *s1, const char *s2);
void VRT_ESI(struct sess *sp); void VRT_ESI(struct sess *sp);
void VRT_Rollback(struct sess *sp); void VRT_Rollback(struct sess *sp);
/* Synthetic pages */
void VRT_synth_page(struct sess *sp, unsigned flags, const char *, ...);
/* Backend related */ /* Backend related */
void VRT_init_dir_simple(struct cli *, struct director **, const struct vrt_dir_simple *); 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 *); void VRT_init_dir_random(struct cli *, struct director **, const struct vrt_dir_random *);
......
...@@ -269,7 +269,7 @@ parse_set(struct tokenlist *tl) ...@@ -269,7 +269,7 @@ parse_set(struct tokenlist *tl)
vcc_ErrWhere(tl, tl->t); vcc_ErrWhere(tl, tl->t);
return; return;
} }
Fb(tl, 0, "0);\n"); Fb(tl, 0, "vrt_magic_string_end);\n");
break; break;
default: default:
vsb_printf(tl->sb, vsb_printf(tl->sb,
...@@ -372,7 +372,25 @@ parse_panic(struct tokenlist *tl) ...@@ -372,7 +372,25 @@ parse_panic(struct tokenlist *tl)
do do
Fb(tl, 0, ", "); Fb(tl, 0, ", ");
while (vcc_StringVal(tl)); 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 { ...@@ -398,6 +416,7 @@ static struct action_table {
{ "purge_url", parse_purge_url }, { "purge_url", parse_purge_url },
{ "remove", parse_unset }, /* backward compatibility */ { "remove", parse_unset }, /* backward compatibility */
{ "set", parse_set }, { "set", parse_set },
{ "synthetic", parse_synthetic },
{ "unset", parse_unset }, { "unset", parse_unset },
{ NULL, NULL } { NULL, NULL }
}; };
......
...@@ -326,6 +326,8 @@ vcl_output_lang_h(struct vsb *sb) ...@@ -326,6 +326,8 @@ vcl_output_lang_h(struct vsb *sb)
vsb_cat(sb, " * A backend probe specification\n"); vsb_cat(sb, " * A backend probe specification\n");
vsb_cat(sb, " */\n"); vsb_cat(sb, " */\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, "struct vrt_backend_probe {\n");
vsb_cat(sb, " char *request;\n"); vsb_cat(sb, " char *request;\n");
vsb_cat(sb, " double timeout;\n"); vsb_cat(sb, " double timeout;\n");
...@@ -432,6 +434,9 @@ vcl_output_lang_h(struct vsb *sb) ...@@ -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_ESI(struct sess *sp);\n");
vsb_cat(sb, "void VRT_Rollback(struct sess *sp);\n"); vsb_cat(sb, "void VRT_Rollback(struct sess *sp);\n");
vsb_cat(sb, "\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, "/* 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_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"); vsb_cat(sb, "void VRT_init_dir_random(struct cli *, struct director **, const struct vrt_dir_random *);\n");
......
...@@ -371,6 +371,29 @@ vcc_Lexer(struct tokenlist *tl, struct source *sp) ...@@ -371,6 +371,29 @@ vcc_Lexer(struct tokenlist *tl, struct source *sp)
return; 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) */ /* Match for the fixed tokens (see token.tcl) */
u = vcl_fixed_token(p, &q); u = vcl_fixed_token(p, &q);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment