vinyl-cache/bin/vinyld/cache/cache_vpi.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2019 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 */
31
32
#include "config.h"
33
34
#include <stdio.h>
35
36
#include "cache_int.h"
37
38
#include "vcl.h"
39
#include "vbm.h"
40
41
#include "vcc_interface.h"
42
43
#include "cache_vcl.h"
44
45
/*--------------------------------------------------------------------
46
 * Private & exclusive interfaces between VCC and vinyld
47
 */
48
49
const size_t vpi_wrk_len = sizeof(struct wrk_vpi);
50
51
void
52 423509
VPI_wrk_init(struct worker *wrk, void *p, size_t spc)
53
{
54 423509
        struct wrk_vpi *vpi = p;
55
56 423509
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
57 423509
        AN(vpi);
58 423509
        assert(spc >= sizeof *vpi);
59 423509
        INIT_OBJ(vpi, WRK_VPI_MAGIC);
60 423509
        wrk->vpi = vpi;
61 423509
}
62
63
void
64 6216
VPI_trace(VRT_CTX, unsigned u)
65
{
66
67 6216
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
68 6216
        CHECK_OBJ_NOTNULL(ctx->vcl, VCL_MAGIC);
69 6216
        CHECK_OBJ_NOTNULL(ctx->vcl->conf, VCL_CONF_MAGIC);
70 6216
        assert(u < ctx->vcl->conf->nref);
71 6216
        if (ctx->vsl != NULL)
72 12096
                VSLb(ctx->vsl, SLT_VCL_trace, "%s %u %u.%u.%u",
73 6048
                    ctx->vcl->loaded_name, u, ctx->vcl->conf->ref[u].source,
74 6048
                    ctx->vcl->conf->ref[u].line, ctx->vcl->conf->ref[u].pos);
75
        else
76 336
                VSL(SLT_VCL_trace, NO_VXID, "%s %u %u.%u.%u",
77 168
                    ctx->vcl->loaded_name, u, ctx->vcl->conf->ref[u].source,
78 168
                    ctx->vcl->conf->ref[u].line, ctx->vcl->conf->ref[u].pos);
79 6216
}
80
81
static void
82 147
vpi_ref_panic(struct vsb *vsb, unsigned n, const struct vcl *vcl)
83
{
84 147
        const struct VCL_conf *conf = NULL;
85
        const struct vpi_ref *ref;
86 147
        const char *src = NULL;
87 147
        int w = 0;
88
89 147
        AN(vsb);
90
91 147
        if (vcl != NULL)
92 147
                conf = vcl->conf;
93 147
        if (conf != NULL && conf->magic != VCL_CONF_MAGIC)
94 0
                conf = NULL;
95
96 147
        if (conf == NULL) {
97 0
                VSB_printf(vsb, "ref = %u, nref = ?,\n", n);
98 0
                return;
99
        }
100 147
        if (n >= conf->nref) {
101 0
                VSB_printf(vsb, "ref = %u *invalid*, nref = %u\n",
102 0
                    n, conf->nref);
103 0
                return;
104
        }
105
106 147
        VSB_printf(vsb, "ref = %u,\n", n);
107
108 147
        ref = &conf->ref[n];
109 147
        if (PAN_dump_struct(vsb, ref, VPI_REF_MAGIC, "vpi_ref"))
110 0
                return;
111
112 147
        if (ref->source < conf->nsrc) {
113 294
                VSB_printf(vsb, "source = %u (\"%s\"),\n", ref->source,
114 147
                    conf->srcname[ref->source]);
115 147
                src = conf->srcbody[ref->source];
116 147
        } else {
117 0
                VSB_printf(vsb, "source = %u *invalid*,\n", ref->source);
118
        }
119
120 147
        if (src != NULL) {
121 147
                w = vstrlen(src);
122 147
                assert(w > 0);
123 147
                if (ref->offset >= (unsigned)w) {
124 0
                        src = NULL;
125 0
                } else {
126 147
                        src += ref->offset;
127
                }
128 147
        }
129
130 147
        VSB_printf(vsb, "offset = %u,\n", ref->offset);
131 147
        VSB_printf(vsb, "line = %u,\n", ref->line);
132 147
        VSB_printf(vsb, "pos = %u,\n", ref->pos);
133 147
        if (src != NULL) {
134 147
                VSB_cat(vsb, "src = ");
135 147
                VSB_quote(vsb, src, 40, VSB_QUOTE_CSTR | VSB_QUOTE_ABBREVIATE);
136 147
                VSB_putc(vsb, '\n');
137 147
        } else {
138 0
                VSB_printf(vsb, "token = \"%s\"\n", ref->token);
139
        }
140 147
        VSB_indent(vsb, -2);
141 147
        VSB_cat(vsb, "},\n");
142
143 147
}
144
void
145 147
VPI_Panic(struct vsb *vsb, const struct wrk_vpi *vpi, const struct vcl *vcl)
146
{
147
        const char *hand;
148
149 147
        AN(vsb);
150 147
        if (PAN_dump_struct(vsb, vpi, WRK_VPI_MAGIC, "vpi"))
151 0
                return;
152
153 147
        hand = VCL_Return_Name(vpi->handling);
154 147
        if (vpi->handling == 0)
155 147
                hand = "none";
156 0
        else if (hand == NULL)
157 0
                hand = "*invalid*";
158
159 294
        VSB_printf(vsb, "handling (VCL::return) = 0x%x (%s),\n",
160 147
            vpi->handling, hand);
161
162 147
        vpi_ref_panic(vsb, vpi->ref, vcl);
163
164 147
        VSB_indent(vsb, -2);
165 147
        VSB_cat(vsb, "},\n");
166 147
}
167
168
/*
169
 * After vcl_fini {} == VGC_function_vcl_fini() is called from VGC_Discard(),
170
 * handling must either be OK from VCL "return (ok)" or FAIL from VRT_fail().
171
 *
172
 * replace OK with 0 for _fini callbacks because that handling has meaning only
173
 * when returning from VCL subs
174
 */
