r3026 - in trunk/varnish-cache: bin/varnishd include lib/libvcl

phk at projects.linpro.no phk at projects.linpro.no
Fri Jul 25 18:33:05 CEST 2008


Author: phk
Date: 2008-07-25 18:33:04 +0200 (Fri, 25 Jul 2008)
New Revision: 3026

Modified:
   trunk/varnish-cache/bin/varnishd/cache.h
   trunk/varnish-cache/bin/varnishd/cache_hash.c
   trunk/varnish-cache/bin/varnishd/cache_vrt.c
   trunk/varnish-cache/include/stat_field.h
   trunk/varnish-cache/include/vrt.h
   trunk/varnish-cache/lib/libvcl/vcc_action.c
   trunk/varnish-cache/lib/libvcl/vcc_fixed_token.c
   trunk/varnish-cache/lib/libvcl/vcc_token.c
Log:
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.


Modified: trunk/varnish-cache/bin/varnishd/cache.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache.h	2008-07-25 15:27:04 UTC (rev 3025)
+++ trunk/varnish-cache/bin/varnishd/cache.h	2008-07-25 16:33:04 UTC (rev 3026)
@@ -461,6 +461,7 @@
 
 /* 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 @@
 /* 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))

Modified: trunk/varnish-cache/bin/varnishd/cache_hash.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_hash.c	2008-07-25 15:27:04 UTC (rev 3025)
+++ trunk/varnish-cache/bin/varnishd/cache_hash.c	2008-07-25 16:33:04 UTC (rev 3026)
@@ -116,7 +116,7 @@
 		CHECK_OBJ_NOTNULL(w->nobj, OBJECT_MAGIC);
 }
 
-static void
+void
 HSH_Freestore(struct object *o)
 {
 	struct storage *st, *stn;

Modified: trunk/varnish-cache/bin/varnishd/cache_vrt.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_vrt.c	2008-07-25 15:27:04 UTC (rev 3025)
+++ trunk/varnish-cache/bin/varnishd/cache_vrt.c	2008-07-25 16:33:04 UTC (rev 3026)
@@ -51,6 +51,9 @@
 #include "vcl.h"
 #include "cache.h"
 
+
+void *vrt_magic_string_end = &vrt_magic_string_end;
+
 /*--------------------------------------------------------------------*/
 
 void
@@ -136,7 +139,9 @@
 		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,7 +649,39 @@
 
 /*--------------------------------------------------------------------*/
 
+/*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)
 {
 	

Modified: trunk/varnish-cache/include/stat_field.h
===================================================================
--- trunk/varnish-cache/include/stat_field.h	2008-07-25 15:27:04 UTC (rev 3025)
+++ trunk/varnish-cache/include/stat_field.h	2008-07-25 16:33:04 UTC (rev 3026)
@@ -105,6 +105,12 @@
 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")

Modified: trunk/varnish-cache/include/vrt.h
===================================================================
--- trunk/varnish-cache/include/vrt.h	2008-07-25 15:27:04 UTC (rev 3025)
+++ trunk/varnish-cache/include/vrt.h	2008-07-25 16:33:04 UTC (rev 3026)
@@ -45,6 +45,8 @@
  * A backend probe specification
  */
 
+extern void *vrt_magic_string_end;
+
 struct vrt_backend_probe {
 	char		*request;
 	double		timeout;
@@ -151,6 +153,9 @@
 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 *);

Modified: trunk/varnish-cache/lib/libvcl/vcc_action.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_action.c	2008-07-25 15:27:04 UTC (rev 3025)
+++ trunk/varnish-cache/lib/libvcl/vcc_action.c	2008-07-25 16:33:04 UTC (rev 3026)
@@ -269,7 +269,7 @@
 			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,11 +372,29 @@
 	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");
+}
+
+/*--------------------------------------------------------------------*/
+
 typedef void action_f(struct tokenlist *tl);
 
 static struct action_table {
@@ -398,6 +416,7 @@
 	{ "purge_url",		parse_purge_url },
 	{ "remove", 		parse_unset }, /* backward compatibility */
 	{ "set", 		parse_set },
+	{ "synthetic", 		parse_synthetic },
 	{ "unset", 		parse_unset },
 	{ NULL,			NULL }
 };

Modified: trunk/varnish-cache/lib/libvcl/vcc_fixed_token.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_fixed_token.c	2008-07-25 15:27:04 UTC (rev 3025)
+++ trunk/varnish-cache/lib/libvcl/vcc_fixed_token.c	2008-07-25 16:33:04 UTC (rev 3026)
@@ -326,6 +326,8 @@
 	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 @@
 	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");

Modified: trunk/varnish-cache/lib/libvcl/vcc_token.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_token.c	2008-07-25 15:27:04 UTC (rev 3025)
+++ trunk/varnish-cache/lib/libvcl/vcc_token.c	2008-07-25 16:33:04 UTC (rev 3026)
@@ -371,6 +371,29 @@
 			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);




More information about the varnish-commit mailing list