Commit 1d3ad7af authored by Geoff Simmons's avatar Geoff Simmons

Add the sub object.

parent e7953f51
Pipeline #355 skipped
......@@ -40,6 +40,7 @@ CONTENTS
========
* label()
* sub()
* STRING version()
.. _obj_label:
......@@ -69,6 +70,33 @@ label.go
VOID label.go(INT)
.. _obj_sub:
sub
---
::
new OBJ = sub()
.. _func_sub.add:
sub.add
-------
::
VOID sub.add(INT n, STRING sub)
.. _func_sub.call:
sub.call
--------
::
VOID sub.call(INT n)
.. _func_version:
version
......
# looks like -*- vcl -*-
varnishtest "sub object"
varnish v1 -arg "-p vcc_err_unref=off" -vcl {
import ${vmod_dispatch};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new s = dispatch.sub();
s.add(0, "sub1");
s.add(1, "sub2");
}
sub sub1 {
set req.http.Sub = "sub1";
}
sub sub2 {
set req.http.Sub = "sub2";
}
sub vcl_recv {
if (req.url == "/0") {
s.call(0);
}
if (req.url == "/1") {
s.call(1);
}
return(synth(200));
}
sub vcl_synth {
set resp.http.Sub = req.http.Sub;
}
} -start
client c1 {
txreq -url "/0"
rxresp
expect resp.status == 200
expect resp.http.Sub == "sub1"
txreq -url "/1"
rxresp
expect resp.status == 200
expect resp.http.Sub == "sub2"
} -run
varnish v1 -errvcl {vmod dispatch error: s.add(0): subroutine name is empty} {
import ${vmod_dispatch};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new s = dispatch.sub();
s.add(0, "");
}
}
varnish v1 -errvcl {vmod dispatch error: s.add(-1, foo): n must be >= 0} {
import ${vmod_dispatch};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new s = dispatch.sub();
s.add(-1, "foo");
}
}
varnish v1 -errvcl {vmod dispatch error: s.add(0, foo): VCL subroutine not found} {
import ${vmod_dispatch};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new s = dispatch.sub();
s.add(0, "foo");
}
}
varnish v1 -vcl {
import ${vmod_dispatch};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new s = dispatch.sub();
s.add(0, "sub1");
s.add(2, "sub2");
}
sub vcl_recv {
if (req.url == "/negative") {
s.call(-1);
}
elsif (req.url == "/notset") {
s.call(1);
}
elsif (req.url == "/outofrange") {
s.call(3);
}
elsif (req.url == "/add") {
s.add(1, "sub1");
}
return(synth(200));
}
sub vcl_synth {
set resp.http.Sub = req.http.Sub;
}
sub sub1 {
set req.http.Sub = "sub1";
}
sub sub2 {
set req.http.Sub = "sub2";
}
}
client c1 {
txreq -url "/negative"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect resp.http.Sub == ""
} -run
client c1 {
txreq -url "/notset"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect resp.http.Sub == ""
} -run
client c1 {
txreq -url "/outofrange"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect resp.http.Sub == ""
} -run
client c1 {
txreq -url "/add"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect resp.http.Sub == ""
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect * * VCL_Error "^vmod dispatch error: s.call.-1.: n must be >= 0$"
expect * * VCL_Error "^vmod dispatch error: s.call.1.: sub 1 was not added$"
expect * * VCL_Error "^vmod dispatch error: s.call.3.: highest sub number is 2"
expect * * VCL_Error "^vmod dispatch error: s.add.1, sub1. may only be called in vcl_init$"
} -start
logexpect l1 -wait
......@@ -33,6 +33,7 @@
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include "cache/cache.h"
#include "vcl.h"
......@@ -57,6 +58,22 @@ struct vmod_dispatch_label {
unsigned nvcls;
};
struct vmod_dispatch_sub {
unsigned magic;
#define VMOD_DISPATCH_SUB_MAGIC 0x24a617ec
vcl_func_f **func;
struct vbitmap *bitmap;
char *vcl_name;
unsigned nsubs;
};
struct vmod_dispatch_vcl {
unsigned magic;
#define VMOD_DISPATCH_VCL_MAGIC 0x214188f2
VTAILQ_ENTRY(vcl) list;
void *dlh;
};
static struct vrt_ctx dummy_ctx = { .magic = VRT_CTX_MAGIC };
VCL_VOID
......@@ -175,6 +192,124 @@ vmod_label_go(VRT_CTX, struct vmod_dispatch_label *label, VCL_INT n)
VRT_handling(ctx, VCL_RET_VCL);
}
VCL_VOID
vmod_sub__init(VRT_CTX, struct vmod_dispatch_sub **subp, const char *vcl_name)
{
struct vmod_dispatch_sub *sub;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AN(subp);
AZ(*subp);
AN(vcl_name);
ALLOC_OBJ(sub, VMOD_DISPATCH_SUB_MAGIC);
AN(sub);
*subp = sub;
sub->bitmap = vbit_new(INIT_BITS);
AN(sub->bitmap);
sub->vcl_name = strdup(vcl_name);
AN(sub->vcl_name);
AZ(sub->func);
AZ(sub->nsubs);
}
VCL_VOID
vmod_sub__fini(struct vmod_dispatch_sub **subp)
{
struct vmod_dispatch_sub *sub;
if (subp == NULL || *subp == NULL)
return;
CHECK_OBJ(*subp, VMOD_DISPATCH_SUB_MAGIC);
sub = *subp;
*subp = NULL;
if (sub->func != NULL)
free(sub->func);
if (sub->bitmap != NULL)
vbit_destroy(sub->bitmap);
if (sub->vcl_name != NULL)
free(sub->vcl_name);
FREE_OBJ(sub);
}
VCL_VOID
vmod_sub_add(VRT_CTX, struct vmod_dispatch_sub *sub, VCL_INT n,
VCL_STRING subname)
{
uintptr_t snap;
struct vmod_dispatch_vcl *vcl;
char *funcname;
vcl_func_f *vcl_func;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(sub, VMOD_DISPATCH_SUB_MAGIC);
CAST_OBJ_NOTNULL(vcl, (void *)ctx->vcl, VMOD_DISPATCH_VCL_MAGIC);
if (subname == NULL || *subname == '\0') {
VERR(ctx, "%s.add(%ld): subroutine name is empty",
sub->vcl_name, n);
return;
}
if ((ctx->method & VCL_MET_INIT) == 0) {
VERR(ctx, "%s.add(%ld, %s) may only be called in vcl_init",
sub->vcl_name, n, subname);
return;
}
if (n < 0) {
VERR(ctx, "%s.add(%ld, %s): n must be >= 0", sub->vcl_name,
n, subname);
return;
}
snap = WS_Snapshot(ctx->ws);
if ((funcname = WS_Printf(ctx->ws, "VGC_function_%s", subname))
== NULL) {
VERR(ctx, "%s.add(%ld, %s): insufficient workspace for "
"internal C function name", sub->vcl_name, n, subname);
return;
}
vcl_func = dlsym(vcl->dlh, funcname);
WS_Reset(ctx->ws, snap);
if (vcl_func == NULL) {
VERR(ctx, "%s.add(%ld, %s): VCL subroutine not found: %s",
sub->vcl_name, n, subname, dlerror());
return;
}
if (n >= sub->nsubs)
sub->nsubs = n + 1;
if ((sub->func = realloc(sub->func, sub->nsubs * sizeof(vcl_func)))
== NULL) {
VERR(ctx, "%s.add(%ld, %s): out of memory", sub->vcl_name, n,
subname);
return;
}
sub->func[n] = vcl_func;
vbit_set(sub->bitmap, n);
}
VCL_VOID
vmod_sub_call(VRT_CTX, struct vmod_dispatch_sub *sub, VCL_INT n)
{
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(sub, VMOD_DISPATCH_SUB_MAGIC);
if (n < 0) {
VERR(ctx, "%s.call(%ld): n must be >= 0", sub->vcl_name, n);
return;
}
if (n >= sub->nsubs) {
VERR(ctx, "%s.call(%ld): highest sub number is %d",
sub->vcl_name, n, sub->nsubs - 1);
return;
}
if (!vbit_test(sub->bitmap, n)) {
VERR(ctx, "%s.call(%ld): sub %ld was not added", sub->vcl_name,
n, n);
return;
}
AN(sub->func[n]);
sub->func[n](ctx);
}
VCL_STRING
vmod_version(VRT_CTX)
{
......
......@@ -27,6 +27,12 @@ $Method VOID .add(INT n, STRING label)
$Method VOID .go(INT)
$Object sub()
$Method VOID .add(INT n, STRING sub)
$Method VOID .call(INT n)
$Function STRING version()
Return the version string for this VMOD.
......
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