From phk at FreeBSD.org Fri Dec 1 22:34:09 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Fri, 1 Dec 2017 22:34:09 +0000 (UTC) Subject: [master] 2cc40be Make sure nobody else wastes time on this Message-ID: <20171201223409.61959928CE@lists.varnish-cache.org> commit 2cc40bea6e7058d2e598e7547026686d43e9ba39 Author: Poul-Henning Kamp Date: Fri Dec 1 20:49:28 2017 +0000 Make sure nobody else wastes time on this diff --git a/lib/libvcc/generate.py b/lib/libvcc/generate.py index 3b4972b..f1cb87f 100755 --- a/lib/libvcc/generate.py +++ b/lib/libvcc/generate.py @@ -52,6 +52,9 @@ buildroot = "../.." if len(sys.argv) == 3: srcroot = sys.argv[1] buildroot = sys.argv[2] +elif len(sys.argv) != 1: + print("Two arguments or none") + exit(2) tokens = { "T_INC": "++", From phk at FreeBSD.org Fri Dec 1 22:34:09 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Fri, 1 Dec 2017 22:34:09 +0000 (UTC) Subject: [master] c91a6ce Canonize VMOD argument ENUM values to replace strcmp(3) or more involved versions of same with a simple pointer comparison. Message-ID: <20171201223409.862DB928D1@lists.varnish-cache.org> commit c91a6cedf2dfffc84344554a206fc75f57ee6177 Author: Poul-Henning Kamp Date: Fri Dec 1 22:32:51 2017 +0000 Canonize VMOD argument ENUM values to replace strcmp(3) or more involved versions of same with a simple pointer comparison. diff --git a/bin/varnishd/mgt/mgt_main.c b/bin/varnishd/mgt/mgt_main.c index f460f5e..cf9c454 100644 --- a/bin/varnishd/mgt/mgt_main.c +++ b/bin/varnishd/mgt/mgt_main.c @@ -66,7 +66,7 @@ int exit_status = 0; struct vsb *vident; struct VSC_mgt *VSC_C_mgt; static int I_fd = -1; -static char *Cn_arg; +static char *Cn_arg; static struct vpf_fh *pfh1 = NULL; static struct vpf_fh *pfh2 = NULL; diff --git a/bin/varnishtest/tests/m00000.vtc b/bin/varnishtest/tests/m00000.vtc index 6200b80..1690a78 100644 --- a/bin/varnishtest/tests/m00000.vtc +++ b/bin/varnishtest/tests/m00000.vtc @@ -22,7 +22,8 @@ varnish v1 -vcl+backend { sub vcl_deliver { set resp.http.foo = std.toupper(resp.http.foo); set resp.http.bar = std.tolower(resp.http.bar); - set resp.http.who = debug.author(phk); + set resp.http.who = debug.author(mithrandir); + set resp.http.really = debug.author(); set resp.http.what = vtc.typesize("dfijlopsz"); set resp.http.not = vtc.typesize("*"); debug.test_priv_call(); @@ -42,6 +43,8 @@ client c1 { expect resp.bodylen == "4" expect resp.http.foo == "BAR" expect resp.http.bar == "foo" + expect resp.http.who == "Tollef" + expect resp.http.really == "Poul-Henning" expect resp.http.encrypted == "ROT52" expect resp.http.what >= 16 expect resp.http.not == -1 @@ -53,7 +56,8 @@ logexpect l1 -v v1 -g raw -d 1 { expect 0 = RespHeader {^foo: BAR} expect 0 = RespUnset {^bar: fOo} expect 0 = RespHeader {^bar: foo} - expect 0 = RespHeader {^who: Poul-Henning} + expect 0 = RespHeader {^who: Tollef} + expect 0 = RespHeader {^really: Poul-Henning} expect 0 = RespHeader {^what: [1-9][0-9]} expect 0 = RespHeader {^not: -1} expect 0 = VCL_Log {^VCL initiated log} diff --git a/flint.lnt b/flint.lnt index 5f57bef..4727891 100644 --- a/flint.lnt +++ b/flint.lnt @@ -81,6 +81,13 @@ /////////////////////////////////////////////////////////////////////// +// Vmod/vmodtool.py + +-esym(14, vmod_enum_*) // Symbol '___' previously defined (___) +-esym(759, vmod_enum_*) // header declaration for symbol '___' defined at (___) +-esym(765, vmod_enum_*) // external '___' (___) could be made static + +/////////////////////////////////////////////////////////////////////// // -sem(VAS_Fail, r_no) // does not return diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c index a36932f..10854f5 100644 --- a/lib/libvcc/vcc_expr.c +++ b/lib/libvcc/vcc_expr.c @@ -528,6 +528,7 @@ vcc_priv_arg(struct vcc *tl, const char *p, const char *name, const char *vmod) struct func_arg { vcc_type_t type; const char *enum_bits; + const char *cname; const char *name; const char *val; struct expr *result; @@ -535,6 +536,18 @@ struct func_arg { }; static void +vcc_do_enum(struct vcc *tl, struct func_arg *fa, int len, const char *ptr) +{ + const char *r; + + (void)tl; + r = strchr(fa->cname, '.'); + AN(r); + fa->result = vcc_mk_expr(VOID, "*%.*s.enum_%.*s", + (int)(r - fa->cname), fa->cname, len, ptr); +} + +static void vcc_do_arg(struct vcc *tl, struct func_arg *fa) { const char *p, *r; @@ -559,7 +572,7 @@ vcc_do_arg(struct vcc *tl, struct func_arg *fa) vcc_ErrWhere(tl, tl->t); return; } - fa->result = vcc_mk_expr(VOID, "\"%.*s\"", PF(tl->t)); + vcc_do_enum(tl, fa, PF(tl->t)); SkipToken(tl, ID); } else { vcc_expr0(tl, &e2, fa->type); @@ -610,6 +623,7 @@ vcc_func(struct vcc *tl, struct expr **e, const char *spec, while (*p != '\0') { fa = calloc(1, sizeof *fa); AN(fa); + fa->cname = cfunc; VTAILQ_INSERT_TAIL(&head, fa, list); if (!memcmp(p, "PRIV_", 5)) { fa->result = vcc_priv_arg(tl, p, sym->name, sym->vmod); @@ -685,6 +699,8 @@ vcc_func(struct vcc *tl, struct expr **e, const char *spec, e1 = vcc_mk_expr(rfmt, "%s(ctx%s\v+", cfunc, extra); VTAILQ_FOREACH_SAFE(fa, &head, list, fa2) { + if (fa->result == NULL && fa->type == ENUM && fa->val != NULL) + vcc_do_enum(tl, fa, strlen(fa->val), fa->val); if (fa->result == NULL && fa->val != NULL) fa->result = vcc_mk_expr(fa->type, "%s", fa->val); if (fa->result != NULL) diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py index d271a2c..50bfea3 100755 --- a/lib/libvcc/vmodtool.py +++ b/lib/libvcc/vmodtool.py @@ -86,6 +86,7 @@ CLEANFILES = $(builddir)/vcc_if.c $(builddir)/vcc_if.h \\ \t$(builddir)/vmod_XXX.man.rst ''' + privs = { 'PRIV_CALL': "struct vmod_priv *", 'PRIV_VCL': "struct vmod_priv *", @@ -196,6 +197,9 @@ def fmt_cstruct(fo, mn, x): ####################################################################### +enum_values = {} + + class ctype(object): def __init__(self, vt, ct): self.vt = vt @@ -259,7 +263,9 @@ def vtype(txt): e = e[0].split(',') ct.spec = [] for i in e: - ct.spec.append(i.strip()) + j = i.strip() + enum_values[j] = True + ct.spec.append(j) return ct, r @@ -289,6 +295,8 @@ def arg(txt): if not m: err("Unbalanced quote") a.defval = s[:m.end()] + if a.vt == "ENUM": + a.defval = a.defval[1:-1] s = s[m.end():] else: i = s.find(',') @@ -296,6 +304,8 @@ def arg(txt): i = len(s) a.defval = s[:i].rstrip() s = s[i:] + if a.vt == "ENUM" and a.defval not in a.spec: + err("ENUM default value <%s> not valid" % a.defval, warn=False) return a, s @@ -701,13 +711,13 @@ class s_method(stanza): ####################################################################### dispatch = { - "Module": s_module, - "Prefix": s_prefix, - "ABI": s_abi, - "Event": s_event, - "Function": s_function, - "Object": s_object, - "Method": s_method, + "Module": s_module, + "Prefix": s_prefix, + "ABI": s_abi, + "Event": s_event, + "Function": s_function, + "Object": s_object, + "Method": s_method, } @@ -782,11 +792,20 @@ class vcc(object): fn = self.pfx + ".h" fo = self.openfile(fn) write_c_file_warning(fo) + fo.write("#ifndef VDEF_H_INCLUDED\n") + fo.write('# error "Include vdef.h first"\n') + fo.write("#endif\n") fo.write("#ifndef VRT_H_INCLUDED\n") fo.write('# error "Include vrt.h first"\n') fo.write("#endif\n") fo.write("\n") + l = enum_values.keys() + l.sort() + for j in l: + fo.write("extern VCL_ENUM %senum_%s;\n" % (self.sympfx, j)) + fo.write("\n") + for j in self.contents: j.hfile(fo) fo.close() @@ -796,12 +815,22 @@ class vcc(object): fo.write("\n%s {\n" % csn) for j in self.contents: j.cstruct(fo) + fo.write("\n") + l = enum_values.keys() + l.sort() + for j in l: + fo.write("\tVCL_ENUM\t\t\t*enum_%s;\n" % j) fo.write("};\n") def cstruct_init(self, fo, csn): fo.write("\nstatic const %s Vmod_Func = {\n" % csn) for j in self.contents: j.cstruct_init(fo) + fo.write("\n") + l = enum_values.keys() + l.sort() + for j in l: + fo.write("\t&%senum_%s,\n" % (self.sympfx, j)) fo.write("};\n") def specstr(self, fo): @@ -857,6 +886,12 @@ class vcc(object): fo.write("\n") + l = enum_values.keys() + l.sort() + for j in l: + fo.write('VCL_ENUM %senum_%s = "%s";\n' % (self.sympfx, j, j)) + fo.write("\n") + fx = open(fn2, "w") for i in self.contents: diff --git a/lib/libvmod_debug/flint.lnt b/lib/libvmod_debug/flint.lnt index e69de29..36d2255 100644 --- a/lib/libvmod_debug/flint.lnt +++ b/lib/libvmod_debug/flint.lnt @@ -0,0 +1,3 @@ +-esym(759, xyzzy_enum_*) // header declaration for symbol '___' defined at (___) +-esym(765, xyzzy_enum_*) // external '___' (___) could be made static + diff --git a/lib/libvmod_debug/vmod.vcc b/lib/libvmod_debug/vmod.vcc index bb12df3..5933d52 100644 --- a/lib/libvmod_debug/vmod.vcc +++ b/lib/libvmod_debug/vmod.vcc @@ -45,7 +45,7 @@ $Function VOID panic(STRING_LIST) Don't. $Function STRING author(ENUM { phk, des, kristian, mithrandir } person="phk", - ENUM { phk, slink, geoff } someone="phk") + ENUM { phk, slink, geoff } someone='phk') Test function for ENUM arguments @@ -73,7 +73,7 @@ $Function STEVEDORE no_stevedore() Fails at storage selection. -$Object obj(STRING string="default", ENUM { one, two, three } number="one") +$Object obj(STRING string="default", ENUM { one, two, three } number=one) Test object diff --git a/lib/libvmod_debug/vmod_debug.c b/lib/libvmod_debug/vmod_debug.c index f094fc9..c24d78a 100644 --- a/lib/libvmod_debug/vmod_debug.c +++ b/lib/libvmod_debug/vmod_debug.c @@ -88,14 +88,18 @@ xyzzy_author(VRT_CTX, VCL_ENUM person, VCL_ENUM someone) (void)someone; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); - if (!strcmp(person, "phk")) + if (person == xyzzy_enum_phk) return ("Poul-Henning"); - if (!strcmp(person, "des")) + assert(strcmp(person, "phk")); + if (person == xyzzy_enum_des) return ("Dag-Erling"); - if (!strcmp(person, "kristian")) + assert(strcmp(person, "des")); + if (person == xyzzy_enum_kristian) return ("Kristian"); - if (!strcmp(person, "mithrandir")) + assert(strcmp(person, "kristian")); + if (person == xyzzy_enum_mithrandir) return ("Tollef"); + assert(strcmp(person, "mithrandir")); WRONG("Illegal VMOD enum"); } From phk at FreeBSD.org Fri Dec 1 23:02:06 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Fri, 1 Dec 2017 23:02:06 +0000 (UTC) Subject: [master] b6ce6d6 Vastly simplify the parse_encoding() and parse_case() functions now that VCL_ENUM have canonical pointers. Message-ID: <20171201230206.35FCE944FD@lists.varnish-cache.org> commit b6ce6d6770541bdf14383086691f1721efc49a6d Author: Poul-Henning Kamp Date: Fri Dec 1 23:01:07 2017 +0000 Vastly simplify the parse_encoding() and parse_case() functions now that VCL_ENUM have canonical pointers. diff --git a/lib/libvmod_blob/Makefile.am b/lib/libvmod_blob/Makefile.am index 7b5ce59..888895a 100644 --- a/lib/libvmod_blob/Makefile.am +++ b/lib/libvmod_blob/Makefile.am @@ -10,9 +10,7 @@ libvmod_blob_la_SOURCES = \ hex.c \ url.c \ wb.h \ - wb.c \ - parse_encoding.h \ - parse_encoding.c + wb.c base64.o: base64.c base64.h diff --git a/lib/libvmod_blob/parse_encoding.c b/lib/libvmod_blob/parse_encoding.c deleted file mode 100644 index 2f7a538..0000000 --- a/lib/libvmod_blob/parse_encoding.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * for the time being, this code is auto-generated outside the varnishd source - * tree, see - * https://code.uplex.de/uplex-varnish/libvmod-blobcode/blob/master/src/gen_enum_parse.pl - * - * TODO: integrate in vmodtool.py or replace with something else - * cf. the same TODO for the shard director in libvmod_directors - * make generation of the offset-pointer p optional - */ - -#include "parse_encoding.h" -#define term(c) ((c) == '\0') - -enum encoding -parse_encoding (const char *m) { - enum encoding r; - - switch (m[0]) { - case 'B': goto _0B; // BASE64, BASE64URL, BASE64URLNOPAD - case 'H': goto _0H; // HEX - case 'I': goto _0I; // IDENTITY - case 'U': goto _0U; // URL - default: goto invalid; - } - _0B: - switch (m[1]) { - case 'A': goto _1BA; // BASE64, BASE64URL, BASE64URLNOPAD - default: goto invalid; - } - _1BA: - switch (m[2]) { - case 'S': goto _2BAS; // BASE64, BASE64URL, BASE64URLNOPAD - default: goto invalid; - } - _2BAS: - switch (m[3]) { - case 'E': goto _3BASE; // BASE64, BASE64URL, BASE64URLNOPAD - default: goto invalid; - } - _3BASE: - switch (m[4]) { - case '6': goto _4BASE6; // BASE64, BASE64URL, BASE64URLNOPAD - default: goto invalid; - } - _4BASE6: - switch (m[5]) { - case '4': goto _5BASE64; // BASE64, BASE64URL, BASE64URLNOPAD - default: goto invalid; - } - _5BASE64: - //BASE64 - if (term(m[6])) { - r = BASE64; - goto ok; - } - switch (m[6]) { - case 'U': goto _6BASE64U; // BASE64URL, BASE64URLNOPAD - default: goto invalid; - } - _6BASE64U: - switch (m[7]) { - case 'R': goto _7BASE64UR; // BASE64URL, BASE64URLNOPAD - default: goto invalid; - } - _7BASE64UR: - switch (m[8]) { - case 'L': goto _8BASE64URL; // BASE64URL, BASE64URLNOPAD - default: goto invalid; - } - _8BASE64URL: - //BASE64URL - if (term(m[9])) { - r = BASE64URL; - goto ok; - } - switch (m[9]) { - case 'N': goto _9BASE64URLN; // BASE64URLNOPAD - default: goto invalid; - } - _9BASE64URLN: - //BASE64URLNOPAD - if ((m[10] == 'O') && (m[11] == 'P') && (m[12] == 'A') && (m[13] == 'D') && (term(m[14]))) { - r = BASE64URLNOPAD; - goto ok; - } - goto invalid; - _0H: - //HEX - if ((m[1] == 'E') && (m[2] == 'X') && (term(m[3]))) { - r = HEX; - goto ok; - } - goto invalid; - _0I: - //IDENTITY - if ((m[1] == 'D') && (m[2] == 'E') && (m[3] == 'N') && (m[4] == 'T') && (m[5] == 'I') && (m[6] == 'T') && (m[7] == 'Y') && (term(m[8]))) { - r = IDENTITY; - goto ok; - } - goto invalid; - _0U: - //URL - if ((m[1] == 'R') && (m[2] == 'L') && (term(m[3]))) { - r = URL; - goto ok; - } - goto invalid; - ok: - return r; - invalid: - return _INVALID; -} diff --git a/lib/libvmod_blob/parse_encoding.h b/lib/libvmod_blob/parse_encoding.h deleted file mode 100644 index 472ebf8..0000000 --- a/lib/libvmod_blob/parse_encoding.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * for the time being, this code is auto-generated outside the varnishd source - * tree, see - * https://code.uplex.de/uplex-varnish/libvmod-blobcode/blob/master/src/gen_enum_parse.pl - * - * TODO: integrate in vmodtool.py or replace with something else - * cf. the same TODO for the shard director in libvmod_directors - */ - -enum encoding { - _INVALID = 0, - IDENTITY, - BASE64, - BASE64URL, - BASE64URLNOPAD, - HEX, - URL, - __MAX_ENCODING -}; - -enum encoding parse_encoding (const char *); - diff --git a/lib/libvmod_blob/vmod_blob.c b/lib/libvmod_blob/vmod_blob.c index 927af20..72ec60f 100644 --- a/lib/libvmod_blob/vmod_blob.c +++ b/lib/libvmod_blob/vmod_blob.c @@ -55,13 +55,6 @@ static const struct vmod_blob_fptr { len_f *const encode_l; encode_f *const encode; } func[__MAX_ENCODING] = { - [_INVALID] = { - /* make implicit null init explicit for clarity */ - .decode_l = NULL, - .decode = NULL, - .encode_l = NULL, - .encode = NULL - }, [IDENTITY] = { .decode_l = id_decode_l, .decode = id_decode, @@ -123,6 +116,19 @@ static const struct vmod_priv null_blob[1] = } }; +#include +static enum encoding +parse_encoding(VCL_ENUM e) +{ + if (e == vmod_enum_BASE64) return(BASE64); + if (e == vmod_enum_BASE64URL) return(BASE64URL); + if (e == vmod_enum_BASE64URLNOPAD) return(BASE64URLNOPAD); + if (e == vmod_enum_HEX) return(HEX); + if (e == vmod_enum_IDENTITY) return(IDENTITY); + if (e == vmod_enum_URL) return(URL); + WRONG("illegal encoding enum"); +} + static inline size_t decode_l_va(enum encoding dec, const char * const p, va_list ap) { @@ -156,19 +162,10 @@ err_decode(VRT_CTX, const char *enc) static inline enum case_e parse_case(VCL_ENUM case_s) { - switch (*case_s) { - case 'D': - AZ(strcmp(case_s + 1, "EFAULT")); - return DEFAULT; - case 'L': - AZ(strcmp(case_s + 1, "OWER")); - return LOWER; - case 'U': - AZ(strcmp(case_s + 1, "PPER")); - return UPPER; - default: - WRONG("illegal case enum"); - } + if (case_s == vmod_enum_DEFAULT) return(DEFAULT); + if (case_s == vmod_enum_LOWER) return(LOWER); + if (case_s == vmod_enum_UPPER) return(UPPER); + WRONG("illegal case enum"); } static inline int diff --git a/lib/libvmod_blob/vmod_blob.h b/lib/libvmod_blob/vmod_blob.h index 04663e5..ba359c1 100644 --- a/lib/libvmod_blob/vmod_blob.h +++ b/lib/libvmod_blob/vmod_blob.h @@ -30,9 +30,17 @@ #include #include -#include "parse_encoding.h" +enum encoding { + IDENTITY = 1, + BASE64, + BASE64URL, + BASE64URLNOPAD, + HEX, + URL, + __MAX_ENCODING +}; -#define AENC(enc) assert((enc) > _INVALID && (enc) < __MAX_ENCODING) +#define AENC(enc) assert((enc) >= IDENTITY && (enc) < __MAX_ENCODING) /* * The enums MUST appear in this order, since LOWER and UPPER are used to From daghf at varnish-software.com Mon Dec 4 10:10:13 2017 From: daghf at varnish-software.com (Dag Haavi Finstad) Date: Mon, 4 Dec 2017 10:10:13 +0000 (UTC) Subject: [master] b9f7170 Avoid premature H/2 session close Message-ID: <20171204101013.241019496D@lists.varnish-cache.org> commit b9f7170b035ccdefc071b009c2c1062c13c5b1e8 Author: Dag Haavi Finstad Date: Tue Nov 28 16:46:01 2017 +0100 Avoid premature H/2 session close Timing out an H/2 session needs to take into account any active streams being processed. diff --git a/bin/varnishd/http2/cache_http2_proto.c b/bin/varnishd/http2/cache_http2_proto.c index a43bc5c..5dd01c1 100644 --- a/bin/varnishd/http2/cache_http2_proto.c +++ b/bin/varnishd/http2/cache_http2_proto.c @@ -881,16 +881,40 @@ h2_rxframe(struct worker *wrk, struct h2_sess *h2) enum htc_status_e hs; h2_frame h2f; h2_error h2e; + int again; + struct h2_req *r2, *r22; char b[8]; ASSERT_RXTHR(h2); (void)VTCP_blocking(*h2->htc->rfd); - h2->sess->t_idle = VTIM_real(); - hs = HTC_RxStuff(h2->htc, h2_frame_complete, - NULL, NULL, NAN, - h2->sess->t_idle + cache_param->timeout_idle, - 16384 + 9); // rfc7540,l,4228,4228 - if (hs != HTC_S_COMPLETE) { + while (1) { + h2->sess->t_idle = VTIM_real(); + hs = HTC_RxStuff(h2->htc, h2_frame_complete, + NULL, NULL, NAN, + h2->sess->t_idle + cache_param->timeout_idle, + 16384 + 9); // rfc7540,l,4228,4228 + if (hs == HTC_S_COMPLETE) + break; + else if (hs == HTC_S_TIMEOUT) { + again = 0; + VTAILQ_FOREACH_SAFE(r2, &h2->streams, list, r22) { + switch (r2->state) { + case H2_S_CLOSED: + if (!r2->scheduled) + h2_del_req(wrk, r2); + break; + case H2_S_OPEN: + case H2_S_CLOS_REM: + case H2_S_CLOS_LOC: + again = 1; + break; + default: + break; + } + } + if (again) + continue; + } Lck_Lock(&h2->sess->mtx); VSLb(h2->vsl, SLT_Debug, "H2: No frame (hs=%d)", hs); h2->error = H2CE_NO_ERROR; From phk at FreeBSD.org Tue Dec 5 22:34:11 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Tue, 5 Dec 2017 22:34:11 +0000 (UTC) Subject: [master] f7860ad Simplify VCC's handling of procedures. Message-ID: <20171205223411.1880D94302@lists.varnish-cache.org> commit f7860ad011378b60c8168726dec4462da668832f Author: Poul-Henning Kamp Date: Tue Dec 5 22:31:30 2017 +0000 Simplify VCC's handling of procedures. Give procedures proper data structures and stick the VCL methods into the symbol table up front and GC a lot of small hacks and workarounds. diff --git a/lib/libvcc/vcc_compile.c b/lib/libvcc/vcc_compile.c index e07ee9b..53fc9b9 100644 --- a/lib/libvcc/vcc_compile.c +++ b/lib/libvcc/vcc_compile.c @@ -62,7 +62,7 @@ #include "libvcc.h" #include "vfil.h" -struct method method_tab[] = { +static const struct method method_tab[] = { { "none", 0U, 0}, #define VCL_MET_MAC(l,U,t,b) { "vcl_"#l, b, VCL_MET_##U }, #include "tbl/vcl_returns.h" @@ -95,6 +95,24 @@ TlDup(struct vcc *tl, const char *s) /*--------------------------------------------------------------------*/ +struct proc * +vcc_NewProc(struct vcc *tl, struct symbol *sym) +{ + struct proc *p; + + ALLOC_OBJ(p, PROC_MAGIC); + AN(p); + VTAILQ_INIT(&p->calls); + VTAILQ_INIT(&p->uses); + VTAILQ_INSERT_TAIL(&tl->procs, p, list); + p->body = VSB_new_auto(); + AN(p->body); + sym->proc = p; + return (p); +} + +/*--------------------------------------------------------------------*/ + struct inifin * New_IniFin(struct vcc *tl) { @@ -111,25 +129,6 @@ New_IniFin(struct vcc *tl) return (p); } -/*--------------------------------------------------------------------*/ - -int -IsMethod(const struct token *t) -{ - int i; - - assert(t->tok == ID); - for (i = 1; method_tab[i].name != NULL; i++) { - if (vcc_IdIs(t, method_tab[i].name)) - return (i); - } - if ((t->b[0] == 'v'|| t->b[0] == 'V') && - (t->b[1] == 'c'|| t->b[1] == 'C') && - (t->b[2] == 'l'|| t->b[2] == 'L')) - return (-2); - return (-1); -} - /*-------------------------------------------------------------------- * Printf output to the vsbs, possibly indented */ @@ -535,10 +534,10 @@ static struct vsb * vcc_CompileSource(struct vcc *tl, struct source *sp) { struct symbol *sym; + struct proc *p; const struct var *v; struct vsb *vsb; struct inifin *ifp; - int i; vcc_Expr_Init(tl); @@ -626,26 +625,19 @@ vcc_CompileSource(struct vcc *tl, struct source *sp) /* Emit method functions */ Fh(tl, 1, "\n"); - for (i = 1; i < VCL_MET_MAX; i++) { + VTAILQ_FOREACH(p, &tl->procs, list) { + if (p->method == NULL) + continue; Fh(tl, 1, "void v_matchproto_(vcl_func_f) " "VGC_function_%s(VRT_CTX);\n", - method_tab[i].name); + p->method->name); Fc(tl, 1, "\nvoid v_matchproto_(vcl_func_f)\n"); - Fc(tl, 1, - "VGC_function_%s(VRT_CTX)\n", - method_tab[i].name); - AZ(VSB_finish(tl->fm[i])); - Fc(tl, 1, "{\n"); - /* - * We want vmods to be able set a FAIL return value - * in members called from vcl_init, so set OK up front - * and return with whatever was set last. - */ - Fc(tl, 1, "%s", VSB_data(tl->fm[i])); - if (method_tab[i].bitval == VCL_MET_INIT) - Fc(tl, 1, " return;\n"); - Fc(tl, 1, "}\n"); + Fc(tl, 1, "VGC_function_%s(VRT_CTX)\n", + p->method->name); + AZ(VSB_finish(p->body)); + Fc(tl, 1, "{\n%s}\n", VSB_data(p->body)); + VSB_destroy(&p->body); } EmitInitFini(tl); @@ -710,6 +702,8 @@ struct vcc * VCC_New(void) { struct vcc *tl; + struct symbol *sym; + struct proc *p; int i; ALLOC_OBJ(tl, VCC_MAGIC); @@ -717,6 +711,7 @@ VCC_New(void) VTAILQ_INIT(&tl->inifin); VTAILQ_INIT(&tl->tokens); VTAILQ_INIT(&tl->sources); + VTAILQ_INIT(&tl->procs); tl->nsources = 0; @@ -729,9 +724,11 @@ VCC_New(void) tl->fh = VSB_new_auto(); assert(tl->fh != NULL); - for (i = 0; i < VCL_MET_MAX; i++) { - tl->fm[i] = VSB_new_auto(); - assert(tl->fm[i] != NULL); + for (i = 1; i < VCL_MET_MAX; i++) { + sym = VCC_Symbol(tl, NULL, + method_tab[i].name, NULL, SYM_SUB, 1); + p = vcc_NewProc(tl, sym); + p->method = &method_tab[i]; } tl->sb = VSB_new_auto(); AN(tl->sb); diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h index 47e3033..7f09b47 100644 --- a/lib/libvcc/vcc_compile.h +++ b/lib/libvcc/vcc_compile.h @@ -49,6 +49,7 @@ struct vsb; struct token; struct sockaddr_storage; +struct method; unsigned vcl_fixed_token(const char *p, const char **q); extern const char * const vcl_tnames[256]; @@ -146,6 +147,21 @@ struct symbol { VTAILQ_HEAD(tokenhead, token); +struct proc { + unsigned magic; +#define PROC_MAGIC 0xd1d98499 + const struct method *method; + VTAILQ_HEAD(,proccall) calls; + VTAILQ_HEAD(,procuse) uses; + VTAILQ_ENTRY(proc) list; + struct token *name; + unsigned ret_bitmap; + unsigned called; + unsigned active; + struct token *return_tok[VCL_RET_MAX]; + struct vsb *body; +}; + struct inifin { unsigned magic; #define INIFIN_MAGIC 0x583c274c @@ -191,11 +207,10 @@ struct vcc { struct vsb *fb; /* Body of current sub * NULL otherwise */ - struct vsb *fm[VCL_MET_MAX]; /* Method bodies */ struct vsb *sb; int err; struct proc *curproc; - struct proc *mprocs[VCL_MET_MAX]; + VTAILQ_HEAD(, proc) procs; VTAILQ_HEAD(, acl_e) acl; @@ -244,8 +259,8 @@ void vcc_IsField(struct vcc *tl, struct token **t, struct fld_spec *fs); void vcc_FieldsOk(struct vcc *tl, const struct fld_spec *fs); /* vcc_compile.c */ -extern struct method method_tab[]; -struct inifin *New_IniFin(struct vcc *tl); +struct inifin *New_IniFin(struct vcc *); +struct proc *vcc_NewProc(struct vcc*, struct symbol*); /* * H -> Header, before the C code @@ -261,7 +276,6 @@ void Fc(const struct vcc *tl, int indent, const char *fmt, ...) void Fb(const struct vcc *tl, int indent, const char *fmt, ...) v_printflike_(3, 4); void EncToken(struct vsb *sb, const struct token *t); -int IsMethod(const struct token *t); void *TlAlloc(struct vcc *tl, unsigned len); char *TlDup(struct vcc *tl, const char *s); @@ -346,7 +360,6 @@ int vcc_CheckReferences(struct vcc *tl); void VCC_XrefTable(struct vcc *); void vcc_AddCall(struct vcc *tl, struct token *t); -struct proc *vcc_AddProc(struct vcc *tl, struct token *t); void vcc_ProcAction(struct proc *p, unsigned action, struct token *t); int vcc_CheckAction(struct vcc *tl); void vcc_AddUses(struct vcc *tl, const struct token *t, unsigned mask, diff --git a/lib/libvcc/vcc_parse.c b/lib/libvcc/vcc_parse.c index 2466431..13615cd 100644 --- a/lib/libvcc/vcc_parse.c +++ b/lib/libvcc/vcc_parse.c @@ -209,48 +209,58 @@ static void vcc_ParseFunction(struct vcc *tl) { struct symbol *sym; - int m, i; + struct proc *p; vcc_NextToken(tl); vcc_ExpectVid(tl, "function"); ERRCHK(tl); - m = IsMethod(tl->t); - if (m == -2) { - VSB_printf(tl->sb, - "VCL sub's named 'vcl*' are reserved names.\n"); + sym = vcc_AddDef(tl, tl->t, SYM_SUB); + AN(sym); + p = sym->proc; + if (p == NULL) { + if ((tl->t->b[0] == 'v'|| tl->t->b[0] == 'V') && + (tl->t->b[1] == 'c'|| tl->t->b[1] == 'C') && + (tl->t->b[2] == 'l'|| tl->t->b[2] == 'L')) { + VSB_printf(tl->sb, + "VCL sub's named 'vcl*' are reserved names.\n"); + vcc_ErrWhere(tl, tl->t); + VSB_printf(tl->sb, "Valid vcl_* methods are:\n"); + VTAILQ_FOREACH(p, &tl->procs, list) { + if (p->method != NULL) + VSB_printf(tl->sb, "\t%s\n", + p->method->name); + } + return; + } + VCC_GlobalSymbol(sym, SUB, "VGC_function"); + p = vcc_NewProc(tl, sym); + p->name = tl->t; + tl->fb = tl->fc; + Fh(tl, 0, "void %s(VRT_CTX);\n", sym->rname); + Fc(tl, 1, "\nvoid v_matchproto_(vcl_func_t)\n"); + Fc(tl, 1, "%s(VRT_CTX)\n", sym->rname); + } else if (p->method == NULL) { + VSB_printf(tl->sb, "Function '%s' redefined\n", sym->name); vcc_ErrWhere(tl, tl->t); - VSB_printf(tl->sb, "Valid vcl_* methods are:\n"); - for (i = 1; method_tab[i].name != NULL; i++) - VSB_printf(tl->sb, "\t%s\n", method_tab[i].name); + VSB_printf(tl->sb, "Previously defined here:\n"); + vcc_ErrWhere(tl, p->name); return; - } else if (m != -1) { - assert(m < VCL_MET_MAX); - tl->fb = tl->fm[m]; - if (tl->mprocs[m] == NULL) { + } else { + /* Add to VCL sub */ + AN(p->method); + if (p->name == NULL) { (void)vcc_AddDef(tl, tl->t, SYM_SUB); (void)vcc_AddRef(tl, tl->t, SYM_SUB); - tl->mprocs[m] = vcc_AddProc(tl, tl->t); + p->name = tl->t; } - tl->curproc = tl->mprocs[m]; + tl->fb = p->body; Fb(tl, 1, " /* ... from "); vcc_Coord(tl, tl->fb, NULL); Fb(tl, 0, " */\n"); - } else { - tl->fb = tl->fc; - sym = vcc_AddDef(tl, tl->t, SYM_SUB); - VCC_GlobalSymbol(sym, SUB, "VGC_function"); - if (sym->ndef > 1) { - VSB_printf(tl->sb, - "Function '%s' redefined\n", sym->name); - vcc_ErrWhere(tl, tl->t); - return; - } - tl->curproc = vcc_AddProc(tl, tl->t); - Fh(tl, 0, "void %s(VRT_CTX);\n", sym->rname); - Fc(tl, 1, "\nvoid v_matchproto_(vcl_func_t)\n"); - Fc(tl, 1, "%s(VRT_CTX)\n", sym->rname); } + CHECK_OBJ_NOTNULL(p, PROC_MAGIC); + tl->curproc = p; vcc_NextToken(tl); tl->indent += INDENT; Fb(tl, 1, "{\n"); diff --git a/lib/libvcc/vcc_xref.c b/lib/libvcc/vcc_xref.c index 267c949..fff066c 100644 --- a/lib/libvcc/vcc_xref.c +++ b/lib/libvcc/vcc_xref.c @@ -45,7 +45,7 @@ struct proccall { VTAILQ_ENTRY(proccall) list; - struct proc *p; + struct symbol *sym; struct token *t; }; @@ -56,17 +56,6 @@ struct procuse { const char *use; }; -struct proc { - VTAILQ_HEAD(,proccall) calls; - VTAILQ_HEAD(,procuse) uses; - struct token *name; - unsigned ret_bitmap; - unsigned exists; - unsigned called; - unsigned active; - struct token *return_tok[VCL_RET_MAX]; -}; - /*-------------------------------------------------------------------- * Keep track of definitions and references */ @@ -132,38 +121,6 @@ vcc_CheckReferences(struct vcc *tl) * Returns checks */ -static struct proc * -vcc_findproc(struct vcc *tl, struct token *t) -{ - struct symbol *sym; - struct proc *p; - - - sym = VCC_SymbolTok(tl, NULL, t, SYM_SUB, 1); - AN(sym); - if (sym->proc != NULL) - return (sym->proc); - - p = TlAlloc(tl, sizeof *p); - assert(p != NULL); - VTAILQ_INIT(&p->calls); - VTAILQ_INIT(&p->uses); - p->name = t; - sym->proc = p; - return (p); -} - -struct proc * -vcc_AddProc(struct vcc *tl, struct token *t) -{ - struct proc *p; - - p = vcc_findproc(tl, t); - p->name = t; /* make sure the name matches the definition */ - p->exists++; - return (p); -} - void vcc_AddUses(struct vcc *tl, const struct token *t, unsigned mask, const char *use) @@ -184,12 +141,11 @@ void vcc_AddCall(struct vcc *tl, struct token *t) { struct proccall *pc; - struct proc *p; - p = vcc_findproc(tl, t); pc = TlAlloc(tl, sizeof *pc); assert(pc != NULL); - pc->p = p; + pc->sym = VCC_SymbolTok(tl, NULL, t, SYM_SUB, 1); + AN(pc->sym); pc->t = t; VTAILQ_INSERT_TAIL(&tl->curproc->calls, pc, list); } @@ -211,11 +167,7 @@ vcc_CheckActionRecurse(struct vcc *tl, struct proc *p, unsigned bitmap) unsigned u; struct proccall *pc; - if (!p->exists) { - VSB_printf(tl->sb, "Function %.*s does not exist\n", - PF(p->name)); - return (1); - } + AN(p); if (p->active) { VSB_printf(tl->sb, "Function recurses on\n"); vcc_ErrWhere(tl, p->name); @@ -238,9 +190,15 @@ vcc_CheckActionRecurse(struct vcc *tl, struct proc *p, unsigned bitmap) } p->active = 1; VTAILQ_FOREACH(pc, &p->calls, list) { - if (vcc_CheckActionRecurse(tl, pc->p, bitmap)) { - VSB_printf(tl->sb, "\n...called from \"%.*s\"\n", - PF(p->name)); + if (pc->sym->proc == NULL) { + VSB_printf(tl->sb, "Function %s does not exist\n", + pc->sym->name); + vcc_ErrWhere(tl, pc->t); + return (1); + } + if (vcc_CheckActionRecurse(tl, pc->sym->proc, bitmap)) { + VSB_printf(tl->sb, "\n...called from \"%s\"\n", + pc->sym->name); vcc_ErrWhere(tl, pc->t); return (1); } @@ -256,21 +214,18 @@ static void vcc_checkaction1(struct vcc *tl, const struct symbol *sym) { struct proc *p; - struct method *m; - int i; p = sym->proc; AN(p); - i = IsMethod(p->name); - if (i < 0) + AN(p->name); + if(p->method == NULL) return; - m = method_tab + i; - if (vcc_CheckActionRecurse(tl, p, m->ret_bitmap)) { + if (vcc_CheckActionRecurse(tl, p, p->method->ret_bitmap)) { VSB_printf(tl->sb, - "\n...which is the \"%s\" method\n", m->name); + "\n...which is the \"%s\" method\n", p->method->name); VSB_printf(tl->sb, "Legal returns are:"); #define VCL_RET_MAC(l, U, B) \ - if (m->ret_bitmap & ((1 << VCL_RET_##U))) \ + if (p->method->ret_bitmap & ((1 << VCL_RET_##U))) \ VSB_printf(tl->sb, " \"%s\"", #l); #include "tbl/vcl_returns.h" @@ -324,7 +279,7 @@ vcc_FindIllegalUse(const struct proc *p, const struct method *m) static int vcc_CheckUseRecurse(struct vcc *tl, const struct proc *p, - struct method *m) + const struct method *m) { struct proccall *pc; struct procuse *pu; @@ -341,9 +296,9 @@ vcc_CheckUseRecurse(struct vcc *tl, const struct proc *p, return (1); } VTAILQ_FOREACH(pc, &p->calls, list) { - if (vcc_CheckUseRecurse(tl, pc->p, m)) { - VSB_printf(tl->sb, "\n...called from \"%.*s\"\n", - PF(p->name)); + if (vcc_CheckUseRecurse(tl, pc->sym->proc, m)) { + VSB_printf(tl->sb, "\n...called from \"%s\"\n", + pc->sym->name); vcc_ErrWhere(tl, pc->t); return (1); } @@ -355,29 +310,23 @@ static void vcc_checkuses(struct vcc *tl, const struct symbol *sym) { struct proc *p; - struct method *m; struct procuse *pu; - int i; p = sym->proc; AN(p); - - i = IsMethod(p->name); - if (i < 0) + if (p->method == NULL) return; - m = method_tab + i; - pu = vcc_FindIllegalUse(p, m); + pu = vcc_FindIllegalUse(p, p->method); if (pu != NULL) { - VSB_printf(tl->sb, - "'%.*s': %s in method '%.*s'.", + VSB_printf(tl->sb, "'%.*s': %s in method '%.*s'.", PF(pu->t), pu->use, PF(p->name)); VSB_cat(tl->sb, "\nAt: "); vcc_ErrWhere(tl, pu->t); return; } - if (vcc_CheckUseRecurse(tl, p, m)) { + if (vcc_CheckUseRecurse(tl, p, p->method)) { VSB_printf(tl->sb, - "\n...which is the \"%s\" method\n", m->name); + "\n...which is the \"%s\" method\n", p->method->name); return; } } From phk at FreeBSD.org Wed Dec 6 13:06:12 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Wed, 6 Dec 2017 13:06:12 +0000 (UTC) Subject: [master] 4e1699f Unify handling of emitted functions. Message-ID: <20171206130612.1714E94EC1@lists.varnish-cache.org> commit 4e1699f6b0046d358c0d60d733a2b9479634d5d3 Author: Poul-Henning Kamp Date: Wed Dec 6 13:04:49 2017 +0000 Unify handling of emitted functions. diff --git a/lib/libvcc/vcc_action.c b/lib/libvcc/vcc_action.c index 2c9b046..69adcec 100644 --- a/lib/libvcc/vcc_action.c +++ b/lib/libvcc/vcc_action.c @@ -286,8 +286,8 @@ parse_return(struct vcc *tl) const char *h; vcc_NextToken(tl); - if (tl->t->tok == ';' && tl->fb == tl->fc) { - /* fb == fc means we're in a subroutine */ + AN(tl->curproc); + if (tl->t->tok == ';' && tl->curproc->method == NULL) { Fb(tl, 1, "return;\n"); return; } diff --git a/lib/libvcc/vcc_compile.c b/lib/libvcc/vcc_compile.c index 53fc9b9..e46c09e 100644 --- a/lib/libvcc/vcc_compile.c +++ b/lib/libvcc/vcc_compile.c @@ -107,10 +107,25 @@ vcc_NewProc(struct vcc *tl, struct symbol *sym) VTAILQ_INSERT_TAIL(&tl->procs, p, list); p->body = VSB_new_auto(); AN(p->body); + p->cname = VSB_new_auto(); + AN(p->cname); sym->proc = p; return (p); } +static void +vcc_EmitProc(struct vcc *tl, struct proc *p) +{ + AZ(VSB_finish(p->cname)); + AZ(VSB_finish(p->body)); + Fh(tl, 1, "vcl_func_f %s;\n", VSB_data(p->cname)); + Fc(tl, 1, "\nvoid v_matchproto_(vcl_func_f)\n"); + Fc(tl, 1, "%s(VRT_CTX)\n", VSB_data(p->cname)); + Fc(tl, 1, "{\n%s}\n", VSB_data(p->body)); + VSB_destroy(&p->body); + VSB_destroy(&p->cname); +} + /*--------------------------------------------------------------------*/ struct inifin * @@ -625,20 +640,12 @@ vcc_CompileSource(struct vcc *tl, struct source *sp) /* Emit method functions */ Fh(tl, 1, "\n"); - VTAILQ_FOREACH(p, &tl->procs, list) { + VTAILQ_FOREACH(p, &tl->procs, list) if (p->method == NULL) - continue; - Fh(tl, 1, - "void v_matchproto_(vcl_func_f) " - "VGC_function_%s(VRT_CTX);\n", - p->method->name); - Fc(tl, 1, "\nvoid v_matchproto_(vcl_func_f)\n"); - Fc(tl, 1, "VGC_function_%s(VRT_CTX)\n", - p->method->name); - AZ(VSB_finish(p->body)); - Fc(tl, 1, "{\n%s}\n", VSB_data(p->body)); - VSB_destroy(&p->body); - } + vcc_EmitProc(tl, p); + VTAILQ_FOREACH(p, &tl->procs, list) + if (p->method != NULL) + vcc_EmitProc(tl, p); EmitInitFini(tl); @@ -729,6 +736,7 @@ VCC_New(void) method_tab[i].name, NULL, SYM_SUB, 1); p = vcc_NewProc(tl, sym); p->method = &method_tab[i]; + VSB_printf(p->cname, "VGC_function_%s", p->method->name); } tl->sb = VSB_new_auto(); AN(tl->sb); diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h index 7f09b47..074e66c 100644 --- a/lib/libvcc/vcc_compile.h +++ b/lib/libvcc/vcc_compile.h @@ -159,6 +159,7 @@ struct proc { unsigned called; unsigned active; struct token *return_tok[VCL_RET_MAX]; + struct vsb *cname; struct vsb *body; }; diff --git a/lib/libvcc/vcc_parse.c b/lib/libvcc/vcc_parse.c index 13615cd..94e6279 100644 --- a/lib/libvcc/vcc_parse.c +++ b/lib/libvcc/vcc_parse.c @@ -236,10 +236,7 @@ vcc_ParseFunction(struct vcc *tl) VCC_GlobalSymbol(sym, SUB, "VGC_function"); p = vcc_NewProc(tl, sym); p->name = tl->t; - tl->fb = tl->fc; - Fh(tl, 0, "void %s(VRT_CTX);\n", sym->rname); - Fc(tl, 1, "\nvoid v_matchproto_(vcl_func_t)\n"); - Fc(tl, 1, "%s(VRT_CTX)\n", sym->rname); + VSB_printf(p->cname, "%s", sym->rname); } else if (p->method == NULL) { VSB_printf(tl->sb, "Function '%s' redefined\n", sym->name); vcc_ErrWhere(tl, tl->t); @@ -254,12 +251,12 @@ vcc_ParseFunction(struct vcc *tl) (void)vcc_AddRef(tl, tl->t, SYM_SUB); p->name = tl->t; } - tl->fb = p->body; - Fb(tl, 1, " /* ... from "); - vcc_Coord(tl, tl->fb, NULL); - Fb(tl, 0, " */\n"); } CHECK_OBJ_NOTNULL(p, PROC_MAGIC); + tl->fb = p->body; + Fb(tl, 1, " /* ... from "); + vcc_Coord(tl, p->body, NULL); + Fb(tl, 0, " */\n"); tl->curproc = p; vcc_NextToken(tl); tl->indent += INDENT; From phk at FreeBSD.org Thu Dec 7 10:36:07 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Thu, 7 Dec 2017 10:36:07 +0000 (UTC) Subject: [master] 32124b2 Clarify probe documentation. Message-ID: <20171207103607.D060B94E4B@lists.varnish-cache.org> commit 32124b299059fb8f8786e4703cf1de4cc2f61f04 Author: Poul-Henning Kamp Date: Thu Dec 7 10:34:38 2017 +0000 Clarify probe documentation. Fixes #2510 Submitted by: klean at github diff --git a/doc/sphinx/reference/vcl.rst b/doc/sphinx/reference/vcl.rst index e826779..a0f94db 100644 --- a/doc/sphinx/reference/vcl.rst +++ b/doc/sphinx/reference/vcl.rst @@ -270,11 +270,12 @@ There are no mandatory options. These are the options you can set: ``.url`` The URL to query. Defaults to ``/``. + Mutually exclusive with ``.request`` ``.request`` Specify a full HTTP request using multiple strings. ``.request`` will - have ``\r\n`` automatically inserted after every string. If - specified, ``.request`` will take precedence over ``.url``. + have ``\r\n`` automatically inserted after every string. + Mutually exclusive with ``.url``. ``.expected_response`` The expected HTTP response code. Defaults to ``200``. @@ -296,8 +297,9 @@ There are no mandatory options. These are the options you can set: Defaults to ``8``. ``.threshold`` - How many of the polls in .window must have succeeded for us to - consider the backend healthy. Defaults to ``3``. + How many of the polls in ``.window`` must have succeeded to + for the backend to be healthy. + Defaults to ``3``. Access Control List (ACL) From phk at FreeBSD.org Fri Dec 8 22:15:12 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Fri, 8 Dec 2017 22:15:12 +0000 (UTC) Subject: [master] 9c00768 Straighten out STRING_LIST expressions a bit and always translate STRING_LIST to STRING for error messages. Message-ID: <20171208221512.7472494841@lists.varnish-cache.org> commit 9c007687f9a60d80e53ca798dbe6dc452316034b Author: Poul-Henning Kamp Date: Fri Dec 8 22:13:29 2017 +0000 Straighten out STRING_LIST expressions a bit and always translate STRING_LIST to STRING for error messages. diff --git a/bin/varnishtest/tests/v00018.vtc b/bin/varnishtest/tests/v00018.vtc index 3e84fb0..186f7cb 100644 --- a/bin/varnishtest/tests/v00018.vtc +++ b/bin/varnishtest/tests/v00018.vtc @@ -38,7 +38,7 @@ varnish v1 -errvcl {Expected ';' got 'if'} { sub vcl_recv { set req.url = "foo" if "bar"; } } -varnish v1 -errvcl {Symbol not found: 'req.foo' (expected type STRING_LIST):} { +varnish v1 -errvcl {Symbol not found: 'req.foo' (expected type STRING):} { backend b { .host = "127.0.0.1"; } sub vcl_hash { hash_data(req.foo); } } @@ -98,7 +98,7 @@ varnish v1 -errvcl {Expected an action, 'if', '{' or '}'} { sub vcl_recv { kluf ; } } -varnish v1 -errvcl {Unknown token '<<' when looking for STRING_LIST} { +varnish v1 -errvcl {Unknown token '<<' when looking for STRING} { backend b { .host = "127.0.0.1"; } sub vcl_synth { synthetic( << "foo"; } } diff --git a/bin/varnishtest/tests/v00020.vtc b/bin/varnishtest/tests/v00020.vtc index 3688987..c720531 100644 --- a/bin/varnishtest/tests/v00020.vtc +++ b/bin/varnishtest/tests/v00020.vtc @@ -31,7 +31,7 @@ varnish v1 -errvcl {Comparison of different types: INT '!=' STRING} { } } -varnish v1 -errvcl {Symbol not found: 'vcl_recv' (expected type STRING_LIST)} { +varnish v1 -errvcl {Symbol not found: 'vcl_recv' (expected type STRING)} { sub vcl_recv { set req.http.foo = vcl_recv; } diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c index 10854f5..efc84de 100644 --- a/lib/libvcc/vcc_expr.c +++ b/lib/libvcc/vcc_expr.c @@ -38,6 +38,18 @@ #include "vcc_compile.h" +struct expr { + unsigned magic; +#define EXPR_MAGIC 0x38c794ab + vcc_type_t fmt; + struct vsb *vsb; + uint8_t constant; +#define EXPR_VAR (1<<0) +#define EXPR_CONST (1<<1) +#define EXPR_STR_CONST (1<<2) // Last STRING_LIST elem is "..." + struct token *t1, *t2; +}; + /*-------------------------------------------------------------------- * Recognize and convert units of time, return seconds. */ @@ -197,18 +209,6 @@ vcc_ByteVal(struct vcc *tl, double *d) * them. */ -struct expr { - unsigned magic; -#define EXPR_MAGIC 0x38c794ab - vcc_type_t fmt; - struct vsb *vsb; - uint8_t constant; -#define EXPR_VAR (1<<0) -#define EXPR_CONST (1<<1) -#define EXPR_STR_CONST (1<<2) - struct token *t1, *t2; -}; - static inline int vcc_isconst(const struct expr *e) { @@ -216,6 +216,14 @@ vcc_isconst(const struct expr *e) return (e->constant & EXPR_CONST); } +static const char * +vcc_utype(vcc_type_t t) +{ + if (t == STRING_LIST) + return (STRING->name); + return (t->name); +} + static void vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt); static struct expr * @@ -394,7 +402,7 @@ vcc_expr_tostring(struct vcc *tl, struct expr **e, vcc_type_t fmt) } if (p == NULL) { VSB_printf(tl->sb, - "Cannot convert %s to STRING.\n", (*e)->fmt->name); + "Cannot convert %s to STRING.\n", vcc_utype((*e)->fmt)); vcc_ErrWhere2(tl, (*e)->t1, tl->t); return; } @@ -579,10 +587,9 @@ vcc_do_arg(struct vcc *tl, struct func_arg *fa) ERRCHK(tl); if (e2->fmt != fa->type) { VSB_printf(tl->sb, "Wrong argument type."); - VSB_printf(tl->sb, " Expected %s.", - fa->type->name); - VSB_printf(tl->sb, " Got %s.\n", - e2->fmt->name); + VSB_printf(tl->sb, + " Expected %s.", vcc_utype(fa->type)); + VSB_printf(tl->sb, " Got %s.\n", vcc_utype(e2->fmt)); vcc_ErrWhere2(tl, e2->t1, tl->t); return; } @@ -779,7 +786,10 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt) vcc_expr0(tl, &e2, fmt); ERRCHK(tl); SkipToken(tl, ')'); - *e = vcc_expr_edit(e2->fmt, "(\v1)", e2, NULL); + if (fmt == STRING_LIST && e2->fmt == STRING_LIST) + *e = e2; // (...) not needed or wanted. + else + *e = vcc_expr_edit(e2->fmt, "(\v1)", e2, NULL); return; } switch (tl->t->tok) { @@ -798,7 +808,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt) VSB_printf(tl->sb, "Symbol not found: "); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " (expected type %s):\n", - fmt->name); + vcc_utype(fmt)); vcc_ErrWhere(tl, tl->t); return; } @@ -847,9 +857,12 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt) EncToken(e1->vsb, tl->t); e1->fmt = STRING; AZ(VSB_finish(e1->vsb)); + e1->constant |= EXPR_STR_CONST; + if (fmt == STRING_LIST) + e1->fmt = fmt; } e1->t1 = tl->t; - e1->constant = EXPR_CONST; + e1->constant |= EXPR_CONST; vcc_NextToken(tl); *e = e1; return; @@ -892,7 +905,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt) } VSB_printf(tl->sb, "Unknown token "); vcc_ErrToken(tl, tl->t); - VSB_printf(tl->sb, " when looking for %s\n\n", fmt->name); + VSB_printf(tl->sb, " when looking for %s\n\n", vcc_utype(fmt)); vcc_ErrWhere(tl, tl->t); } @@ -920,7 +933,7 @@ vcc_expr_mul(struct vcc *tl, struct expr **e, vcc_type_t fmt) if (tl->t->tok != '*' && tl->t->tok != '/') return; VSB_printf(tl->sb, "Operator %.*s not possible on type %s.\n", - PF(tl->t), f3->name); + PF(tl->t), vcc_utype(f3)); vcc_ErrWhere(tl, tl->t); return; } @@ -933,7 +946,7 @@ vcc_expr_mul(struct vcc *tl, struct expr **e, vcc_type_t fmt) if (e2->fmt != REAL && e2->fmt != INT) { VSB_printf(tl->sb, "%s %.*s %s not possible.\n", - f2->name, PF(tk), e2->fmt->name); + vcc_utype(f2), PF(tk), vcc_utype(e2->fmt)); vcc_ErrWhere(tl, tk); return; } @@ -968,7 +981,7 @@ vcc_expr_string_add(struct vcc *tl, struct expr **e, struct expr *e2) while (e2 != NULL || tl->t->tok == '+') { if (e2 == NULL) { vcc_NextToken(tl); - vcc_expr_mul(tl, &e2, STRING); + vcc_expr_mul(tl, &e2, f2); } ERRCHK(tl); if (e2->fmt != STRING && e2->fmt != STRING_LIST) @@ -976,20 +989,9 @@ vcc_expr_string_add(struct vcc *tl, struct expr **e, struct expr *e2) ERRCHK(tl); assert(e2->fmt == STRING || e2->fmt == STRING_LIST); - if (vcc_isconst(*e) && vcc_isconst(e2)) { - assert((*e)->fmt == STRING); - assert(e2->fmt == STRING); - *e = vcc_expr_edit(STRING, "\v1\n\v2", *e, e2); - (*e)->constant = EXPR_CONST; - } else if (((*e)->constant & EXPR_STR_CONST) && - vcc_isconst(e2)) { - assert((*e)->fmt == STRING_LIST); - assert(e2->fmt == STRING); - *e = vcc_expr_edit(STRING_LIST, "\v1\n\v2", *e, e2); - (*e)->constant = EXPR_VAR | EXPR_STR_CONST; - } else if (e2->fmt == STRING && vcc_isconst(e2)) { - *e = vcc_expr_edit(STRING_LIST, "\v1,\n\v2", *e, e2); - (*e)->constant = EXPR_VAR | EXPR_STR_CONST; + if (((*e)->constant & EXPR_STR_CONST) && vcc_isconst(e2)) { + *e = vcc_expr_edit((*e)->fmt, "\v1\n\v2", *e, e2); + (*e)->constant = EXPR_CONST | EXPR_STR_CONST; } else { *e = vcc_expr_edit(STRING_LIST, "\v1,\n\v2", *e, e2); (*e)->constant = EXPR_VAR; @@ -1085,7 +1087,7 @@ vcc_expr_add(struct vcc *tl, struct expr **e, vcc_type_t fmt) } VSB_printf(tl->sb, "%s %.*s %s not possible.\n", - (*e)->fmt->name, PF(tk), e2->fmt->name); + vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt)); vcc_ErrWhere2(tl, tk, tl->t); return; } @@ -1165,7 +1167,7 @@ vcc_expr_cmp(struct vcc *tl, struct expr **e, vcc_type_t fmt) *e = NULL; - vcc_expr_strfold(tl, e, fmt); + vcc_expr_add(tl, e, fmt); ERRCHK(tl); if ((*e)->fmt == BOOL) @@ -1186,9 +1188,9 @@ vcc_expr_cmp(struct vcc *tl, struct expr **e, vcc_type_t fmt) ERRCHK(tl); if (e2->fmt != (*e)->fmt) { /* XXX */ VSB_printf(tl->sb, "Comparison of different types: "); - VSB_printf(tl->sb, "%s ", (*e)->fmt->name); + VSB_printf(tl->sb, "%s ", vcc_utype((*e)->fmt)); vcc_ErrToken(tl, tk); - VSB_printf(tl->sb, " %s\n", e2->fmt->name); + VSB_printf(tl->sb, " %s\n", vcc_utype(e2->fmt)); vcc_ErrWhere(tl, tk); return; } @@ -1235,9 +1237,9 @@ vcc_expr_cmp(struct vcc *tl, struct expr **e, vcc_type_t fmt) ERRCHK(tl); if (e2->fmt != (*e)->fmt) { VSB_printf(tl->sb, "Comparison of different types: "); - VSB_printf(tl->sb, "%s ", (*e)->fmt->name); + VSB_printf(tl->sb, "%s ", vcc_utype((*e)->fmt)); vcc_ErrToken(tl, tk); - VSB_printf(tl->sb, " %s\n", e2->fmt->name); + VSB_printf(tl->sb, " %s\n", vcc_utype(e2->fmt)); vcc_ErrWhere(tl, tk); return; } @@ -1254,7 +1256,7 @@ vcc_expr_cmp(struct vcc *tl, struct expr **e, vcc_type_t fmt) case '~': case T_NOMATCH: VSB_printf(tl->sb, "Operator %.*s not possible on %s\n", - PF(tl->t), (*e)->fmt->name); + PF(tl->t), vcc_utype((*e)->fmt)); vcc_ErrWhere(tl, tl->t); return; default: @@ -1295,7 +1297,7 @@ vcc_expr_not(struct vcc *tl, struct expr **e, vcc_type_t fmt) return; } VSB_printf(tl->sb, "'!' must be followed by BOOL, found "); - VSB_printf(tl->sb, "%s.\n", e2->fmt->name); + VSB_printf(tl->sb, "%s.\n", vcc_utype(e2->fmt)); vcc_ErrWhere2(tl, tk, tl->t); } @@ -1325,7 +1327,7 @@ vcc_expr_cand(struct vcc *tl, struct expr **e, vcc_type_t fmt) if (e2->fmt != BOOL) { VSB_printf(tl->sb, "'&&' must be followed by BOOL," - " found %s.\n", e2->fmt->name); + " found %s.\n", vcc_utype(e2->fmt)); vcc_ErrWhere2(tl, tk, tl->t); return; } @@ -1359,7 +1361,7 @@ vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt) if (e2->fmt != BOOL) { VSB_printf(tl->sb, "'||' must be followed by BOOL," - " found %s.\n", e2->fmt->name); + " found %s.\n", vcc_utype(e2->fmt)); vcc_ErrWhere2(tl, tk, tl->t); return; } @@ -1394,7 +1396,7 @@ vcc_Expr(struct vcc *tl, vcc_type_t fmt) e->t1 = t1; if (!tl->err && fmt != e->fmt) { VSB_printf(tl->sb, "Expression has type %s, expected %s\n", - e->fmt->name, fmt->name); + vcc_utype(e->fmt), vcc_utype(fmt)); tl->err = 1; } if (!tl->err) { From nils.goroll at uplex.de Sun Dec 10 11:34:10 2017 From: nils.goroll at uplex.de (Nils Goroll) Date: Sun, 10 Dec 2017 11:34:10 +0000 (UTC) Subject: [master] 328cea2 superfluous include Message-ID: <20171210113411.077DC949E0@lists.varnish-cache.org> commit 328cea21490f33d8774383e678f089be0d209c2a Author: Nils Goroll Date: Sun Dec 10 12:29:19 2017 +0100 superfluous include diff --git a/lib/libvmod_blob/vmod_blob.c b/lib/libvmod_blob/vmod_blob.c index 72ec60f..693f994 100644 --- a/lib/libvmod_blob/vmod_blob.c +++ b/lib/libvmod_blob/vmod_blob.c @@ -116,7 +116,6 @@ static const struct vmod_priv null_blob[1] = } }; -#include static enum encoding parse_encoding(VCL_ENUM e) { From nils.goroll at uplex.de Sun Dec 10 11:45:07 2017 From: nils.goroll at uplex.de (Nils Goroll) Date: Sun, 10 Dec 2017 11:45:07 +0000 (UTC) Subject: [master] 38f712a use a table file for vmod enum to c enum Message-ID: <20171210114508.0EBA994E26@lists.varnish-cache.org> commit 38f712a62fcfa875d90c41a0f001ce3267e3069a Author: Nils Goroll Date: Sun Dec 10 12:41:36 2017 +0100 use a table file for vmod enum to c enum diff --git a/lib/libvmod_blob/Makefile.am b/lib/libvmod_blob/Makefile.am index 888895a..9be1c7d 100644 --- a/lib/libvmod_blob/Makefile.am +++ b/lib/libvmod_blob/Makefile.am @@ -10,7 +10,8 @@ libvmod_blob_la_SOURCES = \ hex.c \ url.c \ wb.h \ - wb.c + wb.c \ + tbl_encodings.h base64.o: base64.c base64.h diff --git a/lib/libvmod_blob/tbl_encodings.h b/lib/libvmod_blob/tbl_encodings.h new file mode 100644 index 0000000..2319e9c --- /dev/null +++ b/lib/libvmod_blob/tbl_encodings.h @@ -0,0 +1,7 @@ +VMODENUM(BASE64) +VMODENUM(BASE64URL) +VMODENUM(BASE64URLNOPAD) +VMODENUM(HEX) +VMODENUM(IDENTITY) +VMODENUM(URL) +#undef VMODENUM diff --git a/lib/libvmod_blob/vmod_blob.c b/lib/libvmod_blob/vmod_blob.c index 693f994..7819701 100644 --- a/lib/libvmod_blob/vmod_blob.c +++ b/lib/libvmod_blob/vmod_blob.c @@ -119,12 +119,8 @@ static const struct vmod_priv null_blob[1] = static enum encoding parse_encoding(VCL_ENUM e) { - if (e == vmod_enum_BASE64) return(BASE64); - if (e == vmod_enum_BASE64URL) return(BASE64URL); - if (e == vmod_enum_BASE64URLNOPAD) return(BASE64URLNOPAD); - if (e == vmod_enum_HEX) return(HEX); - if (e == vmod_enum_IDENTITY) return(IDENTITY); - if (e == vmod_enum_URL) return(URL); +#define VMODENUM(n) if (e == vmod_enum_ ## n) return(n); +#include "tbl_encodings.h" WRONG("illegal encoding enum"); } From nils.goroll at uplex.de Sun Dec 10 12:00:08 2017 From: nils.goroll at uplex.de (Nils Goroll) Date: Sun, 10 Dec 2017 12:00:08 +0000 (UTC) Subject: [master] 22480f2 straighten out the rest of the blob vmod enum handling Message-ID: <20171210120008.F329A94441@lists.varnish-cache.org> commit 22480f2e6013867333def4b1d7732eaa0a7a1767 Author: Nils Goroll Date: Sun Dec 10 12:55:06 2017 +0100 straighten out the rest of the blob vmod enum handling diff --git a/lib/libvmod_blob/Makefile.am b/lib/libvmod_blob/Makefile.am index 9be1c7d..2695913 100644 --- a/lib/libvmod_blob/Makefile.am +++ b/lib/libvmod_blob/Makefile.am @@ -11,7 +11,8 @@ libvmod_blob_la_SOURCES = \ url.c \ wb.h \ wb.c \ - tbl_encodings.h + tbl_encodings.h \ + tbl_case.h base64.o: base64.c base64.h diff --git a/lib/libvmod_blob/tbl_case.h b/lib/libvmod_blob/tbl_case.h new file mode 100644 index 0000000..c5b4695 --- /dev/null +++ b/lib/libvmod_blob/tbl_case.h @@ -0,0 +1,8 @@ +/* + * this order MUST be preserved, since enum case_e LOWER and UPPER are used to + * index the array of cached encodings for the blob object. + */ +VMODENUM(LOWER) +VMODENUM(UPPER) +VMODENUM(DEFAULT) +#undef VMODENUM diff --git a/lib/libvmod_blob/vmod_blob.c b/lib/libvmod_blob/vmod_blob.c index 7819701..6e5a198 100644 --- a/lib/libvmod_blob/vmod_blob.c +++ b/lib/libvmod_blob/vmod_blob.c @@ -124,6 +124,15 @@ parse_encoding(VCL_ENUM e) WRONG("illegal encoding enum"); } +static enum case_e +parse_case(VCL_ENUM e) +{ +#define VMODENUM(n) if (e == vmod_enum_ ## n) return(n); +#include "tbl_case.h" + WRONG("illegal case enum"); +} + + static inline size_t decode_l_va(enum encoding dec, const char * const p, va_list ap) { @@ -154,15 +163,6 @@ err_decode(VRT_CTX, const char *enc) } } -static inline enum case_e -parse_case(VCL_ENUM case_s) -{ - if (case_s == vmod_enum_DEFAULT) return(DEFAULT); - if (case_s == vmod_enum_LOWER) return(LOWER); - if (case_s == vmod_enum_UPPER) return(UPPER); - WRONG("illegal case enum"); -} - static inline int encodes_hex(enum encoding enc) { diff --git a/lib/libvmod_blob/vmod_blob.h b/lib/libvmod_blob/vmod_blob.h index ba359c1..e47dff8 100644 --- a/lib/libvmod_blob/vmod_blob.h +++ b/lib/libvmod_blob/vmod_blob.h @@ -31,25 +31,21 @@ #include enum encoding { - IDENTITY = 1, - BASE64, - BASE64URL, - BASE64URLNOPAD, - HEX, - URL, + _INVALID = 0, +#define VMODENUM(x) x, +#include "tbl_encodings.h" __MAX_ENCODING }; -#define AENC(enc) assert((enc) >= IDENTITY && (enc) < __MAX_ENCODING) +#define AENC(enc) assert((enc) > _INVALID && (enc) < __MAX_ENCODING) /* * The enums MUST appear in this order, since LOWER and UPPER are used to * index the array of cached encodings for the blob object. */ enum case_e { - LOWER, - UPPER, - DEFAULT, +#define VMODENUM(x) x, +#include "tbl_case.h" }; /* From nils.goroll at uplex.de Sun Dec 10 14:15:09 2017 From: nils.goroll at uplex.de (Nils Goroll) Date: Sun, 10 Dec 2017 14:15:09 +0000 (UTC) Subject: [master] 111962e some changes we missed to note for 5.2 Message-ID: <20171210141509.245239473C@lists.varnish-cache.org> commit 111962e890a4bd9f937ea962acf5c72cd4d080f7 Author: Nils Goroll Date: Sun Dec 10 15:07:28 2017 +0100 some changes we missed to note for 5.2 diff --git a/include/vrt.h b/include/vrt.h index fef0c9d..dd2bf26 100644 --- a/include/vrt.h +++ b/include/vrt.h @@ -61,6 +61,8 @@ * 6.1 (2017-09-15 aka 5.2) * http_CollectHdrSep added * VRT_purge modified (may fail a transaction, signature changed) + * VRT_r_req_hash() added + * VRT_r_bereq_hash() added * 6.0 (2017-03-15): * VRT_hit_for_pass added * VRT_ipcmp added From nils.goroll at uplex.de Sun Dec 10 14:15:09 2017 From: nils.goroll at uplex.de (Nils Goroll) Date: Sun, 10 Dec 2017 14:15:09 +0000 (UTC) Subject: [master] ddd9d4d one note too much is better than a forgotten one Message-ID: <20171210141509.3BD599473F@lists.varnish-cache.org> commit ddd9d4da43610d03fe63d5254dc11438fd9024e9 Author: Nils Goroll Date: Sun Dec 10 15:10:00 2017 +0100 one note too much is better than a forgotten one diff --git a/include/vrt.h b/include/vrt.h index dd2bf26..df9e18a 100644 --- a/include/vrt.h +++ b/include/vrt.h @@ -58,6 +58,8 @@ * VRT_VSC_Destroy() added * struct director.event added * struct director.destroy added + * VRT_r_beresp_storage_hint() removed - under discussion #2509 + * VRT_l_beresp_storage_hint() removed - under discussion #2509 * 6.1 (2017-09-15 aka 5.2) * http_CollectHdrSep added * VRT_purge modified (may fail a transaction, signature changed) From nils.goroll at uplex.de Sun Dec 10 14:15:09 2017 From: nils.goroll at uplex.de (Nils Goroll) Date: Sun, 10 Dec 2017 14:15:09 +0000 (UTC) Subject: [master] b57c329 add the blob wrapper to vrt Message-ID: <20171210141509.5D82E94742@lists.varnish-cache.org> commit b57c329a33cb512400ba1c068fef0bf81259cdb1 Author: Nils Goroll Date: Sun Dec 10 15:14:13 2017 +0100 add the blob wrapper to vrt it is genereally useful also for vmods diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c index 1a95db3..3d0952f 100644 --- a/bin/varnishd/cache/cache_vrt.c +++ b/bin/varnishd/cache/cache_vrt.c @@ -590,3 +590,21 @@ VRT_ipcmp(const struct suckaddr *sua1, const struct suckaddr *sua2) return(1); return (VSA_Compare_IP(sua1, sua2)); } + +struct vmod_priv * +VRT_blob(VRT_CTX, const char *err, const uint8_t *src, size_t len) +{ + struct vmod_priv *p; + void *d; + + p = (void *)WS_Alloc(ctx->ws, sizeof *p); + d = WS_Copy(ctx->ws, src, len); + if (p == NULL || d == NULL) { + VRT_fail(ctx, "Workspace overflow (%s)", err); + return (NULL); + } + memset(p, 0, sizeof *p); + p->len = len; + p->priv = d; + return (p); +} diff --git a/bin/varnishd/cache/cache_vrt_var.c b/bin/varnishd/cache/cache_vrt_var.c index 01e5997..b99bd9f 100644 --- a/bin/varnishd/cache/cache_vrt_var.c +++ b/bin/varnishd/cache/cache_vrt_var.c @@ -730,31 +730,12 @@ VRT_BODY_L(resp) /*--------------------------------------------------------------------*/ -static struct vmod_priv * -vrt_do_blob(VRT_CTX, const char *err, const uint8_t *src, size_t len) -{ - struct vmod_priv *p; - void *d; - - p = (void *)WS_Alloc(ctx->ws, sizeof *p); - d = WS_Copy(ctx->ws, src, len); - if (p == NULL || d == NULL) { - VRT_fail(ctx, "Workspace overflow (%s)", err); - return (NULL); - } - memset(p, 0, sizeof *p); - p->len = len; - p->priv = d; - return (p); -} - VCL_BLOB VRT_r_req_hash(VRT_CTX) { CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC); - return (vrt_do_blob(ctx, "req.hash", ctx->req->digest, - DIGEST_LEN)); + return (VRT_blob(ctx, "req.hash", ctx->req->digest, DIGEST_LEN)); } VCL_BLOB @@ -762,8 +743,7 @@ VRT_r_bereq_hash(VRT_CTX) { CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC); - return (vrt_do_blob(ctx, "bereq.hash", ctx->bo->digest, - DIGEST_LEN)); + return (VRT_blob(ctx, "bereq.hash", ctx->bo->digest, DIGEST_LEN)); } /*--------------------------------------------------------------------*/ diff --git a/include/vrt.h b/include/vrt.h index df9e18a..0a78bd1 100644 --- a/include/vrt.h +++ b/include/vrt.h @@ -60,6 +60,7 @@ * struct director.destroy added * VRT_r_beresp_storage_hint() removed - under discussion #2509 * VRT_l_beresp_storage_hint() removed - under discussion #2509 + * VRT_blob() added * 6.1 (2017-09-15 aka 5.2) * http_CollectHdrSep added * VRT_purge modified (may fail a transaction, signature changed) @@ -368,6 +369,7 @@ void VRT_hashdata(VRT_CTX, const char *str, ...); int VRT_strcmp(const char *s1, const char *s2); void VRT_memmove(void *dst, const void *src, unsigned len); int VRT_ipcmp(const struct suckaddr *sua1, const struct suckaddr *sua2); +struct vmod_priv *VRT_blob(VRT_CTX, const char *, const uint8_t *, size_t); void VRT_Rollback(VRT_CTX, const struct http *); From fgsch at lodoss.net Sun Dec 10 23:57:07 2017 From: fgsch at lodoss.net (Federico G. Schwindt) Date: Sun, 10 Dec 2017 23:57:07 +0000 (UTC) Subject: [master] b0d5261 Spelling Message-ID: <20171210235707.E7E0D944F0@lists.varnish-cache.org> commit b0d52615c2caa1d6d43c550c0d4b16cca34c8a1f Author: Federico G. Schwindt Date: Sun Dec 10 23:55:48 2017 +0000 Spelling diff --git a/doc/sphinx/reference/vcl.rst b/doc/sphinx/reference/vcl.rst index a0f94db..024b568 100644 --- a/doc/sphinx/reference/vcl.rst +++ b/doc/sphinx/reference/vcl.rst @@ -94,7 +94,7 @@ context some data types will evaluate to ``true`` or ``false`` depending on their value. String types will evaluate to ``false`` if they are empty; backend types -will evalute to ``false`` if they don't have a backend assigned; integer +will evaluate to ``false`` if they don't have a backend assigned; integer types will evaluate to ``false`` if their value is zero; duration types will evaluate to ``false`` if their value is equal or less than zero. @@ -298,7 +298,7 @@ There are no mandatory options. These are the options you can set: ``.threshold`` How many of the polls in ``.window`` must have succeeded to - for the backend to be healthy. + consider the backend to be healthy. Defaults to ``3``. From phk at FreeBSD.org Mon Dec 11 09:22:12 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Mon, 11 Dec 2017 09:22:12 +0000 (UTC) Subject: [master] f7bc45c Move the numerical value functions to _utils Message-ID: <20171211092212.4001B94556@lists.varnish-cache.org> commit f7bc45c32cfcdc494484ab75e477f049d3efa4a3 Author: Poul-Henning Kamp Date: Sun Dec 10 11:33:03 2017 +0000 Move the numerical value functions to _utils diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h index 074e66c..d19e64f 100644 --- a/lib/libvcc/vcc_compile.h +++ b/lib/libvcc/vcc_compile.h @@ -281,9 +281,6 @@ void *TlAlloc(struct vcc *tl, unsigned len); char *TlDup(struct vcc *tl, const char *s); /* vcc_expr.c */ -double vcc_DoubleVal(struct vcc *tl); -void vcc_Duration(struct vcc *tl, double *); -unsigned vcc_UintVal(struct vcc *tl); void vcc_Expr(struct vcc *tl, vcc_type_t typ); void vcc_Expr_Call(struct vcc *tl, const struct symbol *sym); void vcc_Expr_Init(struct vcc *tl); @@ -309,6 +306,12 @@ void Resolve_Sockaddr(struct vcc *tl, const char *host, const char *defport, const char **ipv4, const char **ipv4_ascii, const char **ipv6, const char **ipv6_ascii, const char **p_ascii, int maxips, const struct token *t_err, const char *errid); +double vcc_TimeUnit(struct vcc *); +void vcc_ByteVal(struct vcc *, double *); +void vcc_NumVal(struct vcc *, double *, int *); +double vcc_DoubleVal(struct vcc *tl); +void vcc_Duration(struct vcc *tl, double *); +unsigned vcc_UintVal(struct vcc *tl); /* vcc_storage.c */ void vcc_stevedore(struct vcc *vcc, const char *stv_name); diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c index efc84de..ec3d1d4 100644 --- a/lib/libvcc/vcc_expr.c +++ b/lib/libvcc/vcc_expr.c @@ -49,161 +49,6 @@ struct expr { #define EXPR_STR_CONST (1<<2) // Last STRING_LIST elem is "..." struct token *t1, *t2; }; - -/*-------------------------------------------------------------------- - * Recognize and convert units of time, return seconds. - */ - -static double -vcc_TimeUnit(struct vcc *tl) -{ - double sc = 1.0; - - assert(tl->t->tok == ID); - if (vcc_IdIs(tl->t, "ms")) - sc = 1e-3; - else if (vcc_IdIs(tl->t, "s")) - sc = 1.0; - else if (vcc_IdIs(tl->t, "m")) - sc = 60.0; - else if (vcc_IdIs(tl->t, "h")) - sc = 60.0 * 60.0; - else if (vcc_IdIs(tl->t, "d")) - sc = 60.0 * 60.0 * 24.0; - else if (vcc_IdIs(tl->t, "w")) - sc = 60.0 * 60.0 * 24.0 * 7.0; - else if (vcc_IdIs(tl->t, "y")) - sc = 60.0 * 60.0 * 24.0 * 365.0; - else { - VSB_printf(tl->sb, "Unknown time unit "); - vcc_ErrToken(tl, tl->t); - VSB_printf(tl->sb, - ". Legal are 'ms', 's', 'm', 'h', 'd', 'w' and 'y'\n"); - vcc_ErrWhere(tl, tl->t); - return (1.0); - } - vcc_NextToken(tl); - return (sc); -} - -/*-------------------------------------------------------------------- - * Recognize and convert { CNUM } to unsigned value - * The tokenizer made sure we only get digits. - */ - -unsigned -vcc_UintVal(struct vcc *tl) -{ - unsigned d = 0; - const char *p; - - Expect(tl, CNUM); - for (p = tl->t->b; p < tl->t->e; p++) { - d *= 10; - d += *p - '0'; - } - vcc_NextToken(tl); - return (d); -} - -/*-------------------------------------------------------------------- - * Recognize and convert { CNUM [ '.' [ CNUM ] ] } to double value - * The tokenizer made sure we only get digits and a '.' - */ - -static void -vcc_NumVal(struct vcc *tl, double *d, int *frac) -{ - double e = 0.1; - const char *p; - - *frac = 0; - *d = 0.0; - Expect(tl, CNUM); - if (tl->err) { - *d = NAN; - return; - } - for (p = tl->t->b; p < tl->t->e; p++) { - *d *= 10; - *d += *p - '0'; - } - vcc_NextToken(tl); - if (tl->t->tok != '.') - return; - *frac = 1; - vcc_NextToken(tl); - if (tl->t->tok != CNUM) - return; - for (p = tl->t->b; p < tl->t->e; p++) { - *d += (*p - '0') * e; - e *= 0.1; - } - vcc_NextToken(tl); -} - -double -vcc_DoubleVal(struct vcc *tl) -{ - double d; - int i; - - vcc_NumVal(tl, &d, &i); - return (d); -} - -/*--------------------------------------------------------------------*/ - -void -vcc_Duration(struct vcc *tl, double *d) -{ - double v, sc; - - v = vcc_DoubleVal(tl); - ERRCHK(tl); - ExpectErr(tl, ID); - sc = vcc_TimeUnit(tl); - *d = v * sc; -} - -/*--------------------------------------------------------------------*/ - -static void -vcc_ByteVal(struct vcc *tl, double *d) -{ - double v, sc; - - v = vcc_DoubleVal(tl); - ERRCHK(tl); - if (tl->t->tok != ID) { - VSB_printf(tl->sb, "Expected BYTES unit (B, KB, MB...) got "); - vcc_ErrToken(tl, tl->t); - VSB_printf(tl->sb, "\n"); - vcc_ErrWhere(tl, tl->t); - return; - } - if (vcc_IdIs(tl->t, "B")) - sc = 1.; - else if (vcc_IdIs(tl->t, "KB")) - sc = 1024.; - else if (vcc_IdIs(tl->t, "MB")) - sc = 1024. * 1024.; - else if (vcc_IdIs(tl->t, "GB")) - sc = 1024. * 1024. * 1024.; - else if (vcc_IdIs(tl->t, "TB")) - sc = 1024. * 1024. * 1024. * 1024.; - else { - VSB_printf(tl->sb, "Unknown BYTES unit "); - vcc_ErrToken(tl, tl->t); - VSB_printf(tl->sb, - ". Legal are 'B', 'KB', 'MB', 'GB' and 'TB'\n"); - vcc_ErrWhere(tl, tl->t); - return; - } - vcc_NextToken(tl); - *d = v * sc; -} - /*-------------------------------------------------------------------- * Facility for carrying expressions around and do text-processing on * them. diff --git a/lib/libvcc/vcc_utils.c b/lib/libvcc/vcc_utils.c index 9db35bb..8d83897 100644 --- a/lib/libvcc/vcc_utils.c +++ b/lib/libvcc/vcc_utils.c @@ -29,6 +29,7 @@ #include "config.h" +#include #include #include #include @@ -249,3 +250,158 @@ Resolve_Sockaddr(struct vcc *tl, VSB_destroy(&rss->vsb); FREE_OBJ(rss); } + +/*-------------------------------------------------------------------- + * Recognize and convert units of time, return seconds. + */ + +double +vcc_TimeUnit(struct vcc *tl) +{ + double sc = 1.0; + + assert(tl->t->tok == ID); + if (vcc_IdIs(tl->t, "ms")) + sc = 1e-3; + else if (vcc_IdIs(tl->t, "s")) + sc = 1.0; + else if (vcc_IdIs(tl->t, "m")) + sc = 60.0; + else if (vcc_IdIs(tl->t, "h")) + sc = 60.0 * 60.0; + else if (vcc_IdIs(tl->t, "d")) + sc = 60.0 * 60.0 * 24.0; + else if (vcc_IdIs(tl->t, "w")) + sc = 60.0 * 60.0 * 24.0 * 7.0; + else if (vcc_IdIs(tl->t, "y")) + sc = 60.0 * 60.0 * 24.0 * 365.0; + else { + VSB_printf(tl->sb, "Unknown time unit "); + vcc_ErrToken(tl, tl->t); + VSB_printf(tl->sb, + ". Legal are 'ms', 's', 'm', 'h', 'd', 'w' and 'y'\n"); + vcc_ErrWhere(tl, tl->t); + return (1.0); + } + vcc_NextToken(tl); + return (sc); +} + +/*-------------------------------------------------------------------- + * Recognize and convert { CNUM } to unsigned value + * The tokenizer made sure we only get digits. + */ + +unsigned +vcc_UintVal(struct vcc *tl) +{ + unsigned d = 0; + const char *p; + + Expect(tl, CNUM); + for (p = tl->t->b; p < tl->t->e; p++) { + d *= 10; + d += *p - '0'; + } + vcc_NextToken(tl); + return (d); +} + +/*-------------------------------------------------------------------- + * Recognize and convert { CNUM [ '.' [ CNUM ] ] } to double value + * The tokenizer made sure we only get digits and a '.' + */ + +void +vcc_NumVal(struct vcc *tl, double *d, int *frac) +{ + double e = 0.1; + const char *p; + + *frac = 0; + *d = 0.0; + Expect(tl, CNUM); + if (tl->err) { + *d = NAN; + return; + } + for (p = tl->t->b; p < tl->t->e; p++) { + *d *= 10; + *d += *p - '0'; + } + vcc_NextToken(tl); + if (tl->t->tok != '.') + return; + *frac = 1; + vcc_NextToken(tl); + if (tl->t->tok != CNUM) + return; + for (p = tl->t->b; p < tl->t->e; p++) { + *d += (*p - '0') * e; + e *= 0.1; + } + vcc_NextToken(tl); +} + +double +vcc_DoubleVal(struct vcc *tl) +{ + double d; + int i; + + vcc_NumVal(tl, &d, &i); + return (d); +} + +/*--------------------------------------------------------------------*/ + +void +vcc_Duration(struct vcc *tl, double *d) +{ + double v, sc; + + v = vcc_DoubleVal(tl); + ERRCHK(tl); + ExpectErr(tl, ID); + sc = vcc_TimeUnit(tl); + *d = v * sc; +} + +/*--------------------------------------------------------------------*/ + +void +vcc_ByteVal(struct vcc *tl, double *d) +{ + double v, sc; + + v = vcc_DoubleVal(tl); + ERRCHK(tl); + if (tl->t->tok != ID) { + VSB_printf(tl->sb, "Expected BYTES unit (B, KB, MB...) got "); + vcc_ErrToken(tl, tl->t); + VSB_printf(tl->sb, "\n"); + vcc_ErrWhere(tl, tl->t); + return; + } + if (vcc_IdIs(tl->t, "B")) + sc = 1.; + else if (vcc_IdIs(tl->t, "KB")) + sc = 1024.; + else if (vcc_IdIs(tl->t, "MB")) + sc = 1024. * 1024.; + else if (vcc_IdIs(tl->t, "GB")) + sc = 1024. * 1024. * 1024.; + else if (vcc_IdIs(tl->t, "TB")) + sc = 1024. * 1024. * 1024. * 1024.; + else { + VSB_printf(tl->sb, "Unknown BYTES unit "); + vcc_ErrToken(tl, tl->t); + VSB_printf(tl->sb, + ". Legal are 'B', 'KB', 'MB', 'GB' and 'TB'\n"); + vcc_ErrWhere(tl, tl->t); + return; + } + vcc_NextToken(tl); + *d = v * sc; +} + From phk at FreeBSD.org Mon Dec 11 09:22:12 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Mon, 11 Dec 2017 09:22:12 +0000 (UTC) Subject: [master] 7674f65 Tell flexelint about the tbl_*.h files. Message-ID: <20171211092212.6046394559@lists.varnish-cache.org> commit 7674f657e385a396ea4504fb1879b25fa0658178 Author: Poul-Henning Kamp Date: Mon Dec 11 09:20:50 2017 +0000 Tell flexelint about the tbl_*.h files. diff --git a/lib/libvmod_blob/flint.lnt b/lib/libvmod_blob/flint.lnt index e69de29..1b6f088 100644 --- a/lib/libvmod_blob/flint.lnt +++ b/lib/libvmod_blob/flint.lnt @@ -0,0 +1 @@ +-efile(451, "tbl_*.h") // No include guard From nils.goroll at uplex.de Mon Dec 11 13:45:12 2017 From: nils.goroll at uplex.de (Nils Goroll) Date: Mon, 11 Dec 2017 13:45:12 +0000 (UTC) Subject: [master] 318a17c changelog tlc Message-ID: <20171211134512.8D54594799@lists.varnish-cache.org> commit 318a17cfec5b33f77a4667b68716edd5839f1051 Author: Nils Goroll Date: Mon Dec 11 14:44:01 2017 +0100 changelog tlc diff --git a/doc/changes.rst b/doc/changes.rst index fe09dea..4d1f91d 100644 --- a/doc/changes.rst +++ b/doc/changes.rst @@ -30,8 +30,8 @@ Usage used during ESI delivery. It should not be tuned unless advised by a developer. -VCL ---- +VCL and bundled VMODs +--------------------- * Fix behaviour of restarts to how it was originally intended: Restarts now leave all the request properties in place except for @@ -43,6 +43,18 @@ VCL * Removed ``beresp.storage_hint`` (was deprecated since Varnish 5.1) +* workspace overflows in ``std.log()`` now trigger a VCL failure + +* workspace overflows in ``std.syslog()`` are ignored + +Logging / statistics +-------------------- + +* Turned off PROXY protocol debugging by default, can be enabled with + the ``protocol`` debug flag + +* added ``cache_hit_grace`` statisctics counter + C APIs (for vmod and utility authors) ------------------------------------- @@ -78,10 +90,37 @@ C APIs (for vmod and utility authors) * director health state queries have been merged to ``VRT_Healthy()`` +* Renamed macros: + * ``__match_proto__()`` -> ``v_matchproto_()`` + * ``__v_printflike()`` -> ``v_printflike_()`` + * ``__state_variable__()`` -> ``v_statevariable_()`` + * ``__unused`` -> ``v_unused_`` + * ``__attribute__((__noreturn__)`` -> ``v_noreturn_`` + + * ENUMs are now fixed pointers per vcl + +* Added ``VRT_blob()`` utility function to create a blob as a copy + of some chunk of data on the workspace. + + +Other changes relevant for VMODs +-------------------------------- + +* ``PRIV_*`` function/method arguments are not excluded from + auto-generated vmod documentation + +Fixed bugs which may influence VCL behaviour +-------------------------------------------- + +* After reusing a backend connection fails once, a fresh connection + will be opened (2135) + +.. _2135: https://github.com/varnishcache/varnish-cache/pull/2135 + Fixed bugs ---------- -XXX TODO +**TODO** ================================ Varnish Cache 5.2.0 (2017-09-15) From dridi.boukelmoune at gmail.com Mon Dec 11 22:54:10 2017 From: dridi.boukelmoune at gmail.com (Dridi Boukelmoune) Date: Mon, 11 Dec 2017 22:54:10 +0000 (UTC) Subject: [master] 575197f Initialize a variable Message-ID: <20171211225410.8E51A9632D@lists.varnish-cache.org> commit 575197f24eca6ed4399032b7efbed9ecb0697fea Author: Dridi Boukelmoune Date: Mon Dec 11 23:51:39 2017 +0100 Initialize a variable Otherwise some compilers *cough* GCC *cough* may fail to see that it's properly written before any read. diff --git a/lib/libvarnish/binary_heap.c b/lib/libvarnish/binary_heap.c index 88c85d4..b49f9d6 100644 --- a/lib/libvarnish/binary_heap.c +++ b/lib/libvarnish/binary_heap.c @@ -520,14 +520,12 @@ chk2(struct binheap *bh) #endif int -main(int argc, char **argv) +main(void) { struct binheap *bh; unsigned j, u, v, lr, n; struct foo *fp; - (void)argc; - (void)argv; VRND_SeedAll(); VRND_SeedTestable(1); bh = binheap_new(NULL, cmp, update); @@ -537,6 +535,8 @@ main(int argc, char **argv) child(bh, n + 1, &u, &v); } + lr = 0; /* unconfuse some compilers... */ + for (j = 0; j < 2; j++) { /* First insert our N elements */ for (u = 0; u < N; u++) { @@ -614,7 +614,7 @@ main(int argc, char **argv) AN(ff[v]->idx); } #ifdef CHECK2 - chk2(bh); + chk2(bh); #endif } fprintf(stderr, "%d updates OK\n", M); From phk at FreeBSD.org Tue Dec 12 09:38:06 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Tue, 12 Dec 2017 09:38:06 +0000 (UTC) Subject: [master] 5e8c00f Renovate the comparison part of VCL expressions Message-ID: <20171212093806.E3702A6187@lists.varnish-cache.org> commit 5e8c00f43e80a3c694ae9af06ec454d96c194ac6 Author: Poul-Henning Kamp Date: Tue Dec 12 09:36:53 2017 +0000 Renovate the comparison part of VCL expressions diff --git a/lib/libvcc/vcc_acl.c b/lib/libvcc/vcc_acl.c index 374c886..d11f926 100644 --- a/lib/libvcc/vcc_acl.c +++ b/lib/libvcc/vcc_acl.c @@ -460,22 +460,6 @@ vcc_acl_emit(struct vcc *tl, const char *name, const char *rname, int anon) } void -vcc_Acl_Hack(struct vcc *tl, char *b, size_t bl) -{ - char name[32]; - unsigned tcond; - - VTAILQ_INIT(&tl->acl); - tcond = tl->t->tok; - vcc_NextToken(tl); - bprintf(name, "%u", tl->unique++); - vcc_acl_entry(tl); - vcc_acl_emit(tl, name, name, 1); - assert(snprintf(b, bl - 1, "%smatch_acl_anon_%s(ctx, \v1)", - (tcond == T_NEQ ? "!" : ""), name) < bl - 1); -} - -void vcc_ParseAcl(struct vcc *tl) { struct token *an; diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h index d19e64f..2209f23 100644 --- a/lib/libvcc/vcc_compile.h +++ b/lib/libvcc/vcc_compile.h @@ -245,7 +245,6 @@ struct method { /* vcc_acl.c */ void vcc_ParseAcl(struct vcc *tl); -void vcc_Acl_Hack(struct vcc *tl, char *b, size_t bl); /* vcc_action.c */ int vcc_ParseAction(struct vcc *tl); diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c index ec3d1d4..b55f4ba 100644 --- a/lib/libvcc/vcc_expr.c +++ b/lib/libvcc/vcc_expr.c @@ -939,23 +939,6 @@ vcc_expr_add(struct vcc *tl, struct expr **e, vcc_type_t fmt) } /*-------------------------------------------------------------------- - * Fold the STRING types correctly - */ - -static void -vcc_expr_strfold(struct vcc *tl, struct expr **e, vcc_type_t fmt) -{ - - vcc_expr_add(tl, e, fmt); - ERRCHK(tl); - - if (fmt != STRING_LIST && (*e)->fmt == STRING_LIST) - vcc_expr_tostring(tl, e, STRING); - else if (fmt == STRING_LIST && (*e)->fmt == STRING) - (*e)->fmt = STRING_LIST; -} - -/*-------------------------------------------------------------------- * SYNTAX: * ExprCmp: * ExprAdd @@ -966,34 +949,113 @@ vcc_expr_strfold(struct vcc *tl, struct expr **e, vcc_type_t fmt) * ExprAdd(IP) '!~' IP */ -#define NUM_REL(typ) \ - {typ, T_EQ, "(\v1 == \v2)" }, \ - {typ, T_NEQ, "(\v1 != \v2)" }, \ - {typ, T_LEQ, "(\v1 <= \v2)" }, \ - {typ, T_GEQ, "(\v1 >= \v2)" }, \ - {typ, '<', "(\v1 < \v2)" }, \ - {typ, '>', "(\v1 > \v2)" } - -static const struct cmps { +struct cmps; + +typedef void cmp_f(struct vcc *, struct expr **, const struct cmps *); + +struct cmps { vcc_type_t fmt; unsigned token; const char *emit; -} vcc_cmps[] = { + cmp_f *func; +}; + +static void v_matchproto_(cmp_f) +cmp_simple(struct vcc *tl, struct expr **e, const struct cmps *cp) +{ + struct expr *e2; + struct token *tk; + + tk = tl->t; + vcc_NextToken(tl); + if ((*e)->fmt == STRING_LIST) + vcc_expr_tostring(tl, e, STRING); + vcc_expr_add(tl, &e2, (*e)->fmt); + ERRCHK(tl); + + if (e2->fmt != (*e)->fmt) { /* XXX */ + VSB_printf(tl->sb, "Comparison of different types: "); + VSB_printf(tl->sb, "%s ", vcc_utype((*e)->fmt)); + vcc_ErrToken(tl, tk); + VSB_printf(tl->sb, " %s\n", vcc_utype(e2->fmt)); + vcc_ErrWhere(tl, tk); + return; + } + *e = vcc_expr_edit(BOOL, cp->emit, *e, e2); +} + +static void v_matchproto_(cmp_f) +cmp_regexp(struct vcc *tl, struct expr **e, const struct cmps *cp) +{ + char buf[128]; + const char *re; + + if ((*e)->fmt != STRING) + vcc_expr_tostring(tl, e, STRING); + vcc_NextToken(tl); + ExpectErr(tl, CSTR); + re = vcc_regexp(tl); + ERRCHK(tl); + vcc_NextToken(tl); + bprintf(buf, "%sVRT_re_match(ctx, \v1, %s)", cp->emit, re); + *e = vcc_expr_edit(BOOL, buf, *e, NULL); +} + +static void v_matchproto_(cmp_f) +cmp_acl(struct vcc *tl, struct expr **e, const struct cmps *cp) +{ + struct symbol *sym; + char buf[256]; + + vcc_NextToken(tl); + vcc_ExpectVid(tl, "ACL"); + sym = vcc_AddRef(tl, tl->t, SYM_ACL); + vcc_NextToken(tl); + VCC_GlobalSymbol(sym, ACL, ACL_SYMBOL_PREFIX); + bprintf(buf, "%sVRT_acl_match(ctx, %s, \v1)", cp->emit, sym->rname); + *e = vcc_expr_edit(BOOL, buf, *e, NULL); +} + +#define IDENT_REL(typ) \ + {typ, T_EQ, "(\v1 == \v2)", cmp_simple }, \ + {typ, T_NEQ, "(\v1 != \v2)", cmp_simple } + +#define NUM_REL(typ) \ + {typ, T_EQ, "(\v1 == \v2)", cmp_simple }, \ + {typ, T_NEQ, "(\v1 != \v2)", cmp_simple }, \ + {typ, T_LEQ, "(\v1 <= \v2)", cmp_simple }, \ + {typ, T_GEQ, "(\v1 >= \v2)", cmp_simple }, \ + {typ, '<', "(\v1 < \v2)", cmp_simple }, \ + {typ, '>', "(\v1 > \v2)", cmp_simple } + +static const struct cmps vcc_cmps[] = { NUM_REL(INT), NUM_REL(DURATION), NUM_REL(BYTES), NUM_REL(REAL), NUM_REL(TIME), - - {IP, T_EQ, "!VRT_ipcmp(\v1, \v2)" }, - {IP, T_NEQ, "VRT_ipcmp(\v1, \v2)" }, - - {STRING, T_EQ, "!VRT_strcmp(\v1, \v2)" }, - {STRING, T_NEQ, "VRT_strcmp(\v1, \v2)" }, - {STRING_LIST, T_EQ, "!VRT_strcmp(\v1, \v2)" }, - {STRING_LIST, T_NEQ, "VRT_strcmp(\v1, \v2)" }, - - {VOID, 0, NULL} + IDENT_REL(BACKEND), + IDENT_REL(ACL), + IDENT_REL(PROBE), + IDENT_REL(STEVEDORE), + IDENT_REL(SUB), + IDENT_REL(INSTANCE), + + {IP, T_EQ, "!VRT_ipcmp(\v1, \v2)", cmp_simple }, + {IP, T_NEQ, "VRT_ipcmp(\v1, \v2)", cmp_simple }, + {IP, '~', "", cmp_acl }, + {IP, T_NOMATCH, "!", cmp_acl }, + + {STRING, T_EQ, "!VRT_strcmp(\v1, \v2)", cmp_simple }, + {STRING_LIST, T_EQ, "!VRT_strcmp(\v1, \v2)", cmp_simple }, + {STRING, T_NEQ, "VRT_strcmp(\v1, \v2)", cmp_simple }, + {STRING_LIST, T_NEQ, "VRT_strcmp(\v1, \v2)", cmp_simple }, + {STRING, '~', "", cmp_regexp }, + {STRING_LIST, '~', "", cmp_regexp }, + {STRING, T_NOMATCH, "!", cmp_regexp }, + {STRING_LIST, T_NOMATCH, "!", cmp_regexp }, + + {VOID, 0, NULL, NULL} }; #undef NUM_REL @@ -1001,14 +1063,8 @@ static const struct cmps { static void vcc_expr_cmp(struct vcc *tl, struct expr **e, vcc_type_t fmt) { - struct expr *e2; const struct cmps *cp; - char buf[256]; - const char *re; - const char *not; struct token *tk; - struct symbol *sym; - enum symkind kind; *e = NULL; @@ -1022,76 +1078,11 @@ vcc_expr_cmp(struct vcc *tl, struct expr **e, vcc_type_t fmt) for (cp = vcc_cmps; cp->fmt != VOID; cp++) if ((*e)->fmt == cp->fmt && tl->t->tok == cp->token) break; - if (cp->fmt != VOID) { - vcc_NextToken(tl); - if ((*e)->fmt == STRING_LIST) { - // XXX: This is not optimal, but we can't pass two - // STRING_LIST's to a function anyway... - vcc_expr_tostring(tl, e, STRING); - } - vcc_expr_strfold(tl, &e2, (*e)->fmt); - ERRCHK(tl); - if (e2->fmt != (*e)->fmt) { /* XXX */ - VSB_printf(tl->sb, "Comparison of different types: "); - VSB_printf(tl->sb, "%s ", vcc_utype((*e)->fmt)); - vcc_ErrToken(tl, tk); - VSB_printf(tl->sb, " %s\n", vcc_utype(e2->fmt)); - vcc_ErrWhere(tl, tk); - return; - } - *e = vcc_expr_edit(BOOL, cp->emit, *e, e2); - return; - } - if (((*e)->fmt == STRING || (*e)->fmt == STRING_LIST) && - (tl->t->tok == '~' || tl->t->tok == T_NOMATCH)) { - if ((*e)->fmt == STRING_LIST) - vcc_expr_tostring(tl, e, STRING); - not = tl->t->tok == '~' ? "" : "!"; - vcc_NextToken(tl); - ExpectErr(tl, CSTR); - re = vcc_regexp(tl); - ERRCHK(tl); - vcc_NextToken(tl); - bprintf(buf, "%sVRT_re_match(ctx, \v1, %s)", not, re); - *e = vcc_expr_edit(BOOL, buf, *e, NULL); + if (cp->func != NULL) { + cp->func(tl, e, cp); return; } - if ((*e)->fmt == IP && - (tl->t->tok == '~' || tl->t->tok == T_NOMATCH)) { - not = tl->t->tok == '~' ? "" : "!"; - vcc_NextToken(tl); - vcc_ExpectVid(tl, "ACL"); - sym = vcc_AddRef(tl, tl->t, SYM_ACL); - VCC_GlobalSymbol(sym, ACL, ACL_SYMBOL_PREFIX); - bprintf(buf, "%sVRT_acl_match(ctx, %s, \v1)", not, sym->rname); - vcc_NextToken(tl); - *e = vcc_expr_edit(BOOL, buf, *e, NULL); - return; - } - if ((*e)->fmt == IP && (tl->t->tok == T_EQ || tl->t->tok == T_NEQ)) { - vcc_Acl_Hack(tl, buf, sizeof buf); - *e = vcc_expr_edit(BOOL, buf, *e, NULL); - return; - } - kind = VCC_HandleKind((*e)->fmt); - if (kind != SYM_NONE && (tl->t->tok == T_EQ || tl->t->tok == T_NEQ)) { - bprintf(buf, "(\v1 %.*s \v2)", PF(tk)); - vcc_NextToken(tl); - e2 = NULL; - vcc_expr0(tl, &e2, (*e)->fmt); - ERRCHK(tl); - if (e2->fmt != (*e)->fmt) { - VSB_printf(tl->sb, "Comparison of different types: "); - VSB_printf(tl->sb, "%s ", vcc_utype((*e)->fmt)); - vcc_ErrToken(tl, tk); - VSB_printf(tl->sb, " %s\n", vcc_utype(e2->fmt)); - vcc_ErrWhere(tl, tk); - return; - } - *e = vcc_expr_edit(BOOL, buf, *e, e2); - return; - } - switch (tl->t->tok) { + switch (tk->tok) { case T_EQ: case T_NEQ: case '<': @@ -1113,6 +1104,8 @@ vcc_expr_cmp(struct vcc *tl, struct expr **e, vcc_type_t fmt) *e = vcc_expr_edit(BOOL, "(\v1 != 0)", *e, NULL); else if ((*e)->fmt == DURATION) *e = vcc_expr_edit(BOOL, "(\v1 > 0)", *e, NULL); + else + INCOMPL(); } /*-------------------------------------------------------------------- From phk at FreeBSD.org Tue Dec 12 13:11:07 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Tue, 12 Dec 2017 13:11:07 +0000 (UTC) Subject: [master] 3d23688 Add a VSB for function prologues Message-ID: <20171212131107.12C1AAA304@lists.varnish-cache.org> commit 3d236885e806441fd2d9cbfe7c4d5c58ad716f5f Author: Poul-Henning Kamp Date: Tue Dec 12 09:45:54 2017 +0000 Add a VSB for function prologues diff --git a/lib/libvcc/vcc_compile.c b/lib/libvcc/vcc_compile.c index e46c09e..28975b0 100644 --- a/lib/libvcc/vcc_compile.c +++ b/lib/libvcc/vcc_compile.c @@ -105,6 +105,8 @@ vcc_NewProc(struct vcc *tl, struct symbol *sym) VTAILQ_INIT(&p->calls); VTAILQ_INIT(&p->uses); VTAILQ_INSERT_TAIL(&tl->procs, p, list); + p->prologue = VSB_new_auto(); + AN(p->prologue); p->body = VSB_new_auto(); AN(p->body); p->cname = VSB_new_auto(); @@ -117,12 +119,14 @@ static void vcc_EmitProc(struct vcc *tl, struct proc *p) { AZ(VSB_finish(p->cname)); + AZ(VSB_finish(p->prologue)); AZ(VSB_finish(p->body)); Fh(tl, 1, "vcl_func_f %s;\n", VSB_data(p->cname)); Fc(tl, 1, "\nvoid v_matchproto_(vcl_func_f)\n"); Fc(tl, 1, "%s(VRT_CTX)\n", VSB_data(p->cname)); - Fc(tl, 1, "{\n%s}\n", VSB_data(p->body)); + Fc(tl, 1, "{\n%s\n%s}\n", VSB_data(p->prologue), VSB_data(p->body)); VSB_destroy(&p->body); + VSB_destroy(&p->prologue); VSB_destroy(&p->cname); } diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h index 2209f23..bade028 100644 --- a/lib/libvcc/vcc_compile.h +++ b/lib/libvcc/vcc_compile.h @@ -160,6 +160,7 @@ struct proc { unsigned active; struct token *return_tok[VCL_RET_MAX]; struct vsb *cname; + struct vsb *prologue; struct vsb *body; }; From phk at FreeBSD.org Tue Dec 12 13:11:07 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Tue, 12 Dec 2017 13:11:07 +0000 (UTC) Subject: [master] 66e06b1 Unify the "I need an expression of _exactly_ this type" paths. Message-ID: <20171212131107.24504AA306@lists.varnish-cache.org> commit 66e06b157ab94919716d3b6562441b68f0ef200c Author: Poul-Henning Kamp Date: Tue Dec 12 11:44:26 2017 +0000 Unify the "I need an expression of _exactly_ this type" paths. diff --git a/bin/varnishtest/tests/m00000.vtc b/bin/varnishtest/tests/m00000.vtc index 1690a78..14875e6 100644 --- a/bin/varnishtest/tests/m00000.vtc +++ b/bin/varnishtest/tests/m00000.vtc @@ -81,7 +81,7 @@ varnish v1 -errvcl {Wrong enum value. Expected one of:} { } } -varnish v1 -errvcl {Wrong argument type. Expected REAL. Got STRING.} { +varnish v1 -errvcl {Expression has type STRING, expected REAL} { import std; sub vcl_deliver { set resp.http.who = std.random("foo", "bar"); diff --git a/bin/varnishtest/tests/m00012.vtc b/bin/varnishtest/tests/m00012.vtc index 294458c..33f25c7 100644 --- a/bin/varnishtest/tests/m00012.vtc +++ b/bin/varnishtest/tests/m00012.vtc @@ -9,7 +9,7 @@ varnish v1 -errvcl {BLOBs can only be used as arguments to VMOD functions.} { } } -varnish v1 -errvcl {Wrong argument type. Expected BLOB. Got STRING.} { +varnish v1 -errvcl {Expression has type STRING, expected BLOB} { backend b1 {.host = "${bad_backend}";} diff --git a/bin/varnishtest/tests/r01212.vtc b/bin/varnishtest/tests/r01212.vtc index 0fc2634..236b459 100644 --- a/bin/varnishtest/tests/r01212.vtc +++ b/bin/varnishtest/tests/r01212.vtc @@ -1,6 +1,6 @@ varnishtest "#1212 - Vmod with HEADER argument given a STRING asserts the VCL compiler" -varnish v1 -errvcl {Wrong argument type. Expected HEADER. Got STRING.} { +varnish v1 -errvcl {Expression has type STRING, expected HEADER} { import std; backend b { .host = "127.0.0.1"; } sub vcl_recv { diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c index b55f4ba..c99242e 100644 --- a/lib/libvcc/vcc_expr.c +++ b/lib/libvcc/vcc_expr.c @@ -276,8 +276,7 @@ vcc_Eval_Regsub(struct vcc *tl, struct expr **e, const struct symbol *sym, SkipToken(tl, '('); vcc_expr0(tl, &e2, STRING); - if (e2 == NULL) - return; + ERRCHK(tl); SkipToken(tl, ','); ExpectErr(tl, CSTR); @@ -289,8 +288,7 @@ vcc_Eval_Regsub(struct vcc *tl, struct expr **e, const struct symbol *sym, SkipToken(tl, ','); vcc_expr0(tl, &e2, STRING); - if (e2 == NULL) - return; + ERRCHK(tl); *e = vcc_expr_edit(STRING, "\v1,\n\v2)\v-", *e, e2); SkipToken(tl, ')'); } @@ -430,20 +428,7 @@ vcc_do_arg(struct vcc *tl, struct func_arg *fa) } else { vcc_expr0(tl, &e2, fa->type); ERRCHK(tl); - if (e2->fmt != fa->type) { - VSB_printf(tl->sb, "Wrong argument type."); - VSB_printf(tl->sb, - " Expected %s.", vcc_utype(fa->type)); - VSB_printf(tl->sb, " Got %s.\n", vcc_utype(e2->fmt)); - vcc_ErrWhere2(tl, e2->t1, tl->t); - return; - } assert(e2->fmt == fa->type); - if (e2->fmt == STRING_LIST) { - e2 = vcc_expr_edit(STRING_LIST, - "\v+\n\v1,\nvrt_magic_string_end\v-", - e2, NULL); - } fa->result = e2; } } @@ -1176,12 +1161,12 @@ vcc_expr_cand(struct vcc *tl, struct expr **e, vcc_type_t fmt) /*-------------------------------------------------------------------- * SYNTAX: - * Expr0: + * Expr1: * ExprCand { '||' ExprCand } * */ static void -vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt) +vcc_expr1(struct vcc *tl, struct expr **e, vcc_type_t fmt) { struct expr *e2; struct token *tk; @@ -1214,6 +1199,32 @@ vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt) } /*-------------------------------------------------------------------- + * This function is the entry-point for getting an expression with + * a particular type, ready for inclusion in the VGC. + */ + +static void +vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt) +{ + struct token *t1; + + assert(fmt != VOID); + t1 = tl->t; + vcc_expr1(tl, e, fmt); + ERRCHK(tl); + if (fmt != (*e)->fmt) { + VSB_printf(tl->sb, "Expression has type %s, expected %s\n", + vcc_utype((*e)->fmt), vcc_utype(fmt)); + tl->err = 1; + } + if ((*e)->fmt == STRING_LIST) + *e = vcc_expr_edit(STRING_LIST, + "\v+\n\v1,\nvrt_magic_string_end\v-", *e, NULL); + if (tl->err) + vcc_ErrWhere2(tl, t1, tl->t); +} + +/*-------------------------------------------------------------------- * This function parses and emits the C-code to evaluate an expression * * We know up front what kind of type we want the expression to be, @@ -1223,29 +1234,13 @@ vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt) void vcc_Expr(struct vcc *tl, vcc_type_t fmt) { - struct expr *e; - struct token *t1; + struct expr *e = NULL; assert(fmt != VOID); - - t1 = tl->t; vcc_expr0(tl, &e, fmt); ERRCHK(tl); - e->t1 = t1; - if (!tl->err && fmt != e->fmt) { - VSB_printf(tl->sb, "Expression has type %s, expected %s\n", - vcc_utype(e->fmt), vcc_utype(fmt)); - tl->err = 1; - } - if (!tl->err) { - if (e->fmt == STRING_LIST) { - e = vcc_expr_edit(STRING_LIST, - "\v+\n\v1,\nvrt_magic_string_end\v-", e, NULL); - } - vcc_expr_fmt(tl->fb, tl->indent, e); - VSB_putc(tl->fb, '\n'); - } else if (t1 != tl->t) - vcc_ErrWhere2(tl, t1, tl->t); + vcc_expr_fmt(tl->fb, tl->indent, e); + VSB_printf(tl->fb, "\n"); vcc_delete_expr(e); } diff --git a/lib/libvcc/vcc_vmod.c b/lib/libvcc/vcc_vmod.c index e6d6e64..9a3344d 100644 --- a/lib/libvcc/vcc_vmod.c +++ b/lib/libvcc/vcc_vmod.c @@ -238,7 +238,7 @@ vcc_ParseImport(struct vcc *tl) VSB_printf(ifp->fin, "\t\t(void)%s(ctx, &vmod_priv_%.*s,\n" "\t\t\t VCL_EVENT_DISCARD);\n", p, PF(mod)); - VSB_printf(ifp->event, "\t%s(ctx, &vmod_priv_%.*s, ev)", + VSB_printf(ifp->event, "%s(ctx, &vmod_priv_%.*s, ev)", p, PF(mod)); } else if (!strcmp(p, "$FUNC")) { p += strlen(p) + 1; From phk at FreeBSD.org Tue Dec 12 13:11:07 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Tue, 12 Dec 2017 13:11:07 +0000 (UTC) Subject: [master] 0fb21d3 Polishing, i-dotting and t-crossing Message-ID: <20171212131107.3B883AA309@lists.varnish-cache.org> commit 0fb21d3c078fbe6f84d38340578851ce70318441 Author: Poul-Henning Kamp Date: Tue Dec 12 13:07:11 2017 +0000 Polishing, i-dotting and t-crossing diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c index c99242e..eb9a3e6 100644 --- a/lib/libvcc/vcc_expr.c +++ b/lib/libvcc/vcc_expr.c @@ -70,6 +70,7 @@ vcc_utype(vcc_type_t t) } static void vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt); +static void vcc_expr_cor(struct vcc *tl, struct expr **e, vcc_type_t fmt); static struct expr * vcc_new_expr(void) @@ -593,7 +594,7 @@ vcc_Eval_SymFunc(struct vcc *tl, struct expr **e, const struct symbol *sym, /*-------------------------------------------------------------------- * SYNTAX: * Expr4: - * '(' Expr0 ')' + * '(' ExprCor ')' * symbol * CNUM * CSTR @@ -613,13 +614,16 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt) *e = NULL; if (tl->t->tok == '(') { SkipToken(tl, '('); - vcc_expr0(tl, &e2, fmt); + vcc_expr_cor(tl, &e2, fmt); ERRCHK(tl); SkipToken(tl, ')'); - if (fmt == STRING_LIST && e2->fmt == STRING_LIST) - *e = e2; // (...) not needed or wanted. - else + if (e2->fmt == STRING_LIST) { + *e = e2; + if (fmt == STRING) + vcc_expr_tostring(tl, e, STRING); + } else { *e = vcc_expr_edit(e2->fmt, "(\v1)", e2, NULL); + } return; } switch (tl->t->tok) { @@ -721,8 +725,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt) sign, d * vcc_TimeUnit(tl)); ERRCHK(tl); } else if (i || fmt == REAL) - e1 = vcc_mk_expr(REAL, "%s%f", - sign, d); + e1 = vcc_mk_expr(REAL, "%s%f", sign, d); else e1 = vcc_mk_expr(INT, "%s%ld", sign, (unsigned long)d); @@ -741,7 +744,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt) /*-------------------------------------------------------------------- * SYNTAX: - * Expr3: + * ExprMul: * Expr4 { {'*'|'/'} Expr4 } * */ @@ -749,31 +752,28 @@ static void vcc_expr_mul(struct vcc *tl, struct expr **e, vcc_type_t fmt) { struct expr *e2; - vcc_type_t f2, f3; + vcc_type_t f2; struct token *tk; *e = NULL; vcc_expr4(tl, e, fmt); ERRCHK(tl); AN(*e); - f3 = (*e)->fmt; - - f2 = f3->multype; - if (f2 == NULL) { - if (tl->t->tok != '*' && tl->t->tok != '/') - return; - VSB_printf(tl->sb, "Operator %.*s not possible on type %s.\n", - PF(tl->t), vcc_utype(f3)); - vcc_ErrWhere(tl, tl->t); - return; - } while (tl->t->tok == '*' || tl->t->tok == '/') { + f2 = (*e)->fmt->multype; + if (f2 == NULL) { + VSB_printf(tl->sb, + "Operator %.*s not possible on type %s.\n", + PF(tl->t), vcc_utype((*e)->fmt)); + vcc_ErrWhere(tl, tl->t); + return; + } tk = tl->t; vcc_NextToken(tl); vcc_expr4(tl, &e2, f2); ERRCHK(tl); - if (e2->fmt != REAL && e2->fmt != INT) { + if (e2->fmt != INT && e2->fmt != f2) { VSB_printf(tl->sb, "%s %.*s %s not possible.\n", vcc_utype(f2), PF(tk), vcc_utype(e2->fmt)); @@ -781,9 +781,9 @@ vcc_expr_mul(struct vcc *tl, struct expr **e, vcc_type_t fmt) return; } if (tk->tok == '*') - *e = vcc_expr_edit(f3, "(\v1*\v2)", *e, e2); + *e = vcc_expr_edit((*e)->fmt, "(\v1*\v2)", *e, e2); else - *e = vcc_expr_edit(f3, "(\v1/\v2)", *e, e2); + *e = vcc_expr_edit((*e)->fmt, "(\v1/\v2)", *e, e2); } } @@ -930,8 +930,10 @@ vcc_expr_add(struct vcc *tl, struct expr **e, vcc_type_t fmt) * ExprAdd Relation ExprAdd * ExprAdd(STRING) '~' CString * ExprAdd(STRING) '!~' CString - * ExprAdd(IP) '~' IP - * ExprAdd(IP) '!~' IP + * ExprAdd(IP) '==' ExprAdd(IP) + * ExprAdd(IP) '!=' ExprAdd(IP) + * ExprAdd(IP) '~' ACL + * ExprAdd(IP) '!~' ACL */ struct cmps; @@ -941,8 +943,8 @@ typedef void cmp_f(struct vcc *, struct expr **, const struct cmps *); struct cmps { vcc_type_t fmt; unsigned token; - const char *emit; cmp_f *func; + const char *emit; }; static void v_matchproto_(cmp_f) @@ -957,6 +959,8 @@ cmp_simple(struct vcc *tl, struct expr **e, const struct cmps *cp) vcc_expr_tostring(tl, e, STRING); vcc_expr_add(tl, &e2, (*e)->fmt); ERRCHK(tl); + if (e2->fmt == STRING_LIST) + vcc_expr_tostring(tl, &e2, STRING); if (e2->fmt != (*e)->fmt) { /* XXX */ VSB_printf(tl->sb, "Comparison of different types: "); @@ -1001,17 +1005,16 @@ cmp_acl(struct vcc *tl, struct expr **e, const struct cmps *cp) *e = vcc_expr_edit(BOOL, buf, *e, NULL); } -#define IDENT_REL(typ) \ - {typ, T_EQ, "(\v1 == \v2)", cmp_simple }, \ - {typ, T_NEQ, "(\v1 != \v2)", cmp_simple } +#define IDENT_REL(typ) \ + {typ, T_EQ, cmp_simple, "(\v1 == \v2)" }, \ + {typ, T_NEQ, cmp_simple, "(\v1 != \v2)" } -#define NUM_REL(typ) \ - {typ, T_EQ, "(\v1 == \v2)", cmp_simple }, \ - {typ, T_NEQ, "(\v1 != \v2)", cmp_simple }, \ - {typ, T_LEQ, "(\v1 <= \v2)", cmp_simple }, \ - {typ, T_GEQ, "(\v1 >= \v2)", cmp_simple }, \ - {typ, '<', "(\v1 < \v2)", cmp_simple }, \ - {typ, '>', "(\v1 > \v2)", cmp_simple } +#define NUM_REL(typ) \ + IDENT_REL(typ), \ + {typ, T_LEQ, cmp_simple, "(\v1 <= \v2)" }, \ + {typ, T_GEQ, cmp_simple, "(\v1 >= \v2)" }, \ + {typ, '<', cmp_simple, "(\v1 < \v2)" }, \ + {typ, '>', cmp_simple, "(\v1 > \v2)" } static const struct cmps vcc_cmps[] = { NUM_REL(INT), @@ -1026,23 +1029,26 @@ static const struct cmps vcc_cmps[] = { IDENT_REL(SUB), IDENT_REL(INSTANCE), - {IP, T_EQ, "!VRT_ipcmp(\v1, \v2)", cmp_simple }, - {IP, T_NEQ, "VRT_ipcmp(\v1, \v2)", cmp_simple }, - {IP, '~', "", cmp_acl }, - {IP, T_NOMATCH, "!", cmp_acl }, + {IP, T_EQ, cmp_simple, "!VRT_ipcmp(\v1, \v2)" }, + {IP, T_NEQ, cmp_simple, "VRT_ipcmp(\v1, \v2)" }, + + {IP, '~', cmp_acl, "" }, + {IP, T_NOMATCH, cmp_acl, "!" }, + + {STRING, T_EQ, cmp_simple, "!VRT_strcmp(\v1, \v2)" }, + {STRING_LIST, T_EQ, cmp_simple, "!VRT_strcmp(\v1, \v2)" }, + {STRING, T_NEQ, cmp_simple, "VRT_strcmp(\v1, \v2)" }, + {STRING_LIST, T_NEQ, cmp_simple, "VRT_strcmp(\v1, \v2)" }, - {STRING, T_EQ, "!VRT_strcmp(\v1, \v2)", cmp_simple }, - {STRING_LIST, T_EQ, "!VRT_strcmp(\v1, \v2)", cmp_simple }, - {STRING, T_NEQ, "VRT_strcmp(\v1, \v2)", cmp_simple }, - {STRING_LIST, T_NEQ, "VRT_strcmp(\v1, \v2)", cmp_simple }, - {STRING, '~', "", cmp_regexp }, - {STRING_LIST, '~', "", cmp_regexp }, - {STRING, T_NOMATCH, "!", cmp_regexp }, - {STRING_LIST, T_NOMATCH, "!", cmp_regexp }, + {STRING, '~', cmp_regexp, "" }, + {STRING_LIST, '~', cmp_regexp, "" }, + {STRING, T_NOMATCH, cmp_regexp, "!" }, + {STRING_LIST, T_NOMATCH, cmp_regexp, "!" }, {VOID, 0, NULL, NULL} }; +#undef IDENT_REL #undef NUM_REL static void @@ -1052,21 +1058,21 @@ vcc_expr_cmp(struct vcc *tl, struct expr **e, vcc_type_t fmt) struct token *tk; *e = NULL; - vcc_expr_add(tl, e, fmt); ERRCHK(tl); + tk = tl->t; if ((*e)->fmt == BOOL) return; - tk = tl->t; - for (cp = vcc_cmps; cp->fmt != VOID; cp++) - if ((*e)->fmt == cp->fmt && tl->t->tok == cp->token) - break; - if (cp->func != NULL) { - cp->func(tl, e, cp); - return; + for (cp = vcc_cmps; cp->fmt != VOID; cp++) { + if ((*e)->fmt == cp->fmt && tl->t->tok == cp->token) { + AN(cp->func); + cp->func(tl, e, cp); + return; + } } + switch (tk->tok) { case T_EQ: case T_NEQ: @@ -1115,13 +1121,13 @@ vcc_expr_not(struct vcc *tl, struct expr **e, vcc_type_t fmt) tk = tl->t; vcc_expr_cmp(tl, &e2, fmt); ERRCHK(tl); - if (e2->fmt == BOOL) { + if (e2->fmt != BOOL) { + VSB_printf(tl->sb, "'!' must be followed by BOOL, found "); + VSB_printf(tl->sb, "%s.\n", vcc_utype(e2->fmt)); + vcc_ErrWhere2(tl, tk, tl->t); + } else { *e = vcc_expr_edit(BOOL, "!(\v1)", e2, NULL); - return; } - VSB_printf(tl->sb, "'!' must be followed by BOOL, found "); - VSB_printf(tl->sb, "%s.\n", vcc_utype(e2->fmt)); - vcc_ErrWhere2(tl, tk, tl->t); } /*-------------------------------------------------------------------- @@ -1161,12 +1167,12 @@ vcc_expr_cand(struct vcc *tl, struct expr **e, vcc_type_t fmt) /*-------------------------------------------------------------------- * SYNTAX: - * Expr1: + * ExprCOR: * ExprCand { '||' ExprCand } * */ static void -vcc_expr1(struct vcc *tl, struct expr **e, vcc_type_t fmt) +vcc_expr_cor(struct vcc *tl, struct expr **e, vcc_type_t fmt) { struct expr *e2; struct token *tk; @@ -1174,28 +1180,24 @@ vcc_expr1(struct vcc *tl, struct expr **e, vcc_type_t fmt) *e = NULL; vcc_expr_cand(tl, e, fmt); ERRCHK(tl); - if ((*e)->fmt == BOOL && tl->t->tok == T_COR) { - *e = vcc_expr_edit(BOOL, "(\v+\n\v1", *e, NULL); - while (tl->t->tok == T_COR) { - vcc_NextToken(tl); - tk = tl->t; - vcc_expr_cand(tl, &e2, fmt); - ERRCHK(tl); - if (e2->fmt != BOOL) { - VSB_printf(tl->sb, - "'||' must be followed by BOOL," - " found %s.\n", vcc_utype(e2->fmt)); - vcc_ErrWhere2(tl, tk, tl->t); - return; - } - *e = vcc_expr_edit(BOOL, "\v1\v-\n||\v+\n\v2", *e, e2); - } - *e = vcc_expr_edit(BOOL, "\v1\v-\n)", *e, NULL); - } - if (fmt != (*e)->fmt && (fmt == STRING || fmt == STRING_LIST)) { - vcc_expr_tostring(tl, e, fmt); + if ((*e)->fmt != BOOL || tl->t->tok != T_COR) + return; + *e = vcc_expr_edit(BOOL, "(\v+\n\v1", *e, NULL); + while (tl->t->tok == T_COR) { + vcc_NextToken(tl); + tk = tl->t; + vcc_expr_cand(tl, &e2, fmt); ERRCHK(tl); + if (e2->fmt != BOOL) { + VSB_printf(tl->sb, + "'||' must be followed by BOOL," + " found %s.\n", vcc_utype(e2->fmt)); + vcc_ErrWhere2(tl, tk, tl->t); + return; + } + *e = vcc_expr_edit(BOOL, "\v1\v-\n||\v+\n\v2", *e, e2); } + *e = vcc_expr_edit(BOOL, "\v1\v-\n)", *e, NULL); } /*-------------------------------------------------------------------- @@ -1208,10 +1210,15 @@ vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt) { struct token *t1; + *e = NULL; assert(fmt != VOID); t1 = tl->t; - vcc_expr1(tl, e, fmt); + vcc_expr_cor(tl, e, fmt); ERRCHK(tl); + if (fmt != (*e)->fmt && (fmt == STRING || fmt == STRING_LIST)) { + vcc_expr_tostring(tl, e, fmt); + ERRCHK(tl); + } if (fmt != (*e)->fmt) { VSB_printf(tl->sb, "Expression has type %s, expected %s\n", vcc_utype((*e)->fmt), vcc_utype(fmt)); From phk at FreeBSD.org Wed Dec 13 10:45:12 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Wed, 13 Dec 2017 10:45:12 +0000 (UTC) Subject: [master] 6f6242b Rework VCC implementation of strings. Message-ID: <20171213104512.DFE2896DD7@lists.varnish-cache.org> commit 6f6242be57227ff0646b1909ebc185cb232a6ad3 Author: Poul-Henning Kamp Date: Wed Dec 13 10:43:25 2017 +0000 Rework VCC implementation of strings. Add a new type "STRINGS" which is internal to vcc_expr.c only, and convert to "STRING" and "STRING_LIST" at the edge of vcc_expr.c and as necessary inside. (More to come.) Various and sundry cleanups along the way. diff --git a/lib/libvcc/generate.py b/lib/libvcc/generate.py index f1cb87f..398b658 100755 --- a/lib/libvcc/generate.py +++ b/lib/libvcc/generate.py @@ -834,7 +834,8 @@ stv_variables = ( # VCL to C type conversion vcltypes = { - 'STRING_LIST': "void*", + 'STRINGS': "void", + 'STRING_LIST': "void*", 'SUB': "void*", } diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h index bade028..47d8525 100644 --- a/lib/libvcc/vcc_compile.h +++ b/lib/libvcc/vcc_compile.h @@ -39,7 +39,6 @@ #include "vqueue.h" #include "vsb.h" - #include "vcc_token_defs.h" #ifndef NULL diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c index eb9a3e6..7ad4bb0 100644 --- a/lib/libvcc/vcc_expr.c +++ b/lib/libvcc/vcc_expr.c @@ -26,7 +26,6 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * XXX: add VRT_count()'s */ #include "config.h" @@ -48,7 +47,9 @@ struct expr { #define EXPR_CONST (1<<1) #define EXPR_STR_CONST (1<<2) // Last STRING_LIST elem is "..." struct token *t1, *t2; + int nstr; }; + /*-------------------------------------------------------------------- * Facility for carrying expressions around and do text-processing on * them. @@ -61,11 +62,18 @@ vcc_isconst(const struct expr *e) return (e->constant & EXPR_CONST); } +static inline int +vcc_islit(const struct expr *e) +{ + AN(e->constant); + return (e->constant & EXPR_STR_CONST); +} + static const char * vcc_utype(vcc_type_t t) { - if (t == STRING_LIST) - return (STRING->name); + if (t == STRINGS || t == STRING_LIST) + t = STRING; return (t->name); } @@ -73,31 +81,25 @@ static void vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt); static void vcc_expr_cor(struct vcc *tl, struct expr **e, vcc_type_t fmt); static struct expr * -vcc_new_expr(void) +vcc_new_expr(vcc_type_t fmt) { struct expr *e; - /* XXX: use TlAlloc() ? */ ALLOC_OBJ(e, EXPR_MAGIC); AN(e); e->vsb = VSB_new_auto(); - e->fmt = VOID; + e->fmt = fmt; e->constant = EXPR_VAR; return (e); } -static struct expr * -vcc_mk_expr(vcc_type_t fmt, const char *str, ...) - v_printflike_(2, 3); - -static struct expr * +static struct expr * v_printflike_(2, 3) vcc_mk_expr(vcc_type_t fmt, const char *str, ...) { va_list ap; struct expr *e; - e = vcc_new_expr(); - e->fmt = fmt; + e = vcc_new_expr(fmt); va_start(ap, str); VSB_vprintf(e->vsb, str, ap); va_end(ap); @@ -126,6 +128,7 @@ vcc_delete_expr(struct expr *e) * We use '\v' as the magic escape character. * \v1 insert subexpression 1 * \v2 insert subexpression 2 + * \vS insert subexpression 1(STRINGS) as STRING * \v+ increase indentation * \v- decrease indentation * anything else is literal @@ -144,7 +147,7 @@ vcc_expr_edit(vcc_type_t fmt, const char *p, struct expr *e1, int nl = 1; AN(e1); - e = vcc_new_expr(); + e = vcc_new_expr(fmt); while (*p != '\0') { if (*p != '\v') { if (*p != '\n' || !nl) @@ -157,6 +160,16 @@ vcc_expr_edit(vcc_type_t fmt, const char *p, struct expr *e1, switch (*++p) { case '+': VSB_cat(e->vsb, "\v+"); break; case '-': VSB_cat(e->vsb, "\v-"); break; + case 'S': + assert(e1->fmt == STRINGS); + if (e1->nstr > 1) + VSB_cat(e->vsb, + "\nVRT_CollectString(ctx,\v+\n"); + VSB_cat(e->vsb, VSB_data(e1->vsb)); + if (e1->nstr > 1) + VSB_cat(e->vsb, + ",\nvrt_magic_string_end)\v-\n"); + break; case '1': VSB_cat(e->vsb, VSB_data(e1->vsb)); break; @@ -176,7 +189,6 @@ vcc_expr_edit(vcc_type_t fmt, const char *p, struct expr *e1, e->t2 = e2->t2; vcc_delete_expr(e1); vcc_delete_expr(e2); - e->fmt = fmt; return (e); } @@ -196,26 +208,20 @@ vcc_expr_fmt(struct vsb *d, int ind, const struct expr *e1) while (*p != '\0') { if (*p == '\n') { VSB_putc(d, '\n'); - if (p[1] != '\0') { - for (i = 0; i < ind; i++) - VSB_cat(d, " "); + if (++p == '\0') + break; + for (i = 0; i < ind; i++) + VSB_cat(d, " "); + } else if (*p != '\v') { + VSB_putc(d, *p++); + } else { + switch (*++p) { + case '+': ind += 2; break; + case '-': ind -= 2; break; + default: WRONG("Illegal format in VCC expression"); } p++; - continue; - } - if (*p != '\v') { - VSB_putc(d, *p); - p++; - continue; } - p++; - switch (*p) { - case '+': ind += 2; break; - case '-': ind -= 2; break; - default: - WRONG("Illegal format in VCC expression"); - } - p++; } } @@ -229,33 +235,26 @@ vcc_expr_tostring(struct vcc *tl, struct expr **e, vcc_type_t fmt) uint8_t constant = EXPR_VAR; CHECK_OBJ_NOTNULL(*e, EXPR_MAGIC); - assert(fmt == STRING || fmt == STRING_LIST); + assert(fmt == STRINGS || fmt == STRING_LIST || fmt == STRING); assert(fmt != (*e)->fmt); - if ((*e)->fmt == STRING || - ((*e)->fmt == STRING_LIST && vcc_isconst(*e))) { - (*e)->fmt = fmt; - return; - } p = (*e)->fmt->tostring; - if (p == NULL && (*e)->fmt == BLOB) { - VSB_printf(tl->sb, - "Wrong use of BLOB value.\n" - "BLOBs can only be used as arguments to VMOD" - " functions.\n"); - vcc_ErrWhere2(tl, (*e)->t1, tl->t); - return; - } - if (p == NULL) { - VSB_printf(tl->sb, - "Cannot convert %s to STRING.\n", vcc_utype((*e)->fmt)); - vcc_ErrWhere2(tl, (*e)->t1, tl->t); - return; - } - AN(p); - if (*p != '\0') { + if (p != NULL) { + AN(*p); *e = vcc_expr_edit(fmt, p, *e, NULL); (*e)->constant = constant; + (*e)->nstr = 1; + } else { + if ((*e)->fmt == BLOB) + VSB_printf(tl->sb, + "Wrong use of BLOB value.\n" + "BLOBs can only be used as arguments to VMOD" + " functions.\n"); + else + VSB_printf(tl->sb, + "Cannot convert %s to STRING.\n", + vcc_utype((*e)->fmt)); + vcc_ErrWhere2(tl, (*e)->t1, tl->t); } } @@ -272,25 +271,20 @@ vcc_Eval_Regsub(struct vcc *tl, struct expr **e, const struct symbol *sym, char buf[128]; (void)fmt; - vcc_delete_expr(*e); SkipToken(tl, ID); SkipToken(tl, '('); - vcc_expr0(tl, &e2, STRING); ERRCHK(tl); - SkipToken(tl, ','); ExpectErr(tl, CSTR); p = vcc_regexp(tl); - vcc_NextToken(tl); - bprintf(buf, "VRT_regsub(ctx, %d,\v+\n\v1,\n%s", all, p); *e = vcc_expr_edit(STRING, buf, e2, NULL); - SkipToken(tl, ','); vcc_expr0(tl, &e2, STRING); ERRCHK(tl); - *e = vcc_expr_edit(STRING, "\v1,\n\v2)\v-", *e, e2); + *e = vcc_expr_edit(STRINGS, "\v1,\n\v2)\v-", *e, e2); + (*e)->nstr = 1; SkipToken(tl, ')'); } @@ -318,14 +312,19 @@ vcc_Eval_Handle(struct vcc *tl, struct expr **e, const struct symbol *sym, AN(sym->rname); - if (sym->fmt != STRING && (fmt == STRING || fmt == STRING_LIST)) { - *e = vcc_mk_expr(STRING, "\"%s\"", sym->name); + if (sym->fmt != STRING && fmt == STRINGS) { (void)vcc_AddRef(tl, tl->t, sym->kind); + *e = vcc_mk_expr(STRINGS, "\"%s\"", sym->name); + (*e)->nstr = 1; + (*e)->constant |= EXPR_CONST | EXPR_STR_CONST; } else { vcc_ExpectVid(tl, "handle"); (void)vcc_AddRef(tl, tl->t, sym->kind); *e = vcc_mk_expr(sym->fmt, "%s", sym->rname); - (*e)->constant = EXPR_VAR; /* XXX ? */ + (*e)->constant = EXPR_VAR; + (*e)->nstr = 1; + if ((*e)->fmt == STRING) + (*e)->fmt = STRINGS; } vcc_NextToken(tl); } @@ -343,6 +342,10 @@ vcc_Eval_Var(struct vcc *tl, struct expr **e, const struct symbol *sym, vcc_AddUses(tl, tl->t, sym->r_methods, "Not available"); ERRCHK(tl); *e = vcc_mk_expr(sym->fmt, "%s", sym->rname); + (*e)->constant = EXPR_VAR; + (*e)->nstr = 1; + if ((*e)->fmt == STRING) + (*e)->fmt = STRINGS; vcc_NextToken(tl); } @@ -551,11 +554,8 @@ vcc_func(struct vcc *tl, struct expr **e, const char *spec, } free(fa); } - e1 = vcc_expr_edit(e1->fmt, "\v1\n)\v-", e1, NULL); - *e = e1; - + *e = vcc_expr_edit(e1->fmt, "\v1\n)\v-", e1, NULL); SkipToken(tl, ')'); - } /*-------------------------------------------------------------------- @@ -589,6 +589,11 @@ vcc_Eval_SymFunc(struct vcc *tl, struct expr **e, const struct symbol *sym, SkipToken(tl, ID); assert(sym->fmt == VCC_Type(sym->eval_priv)); vcc_func(tl, e, sym->eval_priv, sym->extra, sym); + ERRCHK(tl); + if ((*e)->fmt == STRING) { + (*e)->fmt = STRINGS; + (*e)->nstr = 1; + } } /*-------------------------------------------------------------------- @@ -617,13 +622,10 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt) vcc_expr_cor(tl, &e2, fmt); ERRCHK(tl); SkipToken(tl, ')'); - if (e2->fmt == STRING_LIST) { + if (e2->fmt == STRINGS) *e = e2; - if (fmt == STRING) - vcc_expr_tostring(tl, e, STRING); - } else { + else *e = vcc_expr_edit(e2->fmt, "(\v1)", e2, NULL); - } return; } switch (tl->t->tok) { @@ -665,7 +667,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt) ERRCHK(tl); /* Unless asked for a HEADER, fold to string here */ if (*e && fmt != HEADER && (*e)->fmt == HEADER) { - vcc_expr_tostring(tl, e, STRING); + vcc_expr_tostring(tl, e, STRINGS); ERRCHK(tl); } return; @@ -687,13 +689,11 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt) e1 = vcc_mk_expr(IP, "%s", ip); ERRCHK(tl); } else { - e1 = vcc_new_expr(); + e1 = vcc_new_expr(STRINGS); EncToken(e1->vsb, tl->t); - e1->fmt = STRING; AZ(VSB_finish(e1->vsb)); e1->constant |= EXPR_STR_CONST; - if (fmt == STRING_LIST) - e1->fmt = fmt; + e1->nstr = 1; } e1->t1 = tl->t; e1->constant |= EXPR_CONST; @@ -774,9 +774,8 @@ vcc_expr_mul(struct vcc *tl, struct expr **e, vcc_type_t fmt) vcc_expr4(tl, &e2, f2); ERRCHK(tl); if (e2->fmt != INT && e2->fmt != f2) { - VSB_printf(tl->sb, - "%s %.*s %s not possible.\n", - vcc_utype(f2), PF(tk), vcc_utype(e2->fmt)); + VSB_printf(tl->sb, "%s %.*s %s not possible.\n", + vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt)); vcc_ErrWhere(tl, tk); return; } @@ -791,45 +790,8 @@ vcc_expr_mul(struct vcc *tl, struct expr **e, vcc_type_t fmt) * SYNTAX: * ExprAdd: * ExprMul { {'+'|'-'} ExprMul } * - * - * For reasons of memory allocation/copying and general performance, - * STRINGs in VCL are quite special. Addition/concatenation is split - * into it's own subfunction to encapsulate this. */ -static void -vcc_expr_string_add(struct vcc *tl, struct expr **e, struct expr *e2) -{ - vcc_type_t f2; - - AN(e); - AN(*e); - AN(e2); - f2 = (*e)->fmt; - assert (f2 == STRING || f2 == STRING_LIST); - - while (e2 != NULL || tl->t->tok == '+') { - if (e2 == NULL) { - vcc_NextToken(tl); - vcc_expr_mul(tl, &e2, f2); - } - ERRCHK(tl); - if (e2->fmt != STRING && e2->fmt != STRING_LIST) - vcc_expr_tostring(tl, &e2, f2); - ERRCHK(tl); - assert(e2->fmt == STRING || e2->fmt == STRING_LIST); - - if (((*e)->constant & EXPR_STR_CONST) && vcc_isconst(e2)) { - *e = vcc_expr_edit((*e)->fmt, "\v1\n\v2", *e, e2); - (*e)->constant = EXPR_CONST | EXPR_STR_CONST; - } else { - *e = vcc_expr_edit(STRING_LIST, "\v1,\n\v2", *e, e2); - (*e)->constant = EXPR_VAR; - } - e2 = NULL; - } -} - static const struct adds { unsigned op; vcc_type_t a; @@ -852,7 +814,7 @@ static const struct adds { { '+', TIME, DURATION, TIME }, { '-', TIME, DURATION, TIME }, - { EOI, VOID, VOID, VOID } + { EOI, VOID, VOID, VOID } }; static void @@ -860,66 +822,59 @@ vcc_expr_add(struct vcc *tl, struct expr **e, vcc_type_t fmt) { const struct adds *ap; struct expr *e2; - vcc_type_t f2; struct token *tk; - char buf[128]; + int n; *e = NULL; vcc_expr_mul(tl, e, fmt); ERRCHK(tl); - if (tl->t->tok != '+' && tl->t->tok != '-') - return; - - f2 = (*e)->fmt; - for (ap = vcc_adds; ap->op != EOI; ap++) - if (ap->a == f2 && ap->op == tl->t->tok) - break; - - if (ap->op == EOI && - (fmt == STRING || fmt == STRING_LIST) && - f2 != STRING && f2 != STRING_LIST) { - vcc_expr_tostring(tl, e, fmt); - f2 = (*e)->fmt; - } - while (tl->t->tok == '+' || tl->t->tok == '-') { tk = tl->t; + for (ap = vcc_adds; ap->op != EOI; ap++) + if (tk->tok == ap->op && (*e)->fmt == ap->a) + break; vcc_NextToken(tl); - vcc_expr_mul(tl, &e2, f2); + if (ap->op == EOI && fmt == STRINGS) + vcc_expr_mul(tl, &e2, STRINGS); + else + vcc_expr_mul(tl, &e2, (*e)->fmt); ERRCHK(tl); - for (ap = vcc_adds; ap->op != EOI; ap++) { + for (ap = vcc_adds; ap->op != EOI; ap++) if (tk->tok == ap->op && (*e)->fmt == ap->a && e2->fmt == ap->b) break; - } - if (ap->fmt != VOID) { - bprintf(buf, "(\v1 %c \v2)", ap->op); - *e = vcc_expr_edit(ap->fmt, buf, *e, e2); - continue; - } - - if (tk->tok == '+' && ap->op == EOI) { - if ((*e)->fmt == STRING && e2->fmt == STRING) { - vcc_expr_string_add(tl, e, e2); - return; - } - - if (fmt == STRING || fmt == STRING_LIST) { - /* Time to fold and add as string */ - if ((*e)->fmt != fmt) - vcc_expr_tostring(tl, e, fmt); - vcc_expr_string_add(tl, e, e2); - return; + if (ap->op == '+') { + *e = vcc_expr_edit(ap->fmt, "(\v1 + \v2)", *e, e2); + } else if (ap->op == '-') { + *e = vcc_expr_edit(ap->fmt, "(\v1 - \v2)", *e, e2); + } else if (tk->tok == '+' && + ((*e)->fmt == STRINGS || fmt == STRINGS)) { + if ((*e)->fmt != STRINGS) + vcc_expr_tostring(tl, e, STRINGS); + if (e2->fmt != STRINGS) + vcc_expr_tostring(tl, &e2, STRINGS); + if (vcc_islit(*e) && vcc_isconst(e2)) { + *e = vcc_expr_edit(STRINGS, + "\v1\n\v2", *e, e2); + (*e)->constant = EXPR_CONST; + if (vcc_islit(e2)) + (*e)->constant |= EXPR_STR_CONST; + } else { + n = (*e)->nstr + e2->nstr; + *e = vcc_expr_edit(STRINGS, + "\v1,\n\v2", *e, e2); + (*e)->constant = EXPR_VAR; + (*e)->nstr = n; } + } else { + VSB_printf(tl->sb, "%s %.*s %s not possible.\n", + vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt)); + vcc_ErrWhere2(tl, tk, tl->t); + return; } - - VSB_printf(tl->sb, "%s %.*s %s not possible.\n", - vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt)); - vcc_ErrWhere2(tl, tk, tl->t); - return; } } @@ -955,22 +910,16 @@ cmp_simple(struct vcc *tl, struct expr **e, const struct cmps *cp) tk = tl->t; vcc_NextToken(tl); - if ((*e)->fmt == STRING_LIST) - vcc_expr_tostring(tl, e, STRING); vcc_expr_add(tl, &e2, (*e)->fmt); ERRCHK(tl); - if (e2->fmt == STRING_LIST) - vcc_expr_tostring(tl, &e2, STRING); - - if (e2->fmt != (*e)->fmt) { /* XXX */ - VSB_printf(tl->sb, "Comparison of different types: "); - VSB_printf(tl->sb, "%s ", vcc_utype((*e)->fmt)); - vcc_ErrToken(tl, tk); - VSB_printf(tl->sb, " %s\n", vcc_utype(e2->fmt)); + + if (e2->fmt != (*e)->fmt) { + VSB_printf(tl->sb, + "Comparison of different types: %s '%.*s' %s\n", + vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt)); vcc_ErrWhere(tl, tk); - return; - } - *e = vcc_expr_edit(BOOL, cp->emit, *e, e2); + } else + *e = vcc_expr_edit(BOOL, cp->emit, *e, e2); } static void v_matchproto_(cmp_f) @@ -979,13 +928,11 @@ cmp_regexp(struct vcc *tl, struct expr **e, const struct cmps *cp) char buf[128]; const char *re; - if ((*e)->fmt != STRING) - vcc_expr_tostring(tl, e, STRING); + *e = vcc_expr_edit(STRING, "\vS", *e, NULL); vcc_NextToken(tl); ExpectErr(tl, CSTR); re = vcc_regexp(tl); ERRCHK(tl); - vcc_NextToken(tl); bprintf(buf, "%sVRT_re_match(ctx, \v1, %s)", cp->emit, re); *e = vcc_expr_edit(BOOL, buf, *e, NULL); } @@ -1005,6 +952,28 @@ cmp_acl(struct vcc *tl, struct expr **e, const struct cmps *cp) *e = vcc_expr_edit(BOOL, buf, *e, NULL); } +static void v_matchproto_(cmp_f) +cmp_string(struct vcc *tl, struct expr **e, const struct cmps *cp) +{ + struct expr *e2; + struct token *tk; + + tk = tl->t; + vcc_NextToken(tl); + vcc_expr_add(tl, &e2, STRINGS); + ERRCHK(tl); + if (e2->fmt != STRINGS) { + VSB_printf(tl->sb, + "Comparison of different types: %s '%.*s' %s\n", + vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt)); + vcc_ErrWhere(tl, tk); + } else { + *e = vcc_expr_edit(STRING, "\vS", *e, NULL); + e2 = vcc_expr_edit(STRING, "\vS", e2, NULL); + *e = vcc_expr_edit(BOOL, cp->emit, *e, e2); + } +} + #define IDENT_REL(typ) \ {typ, T_EQ, cmp_simple, "(\v1 == \v2)" }, \ {typ, T_NEQ, cmp_simple, "(\v1 != \v2)" } @@ -1035,17 +1004,13 @@ static const struct cmps vcc_cmps[] = { {IP, '~', cmp_acl, "" }, {IP, T_NOMATCH, cmp_acl, "!" }, - {STRING, T_EQ, cmp_simple, "!VRT_strcmp(\v1, \v2)" }, - {STRING_LIST, T_EQ, cmp_simple, "!VRT_strcmp(\v1, \v2)" }, - {STRING, T_NEQ, cmp_simple, "VRT_strcmp(\v1, \v2)" }, - {STRING_LIST, T_NEQ, cmp_simple, "VRT_strcmp(\v1, \v2)" }, + {STRINGS, T_EQ, cmp_string, "!VRT_strcmp(\v1, \v2)" }, + {STRINGS, T_NEQ, cmp_string, "VRT_strcmp(\v1, \v2)" }, - {STRING, '~', cmp_regexp, "" }, - {STRING_LIST, '~', cmp_regexp, "" }, - {STRING, T_NOMATCH, cmp_regexp, "!" }, - {STRING_LIST, T_NOMATCH, cmp_regexp, "!" }, + {STRINGS, '~', cmp_regexp, "" }, + {STRINGS, T_NOMATCH, cmp_regexp, "!" }, - {VOID, 0, NULL, NULL} + {VOID, 0, NULL, NULL} }; #undef IDENT_REL @@ -1091,10 +1056,12 @@ vcc_expr_cmp(struct vcc *tl, struct expr **e, vcc_type_t fmt) } if (fmt != BOOL) return; - if ((*e)->fmt == STRING || (*e)->fmt == BACKEND || (*e)->fmt == INT) + if ((*e)->fmt == BACKEND || (*e)->fmt == INT) *e = vcc_expr_edit(BOOL, "(\v1 != 0)", *e, NULL); else if ((*e)->fmt == DURATION) *e = vcc_expr_edit(BOOL, "(\v1 > 0)", *e, NULL); + else if ((*e)->fmt == STRINGS) + *e = vcc_expr_edit(BOOL, "(\vS != 0)", *e, NULL); else INCOMPL(); } @@ -1210,25 +1177,34 @@ vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt) { struct token *t1; - *e = NULL; assert(fmt != VOID); + assert(fmt != STRINGS); + *e = NULL; t1 = tl->t; - vcc_expr_cor(tl, e, fmt); + if (fmt == STRING_LIST || fmt == STRING) + vcc_expr_cor(tl, e, STRINGS); + else + vcc_expr_cor(tl, e, fmt); ERRCHK(tl); - if (fmt != (*e)->fmt && (fmt == STRING || fmt == STRING_LIST)) { + assert((*e)->fmt != STRING_LIST && (*e)->fmt != STRING); + + if ((*e)->fmt == STRINGS && fmt == STRING_LIST) + (*e)->fmt = STRING_LIST; + else if ((*e)->fmt == STRINGS && fmt == STRING) + *e = vcc_expr_edit(STRING, "\vS", *e, NULL); + else if ((*e)->fmt != STRINGS && (fmt == STRING || fmt == STRING_LIST)) vcc_expr_tostring(tl, e, fmt); - ERRCHK(tl); - } - if (fmt != (*e)->fmt) { - VSB_printf(tl->sb, "Expression has type %s, expected %s\n", - vcc_utype((*e)->fmt), vcc_utype(fmt)); - tl->err = 1; - } + if ((*e)->fmt == STRING_LIST) *e = vcc_expr_edit(STRING_LIST, "\v+\n\v1,\nvrt_magic_string_end\v-", *e, NULL); - if (tl->err) + + if (fmt != (*e)->fmt) { + VSB_printf(tl->sb, "Expression has type %s, expected %s\n", + vcc_utype((*e)->fmt), vcc_utype(fmt)); vcc_ErrWhere2(tl, t1, tl->t); + return; + } } /*-------------------------------------------------------------------- @@ -1244,6 +1220,7 @@ vcc_Expr(struct vcc *tl, vcc_type_t fmt) struct expr *e = NULL; assert(fmt != VOID); + assert(fmt != STRINGS); vcc_expr0(tl, &e, fmt); ERRCHK(tl); vcc_expr_fmt(tl->fb, tl->indent, e); diff --git a/lib/libvcc/vcc_types.c b/lib/libvcc/vcc_types.c index 00a2198..cb446c8 100644 --- a/lib/libvcc/vcc_types.c +++ b/lib/libvcc/vcc_types.c @@ -134,10 +134,15 @@ const struct type STRING[1] = {{ .tostring = "", }}; +const struct type STRINGS[1] = {{ + .magic = TYPE_MAGIC, + .name = "STRINGS", + .tostring = "", +}}; + const struct type STRING_LIST[1] = {{ .magic = TYPE_MAGIC, .name = "STRING_LIST", - .tostring = "VRT_CollectString(ctx,\n\v1,\nvrt_magic_string_end)", }}; const struct type SUB[1] = {{ diff --git a/lib/libvcc/vcc_utils.c b/lib/libvcc/vcc_utils.c index 8d83897..a793c62 100644 --- a/lib/libvcc/vcc_utils.c +++ b/lib/libvcc/vcc_utils.c @@ -73,6 +73,7 @@ vcc_regexp(struct vcc *tl) EncToken(ifp->ini, tl->t); VSB_printf(ifp->ini, ");"); VSB_printf(ifp->fin, "\t\tVRT_re_fini(%s);", buf); + vcc_NextToken(tl); return (p); } From phk at FreeBSD.org Thu Dec 14 10:16:04 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Thu, 14 Dec 2017 10:16:04 +0000 (UTC) Subject: [master] b317d95 Introduce VCL_STRANDS, and use it for string compare. Message-ID: <20171214101604.E1628B3652@lists.varnish-cache.org> commit b317d959cc797221ece4127896b305d30204f58f Author: Poul-Henning Kamp Date: Thu Dec 14 10:12:15 2017 +0000 Introduce VCL_STRANDS, and use it for string compare. VCL_STRANDS is an alternative to VCL_STRING_LIST which uses a struct instead of varargs. This means that multiple VCL_STRANDS can be passed to a function, and string-compare really needed that to not waste workspace. Add <, >, <=, >= string comparisons while here anyway. The struct and a const char *[N] array are built on the stack and they are only valid for the duration of the function call. diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c index 3d0952f..9adc590 100644 --- a/bin/varnishd/cache/cache_vrt.c +++ b/bin/varnishd/cache/cache_vrt.c @@ -157,6 +157,64 @@ VRT_GetHdr(VRT_CTX, const struct gethdr_s *hs) } /*-------------------------------------------------------------------- + * Build STRANDS from what is essentially a STRING_LIST + */ + +VCL_STRANDS +VRT_BundleStrands(int n, struct strands *s, char const **d, const char *f, ...) +{ + va_list ap; + + s->n = n; + s->p = d; + *d++ = f; + va_start(ap, f); + while(--n) + *d++ = va_arg(ap, const char *); + assert(va_arg(ap, const char *) == vrt_magic_string_end); + va_end(ap); + return (s); +} + +/*-------------------------------------------------------------------- + * Compare two STRANDS + */ + +int +VRT_CompareStrands(VCL_STRANDS a, VCL_STRANDS b) +{ + const char *pa = NULL, *pb = NULL; + int na = 0, nb = 0; + + while (1) { + if (pa != NULL && *pa == '\0') + pa = NULL; + if (pb != NULL && *pb == '\0') + pb = NULL; + if (pa == NULL && na < a->n) + pa = a->p[na++]; + else if (pb == NULL && nb < b->n) + pb = b->p[nb++]; + else if (pa == NULL && pb == NULL) + return (0); + else if (pa == NULL) + return (-1); + else if (pb == NULL) + return (1); + else if (*pa == '\0') + pa = NULL; + else if (*pb == '\0') + pb = NULL; + else if (*pa != *pb) + return (*pa - *pb); + else { + pa++; + pb++; + } + } +} + +/*-------------------------------------------------------------------- * Collapse a STRING_LIST in the space provided, or return NULL */ @@ -341,7 +399,7 @@ VRT_r_now(VRT_CTX) /*--------------------------------------------------------------------*/ -char * +VCL_STRING v_matchproto_() VRT_IP_string(VRT_CTX, VCL_IP ip) { char *p; @@ -361,7 +419,7 @@ VRT_IP_string(VRT_CTX, VCL_IP ip) return (p); } -char * +VCL_STRING v_matchproto_() VRT_INT_string(VRT_CTX, long num) { @@ -369,7 +427,7 @@ VRT_INT_string(VRT_CTX, long num) return (WS_Printf(ctx->ws, "%ld", num)); } -char * +VCL_STRING v_matchproto_() VRT_REAL_string(VRT_CTX, double num) { @@ -377,7 +435,7 @@ VRT_REAL_string(VRT_CTX, double num) return (WS_Printf(ctx->ws, "%.3f", num)); } -char * +VCL_STRING v_matchproto_() VRT_TIME_string(VRT_CTX, double t) { char *p; @@ -389,7 +447,7 @@ VRT_TIME_string(VRT_CTX, double t) return (p); } -const char * v_matchproto_() +VCL_STRING v_matchproto_() VRT_BACKEND_string(VCL_BACKEND d) { if (d == NULL) @@ -398,7 +456,7 @@ VRT_BACKEND_string(VCL_BACKEND d) return (d->vcl_name); } -const char * +VCL_STRING v_matchproto_() VRT_BOOL_string(unsigned val) { diff --git a/bin/varnishtest/tests/a00015.vtc b/bin/varnishtest/tests/a00015.vtc index 03caf19..843637f 100644 --- a/bin/varnishtest/tests/a00015.vtc +++ b/bin/varnishtest/tests/a00015.vtc @@ -12,7 +12,7 @@ server s1 { txresp -hdr "Content-Type: text/plain" -body response } -start -varnish v1 -vcl+backend {} -start +varnish v1 -vcl+backend {} -start -cliok "param.set debug +syncvsl" client c1 { txreq -req POST -hdr "Content-Type: text/plain" -body request diff --git a/bin/varnishtest/tests/v00002.vtc b/bin/varnishtest/tests/v00002.vtc new file mode 100644 index 0000000..48d914e --- /dev/null +++ b/bin/varnishtest/tests/v00002.vtc @@ -0,0 +1,174 @@ +varnishtest "Test VCL STRINGS/STRANDS comparisons" + +server s1 { + rxreq + txresp +} -start + +varnish v1 -vcl+backend { + sub vcl_deliver { + set resp.http.test = req.http.test; + + set resp.http.eq = + req.http.foo == req.http.bar; + + set resp.http.neq = + req.http.foo != req.http.bar; + + set resp.http.lt = + req.http.foo < req.http.bar; + + set resp.http.le = + req.http.foo <= req.http.bar; + + set resp.http.gt = + req.http.foo > req.http.bar; + + set resp.http.ge = + req.http.foo >= req.http.bar; + } +} -start + +client c1 { + txreq -hdr "foo: 1" -hdr "bar: 1" -hdr "test: 1" + rxresp + expect resp.http.eq == true + expect resp.http.neq == false + expect resp.http.lt == false + expect resp.http.le == true + expect resp.http.gt == false + expect resp.http.ge == true + + txreq -hdr "foo: 1" -hdr "bar: 2" -hdr "test: 2" + rxresp + expect resp.http.eq == false + expect resp.http.neq == true + expect resp.http.lt == true + expect resp.http.le == true + expect resp.http.gt == false + expect resp.http.ge == false + + txreq -hdr "foo: 2" -hdr "bar: 1" -hdr "test: 3" + rxresp + expect resp.http.eq == false + expect resp.http.neq == true + expect resp.http.lt == false + expect resp.http.le == false + expect resp.http.gt == true + expect resp.http.ge == true + + txreq -hdr "foo: 1" -hdr "bar: 11" -hdr "test: 4" + rxresp + expect resp.http.eq == false + expect resp.http.neq == true + expect resp.http.lt == true + expect resp.http.le == true + expect resp.http.gt == false + expect resp.http.ge == false + + txreq -hdr "foo: 11" -hdr "bar: 1" -hdr "test: 5" + rxresp + expect resp.http.eq == false + expect resp.http.neq == true + expect resp.http.lt == false + expect resp.http.le == false + expect resp.http.gt == true + expect resp.http.ge == true + + txreq -hdr "foo:" -hdr "bar:" -hdr "test: 6" + rxresp + expect resp.http.eq == true + expect resp.http.neq == false + expect resp.http.lt == false + expect resp.http.le == true + expect resp.http.gt == false + expect resp.http.ge == true + + txreq -hdr "foo:" -hdr "bar: 1" -hdr "test: 7" + rxresp + expect resp.http.eq == false + expect resp.http.neq == true + expect resp.http.lt == true + expect resp.http.le == true + expect resp.http.gt == false + expect resp.http.ge == false + +} -run + +varnish v1 -vsl_catchup -vcl+backend { + sub vcl_deliver { + set resp.http.test = req.http.test; + + set resp.http.eq = + req.http.foo + " " == req.http.bar + " "; + + set resp.http.neq = + req.http.foo + " " != req.http.bar + " "; + + set resp.http.lt = + req.http.foo + " " < req.http.bar + " "; + + set resp.http.le = + req.http.foo + " " <= req.http.bar + " "; + + set resp.http.gt = + req.http.foo + " " > req.http.bar + " "; + + set resp.http.ge = + req.http.foo + " " >= req.http.bar + " "; + } +} + +client c1 -run + +varnish v1 -vsl_catchup -vcl+backend { + sub vcl_deliver { + set resp.http.test = req.http.test; + + set resp.http.eq = + req.http.foo == req.http.bar + req.http.not; + + set resp.http.neq = + req.http.foo != req.http.bar + req.http.not; + + set resp.http.lt = + req.http.foo < req.http.bar + req.http.not; + + set resp.http.le = + req.http.foo <= req.http.bar + req.http.not; + + set resp.http.gt = + req.http.foo > req.http.bar + req.http.not; + + set resp.http.ge = + req.http.foo >= req.http.bar + req.http.not; + } +} + +client c1 -run + +varnish v1 -vsl_catchup -vcl+backend { + sub vcl_deliver { + set resp.http.test = req.http.test; + + set resp.http.eq = + req.http.not + req.http.foo == req.http.bar + req.http.not; + + set resp.http.neq = + req.http.not + req.http.foo != req.http.bar + req.http.not; + + set resp.http.lt = + req.http.not + req.http.foo < req.http.bar + req.http.not; + + set resp.http.le = + req.http.not + req.http.foo <= req.http.bar + req.http.not; + + set resp.http.gt = + req.http.not + req.http.foo > req.http.bar + req.http.not; + + set resp.http.ge = + req.http.not + req.http.foo >= req.http.bar + req.http.not; + } +} + +client c1 -run diff --git a/include/vrt.h b/include/vrt.h index 0a78bd1..12e0375 100644 --- a/include/vrt.h +++ b/include/vrt.h @@ -61,6 +61,7 @@ * VRT_r_beresp_storage_hint() removed - under discussion #2509 * VRT_l_beresp_storage_hint() removed - under discussion #2509 * VRT_blob() added + * VCL_STRANDS added * 6.1 (2017-09-15 aka 5.2) * http_CollectHdrSep added * VRT_purge modified (may fail a transaction, signature changed) @@ -114,6 +115,11 @@ struct vsb; struct vsl_log; struct ws; +struct strands { + int n; + const char **p; +}; + /*********************************************************************** * This is the central definition of the mapping from VCL types to * C-types. The python scripts read these from here. @@ -136,6 +142,7 @@ typedef const struct suckaddr * VCL_IP; typedef const struct vrt_backend_probe * VCL_PROBE; typedef double VCL_REAL; typedef const struct stevedore * VCL_STEVEDORE; +typedef const struct strands * VCL_STRANDS; typedef const char * VCL_STRING; typedef double VCL_TIME; typedef struct vcl * VCL_VCL; @@ -421,14 +428,19 @@ VCL_STEVEDORE VRT_stevedore(const char *nm); /* Convert things to string */ -char *VRT_IP_string(VRT_CTX, VCL_IP); -char *VRT_INT_string(VRT_CTX, VCL_INT); -char *VRT_REAL_string(VRT_CTX, VCL_REAL); -char *VRT_TIME_string(VRT_CTX, VCL_TIME); -const char *VRT_BOOL_string(VCL_BOOL); -const char *VRT_BACKEND_string(VCL_BACKEND); -const char *VRT_STEVEDORE_string(VCL_STEVEDORE); -const char *VRT_CollectString(VRT_CTX, const char *p, ...); +VCL_STRANDS VRT_BundleStrands(int, struct strands *, char const **, + const char *f, ...); +int VRT_CompareStrands(VCL_STRANDS a, VCL_STRANDS b); + +VCL_STRING VRT_BACKEND_string(VCL_BACKEND); +VCL_STRING VRT_BOOL_string(VCL_BOOL); +VCL_STRING VRT_CollectString(VRT_CTX, const char *p, ...); +VCL_STRING VRT_INT_string(VRT_CTX, VCL_INT); +VCL_STRING VRT_IP_string(VRT_CTX, VCL_IP); +VCL_STRING VRT_REAL_string(VRT_CTX, VCL_REAL); +VCL_STRING VRT_STEVEDORE_string(VCL_STEVEDORE); +VCL_STRING VRT_STRANDS_string(VCL_STRANDS); +VCL_STRING VRT_TIME_string(VRT_CTX, VCL_TIME); #ifdef va_start // XXX: hackish void *VRT_VSC_Alloc(const char *, size_t, size_t, const unsigned char *, size_t, diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c index 7ad4bb0..742ca21 100644 --- a/lib/libvcc/vcc_expr.c +++ b/lib/libvcc/vcc_expr.c @@ -129,6 +129,8 @@ vcc_delete_expr(struct expr *e) * \v1 insert subexpression 1 * \v2 insert subexpression 2 * \vS insert subexpression 1(STRINGS) as STRING + * \vT insert subexpression 1(STRINGS) as STRANDS + * \vt insert subexpression 1(STRINGS) as STRANDS * \v+ increase indentation * \v- decrease indentation * anything else is literal @@ -140,10 +142,10 @@ vcc_delete_expr(struct expr *e) */ static struct expr * -vcc_expr_edit(vcc_type_t fmt, const char *p, struct expr *e1, +vcc_expr_edit(struct vcc *tl, vcc_type_t fmt, const char *p, struct expr *e1, struct expr *e2) { - struct expr *e; + struct expr *e, *e3; int nl = 1; AN(e1); @@ -161,15 +163,33 @@ vcc_expr_edit(vcc_type_t fmt, const char *p, struct expr *e1, case '+': VSB_cat(e->vsb, "\v+"); break; case '-': VSB_cat(e->vsb, "\v-"); break; case 'S': + case 's': + e3 = (*p == 'S' ? e1 : e2); + AN(e3); assert(e1->fmt == STRINGS); - if (e1->nstr > 1) + if (e3->nstr > 1) VSB_cat(e->vsb, "\nVRT_CollectString(ctx,\v+\n"); - VSB_cat(e->vsb, VSB_data(e1->vsb)); - if (e1->nstr > 1) + VSB_cat(e->vsb, VSB_data(e3->vsb)); + if (e3->nstr > 1) VSB_cat(e->vsb, ",\nvrt_magic_string_end)\v-\n"); break; + case 'T': + case 't': + e3 = (*p == 'T' ? e1 : e2); + AN(e3); + VSB_printf(tl->curproc->prologue, + " struct strands strs_%u_a;\n" + " const char * strs_%u_s[%d];\n", + tl->unique, tl->unique, e3->nstr); + VSB_printf(e->vsb, + "\v+\nVRT_BundleStrands(%d, &strs_%u_a, strs_%u_s," + "\v+\n%s,\nvrt_magic_string_end)\v-\v-", + e3->nstr, tl->unique, tl->unique, + VSB_data(e3->vsb)); + tl->unique++; + break; case '1': VSB_cat(e->vsb, VSB_data(e1->vsb)); break; @@ -208,7 +228,7 @@ vcc_expr_fmt(struct vsb *d, int ind, const struct expr *e1) while (*p != '\0') { if (*p == '\n') { VSB_putc(d, '\n'); - if (++p == '\0') + if (*++p == '\0') break; for (i = 0; i < ind; i++) VSB_cat(d, " "); @@ -241,7 +261,7 @@ vcc_expr_tostring(struct vcc *tl, struct expr **e, vcc_type_t fmt) p = (*e)->fmt->tostring; if (p != NULL) { AN(*p); - *e = vcc_expr_edit(fmt, p, *e, NULL); + *e = vcc_expr_edit(tl, fmt, p, *e, NULL); (*e)->constant = constant; (*e)->nstr = 1; } else { @@ -279,11 +299,11 @@ vcc_Eval_Regsub(struct vcc *tl, struct expr **e, const struct symbol *sym, ExpectErr(tl, CSTR); p = vcc_regexp(tl); bprintf(buf, "VRT_regsub(ctx, %d,\v+\n\v1,\n%s", all, p); - *e = vcc_expr_edit(STRING, buf, e2, NULL); + *e = vcc_expr_edit(tl, STRING, buf, e2, NULL); SkipToken(tl, ','); vcc_expr0(tl, &e2, STRING); ERRCHK(tl); - *e = vcc_expr_edit(STRINGS, "\v1,\n\v2)\v-", *e, e2); + *e = vcc_expr_edit(tl, STRINGS, "\v1,\n\v2)\v-", *e, e2); (*e)->nstr = 1; SkipToken(tl, ')'); } @@ -545,7 +565,7 @@ vcc_func(struct vcc *tl, struct expr **e, const char *spec, if (fa->result == NULL && fa->val != NULL) fa->result = vcc_mk_expr(fa->type, "%s", fa->val); if (fa->result != NULL) - e1 = vcc_expr_edit(e1->fmt, "\v1,\n\v2", + e1 = vcc_expr_edit(tl, e1->fmt, "\v1,\n\v2", e1, fa->result); else { VSB_printf(tl->sb, "Argument '%s' missing\n", @@ -554,7 +574,7 @@ vcc_func(struct vcc *tl, struct expr **e, const char *spec, } free(fa); } - *e = vcc_expr_edit(e1->fmt, "\v1\n)\v-", e1, NULL); + *e = vcc_expr_edit(tl, e1->fmt, "\v1\n)\v-", e1, NULL); SkipToken(tl, ')'); } @@ -625,7 +645,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt) if (e2->fmt == STRINGS) *e = e2; else - *e = vcc_expr_edit(e2->fmt, "(\v1)", e2, NULL); + *e = vcc_expr_edit(tl, e2->fmt, "(\v1)", e2, NULL); return; } switch (tl->t->tok) { @@ -780,9 +800,9 @@ vcc_expr_mul(struct vcc *tl, struct expr **e, vcc_type_t fmt) return; } if (tk->tok == '*') - *e = vcc_expr_edit((*e)->fmt, "(\v1*\v2)", *e, e2); + *e = vcc_expr_edit(tl, (*e)->fmt, "(\v1*\v2)", *e, e2); else - *e = vcc_expr_edit((*e)->fmt, "(\v1/\v2)", *e, e2); + *e = vcc_expr_edit(tl, (*e)->fmt, "(\v1/\v2)", *e, e2); } } @@ -847,9 +867,9 @@ vcc_expr_add(struct vcc *tl, struct expr **e, vcc_type_t fmt) break; if (ap->op == '+') { - *e = vcc_expr_edit(ap->fmt, "(\v1 + \v2)", *e, e2); + *e = vcc_expr_edit(tl, ap->fmt, "(\v1 + \v2)", *e, e2); } else if (ap->op == '-') { - *e = vcc_expr_edit(ap->fmt, "(\v1 - \v2)", *e, e2); + *e = vcc_expr_edit(tl, ap->fmt, "(\v1 - \v2)", *e, e2); } else if (tk->tok == '+' && ((*e)->fmt == STRINGS || fmt == STRINGS)) { if ((*e)->fmt != STRINGS) @@ -857,14 +877,14 @@ vcc_expr_add(struct vcc *tl, struct expr **e, vcc_type_t fmt) if (e2->fmt != STRINGS) vcc_expr_tostring(tl, &e2, STRINGS); if (vcc_islit(*e) && vcc_isconst(e2)) { - *e = vcc_expr_edit(STRINGS, + *e = vcc_expr_edit(tl, STRINGS, "\v1\n\v2", *e, e2); (*e)->constant = EXPR_CONST; if (vcc_islit(e2)) (*e)->constant |= EXPR_STR_CONST; } else { n = (*e)->nstr + e2->nstr; - *e = vcc_expr_edit(STRINGS, + *e = vcc_expr_edit(tl, STRINGS, "\v1,\n\v2", *e, e2); (*e)->constant = EXPR_VAR; (*e)->nstr = n; @@ -919,7 +939,7 @@ cmp_simple(struct vcc *tl, struct expr **e, const struct cmps *cp) vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt)); vcc_ErrWhere(tl, tk); } else - *e = vcc_expr_edit(BOOL, cp->emit, *e, e2); + *e = vcc_expr_edit(tl, BOOL, cp->emit, *e, e2); } static void v_matchproto_(cmp_f) @@ -928,13 +948,13 @@ cmp_regexp(struct vcc *tl, struct expr **e, const struct cmps *cp) char buf[128]; const char *re; - *e = vcc_expr_edit(STRING, "\vS", *e, NULL); + *e = vcc_expr_edit(tl, STRING, "\vS", *e, NULL); vcc_NextToken(tl); ExpectErr(tl, CSTR); re = vcc_regexp(tl); ERRCHK(tl); bprintf(buf, "%sVRT_re_match(ctx, \v1, %s)", cp->emit, re); - *e = vcc_expr_edit(BOOL, buf, *e, NULL); + *e = vcc_expr_edit(tl, BOOL, buf, *e, NULL); } static void v_matchproto_(cmp_f) @@ -949,7 +969,7 @@ cmp_acl(struct vcc *tl, struct expr **e, const struct cmps *cp) vcc_NextToken(tl); VCC_GlobalSymbol(sym, ACL, ACL_SYMBOL_PREFIX); bprintf(buf, "%sVRT_acl_match(ctx, %s, \v1)", cp->emit, sym->rname); - *e = vcc_expr_edit(BOOL, buf, *e, NULL); + *e = vcc_expr_edit(tl, BOOL, buf, *e, NULL); } static void v_matchproto_(cmp_f) @@ -957,6 +977,7 @@ cmp_string(struct vcc *tl, struct expr **e, const struct cmps *cp) { struct expr *e2; struct token *tk; + char buf[128]; tk = tl->t; vcc_NextToken(tl); @@ -967,10 +988,12 @@ cmp_string(struct vcc *tl, struct expr **e, const struct cmps *cp) "Comparison of different types: %s '%.*s' %s\n", vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt)); vcc_ErrWhere(tl, tk); + } else if ((*e)->nstr == 1 && e2->nstr == 1) { + bprintf(buf, "(%s VRT_strcmp(\v1, \v2))", cp->emit); + *e = vcc_expr_edit(tl, BOOL, buf, *e, e2); } else { - *e = vcc_expr_edit(STRING, "\vS", *e, NULL); - e2 = vcc_expr_edit(STRING, "\vS", e2, NULL); - *e = vcc_expr_edit(BOOL, cp->emit, *e, e2); + bprintf(buf, "(%s VRT_CompareStrands(\vT, \vt))", cp->emit); + *e = vcc_expr_edit(tl, BOOL, buf, *e, e2); } } @@ -1004,8 +1027,12 @@ static const struct cmps vcc_cmps[] = { {IP, '~', cmp_acl, "" }, {IP, T_NOMATCH, cmp_acl, "!" }, - {STRINGS, T_EQ, cmp_string, "!VRT_strcmp(\v1, \v2)" }, - {STRINGS, T_NEQ, cmp_string, "VRT_strcmp(\v1, \v2)" }, + {STRINGS, T_EQ, cmp_string, "0 =="}, + {STRINGS, T_NEQ, cmp_string, "0 !="}, + {STRINGS, '<', cmp_string, "0 > "}, + {STRINGS, '>', cmp_string, "0 < "}, + {STRINGS, T_LEQ, cmp_string, "0 >="}, + {STRINGS, T_GEQ, cmp_string, "0 <="}, {STRINGS, '~', cmp_regexp, "" }, {STRINGS, T_NOMATCH, cmp_regexp, "!" }, @@ -1057,11 +1084,11 @@ vcc_expr_cmp(struct vcc *tl, struct expr **e, vcc_type_t fmt) if (fmt != BOOL) return; if ((*e)->fmt == BACKEND || (*e)->fmt == INT) - *e = vcc_expr_edit(BOOL, "(\v1 != 0)", *e, NULL); + *e = vcc_expr_edit(tl, BOOL, "(\v1 != 0)", *e, NULL); else if ((*e)->fmt == DURATION) - *e = vcc_expr_edit(BOOL, "(\v1 > 0)", *e, NULL); + *e = vcc_expr_edit(tl, BOOL, "(\v1 > 0)", *e, NULL); else if ((*e)->fmt == STRINGS) - *e = vcc_expr_edit(BOOL, "(\vS != 0)", *e, NULL); + *e = vcc_expr_edit(tl, BOOL, "(\vS != 0)", *e, NULL); else INCOMPL(); } @@ -1093,7 +1120,7 @@ vcc_expr_not(struct vcc *tl, struct expr **e, vcc_type_t fmt) VSB_printf(tl->sb, "%s.\n", vcc_utype(e2->fmt)); vcc_ErrWhere2(tl, tk, tl->t); } else { - *e = vcc_expr_edit(BOOL, "!(\v1)", e2, NULL); + *e = vcc_expr_edit(tl, BOOL, "!(\v1)", e2, NULL); } } @@ -1114,7 +1141,7 @@ vcc_expr_cand(struct vcc *tl, struct expr **e, vcc_type_t fmt) ERRCHK(tl); if ((*e)->fmt != BOOL || tl->t->tok != T_CAND) return; - *e = vcc_expr_edit(BOOL, "(\v+\n\v1", *e, NULL); + *e = vcc_expr_edit(tl, BOOL, "(\v+\n\v1", *e, NULL); while (tl->t->tok == T_CAND) { vcc_NextToken(tl); tk = tl->t; @@ -1127,9 +1154,9 @@ vcc_expr_cand(struct vcc *tl, struct expr **e, vcc_type_t fmt) vcc_ErrWhere2(tl, tk, tl->t); return; } - *e = vcc_expr_edit(BOOL, "\v1\v-\n&&\v+\n\v2", *e, e2); + *e = vcc_expr_edit(tl, BOOL, "\v1\v-\n&&\v+\n\v2", *e, e2); } - *e = vcc_expr_edit(BOOL, "\v1\v-\n)", *e, NULL); + *e = vcc_expr_edit(tl, BOOL, "\v1\v-\n)", *e, NULL); } /*-------------------------------------------------------------------- @@ -1149,7 +1176,7 @@ vcc_expr_cor(struct vcc *tl, struct expr **e, vcc_type_t fmt) ERRCHK(tl); if ((*e)->fmt != BOOL || tl->t->tok != T_COR) return; - *e = vcc_expr_edit(BOOL, "(\v+\n\v1", *e, NULL); + *e = vcc_expr_edit(tl, BOOL, "(\v+\n\v1", *e, NULL); while (tl->t->tok == T_COR) { vcc_NextToken(tl); tk = tl->t; @@ -1162,9 +1189,9 @@ vcc_expr_cor(struct vcc *tl, struct expr **e, vcc_type_t fmt) vcc_ErrWhere2(tl, tk, tl->t); return; } - *e = vcc_expr_edit(BOOL, "\v1\v-\n||\v+\n\v2", *e, e2); + *e = vcc_expr_edit(tl, BOOL, "\v1\v-\n||\v+\n\v2", *e, e2); } - *e = vcc_expr_edit(BOOL, "\v1\v-\n)", *e, NULL); + *e = vcc_expr_edit(tl, BOOL, "\v1\v-\n)", *e, NULL); } /*-------------------------------------------------------------------- @@ -1191,12 +1218,15 @@ vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt) if ((*e)->fmt == STRINGS && fmt == STRING_LIST) (*e)->fmt = STRING_LIST; else if ((*e)->fmt == STRINGS && fmt == STRING) - *e = vcc_expr_edit(STRING, "\vS", *e, NULL); - else if ((*e)->fmt != STRINGS && (fmt == STRING || fmt == STRING_LIST)) + *e = vcc_expr_edit(tl, STRING, "\vS", *e, NULL); + else if ((*e)->fmt == STRINGS && fmt == STRANDS) { + *e = vcc_expr_edit(tl, STRANDS, "\vT", (*e), NULL); + } else if ((*e)->fmt != STRINGS && + (fmt == STRING || fmt == STRING_LIST)) vcc_expr_tostring(tl, e, fmt); if ((*e)->fmt == STRING_LIST) - *e = vcc_expr_edit(STRING_LIST, + *e = vcc_expr_edit(tl, STRING_LIST, "\v+\n\v1,\nvrt_magic_string_end\v-", *e, NULL); if (fmt != (*e)->fmt) { diff --git a/lib/libvcc/vcc_types.c b/lib/libvcc/vcc_types.c index cb446c8..dbeaacb 100644 --- a/lib/libvcc/vcc_types.c +++ b/lib/libvcc/vcc_types.c @@ -131,7 +131,11 @@ const struct type STEVEDORE[1] = {{ const struct type STRING[1] = {{ .magic = TYPE_MAGIC, .name = "STRING", - .tostring = "", +}}; + +const struct type STRANDS[1] = {{ + .magic = TYPE_MAGIC, + .name = "STRANDS", }}; const struct type STRINGS[1] = {{ From phk at FreeBSD.org Thu Dec 14 12:32:04 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Thu, 14 Dec 2017 12:32:04 +0000 (UTC) Subject: [master] e8d8f58 Move this very slow test earlier in the sequence. Message-ID: <20171214123204.97346B5C87@lists.varnish-cache.org> commit e8d8f5886adeb5ae2203b878c19174183da17a68 Author: Poul-Henning Kamp Date: Thu Dec 14 12:31:08 2017 +0000 Move this very slow test earlier in the sequence. diff --git a/bin/varnishtest/tests/v00003.vtc b/bin/varnishtest/tests/v00003.vtc new file mode 100644 index 0000000..ff218f2 --- /dev/null +++ b/bin/varnishtest/tests/v00003.vtc @@ -0,0 +1,94 @@ +varnishtest "vcl.state coverage tests" + +server s1 -repeat 20 { + rxreq + txresp + delay .2 + close +} -start + +# The debug vmod logs temperature vcl events +varnish v1 -arg "-p vcl_cooldown=1" -vcl { + import debug; + backend default { + .host = "${s1_addr}"; + .probe = { .interval = 1s; .initial = 1;} + } +} -start + +# We only have one vcl yet +varnish v1 -expect VBE.vcl1.default.happy >= 0 +varnish v1 -expect !VBE.vcl2.default.happy +varnish v1 -cliok "backend.list -p *.*" + +varnish v1 -vcl { + backend default { + .host = "${s1_addr}"; + .probe = { .interval = 1s; .initial = 1;} + } +} + +# Now we have two vcls (and run on the latest loaded) +delay .4 +varnish v1 -expect VBE.vcl1.default.happy >= 0 +varnish v1 -expect VBE.vcl2.default.happy >= 0 + +# Freeze the first VCL +varnish v1 -cliok "vcl.state vcl1 cold" +delay .4 +varnish v1 -expect !VBE.vcl1.default.happy + +# Set it auto should be a no-op +varnish v1 -cliok "vcl.state vcl1 auto" +delay .4 +varnish v1 -expect !VBE.vcl1.default.happy + +# Use it, and it should come alive +varnish v1 -cliok "vcl.use vcl1" +delay .4 +varnish v1 -expect VBE.vcl1.default.happy >= 0 +varnish v1 -expect VBE.vcl2.default.happy >= 0 + +# and the unused one should go cold +delay 4 +varnish v1 -expect !VBE.vcl2.default.happy + +# Mark the used warm and use the other +varnish v1 -cliok "vcl.state vcl1 warm" +varnish v1 -cliok "vcl.use vcl2" + +# It will stay warm even after the cooldown period +delay 4 +varnish v1 -expect VBE.vcl1.default.happy >= 0 +varnish v1 -expect VBE.vcl2.default.happy >= 0 + +# You can't freeze the active VCL +varnish v1 -clierr 300 "vcl.state vcl2 cold" + +# However a warm event is guaranteed... +logexpect l1 -v v1 -g raw { + expect * 0 Debug "vcl1: VCL_EVENT_COLD" + expect * 0 Debug "vcl1: VCL_EVENT_WARM" +} -start + +# ...when you use a cold VCL +varnish v1 -cliok "vcl.state vcl1 cold" +varnish v1 -cliok "vcl.use vcl1" + +logexpect l1 -wait + +# It will apply the cooldown period once inactive +varnish v1 -cliok "vcl.use vcl2" +delay .4 +varnish v1 -expect VBE.vcl1.default.happy >= 0 +delay 4 +varnish v1 -expect !VBE.vcl1.default.happy + +# A VMOD's warm-up can fail +varnish v1 -cliok "param.set max_esi_depth 42" +varnish v1 -clierr 300 "vcl.state vcl1 warm" + +# A warm-up failure can also fail a child start +varnish v1 -cliok stop +varnish v1 -cliok "vcl.state vcl1 warm" +varnish v1 -clierr 300 start diff --git a/bin/varnishtest/tests/v00044.vtc b/bin/varnishtest/tests/v00044.vtc deleted file mode 100644 index ff218f2..0000000 --- a/bin/varnishtest/tests/v00044.vtc +++ /dev/null @@ -1,94 +0,0 @@ -varnishtest "vcl.state coverage tests" - -server s1 -repeat 20 { - rxreq - txresp - delay .2 - close -} -start - -# The debug vmod logs temperature vcl events -varnish v1 -arg "-p vcl_cooldown=1" -vcl { - import debug; - backend default { - .host = "${s1_addr}"; - .probe = { .interval = 1s; .initial = 1;} - } -} -start - -# We only have one vcl yet -varnish v1 -expect VBE.vcl1.default.happy >= 0 -varnish v1 -expect !VBE.vcl2.default.happy -varnish v1 -cliok "backend.list -p *.*" - -varnish v1 -vcl { - backend default { - .host = "${s1_addr}"; - .probe = { .interval = 1s; .initial = 1;} - } -} - -# Now we have two vcls (and run on the latest loaded) -delay .4 -varnish v1 -expect VBE.vcl1.default.happy >= 0 -varnish v1 -expect VBE.vcl2.default.happy >= 0 - -# Freeze the first VCL -varnish v1 -cliok "vcl.state vcl1 cold" -delay .4 -varnish v1 -expect !VBE.vcl1.default.happy - -# Set it auto should be a no-op -varnish v1 -cliok "vcl.state vcl1 auto" -delay .4 -varnish v1 -expect !VBE.vcl1.default.happy - -# Use it, and it should come alive -varnish v1 -cliok "vcl.use vcl1" -delay .4 -varnish v1 -expect VBE.vcl1.default.happy >= 0 -varnish v1 -expect VBE.vcl2.default.happy >= 0 - -# and the unused one should go cold -delay 4 -varnish v1 -expect !VBE.vcl2.default.happy - -# Mark the used warm and use the other -varnish v1 -cliok "vcl.state vcl1 warm" -varnish v1 -cliok "vcl.use vcl2" - -# It will stay warm even after the cooldown period -delay 4 -varnish v1 -expect VBE.vcl1.default.happy >= 0 -varnish v1 -expect VBE.vcl2.default.happy >= 0 - -# You can't freeze the active VCL -varnish v1 -clierr 300 "vcl.state vcl2 cold" - -# However a warm event is guaranteed... -logexpect l1 -v v1 -g raw { - expect * 0 Debug "vcl1: VCL_EVENT_COLD" - expect * 0 Debug "vcl1: VCL_EVENT_WARM" -} -start - -# ...when you use a cold VCL -varnish v1 -cliok "vcl.state vcl1 cold" -varnish v1 -cliok "vcl.use vcl1" - -logexpect l1 -wait - -# It will apply the cooldown period once inactive -varnish v1 -cliok "vcl.use vcl2" -delay .4 -varnish v1 -expect VBE.vcl1.default.happy >= 0 -delay 4 -varnish v1 -expect !VBE.vcl1.default.happy - -# A VMOD's warm-up can fail -varnish v1 -cliok "param.set max_esi_depth 42" -varnish v1 -clierr 300 "vcl.state vcl1 warm" - -# A warm-up failure can also fail a child start -varnish v1 -cliok stop -varnish v1 -cliok "vcl.state vcl1 warm" -varnish v1 -clierr 300 start From phk at FreeBSD.org Thu Dec 14 12:35:07 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Thu, 14 Dec 2017 12:35:07 +0000 (UTC) Subject: [master] 385bed9 Make VCL_STRANDS available to VMOD writers. Message-ID: <20171214123507.7164BB5D24@lists.varnish-cache.org> commit 385bed9d5c7dacec177ab98503cef482bd0420ca Author: Poul-Henning Kamp Date: Thu Dec 14 12:34:15 2017 +0000 Make VCL_STRANDS available to VMOD writers. diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py index 50bfea3..c57f96e 100755 --- a/lib/libvcc/vmodtool.py +++ b/lib/libvcc/vmodtool.py @@ -110,6 +110,7 @@ ctypes = { 'PROBE': "VCL_PROBE", 'REAL': "VCL_REAL", 'STEVEDORE': "VCL_STEVEDORE", + 'STRANDS': "VCL_STRANDS", 'STRING': "VCL_STRING", 'STRING_LIST': "const char *, ...", 'TIME': "VCL_TIME", From hermunn at varnish-software.com Thu Dec 14 13:41:06 2017 From: hermunn at varnish-software.com (PÃ¥l Hermunn Johansen) Date: Thu, 14 Dec 2017 13:41:06 +0000 (UTC) Subject: [4.1] fd089d6 PPC requires a larger file storage Message-ID: <20171214134107.07D30B6E6F@lists.varnish-cache.org> commit fd089d6fbfc6be62a5c1e798815a1e1242ebc88e Author: Martin Blix Grydeland Date: Thu Nov 16 13:39:06 2017 +0100 PPC requires a larger file storage I'm guessing this is due to rounding. All test cases involving file stevedore has a minimum 10m file in the test, was silly to attempt a smaller one in this test. Fixes: #2496 diff --git a/bin/varnishtest/tests/r02429.vtc b/bin/varnishtest/tests/r02429.vtc index 02c8450..81e42f0 100644 --- a/bin/varnishtest/tests/r02429.vtc +++ b/bin/varnishtest/tests/r02429.vtc @@ -4,7 +4,7 @@ server s1 { accept } -start -varnish v1 -arg "-s Transient=file,${tmpdir}/_.file,1m" -vcl+backend { +varnish v1 -arg "-s Transient=file,${tmpdir}/_.file,10m" -vcl+backend { sub vcl_backend_error { synthetic("foo"); return (deliver); From hermunn at varnish-software.com Thu Dec 14 14:08:06 2017 From: hermunn at varnish-software.com (PÃ¥l Hermunn Johansen) Date: Thu, 14 Dec 2017 14:08:06 +0000 (UTC) Subject: [4.1] f364d4a Specify that time is in seconds Message-ID: <20171214140806.A8AB5B7584@lists.varnish-cache.org> commit f364d4aab7795a5bbe805fc5de8918abf366d3b7 Author: Federico G. Schwindt Date: Thu Oct 12 07:46:30 2017 +0100 Specify that time is in seconds Addresses #2456 in a different way. diff --git a/doc/sphinx/reference/varnishncsa.rst b/doc/sphinx/reference/varnishncsa.rst index 708989d..5744810 100644 --- a/doc/sphinx/reference/varnishncsa.rst +++ b/doc/sphinx/reference/varnishncsa.rst @@ -151,9 +151,10 @@ Supported formatters are: Extended variables. Supported variables are: Varnish:time_firstbyte - Time from when the request processing starts until the first byte - is sent to the client. For backend mode: Time from the request was - sent to the backend to the entire header had been received. + Time from when the request processing starts until the first + byte is sent to the client, in seconds. For backend mode: Time + from the request was sent to the backend to the entire header + had been received. Varnish:hitmiss Whether the request was a cache hit or miss. Pipe and pass are From dridi at varni.sh Thu Dec 14 16:38:28 2017 From: dridi at varni.sh (Dridi Boukelmoune) Date: Thu, 14 Dec 2017 17:38:28 +0100 Subject: [master] 3ad1666 Remove the test of varnishtest -i with an empty argument. In-Reply-To: <20171023182011.854F5A542A@lists.varnish-cache.org> References: <20171023182011.854F5A542A@lists.varnish-cache.org> Message-ID: Hi! On Mon, Oct 23, 2017 at 8:20 PM, Geoff Simmons wrote: > > commit 3ad16662cda0510a88a04fe86f264156583b8f20 > Author: Geoff Simmons > Date: Mon Oct 23 20:17:36 2017 +0200 > > Remove the test of varnishtest -i with an empty argument. > > Getting the quoting right to pass along the empty string in SunOS > is not working. You can get all the quoting you want it won't work, because bug ;) > The code path is tested in vsl_glob_test. I have a workaround if we want to revive this check, let me know. Dridi > diff --git a/bin/varnishtest/tests/u00006.vtc b/bin/varnishtest/tests/u00006.vtc > index 24f69ca..8dcb2f9 100644 > --- a/bin/varnishtest/tests/u00006.vtc > +++ b/bin/varnishtest/tests/u00006.vtc > @@ -38,8 +38,6 @@ shell -err -expect {-i: "Resp" is ambiguous} \ > "varnishlog -i Resp" > shell -err -expect {-i: Syntax error in "Re**sp"} \ > "varnishlog -i Re**sp" > -shell -err -expect {-i: "" matches zero tags} \ > - {varnishlog -i ""} > > shell -err -expect {-I: "foo" matches zero tags} \ > "varnishlog -I foo:bar" > _______________________________________________ > varnish-commit mailing list > varnish-commit at varnish-cache.org > https://www.varnish-cache.org/lists/mailman/listinfo/varnish-commit From geoff at uplex.de Thu Dec 14 17:27:12 2017 From: geoff at uplex.de (Geoff Simmons) Date: Thu, 14 Dec 2017 18:27:12 +0100 Subject: [master] 3ad1666 Remove the test of varnishtest -i with an empty argument. In-Reply-To: References: <20171023182011.854F5A542A@lists.varnish-cache.org> Message-ID: On 12/14/2017 05:38 PM, Dridi Boukelmoune wrote: > I have a workaround if we want to revive this check, let me know. Well, what does the workaround do? The way I see it personally, we should automatically test as much of the code as we can, but if we do in fact test that path adequately with the vsl_glob_test, it doesn't seem urgent to restore the vtc test. IIRC we were trying to get VTEST back to green, since some of the tests were failing with disturbing consistency. One of them, I think it was this one, resulted in the process table on the SunOS system being filled up with varnishtest zombies, which eventually led almost all of the tests failing. I remember spending a full day fighting with the shell quoting, until we finally gave up, and really don't want to have to do that again. But if there's a nice workaround that avoids the trouble, well sure. Best, Geoff -- ** * * UPLEX - Nils Goroll Systemoptimierung Scheffelstra?e 32 22301 Hamburg Tel +49 40 2880 5731 Mob +49 176 636 90917 Fax +49 40 42949753 http://uplex.de -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: OpenPGP digital signature URL: From dridi at varni.sh Thu Dec 14 18:24:46 2017 From: dridi at varni.sh (Dridi Boukelmoune) Date: Thu, 14 Dec 2017 19:24:46 +0100 Subject: [master] 3ad1666 Remove the test of varnishtest -i with an empty argument. In-Reply-To: References: <20171023182011.854F5A542A@lists.varnish-cache.org> Message-ID: On Thu, Dec 14, 2017 at 6:27 PM, Geoff Simmons wrote: > > On 12/14/2017 05:38 PM, Dridi Boukelmoune wrote: > > > I have a workaround if we want to revive this check, let me know. > > Well, what does the workaround do? Adds more arguments to the command line, only the last empty arg[s] are accidentally stripped by libtool (and only on SunOS to my knowledge). +shell -err -expect {-i: "" matches zero tags} \ + {varnishlog -i "" -g unreachable} > The way I see it personally, we should automatically test as much of the > code as we can, but if we do in fact test that path adequately with the > vsl_glob_test, it doesn't seem urgent to restore the vtc test. Testing from the outside ensures we catch usage regressions though. >From the command line today: $ varnishlog -i "" -g unreachable -i: "" matches zero tags > IIRC we were trying to get VTEST back to green, since some of the tests > were failing with disturbing consistency. > > One of them, I think it was this one, resulted in the process table on > the SunOS system being filled up with varnishtest zombies, which > eventually led almost all of the tests failing. That's a different problem. > I remember spending a full day fighting with the shell quoting, until we > finally gave up, and really don't want to have to do that again. But if > there's a nice workaround that avoids the trouble, well sure. Your mistake was to believe the quoting was wrong, I couldn't buy that the shell working otherwise fine would fail this quoting only in varnishtest. While I was trying to build hitch on different platforms, after utterly failing to run the test suite on SunOS I figured I could revisit this commit instead. Dridi From fgsch at lodoss.net Fri Dec 15 18:44:04 2017 From: fgsch at lodoss.net (Federico G. Schwindt) Date: Fri, 15 Dec 2017 18:44:04 +0000 (UTC) Subject: [master] e06e3bc Fix use-after-free Message-ID: <20171215184404.C5EE7B046B@lists.varnish-cache.org> commit e06e3bc7c7e35e008a6f2f101cfd1c10cb0a5093 Author: Federico G. Schwindt Date: Fri Dec 15 18:30:28 2017 +0000 Fix use-after-free Spotted by ASAN. diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c index 742ca21..affbe68 100644 --- a/lib/libvcc/vcc_expr.c +++ b/lib/libvcc/vcc_expr.c @@ -843,7 +843,7 @@ vcc_expr_add(struct vcc *tl, struct expr **e, vcc_type_t fmt) const struct adds *ap; struct expr *e2; struct token *tk; - int n; + int lit, n; *e = NULL; vcc_expr_mul(tl, e, fmt); @@ -877,10 +877,11 @@ vcc_expr_add(struct vcc *tl, struct expr **e, vcc_type_t fmt) if (e2->fmt != STRINGS) vcc_expr_tostring(tl, &e2, STRINGS); if (vcc_islit(*e) && vcc_isconst(e2)) { + lit = vcc_islit(e2); *e = vcc_expr_edit(tl, STRINGS, "\v1\n\v2", *e, e2); (*e)->constant = EXPR_CONST; - if (vcc_islit(e2)) + if (lit) (*e)->constant |= EXPR_STR_CONST; } else { n = (*e)->nstr + e2->nstr; From fgsch at lodoss.net Sat Dec 16 20:17:06 2017 From: fgsch at lodoss.net (Federico G. Schwindt) Date: Sat, 16 Dec 2017 20:17:06 +0000 (UTC) Subject: [master] 814f2b4 Free some resources on VEV_Destroy Message-ID: <20171216201706.D8E7EA7BF7@lists.varnish-cache.org> commit 814f2b424ef43283afa77d3a60283d72bcaac737 Author: Federico G. Schwindt Date: Sat Dec 16 19:33:28 2017 +0000 Free some resources on VEV_Destroy diff --git a/lib/libvarnish/vev.c b/lib/libvarnish/vev.c index ac69754..25494a2 100644 --- a/lib/libvarnish/vev.c +++ b/lib/libvarnish/vev.c @@ -219,11 +219,11 @@ VEV_Destroy(struct vev_root **evbp) { struct vev_root *evb; - AN(evbp); - evb = *evbp; - *evbp = NULL; - CHECK_OBJ_NOTNULL(evb, VEV_BASE_MAGIC); + TAKE_OBJ_NOTNULL(evb, evbp, VEV_BASE_MAGIC); assert(evb->thread == pthread_self()); + free(evb->pfd); + free(evb->pev); + /* destroy evb->binheap */ evb->magic = 0; free(evb); } From fgsch at lodoss.net Sat Dec 16 20:17:06 2017 From: fgsch at lodoss.net (Federico G. Schwindt) Date: Sat, 16 Dec 2017 20:17:06 +0000 (UTC) Subject: [master] 7c30e2e Ignore more functions Message-ID: <20171216201706.E942EA7BFA@lists.varnish-cache.org> commit 7c30e2eacd2225da58d2d6ad192ee0aa42f34281 Author: Federico G. Schwindt Date: Sat Dec 16 19:34:26 2017 +0000 Ignore more functions diff --git a/tools/lsan.suppr b/tools/lsan.suppr index 85effbc..5cef2ee 100644 --- a/tools/lsan.suppr +++ b/tools/lsan.suppr @@ -13,3 +13,7 @@ leak:VSL_Setup leak:WRK_BgThread # leak:hpack/vhp_gen_hufdec.c +# +leak:binheap_new +# ev +leak:mct_callback From hermunn at varnish-software.com Mon Dec 18 09:23:10 2017 From: hermunn at varnish-software.com (PÃ¥l Hermunn Johansen) Date: Mon, 18 Dec 2017 09:23:10 +0000 (UTC) Subject: [4.1] 23dcf55 Deref the objcore before switching to synth on error. Message-ID: <20171218092310.DB15DA8440@lists.varnish-cache.org> commit 23dcf55bdf6a24cd98f88863b1003b44327a7833 Author: Martin Blix Grydeland Date: Fri Nov 24 13:54:01 2017 +0100 Deref the objcore before switching to synth on error. Also add asserts for the references held in req->objcore and req->stale_oc. The test case for #1807 catches this bug after adding the asserts. Fixes: #2502 diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index a6c4c0b..46e7765 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -121,6 +121,7 @@ cnt_deliver(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(req, REQ_MAGIC); CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC); CHECK_OBJ_NOTNULL(req->objcore->objhead, OBJHEAD_MAGIC); + AZ(req->stale_oc); AN(req->vcl); assert(req->objcore->refcnt > 0); @@ -131,6 +132,7 @@ cnt_deliver(struct worker *wrk, struct req *req) HTTP_Setup(req->resp, req->ws, req->vsl, SLT_RespMethod); if (HTTP_Decode(req->resp, ObjGetattr(req->wrk, req->objcore, OA_HEADERS, NULL))) { + (void)HSH_DerefObjCore(wrk, &req->objcore); req->err_code = 500; req->req_step = R_STP_SYNTH; return (REQ_FSM_MORE); @@ -225,6 +227,8 @@ cnt_deliver(struct worker *wrk, struct req *req) (void)HSH_DerefObjCore(wrk, &req->objcore); http_Teardown(req->resp); + AZ(req->objcore); + AZ(req->stale_oc); return (REQ_FSM_DONE); } @@ -244,6 +248,9 @@ cnt_synth(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + AZ(req->objcore); + AZ(req->stale_oc); + wrk->stats->s_synth++; now = W_TIM_real(wrk); @@ -327,6 +334,7 @@ cnt_fetch(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC); + AZ(req->stale_oc); wrk->stats->s_fetch++; (void)VRB_Ignore(req); @@ -358,6 +366,7 @@ cnt_lookup(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); AZ(req->objcore); + AZ(req->stale_oc); AN(req->vcl); @@ -500,6 +509,7 @@ cnt_miss(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(req, REQ_MAGIC); AN(req->vcl); CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC); + CHECK_OBJ_ORNULL(req->stale_oc, OBJCORE_MAGIC); VCL_miss_method(req->vcl, wrk, req, NULL, NULL); switch (wrk->handling) { @@ -541,6 +551,7 @@ cnt_pass(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(req, REQ_MAGIC); AN(req->vcl); AZ(req->objcore); + AZ(req->stale_oc); VCL_pass_method(req->vcl, wrk, req, NULL, NULL); switch (wrk->handling) { @@ -574,6 +585,8 @@ cnt_pipe(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + AZ(req->objcore); + AZ(req->stale_oc); AN(req->vcl); wrk->stats->s_pipe++; @@ -615,6 +628,8 @@ cnt_restart(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + AZ(req->objcore); + AZ(req->stale_oc); req->director_hint = NULL; if (++req->restarts >= cache_param->max_restarts) { @@ -652,6 +667,7 @@ cnt_recv(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(req, REQ_MAGIC); AN(req->vcl); AZ(req->objcore); + AZ(req->stale_oc); AZ(req->err_code); AZ(isnan(req->t_first)); @@ -762,6 +778,7 @@ cnt_purge(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); AZ(req->objcore); + AZ(req->stale_oc); AN(req->vcl); From hermunn at varnish-software.com Mon Dec 18 09:41:06 2017 From: hermunn at varnish-software.com (PÃ¥l Hermunn Johansen) Date: Mon, 18 Dec 2017 09:41:06 +0000 (UTC) Subject: [4.1] bc993de Update changelog: First 4.1.10 changes Message-ID: <20171218094106.3BB3CA88CE@lists.varnish-cache.org> commit bc993dec9bfe37c43b63cc2c3b68d2dc3f685450 Author: P?l Hermunn Johansen Date: Mon Dec 18 10:35:26 2017 +0100 Update changelog: First 4.1.10 changes diff --git a/doc/changes.rst b/doc/changes.rst index a8ab3c4..e1985b0 100644 --- a/doc/changes.rst +++ b/doc/changes.rst @@ -1,3 +1,26 @@ +================================= +Varnish Cache 4.1.10 (unreleased) +================================= + +Changes since 4.1.9: + +* New counter added: cache_hit_grace (see 2455_) +* Doc: Specify that time_firstbyte is in seconds (see 2456_) + +.. _2455: https://github.com/varnishcache/varnish-cache/pull/2455 +.. _2456: https://github.com/varnishcache/varnish-cache/pull/2456 + +Bugs fixed +---------- + +* 1772_ - Honor first_byte_timeout for recycled backend connections +* 2135_ - Limit Backend Connection retries to a single retry +* 2502_ - objcore reference count leak + +.. _1772: https://github.com/varnishcache/varnish-cache/issues/1772 +.. _2135: https://github.com/varnishcache/varnish-cache/pull/2135 +.. _2502: https://github.com/varnishcache/varnish-cache/issues/2502 + ================================ Varnish Cache 4.1.9 (2017-11-14) ================================ From daghf at varnish-software.com Mon Dec 18 12:51:05 2017 From: daghf at varnish-software.com (Dag Haavi Finstad) Date: Mon, 18 Dec 2017 12:51:05 +0000 (UTC) Subject: [master] 1d4149f H/2: Fail streams with missing :method or :path Message-ID: <20171218125105.B3170ABDDA@lists.varnish-cache.org> commit 1d4149f26e96a866a179ab9a75907230bd9dab84 Author: Dag Haavi Finstad Date: Tue Dec 12 11:23:00 2017 +0100 H/2: Fail streams with missing :method or :path Fixes: #2351 diff --git a/bin/varnishd/http2/cache_http2_proto.c b/bin/varnishd/http2/cache_http2_proto.c index 5dd01c1..89eb620 100644 --- a/bin/varnishd/http2/cache_http2_proto.c +++ b/bin/varnishd/http2/cache_http2_proto.c @@ -536,6 +536,16 @@ h2_end_headers(struct worker *wrk, struct h2_sess *h2, return (H2CE_PROTOCOL_ERROR); //rfc7540,l,1838,1840 } + if (req->http->hd[HTTP_HDR_METHOD].b == NULL) { + VSLb(h2->vsl, SLT_Debug, "Missing :method"); + return (H2SE_PROTOCOL_ERROR); //rfc7540,l,3087,3090 + } + if(req->http->hd[HTTP_HDR_URL].b == NULL) { + VSLb(h2->vsl, SLT_Debug, "Missing :path"); + return (H2SE_PROTOCOL_ERROR); //rfc7540,l,3087,3090 + } + AN(req->http->hd[HTTP_HDR_PROTO].b); + req->req_step = R_STP_TRANSPORT; req->task.func = h2_do_req; req->task.priv = req; diff --git a/bin/varnishtest/tests/r02351.vtc b/bin/varnishtest/tests/r02351.vtc new file mode 100644 index 0000000..d2ee19a --- /dev/null +++ b/bin/varnishtest/tests/r02351.vtc @@ -0,0 +1,45 @@ +varnishtest "#2351: :path/:method error handling" + +server s1 { + rxreq + txresp +} -start + +varnish v1 -vcl+backend {} -start +varnish v1 -cliok "param.set feature +http2" +varnish v1 -cliok "param.set debug +syncvsl" + +client c1 { + # missing everything + stream 1 { + txreq -noadd + rxrst + expect rst.err == PROTOCOL_ERROR + } -run + + # missing :path + stream 3 { + txreq -noadd -hdr ":authority" "example.com" -hdr ":method" "GET" -hdr ":scheme" "http" + rxrst + expect rst.err == PROTOCOL_ERROR + } -run + + # missing :method + stream 5 { + txreq -noadd -hdr ":authority" "example.com" -hdr ":path" "/foo" -hdr ":scheme" "http" + rxrst + expect rst.err == PROTOCOL_ERROR + } -run + + # Duplicate :path + stream 7 { + txreq -noadd -hdr ":path" "/" -hdr ":path" "/foo" -hdr ":method" "GET" -hdr ":authority" "example.com" -hdr ":scheme" "http" + rxrst + expect rst.err == PROTOCOL_ERROR + } -run +} -run + +varnish v1 -expect MEMPOOL.req0.live == 0 +varnish v1 -expect MEMPOOL.req1.live == 0 +varnish v1 -expect MEMPOOL.sess0.live == 0 +varnish v1 -expect MEMPOOL.sess1.live == 0 From guillaume at varnish-software.com Mon Dec 18 15:11:06 2017 From: guillaume at varnish-software.com (Guillaume Quintard) Date: Mon, 18 Dec 2017 15:11:06 +0000 (UTC) Subject: [master] 731f8a2 Be more concise Message-ID: <20171218151106.828FDB3E91@lists.varnish-cache.org> commit 731f8a205eec74ab77e060953470499a671af38f Author: Guillaume Quintard Date: Mon Dec 18 16:10:08 2017 +0100 Be more concise diff --git a/doc/sphinx/reference/varnishd.rst b/doc/sphinx/reference/varnishd.rst index 6992531..463f76c 100644 --- a/doc/sphinx/reference/varnishd.rst +++ b/doc/sphinx/reference/varnishd.rst @@ -295,8 +295,7 @@ The following storage types are available: -s The file backend stores data in a file on disk. The file will be - accessed using mmap. Note that this storage is reset every time ``varnishd`` - starts. + accessed using mmap. Note that this storage provide no cache persistence. The path is mandatory. If path points to a directory, a temporary file will be created in that directory and immediately unlinked. If From nils.goroll at uplex.de Tue Dec 19 16:15:10 2017 From: nils.goroll at uplex.de (Nils Goroll) Date: Tue, 19 Dec 2017 16:15:10 +0000 (UTC) Subject: [master] 5bb52ba Test that vcl-set headers do not get filtered via Connection Message-ID: <20171219161510.1A467B0E96@lists.varnish-cache.org> commit 5bb52ba247286202c339d367f322d572acc62292 Author: Nils Goroll Date: Tue Dec 19 17:11:35 2017 +0100 Test that vcl-set headers do not get filtered via Connection diff --git a/bin/varnishtest/tests/c00016.vtc b/bin/varnishtest/tests/c00016.vtc index 0d285d9..bfe33d4 100644 --- a/bin/varnishtest/tests/c00016.vtc +++ b/bin/varnishtest/tests/c00016.vtc @@ -4,22 +4,28 @@ server s1 { rxreq expect req.url == "/foo" expect req.http.Foo == "bar" + expect req.http.FromVCL == "123" txresp -hdr "Bar: foo" -body "foobar" rxreq expect req.url == "/bar" expect req.http.Foo == + expect req.http.FromVCL == "123" txresp -hdr "Bar: fnry,glyf, FOO ,brok" -hdr "Connection: bar" -body "foobar" } -start -varnish v1 -vcl+backend { } -start +varnish v1 -vcl+backend { + sub vcl_recv { + set req.http.FromVCL = "123"; + } +} -start client c1 { txreq -url "/foo" -hdr "Foo: bar" rxresp expect resp.http.Bar == "foo" - txreq -url "/bar" -hdr "Foo: bar2" -hdr "Connection: foo, close" + txreq -url "/bar" -hdr "Foo: bar2" -hdr "Connection: FromVCL, foo, close" rxresp expect req.http.Bar == } -run From nils.goroll at uplex.de Tue Dec 19 16:15:10 2017 From: nils.goroll at uplex.de (Nils Goroll) Date: Tue, 19 Dec 2017 16:15:10 +0000 (UTC) Subject: [master] c3c5596 break up long lines for legibility Message-ID: <20171219161510.34D77B0E99@lists.varnish-cache.org> commit c3c5596f2c5d0013b60d79827f8054a790e59972 Author: Nils Goroll Date: Tue Dec 19 17:13:37 2017 +0100 break up long lines for legibility diff --git a/bin/varnishtest/tests/c00016.vtc b/bin/varnishtest/tests/c00016.vtc index bfe33d4..847fb87 100644 --- a/bin/varnishtest/tests/c00016.vtc +++ b/bin/varnishtest/tests/c00016.vtc @@ -11,7 +11,9 @@ server s1 { expect req.url == "/bar" expect req.http.Foo == expect req.http.FromVCL == "123" - txresp -hdr "Bar: fnry,glyf, FOO ,brok" -hdr "Connection: bar" -body "foobar" + txresp -hdr "Bar: fnry,glyf, FOO ,brok" \ + -hdr "Connection: bar" \ + -body "foobar" } -start varnish v1 -vcl+backend { @@ -25,13 +27,18 @@ client c1 { rxresp expect resp.http.Bar == "foo" - txreq -url "/bar" -hdr "Foo: bar2" -hdr "Connection: FromVCL, foo, close" + txreq -url "/bar" \ + -hdr "Foo: bar2" \ + -hdr "Connection: FromVCL, foo, close" rxresp expect req.http.Bar == } -run client c1 { - txreq -url "/bar" -hdr "foo: 1" -hdr "Age: 200" -hdr "Connection: Age" + txreq -url "/bar" \ + -hdr "foo: 1" \ + -hdr "Age: 200" \ + -hdr "Connection: Age" rxresp expect resp.status == 400 } -run From phk at FreeBSD.org Wed Dec 20 08:55:11 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Wed, 20 Dec 2017 08:55:11 +0000 (UTC) Subject: [master] 9343c46 Minor API cleanup Message-ID: <20171220085511.1B00E9B0F0@lists.varnish-cache.org> commit 9343c46733943e8fef2f48d346fce79233eabfb3 Author: Poul-Henning Kamp Date: Wed Dec 20 08:43:21 2017 +0000 Minor API cleanup diff --git a/include/vsl_priv.h b/include/vsl_priv.h index 8ac6c66..7ab0606 100644 --- a/include/vsl_priv.h +++ b/include/vsl_priv.h @@ -59,7 +59,7 @@ struct VSL_head { #define VSL_HEAD_MARKER "VSLHEAD1" /* Incr. as version# */ - char marker[VSM_MARKER_LEN]; + char marker[8]; ssize_t segsize; unsigned segment_n; ssize_t offset[VSL_SEGMENTS]; diff --git a/include/vsm_priv.h b/include/vsm_priv.h index 00619fc..9bb3271 100644 --- a/include/vsm_priv.h +++ b/include/vsm_priv.h @@ -34,6 +34,4 @@ #define VSM_MGT_DIRNAME "_.vsm_mgt" #define VSM_CHILD_DIRNAME "_.vsm_child" -#define VSM_MARKER_LEN 8 - #endif /* VSM_PRIV_H_INCLUDED */ From phk at FreeBSD.org Wed Dec 20 08:55:11 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Wed, 20 Dec 2017 08:55:11 +0000 (UTC) Subject: [master] 1d9ba3f Add a (presently constant at zero) offset field to the VSM index. Message-ID: <20171220085511.2BB9E9B0F2@lists.varnish-cache.org> commit 1d9ba3fc12be6fb9ddf9511c51f70f7e06a2c450 Author: Poul-Henning Kamp Date: Wed Dec 20 08:54:02 2017 +0000 Add a (presently constant at zero) offset field to the VSM index. diff --git a/lib/libvarnish/vsmw.c b/lib/libvarnish/vsmw.c index a778599..c36e2d8 100644 --- a/lib/libvarnish/vsmw.c +++ b/lib/libvarnish/vsmw.c @@ -109,7 +109,7 @@ vsmw_write_index(const struct vsmw *vsmw, int fd, const struct vsmwseg *seg) CHECK_OBJ_NOTNULL(vsmw, VSMW_MAGIC); CHECK_OBJ_NOTNULL(seg, VSMWSEG_MAGIC); VSB_clear(vsmw->vsb); - VSB_printf(vsmw->vsb, "%s %zu %s %s\n", + VSB_printf(vsmw->vsb, "%s 0 %zu %s %s\n", seg->fn, seg->len, seg->class, diff --git a/lib/libvarnishapi/vsm.c b/lib/libvarnishapi/vsm.c index 53fb98b..4169a23 100644 --- a/lib/libvarnishapi/vsm.c +++ b/lib/libvarnishapi/vsm.c @@ -156,7 +156,7 @@ vsm_unmapseg(struct vsm_seg *vg) AN(vg->b); AN(vg->e); - sz = strtoul(vg->av[2], NULL, 10); + sz = strtoul(vg->av[3], NULL, 10); assert(sz > 0); ps = getpagesize(); len = RUP2(sz, ps); @@ -468,13 +468,14 @@ vsm_refresh_set2(struct vsm *vd, struct vsm_set *vs, struct vsb *vsb) av = VAV_Parse(p, &ac, 0); p = e + 1; - if (av[0] != NULL || ac < 4 || ac > 5) { + if (av[0] != NULL || ac < 5 || ac > 6) { (void)(vsm_diag(vd, "vsm_refresh_set2: bad index (%d/%s)", ac, av[0])); VAV_Free(av); break; } + xxxassert(!strcmp(av[2], "0")); if (vg == NULL) { ALLOC_OBJ(vg2, VSM_SEG_MAGIC); @@ -487,9 +488,8 @@ vsm_refresh_set2(struct vsm *vd, struct vsm_set *vs, struct vsb *vsb) continue; } - while (vg != NULL && vsm_cmp_av(&vg->av[1], &av[1])) { + while (vg != NULL && vsm_cmp_av(&vg->av[1], &av[1])) vg = VTAILQ_NEXT(vg, list); - } VAV_Free(av); @@ -681,8 +681,8 @@ VSM__itern(struct vsm *vd, struct vsm_fantom *vf) return (0); memset(vf, 0, sizeof *vf); vf->priv = vg2->serial; - vf->class = vg2->av[3]; - vf->ident = vg2->av[4]; + vf->class = vg2->av[4]; + vf->ident = vg2->av[5]; return (1); } @@ -704,8 +704,8 @@ VSM_Map(struct vsm *vd, struct vsm_fantom *vf) return (vsm_diag(vd, "VSM_Map: bad fantom")); assert(vg->serial == vf->priv); - assert(vg->av[3] == vf->class); - assert(vg->av[4] == vf->ident); + assert(vg->av[4] == vf->class); + assert(vg->av[5] == vf->ident); if (vg->b != NULL) { assert(vg->refs > 0); @@ -716,7 +716,7 @@ VSM_Map(struct vsm *vd, struct vsm_fantom *vf) return (0); } - sz = strtoul(vg->av[2], NULL, 10); + sz = strtoul(vg->av[3], NULL, 10); assert(sz > 0); ps = getpagesize(); len = RUP2(sz, ps); From nils.goroll at uplex.de Wed Dec 20 16:54:06 2017 From: nils.goroll at uplex.de (Nils Goroll) Date: Wed, 20 Dec 2017 16:54:06 +0000 (UTC) Subject: [master] 2936d0f start using my license for real Message-ID: <20171220165406.66328A982C@lists.varnish-cache.org> commit 2936d0f086069da62ea47fce484d29aa567536ba Author: Nils Goroll Date: Wed Dec 20 17:50:49 2017 +0100 start using my license for real phk probably has this in a global flexelint config diff --git a/flint.lnt b/flint.lnt index 4727891..94c1239 100644 --- a/flint.lnt +++ b/flint.lnt @@ -37,6 +37,7 @@ -e728 // Symbol ... not explicitly initialized -e737 // Loss of sign in promotion from int to unsigned int -e763 // Redundant declaration for symbol '...' previously declared +-e717 // do ... while(0); -e777 // Testing floats for equality -e785 // Too few initializers for aggregate -e786 // String concatenation within initializer From phk at FreeBSD.org Wed Dec 20 20:34:06 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Wed, 20 Dec 2017 20:34:06 +0000 (UTC) Subject: [master] a417bf6 Trade space for time in setting up VSC segments. Message-ID: <20171220203406.81795AF492@lists.varnish-cache.org> commit a417bf6fcb78b418865fec874cc8211ac63828cc Author: Poul-Henning Kamp Date: Wed Dec 20 20:30:13 2017 +0000 Trade space for time in setting up VSC segments. Originally it was the plan that the JSON would be gzip'ed in the VSM, but to avoid exposing VGZ in the API we didn't, but kept the gzip'ed JSON in the generated VSC code because why not? Well now we know why not: It wastes a lot of time for very little space, in particular if you have many backends. Provides some relief for: #2513 & #2518 diff --git a/bin/varnishd/common/common_vsc.c b/bin/varnishd/common/common_vsc.c index 9379f2d..ce07893 100644 --- a/bin/varnishd/common/common_vsc.c +++ b/bin/varnishd/common/common_vsc.c @@ -41,7 +41,6 @@ #include "miniobj.h" #include "vas.h" #include "vend.h" -#include "vgz.h" #include "vmb.h" #include "vsmw.h" #include "vqueue.h" @@ -68,11 +67,10 @@ vsc_callback_f *vsc_lock; vsc_callback_f *vsc_unlock; void * -VRT_VSC_Alloc(const char *nm, size_t sd, size_t sj, const unsigned char *zj, - size_t szj, const char *fmt, va_list va) +VRT_VSC_Alloc(const char *nm, size_t sd, const unsigned char *jp, + size_t sj, const char *fmt, va_list va) { char *p; - z_stream vz; struct vsc_segs *vsg; char buf[1024]; @@ -88,14 +86,7 @@ VRT_VSC_Alloc(const char *nm, size_t sd, size_t sj, const unsigned char *zj, p = VSMW_Allocv(heritage.proc_vsmw, VSC_CLASS, 8 + sd + sj, buf, va); AN(p); - memset(&vz, 0, sizeof vz); - assert(Z_OK == inflateInit2(&vz, 31)); - vz.next_in = TRUST_ME(zj); - vz.avail_in = szj; - vz.next_out = (void*)(p + 8 + sd); - vz.avail_out = sj; - assert(Z_STREAM_END == inflate(&vz, Z_FINISH)); - assert(Z_OK == inflateEnd(&vz)); + memcpy(p + 8 + sd, jp, sj); ALLOC_OBJ(vsg, VSC_SEGS_MAGIC); AN(vsg); vsg->seg = p; diff --git a/include/vrt.h b/include/vrt.h index 12e0375..6c96796 100644 --- a/include/vrt.h +++ b/include/vrt.h @@ -443,7 +443,7 @@ VCL_STRING VRT_STRANDS_string(VCL_STRANDS); VCL_STRING VRT_TIME_string(VRT_CTX, VCL_TIME); #ifdef va_start // XXX: hackish -void *VRT_VSC_Alloc(const char *, size_t, size_t, const unsigned char *, size_t, +void *VRT_VSC_Alloc(const char *, size_t, const unsigned char *, size_t, const char *, va_list); void VRT_VSC_Destroy(const char *, const void *); #endif diff --git a/lib/libvcc/vsctool.py b/lib/libvcc/vsctool.py index 942328f..d5ad76c 100644 --- a/lib/libvcc/vsctool.py +++ b/lib/libvcc/vsctool.py @@ -36,11 +36,6 @@ from __future__ import print_function import getopt import json import sys -import gzip -try: - import StringIO -except ImportError: - import io import collections import struct @@ -66,22 +61,12 @@ else: def b(x): return codecs.latin_1_encode(x)[0] -def gzip_str(s): - try: - out = StringIO.StringIO() - except NameError: - out = io.BytesIO() - - gzip.GzipFile(fileobj=out, mode="w").write(b(s)) - out.seek(4) - out.write(struct.pack("= 70: + if len(t) >= 69: fo.write(t + "\n") t = "\t" if len(t) > 1: @@ -142,7 +124,12 @@ class vscset(object): fo.write("\n};\n") s = json.dumps(dd, indent=2, separators=(',', ': ')) fo.write("\n// ") - fo.write("\n// ".join(s.split("\n"))) + for i in s.split("\n"): + j = "// " + i + if len(j) > 72: + fo.write(j[:72] + "[...]\n") + else: + fo.write(j + "\n") fo.write("\n") @@ -183,11 +170,16 @@ class vscset(object): (self.name, self.name.upper())) fo.write("\n") + fo.write("#define PARANOIA(a,n)\t\t\t\t\\\n") + fo.write(" _Static_assert(\t\t\t\t\\\n") + fo.write("\toffsetof(" + self.struct + ", a) == n,\t\\\n") + fo.write("\t\"VSC element '\" #a \"' at wrong offset\")\n\n") + for i in self.mbrs: - fo.write("_Static_assert(offsetof(" + self.struct) - fo.write(", " + i.arg + ")") - fo.write(" == %d,\n" % (i.param["index"] - 8)) - fo.write(' "VSC element offset is wrong");\n') + fo.write("PARANOIA(" + i.arg) + fo.write(", %d);\n" % (i.param["index"] - 8)) + + fo.write("#undef PARANOIA\n") self.emit_json(fo) @@ -203,10 +195,8 @@ class vscset(object): fo.write("\tretval = VRT_VSC_Alloc") fo.write("(vsc_" + self.name + "_name, ") fo.write("sizeof(" + self.struct + "),\n\t ") - fo.write("vsc_" + self.name + "_jsonlen, ") - fo.write("vsc_" + self.name + "_zjson, ") - fo.write("sizeof vsc_" + self.name + "_zjson,\n") - fo.write("\t fmt, ap);\n") + fo.write("vsc_" + self.name + "_json, ") + fo.write("sizeof vsc_" + self.name + "_json, fmt, ap);\n") fo.write("\tva_end(ap);\n") fo.write("\treturn(retval);\n") fo.write("}\n") @@ -235,8 +225,12 @@ class vscset(object): fo.write("\tAN(dst);\n") fo.write("\tAN(src);\n") for i in self.mbrs: - fo.write("\tdst->" + i.arg) - fo.write(" += src->" + i.arg + ";\n") + s1 = "\tdst->" + i.arg + " +=" + s2 = "src->" + i.arg + ";" + if len((s1 + " " + s2).expandtabs()) < 79: + fo.write(s1 + " " + s2 + "\n") + else: + fo.write(s1 + "\n\t " + s2 + "\n") fo.write("}\n") ####################################################################### From phk at FreeBSD.org Wed Dec 20 21:09:07 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Wed, 20 Dec 2017 21:09:07 +0000 (UTC) Subject: [master] 2b878a3 Get rid of this one-define .h file. Message-ID: <20171220210907.847F2AFFCB@lists.varnish-cache.org> commit 2b878a322220d16cb0a2e3dbd4048be7c8f30af5 Author: Poul-Henning Kamp Date: Wed Dec 20 21:08:17 2017 +0000 Get rid of this one-define .h file. diff --git a/bin/varnishd/common/common_vsc.c b/bin/varnishd/common/common_vsc.c index ce07893..8b9bcd7 100644 --- a/bin/varnishd/common/common_vsc.c +++ b/bin/varnishd/common/common_vsc.c @@ -44,7 +44,6 @@ #include "vmb.h" #include "vsmw.h" #include "vqueue.h" -#include "vapi/vsc_int.h" #include "common/heritage.h" @@ -83,7 +82,7 @@ VRT_VSC_Alloc(const char *nm, size_t sd, const unsigned char *jp, bprintf(buf, "%s.%s", nm, fmt); AN(heritage.proc_vsmw); - p = VSMW_Allocv(heritage.proc_vsmw, VSC_CLASS, 8 + sd + sj, buf, va); + p = VSMW_Allocv(heritage.proc_vsmw, "Stat", 8 + sd + sj, buf, va); AN(p); memcpy(p + 8 + sd, jp, sj); diff --git a/include/Makefile.am b/include/Makefile.am index 5bec5a5..99d6622 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -43,7 +43,6 @@ nobase_pkginclude_HEADERS = \ tbl/waiters.h \ vapi/vsm.h \ vapi/vsc.h \ - vapi/vsc_int.h \ vapi/vsl.h \ vapi/vsl_int.h \ vapi/voptget.h \ diff --git a/include/vapi/vsc.h b/include/vapi/vsc.h index 88ac0b7..82fa89f 100644 --- a/include/vapi/vsc.h +++ b/include/vapi/vsc.h @@ -35,8 +35,6 @@ #ifndef VAPI_VSC_H_INCLUDED #define VAPI_VSC_H_INCLUDED -#include "vapi/vsc_int.h" - struct vsm; struct vsc; struct vsm_fantom; diff --git a/include/vapi/vsc_int.h b/include/vapi/vsc_int.h deleted file mode 100644 index 6859ac6..0000000 --- a/include/vapi/vsc_int.h +++ /dev/null @@ -1,31 +0,0 @@ -/*- - * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2015 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#define VSC_CLASS "Stat" diff --git a/lib/libvarnishapi/vsc.c b/lib/libvarnishapi/vsc.c index 45a159a..b13550f 100644 --- a/lib/libvarnishapi/vsc.c +++ b/lib/libvarnishapi/vsc.c @@ -399,7 +399,7 @@ VSC_Iter(struct vsc *vsc, struct vsm *vsm, VSC_iter_f *fiter, void *priv) AN(vsm); sp = VTAILQ_FIRST(&vsc->segs); VSM_FOREACH(&ifantom, vsm) { - if (strcmp(ifantom.class, VSC_CLASS)) + if (strcmp(ifantom.class, "Stat")) continue; while (sp != NULL && (strcmp(ifantom.ident, sp->fantom->ident) || From daghf at varnish-software.com Thu Dec 21 12:44:04 2017 From: daghf at varnish-software.com (Dag Haavi Finstad) Date: Thu, 21 Dec 2017 12:44:04 +0000 (UTC) Subject: [master] c8a5904 h2: Do a VSL_Flush prior to changing vsl->wid Message-ID: <20171221124404.F24BB95FEE@lists.varnish-cache.org> commit c8a59044eb6b0dde2a5ba99393794479d7d89d08 Author: Dag Haavi Finstad Date: Thu Dec 21 13:41:02 2017 +0100 h2: Do a VSL_Flush prior to changing vsl->wid This ensures we don't end up with a VSL batched record with conflicting ids, which breaks the -g grouping modes. diff --git a/bin/varnishd/http2/cache_http2_session.c b/bin/varnishd/http2/cache_http2_session.c index fcee836..a0fa1dd 100644 --- a/bin/varnishd/http2/cache_http2_session.c +++ b/bin/varnishd/http2/cache_http2_session.c @@ -94,6 +94,7 @@ h2_new_sess(const struct worker *wrk, struct sess *sp, struct req *srq) h2->htc = srq->htc; h2->ws = srq->ws; h2->vsl = srq->vsl; + VSL_Flush(h2->vsl, 0); h2->vsl->wid = sp->vxid; h2->htc->rfd = &sp->fd; h2->sess = sp; From phk at FreeBSD.org Thu Dec 21 16:52:06 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Thu, 21 Dec 2017 16:52:06 +0000 (UTC) Subject: [master] 29872fb polish Message-ID: <20171221165206.BF69F9B174@lists.varnish-cache.org> commit 29872fb8c522e0a2f65522e10d72452d277a5808 Author: Poul-Henning Kamp Date: Thu Dec 21 10:58:29 2017 +0000 polish diff --git a/include/vsl_priv.h b/include/vsl_priv.h index 7ab0606..434550f 100644 --- a/include/vsl_priv.h +++ b/include/vsl_priv.h @@ -32,11 +32,12 @@ * NB: THIS IS NOT A PUBLIC API TO VARNISH! */ -#ifndef VSL_PRIV_H_INCLUDED +#ifdef VSL_PRIV_H_INCLUDED +# error "vsl_priv.h included more than once" +#endif #define VSL_PRIV_H_INCLUDED #include "vapi/vsl_int.h" -#include "vsm_priv.h" #define VSL_CLASS "Log" #define VSL_SEGMENTS 8U // power of two @@ -65,5 +66,3 @@ struct VSL_head { ssize_t offset[VSL_SEGMENTS]; uint32_t log[]; }; - -#endif /* VSL_PRIV_H_INCLUDED */ From phk at FreeBSD.org Thu Dec 21 16:52:06 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Thu, 21 Dec 2017 16:52:06 +0000 (UTC) Subject: [master] 48cbc79 Put the VSC prefix data in a struct. Message-ID: <20171221165206.D13C19B177@lists.varnish-cache.org> commit 48cbc79b3c9d43693f74ee229b00c8630a896d0b Author: Poul-Henning Kamp Date: Thu Dec 21 16:33:55 2017 +0000 Put the VSC prefix data in a struct. ...Now that we will need more than one integer. diff --git a/bin/varnishd/common/common_vsc.c b/bin/varnishd/common/common_vsc.c index 8b9bcd7..7f9f239 100644 --- a/bin/varnishd/common/common_vsc.c +++ b/bin/varnishd/common/common_vsc.c @@ -40,8 +40,8 @@ #include "miniobj.h" #include "vas.h" -#include "vend.h" #include "vmb.h" +#include "vsc_priv.h" #include "vsmw.h" #include "vqueue.h" @@ -56,6 +56,7 @@ struct vsc_segs { const char *nm; VTAILQ_ENTRY(vsc_segs) list; void *seg; + struct vsc_head *head; void *ptr; }; @@ -72,6 +73,7 @@ VRT_VSC_Alloc(const char *nm, size_t sd, const unsigned char *jp, char *p; struct vsc_segs *vsg; char buf[1024]; + uint64_t co, jo; if (vsc_lock != NULL) vsc_lock(); @@ -81,22 +83,27 @@ VRT_VSC_Alloc(const char *nm, size_t sd, const unsigned char *jp, else bprintf(buf, "%s.%s", nm, fmt); + co = PRNDUP(sizeof(struct vsc_head)); + jo = co + PRNDUP(sd); AN(heritage.proc_vsmw); - p = VSMW_Allocv(heritage.proc_vsmw, "Stat", 8 + sd + sj, buf, va); + p = VSMW_Allocv(heritage.proc_vsmw, VSC_CLASS, + jo + PRNDUP(sj), buf, va); AN(p); - memcpy(p + 8 + sd, jp, sj); ALLOC_OBJ(vsg, VSC_SEGS_MAGIC); AN(vsg); vsg->seg = p; - vsg->ptr = p + 8; + vsg->head = (void*)p; + vsg->head->ctr_offset = co; + vsg->ptr = p + co; VTAILQ_INSERT_TAIL(&vsc_seglist, vsg, list); + memcpy(p + jo, jp, sj); VWMB(); - vbe64enc(p, sd); + vsg->head->json_offset = jo; vsg->nm = nm; if (vsc_unlock != NULL) vsc_unlock(); - return (p + 8); + return (vsg->ptr); } void diff --git a/include/Makefile.am b/include/Makefile.am index 99d6622..822dcdd 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -90,6 +90,7 @@ nobase_noinst_HEADERS = \ vmb.h \ vnum.h \ vpf.h \ + vsc_priv.h \ vsl_priv.h \ vsmw.h \ vsm_priv.h \ diff --git a/include/vsc_priv.h b/include/vsc_priv.h new file mode 100644 index 0000000..e0d9f2e --- /dev/null +++ b/include/vsc_priv.h @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 2017 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * Author: Martin Blix Grydeland + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Define the layout of the statistics VSM segments + * + * NB: THIS IS NOT A PUBLIC API TO VARNISH! + */ + +#ifdef VSC_PRIV_H_INCLUDED +# error "vsc_priv.h included more than once" +#endif +#define VSC_PRIV_H_INCLUDED + +#define VSC_CLASS "Stat" + +struct vsc_head { + volatile uint64_t json_offset; + uint64_t ctr_offset; +}; diff --git a/lib/libvarnishapi/vsc.c b/lib/libvarnishapi/vsc.c index b13550f..92a4939 100644 --- a/lib/libvarnishapi/vsc.c +++ b/lib/libvarnishapi/vsc.c @@ -45,7 +45,7 @@ #include "vqueue.h" #include "vjsn.h" #include "vsb.h" -#include "vend.h" +#include "vsc_priv.h" #include "vmb.h" #include "vapi/vsc.h" @@ -70,6 +70,7 @@ struct vsc_seg { VTAILQ_ENTRY(vsc_seg) list; struct vsm_fantom fantom[1]; struct vjsn *vj; + struct vsc_head *head; unsigned npoints; struct vsc_pt *points; }; @@ -204,7 +205,7 @@ vsc_clean_point(struct vsc_pt *point) } static int -vsc_fill_point(const struct vsc *vsc, const struct vsm_fantom *fantom, +vsc_fill_point(const struct vsc *vsc, struct vsc_seg *seg, const struct vjsn_val *vv, struct vsb *vsb, struct vsc_pt *point) { struct vjsn_val *vt; @@ -217,7 +218,7 @@ vsc_fill_point(const struct vsc *vsc, const struct vsm_fantom *fantom, assert(vt->type == VJSN_STRING); VSB_clear(vsb); - VSB_printf(vsb, "%s.%s", fantom->ident, vt->value); + VSB_printf(vsb, "%s.%s", seg->fantom->ident, vt->value); AZ(VSB_finish(vsb)); if (vsc_filter(vsc, VSB_data(vsb))) @@ -285,7 +286,8 @@ vsc_fill_point(const struct vsc *vsc, const struct vsm_fantom *fantom, AN(vt); point->point.ptr = (volatile void*) - ((volatile char*)fantom->b + atoi(vt->value)); + ((volatile char*)seg->fantom->b + + seg->head->ctr_offset + atoi(vt->value)); return (1); } @@ -314,7 +316,6 @@ static struct vsc_seg * vsc_add_seg(const struct vsc *vsc, struct vsm *vsm, const struct vsm_fantom *fp) { struct vsc_seg *sp; - uint64_t u; const char *p; const char *e; struct vjsn_val *vv, *vve; @@ -335,16 +336,14 @@ vsc_add_seg(const struct vsc *vsc, struct vsm *vsm, const struct vsm_fantom *fp) FREE_OBJ(sp); return (NULL); } - // AZ(VSM_Map(vsm, sp->fantom)); - u = vbe64dec(sp->fantom->b); - if (u == 0) { + sp->head = sp->fantom->b; + if (sp->head->json_offset == 0) { VRMB(); usleep(100000); - u = vbe64dec(sp->fantom->b); } - assert(u > 0); - p = (char*)sp->fantom->b + 8 + u; + assert(sp->head->json_offset > 0); + p = (char*)sp->fantom->b + sp->head->json_offset; assert (p < (char*)sp->fantom->e); sp->vj = vjsn_parse(p, &e); XXXAZ(e); @@ -359,7 +358,7 @@ vsc_add_seg(const struct vsc *vsc, struct vsm *vsm, const struct vsm_fantom *fp) AN(vve); pp = sp->points; VTAILQ_FOREACH(vv, &vve->children, list) { - if (vsc_fill_point(vsc, sp->fantom, vv, vsb, pp) && + if (vsc_fill_point(vsc, sp, vv, vsb, pp) && vsc->fnew != NULL) pp->point.priv = vsc->fnew(vsc->priv, &pp->point); pp++; @@ -399,7 +398,7 @@ VSC_Iter(struct vsc *vsc, struct vsm *vsm, VSC_iter_f *fiter, void *priv) AN(vsm); sp = VTAILQ_FIRST(&vsc->segs); VSM_FOREACH(&ifantom, vsm) { - if (strcmp(ifantom.class, "Stat")) + if (strcmp(ifantom.class, VSC_CLASS)) continue; while (sp != NULL && (strcmp(ifantom.ident, sp->fantom->ident) || diff --git a/lib/libvcc/vsctool.py b/lib/libvcc/vsctool.py index d5ad76c..da89aee 100644 --- a/lib/libvcc/vsctool.py +++ b/lib/libvcc/vsctool.py @@ -79,7 +79,7 @@ class vscset(object): self.mbrs = [] self.head = m self.completed = False - self.off = 8 + self.off = 0 def addmbr(self, m): assert not self.completed @@ -177,7 +177,7 @@ class vscset(object): for i in self.mbrs: fo.write("PARANOIA(" + i.arg) - fo.write(", %d);\n" % (i.param["index"] - 8)) + fo.write(", %d);\n" % (i.param["index"])) fo.write("#undef PARANOIA\n") From nils.goroll at uplex.de Thu Dec 21 17:17:06 2017 From: nils.goroll at uplex.de (Nils Goroll) Date: Thu, 21 Dec 2017 17:17:06 +0000 (UTC) Subject: [master] fb5779c vmodtool: enforce unique argument names Message-ID: <20171221171706.84C3C9BB34@lists.varnish-cache.org> commit fb5779c6e2c765dea4b54019330cf6741a80bd41 Author: Nils Goroll Date: Thu Dec 21 18:13:55 2017 +0100 vmodtool: enforce unique argument names diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py index 851f032..f870e69 100755 --- a/lib/libvcc/vmodtool.py +++ b/lib/libvcc/vmodtool.py @@ -337,8 +337,13 @@ class prototype(object): assert s[-1] == ")" s = s[1:-1].lstrip() self.args = [] + names = {} while len(s) > 0: a, s = arg(s) + if a.nm is not None and a.nm in names: + err("%s(): duplicate argument name '%s'\n" % (self.name, a.nm), + warn=False) + names[a.nm] = True self.args.append(a) s = s.lstrip() if len(s) == 0: From nils.goroll at uplex.de Thu Dec 21 17:42:06 2017 From: nils.goroll at uplex.de (Nils Goroll) Date: Thu, 21 Dec 2017 17:42:06 +0000 (UTC) Subject: [master] 9a64ba9 vmodtool: enforce function and argument names be valid c symbols Message-ID: <20171221174206.F0FEAA036F@lists.varnish-cache.org> commit 9a64ba93badcee6bc46fc98c84a49b862053548a Author: Nils Goroll Date: Thu Dec 21 18:39:43 2017 +0100 vmodtool: enforce function and argument names be valid c symbols diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py index f870e69..6400d4d 100755 --- a/lib/libvcc/vmodtool.py +++ b/lib/libvcc/vmodtool.py @@ -310,6 +310,8 @@ def arg(txt): return a, s +def nmlegal(nm): + return re.match('^[a-zA-Z0-9_]+$', nm) # XXX cant have ( or ) in an argument default value class prototype(object): @@ -332,6 +334,8 @@ class prototype(object): i = s.find("(") assert i > 0 self.name = prefix + s[:i].strip() + if not nmlegal(self.cname()): + err("%s(): Illegal name\n" % self.name, warn=False) s = s[i:].strip() assert s[0] == "(" assert s[-1] == ")" @@ -340,10 +344,14 @@ class prototype(object): names = {} while len(s) > 0: a, s = arg(s) - if a.nm is not None and a.nm in names: - err("%s(): duplicate argument name '%s'\n" % (self.name, a.nm), - warn=False) - names[a.nm] = True + if a.nm is not None: + if not nmlegal(a.nm): + err("%s(): illegal argument name '%s'\n" + % (self.name, a.nm), warn=False) + if a.nm in names: + err("%s(): duplicate argument name '%s'\n" + % (self.name, a.nm), warn=False) + names[a.nm] = True self.args.append(a) s = s.lstrip() if len(s) == 0: From phk at FreeBSD.org Fri Dec 22 09:58:09 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Fri, 22 Dec 2017 09:58:09 +0000 (UTC) Subject: [master] 73ba50b Hand back an opaque pointer to VSC segments. Message-ID: <20171222095809.4AD2EB498C@lists.varnish-cache.org> commit 73ba50b89ad9d33f62453667c8e8e93074f0f5cf Author: Poul-Henning Kamp Date: Fri Dec 22 09:56:05 2017 +0000 Hand back an opaque pointer to VSC segments. This eliminates a O(N) lookup when we want to do something (ie: Destroy) to a VSC segment subsequently. diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index 189e5ef..fdf131f 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -757,8 +757,7 @@ int Lck_CondWait(pthread_cond_t *cond, struct lock *lck, double); assert(Lck__Owned(a)); \ } while (0) -struct VSC_lck *Lck_CreateClass(const char *name); -void Lck_DestroyClass(struct VSC_lck **vsclck); +struct VSC_lck *Lck_CreateClass(struct vsc_seg **, const char *name); #define LOCK(nam) extern struct VSC_lck *lck_##nam; #include "tbl/locks.h" diff --git a/bin/varnishd/cache/cache_backend.c b/bin/varnishd/cache/cache_backend.c index d1e5525..3b67257 100644 --- a/bin/varnishd/cache/cache_backend.c +++ b/bin/varnishd/cache/cache_backend.c @@ -335,14 +335,14 @@ static void vbe_dir_event(const struct director *d, enum vcl_event_e ev) { struct backend *bp; - struct VSC_vbe *vsc; CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); CAST_OBJ_NOTNULL(bp, d->priv, BACKEND_MAGIC); if (ev == VCL_EVENT_WARM) { AZ(bp->vsc); - bp->vsc = VSC_vbe_New(bp->director->display_name); + bp->vsc = + VSC_vbe_New(&bp->vsc_seg, bp->director->display_name); AN(bp->vsc); } @@ -353,13 +353,10 @@ vbe_dir_event(const struct director *d, enum vcl_event_e ev) VBP_Control(bp, 0); if (ev == VCL_EVENT_COLD) { - AN(bp->vsc); Lck_Lock(&backends_mtx); - vsc = bp->vsc; bp->vsc = NULL; Lck_Unlock(&backends_mtx); - VSC_vbe_Destroy(&vsc); - AZ(bp->vsc); + VSC_vbe_Destroy(&bp->vsc_seg); } } diff --git a/bin/varnishd/cache/cache_backend.h b/bin/varnishd/cache/cache_backend.h index ff3cde3..b0a0442 100644 --- a/bin/varnishd/cache/cache_backend.h +++ b/bin/varnishd/cache/cache_backend.h @@ -59,6 +59,7 @@ struct backend { struct vbp_target *probe; + struct vsc_seg *vsc_seg; struct VSC_vbe *vsc; struct tcp_pool *tcp_pool; diff --git a/bin/varnishd/cache/cache_lck.c b/bin/varnishd/cache/cache_lck.c index ee3e864..1509723 100644 --- a/bin/varnishd/cache/cache_lck.c +++ b/bin/varnishd/cache/cache_lck.c @@ -245,15 +245,9 @@ Lck_Delete(struct lock *lck) } struct VSC_lck * -Lck_CreateClass(const char *name) +Lck_CreateClass(struct vsc_seg **sg, const char *name) { - return(VSC_lck_New(name)); -} - -void -Lck_DestroyClass(struct VSC_lck **vsclck) -{ - VSC_lck_Destroy(vsclck); + return(VSC_lck_New(sg, name)); } #define LOCK(nam) struct VSC_lck *lck_##nam; @@ -265,6 +259,6 @@ LCK_Init(void) AZ(pthread_mutexattr_init(&attr)); AZ(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK)); -#define LOCK(nam) lck_##nam = Lck_CreateClass(#nam); +#define LOCK(nam) lck_##nam = Lck_CreateClass(NULL, #nam); #include "tbl/locks.h" } diff --git a/bin/varnishd/cache/cache_mempool.c b/bin/varnishd/cache/cache_mempool.c index 9017532..1a9f040 100644 --- a/bin/varnishd/cache/cache_mempool.c +++ b/bin/varnishd/cache/cache_mempool.c @@ -59,6 +59,7 @@ struct mempool { volatile struct poolparam *param; volatile unsigned *cur_size; uint64_t live; + struct vsc_seg *vsc_seg; struct VSC_mempool *vsc; unsigned n_pool; pthread_t thread; @@ -160,7 +161,7 @@ mpl_guard(void *priv) FREE_OBJ(mi); mi = NULL; } - VSC_mempool_Destroy(&mpl->vsc); + VSC_mempool_Destroy(&mpl->vsc_seg); Lck_Unlock(&mpl->mtx); Lck_Delete(&mpl->mtx); FREE_OBJ(mpl); @@ -238,7 +239,7 @@ MPL_New(const char *name, VTAILQ_INIT(&mpl->surplus); Lck_New(&mpl->mtx, lck_mempool); /* XXX: prealloc min_pool */ - mpl->vsc = VSC_mempool_New(mpl->name + 4); + mpl->vsc = VSC_mempool_New(&mpl->vsc_seg, mpl->name + 4); AN(mpl->vsc); AZ(pthread_create(&mpl->thread, NULL, mpl_guard, mpl)); AZ(pthread_detach(mpl->thread)); diff --git a/bin/varnishd/cache/cache_shmlog.c b/bin/varnishd/cache/cache_shmlog.c index f663bff..cbb72a8 100644 --- a/bin/varnishd/cache/cache_shmlog.c +++ b/bin/varnishd/cache/cache_shmlog.c @@ -505,7 +505,7 @@ VSM_Init(void) vsc_lock = vsm_vsc_lock; vsc_unlock = vsm_vsc_unlock; - VSC_C_main = VSC_main_New(""); + VSC_C_main = VSC_main_New(NULL, ""); AN(VSC_C_main); AN(heritage.proc_vsmw); diff --git a/bin/varnishd/common/common_vsc.c b/bin/varnishd/common/common_vsc.c index 7f9f239..1e8842d 100644 --- a/bin/varnishd/common/common_vsc.c +++ b/bin/varnishd/common/common_vsc.c @@ -49,29 +49,29 @@ /*--------------------------------------------------------------------*/ -struct vsc_segs { +struct vsc_seg { unsigned magic; -#define VSC_SEGS_MAGIC 0x9b355991 +#define VSC_SEG_MAGIC 0x9b355991 const char *nm; - VTAILQ_ENTRY(vsc_segs) list; + VTAILQ_ENTRY(vsc_seg) list; void *seg; struct vsc_head *head; void *ptr; }; -static VTAILQ_HEAD(,vsc_segs) vsc_seglist = +static VTAILQ_HEAD(,vsc_seg) vsc_seglist = VTAILQ_HEAD_INITIALIZER(vsc_seglist); vsc_callback_f *vsc_lock; vsc_callback_f *vsc_unlock; void * -VRT_VSC_Alloc(const char *nm, size_t sd, const unsigned char *jp, - size_t sj, const char *fmt, va_list va) +VRT_VSC_Alloc(struct vsc_seg **sg, const char *nm, size_t sd, + const unsigned char *jp, size_t sj, const char *fmt, va_list va) { char *p; - struct vsc_segs *vsg; + struct vsc_seg *vsg; char buf[1024]; uint64_t co, jo; @@ -90,7 +90,7 @@ VRT_VSC_Alloc(const char *nm, size_t sd, const unsigned char *jp, jo + PRNDUP(sj), buf, va); AN(p); - ALLOC_OBJ(vsg, VSC_SEGS_MAGIC); + ALLOC_OBJ(vsg, VSC_SEG_MAGIC); AN(vsg); vsg->seg = p; vsg->head = (void*)p; @@ -103,22 +103,20 @@ VRT_VSC_Alloc(const char *nm, size_t sd, const unsigned char *jp, vsg->nm = nm; if (vsc_unlock != NULL) vsc_unlock(); + if (sg != NULL) + *sg = vsg; return (vsg->ptr); } void -VRT_VSC_Destroy(const char *nm, const void *p) +VRT_VSC_Destroy(const char *nm, struct vsc_seg *vsg) { - struct vsc_segs *vsg; if (vsc_lock != NULL) vsc_lock(); AN(heritage.proc_vsmw); - VTAILQ_FOREACH(vsg, &vsc_seglist, list) - if (vsg->ptr == p) - break; - AN(vsg); + CHECK_OBJ_NOTNULL(vsg, VSC_SEG_MAGIC); assert(vsg->nm == nm); VSMW_Free(heritage.proc_vsmw, &vsg->seg); VTAILQ_REMOVE(&vsc_seglist, vsg, list); diff --git a/bin/varnishd/hash/hash_classic.c b/bin/varnishd/hash/hash_classic.c index 33704e4..3440b9b 100644 --- a/bin/varnishd/hash/hash_classic.c +++ b/bin/varnishd/hash/hash_classic.c @@ -94,7 +94,7 @@ hcl_start(void) { unsigned u; - lck_hcl = Lck_CreateClass("hcl"); + lck_hcl = Lck_CreateClass(NULL, "hcl"); hcl_head = calloc(hcl_nhash, sizeof *hcl_head); XXXAN(hcl_head); diff --git a/bin/varnishd/hash/hash_simple_list.c b/bin/varnishd/hash/hash_simple_list.c index e2726ea..4c1e902 100644 --- a/bin/varnishd/hash/hash_simple_list.c +++ b/bin/varnishd/hash/hash_simple_list.c @@ -52,7 +52,7 @@ static void v_matchproto_(hash_start_f) hsl_start(void) { - lck_hsl = Lck_CreateClass("hsl"); + lck_hsl = Lck_CreateClass(NULL, "hsl"); Lck_New(&hsl_mtx, lck_hsl); } diff --git a/bin/varnishd/mgt/mgt.h b/bin/varnishd/mgt/mgt.h index 9a03a4a..46595d2 100644 --- a/bin/varnishd/mgt/mgt.h +++ b/bin/varnishd/mgt/mgt.h @@ -48,6 +48,7 @@ #include "common/common_param.h" +struct vsc_seg; #include "VSC_mgt.h" struct cli; diff --git a/bin/varnishd/mgt/mgt_main.c b/bin/varnishd/mgt/mgt_main.c index cf9c454..da963b5 100644 --- a/bin/varnishd/mgt/mgt_main.c +++ b/bin/varnishd/mgt/mgt_main.c @@ -808,7 +808,7 @@ main(int argc, char * const *argv) mgt_SHM_Init(); mgt_SHM_static_alloc(i_arg, strlen(i_arg) + 1L, "Arg", "-i"); - VSC_C_mgt = VSC_mgt_New(""); + VSC_C_mgt = VSC_mgt_New(NULL, ""); if (M_arg != NULL) mgt_cli_master(M_arg); diff --git a/bin/varnishd/storage/storage_file.c b/bin/varnishd/storage/storage_file.c index 285a62d..af2817f 100644 --- a/bin/varnishd/storage/storage_file.c +++ b/bin/varnishd/storage/storage_file.c @@ -411,9 +411,9 @@ smf_open(struct stevedore *st) ASSERT_CLI(); st->lru = LRU_Alloc(); if (lck_smf == NULL) - lck_smf = Lck_CreateClass("smf"); + lck_smf = Lck_CreateClass(NULL, "smf"); CAST_OBJ_NOTNULL(sc, st->priv, SMF_SC_MAGIC); - sc->stats = VSC_smf_New(st->ident); + sc->stats = VSC_smf_New(NULL, st->ident); Lck_New(&sc->mtx, lck_smf); Lck_Lock(&sc->mtx); smf_open_chunk(sc, sc->filesize, 0, &fail, &sum); diff --git a/bin/varnishd/storage/storage_malloc.c b/bin/varnishd/storage/storage_malloc.c index e82217e..4ea548b 100644 --- a/bin/varnishd/storage/storage_malloc.c +++ b/bin/varnishd/storage/storage_malloc.c @@ -210,10 +210,10 @@ sma_open(struct stevedore *st) ASSERT_CLI(); st->lru = LRU_Alloc(); if (lck_sma == NULL) - lck_sma = Lck_CreateClass("sma"); + lck_sma = Lck_CreateClass(NULL, "sma"); CAST_OBJ_NOTNULL(sma_sc, st->priv, SMA_SC_MAGIC); Lck_New(&sma_sc->sma_mtx, lck_sma); - sma_sc->stats = VSC_sma_New(st->ident); + sma_sc->stats = VSC_sma_New(NULL, st->ident); if (sma_sc->sma_max != SIZE_MAX) sma_sc->stats->g_space = sma_sc->sma_max; } diff --git a/bin/varnishd/storage/storage_persistent.c b/bin/varnishd/storage/storage_persistent.c index 59af759..95f7b4f 100644 --- a/bin/varnishd/storage/storage_persistent.c +++ b/bin/varnishd/storage/storage_persistent.c @@ -679,7 +679,7 @@ static struct cli_proto debug_cmds[] = { static void smp_init(void) { - lck_smp = Lck_CreateClass("smp"); + lck_smp = Lck_CreateClass(NULL, "smp"); CLI_AddFuncs(debug_cmds); smp_oc_realmethods = SML_methods; smp_oc_realmethods.objtouch = NULL; diff --git a/include/vrt.h b/include/vrt.h index 6c96796..ee440aa 100644 --- a/include/vrt.h +++ b/include/vrt.h @@ -112,6 +112,7 @@ struct vmod; struct vmod_priv; struct vrt_acl; struct vsb; +struct vsc_seg; struct vsl_log; struct ws; @@ -443,7 +444,7 @@ VCL_STRING VRT_STRANDS_string(VCL_STRANDS); VCL_STRING VRT_TIME_string(VRT_CTX, VCL_TIME); #ifdef va_start // XXX: hackish -void *VRT_VSC_Alloc(const char *, size_t, const unsigned char *, size_t, - const char *, va_list); -void VRT_VSC_Destroy(const char *, const void *); +void *VRT_VSC_Alloc(struct vsc_seg **, const char *, size_t, + const unsigned char *, size_t, const char *, va_list); +void VRT_VSC_Destroy(const char *, struct vsc_seg *); #endif diff --git a/lib/libvcc/vsctool.py b/lib/libvcc/vsctool.py index da89aee..98283ed 100644 --- a/lib/libvcc/vsctool.py +++ b/lib/libvcc/vsctool.py @@ -144,10 +144,10 @@ class vscset(object): fo.write("\n"); fo.write(self.struct + " *VSC_" + self.name + "_New") - fo.write("(const char *fmt, ...);\n"); + fo.write("(struct vsc_seg **, const char *fmt, ...);\n"); fo.write("void VSC_" + self.name + "_Destroy") - fo.write("(" + self.struct + "**);\n") + fo.write("(struct vsc_seg **);\n") if 'sumfunction' in self.head.param: fo.write("void VSC_" + self.name + "_Summ") @@ -186,14 +186,14 @@ class vscset(object): fo.write("\n") fo.write(self.struct + "*\n"); fo.write("VSC_" + self.name + "_New") - fo.write("(const char *fmt, ...)\n"); + fo.write("(struct vsc_seg **sg, const char *fmt, ...)\n"); fo.write("{\n") fo.write("\tva_list ap;\n") fo.write("\t" + self.struct + " *retval;\n") fo.write("\n") fo.write("\tva_start(ap, fmt);\n") fo.write("\tretval = VRT_VSC_Alloc") - fo.write("(vsc_" + self.name + "_name, ") + fo.write("(sg, vsc_" + self.name + "_name, ") fo.write("sizeof(" + self.struct + "),\n\t ") fo.write("vsc_" + self.name + "_json, ") fo.write("sizeof vsc_" + self.name + "_json, fmt, ap);\n") @@ -204,13 +204,13 @@ class vscset(object): fo.write("\n") fo.write("void\n") fo.write("VSC_" + self.name + "_Destroy") - fo.write("(" + self.struct + " **pp)\n") + fo.write("(struct vsc_seg **sg)\n") fo.write("{\n") - fo.write("\t" + self.struct + "*p;\n") + fo.write("\tstruct vsc_seg *p;\n") fo.write("\n") - fo.write("\tAN(pp);\n") - fo.write("\tp = *pp;\n") - fo.write("\t*pp = NULL;\n") + fo.write("\tAN(sg);\n") + fo.write("\tp = *sg;\n") + fo.write("\t*sg = NULL;\n") fo.write('\tVRT_VSC_Destroy(vsc_%s_name, p);\n' % self.name) fo.write("}\n") diff --git a/lib/libvmod_debug/vmod_debug.c b/lib/libvmod_debug/vmod_debug.c index c24d78a..2298d10 100644 --- a/lib/libvmod_debug/vmod_debug.c +++ b/lib/libvmod_debug/vmod_debug.c @@ -66,6 +66,7 @@ struct priv_vcl { static VCL_DURATION vcl_release_delay = 0.0; static pthread_mutex_t vsc_mtx = PTHREAD_MUTEX_INITIALIZER; +static struct vsc_seg *vsc_seg; static struct VSC_debug *vsc; VCL_VOID v_matchproto_(td_debug_panic) @@ -361,7 +362,7 @@ event_function(VRT_CTX, struct vmod_priv *priv, enum vcl_event_e e) case VCL_EVENT_COLD: return (event_cold(ctx, priv)); case VCL_EVENT_DISCARD: if (vsc) - VSC_debug_Destroy(&vsc); + VSC_debug_Destroy(&vsc_seg); return (0); default: return (0); } @@ -584,7 +585,7 @@ xyzzy_vsc_new(VRT_CTX) (void)ctx; AZ(pthread_mutex_lock(&vsc_mtx)); if (vsc == NULL) - vsc = VSC_debug_New(""); + vsc = VSC_debug_New(&vsc_seg, ""); AN(vsc); AZ(pthread_mutex_unlock(&vsc_mtx)); } @@ -594,8 +595,8 @@ xyzzy_vsc_destroy(VRT_CTX) { (void)ctx; AZ(pthread_mutex_lock(&vsc_mtx)); - if (vsc) - VSC_debug_Destroy(&vsc); + if (vsc != NULL) + VSC_debug_Destroy(&vsc_seg); AZ(vsc); AZ(pthread_mutex_unlock(&vsc_mtx)); } From phk at FreeBSD.org Fri Dec 22 10:10:07 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Fri, 22 Dec 2017 10:10:07 +0000 (UTC) Subject: [master] a6c7f8c Forgot storage_umem Message-ID: <20171222101007.DCA85B4E9A@lists.varnish-cache.org> commit a6c7f8c3b462108e1012823e4c669fed3a88814d Author: Poul-Henning Kamp Date: Fri Dec 22 10:09:06 2017 +0000 Forgot storage_umem diff --git a/bin/varnishd/storage/storage_umem.c b/bin/varnishd/storage/storage_umem.c index 0510412..f951f09 100644 --- a/bin/varnishd/storage/storage_umem.c +++ b/bin/varnishd/storage/storage_umem.c @@ -255,10 +255,10 @@ smu_open(struct stevedore *st) ASSERT_CLI(); st->lru = LRU_Alloc(); if (lck_smu == NULL) - lck_smu = Lck_CreateClass("smu"); + lck_smu = Lck_CreateClass(NULL, "smu"); CAST_OBJ_NOTNULL(smu_sc, st->priv, SMU_SC_MAGIC); Lck_New(&smu_sc->smu_mtx, lck_smu); - smu_sc->stats = VSC_smu_New(st->ident); + smu_sc->stats = VSC_smu_New(NULL, st->ident); if (smu_sc->smu_max != SIZE_MAX) smu_sc->stats->g_space = smu_sc->smu_max; From nils.goroll at uplex.de Fri Dec 22 16:33:08 2017 From: nils.goroll at uplex.de (Nils Goroll) Date: Fri, 22 Dec 2017 16:33:08 +0000 (UTC) Subject: [master] fda299c vmodtool: centralize generation of c prototypes in class prototype Message-ID: <20171222163308.771C3BB9E9@lists.varnish-cache.org> commit fda299cf0d3f5879cda7da442350926a80b46fcd Author: Nils Goroll Date: Thu Dec 21 21:33:12 2017 +0100 vmodtool: centralize generation of c prototypes in class prototype generalize functions and methods, some additional cleanup diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py index 6400d4d..5cbe93b 100755 --- a/lib/libvcc/vmodtool.py +++ b/lib/libvcc/vmodtool.py @@ -42,6 +42,7 @@ import re import optparse import unittest import random +import copy rstfmt = False strict_abi = True @@ -334,6 +335,7 @@ class prototype(object): i = s.find("(") assert i > 0 self.name = prefix + s[:i].strip() + self.vcc = st.vcc if not nmlegal(self.cname()): err("%s(): Illegal name\n" % self.name, warn=False) s = s[i:].strip() @@ -359,8 +361,11 @@ class prototype(object): assert s[0] == ',' s = s[1:].lstrip() - def cname(self): - return self.name.replace(".", "_") + def cname(self, pfx=False): + r = self.name.replace(".", "_") + if pfx: + return self.vcc.sympfx + r + return r def vcl_proto(self, short): s = "" @@ -384,14 +389,21 @@ class prototype(object): def c_ret(self): return self.retval.ct - def c_args(self): - if len(self.args) == 0: - return "" - l = [""] + def c_args(self, a=[]): + l = list(a) for i in self.args: l.append(i.ct) return ", ".join(l) + def c_fn(self, args=[], h=False): + s = fn = '' + if not h: + s += 'typedef ' + fn += 'td_' + self.vcc.modname + '_' + fn += self.cname(pfx=h) + s += '%s %s(%s);' % (self.c_ret(), fn, self.c_args(args)) + return "\n".join(lwrap(s)) + "\n" + def specstr(self, fo, cfunc, p): if self.retval is None: fo.write(p + '"VOID\\0"\n') @@ -568,24 +580,16 @@ class s_function(stanza): self.vcc.contents.append(self) def hfile(self, fo): - fn = self.vcc.sympfx + self.proto.name - s = "%s %s(VRT_CTX" % (self.proto.c_ret(), fn) - s += self.proto.c_args() + ");" - for i in lwrap(s): - fo.write(i + "\n") + fo.write(self.proto.c_fn(['VRT_CTX'], True)) def cfile(self, fo): - fn = "td_" + self.vcc.modname + "_" + self.proto.name - s = "typedef %s %s(VRT_CTX" % (self.proto.c_ret(), fn) - s += self.proto.c_args() + ");" - for i in lwrap(s): - fo.write(i + "\n") + fo.write(self.proto.c_fn(['VRT_CTX'])) def cstruct(self, fo): fmt_cstruct(fo, self.vcc.modname, self.proto.cname()) def cstruct_init(self, fo): - fo.write("\t" + self.vcc.sympfx + self.proto.cname() + ",\n") + fo.write("\t" + self.proto.cname(pfx=True) + ",\n") def specstr(self, fo): fo.write('\t"$FUNC\\0"\t"%s.%s\\0"\n\n' % @@ -598,6 +602,15 @@ class s_function(stanza): class s_object(stanza): def parse(self): self.proto = prototype(self, retval=False) + self.proto.retval = vtype('VOID')[0] + + self.init = copy.copy(self.proto) + self.init.name += '__init' + + self.fini = copy.copy(self.proto) + self.fini.name += '__fini' + self.fini.args = [] + self.rstlbl = "obj_" + self.proto.name self.vcc.contents.append(self) self.methods = [] @@ -623,32 +636,11 @@ class s_object(stanza): sn = self.vcc.sympfx + self.vcc.modname + "_" + self.proto.name fo.write("struct %s;\n" % sn) - if h: - def p(x): - return x + " " + self.vcc.sympfx - else: - def p(x): - return "typedef " + x + \ - " td_%s_" % self.vcc.modname - - s = p("VCL_VOID") + "%s__init(VRT_CTX, " % self.proto.name - s += "struct %s **, const char *" % sn - s += self.proto.c_args() + ");" - for i in lwrap(s): - fo.write(i + "\n") - - s = p("VCL_VOID") - s += "%s__fini(struct %s **);" % (self.proto.name, sn) - for i in lwrap(s): - fo.write(i + "\n") - + fo.write(self.init.c_fn( + ['VRT_CTX', 'struct %s **' % sn, 'const char *'], h)) + fo.write(self.fini.c_fn(['struct %s **' % sn], h)) for i in self.methods: - cn = i.proto.cname() - s = p(i.proto.c_ret()) - s += "%s(VRT_CTX, struct %s *" % (cn, sn) - s += i.proto.c_args() + ");" - for i in lwrap(s): - fo.write(i + "\n") + fo.write(i.proto.c_fn(['VRT_CTX', 'struct %s *' % sn], h)); fo.write("\n") def hfile(self, fo): @@ -658,15 +650,15 @@ class s_object(stanza): self.chfile(fo, False) def cstruct(self, fo): - fmt_cstruct(fo, self.vcc.modname, self.proto.name + "__init") - fmt_cstruct(fo, self.vcc.modname, self.proto.name + "__fini") + fmt_cstruct(fo, self.vcc.modname, self.init.name) + fmt_cstruct(fo, self.vcc.modname, self.fini.name) for i in self.methods: i.cstruct(fo) def cstruct_init(self, fo): p = "\t" + self.vcc.sympfx - fo.write(p + self.proto.name + "__init,\n") - fo.write(p + self.proto.name + "__fini,\n") + fo.write(p + self.init.name + ",\n") + fo.write(p + self.fini.name + ",\n") for i in self.methods: i.cstruct_init(fo) fo.write("\n") @@ -680,13 +672,13 @@ class s_object(stanza): (self.vcc.sympfx, self.vcc.modname, self.proto.name)) fo.write("\n") - self.proto.specstr(fo, 'Vmod_%s_Func.%s__init' % - (self.vcc.modname, self.proto.name), '\t ') + self.proto.specstr(fo, 'Vmod_%s_Func.%s' % + (self.vcc.modname, self.init.name), '\t ') fo.write('\t "\\0"\n\n') fo.write('\t "VOID\\0"\n') - fo.write('\t "Vmod_%s_Func.%s__fini\\0"\n' % - (self.vcc.modname, self.proto.name)) + fo.write('\t "Vmod_%s_Func.%s\\0"\n' % + (self.vcc.modname, self.fini.name)) fo.write('\t\t"\\0"\n') fo.write('\t "\\0"\n\n') @@ -713,7 +705,7 @@ class s_method(stanza): fmt_cstruct(fo, self.vcc.modname, self.proto.cname()) def cstruct_init(self, fo): - fo.write('\t' + self.vcc.sympfx + self.proto.cname() + ",\n") + fo.write('\t' + self.proto.cname(pfx=True) + ",\n") def specstr(self, fo): fo.write('\t "%s.%s\\0"\n' % From phk at FreeBSD.org Fri Dec 22 21:38:06 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Fri, 22 Dec 2017 21:38:06 +0000 (UTC) Subject: [master] 3284aed Store VSC documentation in their own segments and only once, no matter how many instances of the VSC set there are. Message-ID: <20171222213806.6F2DB98D90@lists.varnish-cache.org> commit 3284aed8679a176ba0e30b91055f6b074b279fd5 Author: Poul-Henning Kamp Date: Fri Dec 22 21:37:21 2017 +0000 Store VSC documentation in their own segments and only once, no matter how many instances of the VSC set there are. diff --git a/bin/varnishd/common/common_vsc.c b/bin/varnishd/common/common_vsc.c index 1e8842d..3a719ed 100644 --- a/bin/varnishd/common/common_vsc.c +++ b/bin/varnishd/common/common_vsc.c @@ -53,11 +53,19 @@ struct vsc_seg { unsigned magic; #define VSC_SEG_MAGIC 0x9b355991 + struct vsmw *vsm; // keep master/child sep. const char *nm; VTAILQ_ENTRY(vsc_seg) list; void *seg; + + /* VSC segments */ struct vsc_head *head; void *ptr; + struct vsc_seg *doc; + + /* DOC segments */ + const unsigned char *jp; + int refs; }; static VTAILQ_HEAD(,vsc_seg) vsc_seglist = @@ -66,41 +74,86 @@ static VTAILQ_HEAD(,vsc_seg) vsc_seglist = vsc_callback_f *vsc_lock; vsc_callback_f *vsc_unlock; +static struct vsc_seg * +vrt_vsc_mksegv(const char *class, size_t payload, const char *fmt, va_list va) +{ + struct vsc_seg *vsg; + size_t co; + + co = PRNDUP(sizeof(struct vsc_head)); + ALLOC_OBJ(vsg, VSC_SEG_MAGIC); + AN(vsg); + vsg->seg = VSMW_Allocv(heritage.proc_vsmw, class, + co + PRNDUP(payload), fmt, va); + AN(vsg->seg); + vsg->vsm = heritage.proc_vsmw; + vsg->head = (void*)vsg->seg; + vsg->head->body_offset = co; + vsg->ptr = (char*)vsg->seg + co; + return (vsg); +} + +static struct vsc_seg * +vrt_vsc_mksegf(const char *class, size_t payload, const char *fmt, ...) +{ + va_list ap; + struct vsc_seg *vsg; + + va_start(ap, fmt); + vsg = vrt_vsc_mksegv(class, payload, fmt, ap); + va_end(ap); + return (vsg); +} + void * VRT_VSC_Alloc(struct vsc_seg **sg, const char *nm, size_t sd, const unsigned char *jp, size_t sj, const char *fmt, va_list va) { - char *p; - struct vsc_seg *vsg; + struct vsc_seg *vsg, *dvsg; char buf[1024]; - uint64_t co, jo; + uintptr_t jjp; if (vsc_lock != NULL) vsc_lock(); + jjp = (uintptr_t)jp; + + VTAILQ_FOREACH(dvsg, &vsc_seglist, list) { + if (dvsg->vsm != heritage.proc_vsmw) + continue; + if (dvsg->jp == NULL || dvsg->jp == jp) + break; + } + if (dvsg == NULL || dvsg->jp == NULL) { + /* Create a new documentation segment */ + dvsg = vrt_vsc_mksegf(VSC_DOC_CLASS, sj, + "%jx", (uintmax_t)jjp); + AN(dvsg); + dvsg->jp = jp; + dvsg->head->doc_id = jjp; + memcpy(dvsg->ptr, jp, sj); + VWMB(); + dvsg->head->ready = 1; + VTAILQ_INSERT_HEAD(&vsc_seglist, dvsg, list); + } + AN(dvsg); + dvsg->refs++; + if (*fmt == '\0') bprintf(buf, "%s", nm); else bprintf(buf, "%s.%s", nm, fmt); - co = PRNDUP(sizeof(struct vsc_head)); - jo = co + PRNDUP(sd); AN(heritage.proc_vsmw); - p = VSMW_Allocv(heritage.proc_vsmw, VSC_CLASS, - jo + PRNDUP(sj), buf, va); - AN(p); - ALLOC_OBJ(vsg, VSC_SEG_MAGIC); + vsg = vrt_vsc_mksegv(VSC_CLASS, sd, buf, va); AN(vsg); - vsg->seg = p; - vsg->head = (void*)p; - vsg->head->ctr_offset = co; - vsg->ptr = p + co; + vsg->nm = nm; + vsg->doc = dvsg; + vsg->head->doc_id = jjp; VTAILQ_INSERT_TAIL(&vsc_seglist, vsg, list); - memcpy(p + jo, jp, sj); VWMB(); - vsg->head->json_offset = jo; - vsg->nm = nm; + vsg->head->ready = 1; if (vsc_unlock != NULL) vsc_unlock(); if (sg != NULL) @@ -111,16 +164,27 @@ VRT_VSC_Alloc(struct vsc_seg **sg, const char *nm, size_t sd, void VRT_VSC_Destroy(const char *nm, struct vsc_seg *vsg) { + struct vsc_seg *dvsg; if (vsc_lock != NULL) vsc_lock(); AN(heritage.proc_vsmw); CHECK_OBJ_NOTNULL(vsg, VSC_SEG_MAGIC); + AZ(vsg->jp); + CHECK_OBJ_NOTNULL(vsg->doc, VSC_SEG_MAGIC); + assert(vsg->vsm == heritage.proc_vsmw); assert(vsg->nm == nm); + + dvsg = vsg->doc; VSMW_Free(heritage.proc_vsmw, &vsg->seg); VTAILQ_REMOVE(&vsc_seglist, vsg, list); FREE_OBJ(vsg); + if (--dvsg->refs == 0) { + VSMW_Free(heritage.proc_vsmw, &dvsg->seg); + VTAILQ_REMOVE(&vsc_seglist, dvsg, list); + FREE_OBJ(dvsg); + } if (vsc_unlock != NULL) vsc_unlock(); } diff --git a/include/vsc_priv.h b/include/vsc_priv.h index e0d9f2e..88f55dd 100644 --- a/include/vsc_priv.h +++ b/include/vsc_priv.h @@ -37,8 +37,10 @@ #define VSC_PRIV_H_INCLUDED #define VSC_CLASS "Stat" +#define VSC_DOC_CLASS "StatDoc" struct vsc_head { - volatile uint64_t json_offset; - uint64_t ctr_offset; + volatile int ready; + uint64_t body_offset; + uintptr_t doc_id; }; diff --git a/lib/libvarnishapi/vsc.c b/lib/libvarnishapi/vsc.c index 92a4939..8f7c2df 100644 --- a/lib/libvarnishapi/vsc.c +++ b/lib/libvarnishapi/vsc.c @@ -69,8 +69,11 @@ struct vsc_seg { #define VSC_SEG_MAGIC 0x801177d4 VTAILQ_ENTRY(vsc_seg) list; struct vsm_fantom fantom[1]; - struct vjsn *vj; struct vsc_head *head; + char *body; + + struct vjsn *vj; + unsigned npoints; struct vsc_pt *points; }; @@ -205,7 +208,7 @@ vsc_clean_point(struct vsc_pt *point) } static int -vsc_fill_point(const struct vsc *vsc, struct vsc_seg *seg, +vsc_fill_point(const struct vsc *vsc, const struct vsc_seg *seg, const struct vjsn_val *vv, struct vsb *vsb, struct vsc_pt *point) { struct vjsn_val *vt; @@ -285,9 +288,7 @@ vsc_fill_point(const struct vsc *vsc, struct vsc_seg *seg, vt = vjsn_child(vv, "index"); AN(vt); - point->point.ptr = (volatile void*) - ((volatile char*)seg->fantom->b + - seg->head->ctr_offset + atoi(vt->value)); + point->point.ptr = (volatile void*)(seg->body + atoi(vt->value)); return (1); } @@ -301,22 +302,24 @@ vsc_del_seg(const struct vsc *vsc, struct vsm *vsm, struct vsc_seg *sp) AN(vsm); CHECK_OBJ_NOTNULL(sp, VSC_SEG_MAGIC); AZ(VSM_Unmap(vsm, sp->fantom)); - vjsn_delete(&sp->vj); - pp = sp->points; - for (u = 0; u < sp->npoints; u++, pp++) { - if (vsc->fdestroy != NULL) - vsc->fdestroy(vsc->priv, &pp->point); - vsc_clean_point(pp); + if (sp->vj != NULL) { + vjsn_delete(&sp->vj); + } else { + pp = sp->points; + for (u = 0; u < sp->npoints; u++, pp++) { + if (vsc->fdestroy != NULL) + vsc->fdestroy(vsc->priv, &pp->point); + vsc_clean_point(pp); + } + free(sp->points); } - free(sp->points); FREE_OBJ(sp); } static struct vsc_seg * vsc_add_seg(const struct vsc *vsc, struct vsm *vsm, const struct vsm_fantom *fp) { - struct vsc_seg *sp; - const char *p; + struct vsc_seg *sp, *spd; const char *e; struct vjsn_val *vv, *vve; struct vsb *vsb; @@ -336,34 +339,43 @@ vsc_add_seg(const struct vsc *vsc, struct vsm *vsm, const struct vsm_fantom *fp) FREE_OBJ(sp); return (NULL); } - sp->head = sp->fantom->b; - if (sp->head->json_offset == 0) { + if (sp->head->ready == 0) { VRMB(); usleep(100000); } - assert(sp->head->json_offset > 0); - p = (char*)sp->fantom->b + sp->head->json_offset; - assert (p < (char*)sp->fantom->e); - sp->vj = vjsn_parse(p, &e); - XXXAZ(e); - vve = vjsn_child(sp->vj->value, "elements"); - AN(vve); - sp->npoints = strtoul(vve->value, NULL, 0); - sp->points = calloc(sp->npoints, sizeof *sp->points); - AN(sp->points); - vsb = VSB_new_auto(); - AN(vsb); - vve = vjsn_child(sp->vj->value, "elem"); - AN(vve); - pp = sp->points; - VTAILQ_FOREACH(vv, &vve->children, list) { - if (vsc_fill_point(vsc, sp, vv, vsb, pp) && - vsc->fnew != NULL) - pp->point.priv = vsc->fnew(vsc->priv, &pp->point); - pp++; + assert(sp->head->ready > 0); + sp->body = (char*)sp->fantom->b + sp->head->body_offset; + + if (!strcmp(fp->class, VSC_CLASS)) { + VTAILQ_FOREACH(spd, &vsc->segs, list) + if (spd->head->doc_id == sp->head->doc_id) + break; + AN(spd); + // XXX: Refcount ? + vve = vjsn_child(spd->vj->value, "elements"); + AN(vve); + sp->npoints = strtoul(vve->value, NULL, 0); + sp->points = calloc(sp->npoints, sizeof *sp->points); + AN(sp->points); + vsb = VSB_new_auto(); + AN(vsb); + vve = vjsn_child(spd->vj->value, "elem"); + AN(vve); + pp = sp->points; + VTAILQ_FOREACH(vv, &vve->children, list) { + if (vsc_fill_point(vsc, sp, vv, vsb, pp) && + vsc->fnew != NULL) + pp->point.priv = + vsc->fnew(vsc->priv, &pp->point); + pp++; + } + VSB_destroy(&vsb); + return (sp); } - VSB_destroy(&vsb); + assert(!strcmp(fp->class, VSC_DOC_CLASS)); + sp->vj = vjsn_parse(sp->body, &e); + XXXAZ(e); AN(sp->vj); return (sp); } @@ -398,8 +410,10 @@ VSC_Iter(struct vsc *vsc, struct vsm *vsm, VSC_iter_f *fiter, void *priv) AN(vsm); sp = VTAILQ_FIRST(&vsc->segs); VSM_FOREACH(&ifantom, vsm) { - if (strcmp(ifantom.class, VSC_CLASS)) + if (strcmp(ifantom.class, VSC_CLASS) && + strcmp(ifantom.class, VSC_DOC_CLASS)) continue; + sp2 = sp; while (sp != NULL && (strcmp(ifantom.ident, sp->fantom->ident) || VSM_StillValid(vsm, sp->fantom) != VSM_valid)) { @@ -408,19 +422,18 @@ VSC_Iter(struct vsc *vsc, struct vsm *vsm, VSC_iter_f *fiter, void *priv) VTAILQ_REMOVE(&vsc->segs, sp2, list); vsc_del_seg(vsc, vsm, sp2); } - if (sp != NULL) { - if (fiter != NULL) - i = vsc_iter_seg(vsc, sp, fiter, priv); - sp = VTAILQ_NEXT(sp, list); - } else { + if (sp == NULL) { sp = vsc_add_seg(vsc, vsm, &ifantom); if (sp != NULL) { VTAILQ_INSERT_TAIL(&vsc->segs, sp, list); - if (fiter != NULL) - i = vsc_iter_seg(vsc, sp, fiter, priv); - sp = NULL; + sp2 = NULL; } + } else { + sp2 = VTAILQ_NEXT(sp, list); } + if (sp != NULL && fiter != NULL) + i = vsc_iter_seg(vsc, sp, fiter, priv); + sp = sp2; if (i) break; } From nils.goroll at uplex.de Fri Dec 29 10:38:09 2017 From: nils.goroll at uplex.de (Nils Goroll) Date: Fri, 29 Dec 2017 10:38:09 +0000 (UTC) Subject: [master] 756940f cnt_recv: replace return from switch with break Message-ID: <20171229103809.E278CBAF28@lists.varnish-cache.org> commit 756940fe0ab7a40d1189d8d07a156cd526f0d77e Author: Nils Goroll Date: Tue Dec 26 16:37:53 2017 +0100 cnt_recv: replace return from switch with break just a minor stylistic cleanup: Early returns should mark exceptional cases. diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index f52f8f6..40d87ba 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -890,13 +890,13 @@ cnt_recv(struct worker *wrk, struct req *req) "Only from active VCL"); req->err_code = 503; req->req_step = R_STP_SYNTH; - return (REQ_FSM_MORE); + break; case VCL_RET_PURGE: req->req_step = R_STP_PURGE; - return (REQ_FSM_MORE); + break; case VCL_RET_HASH: req->req_step = R_STP_LOOKUP; - return (REQ_FSM_MORE); + break; case VCL_RET_PIPE: if (req->esi_level > 0) { VSLb(req->vsl, SLT_VCL_Error, @@ -911,19 +911,20 @@ cnt_recv(struct worker *wrk, struct req *req) } else { req->req_step = R_STP_PIPE; } - return (REQ_FSM_MORE); + break; case VCL_RET_PASS: req->req_step = R_STP_PASS; - return (REQ_FSM_MORE); + break; case VCL_RET_SYNTH: req->req_step = R_STP_SYNTH; - return (REQ_FSM_MORE); + break; case VCL_RET_FAIL: req->req_step = R_STP_VCLFAIL; - return (REQ_FSM_MORE); + break; default: WRONG("Illegal return from vcl_recv{}"); } + return (REQ_FSM_MORE); } /*-------------------------------------------------------------------- From nils.goroll at uplex.de Fri Dec 29 10:38:10 2017 From: nils.goroll at uplex.de (Nils Goroll) Date: Fri, 29 Dec 2017 10:38:10 +0000 (UTC) Subject: [master] c15eefb add return(restart) from vcl_recv Message-ID: <20171229103810.0953FBAF2B@lists.varnish-cache.org> commit c15eefb1b237f13564a3453618ede6265396347b Author: Nils Goroll Date: Tue Dec 26 16:19:24 2017 +0100 add return(restart) from vcl_recv This is already possible with some overhead (for example with a de-tour via vcl_pass), but I see absolutely no reason why we should not allow direct restarts from recv. The use case is to rewrite the request and re-start processing of the rewritten request as if it was received as such. This is also possible already with some vcl sub juggling, but is complicated by the VCL call loop detection. Use of restarts avoids this complication and is safe due to max_restarts. diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index 40d87ba..142425c 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -918,6 +918,9 @@ cnt_recv(struct worker *wrk, struct req *req) case VCL_RET_SYNTH: req->req_step = R_STP_SYNTH; break; + case VCL_RET_RESTART: + req->req_step = R_STP_RESTART; + break; case VCL_RET_FAIL: req->req_step = R_STP_VCLFAIL; break; diff --git a/bin/varnishtest/tests/b00019.vtc b/bin/varnishtest/tests/b00019.vtc index 5336478..b5e69c1 100644 --- a/bin/varnishtest/tests/b00019.vtc +++ b/bin/varnishtest/tests/b00019.vtc @@ -1,4 +1,4 @@ -varnishtest "Check that max_restarts works and that we don't fall over" +varnishtest "Check that max_restarts outside vcl_recv works and that we don't fall over" server s1 { rxreq diff --git a/bin/varnishtest/tests/b00024.vtc b/bin/varnishtest/tests/b00024.vtc new file mode 100644 index 0000000..e34817d --- /dev/null +++ b/bin/varnishtest/tests/b00024.vtc @@ -0,0 +1,48 @@ +varnishtest "Check that max_restarts from vcl_recv works and that we don't fall over" + +varnish v1 -vcl { + backend dummy { .host = "${bad_backend}"; } + + sub vcl_recv { + return (restart); + } + + sub vcl_synth { + # when we end up here, we have _exceeded_ the number + # allowed restarts + if (req.restarts == 3) { + set resp.status = 200; + set resp.reason = "restart=3"; + } elsif (req.restarts > 3) { + set resp.status = 501; + set resp.reason = "restart>3"; + } elsif (req.restarts < 3) { + set resp.status = 500; + set resp.reason = "restart<3"; + } + } +} -start + +varnish v1 -cliok "param.set max_restarts 2" + +client c1 { + txreq -url "/" + rxresp + expect resp.status == 200 +} -run + +varnish v1 -cliok "param.set max_restarts 3" + +client c1 { + txreq -url "/" + rxresp + expect resp.status == 501 +} -run + +varnish v1 -cliok "param.set max_restarts 1" + +client c1 { + txreq -url "/" + rxresp + expect resp.status == 500 +} -run diff --git a/doc/changes.rst b/doc/changes.rst index 4d1f91d..b09221b 100644 --- a/doc/changes.rst +++ b/doc/changes.rst @@ -47,6 +47,8 @@ VCL and bundled VMODs * workspace overflows in ``std.syslog()`` are ignored +* added ``return(restart)`` from ``vcl_recv{}`` + Logging / statistics -------------------- diff --git a/lib/libvcc/generate.py b/lib/libvcc/generate.py index 398b658..40d7556 100755 --- a/lib/libvcc/generate.py +++ b/lib/libvcc/generate.py @@ -93,7 +93,7 @@ returns = ( ('recv', "C", - ('fail', 'synth', 'pass', 'pipe', 'hash', 'purge', 'vcl') + ('fail', 'synth', 'restart', 'pass', 'pipe', 'hash', 'purge', 'vcl') ), ('pipe', "C", From nils.goroll at uplex.de Fri Dec 29 10:38:10 2017 From: nils.goroll at uplex.de (Nils Goroll) Date: Fri, 29 Dec 2017 10:38:10 +0000 (UTC) Subject: [master] fac3d73 improve vtc coverage of gunzip + range + streaming Message-ID: <20171229103810.205D9BAF2E@lists.varnish-cache.org> commit fac3d7342e372d82927c9417349899bf1d4ae263 Author: Nils Goroll Date: Fri Dec 29 11:25:01 2017 +0100 improve vtc coverage of gunzip + range + streaming diff --git a/bin/varnishtest/tests/g00005.vtc b/bin/varnishtest/tests/g00005.vtc index 7cb2664..6a49440 100644 --- a/bin/varnishtest/tests/g00005.vtc +++ b/bin/varnishtest/tests/g00005.vtc @@ -1,17 +1,24 @@ varnishtest "test gunzip for client + Range" -server s1 { +server s1 -repeat 3 { rxreq expect req.http.accept-encoding == "gzip" txresp -gzipbody FOOBARBARF } -start varnish v1 -cliok "param.set http_gzip_support true" -vcl+backend { + sub vcl_backend_response { + if (bereq.url ~ "^/nostream") { + set beresp.do_stream = false; + } + } } -start client c1 { - txreq + # no range support with streaming cache miss and gunzip + txreq -hdr "Range: bytes=3-5" rxresp + expect resp.status == 200 expect resp.bodylen == "10" expect resp.http.content-encoding == @@ -32,4 +39,17 @@ client c1 { expect resp.bodylen == "3" expect resp.body == "BAR" + txreq -url "/nostreamcachemiss" -hdr "Range: bytes=3-5" + rxresp + expect resp.status == 206 + expect resp.http.content-encoding == "" + expect resp.bodylen == "3" + expect resp.body == "BAR" + + # simple cache miss no gunzip + txreq -url "/2" -hdr "Range: bytes=3-5" -hdr "Accept-Encoding: gzip" + rxresp + expect resp.status == 206 + expect resp.http.content-encoding == "gzip" + expect resp.bodylen == "3" } -run From nils.goroll at uplex.de Fri Dec 29 18:22:07 2017 From: nils.goroll at uplex.de (Nils Goroll) Date: Fri, 29 Dec 2017 18:22:07 +0000 (UTC) Subject: [master] b1b4dac graphviz/svg/rst: add return(restart) from vcl_recv Message-ID: <20171229182207.2A7E79895F@lists.varnish-cache.org> commit b1b4dac051c720559e39106e27bce8e2a901a0c1 Author: Nils Goroll Date: Fri Dec 29 19:18:33 2017 +0100 graphviz/svg/rst: add return(restart) from vcl_recv Ref: c15eefb1b237f13564a3453618ede6265396347b diff --git a/doc/graphviz/cache_req_fsm.dot b/doc/graphviz/cache_req_fsm.dot index bbec3e5..3501b7b 100644 --- a/doc/graphviz/cache_req_fsm.dot +++ b/doc/graphviz/cache_req_fsm.dot @@ -188,7 +188,7 @@ digraph cache_req_fsm { subgraph xcluster_recv { recv [ shape=record - label="{cnt_recv:|{vcl_recv\{\}|req.*}|{fail|hash|purge|pass|pipe|synth|vcl}}" + label="{cnt_recv:|{vcl_recv\{\}|req.*}|{fail|hash|purge|pass|pipe|restart|synth|vcl}}" ] recv:hash -> hash [style=bold,color=green] hash [ diff --git a/doc/graphviz/cache_req_fsm.svg b/doc/graphviz/cache_req_fsm.svg index 4afe57d..60c71ac 100644 --- a/doc/graphviz/cache_req_fsm.svg +++ b/doc/graphviz/cache_req_fsm.svg @@ -4,28 +4,28 @@ - + cache_req_fsm - + cluster_backend acceptor - -Request received + +Request received recv - -cnt_recv: - -vcl_recv{} - -req.* - + +cnt_recv: + +vcl_recv{} + +req.* + fail hash @@ -36,54 +36,56 @@ pipe -synth - -vcl +restart + +synth + +vcl acceptor->recv - - + + label_select - -LABEL + +LABEL label_select->recv - - + + ESI_REQ - -ESI request + +ESI request ESI_REQ->recv - - + + RESTART -RESTART +RESTART restart - -cnt_restart: - -fail - -ok? - -max_restarts? + +cnt_restart: + +fail + +ok? + +max_restarts? RESTART->restart - - + + hash @@ -108,8 +110,8 @@ recv:pass->hash - - + + recv:purge:s->hash @@ -118,13 +120,13 @@ vcl_label -switch to vcl -LABEL +switch to vcl +LABEL recv:vcl:s->vcl_label - - + + SYNTH @@ -446,17 +448,17 @@ restart:ok:s->recv - - + + err_restart -SYNTH +SYNTH restart:max:s->err_restart - - + + hash:lookup:w->lookup @@ -470,8 +472,8 @@ hash:lookup:e->pipe - - + + purge diff --git a/doc/sphinx/users-guide/vcl-built-in-subs.rst b/doc/sphinx/users-guide/vcl-built-in-subs.rst index 68c28ae..47b183f 100644 --- a/doc/sphinx/users-guide/vcl-built-in-subs.rst +++ b/doc/sphinx/users-guide/vcl-built-in-subs.rst @@ -89,6 +89,9 @@ of the following keywords: ``synth(status code, reason)`` see `synth`_ + ``restart`` + see `restart`_ + ``pass`` see `pass`_ From phk at FreeBSD.org Sat Dec 30 09:58:07 2017 From: phk at FreeBSD.org (Poul-Henning Kamp) Date: Sat, 30 Dec 2017 09:58:07 +0000 (UTC) Subject: [master] fa31403 Increase delay to increase test success probability Message-ID: <20171230095807.C85C7B0675@lists.varnish-cache.org> commit fa31403c6eb07be2bdc448fdc75fcce73c73ca2a Author: Poul-Henning Kamp Date: Sat Dec 30 09:57:05 2017 +0000 Increase delay to increase test success probability diff --git a/bin/varnishtest/tests/g00005.vtc b/bin/varnishtest/tests/g00005.vtc index 6a49440..9eacb10 100644 --- a/bin/varnishtest/tests/g00005.vtc +++ b/bin/varnishtest/tests/g00005.vtc @@ -30,7 +30,7 @@ client c1 { # This delay attempts to ensure that the busyobj # is completed before we attempt the range request - delay .2 + delay 1 txreq -hdr "Range: bytes=3-5" rxresp From gquintard at users.noreply.github.com Mon Dec 18 12:08:06 2017 From: gquintard at users.noreply.github.com (guillaume quintard) Date: Mon, 18 Dec 2017 12:08:06 -0000 Subject: [master] 61573d2 More info about the -s argument Message-ID: <20171218120806.9D91BAB2F5@lists.varnish-cache.org> commit 61573d29a2b503fcce075ab403969e88127b6b19 Author: Guillaume Quintard Date: Thu Dec 14 18:02:39 2017 +0100 More info about the -s argument fix: #2511 diff --git a/doc/sphinx/reference/varnishd.rst b/doc/sphinx/reference/varnishd.rst index 6c97236..6992531 100644 --- a/doc/sphinx/reference/varnishd.rst +++ b/doc/sphinx/reference/varnishd.rst @@ -295,7 +295,8 @@ The following storage types are available: -s The file backend stores data in a file on disk. The file will be - accessed using mmap. + accessed using mmap. Note that this storage is reset every time ``varnishd`` + starts. The path is mandatory. If path points to a directory, a temporary file will be created in that directory and immediately unlinked. If @@ -323,6 +324,18 @@ The following storage types are available: storage backend has multiple issues with it and will likely be removed from a future version of Varnish. + +You can also prefix the type with ``NAME=`` to explicitly name a storage:: + + -s myStorage=malloc,5G + +This allows to address it more easily in VCL:: + + set beresp.storage = storage.myStorage; + +If the name is omitted, Varnish will name storages ``sN``, starting with ``s0`` +and incrementing N for every new storage. + .. _ref-varnishd-opt_j: Jail From gquintard at users.noreply.github.com Mon Dec 18 12:10:08 2017 From: gquintard at users.noreply.github.com (guillaume quintard) Date: Mon, 18 Dec 2017 12:10:08 -0000 Subject: [master] 840e966 python3 compatibility Message-ID: <20171218121008.559CDAB362@lists.varnish-cache.org> commit 840e966daee16cbe6aed0d0a4b31ea40122f8061 Author: Guillaume Quintard Date: Thu Dec 14 17:39:09 2017 +0100 python3 compatibility .keys() doesn't produce a list in python3, only an iterable view diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py index c57f96e..851f032 100755 --- a/lib/libvcc/vmodtool.py +++ b/lib/libvcc/vmodtool.py @@ -801,8 +801,7 @@ class vcc(object): fo.write("#endif\n") fo.write("\n") - l = enum_values.keys() - l.sort() + l = sorted(enum_values) for j in l: fo.write("extern VCL_ENUM %senum_%s;\n" % (self.sympfx, j)) fo.write("\n") @@ -817,8 +816,7 @@ class vcc(object): for j in self.contents: j.cstruct(fo) fo.write("\n") - l = enum_values.keys() - l.sort() + l = sorted(enum_values) for j in l: fo.write("\tVCL_ENUM\t\t\t*enum_%s;\n" % j) fo.write("};\n") @@ -828,8 +826,7 @@ class vcc(object): for j in self.contents: j.cstruct_init(fo) fo.write("\n") - l = enum_values.keys() - l.sort() + l = sorted(enum_values) for j in l: fo.write("\t&%senum_%s,\n" % (self.sympfx, j)) fo.write("};\n") @@ -887,8 +884,7 @@ class vcc(object): fo.write("\n") - l = enum_values.keys() - l.sort() + l = sorted(enum_values) for j in l: fo.write('VCL_ENUM %senum_%s = "%s";\n' % (self.sympfx, j, j)) fo.write("\n")