pthread_mutex_t mtx;
TAILQ_HEAD(,object) objects;
+ char *hash;
+ unsigned hashlen;
};
/* -------------------------------------------------------------------*/
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);
/* 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);
unsigned gen;
regex_t regexp;
char *ban;
+ int hash;
};
static TAILQ_HEAD(,ban) ban_head = TAILQ_HEAD_INITIALIZER(ban_head);
static struct ban *ban_start;
void
-AddBan(const char *regexp)
+AddBan(const char *regexp, int hash)
{
struct ban *b;
int i;
(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);
}
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;
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);
}
{
(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]);
}
BAN_Init(void)
{
- AddBan("a");
+ AddBan("\001", 0);
}
{ 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 },
}
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);
}
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);
*b++ = '#';
}
*b++ = '\0';
- assert(b <= e);
+ VSL(SLT_Debug, sp->fd, "Hash: %s", obj->hash);
+ assert(b <= obj->hash + obj->hashlen);
}
struct object *
/* 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)
/*--------------------------------------------------------------------*/
void
-VRT_purge(const char *regexp)
+VRT_purge(const char *regexp, int hash)
{
- AddBan(regexp);
+ AddBan(regexp, hash);
}
#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;
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)
}
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();
struct hsl_entry {
TAILQ_ENTRY(hsl_entry) list;
- char *key;
- int keylen;
struct objhead *obj;
unsigned refcnt;
};
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)
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
#define CLI_URL_PURGE \
"url.purge", \
"url.purge <regexp>", \
- "\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 <regexp>", \
+ "\tAll objects where the hash string matches regexp will be " \
+ "marked obsolete.", \
1, 1
#define CLI_URL_STATUS \
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 *);
/*--------------------------------------------------------------------*/
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);
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");
}
{ "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 }
};
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");