Commit 315bdbcc authored by Dridi Boukelmoune's avatar Dridi Boukelmoune Committed by Lasse Karstensen

Introduce barriers in varnishtest

They work like semaphores, except that they need explicit initialization
and can optionally be shared between processes.

 Conflicts:
	bin/varnishtest/tests/c00073.vtc
parent abf1ca53
......@@ -27,6 +27,7 @@ varnishtest_SOURCES = \
vtc.h \
vmods.h \
programs.h \
vtc_barrier.c \
vtc_client.c \
vtc_http.c \
vtc_main.c \
......
......@@ -5,6 +5,7 @@ PROG_SRC += vtc_log.c
PROG_SRC += vtc_logexp.c
PROG_SRC += vtc_main.c
PROG_SRC += vtc_sema.c
PROG_SRC += vtc_barrier.c
PROG_SRC += vtc_server.c
PROG_SRC += vtc_varnish.c
PROG_SRC += vtc_process.c
......
varnishtest "Sema operations"
varnishtest "Barrier operations"
barrier b1 cond 4
barrier b2 cond 4
server s1 {
rxreq
sema r1 sync 4
barrier b1 sync
delay .9
txresp
} -start
server s2 {
rxreq
sema r1 sync 4
barrier b1 sync
delay .6
txresp
} -start
server s3 {
rxreq
sema r1 sync 4
barrier b1 sync
delay .2
txresp
} -start
......@@ -25,25 +28,25 @@ client c1 -connect ${s1_sock} {
delay .2
txreq
rxresp
sema r1 sync 4
barrier b2 sync
} -start
client c2 -connect ${s2_sock} {
delay .6
txreq
rxresp
sema r1 sync 4
barrier b2 sync
} -start
client c3 -connect ${s3_sock} {
delay .9
txreq
rxresp
sema r1 sync 4
barrier b2 sync
} -start
# Wait for all servers to have received requests
sema r1 sync 4
barrier b1 sync
# Wait for all clients to have received responses
sema r1 sync 4
barrier b2 sync
varnishtest "Test object trimming"
barrier b1 cond 2
barrier b2 cond 2
server s1 {
rxreq
txresp -nolen -hdr "Transfer-encoding: chunked"
delay .2
chunkedlen 4096
barrier b1 sync
barrier b2 sync
chunkedlen 0
} -start
varnish v1 \
-arg "-s malloc,1m" -vcl+backend { } -start
client c1 {
txreq
rxresp
} -start
barrier b1 sync
varnish v1 -expect SMA.s0.g_bytes > 10000
barrier b2 sync
client c1 -wait
# Removed when adopting to 4.1. VTC kept since it uses barriers.
#varnish v1 -expect SMA.s0.g_bytes < 6000
......@@ -632,6 +632,7 @@ static const struct cmds cmds[] = {
{ "shell", cmd_shell },
{ "err_shell", cmd_err_shell },
{ "sema", cmd_sema },
{ "barrier", cmd_barrier },
{ "random", cmd_random },
{ "feature", cmd_feature },
{ "logexpect", cmd_logexp },
......@@ -655,6 +656,7 @@ exec_file(const char *fn, const char *script, const char *tmpdir,
init_macro();
init_sema();
init_barrier();
init_server();
/* Apply extmacro definitions */
......
......@@ -62,6 +62,7 @@ cmd_f cmd_server;
cmd_f cmd_client;
cmd_f cmd_varnish;
cmd_f cmd_sema;
cmd_f cmd_barrier;
cmd_f cmd_logexp;
cmd_f cmd_process;
......@@ -74,6 +75,7 @@ extern int vtc_witness;
extern int feature_dns;
void init_sema(void);
void init_barrier(void);
void init_server(void);
int http_process(struct vtclog *vl, const char *spec, int sock, int *sfd);
......
/*-
* Copyright (c) 2005 Varnish Software AS
* All rights reserved.
*
* Author: Dridi Boukelmoune <dridi@varnish-software.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 <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "vtc.h"
enum barrier_e {
BARRIER_NONE = 0,
BARRIER_COND,
BARRIER_SOCK,
};
struct barrier {
unsigned magic;
#define BARRIER_MAGIC 0x7b54c275
char *name;
VTAILQ_ENTRY(barrier) list;
pthread_mutex_t mtx;
pthread_cond_t cond;
unsigned waiters;
unsigned expected;
enum barrier_e type;
};
static pthread_mutex_t barrier_mtx;
static VTAILQ_HEAD(, barrier) barriers = VTAILQ_HEAD_INITIALIZER(barriers);
static struct barrier *
barrier_new(char *name, struct vtclog *vl)
{
struct barrier *b;
ALLOC_OBJ(b, BARRIER_MAGIC);
AN(b);
AN(name);
if (*name != 'b')
vtc_log(vl, 0, "Barrier name must start with 'b' (%s)", name);
REPLACE(b->name, name);
AZ(pthread_mutex_init(&b->mtx, NULL));
AZ(pthread_cond_init(&b->cond, NULL));
b->waiters = 0;
b->expected = 0;
VTAILQ_INSERT_TAIL(&barriers, b, list);
return (b);
}
/**********************************************************************
* Init a barrier
*/
static void
barrier_expect(struct barrier *b, const char *av, struct vtclog *vl)
{
unsigned expected;
if (b->type != BARRIER_NONE)
vtc_log(vl, 0,
"Barrier(%s) use error: already initialized", b->name);
AZ(b->expected);
AZ(b->waiters);
expected = strtoul(av, NULL, 0);
if (expected < 2)
vtc_log(vl, 0,
"Barrier(%s) use error: wrong expectation (%u)",
b->name, expected);
b->expected = expected;
}
static void
barrier_cond(struct barrier *b, const char *av, struct vtclog *vl)
{
CHECK_OBJ_NOTNULL(b, BARRIER_MAGIC);
barrier_expect(b, av, vl);
b->type = BARRIER_COND;
}
static void
barrier_sock(struct barrier *b, const char *av, struct vtclog *vl)
{
CHECK_OBJ_NOTNULL(b, BARRIER_MAGIC);
barrier_expect(b, av, vl);
b->type = BARRIER_SOCK;
INCOMPL();
}
/**********************************************************************
* Sync a barrier
*/
static void
barrier_cond_sync(struct barrier *b, struct vtclog *vl)
{
CHECK_OBJ_NOTNULL(b, BARRIER_MAGIC);
assert(b->type == BARRIER_COND);
assert(b->waiters <= b->expected);
if (b->waiters == b->expected)
vtc_log(vl, 0,
"Barrier(%s) use error: more waiters than the %u expected",
b->name, b->expected);
if (++b->waiters == b->expected) {
vtc_log(vl, 4, "Barrier(%s) wake %u", b->name, b->expected);
AZ(pthread_cond_broadcast(&b->cond));
}
else {
vtc_log(vl, 4, "Barrier(%s) wait %u of %u",
b->name, b->waiters, b->expected);
AZ(pthread_cond_wait(&b->cond, &b->mtx));
}
}
static void
barrier_sync(struct barrier *b, struct vtclog *vl)
{
CHECK_OBJ_NOTNULL(b, BARRIER_MAGIC);
switch (b->type) {
case BARRIER_NONE:
vtc_log(vl, 0,
"Barrier(%s) use error: not initialized", b->name);
case BARRIER_COND:
barrier_cond_sync(b, vl);
break;
case BARRIER_SOCK:
INCOMPL();
break;
default:
WRONG("Wrong barrier type");
}
}
/**********************************************************************
* Barrier command dispatch
*/
void
cmd_barrier(CMD_ARGS)
{
struct barrier *b, *b2;
(void)priv;
(void)cmd;
if (av == NULL) {
AZ(pthread_mutex_lock(&barrier_mtx));
/* Reset and free */
VTAILQ_FOREACH_SAFE(b, &barriers, list, b2) {
AZ(pthread_mutex_lock(&b->mtx));
assert(b->type != BARRIER_NONE);
assert(b->waiters == b->expected);
AZ(pthread_mutex_unlock(&b->mtx));
}
AZ(pthread_mutex_unlock(&barrier_mtx));
return;
}
AZ(strcmp(av[0], "barrier"));
av++;
AZ(pthread_mutex_lock(&barrier_mtx));
VTAILQ_FOREACH(b, &barriers, list)
if (!strcmp(b->name, av[0]))
break;
if (b == NULL)
b = barrier_new(av[0], vl);
av++;
AZ(pthread_mutex_lock(&b->mtx));
AZ(pthread_mutex_unlock(&barrier_mtx));
for (; *av != NULL; av++) {
if (!strcmp(*av, "cond")) {
av++;
AN(*av);
barrier_cond(b, *av, vl);
continue;
}
if (!strcmp(*av, "sock")) {
av++;
AN(*av);
barrier_sock(b, *av, vl);
continue;
}
if (!strcmp(*av, "sync")) {
barrier_sync(b, vl);
continue;
}
vtc_log(vl, 0, "Unknown barrier argument: %s", *av);
}
AZ(pthread_mutex_unlock(&b->mtx));
}
void
init_barrier(void)
{
AZ(pthread_mutex_init(&barrier_mtx, NULL));
}
......@@ -1378,6 +1378,7 @@ static const struct cmds http_cmds[] = {
{ "chunked", cmd_http_chunked },
{ "chunkedlen", cmd_http_chunkedlen },
{ "delay", cmd_delay },
{ "barrier", cmd_barrier },
{ "sema", cmd_sema },
{ "expect_close", cmd_http_expect_close },
{ "close", cmd_http_close },
......
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: vcl_center Pages: 1 -->
<svg width="614pt" height="606pt"
viewBox="36.00 36.00 577.54 570.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(40 566)">
<title>vcl_center</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-530 537.544,-530 537.544,4 -4,4"/>
<!-- acceptor -->
<g id="node1" class="node"><title>acceptor</title>
<ellipse fill="none" stroke="black" cx="413.544" cy="-508" rx="40.0939" ry="18"/>
<text text-anchor="middle" x="413.544" y="-504.3" font-family="Times,serif" font-size="14.00">acceptor</text>
</g>
<!-- http1_wait -->
<g id="node2" class="node"><title>http1_wait</title>
<ellipse fill="none" stroke="black" cx="413.544" cy="-421" rx="48.1917" ry="18"/>
<text text-anchor="middle" x="413.544" y="-417.3" font-family="Times,serif" font-size="14.00">http1_wait</text>
</g>
<!-- acceptor&#45;&gt;http1_wait -->
<g id="edge1" class="edge"><title>acceptor&#45;&gt;http1_wait</title>
<path fill="none" stroke="black" d="M413.544,-489.799C413.544,-478.163 413.544,-462.548 413.544,-449.237"/>
<polygon fill="black" stroke="black" points="417.044,-449.175 413.544,-439.175 410.044,-449.175 417.044,-449.175"/>
<text text-anchor="middle" x="465.044" y="-460.8" font-family="Times,serif" font-size="14.00">S_STP_NEWREQ</text>
</g>
<!-- CNT_Request -->
<g id="node4" class="node"><title>CNT_Request</title>
<ellipse fill="none" stroke="black" cx="123.544" cy="-319" rx="61.1893" ry="18"/>
<text text-anchor="middle" x="123.544" y="-315.3" font-family="Times,serif" font-size="14.00">CNT_Request</text>
</g>
<!-- http1_wait&#45;&gt;CNT_Request -->
<g id="edge4" class="edge"><title>http1_wait&#45;&gt;CNT_Request</title>
<path fill="none" stroke="black" d="M365.828,-418.624C301.217,-415.905 190.213,-407.948 157.544,-385 144.546,-375.87 136.143,-360.207 130.942,-346.544"/>
<polygon fill="black" stroke="black" points="134.25,-345.4 127.702,-337.071 127.627,-347.665 134.25,-345.4"/>
<text text-anchor="middle" x="213.044" y="-373.8" font-family="Times,serif" font-size="14.00">S_STP_WORKING</text>
<text text-anchor="middle" x="213.044" y="-358.8" font-family="Times,serif" font-size="14.00">R_STP_RECV</text>
</g>
<!-- disembark -->
<g id="node5" class="node"><title>disembark</title>
<ellipse fill="none" stroke="black" cx="331.544" cy="-91" rx="48.1917" ry="18"/>
<text text-anchor="middle" x="331.544" y="-87.3" font-family="Times,serif" font-size="14.00">disembark</text>
</g>
<!-- http1_wait&#45;&gt;disembark -->
<g id="edge5" class="edge"><title>http1_wait&#45;&gt;disembark</title>
<path fill="none" stroke="black" d="M415.457,-402.989C417.361,-378.708 417.784,-333.462 399.544,-301 393.185,-289.684 382.782,-294.383 376.544,-283 343.071,-221.917 388.812,-191.094 361.544,-127 359.933,-123.214 357.76,-119.538 355.315,-116.079"/>
<polygon fill="black" stroke="black" points="357.823,-113.612 348.842,-107.992 352.358,-117.987 357.823,-113.612"/>
<text text-anchor="middle" x="413.044" y="-264.3" font-family="Times,serif" font-size="14.00">Session close</text>
</g>
<!-- http1_wait&#45;&gt;disembark -->
<g id="edge6" class="edge"><title>http1_wait&#45;&gt;disembark</title>
<path fill="none" stroke="green" d="M422.307,-403.301C437.002,-373.118 463.679,-307.551 449.544,-253 433.475,-190.986 421.974,-174.996 379.544,-127 375.151,-122.031 369.936,-117.349 364.589,-113.125"/>
<polygon fill="green" stroke="green" points="366.294,-110.032 356.177,-106.886 362.124,-115.654 366.294,-110.032"/>
<text text-anchor="middle" x="476.044" y="-264.3" font-family="Times,serif" font-size="14.00">Timeout</text>
</g>
<!-- hash -->
<g id="node3" class="node"><title>hash</title>
<ellipse fill="none" stroke="black" cx="136.544" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="136.544" y="-14.3" font-family="Times,serif" font-size="14.00">hash</text>
</g>
<!-- hash&#45;&gt;CNT_Request -->
<g id="edge2" class="edge"><title>hash&#45;&gt;CNT_Request</title>
<path fill="none" stroke="blue" d="M115.322,-29.1756C84.8323,-45.1329 29.8514,-79.2306 7.54392,-127 -22.451,-191.231 49.4699,-261.077 93.1002,-295.8"/>
<polygon fill="blue" stroke="blue" points="91.1075,-298.684 101.149,-302.065 95.4073,-293.16 91.1075,-298.684"/>
<text text-anchor="middle" x="63.0439" y="-160.8" font-family="Times,serif" font-size="14.00">Busy object</text>
<text text-anchor="middle" x="63.0439" y="-145.8" font-family="Times,serif" font-size="14.00">S_STP_WORKING</text>
<text text-anchor="middle" x="63.0439" y="-130.8" font-family="Times,serif" font-size="14.00">R_STP_LOOKUP</text>
</g>
<!-- CNT_Request&#45;&gt;disembark -->
<g id="edge9" class="edge"><title>CNT_Request&#45;&gt;disembark</title>
<path fill="none" stroke="blue" d="M114.911,-301.078C102.927,-274.969 85.1119,-224.299 107.544,-190 144.65,-133.264 222.638,-109.177 276.058,-99.084"/>
<polygon fill="blue" stroke="blue" points="276.832,-102.501 286.063,-97.3019 275.604,-95.6098 276.832,-102.501"/>
<text text-anchor="middle" x="163.044" y="-223.8" font-family="Times,serif" font-size="14.00">Busy object</text>
<text text-anchor="middle" x="163.044" y="-208.8" font-family="Times,serif" font-size="14.00">S_STP_WORKING</text>
<text text-anchor="middle" x="163.044" y="-193.8" font-family="Times,serif" font-size="14.00">R_STP_LOOKUP</text>
</g>
<!-- http1_cleanup -->
<g id="node7" class="node"><title>http1_cleanup</title>
<ellipse fill="none" stroke="black" cx="287.544" cy="-212.5" rx="60.3893" ry="18"/>
<text text-anchor="middle" x="287.544" y="-208.8" font-family="Times,serif" font-size="14.00">http1_cleanup</text>
</g>
<!-- CNT_Request&#45;&gt;http1_cleanup -->
<g id="edge10" class="edge"><title>CNT_Request&#45;&gt;http1_cleanup</title>
<path fill="none" stroke="black" d="M122.518,-300.739C122.631,-286.098 125.264,-265.533 137.544,-253 161.837,-228.206 179.978,-243.845 213.544,-235 221.094,-233.011 229.047,-230.811 236.828,-228.6"/>
<polygon fill="black" stroke="black" points="237.902,-231.933 246.547,-225.809 235.969,-225.205 237.902,-231.933"/>
</g>
<!-- disembark&#45;&gt;hash -->
<g id="edge3" class="edge"><title>disembark&#45;&gt;hash</title>
<path fill="none" stroke="blue" stroke-dasharray="1,5" d="M298.022,-77.7947C261.99,-64.6754 205.087,-43.9568 169.339,-30.9408"/>
<polygon fill="blue" stroke="blue" points="170.446,-27.6192 159.852,-27.4866 168.051,-34.1967 170.446,-27.6192"/>
</g>
<!-- waiter -->
<g id="node6" class="node"><title>waiter</title>
<ellipse fill="none" stroke="black" cx="376.544" cy="-18" rx="32.4942" ry="18"/>
<text text-anchor="middle" x="376.544" y="-14.3" font-family="Times,serif" font-size="14.00">waiter</text>
</g>
<!-- disembark&#45;&gt;waiter -->
<g id="edge7" class="edge"><title>disembark&#45;&gt;waiter</title>
<path fill="none" stroke="green" stroke-dasharray="1,5" d="M342.208,-73.174C347.78,-64.3831 354.705,-53.4564 360.874,-43.7236"/>
<polygon fill="green" stroke="green" points="363.869,-45.5366 366.266,-35.2165 357.956,-41.7892 363.869,-45.5366"/>
</g>
<!-- waiter&#45;&gt;http1_wait -->
<g id="edge8" class="edge"><title>waiter&#45;&gt;http1_wait</title>
<path fill="none" stroke="green" d="M409.074,-19.7692C455.061,-22.7818 533.544,-35.8546 533.544,-90 533.544,-320 533.544,-320 533.544,-320 533.544,-361.025 491.641,-388.484 457.357,-404.084"/>
<polygon fill="green" stroke="green" points="455.714,-400.982 447.931,-408.171 458.498,-407.404 455.714,-400.982"/>
</g>
<!-- http1_cleanup&#45;&gt;http1_wait -->
<g id="edge13" class="edge"><title>http1_cleanup&#45;&gt;http1_wait</title>
<path fill="none" stroke="black" d="M284.429,-230.778C280.813,-255.928 277.543,-303.29 296.544,-337 313.554,-367.178 346.622,-389.066 373.275,-402.763"/>
<polygon fill="black" stroke="black" points="371.882,-405.979 382.398,-407.266 374.981,-399.702 371.882,-405.979"/>
<text text-anchor="middle" x="348.044" y="-315.3" font-family="Times,serif" font-size="14.00">S_STP_NEWREQ</text>
</g>
<!-- http1_cleanup&#45;&gt;CNT_Request -->
<g id="edge12" class="edge"><title>http1_cleanup&#45;&gt;CNT_Request</title>
<path fill="none" stroke="black" d="M246.12,-225.676C208.748,-236.723 159.343,-251.509 157.544,-253 145.588,-262.907 137.308,-278.12 131.915,-291.339"/>
<polygon fill="black" stroke="black" points="128.55,-290.345 128.34,-300.938 135.11,-292.788 128.55,-290.345"/>
<text text-anchor="middle" x="213.044" y="-271.8" font-family="Times,serif" font-size="14.00">S_STP_WORKING</text>
<text text-anchor="middle" x="213.044" y="-256.8" font-family="Times,serif" font-size="14.00">R_STP_RECV</text>
</g>
<!-- http1_cleanup&#45;&gt;disembark -->
<g id="edge11" class="edge"><title>http1_cleanup&#45;&gt;disembark</title>
<path fill="none" stroke="black" d="M283.67,-194.346C280.556,-176.557 278.212,-148.404 288.544,-127 291.002,-121.907 294.597,-117.309 298.677,-113.246"/>
<polygon fill="black" stroke="black" points="301.159,-115.725 306.404,-106.52 296.563,-110.445 301.159,-115.725"/>
<text text-anchor="middle" x="325.044" y="-145.8" font-family="Times,serif" font-size="14.00">Session close</text>
</g>
</g>
</svg>
This diff is collapsed.
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