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);
/* 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))
......
......@@ -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;
......
......@@ -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)
{
......
......@@ -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")
......
......@@ -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 *);
......
......@@ -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 }
};
......
......@@ -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");
......
......@@ -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);
......
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