]> err.no Git - varnish/commitdiff
Add a facility to constructing a synthetic object from VCL.
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Fri, 25 Jul 2008 16:33:04 +0000 (16:33 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Fri, 25 Jul 2008 16:33:04 +0000 (16:33 +0000)
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: svn+ssh://projects.linpro.no/svn/varnish/trunk@3026 d4fa192b-c00b-0410-8231-f00ffab90ce4

varnish-cache/bin/varnishd/cache.h
varnish-cache/bin/varnishd/cache_hash.c
varnish-cache/bin/varnishd/cache_vrt.c
varnish-cache/include/stat_field.h
varnish-cache/include/vrt.h
varnish-cache/lib/libvcl/vcc_action.c
varnish-cache/lib/libvcl/vcc_fixed_token.c
varnish-cache/lib/libvcl/vcc_token.c

index 43429e1b7617da5426474e36a1c1c220541813b3..aa09f6b2fec6098b37c934bbf394f505f7343466 100644 (file)
@@ -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))
index cfd03e0c0c39ccc8ba5d42d19f6fb5b6dfa49307..6eba5876eaf18ead58462f33a3114e0ebe801e35 100644 (file)
@@ -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;
index 2bc01609f0b62fdccc798dc303b6fbab6065cf7c..cf5919a5b2db9a521a15269a437d4213e0d69992 100644 (file)
@@ -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)
 {
index 217d23055b0ec9779e0ba165420bed0acde47968..8cc050f2370dc8ab3abde5c3231cd1ab8612c6de 100644 (file)
@@ -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")
index 756c73bb0ccabe9029822e58e8d221f1a8969ecf..d9b77cc13bfa30ef3c7002597197d508f49cef47 100644 (file)
@@ -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 *);
index 2b02502f3c3835ea18bdf55fdaca3285d0800df8..05dcdddb212b454ead6d8110161f34161daecbc0 100644 (file)
@@ -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 }
 };
index 52c289fdd3004e6c3015cc09863beb50807ef3b3..89a5cb04de2a23207f660476ecae4ee0876dd909 100644 (file)
@@ -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");
index 5e20e965846aa99c9a30c485afc31bf1e1b4a868..e9ac739cc362b34f66d0742694b138d822c97227 100644 (file)
@@ -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);