struct vcls {
VTAILQ_ENTRY(vcls) list;
- const char *name;
+ char *name;
void *dlh;
struct VCL_conf *conf;
- int discard;
};
/*
VTAILQ_HEAD_INITIALIZER(vcl_head);
-static struct vcls *vcl_active; /* protected by vcl_mtx */
-
static MTX vcl_mtx;
+static struct vcls *vcl_active; /* protected by vcl_mtx */
/*--------------------------------------------------------------------*/
AN(vcl_active);
*vcc = vcl_active->conf;
AN(*vcc);
+ AZ((*vcc)->discard);
(*vcc)->busy++;
UNLOCK(&vcl_mtx);
}
void
VCL_Rel(struct VCL_conf **vcc)
{
- struct vcls *vcl;
struct VCL_conf *vc;
vc = *vcc;
LOCK(&vcl_mtx);
assert(vc->busy > 0);
vc->busy--;
- vcl = vc->priv; /* XXX miniobj */
- if (vc->busy == 0 && vcl_active != vcl) {
- /* XXX: purge backends */
- }
- if (vc->busy == 0 && vcl->discard) {
- VTAILQ_REMOVE(&vcl_head, vcl, list);
- } else {
- vcl = NULL;
- }
+ /*
+ * We do not garbage collect discarded VCL's here, that happens
+ * in VCL_Idle() which is called from the CLI thread.
+ */
UNLOCK(&vcl_mtx);
- if (vcl != NULL) {
- /* XXX: dispose of vcl */
- }
}
/*--------------------------------------------------------------------*/
{
struct vcls *vcl;
- VTAILQ_FOREACH(vcl, &vcl_head, list)
+ ASSERT_CLI();
+ VTAILQ_FOREACH(vcl, &vcl_head, list) {
+ if (vcl->conf->discard)
+ continue;
if (!strcmp(vcl->name, name))
return (vcl);
+ }
return (NULL);
}
{
struct vcls *vcl;
+ ASSERT_CLI();
vcl = vcl_find(name);
if (vcl != NULL) {
cli_out(cli, "Config '%s' already loaded", name);
return (0);
}
+/*--------------------------------------------------------------------
+ * This function is polled from the CLI thread to dispose of any non-busy
+ * VCLs * which have been discarded.
+ */
+
+static void
+VCL_Nuke(struct vcls *vcl)
+{
+
+ ASSERT_CLI();
+ assert(vcl != vcl_active);
+ assert(vcl->conf->discard);
+ assert(vcl->conf->busy == 0);
+ VTAILQ_REMOVE(&vcl_head, vcl, list);
+ vcl->conf->fini_func();
+ free(vcl->name);
+ free(vcl);
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+VCL_Idle(void)
+{
+ struct vcls *vcl, *vcl2;
+
+ ASSERT_CLI();
+ VTAILQ_FOREACH_SAFE(vcl, &vcl_head, list, vcl2)
+ if (vcl->conf->discard && vcl->conf->busy == 0)
+ VCL_Nuke(vcl);
+}
+
/*--------------------------------------------------------------------*/
void
(void)av;
(void)priv;
+ ASSERT_CLI();
VTAILQ_FOREACH(vcl, &vcl_head, list) {
cli_out(cli, "%s %6u %s\n",
vcl == vcl_active ? "* " : " ",
(void)av;
(void)priv;
+ ASSERT_CLI();
if (VCL_Load(av[3], av[2], cli))
cli_result(cli, CLIS_PARAM);
return;
{
struct vcls *vcl;
+ ASSERT_CLI();
(void)av;
(void)priv;
vcl = vcl_find(av[2]);
cli_out(cli, "VCL '%s' unknown", av[2]);
return;
}
- if (vcl->discard) {
- cli_result(cli, CLIS_PARAM);
- cli_out(cli, "VCL %s already discarded", av[2]);
- return;
- }
LOCK(&vcl_mtx);
if (vcl == vcl_active) {
UNLOCK(&vcl_mtx);
cli_out(cli, "VCL %s is the active VCL", av[2]);
return;
}
- vcl->discard = 1;
- if (vcl->conf->busy == 0)
- VTAILQ_REMOVE(&vcl_head, vcl, list);
- else
- vcl = NULL;
+ vcl->conf->discard = 1;
UNLOCK(&vcl_mtx);
- if (vcl != NULL) {
- /* XXX dispose of vcl */
- }
+ if (vcl->conf->busy == 0)
+ VCL_Nuke(vcl);
}
void
cli_result(cli, CLIS_PARAM);
return;
}
- if (vcl->discard) {
- cli_out(cli, "VCL '%s' has been discarded", av[2]);
- cli_result(cli, CLIS_PARAM);
- return;
- }
LOCK(&vcl_mtx);
vcl_active = vcl;
UNLOCK(&vcl_mtx);