vinyl-cache/bin/vinyld/cache/cache_req.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2011 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
 * Request management
31
 *
32
 */
33
34
#include "config.h"
35
36 68204
#include <stdio.h>
37 68204
#include <stdlib.h>
38 68204
39 68204
#include "cache_int.h"
40
#include "cache_filter.h"
41
#include "cache_objhead.h"
42
#include "cache_pool.h"
43
#include "cache_transport.h"
44
#include "storage/storage.h"            // stv_default
45
46
#include "common/heritage.h"
47
#include "vtim.h"
48
49
/*--------------------------------------------------------------------
50
 * Facility to keep obcore references until the end of the task across restarts
51
 */
52
53
struct ocstash {
54
        unsigned                magic;
55
#define OCSTASH_MAGIC           0x242031b5
56
        uint16_t                l;
57
        uint16_t                n;
58
        struct objcore *        ocs[] v_counted_by_(l);
59
};
60
61
static void
62 3812
ocstash_push(struct ocstash *stash, struct objcore **ocp)
63
{
64
65 3812
        CHECK_OBJ_NOTNULL(stash, OCSTASH_MAGIC);
66 3812
        assert(stash->n < stash->l);
67 3812
        TAKE_OBJ_NOTNULL(stash->ocs[stash->n], ocp, OBJCORE_MAGIC);
68 3812
        stash->n++;
69 3812
}
70
71
static void
72 97536
ocstash_clear(struct worker *wrk, struct ocstash *stash)
73
{
74
        uint16_t u;
75
76 97536
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
77 97536
        CHECK_OBJ_NOTNULL(stash, OCSTASH_MAGIC);
78 97536
        assert(stash->n <= stash->l);
79 101348
        for (u = 0; u < stash->n; u++)
80 3812
                (void)HSH_DerefObjCore(wrk, &stash->ocs[u]);
81 969597
        for (; u < stash->l; u++)
82 872061
                AZ(stash->ocs[u]);
83 97536
        stash->n = 0;
84 97536
}
85
86
void
87 3812
Req_StashObjcore(const struct req *req, struct objcore **ocp)
88
{
89
90 3812
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
91 3812
        ocstash_push(req->stash, ocp);
92 3812
}
93
94
/*--------------------------------------------------------------------*/
95
96
void
97 123953
Req_AcctLogCharge(struct VSC_main_wrk *ds, struct req *req)
98
{
99
        struct acct_req *a;
100
101 123953
        AN(ds);
102 123953
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
103
104 123953
        a = &req->acct;
105
106 123953
        if (!IS_NO_VXID(req->vsl->wid) && !req->res_pipe) {
107 181702
                VSLb(req->vsl, SLT_ReqAcct, "%ju %ju %ju %ju %ju %ju",
108 90851
                    (uintmax_t)a->req_hdrbytes,
109 90851
                    (uintmax_t)a->req_bodybytes,
110 90851
                    (uintmax_t)(a->req_hdrbytes + a->req_bodybytes),
111 90851
                    (uintmax_t)a->resp_hdrbytes,
112 90851
                    (uintmax_t)a->resp_bodybytes,
113 90851
                    (uintmax_t)(a->resp_hdrbytes + a->resp_bodybytes));
114 90851
        }
115
116 123953
        if (IS_TOPREQ(req)) {
117
#define ACCT(foo) ds->s_##foo += a->foo;
118
#include "tbl/acct_fields_req.h"
119
        }
120 123953
        memset(a, 0, sizeof *a);
121 123953
}
122
123
void
124 24990
Req_LogHit(struct worker *wrk, struct req *req, struct objcore *oc,
125
    intmax_t fetch_progress)
