[master] 9339f1a Split BAN construction code into a separate source file
Poul-Henning Kamp
phk at FreeBSD.org
Thu Oct 22 17:40:38 CEST 2015
commit 9339f1aea31eba131e3dc116458b8a225b43cd23
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Thu Oct 22 08:53:53 2015 +0000
Split BAN construction code into a separate source file
diff --git a/bin/varnishd/Makefile.am b/bin/varnishd/Makefile.am
index 86906a2..d252c1b 100644
--- a/bin/varnishd/Makefile.am
+++ b/bin/varnishd/Makefile.am
@@ -15,6 +15,7 @@ varnishd_SOURCES = \
cache/cache_backend_probe.c \
cache/cache_backend_tcp.c \
cache/cache_ban.c \
+ cache/cache_ban_build.c \
cache/cache_ban_lurker.c \
cache/cache_busyobj.c \
cache/cache_cli.c \
diff --git a/bin/varnishd/cache/cache_ban.c b/bin/varnishd/cache/cache_ban.c
index e5e03e6..0247d44 100644
--- a/bin/varnishd/cache/cache_ban.c
+++ b/bin/varnishd/cache/cache_ban.c
@@ -40,14 +40,13 @@
#include "vcli_priv.h"
#include "vend.h"
#include "vmb.h"
-#include "vtim.h"
struct lock ban_mtx;
int ban_shutdown;
struct banhead_s ban_head = VTAILQ_HEAD_INITIALIZER(ban_head);
struct ban * volatile ban_start;
+struct ban *ban_magic;
-static struct ban *ban_magic;
static pthread_t ban_thread;
static int ban_holds;
@@ -60,21 +59,6 @@ struct ban_test {
};
/*--------------------------------------------------------------------
- * Variables we can purge on
- */
-
-static const struct pvar {
- const char *name;
- unsigned flag;
- uint8_t tag;
-} pvars[] = {
-#define PVAR(a, b, c) { (a), (b), (c) },
-#include "tbl/ban_vars.h"
-#undef PVAR
- { 0, 0, 0}
-};
-
-/*--------------------------------------------------------------------
* Storage handling of bans
*/
@@ -172,7 +156,7 @@ ban_len(const uint8_t *banspec)
return (u);
}
-static int
+int
ban_equal(const uint8_t *bs1, const uint8_t *bs2)
{
unsigned u;
@@ -209,19 +193,6 @@ ban_mark_completed(struct ban *b)
* Access a lump of bytes in a ban test spec
*/
-static void
-ban_add_lump(const struct ban *b, const void *p, uint32_t len)
-{
- uint8_t buf[sizeof len];
-
- buf[0] = 0xff;
- while (VSB_len(b->vsb) & PALGN)
- VSB_bcat(b->vsb, buf, 1);
- vbe32enc(buf, len);
- VSB_bcat(b->vsb, buf, sizeof buf);
- VSB_bcat(b->vsb, p, len);
-}
-
static const void *
ban_get_lump(const uint8_t **bs)
{
@@ -258,256 +229,6 @@ ban_iter(const uint8_t **bs, struct ban_test *bt)
}
/*--------------------------------------------------------------------
- */
-
-static int
-ban_error(struct ban *b, const char *fmt, ...)
-{
- va_list ap;
-
- CHECK_OBJ_NOTNULL(b, BAN_MAGIC);
- AN(b->vsb);
-
- /* First error is sticky */
- if (!(b->flags & BANS_FLAG_ERROR)) {
- b->flags |= BANS_FLAG_ERROR;
-
- /* Record the error message in the vsb */
- VSB_clear(b->vsb);
- va_start(ap, fmt);
- (void)VSB_vprintf(b->vsb, fmt, ap);
- va_end(ap);
- }
- return (-1);
-}
-
-/*--------------------------------------------------------------------
- * Parse and add a http argument specification
- * Output something which HTTP_GetHdr understands
- */
-
-static void
-ban_parse_http(const struct ban *b, const char *a1)
-{
- int l;
-
- l = strlen(a1) + 1;
- assert(l <= 127);
- VSB_putc(b->vsb, (char)l);
- VSB_cat(b->vsb, a1);
- VSB_putc(b->vsb, ':');
- VSB_putc(b->vsb, '\0');
-}
-
-/*--------------------------------------------------------------------
- * Parse and add a ban test specification
- */
-
-static int
-ban_parse_regexp(struct ban *b, const char *a3)
-{
- const char *error;
- int erroroffset, rc;
- size_t sz;
- pcre *re;
-
- re = pcre_compile(a3, 0, &error, &erroroffset, NULL);
- if (re == NULL)
- return (ban_error(b, "Regex compile error: %s", error));
- rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &sz);
- AZ(rc);
- ban_add_lump(b, re, sz);
- pcre_free(re);
- return (0);
-}
-
-/*--------------------------------------------------------------------
- * Add a (and'ed) test-condition to a ban
- */
-
-int
-BAN_AddTest(struct ban *b, const char *a1, const char *a2, const char *a3)
-{
- const struct pvar *pv;
- int i;
-
- CHECK_OBJ_NOTNULL(b, BAN_MAGIC);
- AN(b->vsb);
- AN(a1);
- AN(a2);
- AN(a3);
-
- if (b->flags & BANS_FLAG_ERROR)
- return (-1);
-
- for (pv = pvars; pv->name != NULL; pv++)
- if (!strncmp(a1, pv->name, strlen(pv->name)))
- break;
-
- if (pv->name == NULL)
- return (ban_error(b,
- "Unknown or unsupported field \"%s\"", a1));
-
- b->flags |= pv->flag;
-
- VSB_putc(b->vsb, pv->tag);
- if (pv->flag & BANS_FLAG_HTTP)
- ban_parse_http(b, a1 + strlen(pv->name));
-
- ban_add_lump(b, a3, strlen(a3) + 1);
- if (!strcmp(a2, "~")) {
- VSB_putc(b->vsb, BANS_OPER_MATCH);
- i = ban_parse_regexp(b, a3);
- if (i)
- return (i);
- } else if (!strcmp(a2, "!~")) {
- VSB_putc(b->vsb, BANS_OPER_NMATCH);
- i = ban_parse_regexp(b, a3);
- if (i)
- return (i);
- } else if (!strcmp(a2, "==")) {
- VSB_putc(b->vsb, BANS_OPER_EQ);
- } else if (!strcmp(a2, "!=")) {
- VSB_putc(b->vsb, BANS_OPER_NEQ);
- } else {
- return (ban_error(b,
- "expected conditional (~, !~, == or !=) got \"%s\"", a2));
- }
- return (0);
-}
-
-/*--------------------------------------------------------------------
- * We maintain ban_start as a pointer to the first element of the list
- * as a separate variable from the VTAILQ, to avoid depending on the
- * internals of the VTAILQ macros. We tacitly assume that a pointer
- * write is always atomic in doing so.
- *
- * Returns:
- * 0: Ban successfully inserted
- * -1: Ban not inserted due to shutdown in progress. The ban has been
- * deleted.
- */
-
-static char ban_error_nomem[] = "Could not get memory";
-
-static char *
-ban_ins_error(const char *p)
-{
- char *r = NULL;
-
- 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;
- double t0;
- char *p;
-
- CHECK_OBJ_NOTNULL(b, BAN_MAGIC);
- AN(b->vsb);
-
- if (ban_shutdown) {
- BAN_Free(b);
- return (ban_ins_error("Shutting down"));
- }
-
- AZ(VSB_finish(b->vsb));
- ln = VSB_len(b->vsb);
- assert(ln >= 0);
-
- if (b->flags & BANS_FLAG_ERROR) {
- p = ban_ins_error(VSB_data(b->vsb));
- BAN_Free(b);
- return (p);
- }
-
- b->spec = malloc(ln + BANS_HEAD_LEN);
- if (b->spec == NULL) {
- BAN_Free(b);
- return (ban_ins_error(NULL));
- }
-
- memset(b->spec, 0, BANS_HEAD_LEN);
- t0 = VTIM_real();
- memcpy(b->spec + BANS_TIMESTAMP, &t0, sizeof t0);
- b->spec[BANS_FLAGS] = b->flags & 0xff;
- memcpy(b->spec + BANS_HEAD_LEN, VSB_data(b->vsb), ln);
- ln += BANS_HEAD_LEN;
- vbe32enc(b->spec + BANS_LENGTH, ln);
-
- VSB_delete(b->vsb);
- b->vsb = NULL;
-
- Lck_Lock(&ban_mtx);
- if (ban_shutdown) {
- /* Check again, we might have raced */
- Lck_Unlock(&ban_mtx);
- BAN_Free(b);
- return (ban_ins_error("Shutting down"));
- }
- VTAILQ_INSERT_HEAD(&ban_head, b, list);
- ban_start = b;
- VSC_C_main->bans++;
- VSC_C_main->bans_added++;
- if (b->flags & BANS_FLAG_OBJ)
- VSC_C_main->bans_obj++;
- if (b->flags & BANS_FLAG_REQ)
- VSC_C_main->bans_req++;
-
- be = VTAILQ_LAST(&ban_head, banhead_s);
- if (cache_param->ban_dups && be != b)
- be->refcount++;
- else
- be = NULL;
-
- /* ban_magic is magic, and needs to be inserted early to give
- * a handle to grab a ref on. We don't report it here as the
- * stevedores will not be opened and ready to accept it
- * yet. Instead it is reported on BAN_Compile, which is after
- * the stevedores has been opened, but before any new objects
- * 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);
-
- return (NULL);
-}
-
-/*--------------------------------------------------------------------
* A new object is created, grab a reference to the newest ban
*/
diff --git a/bin/varnishd/cache/cache_ban.h b/bin/varnishd/cache/cache_ban.h
index ce0ae9e..755b2f4 100644
--- a/bin/varnishd/cache/cache_ban.h
+++ b/bin/varnishd/cache/cache_ban.h
@@ -107,6 +107,7 @@ extern struct lock ban_mtx;
extern int ban_shutdown;
extern struct banhead_s ban_head;
extern struct ban * volatile ban_start;
+extern struct ban *ban_magic;
void ban_mark_completed(struct ban *b);
unsigned ban_len(const uint8_t *banspec);
@@ -114,3 +115,4 @@ void ban_info(enum baninfo event, const uint8_t *ban, unsigned len);
int ban_evaluate(struct worker *wrk, const uint8_t *bs, struct objcore *oc,
const struct http *reqhttp, unsigned *tests);
double ban_time(const uint8_t *banspec);
+int ban_equal(const uint8_t *bs1, const uint8_t *bs2);
diff --git a/bin/varnishd/cache/cache_ban_build.c b/bin/varnishd/cache/cache_ban_build.c
new file mode 100644
index 0000000..ee2f0e7
--- /dev/null
+++ b/bin/varnishd/cache/cache_ban_build.c
@@ -0,0 +1,317 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2015 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * 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.
+ *
+ */
+
+#include "config.h"
+
+#include <pcre.h>
+
+#include "cache.h"
+#include "cache_ban.h"
+
+#include "vend.h"
+#include "vtim.h"
+
+/*--------------------------------------------------------------------
+ * Variables we can purge on
+ */
+
+static const struct pvar {
+ const char *name;
+ unsigned flag;
+ uint8_t tag;
+} pvars[] = {
+#define PVAR(a, b, c) { (a), (b), (c) },
+#include "tbl/ban_vars.h"
+#undef PVAR
+ { 0, 0, 0}
+};
+
+static void
+ban_add_lump(const struct ban *b, const void *p, uint32_t len)
+{
+ uint8_t buf[sizeof len];
+
+ buf[0] = 0xff;
+ while (VSB_len(b->vsb) & PALGN)
+ VSB_bcat(b->vsb, buf, 1);
+ vbe32enc(buf, len);
+ VSB_bcat(b->vsb, buf, sizeof buf);
+ VSB_bcat(b->vsb, p, len);
+}
+
+/*--------------------------------------------------------------------
+ */
+
+static int
+ban_error(struct ban *b, const char *fmt, ...)
+{
+ va_list ap;
+
+ CHECK_OBJ_NOTNULL(b, BAN_MAGIC);
+ AN(b->vsb);
+
+ /* First error is sticky */
+ if (!(b->flags & BANS_FLAG_ERROR)) {
+ b->flags |= BANS_FLAG_ERROR;
+
+ /* Record the error message in the vsb */
+ VSB_clear(b->vsb);
+ va_start(ap, fmt);
+ (void)VSB_vprintf(b->vsb, fmt, ap);
+ va_end(ap);
+ }
+ return (-1);
+}
+
+/*--------------------------------------------------------------------
+ * Parse and add a http argument specification
+ * Output something which HTTP_GetHdr understands
+ */
+
+static void
+ban_parse_http(const struct ban *b, const char *a1)
+{
+ int l;
+
+ l = strlen(a1) + 1;
+ assert(l <= 127);
+ VSB_putc(b->vsb, (char)l);
+ VSB_cat(b->vsb, a1);
+ VSB_putc(b->vsb, ':');
+ VSB_putc(b->vsb, '\0');
+}
+
+/*--------------------------------------------------------------------
+ * Parse and add a ban test specification
+ */
+
+static int
+ban_parse_regexp(struct ban *b, const char *a3)
+{
+ const char *error;
+ int erroroffset, rc;
+ size_t sz;
+ pcre *re;
+
+ re = pcre_compile(a3, 0, &error, &erroroffset, NULL);
+ if (re == NULL)
+ return (ban_error(b, "Regex compile error: %s", error));
+ rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &sz);
+ AZ(rc);
+ ban_add_lump(b, re, sz);
+ pcre_free(re);
+ return (0);
+}
+
+/*--------------------------------------------------------------------
+ * Add a (and'ed) test-condition to a ban
+ */
+
+int
+BAN_AddTest(struct ban *b, const char *a1, const char *a2, const char *a3)
+{
+ const struct pvar *pv;
+ int i;
+
+ CHECK_OBJ_NOTNULL(b, BAN_MAGIC);
+ AN(b->vsb);
+ AN(a1);
+ AN(a2);
+ AN(a3);
+
+ if (b->flags & BANS_FLAG_ERROR)
+ return (-1);
+
+ for (pv = pvars; pv->name != NULL; pv++)
+ if (!strncmp(a1, pv->name, strlen(pv->name)))
+ break;
+
+ if (pv->name == NULL)
+ return (ban_error(b,
+ "Unknown or unsupported field \"%s\"", a1));
+
+ b->flags |= pv->flag;
+
+ VSB_putc(b->vsb, pv->tag);
+ if (pv->flag & BANS_FLAG_HTTP)
+ ban_parse_http(b, a1 + strlen(pv->name));
+
+ ban_add_lump(b, a3, strlen(a3) + 1);
+ if (!strcmp(a2, "~")) {
+ VSB_putc(b->vsb, BANS_OPER_MATCH);
+ i = ban_parse_regexp(b, a3);
+ if (i)
+ return (i);
+ } else if (!strcmp(a2, "!~")) {
+ VSB_putc(b->vsb, BANS_OPER_NMATCH);
+ i = ban_parse_regexp(b, a3);
+ if (i)
+ return (i);
+ } else if (!strcmp(a2, "==")) {
+ VSB_putc(b->vsb, BANS_OPER_EQ);
+ } else if (!strcmp(a2, "!=")) {
+ VSB_putc(b->vsb, BANS_OPER_NEQ);
+ } else {
+ return (ban_error(b,
+ "expected conditional (~, !~, == or !=) got \"%s\"", a2));
+ }
+ return (0);
+}
+
+/*--------------------------------------------------------------------
+ * We maintain ban_start as a pointer to the first element of the list
+ * as a separate variable from the VTAILQ, to avoid depending on the
+ * internals of the VTAILQ macros. We tacitly assume that a pointer
+ * write is always atomic in doing so.
+ *
+ * Returns:
+ * 0: Ban successfully inserted
+ * -1: Ban not inserted due to shutdown in progress. The ban has been
+ * deleted.
+ */
+
+static char ban_error_nomem[] = "Could not get memory";
+
+static char *
+ban_ins_error(const char *p)
+{
+ char *r = NULL;
+
+ 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;
+ double t0;
+ char *p;
+
+ CHECK_OBJ_NOTNULL(b, BAN_MAGIC);
+ AN(b->vsb);
+
+ if (ban_shutdown) {
+ BAN_Free(b);
+ return (ban_ins_error("Shutting down"));
+ }
+
+ AZ(VSB_finish(b->vsb));
+ ln = VSB_len(b->vsb);
+ assert(ln >= 0);
+
+ if (b->flags & BANS_FLAG_ERROR) {
+ p = ban_ins_error(VSB_data(b->vsb));
+ BAN_Free(b);
+ return (p);
+ }
+
+ b->spec = malloc(ln + BANS_HEAD_LEN);
+ if (b->spec == NULL) {
+ BAN_Free(b);
+ return (ban_ins_error(NULL));
+ }
+
+ memset(b->spec, 0, BANS_HEAD_LEN);
+ t0 = VTIM_real();
+ memcpy(b->spec + BANS_TIMESTAMP, &t0, sizeof t0);
+ b->spec[BANS_FLAGS] = b->flags & 0xff;
+ memcpy(b->spec + BANS_HEAD_LEN, VSB_data(b->vsb), ln);
+ ln += BANS_HEAD_LEN;
+ vbe32enc(b->spec + BANS_LENGTH, ln);
+
+ VSB_delete(b->vsb);
+ b->vsb = NULL;
+
+ Lck_Lock(&ban_mtx);
+ if (ban_shutdown) {
+ /* Check again, we might have raced */
+ Lck_Unlock(&ban_mtx);
+ BAN_Free(b);
+ return (ban_ins_error("Shutting down"));
+ }
+ VTAILQ_INSERT_HEAD(&ban_head, b, list);
+ ban_start = b;
+ VSC_C_main->bans++;
+ VSC_C_main->bans_added++;
+ if (b->flags & BANS_FLAG_OBJ)
+ VSC_C_main->bans_obj++;
+ if (b->flags & BANS_FLAG_REQ)
+ VSC_C_main->bans_req++;
+
+ be = VTAILQ_LAST(&ban_head, banhead_s);
+ if (cache_param->ban_dups && be != b)
+ be->refcount++;
+ else
+ be = NULL;
+
+ /* ban_magic is magic, and needs to be inserted early to give
+ * a handle to grab a ref on. We don't report it here as the
+ * stevedores will not be opened and ready to accept it
+ * yet. Instead it is reported on BAN_Compile, which is after
+ * the stevedores has been opened, but before any new objects
+ * 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);
+
+ return (NULL);
+}
More information about the varnish-commit
mailing list