175
176
void
177 1659
VPI_vcl_fini(VRT_CTX)
178
{
179 1659
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
180 1659
        AN(ctx->vpi);
181
182 1659
        if (ctx->vpi->handling == VCL_RET_FAIL)
183 21
                return;
184 1638
        assert(ctx->vpi->handling == VCL_RET_OK);
185 1638
        ctx->vpi->handling = 0;
186 1659
}
187
188
VCL_VCL
189 441
VPI_vcl_get(VRT_CTX, const char *name)
190
{
191
        VCL_VCL vcl;
192
193 441
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
194 441
        vcl = vcl_find(name);
195 441
        AN(vcl);
196 441
        Lck_Lock(&vcl_mtx);
197 441
        vcl->nrefs++;
198 441
        Lck_Unlock(&vcl_mtx);
199 441
        return (vcl);
200
}
201
202
void
203 126
VPI_vcl_rel(VRT_CTX, VCL_VCL vcl)
204
{
205 126
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
206 126
        AN(vcl);
207 126
        Lck_Lock(&vcl_mtx);
208 126
        vcl->nrefs--;
209 126
        Lck_Unlock(&vcl_mtx);
210 126
}
211
212
void
213 861
VPI_vcl_select(VRT_CTX, VCL_VCL vcl)
214
{
215 861
        struct req *req = ctx->req;
216
217 861
        CHECK_OBJ_NOTNULL(vcl, VCL_MAGIC);
218 861
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
219 861
        CHECK_OBJ_NOTNULL(req->top, REQTOP_MAGIC);
220
221 861
        if ((IS_TOPREQ(req) && req->top->vcl0 != NULL) || req->restarts > 0)
222 588
                return;         // Illegal, req-FSM will fail this later.
223
224 273
        if (! IS_TOPREQ(req))
225 21
                assert(req->vcl == req->top->vcl0);
226
227 273
        Req_Rollback(ctx);
228
229 273
        if (IS_TOPREQ(req)) {
230 252
                AN(req->top);
231 252
                AZ(req->top->vcl0);
232 252
                req->top->vcl0 = req->vcl;
233 252
                req->vcl = NULL;
234 252
        }
235 273
        VCL_Update(&req->vcl, vcl);
236 546
        VSLb(ctx->req->vsl, SLT_VCL_use, "%s via %s",
237 273
            req->vcl->loaded_name, vcl->loaded_name);
238 357
}
239
240
void v_noreturn_
241 0
VPI_Fail(const char *func, const char *file, int line,
242
    const char *cond)
243
{
244 0
        VAS_Fail(func, file, line, cond, VAS_ASSERT);
245
}
246
247
enum vcl_func_fail_e
248 441
VPI_Call_Check(VRT_CTX, const struct VCL_conf *conf,
249
    unsigned methods, unsigned n)
250
{
251
        struct vbitmap *vbm;
252
253 441
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
254 441
        CHECK_OBJ_NOTNULL(ctx->vcl, VCL_MAGIC);
255
256 441
        assert(conf == ctx->vcl->conf);
257
258 420
        vbm = ctx->called;
259 420
        AN(vbm);
260
261 420
        if ((methods & ctx->method) == 0)
262 63
                return (VSUB_E_METHOD);
263
264 357
        if (vbit_test(vbm, n))
265 42
                return (VSUB_E_RECURSE);
266
267 315
        return (VSUB_E_OK);
268 420
}
269
270
void
271 315
VPI_Call_Begin(VRT_CTX, unsigned n)
272
{
273
        struct vbitmap *vbm;
274
275 315
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
276 315
        vbm = ctx->called;
277 315
        AN(vbm);
278 315
        vbit_set(vbm, n);
279 315
}
280
281
void
282 315
VPI_Call_End(VRT_CTX, unsigned n)
283
{
284
        struct vbitmap *vbm;
285
286 315
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
287 315
        vbm = ctx->called;
288 315
        AN(vbm);
289 315
        vbit_clr(vbm, n);
290 315
}
291
292
VCL_BOOL
293 126
VPI_PtrCmp(const void *p1, const void *p2)
294
{
295
296 126
        return (p1 != p2);
297
}