varnish-cache/lib/libvmod_vtc/vmod_vtc.c
1
/*-
2
 * Copyright (c) 2012-2017 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@FreeBSD.org>
6
 * Author: Dridi Boukelmoune <dridi.boukelmoune@gmail.com>
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29
30
#include "config.h"
31
32
#include <errno.h>
33
#include <stdio.h>
34
#include <string.h>
35
#include <unistd.h>
36
37
#include "cache/cache.h"
38
39
#include "vtcp.h"
40
#include "vtim.h"
41
42
#include "vcc_if.h"
43
44
VCL_VOID v_matchproto_(td_vtc_barrier_sync)
45 6
vmod_barrier_sync(VRT_CTX, VCL_STRING addr, VCL_DURATION tmo)
46
{
47
        const char *err;
48
        char buf[32];
49
        int sock, i;
50
        ssize_t sz;
51
52 6
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
53 6
        AN(addr);
54 6
        AN(*addr);
55 6
        assert(tmo >= 0.0);
56
57 6
        VSLb(ctx->vsl, SLT_Debug, "barrier_sync(\"%s\")", addr);
58 6
        sock = VTCP_open(addr, NULL, 0., &err);
59 6
        if (sock < 0) {
60 0
                VRT_fail(ctx, "Barrier connection failed: %s", err);
61 6
                return;
62
        }
63
64 6
        sz = VTCP_read(sock, buf, sizeof buf, tmo);
65 6
        i = errno;
66 6
        closefd(&sock);
67 6
        if (sz < 0)
68 0
                VRT_fail(ctx, "Barrier read failed: %s (errno=%d)",
69
                    strerror(i), i);
70 6
        if (sz > 0)
71 0
                VRT_fail(ctx, "Barrier unexpected data (%zdB)", sz);
72
}
73
74
/*--------------------------------------------------------------------*/
75
76
VCL_BACKEND v_matchproto_(td_vtc_no_backend)
77 3
vmod_no_backend(VRT_CTX)
78
{
79
80 3
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
81 3
        return (NULL);
82
}
83
84
VCL_STEVEDORE v_matchproto_(td_vtc_no_stevedore)
85 1
vmod_no_stevedore(VRT_CTX)
86
{
87
88 1
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
89 1
        return (NULL);
90
}
91
92
/*--------------------------------------------------------------------*/
93
94
VCL_VOID v_matchproto_(td_vtc_panic)
95 3
vmod_panic(VRT_CTX, const char *str, ...)
96
{
97
        va_list ap;
98
        const char *b;
99
100 3
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
101
102 3
        va_start(ap, str);
103 3
        b = VRT_String(ctx->ws, "PANIC: ", str, ap);
104 3
        va_end(ap);
105 3
        VAS_Fail("VCL", "", 0, b, VAS_VCL);
106
}
107
108
/*--------------------------------------------------------------------*/
109
110
VCL_VOID v_matchproto_(td_vtc_sleep)
111 2
vmod_sleep(VRT_CTX, VCL_DURATION t)
112
{
113
114 2
        CHECK_OBJ_ORNULL(ctx, VRT_CTX_MAGIC);
115 2
        VTIM_sleep(t);
116 2
}
117
118
/*--------------------------------------------------------------------*/
119
120
static uintptr_t vtc_ws_snapshot;
121
122
static struct ws *
123 72
vtc_ws_find(VRT_CTX, VCL_ENUM which)
124
{
125
126 72
        if (!strcmp(which, "client"))
127 15
                return (ctx->ws);
128 57
        if (!strcmp(which, "backend"))
129 47
                return (ctx->bo->ws);
130 10
        if (!strcmp(which, "session"))
131 8
                return (ctx->req->sp->ws);
132 2
        if (!strcmp(which, "thread"))
133 2
                return (ctx->req->wrk->aws);
134 0
        WRONG("vtc_ws_find Illegal enum");
135
}
136
137
VCL_VOID v_matchproto_(td_vtc_workspace_alloc)
138 53
vmod_workspace_alloc(VRT_CTX, VCL_ENUM which, VCL_INT size)
139
{
140
        struct ws *ws;
141
        void *p;
142
143 53
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
144
145 53
        ws = vtc_ws_find(ctx, which);
146 53
        if (ws == NULL)
147 0
                return;
148 53
        WS_Assert(ws);
149
150 53
        if (size < 0) {
151 46
                size += WS_Reserve(ws, 0);
152 46
                WS_Release(ws, 0);
153
        }
154 53
        if (size <= 0) {
155 1
                VRT_fail(ctx, "Attempted negative WS allocation");
156 1
                return;
157
        }
158 52
        p = WS_Alloc(ws, size);
159 52
        if (p == NULL)
160 1
                VRT_fail(ctx, "vtc.workspace_alloc");
161
        else
162 51
                memset(p, '\0', size);
163
}
164
165
VCL_INT v_matchproto_(td_vtc_workspace_free)
166 11
vmod_workspace_free(VRT_CTX, VCL_ENUM which)
167
{
168
        struct ws *ws;
169
        unsigned u;
170
171 11
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
172
173 11
        ws = vtc_ws_find(ctx, which);
174 11
        if (ws == NULL)
175 0
                return(-1);
176 11
        WS_Assert(ws);
177
178 11
        u = WS_Reserve(ws, 0);
179 11
        WS_Release(ws, 0);
180 11
        return (u);
181
}
182
183
#define VTC_WS_OP(type, def, name, op)                  \
184
VCL_##type v_matchproto_(td_vtc_workspace_##name)       \
185
vmod_workspace_##name(VRT_CTX, VCL_ENUM which)          \
186
{                                                       \
187
        struct ws *ws;                                  \
188
                                                        \
189
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);          \
190
                                                        \
191
        ws = vtc_ws_find(ctx, which);                   \
192
        if (ws == NULL)                                 \
193
                return def ;                            \
194
        WS_Assert(ws);                                  \
195
                                                        \
196
        op;                                             \
197
}
198 1
VTC_WS_OP(VOID, , snapshot, (vtc_ws_snapshot = WS_Snapshot(ws)))
199 1
VTC_WS_OP(VOID, , reset, WS_Reset(ws, vtc_ws_snapshot))
200 1
VTC_WS_OP(VOID, , overflow, WS_MarkOverflow(ws))
201 5
VTC_WS_OP(BOOL, (0), overflowed, return (WS_Overflowed(ws)))
202
#undef VTC_WS_OP
203
204
/*--------------------------------------------------------------------*/
205
206
VCL_INT v_matchproto_(td_vtc_typesize)
207 2
vmod_typesize(VRT_CTX, VCL_STRING s)
208
{
209 2
        size_t i = 0;
210
        const char *p;
211
212 2
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
213
214 11
        for (p = s; *p; p++) {
215 10
                switch (*p) {
216
#define VTC_TYPESIZE(c, t) case c: i += sizeof(t); break;
217 1
                VTC_TYPESIZE('d', double)
218 1
                VTC_TYPESIZE('f', float)
219 1
                VTC_TYPESIZE('i', int)
220 1
                VTC_TYPESIZE('j', intmax_t)
221 1
                VTC_TYPESIZE('l', long)
222 1
                VTC_TYPESIZE('o', off_t)
223 1
                VTC_TYPESIZE('p', void *)
224 1
                VTC_TYPESIZE('s', short)
225 1
                VTC_TYPESIZE('z', size_t)
226
#undef VTC_TYPESIZE
227 1
                default:        return (-1);
228
                }
229
        }
230 1
        return ((VCL_INT)i);
231
}