Commit c4c8f2fa authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Split the datastructures we use to construct bans (ban_proto)

from the data structure we use to store and operate on the ban (ban).
parent 9339f1ae
...@@ -102,6 +102,7 @@ enum { ...@@ -102,6 +102,7 @@ enum {
struct VSC_C_lck; struct VSC_C_lck;
struct ban; struct ban;
struct ban_proto;
struct backend; struct backend;
struct busyobj; struct busyobj;
struct cli; struct cli;
...@@ -657,11 +658,11 @@ typedef enum htc_status_e htc_complete_f(struct http_conn *); ...@@ -657,11 +658,11 @@ typedef enum htc_status_e htc_complete_f(struct http_conn *);
/* cache_ban.c */ /* cache_ban.c */
/* for constructing bans */ /* for constructing bans */
struct ban *BAN_New(void); struct ban_proto *BAN_Build(void);
int BAN_AddTest(struct ban *, const char *, const char *, const char *); const char *BAN_AddTest(struct ban_proto *,
void BAN_Free(struct ban *b); const char *, const char *, const char *);
char *BAN_Insert(struct ban *b); const char *BAN_Commit(struct ban_proto *b);
void BAN_Free_Errormsg(char *); void BAN_Abandon(struct ban_proto *b);
/* for stevedoes resurrecting bans */ /* for stevedoes resurrecting bans */
void BAN_Hold(void); void BAN_Hold(void);
......
...@@ -45,7 +45,6 @@ struct lock ban_mtx; ...@@ -45,7 +45,6 @@ struct lock ban_mtx;
int ban_shutdown; int ban_shutdown;
struct banhead_s ban_head = VTAILQ_HEAD_INITIALIZER(ban_head); struct banhead_s ban_head = VTAILQ_HEAD_INITIALIZER(ban_head);
struct ban * volatile ban_start; struct ban * volatile ban_start;
struct ban *ban_magic;
static pthread_t ban_thread; static pthread_t ban_thread;
static int ban_holds; static int ban_holds;
...@@ -73,23 +72,6 @@ ban_alloc(void) ...@@ -73,23 +72,6 @@ ban_alloc(void)
return (b); return (b);
} }
struct ban *
BAN_New(void)
{
struct ban *b;
b = ban_alloc();
if (b != NULL) {
b->vsb = VSB_new_auto();
if (b->vsb == NULL) {
FREE_OBJ(b);
return (NULL);
}
VTAILQ_INIT(&b->objcore);
}
return (b);
}
void void
BAN_Free(struct ban *b) BAN_Free(struct ban *b)
{ {
...@@ -98,8 +80,6 @@ BAN_Free(struct ban *b) ...@@ -98,8 +80,6 @@ BAN_Free(struct ban *b)
AZ(b->refcount); AZ(b->refcount);
assert(VTAILQ_EMPTY(&b->objcore)); assert(VTAILQ_EMPTY(&b->objcore));
if (b->vsb != NULL)
VSB_delete(b->vsb);
if (b->spec != NULL) if (b->spec != NULL)
free(b->spec); free(b->spec);
FREE_OBJ(b); FREE_OBJ(b);
...@@ -595,8 +575,8 @@ static void ...@@ -595,8 +575,8 @@ static void
ccf_ban(struct cli *cli, const char * const *av, void *priv) ccf_ban(struct cli *cli, const char * const *av, void *priv)
{ {
int narg, i; int narg, i;
struct ban *b; struct ban_proto *bp;
char *p; const char *err = NULL;
(void)priv; (void)priv;
...@@ -616,19 +596,24 @@ ccf_ban(struct cli *cli, const char * const *av, void *priv) ...@@ -616,19 +596,24 @@ ccf_ban(struct cli *cli, const char * const *av, void *priv)
} }
} }
b = BAN_New(); bp = BAN_Build();
if (b == NULL) { if (bp == NULL) {
VCLI_Out(cli, "Out of Memory"); VCLI_Out(cli, "Out of Memory");
VCLI_SetResult(cli, CLIS_CANT); VCLI_SetResult(cli, CLIS_CANT);
return; return;
} }
for (i = 0; i < narg; i += 4) for (i = 0; i < narg; i += 4) {
if (BAN_AddTest(b, av[i + 2], av[i + 3], av[i + 4])) err = BAN_AddTest(bp, av[i + 2], av[i + 3], av[i + 4]);
if (err)
break; break;
p = BAN_Insert(b); }
if (p != NULL) {
VCLI_Out(cli, "%s", p); if (err == NULL)
BAN_Free_Errormsg(p); err = BAN_Commit(bp);
if (err != NULL) {
VCLI_Out(cli, "%s", err);
BAN_Abandon(bp);
VCLI_SetResult(cli, CLIS_PARAM); VCLI_SetResult(cli, CLIS_PARAM);
} }
} }
...@@ -679,6 +664,7 @@ static void ...@@ -679,6 +664,7 @@ static void
ccf_ban_list(struct cli *cli, const char * const *av, void *priv) ccf_ban_list(struct cli *cli, const char * const *av, void *priv)
{ {
struct ban *b, *bl; struct ban *b, *bl;
int64_t o;
(void)av; (void)av;
(void)priv; (void)priv;
...@@ -691,14 +677,14 @@ ccf_ban_list(struct cli *cli, const char * const *av, void *priv) ...@@ -691,14 +677,14 @@ ccf_ban_list(struct cli *cli, const char * const *av, void *priv)
VCLI_Out(cli, "Present bans:\n"); VCLI_Out(cli, "Present bans:\n");
VTAILQ_FOREACH(b, &ban_head, list) { VTAILQ_FOREACH(b, &ban_head, list) {
VCLI_Out(cli, "%10.6f %5u %s", ban_time(b->spec), o = bl == b ? 1 : 0;
bl == b ? b->refcount - 1 : b->refcount, VCLI_Out(cli, "%10.6f %5ju %s", ban_time(b->spec),
(intmax_t)b->refcount - o,
b->flags & BANS_FLAG_COMPLETED ? "C" : " "); b->flags & BANS_FLAG_COMPLETED ? "C" : " ");
if (DO_DEBUG(DBG_LURKER)) { if (DO_DEBUG(DBG_LURKER)) {
VCLI_Out(cli, "%s%s%s %p ", VCLI_Out(cli, "%s%s %p ",
b->flags & BANS_FLAG_REQ ? "R" : "-", b->flags & BANS_FLAG_REQ ? "R" : "-",
b->flags & BANS_FLAG_OBJ ? "O" : "-", b->flags & BANS_FLAG_OBJ ? "O" : "-",
b->flags & BANS_FLAG_ERROR ? "E" : "-",
b); b);
} }
VCLI_Out(cli, " "); VCLI_Out(cli, " ");
...@@ -732,6 +718,7 @@ static struct cli_proto ban_cmds[] = { ...@@ -732,6 +718,7 @@ static struct cli_proto ban_cmds[] = {
void void
BAN_Compile(void) BAN_Compile(void)
{ {
struct ban *b;
/* /*
* All bans have been read from all persistent stevedores. Export * All bans have been read from all persistent stevedores. Export
...@@ -743,8 +730,9 @@ BAN_Compile(void) ...@@ -743,8 +730,9 @@ BAN_Compile(void)
Lck_Lock(&ban_mtx); Lck_Lock(&ban_mtx);
/* Do late reporting of ban_magic */ /* Report the place-holder ban */
AZ(STV_BanInfo(BI_NEW, ban_magic->spec, ban_len(ban_magic->spec))); b = VTAILQ_FIRST(&ban_head);
AZ(STV_BanInfo(BI_NEW, b->spec, ban_len(b->spec)));
ban_export(); ban_export();
...@@ -757,16 +745,19 @@ BAN_Compile(void) ...@@ -757,16 +745,19 @@ BAN_Compile(void)
void void
BAN_Init(void) BAN_Init(void)
{ {
struct ban_proto *bp;
Lck_New(&ban_mtx, lck_ban); Lck_New(&ban_mtx, lck_ban);
CLI_AddFuncs(ban_cmds); CLI_AddFuncs(ban_cmds);
ban_magic = BAN_New();
AN(ban_magic);
AZ(BAN_Insert(ban_magic));
Lck_Lock(&ban_mtx);
ban_mark_completed(ban_magic);
ban_holds = 1; ban_holds = 1;
/* Add a placeholder ban */
bp = BAN_Build();
AN(bp);
AZ(BAN_Commit(bp));
Lck_Lock(&ban_mtx);
ban_mark_completed(VTAILQ_FIRST(&ban_head));
Lck_Unlock(&ban_mtx); Lck_Unlock(&ban_mtx);
} }
......
...@@ -73,7 +73,6 @@ ...@@ -73,7 +73,6 @@
#define BANS_FLAG_OBJ (1<<1) #define BANS_FLAG_OBJ (1<<1)
#define BANS_FLAG_COMPLETED (1<<2) #define BANS_FLAG_COMPLETED (1<<2)
#define BANS_FLAG_HTTP (1<<3) #define BANS_FLAG_HTTP (1<<3)
#define BANS_FLAG_ERROR (1<<4)
#define BANS_OPER_EQ 0x10 #define BANS_OPER_EQ 0x10
#define BANS_OPER_NEQ 0x11 #define BANS_OPER_NEQ 0x11
...@@ -90,13 +89,12 @@ ...@@ -90,13 +89,12 @@
struct ban { struct ban {
unsigned magic; unsigned magic;
#define BAN_MAGIC 0x700b08ea #define BAN_MAGIC 0x700b08ea
unsigned flags; /* BANS_FLAG_* */
VTAILQ_ENTRY(ban) list; VTAILQ_ENTRY(ban) list;
VTAILQ_ENTRY(ban) l_list; VTAILQ_ENTRY(ban) l_list;
int refcount; int64_t refcount;
unsigned flags; /* BANS_FLAG_* */
VTAILQ_HEAD(,objcore) objcore; VTAILQ_HEAD(,objcore) objcore;
struct vsb *vsb;
uint8_t *spec; uint8_t *spec;
}; };
...@@ -107,7 +105,6 @@ extern struct lock ban_mtx; ...@@ -107,7 +105,6 @@ extern struct lock ban_mtx;
extern int ban_shutdown; extern int ban_shutdown;
extern struct banhead_s ban_head; extern struct banhead_s ban_head;
extern struct ban * volatile ban_start; extern struct ban * volatile ban_start;
extern struct ban *ban_magic;
void ban_mark_completed(struct ban *b); void ban_mark_completed(struct ban *b);
unsigned ban_len(const uint8_t *banspec); unsigned ban_len(const uint8_t *banspec);
...@@ -116,3 +113,4 @@ int ban_evaluate(struct worker *wrk, const uint8_t *bs, struct objcore *oc, ...@@ -116,3 +113,4 @@ int ban_evaluate(struct worker *wrk, const uint8_t *bs, struct objcore *oc,
const struct http *reqhttp, unsigned *tests); const struct http *reqhttp, unsigned *tests);
double ban_time(const uint8_t *banspec); double ban_time(const uint8_t *banspec);
int ban_equal(const uint8_t *bs1, const uint8_t *bs2); int ban_equal(const uint8_t *bs1, const uint8_t *bs2);
void BAN_Free(struct ban *b);
...@@ -38,6 +38,15 @@ ...@@ -38,6 +38,15 @@
#include "vend.h" #include "vend.h"
#include "vtim.h" #include "vtim.h"
struct ban_proto {
unsigned magic;
#define BAN_PROTO_MAGIC 0xd8adc494
unsigned flags; /* BANS_FLAG_* */
struct vsb *vsb;
char *err;
};
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
* Variables we can purge on * Variables we can purge on
*/ */
...@@ -53,41 +62,83 @@ static const struct pvar { ...@@ -53,41 +62,83 @@ static const struct pvar {
{ 0, 0, 0} { 0, 0, 0}
}; };
/*--------------------------------------------------------------------
*/
static char ban_build_err_no_mem[] = "No Memory";
/*--------------------------------------------------------------------
*/
struct ban_proto *
BAN_Build(void)
{
struct ban_proto *bp;
ALLOC_OBJ(bp, BAN_PROTO_MAGIC);
if (bp == NULL)
return (bp);
bp->vsb = VSB_new_auto();
if (bp->vsb == NULL) {
FREE_OBJ(bp);
return (NULL);
}
return (bp);
}
void
BAN_Abandon(struct ban_proto *bp)
{
CHECK_OBJ_NOTNULL(bp, BAN_PROTO_MAGIC);
VSB_delete(bp->vsb);
if (bp->err != NULL && bp->err != ban_build_err_no_mem)
REPLACE(bp->err, NULL);
FREE_OBJ(bp);
}
/*--------------------------------------------------------------------
*/
static void static void
ban_add_lump(const struct ban *b, const void *p, uint32_t len) ban_add_lump(const struct ban_proto *bp, const void *p, uint32_t len)
{ {
uint8_t buf[sizeof len]; uint8_t buf[sizeof len];
buf[0] = 0xff; buf[0] = 0xff;
while (VSB_len(b->vsb) & PALGN) while (VSB_len(bp->vsb) & PALGN)
VSB_bcat(b->vsb, buf, 1); VSB_bcat(bp->vsb, buf, 1);
vbe32enc(buf, len); vbe32enc(buf, len);
VSB_bcat(b->vsb, buf, sizeof buf); VSB_bcat(bp->vsb, buf, sizeof buf);
VSB_bcat(b->vsb, p, len); VSB_bcat(bp->vsb, p, len);
} }
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
*/ */
static int static const char *
ban_error(struct ban *b, const char *fmt, ...) ban_error(struct ban_proto *bp, const char *fmt, ...)
{ {
va_list ap; va_list ap;
CHECK_OBJ_NOTNULL(b, BAN_MAGIC); CHECK_OBJ_NOTNULL(bp, BAN_PROTO_MAGIC);
AN(b->vsb); AN(bp->vsb);
/* First error is sticky */ /* First error is sticky */
if (!(b->flags & BANS_FLAG_ERROR)) { if (bp->err == NULL) {
b->flags |= BANS_FLAG_ERROR; if (fmt == ban_build_err_no_mem) {
bp->err = ban_build_err_no_mem;
/* Record the error message in the vsb */ } else {
VSB_clear(b->vsb); /* Record the error message in the vsb */
va_start(ap, fmt); VSB_clear(bp->vsb);
(void)VSB_vprintf(b->vsb, fmt, ap); va_start(ap, fmt);
va_end(ap); (void)VSB_vprintf(bp->vsb, fmt, ap);
va_end(ap);
AZ(VSB_finish(bp->vsb));
bp->err = VSB_data(bp->vsb);
}
} }
return (-1); return (bp->err);
} }
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
...@@ -96,24 +147,24 @@ ban_error(struct ban *b, const char *fmt, ...) ...@@ -96,24 +147,24 @@ ban_error(struct ban *b, const char *fmt, ...)
*/ */
static void static void
ban_parse_http(const struct ban *b, const char *a1) ban_parse_http(const struct ban_proto *bp, const char *a1)
{ {
int l; int l;
l = strlen(a1) + 1; l = strlen(a1) + 1;
assert(l <= 127); assert(l <= 127);
VSB_putc(b->vsb, (char)l); VSB_putc(bp->vsb, (char)l);
VSB_cat(b->vsb, a1); VSB_cat(bp->vsb, a1);
VSB_putc(b->vsb, ':'); VSB_putc(bp->vsb, ':');
VSB_putc(b->vsb, '\0'); VSB_putc(bp->vsb, '\0');
} }
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
* Parse and add a ban test specification * Parse and add a ban test specification
*/ */
static int static const char *
ban_parse_regexp(struct ban *b, const char *a3) ban_parse_regexp(struct ban_proto *bp, const char *a3)
{ {
const char *error; const char *error;
int erroroffset, rc; int erroroffset, rc;
...@@ -122,10 +173,10 @@ ban_parse_regexp(struct ban *b, const char *a3) ...@@ -122,10 +173,10 @@ ban_parse_regexp(struct ban *b, const char *a3)
re = pcre_compile(a3, 0, &error, &erroroffset, NULL); re = pcre_compile(a3, 0, &error, &erroroffset, NULL);
if (re == NULL) if (re == NULL)
return (ban_error(b, "Regex compile error: %s", error)); return (ban_error(bp, "Regex compile error: %s", error));
rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &sz); rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &sz);
AZ(rc); AZ(rc);
ban_add_lump(b, re, sz); ban_add_lump(bp, re, sz);
pcre_free(re); pcre_free(re);
return (0); return (0);
} }
...@@ -134,55 +185,56 @@ ban_parse_regexp(struct ban *b, const char *a3) ...@@ -134,55 +185,56 @@ ban_parse_regexp(struct ban *b, const char *a3)
* Add a (and'ed) test-condition to a ban * Add a (and'ed) test-condition to a ban
*/ */
int const char *
BAN_AddTest(struct ban *b, const char *a1, const char *a2, const char *a3) BAN_AddTest(struct ban_proto *bp,
const char *a1, const char *a2, const char *a3)
{ {
const struct pvar *pv; const struct pvar *pv;
int i; const char *err;
CHECK_OBJ_NOTNULL(b, BAN_MAGIC); CHECK_OBJ_NOTNULL(bp, BAN_PROTO_MAGIC);
AN(b->vsb); AN(bp->vsb);
AN(a1); AN(a1);
AN(a2); AN(a2);
AN(a3); AN(a3);
if (b->flags & BANS_FLAG_ERROR) if (bp->err != NULL)
return (-1); return (bp->err);
for (pv = pvars; pv->name != NULL; pv++) for (pv = pvars; pv->name != NULL; pv++)
if (!strncmp(a1, pv->name, strlen(pv->name))) if (!strncmp(a1, pv->name, strlen(pv->name)))
break; break;
if (pv->name == NULL) if (pv->name == NULL)
return (ban_error(b, return (ban_error(bp,
"Unknown or unsupported field \"%s\"", a1)); "Unknown or unsupported field \"%s\"", a1));
b->flags |= pv->flag; bp->flags |= pv->flag;
VSB_putc(b->vsb, pv->tag); VSB_putc(bp->vsb, pv->tag);
if (pv->flag & BANS_FLAG_HTTP) if (pv->flag & BANS_FLAG_HTTP)
ban_parse_http(b, a1 + strlen(pv->name)); ban_parse_http(bp, a1 + strlen(pv->name));
ban_add_lump(b, a3, strlen(a3) + 1); ban_add_lump(bp, a3, strlen(a3) + 1);
if (!strcmp(a2, "~")) { if (!strcmp(a2, "~")) {
VSB_putc(b->vsb, BANS_OPER_MATCH); VSB_putc(bp->vsb, BANS_OPER_MATCH);
i = ban_parse_regexp(b, a3); err = ban_parse_regexp(bp, a3);
if (i) if (err)
return (i); return (err);
} else if (!strcmp(a2, "!~")) { } else if (!strcmp(a2, "!~")) {
VSB_putc(b->vsb, BANS_OPER_NMATCH); VSB_putc(bp->vsb, BANS_OPER_NMATCH);
i = ban_parse_regexp(b, a3); err = ban_parse_regexp(bp, a3);
if (i) if (err)
return (i); return (err);
} else if (!strcmp(a2, "==")) { } else if (!strcmp(a2, "==")) {
VSB_putc(b->vsb, BANS_OPER_EQ); VSB_putc(bp->vsb, BANS_OPER_EQ);
} else if (!strcmp(a2, "!=")) { } else if (!strcmp(a2, "!=")) {
VSB_putc(b->vsb, BANS_OPER_NEQ); VSB_putc(bp->vsb, BANS_OPER_NEQ);
} else { } else {
return (ban_error(b, return (ban_error(bp,
"expected conditional (~, !~, == or !=) got \"%s\"", a2)); "expected conditional (~, !~, == or !=) got \"%s\"", a2));
} }
return (0); return (NULL);
} }
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
...@@ -197,121 +249,80 @@ BAN_AddTest(struct ban *b, const char *a1, const char *a2, const char *a3) ...@@ -197,121 +249,80 @@ BAN_AddTest(struct ban *b, const char *a1, const char *a2, const char *a3)
* deleted. * deleted.
*/ */
static char ban_error_nomem[] = "Could not get memory"; const char *
BAN_Commit(struct ban_proto *bp)
static char *
ban_ins_error(const char *p)
{ {
char *r = NULL; struct ban *b, *bi;
if (p != NULL)
r = strdup(p);
if (r == NULL)
r = ban_error_nomem;
return (r);
}
void
BAN_Free_Errormsg(char *p)
{
if (p != ban_error_nomem)
free(p);
}
char *
BAN_Insert(struct ban *b)
{
struct ban *bi, *be;
ssize_t ln; ssize_t ln;
double t0; double t0;
char *p;
CHECK_OBJ_NOTNULL(b, BAN_MAGIC); CHECK_OBJ_NOTNULL(bp, BAN_PROTO_MAGIC);
AN(b->vsb); AN(bp->vsb);
if (ban_shutdown) { if (ban_shutdown)
BAN_Free(b); return (ban_error(bp, "Shutting down"));
return (ban_ins_error("Shutting down"));
}
AZ(VSB_finish(b->vsb)); AZ(VSB_finish(bp->vsb));
ln = VSB_len(b->vsb); ln = VSB_len(bp->vsb);
assert(ln >= 0); assert(ln >= 0);
if (b->flags & BANS_FLAG_ERROR) { ALLOC_OBJ(b, BAN_MAGIC);
p = ban_ins_error(VSB_data(b->vsb)); if (b == NULL)
BAN_Free(b); return (ban_error(bp, ban_build_err_no_mem));
return (p); VTAILQ_INIT(&b->objcore);
}
b->spec = malloc(ln + BANS_HEAD_LEN); b->spec = malloc(ln + BANS_HEAD_LEN);
if (b->spec == NULL) { if (b->spec == NULL) {
BAN_Free(b); free(b);
return (ban_ins_error(NULL)); return (ban_error(bp, ban_build_err_no_mem));
} }
b->flags = bp->flags;
memset(b->spec, 0, BANS_HEAD_LEN); memset(b->spec, 0, BANS_HEAD_LEN);
t0 = VTIM_real(); t0 = VTIM_real();
memcpy(b->spec + BANS_TIMESTAMP, &t0, sizeof t0); memcpy(b->spec + BANS_TIMESTAMP, &t0, sizeof t0);
b->spec[BANS_FLAGS] = b->flags & 0xff; b->spec[BANS_FLAGS] = b->flags & 0xff;
memcpy(b->spec + BANS_HEAD_LEN, VSB_data(b->vsb), ln); memcpy(b->spec + BANS_HEAD_LEN, VSB_data(bp->vsb), ln);
ln += BANS_HEAD_LEN; ln += BANS_HEAD_LEN;
vbe32enc(b->spec + BANS_LENGTH, ln); vbe32enc(b->spec + BANS_LENGTH, ln);
VSB_delete(b->vsb);
b->vsb = NULL;
Lck_Lock(&ban_mtx); Lck_Lock(&ban_mtx);
if (ban_shutdown) { if (ban_shutdown) {
/* Check again, we might have raced */ /* We could have raced a shutdown */
Lck_Unlock(&ban_mtx); Lck_Unlock(&ban_mtx);
BAN_Free(b); BAN_Free(b);
return (ban_ins_error("Shutting down")); return (ban_error(bp, "Shutting down"));
} }
bi = VTAILQ_FIRST(&ban_head);
VTAILQ_INSERT_HEAD(&ban_head, b, list); VTAILQ_INSERT_HEAD(&ban_head, b, list);
ban_start = b; ban_start = b;
VSC_C_main->bans++; VSC_C_main->bans++;
VSC_C_main->bans_added++; VSC_C_main->bans_added++;
VSC_C_main->bans_persisted_bytes += ln;
if (b->flags & BANS_FLAG_OBJ) if (b->flags & BANS_FLAG_OBJ)
VSC_C_main->bans_obj++; VSC_C_main->bans_obj++;
if (b->flags & BANS_FLAG_REQ) if (b->flags & BANS_FLAG_REQ)
VSC_C_main->bans_req++; VSC_C_main->bans_req++;
be = VTAILQ_LAST(&ban_head, banhead_s); if (bi != NULL)
if (cache_param->ban_dups && be != b) ban_info(BI_NEW, b->spec, ln); /* Notify stevedores */
be->refcount++;
else if (cache_param->ban_dups) {
be = NULL; /* Hunt down duplicates, and mark them as completed */
for (bi = VTAILQ_NEXT(b, list); bi != NULL;
/* ban_magic is magic, and needs to be inserted early to give bi = VTAILQ_NEXT(bi, list)) {
* a handle to grab a ref on. We don't report it here as the if (!(bi->flags & BANS_FLAG_COMPLETED) &&
* stevedores will not be opened and ready to accept it ban_equal(b->spec, bi->spec)) {
* yet. Instead it is reported on BAN_Compile, which is after ban_mark_completed(bi);
* the stevedores has been opened, but before any new objects VSC_C_main->bans_dups++;
* can have entered the cache (thus no objects in the mean }
* time depending on ban_magic in the list) */ }
VSC_C_main->bans_persisted_bytes += ln;
if (b != ban_magic)
ban_info(BI_NEW, b->spec, ln); /* Notify stevedores */
Lck_Unlock(&ban_mtx);
if (be == NULL)
return (NULL);
/* Hunt down duplicates, and mark them as completed */
bi = b;
Lck_Lock(&ban_mtx);
while (!ban_shutdown && bi != be) {
bi = VTAILQ_NEXT(bi, list);
if (bi->flags & BANS_FLAG_COMPLETED)
continue;
if (!ban_equal(b->spec, bi->spec))
continue;
ban_mark_completed(bi);
VSC_C_main->bans_dups++;
} }
be->refcount--;
Lck_Unlock(&ban_mtx); Lck_Unlock(&ban_mtx);
BAN_Abandon(bp);
return (NULL); return (NULL);
} }
...@@ -395,15 +395,16 @@ VRT_ban_string(VRT_CTX, const char *str) ...@@ -395,15 +395,16 @@ VRT_ban_string(VRT_CTX, const char *str)
{ {
char *a1, *a2, *a3; char *a1, *a2, *a3;
char **av; char **av;
struct ban *b; struct ban_proto *bp;
const char *err;
int i; int i;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AN(ctx->vsl); AN(ctx->vsl);
AN(str); AN(str);
b = BAN_New(); bp = BAN_Build();
if (b == NULL) { if (bp == NULL) {
VSLb(ctx->vsl, SLT_VCL_Error, "ban(): Out of Memory"); VSLb(ctx->vsl, SLT_VCL_Error, "ban(): Out of Memory");
return; return;
} }
...@@ -412,7 +413,7 @@ VRT_ban_string(VRT_CTX, const char *str) ...@@ -412,7 +413,7 @@ VRT_ban_string(VRT_CTX, const char *str)
if (av[0] != NULL) { if (av[0] != NULL) {
VSLb(ctx->vsl, SLT_VCL_Error, "ban(): %s", av[0]); VSLb(ctx->vsl, SLT_VCL_Error, "ban(): %s", av[0]);
VAV_Free(av); VAV_Free(av);
BAN_Free(b); BAN_Abandon(bp);
return; return;
} }
for (i = 0; ;) { for (i = 0; ;) {
...@@ -434,13 +435,17 @@ VRT_ban_string(VRT_CTX, const char *str) ...@@ -434,13 +435,17 @@ VRT_ban_string(VRT_CTX, const char *str)
"ban(): Expected second operand."); "ban(): Expected second operand.");
break; break;
} }
if (BAN_AddTest(b, a1, a2, a3) || av[++i] == NULL) { err = BAN_AddTest(bp, a1, a2, a3);
a1 = BAN_Insert(b); if (err) {
if (a1 != NULL) { VSLb(ctx->vsl, SLT_VCL_Error, "ban(): %s", err);
VSLb(ctx->vsl, SLT_VCL_Error, break;
"ban(): %s", a1); }
BAN_Free_Errormsg(a1); if (av[++i] == NULL) {
} err = BAN_Commit(bp);
if (err == NULL)
bp = NULL;
else
VSLb(ctx->vsl, SLT_VCL_Error, "ban(): %s", err);
break; break;
} }
if (strcmp(av[i], "&&")) { if (strcmp(av[i], "&&")) {
...@@ -450,6 +455,8 @@ VRT_ban_string(VRT_CTX, const char *str) ...@@ -450,6 +455,8 @@ VRT_ban_string(VRT_CTX, const char *str)
break; break;
} }
} }
if (bp != NULL)
BAN_Abandon(bp);
VAV_Free(av); VAV_Free(av);
} }
......
...@@ -106,6 +106,7 @@ ...@@ -106,6 +106,7 @@
-emacro(527, NEEDLESS_RETURN) // unreachable code -emacro(527, NEEDLESS_RETURN) // unreachable code
-sem(BAN_Free, custodial(1))
-sem(EXP_Inject, custodial(1)) -sem(EXP_Inject, custodial(1))
-sem(HSH_Insert, custodial(3)) -sem(HSH_Insert, custodial(3))
-sem(WS_Init, custodial(2)) -sem(WS_Init, custodial(2))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment