Commit ac5e880a authored by Dridi Boukelmoune's avatar Dridi Boukelmoune

Introduce the vmod vtc for varnishtest

This is moving some of the generally useful functions of vmod debug to a
new one that is installed for use out of the Varnish source tree. Things
weren't just moved from one source file to another, some functions were
sligthly renamed, and the behavior of `barrier_sync` was changed to
adhere to the "universal fail" and no longer returns a boolean.

While at it, I added missing __match_proto__ macros to vmod debug.

Refs #2276
Closes #2362
parent 3199e694
varnishtest "Test workspace functions in vmod_debug"
varnishtest "Test workspace functions in vmod_vtc"
server s1 {
rxreq
......@@ -9,20 +9,20 @@ server s1 {
} -start
varnish v1 -vcl+backend {
import debug;
import vtc;
sub vcl_backend_response {
set beresp.http.free_backend = debug.workspace_free(backend);
set beresp.http.free_backend = vtc.workspace_free(backend);
}
sub vcl_deliver {
set resp.http.free_session = debug.workspace_free(session);
set resp.http.free_thread = debug.workspace_free(thread);
set resp.http.free_session = vtc.workspace_free(session);
set resp.http.free_thread = vtc.workspace_free(thread);
set resp.http.overflowed = debug.workspace_overflowed(client);
debug.workspace_allocate(client, 2048);
set resp.http.overflowed = vtc.workspace_overflowed(client);
vtc.workspace_alloc(client, 2048);
if (req.url == "/bar") {
debug.workspace_overflow(client);
vtc.workspace_overflow(client);
}
}
} -start
......
......@@ -12,9 +12,9 @@ server s1 {
} -start
varnish v1 -vcl+backend {
import debug;
import vtc;
sub vcl_deliver {
debug.workspace_allocate(client, -192);
vtc.workspace_alloc(client, -192);
if (req.url ~ "/bar") {
set resp.http.x-foo = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
......@@ -22,7 +22,7 @@ varnish v1 -vcl+backend {
else if (req.url ~ "/baz") {
set resp.http.x-foo = regsub(req.url, "baz", "baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz");
}
set resp.http.x-of = debug.workspace_overflowed(client);
set resp.http.x-of = vtc.workspace_overflowed(client);
}
} -start
......
......@@ -6,14 +6,14 @@ server s1 {
} -start
varnish v1 -vcl+backend {
import debug;
import std;
import vtc;
sub vcl_recv {
set req.http.ws-free = debug.workspace_free(session);
debug.workspace_allocate(session, std.integer(req.http.ws-free, 0));
debug.workspace_snap(session);
debug.workspace_reset(session);
set req.http.ws-free = vtc.workspace_free(session);
vtc.workspace_alloc(session, std.integer(req.http.ws-free, 0));
vtc.workspace_snapshot(session);
vtc.workspace_reset(session);
}
} -start
......
......@@ -10,14 +10,14 @@ varnish v1 \
-arg "-ss2=malloc,1m" \
-arg "-ss0=malloc,1m" \
-vcl+backend {
import debug;
import vtc;
sub vcl_backend_response {
if (bereq.url == "/1") {
set beresp.storage_hint = "invalid";
} else if (bereq.url == "/2") {
set beresp.storage_hint = "s1";
} else if (bereq.url == "/6") {
set beresp.storage = debug.no_stevedore();
set beresp.storage = vtc.no_stevedore();
}
set beresp.http.storage = beresp.storage;
}
......
......@@ -13,6 +13,7 @@ server s2 {
varnish v1 -vcl {
import std;
import debug;
import vtc;
backend dummy { .host = "${bad_backend}"; }
......@@ -30,7 +31,7 @@ varnish v1 -vcl {
sub vcl_backend_fetch {
set bereq.backend = s1.backend();
# hot swap should happen while we sleep
debug.sleep(2s);
vtc.sleep(2s);
if (std.healthy(bereq.backend)) {
return(abandon);
} else {
......
......@@ -13,6 +13,7 @@ server s2 {
varnish v1 -vcl {
import std;
import debug;
import vtc;
backend dummy { .host = "${bad_backend}"; }
......@@ -27,7 +28,7 @@ varnish v1 -vcl {
}
set req.backend_hint = s1.backend();
# hot swap should happen while we sleep
debug.sleep(2s);
vtc.sleep(2s);
if (std.healthy(req.backend_hint)) {
return(synth(800));
} else {
......
......@@ -3,10 +3,10 @@ varnishtest "Backend as a boolean expression"
server s1 -start
varnish v1 -vcl+backend {
import debug;
import vtc;
sub vcl_recv {
set req.backend_hint = debug.no_backend();
set req.backend_hint = vtc.no_backend();
if (!req.backend_hint) {
return (synth(404));
}
......
......@@ -6,10 +6,10 @@ server s1 {
} -start
varnish v1 -vcl+backend {
import debug;
import vtc;
sub vcl_deliver {
set resp.http.foo = debug.blob2hex(debug.str2blob("gunk"));
set resp.http.foo = vtc.blob2hex(vtc.str2blob("gunk"));
}
} -start
......@@ -25,10 +25,10 @@ varnish v1 -errvcl {BLOBs can only be used as arguments to VMOD functions.} {
backend b1 {.host = "127.0.0.1";}
import debug;
import vtc;
sub vcl_deliver {
set resp.http.foo = debug.str2blob("gunk");
set resp.http.foo = vtc.str2blob("gunk");
}
}
......@@ -36,9 +36,9 @@ varnish v1 -errvcl {Wrong argument type. Expected BLOB. Got STRING.} {
backend b1 {.host = "127.0.0.1";}
import debug;
import vtc;
sub vcl_deliver {
set resp.http.foo = debug.blob2hex("gunk");
set resp.http.foo = vtc.blob2hex("gunk");
}
}
varnishtest "Test debug.barrier_sync"
varnishtest "Test vtc.barrier_sync"
barrier b1 sock 2
barrier b2 sock 2
......@@ -9,18 +9,14 @@ server s1 {
} -start
varnish v1 -vcl+backend {
import debug;
import vtc;
sub vcl_recv {
if (!debug.barrier_sync("${b1_sock}")) {
return (synth(400));
}
vtc.barrier_sync("${b1_sock}");
}
sub vcl_backend_response {
if (!debug.barrier_sync("${b2_sock}")) {
return (abandon);
}
vtc.barrier_sync("${b2_sock}");
}
} -start
......
......@@ -6,11 +6,10 @@ server s1 {
} -start
varnish v1 -vcl+backend {
import debug;
import vtc;
sub vcl_recv {
set req.backend_hint = debug.no_backend();
set req.backend_hint = vtc.no_backend();
}
} -start
......
......@@ -6,12 +6,12 @@ server s1 {
} -start
varnish v1 \
-vcl+backend {
import debug;
varnish v1 -vcl+backend {
import vtc;
sub vcl_backend_response {
set beresp.do_gzip = true;
debug.workspace_allocate(backend, debug.workspace_free(backend) - 16);
vtc.workspace_alloc(backend, vtc.workspace_free(backend) - 16);
}
} -start
......
......@@ -10,15 +10,15 @@ server s1 -repeat 64 {
} -start
varnish v1 -vcl+backend {
import debug;
import std;
import vtc;
sub vcl_recv {
return (pass);
}
sub vcl_backend_fetch {
debug.workspace_allocate(backend, -1 * std.integer(bereq.http.WS, 256));
vtc.workspace_alloc(backend, -1 * std.integer(bereq.http.WS, 256));
}
} -start
......
varnishtest "workspace overflow with failed backend fetch"
varnish v1 -vcl {
import debug;
import vtc;
backend default {
.host = "${bad_backend}";
......@@ -10,8 +10,7 @@ varnish v1 -vcl {
sub vcl_backend_fetch {
# avoid LostHeader b Host: %s
set bereq.http.Host = "127.0.0.1";
debug.workspace_allocate(backend,
debug.workspace_free(backend));
vtc.workspace_alloc(backend, vtc.workspace_free(backend));
}
sub vcl_backend_error {
......
......@@ -6,11 +6,11 @@ server s1 {
} -start
varnish v1 -vcl+backend {
import debug;
import std;
import vtc;
sub vcl_recv {
debug.workspace_allocate(client, -92);
vtc.workspace_alloc(client, -92);
if (std.querysort(req.url) == req.url) {
std.log("querysort failed");
}
......
......@@ -12,17 +12,17 @@ server s1 -repeat 2 {
} -start
varnish v1 -vcl+backend {
import debug;
import vtc;
sub vcl_deliver {
if (req.url == "/1") {
debug.workspace_allocate(client,
-1 * (40 + debug.typesize("p") * 25));
vtc.workspace_alloc(client,
-1 * (40 + vtc.typesize("p") * 25));
} else {
debug.workspace_allocate(client,
-1 * (56 + debug.typesize("p") * 25));
vtc.workspace_alloc(client,
-1 * (56 + vtc.typesize("p") * 25));
}
set resp.http.foo = debug.workspace_free(client);
set resp.http.foo = vtc.workspace_free(client);
}
} -start
......
......@@ -7,6 +7,7 @@ server s1 -repeat 12 {
varnish v1 -arg "-p thread_pools=1" -vcl+backend {
import debug;
import vtc;
sub vcl_recv {
if (req.url == "recv") { debug.purge(); }
......@@ -38,7 +39,7 @@ varnish v1 -arg "-p thread_pools=1" -vcl+backend {
sub vcl_backend_fetch {
if (bereq.url == "fetch") { debug.purge(); }
if (bereq.url == "error") {
set bereq.backend = debug.no_backend();
set bereq.backend = vtc.no_backend();
}
}
sub vcl_backend_error {
......
......@@ -6,10 +6,10 @@ server s1 {
} -start
varnish v1 -vcl+backend {
import debug;
import vtc;
sub vcl_recv {
debug.panic("H2 panic");
vtc.panic("H2 panic");
}
} -start
......
......@@ -21,18 +21,15 @@ server s1 {
expect req.url == /5
} -start
varnish v1 -cliok "param.set feature +http2"
varnish v1 -cliok "param.set debug +syncvsl"
varnish v1 -cliok "param.set debug +h2_nocheck"
varnish v1 -vcl+backend {
import debug;
import vtc;
sub vcl_deliver {
if (req.url == "/1") {
if (!debug.barrier_sync("${b1_sock}")) {
return (synth(400));
}
vtc.barrier_sync("${b1_sock}");
}
}
} -start
......
......@@ -25,17 +25,16 @@ server s1 {
} -start
varnish v1 -arg "-smalloc,1m" -vcl+backend {
import debug;
import vtc;
sub vcl_backend_response {
if (beresp.http.panic == "fetch") {
debug.panic("Had Panic header: " + beresp.http.panic);
vtc.panic("Had Panic header: " + beresp.http.panic);
}
}
sub vcl_deliver {
if (resp.http.panic == "deliver") {
debug.panic("Had Panic header: " + resp.http.panic);
vtc.panic("Had Panic header: " + resp.http.panic);
}
}
} -start
......
......@@ -223,10 +223,10 @@ varnish v1 -errvcl {VCL sub's named 'vcl*' are reserved names.} {
}
varnish v1 -errvcl {Function returns VOID} {
import debug;
import vtc;
backend b { .host = "127.0.0.1"; }
sub vcl_recv {
set req.http.foo = debug.sleep(1m);
set req.http.foo = vtc.sleep(1m);
}
}
......@@ -253,10 +253,10 @@ varnish v1 -errvcl {Expected 'from path ...'} {
}
varnish v1 -errvcl {INT * BLOB not possible.} {
import debug;
import vtc;
backend b { .host = "127.0.0.1"; }
sub vcl_deliver {
set resp.status = 100 * debug.str2blob("a");
set resp.status = 100 * vtc.str2blob("a");
}
}
......
......@@ -30,3 +30,4 @@
VTC_VMOD(std)
VTC_VMOD(debug)
VTC_VMOD(directors)
VTC_VMOD(vtc)
......@@ -729,6 +729,7 @@ AC_CONFIG_FILES([
lib/libvmod_debug/Makefile
lib/libvmod_std/Makefile
lib/libvmod_directors/Makefile
lib/libvmod_vtc/Makefile
man/Makefile
varnishapi.pc
varnishapi-uninstalled.pc
......
......@@ -25,13 +25,15 @@ VCL
* Added ``bereq.is_bgfetch`` which is true for background fetches.
C APIs (for vmod authors)
-------------------------
C APIs (for vmod and utility authors)
-------------------------------------
* ``VSM_Name()`` returns the -i argument name, rather than the -n name.
* ``VUT.name`` is gone, use ``VSM_Name(VUT.vsm)``
* New vmod vtc for advanced varnishtest usage (#2276)
================================
Varnish Cache 5.1.3 (2017-08-02)
================================
......
......@@ -184,6 +184,7 @@ SEE ALSO
* :ref:`varnishtop(1)`
* :ref:`vcl(7)`
* :ref:`vtc(7)`
* :ref:`vmod_vtc(3)`
HISTORY
=======
......
......@@ -66,6 +66,7 @@ SEE ALSO
========
* :ref:`varnishtest(1)`
* :ref:`vmod_vtc(3)`
COPYRIGHT
=========
......
......@@ -7,4 +7,5 @@ SUBDIRS = \
libvgz \
libvmod_debug \
libvmod_std \
libvmod_directors
libvmod_directors \
libvmod_vtc
......@@ -202,7 +202,7 @@ vmod_rot52(VRT_CTX, VCL_HTTP hp)
http_PrintfHeader(hp, "Encrypted: ROT52");
}
VCL_STRING
VCL_STRING __match_proto__(td_debug_argtest)
vmod_argtest(VRT_CTX, VCL_STRING one, VCL_REAL two, VCL_STRING three,
VCL_STRING comma, VCL_INT four)
{
......@@ -212,7 +212,7 @@ vmod_argtest(VRT_CTX, VCL_STRING one, VCL_REAL two, VCL_STRING three,
return (WS_Copy(ctx->ws, buf, -1));
}
VCL_INT
VCL_INT __match_proto__(td_debug_vre_limit)
vmod_vre_limit(VRT_CTX)
{
(void)ctx;
......@@ -239,7 +239,7 @@ obj_cb(struct worker *wrk, void *priv, struct objcore *oc, unsigned event)
(intmax_t)(uintptr_t)oc);
}
VCL_VOID __match_proto__()
VCL_VOID __match_proto__(td_debug_register_obj_events)
vmod_register_obj_events(VRT_CTX, struct vmod_priv *priv)
{
struct priv_vcl *priv_vcl;
......@@ -252,7 +252,7 @@ vmod_register_obj_events(VRT_CTX, struct vmod_priv *priv)
VSL(SLT_Debug, 0, "Subscribed to Object Events");
}
VCL_VOID __match_proto__()
VCL_VOID __match_proto__(td_debug_fail)
vmod_fail(VRT_CTX)
{
......@@ -487,7 +487,7 @@ vmod_workspace_overflow(VRT_CTX, VCL_ENUM which)
WS_MarkOverflow(ws);
}
void
VCL_VOID __match_proto__(td_debug_vcl_release_delay)
vmod_vcl_release_delay(VRT_CTX, VCL_DURATION delay)
{
......@@ -496,7 +496,7 @@ vmod_vcl_release_delay(VRT_CTX, VCL_DURATION delay)
vcl_release_delay = delay;
}
VCL_BOOL
VCL_BOOL __match_proto__(td_debug_match_acl)
vmod_match_acl(VRT_CTX, VCL_ACL acl, VCL_IP ip)
{
......@@ -539,7 +539,7 @@ vmod_barrier_sync(VRT_CTX, VCL_STRING addr)
return (0);
}
VCL_VOID
VCL_VOID __match_proto__(td_debug_test_probe)
vmod_test_probe(VRT_CTX, VCL_PROBE probe, VCL_PROBE same)
{
......@@ -573,7 +573,7 @@ vmod_typesize(VRT_CTX, VCL_STRING s)
return ((VCL_INT)i);
}
VCL_VOID
VCL_VOID __match_proto__(td_debug_purge)
vmod_purge(VRT_CTX, double ttl, double grace, double keep)
{
......
#
AM_LDFLAGS = $(AM_LT_LDFLAGS)
AM_CPPFLAGS = \
-I$(top_srcdir)/include \
-I$(top_srcdir)/bin/varnishd \
-I$(top_builddir)/include
vmoddir = $(pkglibdir)/vmods
vmod_srcdir = $(top_srcdir)/lib/libvmod_vtc
vmodtool = $(top_srcdir)/lib/libvcc/vmodtool.py
vmodtoolargs =
vmod_LTLIBRARIES = libvmod_vtc.la
libvmod_vtc_la_CFLAGS = \
@SAN_CFLAGS@
libvmod_vtc_la_LDFLAGS = $(AM_LDFLAGS) -module -export-dynamic -avoid-version -shared -rpath /nowhere \
@SAN_LDFLAGS@
libvmod_vtc_la_SOURCES = \
vmod_vtc.c
nodist_libvmod_vtc_la_SOURCES = \
vcc_if.c \
vcc_if.h
# BUILT_SOURCES is only a hack and dependency tracking does not help for the first build
$(libvmod_vtc_la_OBJECTS):vcc_if.h
vcc_if.h vmod_vtc.rst vmod_vtc.man.rst: vcc_if.c
vcc_if.c: $(vmodtool) $(vmod_srcdir)/vmod.vcc
@PYTHON@ $(vmodtool) $(vmodtoolargs) $(vmod_srcdir)/vmod.vcc
EXTRA_DIST = vmod.vcc
CLEANFILES = $(builddir)/vcc_if.c $(builddir)/vcc_if.h \
$(builddir)/vmod_vtc.rst \
$(builddir)/vmod_vtc.man.rst
#
# Copyright (c) 2017 Varnish Software AS
# All rights reserved.
#
# Author: Dridi Boukelmoune <dridi.boukelmoune@gmail.com>
#
# 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.
$Module vtc 3 Utility module for varnishtest
DESCRIPTION
===========
The goal for this VMOD is to provide VCL users and VMOD authors means to
test corner cases or reach certain conditions with varnishtest.
$Function VOID barrier_sync(STRING addr, DURATION timeout = 0)
When writing test cases, the most common pattern is to start a mock server
instance, a Varnish instance, and spin up a mock client. Those entities run
asynchronously, and others exist like background processes (``process``) or
log readers (``logexpect``). While you can synchronize with individual
entities and wait for their completion, you must use a barrier if you need
to synchronize two or more entities, or wait until a certain point instead
of completion.
Not only is it possible to synchronize between test entities, with the
``barrier_sync`` function you can even synchronize VCL code::
sub vcl_recv {
# wait for some barrier b1 to complete
vtc.barrier_sync("${b1_sock}");
}
If the function fails to synchronize with the barrier for some reason, or if
it reaches the optional timeout, it fails the VCL transaction.
MISCELLANEOUS
=============
$Function BACKEND no_backend()
Fails at backend selection.
$Function STEVEDORE no_stevedore()
Fails at storage selection.
$Function VOID panic(STRING_LIST)
It can be useful to crash the child process in order to test the robustness
of a VMOD.
$Function VOID sleep(DURATION)
Block the current worker thread.
WORKSPACES
==========
It can be useful to put a workspace in a given state when testing corner
cases like resource exhaustion for a transaction, especially for VMOD
development. All functions available allow to pick which workspace you
need to tamper with, available values are ``client``, ``backend``, ``session``
and ``thread``.
$Function VOID workspace_alloc(ENUM { client, backend, session, thread },
INT size)
Allocate and zero out memory from a workspace. A negative size will allocate
as much as needed to leave that many bytes free. The actual allocation size
may be higher to comply with memory alignment requirements of the CPU
architecture. A failed allocation fails the transaction.
$Function INT workspace_free(ENUM { client, backend, session, thread })
Find how much unallocated space there is left in a workspace.
$Function VOID workspace_snapshot(ENUM { client, backend, session, thread})
Snapshot a workspace. Only one snapshot may be active at a time.
$Function VOID workspace_reset(ENUM { client, backend, session, thread })
Reset to the previous snapshot of a workspace, it must be the same workspace
too.
$Function BOOL workspace_overflowed(ENUM { client, backend, session, thread })
Find whether the workspace overflow mark is set or not.
$Function VOID workspace_overflow(ENUM { client, backend, session, thread })
Mark a workspace as overflowed.
$Function INT typesize(STRING)
Returns the size in bytes of a collection of C-datatypes:
* ``'p'``: pointer
* ``'i'``: ``int``
* ``'d'``: ``double``
* ``'f'``: ``float``
* ``'l'``: ``long``
* ``'s'``: ``short``
* ``'z'``: ``size_t``
* ``'o'``: ``off_t``
* ``'j'``: ``intmax_t``
This can be useful for VMOD authors in conjunction with workspace operations.
BLOBS
=====
For VMODs dealing with BLOB arguments or return values, the following functions
offer convenience conversions to and from STRING.
$Function BLOB str2blob(STRING src)
Turn a string into a blob.
$Function STRING blob2hex(BLOB src)
Hexdump a blob.
SEE ALSO
========
* :ref:`vtc(7)`
* :ref:`vcl(7)`
/*-
* Copyright (c) 2012-2017 Varnish Software AS
* All rights reserved.
*
* Author: Poul-Henning Kamp <phk@FreeBSD.org>
* Author: Dridi Boukelmoune <dridi.boukelmoune@gmail.com>
*
* 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 <errno.h>
#include <stdio.h>
#include "cache/cache.h"
#include "vrt.h"
#include "vtcp.h"
#include "vtim.h"
#include "vcc_if.h"
VCL_VOID __match_proto__(td_vtc_barrier_sync)
vmod_barrier_sync(VRT_CTX, VCL_STRING addr, VCL_DURATION tmo)
{
const char *err;
char buf[32];
int sock, i;
ssize_t sz;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AN(addr);
AN(*addr);
assert(tmo >= 0.0);
VSLb(ctx->vsl, SLT_Debug, "barrier_sync(\"%s\")", addr);
sock = VTCP_open(addr, NULL, 0., &err);
if (sock < 0) {
VRT_fail(ctx, "Barrier connection failed: %s", err);
return;
}
sz = VTCP_read(sock, buf, sizeof buf, tmo);
i = errno;
closefd(&sock);
if (sz < 0)
VRT_fail(ctx, "Barrier read failed: %s (errno=%d)",
strerror(i), i);
if (sz > 0)
VRT_fail(ctx, "Barrier unexpected data (%zdB)", sz);
}
/*--------------------------------------------------------------------*/
VCL_BACKEND __match_proto__(td_vtc_no_backend)
vmod_no_backend(VRT_CTX)
{
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
return (NULL);
}
VCL_STEVEDORE __match_proto__(td_vtc_no_stevedore)
vmod_no_stevedore(VRT_CTX)
{
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
return (NULL);
}
/*--------------------------------------------------------------------*/
VCL_VOID __match_proto__(td_vtc_panic)
vmod_panic(VRT_CTX, const char *str, ...)
{
va_list ap;
const char *b;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
va_start(ap, str);
b = VRT_String(ctx->ws, "PANIC: ", str, ap);
va_end(ap);
VAS_Fail("VCL", "", 0, b, VAS_VCL);
}
/*--------------------------------------------------------------------*/
VCL_VOID __match_proto__(td_vtc_sleep)
vmod_sleep(VRT_CTX, VCL_DURATION t)
{
CHECK_OBJ_ORNULL(ctx, VRT_CTX_MAGIC);
VTIM_sleep(t);
}
/*--------------------------------------------------------------------*/
static uintptr_t vtc_ws_snapshot;
static struct ws *
vtc_ws_find(VRT_CTX, VCL_ENUM which)
{
if (!strcmp(which, "client"))
return (ctx->ws);
if (!strcmp(which, "backend"))
return (ctx->bo->ws);
if (!strcmp(which, "session"))
return (ctx->req->sp->ws);
if (!strcmp(which, "thread"))
return (ctx->req->wrk->aws);
VRT_fail(ctx, "Unknown workspace: '%s'", which);
return (NULL);
}
VCL_VOID __match_proto__(td_vtc_workspace_alloc)
vmod_workspace_alloc(VRT_CTX, VCL_ENUM which, VCL_INT size)
{
struct ws *ws;
void *p;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
ws = vtc_ws_find(ctx, which);
WS_Assert(ws);
if (size < 0) {
size += WS_Reserve(ws, 0);
WS_Release(ws, 0);
}
p = WS_Alloc(ws, size);
if (p == NULL)
VRT_fail(ctx, "vtc.workspace_alloc");
else
memset(p, '\0', size);
}
VCL_INT __match_proto__(td_vtc_workspace_free)
vmod_workspace_free(VRT_CTX, VCL_ENUM which)
{
struct ws *ws;
unsigned u;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
ws = vtc_ws_find(ctx, which);
WS_Assert(ws);
u = WS_Reserve(ws, 0);
WS_Release(ws, 0);
return (u);
}
#define VTC_WS_OP(type, name, op) \
VCL_##type __match_proto__(td_vtc_workspace_##name) \
vmod_workspace_##name(VRT_CTX, VCL_ENUM which) \
{ \
struct ws *ws; \
\
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); \
\
ws = vtc_ws_find(ctx, which); \
WS_Assert(ws); \
\
op; \
}
VTC_WS_OP(VOID, snapshot, vtc_ws_snapshot = WS_Snapshot(ws))
VTC_WS_OP(VOID, reset, WS_Reset(ws, vtc_ws_snapshot))
VTC_WS_OP(VOID, overflow, WS_MarkOverflow(ws))
VTC_WS_OP(BOOL, overflowed, return (WS_Overflowed(ws)))
#undef VTC_WS_OP
/*--------------------------------------------------------------------*/
VCL_INT __match_proto__(td_vtc_typesize)
vmod_typesize(VRT_CTX, VCL_STRING s)
{
VCL_INT i = 0;
const char *p;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
for (p = s; *p; p++) {
switch (*p) {
#define VTC_TYPESIZE(c, t) case c: i += sizeof(t); break;
VTC_TYPESIZE('d', double)
VTC_TYPESIZE('f', float)
VTC_TYPESIZE('i', int)
VTC_TYPESIZE('j', intmax_t)
VTC_TYPESIZE('l', long)
VTC_TYPESIZE('o', off_t)
VTC_TYPESIZE('p', void *)
VTC_TYPESIZE('s', short)
VTC_TYPESIZE('z', size_t)
#undef VTC_TYPESIZE
default: return (-1);
}
}
return (i);
}
/*--------------------------------------------------------------------*/
VCL_BLOB __match_proto__(td_vtc_str2blob)
vmod_str2blob(VRT_CTX, VCL_STRING s)
{
struct vmod_priv *p;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
p = WS_Alloc(ctx->ws, sizeof *p);
AN(p);
memset(p, 0, sizeof *p);
p->len = strlen(s);
p->priv = WS_Copy(ctx->ws, s, -1);
return (p);
}
VCL_STRING __match_proto__(td_vtc_blob2hex)
vmod_blob2hex(VRT_CTX, VCL_BLOB b)
{
char *s, *p;
uint8_t *q;
int i;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
s = WS_Alloc(ctx->ws, b->len * 2 + 2);
AN(s);
p = s;
q = b->priv;
for (i = 0; i < b->len; i++) {
assert(snprintf(p, 3, "%02x", *q) == 2);
p += 2;
q += 1;
}
VRT_priv_fini(b);
return (s);
}
......@@ -16,7 +16,8 @@ dist_man_MANS = \
vtc.7 \
varnishtop.1 \
vmod_directors.3 \
vmod_std.3
vmod_std.3 \
vmod_vtc.3
CLEANFILES = $(dist_man_MANS)
......@@ -83,10 +84,13 @@ varnishhist.1: \
$(top_builddir)/doc/sphinx/include/varnishhist_synopsis.rst
${RST2MAN} $(RST2ANY_FLAGS) $(top_srcdir)/doc/sphinx/reference/varnishhist.rst $@
vmod_directors.3: $(top_builddir)/lib/libvmod_directors/vmod_directors.man.rst
${RST2MAN} $(RST2ANY_FLAGS) $? $@
vmod_std.3: $(top_builddir)/lib/libvmod_std/vmod_std.man.rst
${RST2MAN} $(RST2ANY_FLAGS) $? $@
vmod_directors.3: $(top_builddir)/lib/libvmod_directors/vmod_directors.man.rst
vmod_vtc.3: $(top_builddir)/lib/libvmod_vtc/vmod_vtc.man.rst
${RST2MAN} $(RST2ANY_FLAGS) $? $@
.NOPATH: $(dist_man_MANS)
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