126
{
127
        const char *clen, *sep;
128
129 24990
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
130 24990
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
131 24990
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
132
133 24990
        if (fetch_progress >= 0) {
134 2311
                clen = HTTP_GetHdrPack(wrk, oc, H_Content_Length);
135 2311
                if (clen == NULL)
136 211
                        clen = sep = "";
137
                else
138 2100
                        sep = " ";
139 4622
                VSLb(req->vsl, SLT_Hit, "%ju %.6f %.6f %.6f %jd%s%s",
140 2311
                    VXID(ObjGetXID(wrk, oc)), EXP_Dttl(req, oc),
141 2311
                    oc->grace, oc->keep,
142 2311
                    fetch_progress, sep, clen);
143 2311
        } else {
144 45358
                VSLb(req->vsl, SLT_Hit, "%ju %.6f %.6f %.6f",
145 22679
                    VXID(ObjGetXID(wrk, oc)), EXP_Dttl(req, oc),
146 22679
                    oc->grace, oc->keep);
147
        }
148 24990
}
149
150
const char *
151 88320
Req_LogStart(const struct worker *wrk, struct req *req)
152
{
153
        const char *ci, *cp, *endpname;
154
155 88320
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
156 88320
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
157 88320
        CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC);
158
159 88320
        ci = SES_Get_String_Attr(req->sp, SA_CLIENT_IP);
160 88320
        cp = SES_Get_String_Attr(req->sp, SA_CLIENT_PORT);
161 88320
        CHECK_OBJ_NOTNULL(req->sp->listen_sock, LISTEN_SOCK_MAGIC);
162 88320
        endpname = req->sp->listen_sock->name;
163 88320
        AN(endpname);
164 88320
        VSLb(req->vsl, SLT_ReqStart, "%s %s %s", ci, cp, endpname);
165
166 88320
        return (ci);
167
}
168
169
/*--------------------------------------------------------------------
170
 * Alloc/Free a request
171
 */
