From 665adc126ecfed9d0f6e228efc117639ebf62bf3 Mon Sep 17 00:00:00 2001 From: phk Date: Wed, 8 Aug 2007 19:43:51 +0000 Subject: [PATCH] Implement purging on either of hash or url. In VCL: purge_url() purge_hash() (for an interrim period purge() will be the same as purge_url). In CLI url.purge hash.purge purge_hash operates on the hash-string which results from vcl_hash(), by default it is composed of: req.url "#" req.http.host "#" To purge everything on the virtual host foo.bar.com: In CLI: url.purge "#foo.bar.com#$" In VCL: purge_hash("#foo.bar.com#$"); The general format, if you have defined vcl_hash(), is: Each "req.hash +=" operator appends the right hand side of the += and a "#" separator. You'll have to figure out your own regexps. Under the hood: Move the hash string from object to objecthead and save space while we're at it. Fix indentation in generated source. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@1816 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/cache.h | 11 ++++-- varnish-cache/bin/varnishd/cache_ban.c | 21 ++++++++--- varnish-cache/bin/varnishd/cache_cli.c | 1 + varnish-cache/bin/varnishd/cache_hash.c | 21 +++++++---- varnish-cache/bin/varnishd/cache_vrt.c | 4 +- varnish-cache/bin/varnishd/hash_classic.c | 20 +++++----- varnish-cache/bin/varnishd/hash_simple_list.c | 15 ++++---- varnish-cache/include/cli.h | 11 +++++- varnish-cache/include/vrt.h | 2 +- varnish-cache/lib/libvcl/vcc_action.c | 37 +++++++++++++++++-- varnish-cache/lib/libvcl/vcc_fixed_token.c | 2 +- 11 files changed, 101 insertions(+), 44 deletions(-) diff --git a/varnish-cache/bin/varnishd/cache.h b/varnish-cache/bin/varnishd/cache.h index b28c0c75..ba6b426f 100644 --- a/varnish-cache/bin/varnishd/cache.h +++ b/varnish-cache/bin/varnishd/cache.h @@ -262,6 +262,8 @@ struct objhead { pthread_mutex_t mtx; TAILQ_HEAD(,object) objects; + char *hash; + unsigned hashlen; }; /* -------------------------------------------------------------------*/ @@ -368,11 +370,12 @@ struct bereq *vbe_new_bereq(void); void vbe_free_bereq(struct bereq *bereq); /* cache_ban.c */ -void AddBan(const char *); +void AddBan(const char *, int hash); void BAN_Init(void); void cli_func_url_purge(struct cli *cli, char **av, void *priv); +void cli_func_hash_purge(struct cli *cli, char **av, void *priv); void BAN_NewObj(struct object *o); -int BAN_CheckObject(struct object *o, const char *url); +int BAN_CheckObject(struct object *o, const char *url, const char *hash); /* cache_center.c [CNT] */ void CNT_Session(struct sess *sp); @@ -392,8 +395,8 @@ int Fetch(struct sess *sp); /* cache_hash.c */ void HSH_Prealloc(struct sess *sp); -int HSH_Compare(struct sess *sp, const char *b, const char *e); -void HSH_Copy(struct sess *sp, char *b, const char *e); +int HSH_Compare(struct sess *sp, struct objhead *o); +void HSH_Copy(struct sess *sp, struct objhead *o); struct object *HSH_Lookup(struct sess *sp); void HSH_Unbusy(struct object *o); void HSH_Ref(struct object *o); diff --git a/varnish-cache/bin/varnishd/cache_ban.c b/varnish-cache/bin/varnishd/cache_ban.c index e56c6cbd..d29ced3f 100644 --- a/varnish-cache/bin/varnishd/cache_ban.c +++ b/varnish-cache/bin/varnishd/cache_ban.c @@ -46,6 +46,7 @@ struct ban { unsigned gen; regex_t regexp; char *ban; + int hash; }; static TAILQ_HEAD(,ban) ban_head = TAILQ_HEAD_INITIALIZER(ban_head); @@ -53,7 +54,7 @@ static unsigned ban_next; static struct ban *ban_start; void -AddBan(const char *regexp) +AddBan(const char *regexp, int hash) { struct ban *b; int i; @@ -68,6 +69,7 @@ AddBan(const char *regexp) (void)regerror(i, &b->regexp, buf, sizeof buf); VSL(SLT_Debug, 0, "REGEX: <%s>", buf); } + b->hash = hash; b->gen = ++ban_next; b->ban = strdup(regexp); TAILQ_INSERT_HEAD(&ban_head, b, list); @@ -82,7 +84,7 @@ BAN_NewObj(struct object *o) } int -BAN_CheckObject(struct object *o, const char *url) +BAN_CheckObject(struct object *o, const char *url, const char *hash) { struct ban *b, *b0; int i; @@ -91,7 +93,7 @@ BAN_CheckObject(struct object *o, const char *url) for (b = b0; b != NULL && b->gen > o->ban_seq; b = TAILQ_NEXT(b, list)) { - i = regexec(&b->regexp, url, 0, NULL, 0); + i = regexec(&b->regexp, b->hash ? hash : url, 0, NULL, 0); if (!i) return (1); } @@ -104,7 +106,16 @@ cli_func_url_purge(struct cli *cli, char **av, void *priv) { (void)priv; - AddBan(av[2]); + AddBan(av[2], 0); + cli_out(cli, "PURGE %s\n", av[2]); +} + +void +cli_func_hash_purge(struct cli *cli, char **av, void *priv) +{ + + (void)priv; + AddBan(av[2], 1); cli_out(cli, "PURGE %s\n", av[2]); } @@ -112,5 +123,5 @@ void BAN_Init(void) { - AddBan("a"); + AddBan("\001", 0); } diff --git a/varnish-cache/bin/varnishd/cache_cli.c b/varnish-cache/bin/varnishd/cache_cli.c index 43ccae7e..8eb7cfe9 100644 --- a/varnish-cache/bin/varnishd/cache_cli.c +++ b/varnish-cache/bin/varnishd/cache_cli.c @@ -67,6 +67,7 @@ struct cli_proto CLI_cmds[] = { { CLI_URL_QUERY, cli_func_url_query }, #endif { CLI_URL_PURGE, cli_func_url_purge }, + { CLI_HASH_PURGE, cli_func_hash_purge }, { CLI_VCL_LOAD, cli_func_config_load }, { CLI_VCL_LIST, cli_func_config_list }, { CLI_VCL_DISCARD, cli_func_config_discard }, diff --git a/varnish-cache/bin/varnishd/cache_hash.c b/varnish-cache/bin/varnishd/cache_hash.c index 1453922a..55e90def 100644 --- a/varnish-cache/bin/varnishd/cache_hash.c +++ b/varnish-cache/bin/varnishd/cache_hash.c @@ -110,14 +110,16 @@ HSH_Freestore(struct object *o) } int -HSH_Compare(struct sess *sp, const char *b, const char *e) +HSH_Compare(struct sess *sp, struct objhead *obj) { int i; unsigned u, v; + const char *b; - i = sp->lhashptr - (e - b); + i = sp->lhashptr - obj->hashlen; if (i) return (i); + b = obj->hash; for (u = 0; u < sp->ihashptr; u += 2) { v = sp->hashptr[u + 1] - sp->hashptr[u]; i = memcmp(sp->hashptr[u], b, v); @@ -130,16 +132,19 @@ HSH_Compare(struct sess *sp, const char *b, const char *e) } assert(*b == '\0'); b++; - assert(b == e); + assert(b == obj->hash + obj->hashlen); + VSL(SLT_Debug, sp->fd, "Hash Match: %s", obj->hash); return (0); } void -HSH_Copy(struct sess *sp, char *b, const char *e) +HSH_Copy(struct sess *sp, struct objhead *obj) { unsigned u, v; + char *b; - assert((e - b) >= sp->lhashptr); + assert(obj->hashlen >= sp->lhashptr); + b = obj->hash; for (u = 0; u < sp->ihashptr; u += 2) { v = sp->hashptr[u + 1] - sp->hashptr[u]; memcpy(b, sp->hashptr[u], v); @@ -147,7 +152,8 @@ HSH_Copy(struct sess *sp, char *b, const char *e) *b++ = '#'; } *b++ = '\0'; - assert(b <= e); + VSL(SLT_Debug, sp->fd, "Hash: %s", obj->hash); + assert(b <= obj->hash + obj->hashlen); } struct object * @@ -195,7 +201,8 @@ HSH_Lookup(struct sess *sp) /* Object banned but not reaped yet */ } else if (o->ttl <= sp->t_req) { /* Object expired */ - } else if (BAN_CheckObject(o, h->hd[HTTP_HDR_URL].b)) { + } else if (BAN_CheckObject(o, + h->hd[HTTP_HDR_URL].b, oh->hash)) { o->ttl = 0; VSL(SLT_ExpBan, 0, "%u was banned", o->xid); if (o->heap_idx != 0) diff --git a/varnish-cache/bin/varnishd/cache_vrt.c b/varnish-cache/bin/varnishd/cache_vrt.c index bb17e9bd..d8b2d866 100644 --- a/varnish-cache/bin/varnishd/cache_vrt.c +++ b/varnish-cache/bin/varnishd/cache_vrt.c @@ -552,8 +552,8 @@ VRT_int_string(struct sess *sp, int num) /*--------------------------------------------------------------------*/ void -VRT_purge(const char *regexp) +VRT_purge(const char *regexp, int hash) { - AddBan(regexp); + AddBan(regexp, hash); } diff --git a/varnish-cache/bin/varnishd/hash_classic.c b/varnish-cache/bin/varnishd/hash_classic.c index 928a9f03..a52f8667 100644 --- a/varnish-cache/bin/varnishd/hash_classic.c +++ b/varnish-cache/bin/varnishd/hash_classic.c @@ -46,8 +46,6 @@ struct hcl_entry { #define HCL_ENTRY_MAGIC 0x0ba707bf TAILQ_ENTRY(hcl_entry) list; struct hcl_hd *head; - char *key; - unsigned klen; struct objhead *oh; unsigned refcnt; unsigned digest; @@ -146,15 +144,15 @@ hcl_lookup(struct sess *sp, struct objhead *noh) LOCK(&hp->mtx); TAILQ_FOREACH(he, &hp->head, list) { CHECK_OBJ_NOTNULL(he, HCL_ENTRY_MAGIC); - if (sp->lhashptr < he->klen) + if (sp->lhashptr < he->oh->hashlen) continue; - if (sp->lhashptr > he->klen) + if (sp->lhashptr > he->oh->hashlen) break; if (he->digest < digest) continue; if (he->digest > digest) break; - i = HSH_Compare(sp, he->key, he->key + he->klen); + i = HSH_Compare(sp, he->oh); if (i < 0) continue; if (i > 0) @@ -182,19 +180,19 @@ hcl_lookup(struct sess *sp, struct objhead *noh) } UNLOCK(&hp->mtx); - i = sizeof *he2 + sp->lhashptr; - he2 = calloc(i, 1); + he2 = calloc(sizeof *he2, 1); XXXAN(he2); he2->magic = HCL_ENTRY_MAGIC; he2->oh = noh; he2->digest = digest; he2->hash = u1; he2->head = hp; - he2->klen = sp->lhashptr; - noh->hashpriv = he2; - he2->key = (void*)(he2 + 1); - HSH_Copy(sp, he2->key, he2->key + sp->lhashptr); + noh->hashpriv = he2; + noh->hash = malloc(sp->lhashptr); + XXXAN(noh->hash); + noh->hashlen = sp->lhashptr; + HSH_Copy(sp, noh); } assert(he2 == NULL); /* FlexeLint */ INCOMPL(); diff --git a/varnish-cache/bin/varnishd/hash_simple_list.c b/varnish-cache/bin/varnishd/hash_simple_list.c index d5158af3..ba265274 100644 --- a/varnish-cache/bin/varnishd/hash_simple_list.c +++ b/varnish-cache/bin/varnishd/hash_simple_list.c @@ -44,8 +44,6 @@ struct hsl_entry { TAILQ_ENTRY(hsl_entry) list; - char *key; - int keylen; struct objhead *obj; unsigned refcnt; }; @@ -80,7 +78,7 @@ hsl_lookup(struct sess *sp, struct objhead *nobj) LOCK(&hsl_mutex); TAILQ_FOREACH(he, &hsl_head, list) { - i = HSH_Compare(sp, he->key, he->key + he->keylen); + i = HSH_Compare(sp, he->obj); if (i < 0) continue; if (i > 0) @@ -94,14 +92,17 @@ hsl_lookup(struct sess *sp, struct objhead *nobj) UNLOCK(&hsl_mutex); return (NULL); } - he2 = calloc(sizeof *he2 + sp->lhashptr, 1); + he2 = calloc(sizeof *he2, 1); XXXAN(he2); he2->obj = nobj; he2->refcnt = 1; - he2->key = (void*)(he2 + 1); - he2->keylen = sp->lhashptr; - HSH_Copy(sp, he2->key, he2->key + he2->keylen); + nobj->hashpriv = he2; + nobj->hash = malloc(sp->lhashptr); + XXXAN(nobj->hash); + nobj->hashlen = sp->lhashptr; + HSH_Copy(sp, nobj); + if (he != NULL) TAILQ_INSERT_BEFORE(he, he2, list); else diff --git a/varnish-cache/include/cli.h b/varnish-cache/include/cli.h index 2852b208..931884a9 100644 --- a/varnish-cache/include/cli.h +++ b/varnish-cache/include/cli.h @@ -63,8 +63,15 @@ #define CLI_URL_PURGE \ "url.purge", \ "url.purge ", \ - "\tAll urls matching regexp will consider currently cached\n" \ - "\tobjects obsolete", \ + "\tAll objects where the urls matches regexp will be " \ + "marked obsolete.", \ + 1, 1 + +#define CLI_HASH_PURGE \ + "hash.purge", \ + "hash.purge ", \ + "\tAll objects where the hash string matches regexp will be " \ + "marked obsolete.", \ 1, 1 #define CLI_URL_STATUS \ diff --git a/varnish-cache/include/vrt.h b/varnish-cache/include/vrt.h index 7edf14f4..840aaf04 100644 --- a/varnish-cache/include/vrt.h +++ b/varnish-cache/include/vrt.h @@ -70,7 +70,7 @@ int VRT_re_match(const char *, void *re); int VRT_re_test(struct vsb *, const char *, int sub); const char *VRT_regsub(struct sess *sp, const char *, void *, const char *); -void VRT_purge(const char *); +void VRT_purge(const char *, int hash); void VRT_count(struct sess *, unsigned); int VRT_rewrite(const char *, const char *); diff --git a/varnish-cache/lib/libvcl/vcc_action.c b/varnish-cache/lib/libvcl/vcc_action.c index 6ad2cdad..5cad91ea 100644 --- a/varnish-cache/lib/libvcl/vcc_action.c +++ b/varnish-cache/lib/libvcl/vcc_action.c @@ -273,12 +273,12 @@ parse_remove(struct tokenlist *tl) /*--------------------------------------------------------------------*/ static void -parse_purge(struct tokenlist *tl) +parse_purge_url(struct tokenlist *tl) { vcc_NextToken(tl); - Fb(tl, 0, "VRT_purge("); + Fb(tl, 1, "VRT_purge("); Expect(tl, '('); vcc_NextToken(tl); @@ -290,7 +290,31 @@ parse_purge(struct tokenlist *tl) Expect(tl, ')'); vcc_NextToken(tl); - Fb(tl, 0, ");"); + Fb(tl, 0, ", 0);\n"); +} + + +/*--------------------------------------------------------------------*/ + +static void +parse_purge_hash(struct tokenlist *tl) +{ + + vcc_NextToken(tl); + + Fb(tl, 1, "VRT_purge("); + + Expect(tl, '('); + vcc_NextToken(tl); + + if (!vcc_StringVal(tl)) { + vcc_ExpectedStringval(tl); + return; + } + + Expect(tl, ')'); + vcc_NextToken(tl); + Fb(tl, 0, ", 1);\n"); } @@ -310,7 +334,12 @@ static struct action_table { { "call", parse_call }, { "set", parse_set }, { "remove", parse_remove }, - { "purge", parse_purge }, + { "purge_url", parse_purge_url }, + { "purge_hash", parse_purge_hash }, + + /* XXX: Compat remove in 1.2/2.0 */ + { "purge", parse_purge_url }, + { NULL, NULL } }; diff --git a/varnish-cache/lib/libvcl/vcc_fixed_token.c b/varnish-cache/lib/libvcl/vcc_fixed_token.c index 3a0dd45f..60af0017 100644 --- a/varnish-cache/lib/libvcl/vcc_fixed_token.c +++ b/varnish-cache/lib/libvcl/vcc_fixed_token.c @@ -428,7 +428,7 @@ vcl_output_lang_h(struct vsb *sb) vsb_cat(sb, "int VRT_re_test(struct vsb *, const char *, int sub);\n"); vsb_cat(sb, "const char *VRT_regsub(struct sess *sp, const char *, void *, const char *);\n"); vsb_cat(sb, "\n"); - vsb_cat(sb, "void VRT_purge(const char *);\n"); + vsb_cat(sb, "void VRT_purge(const char *, int hash);\n"); vsb_cat(sb, "\n"); vsb_cat(sb, "void VRT_count(struct sess *, unsigned);\n"); vsb_cat(sb, "int VRT_rewrite(const char *, const char *);\n"); -- 2.39.5