172
173
struct req *
174 68410
Req_New(struct sess *sp, const struct req *preq)
175
{
176
        struct pool *pp;
177
        struct req *req;
178
        uint16_t l, nhttp;
179
        unsigned sz, hl;
180
        char *p, *e;
181
182 68410
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
183 68410
        pp = sp->pool;
184 68410
        CHECK_OBJ_NOTNULL(pp, POOL_MAGIC);
185 68410
        CHECK_OBJ_ORNULL(preq, REQ_MAGIC);
186
187 68410
        req = MPL_Get(pp->mpl_req, &sz);
188 68410
        AN(req);
189 68410
        req->magic = REQ_MAGIC;
190 68410
        req->sp = sp;
191
192 68410
        e = (char*)req + sz;
193 68410
        p = (char*)(req + 1);
194 68410
        p = (void*)PRNDUP(p);
195 68410
        assert(p < e);
196
197 68410
        nhttp = (uint16_t)cache_param->http_max_hdr;
198 68410
        hl = HTTP_estimate(nhttp);
199
200 68410
        req->http = HTTP_create(p, nhttp, hl);
201 68410
        p += hl;
202 68410
        p = (void*)PRNDUP(p);
203 68410
        assert(p < e);
204
205 68410
        req->http0 = HTTP_create(p, nhttp, hl);
206 68410
        p += hl;
207 68410
        p = (void*)PRNDUP(p);
208 68410
        assert(p < e);
209
210 68410
        req->resp = HTTP_create(p, nhttp, hl);
211 68410
        p += hl;
212 68410
        p = (void*)PRNDUP(p);
213 68410
        assert(p < e);
214
215 68410
        sz = cache_param->vsl_buffer;
216 68410
        VSL_Init(req->vsl, p, sz);
217 68410
        p += sz;
218 68410
        p = (void*)PRNDUP(p);
219
220 68410
        req->vfc = (void*)p;
221 68410
        INIT_OBJ(req->vfc, VFP_CTX_MAGIC);
222 68410
        p = (void*)PRNDUP(p + sizeof(*req->vfc));
223
224 68410
        req->vdc = (void*)p;
225 68410
        ZERO_OBJ(req->vdc, sizeof *req->vdc);
226 68410
        p = (void*)PRNDUP(p + sizeof(*req->vdc));
227
228 68410
        req->htc = (void*)p;
229 68410
        INIT_OBJ(req->htc, HTTP_CONN_MAGIC);
230 68410
        req->htc->doclose = SC_NULL;
231 68410
        p = (void*)PRNDUP(p + sizeof(*req->htc));
232
233 68410
        if (UNLIKELY(preq != NULL))
234 7773
                req->top = preq->top;
235
        else {
236 60637
                req->top = (void*)p;
237 60637
                INIT_OBJ(req->top, REQTOP_MAGIC);
238 60637
                req->top->topreq = req;
239 60637
                p = (void*)PRNDUP(p + sizeof(*req->top));
240
        }
241
242 68410
        req->max_restarts = cache_param->max_restarts;
243 68410
        assert(req->max_restarts + 1 <= UINT16_MAX);
244
        // each restart may ref one stale_oc and one oc
245 68410
        l = (2 * req->max_restarts) + 1;
246 68410
        sz = SIZEOF_FLEX_OBJ(req->stash, ocs, l);
247 68410
        req->stash = (void*)p;
248 68410
        req->stash->magic = OCSTASH_MAGIC;
249 68410
        req->stash->l = l;
250 68410
        p += sz;
251 68410
        p = (void*)PRNDUP(p);
252
253 68410
        assert(p < e);
254
255 68410
        WS_Init(req->ws, "req", p, e - p);
256
257 68410
        req->t_first = NAN;
258 68410
        req->t_prev = NAN;
259 68410
        req->t_req = NAN;
260 68410
        req->req_step = R_STP_TRANSPORT;
261 68410
        req->doclose = SC_NULL;
262
263 68410
        return (req);
264
}
265
266
void
267 68204
Req_Release(struct req *req)
268
{
269
        struct sess *sp;
270
        struct pool *pp;
271
272 68204
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
273
274
        /* Make sure the request counters have all been zeroed */
275
#define ACCT(foo) \
276
        AZ(req->acct.foo);
277
#include "tbl/acct_fields_req.h"
278
279 68204
        AZ(req->vcl);
280 68204
        if (!IS_NO_VXID(req->vsl->wid))
281 42
                VSL_End(req->vsl);
282
#ifdef ENABLE_WORKSPACE_EMULATOR
283
        WS_Rollback(req->ws, 0);
284
#endif
285 68204
        TAKE_OBJ_NOTNULL(sp, &req->sp, SESS_MAGIC);
286
        pp = sp->pool;
287 68204
        CHECK_OBJ_NOTNULL(pp, POOL_MAGIC);
288 68204
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
289
        MPL_AssertSane(req);
290
        VSL_Flush(req->vsl, 0);
291
        MPL_Free(pp->mpl_req, req);
292
}
293
294
/*----------------------------------------------------------------------
295
 * TODO:
296
 * - check for code duplication with cnt_recv_prep
297
 * - re-check if complete
298
 * - XXX should PRIV_TOP use vcl0?
299
 * - XXX PRIV_TOP does not get rolled back, should it for !IS_TOPREQ ?
300
 */
301
302
void
303 2957
Req_Rollback(VRT_CTX)
304
{
305
        struct req *req;
306
307 2957
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
308 2957
        req = ctx->req;
309 2957
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
310
311 2957
        if (IS_TOPREQ(req))
312 2898
                VCL_TaskLeave(ctx, req->top->privs);
313 2957
        VCL_TaskLeave(ctx, req->privs);
314 2957
        ocstash_clear(req->wrk, req->stash);
315 2957
        VCL_TaskEnter(req->privs);
316 2957
        if (IS_TOPREQ(req))
317 2893
                VCL_TaskEnter(req->top->privs);
318 2957
        HTTP_Clone(req->http, req->http0);
319 2957
        req->vdp_filter_list = NULL;
320 2957
        req->vfp_filter_list = NULL;
321 2957
        req->vcf = NULL;
322 2957
        if (WS_Overflowed(req->ws))
323 210
                req->wrk->stats->ws_client_overflow++;
324 2957
        AN(req->ws_req);
325 2957
        WS_Rollback(req->ws, req->ws_req);
326 2957
}
327
328
/*----------------------------------------------------------------------
329
 * TODO: remove code duplication with cnt_recv_prep
330
 */
331
332
void
333 94590
Req_Cleanup(struct sess *sp, struct worker *wrk, struct req *req)
334
{
335
336 94590
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
337 94590
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
338 94590
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
339 94590
        assert(sp == req->sp);
340 94590
        if (IS_TOPREQ(req))
341 86812
                AZ(req->top->vcl0);
342
343 94590
        AZ(req->director_hint);
344 94590
        req->restarts = 0;
345
346 94590
        ocstash_clear(wrk, req->stash);
347
348 94590
        if (req->vcl != NULL)
349 78184
                VCL_Recache(wrk, &req->vcl);
350
351
        /* Charge and log byte counters */
352 94590
        if (!IS_NO_VXID(req->vsl->wid)) {
353 91313
                Req_AcctLogCharge(wrk->stats, req);
354 91313
                if (!IS_SAME_VXID(req->vsl->wid, sp->vxid))
355 88079
                        VSL_End(req->vsl);
356
                else
357 3234
                        req->vsl->wid = NO_VXID; /* ending an h2 stream 0 */
358 91313
        }
359
360 94590
        if (!isnan(req->t_prev) && req->t_prev > 0. && req->t_prev > sp->t_idle)
361 86141
                sp->t_idle = req->t_prev;
362
        else
363 8449
                sp->t_idle = W_TIM_real(wrk);
364
365 94590
        req->t_first = NAN;
366 94590
        req->t_prev = NAN;
367 94590
        req->t_req = NAN;
368 94590
        req->req_body_status = NULL;
369
370 94590
        req->hash_always_miss = 0;
371 94590
        req->hash_ignore_busy = 0;
372 94590
        req->hash_ignore_vary = 0;
373 94590
        req->esi_level = 0;
374 94590
        req->is_hit = 0;
375 94590
        req->req_step = R_STP_TRANSPORT;
376 94590
        req->vcf = NULL;
377 94590
        req->doclose = SC_NULL;
378 94590
        req->htc->doclose = SC_NULL;
379 94590
        req->htc->body_status = NULL;
380
381 94590
        if (WS_Overflowed(req->ws))
382 3528
                wrk->stats->ws_client_overflow++;
383
384 94590
        wrk->seen_methods = 0;
385
386 94590
        VDP_Fini(req->vdc);
387 94590
}
388
389
/*----------------------------------------------------------------------
390
 * response body for vcl_synth {}
391
 */
392
393
static void
394 105
resp_u_storage(struct req *req)
395
{
396
397 105
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
398 105
        HSH_DerefBoc(req->wrk, req->objcore);
399 105
        (void)HSH_DerefObjCore(req->wrk, &req->objcore);
400 105
}
401
402
int
403 12028
Resp_l_storage(struct req *req, const struct stevedore *stv)
404
{
405
        int r;
406
407 12028
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
408 12028
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
409
410 12028
        if (req->objcore != NULL)
411 63
                resp_u_storage(req);
412 12028
        AZ(req->objcore);
413 12028
        req->objcore = HSH_Private(req->wrk);
414 12028
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
415 12028
        r = STV_NewObject(req->wrk, req->objcore, stv, 0);
416 12028
        if (r == 0)
417 42
                resp_u_storage(req);
418 12028
        return (r);
419
}
420
421
422
/*----------------------------------------------------------------------
423
 */
424
425
void v_matchproto_(vtr_req_fail_f)
426 651
Req_Fail(struct req *req, stream_close_t reason)
427
{
428 651
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
429
430 651
        AN(req->transport->req_fail);
431 651
        req->transport->req_fail(req, reason);
432 651
}