varnish-cache/bin/varnishd/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 122244
#include <stdio.h>
37 122244
#include <stdlib.h>
38 122244
39 122244
#include "cache_varnishd.h"
40
#include "cache_filter.h"
41
#include "cache_pool.h"
42
#include "cache_transport.h"
43
44
#include "common/heritage.h"
45
#include "vtim.h"
46
47
void
48 218961
Req_AcctLogCharge(struct VSC_main_wrk *ds, struct req *req)
49
{
50
        struct acct_req *a;
51
52 218961
        AN(ds);
53 218961
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
54
55 218961
        a = &req->acct;
56
57 218961
        if (!IS_NO_VXID(req->vsl->wid) && !req->res_pipe) {
58 318092
                VSLb(req->vsl, SLT_ReqAcct, "%ju %ju %ju %ju %ju %ju",
59 159046
                    (uintmax_t)a->req_hdrbytes,
60 159046
                    (uintmax_t)a->req_bodybytes,
61 159046
                    (uintmax_t)(a->req_hdrbytes + a->req_bodybytes),
62 159046
                    (uintmax_t)a->resp_hdrbytes,
63 159046
                    (uintmax_t)a->resp_bodybytes,
64 159046
                    (uintmax_t)(a->resp_hdrbytes + a->resp_bodybytes));
65 159046
        }
66
67 218961
        if (IS_TOPREQ(req)) {
68
#define ACCT(foo) ds->s_##foo += a->foo;
69
#include "tbl/acct_fields_req.h"
70
        }
71 218961
        memset(a, 0, sizeof *a);
72 218961
}
73
74
void
75 46717
Req_LogHit(struct worker *wrk, struct req *req, struct objcore *oc,
76
    intmax_t fetch_progress)
77
{
78
        const char *clen, *sep;
79
80 46717
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
81 46717
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
82 46717
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
83
84 46717
        if (fetch_progress >= 0) {
85 4188
                clen = HTTP_GetHdrPack(wrk, oc, H_Content_Length);
86 4188
                if (clen == NULL)
87 374
                        clen = sep = "";
88
                else
89 3814
                        sep = " ";
90 8376
                VSLb(req->vsl, SLT_Hit, "%ju %.6f %.6f %.6f %jd%s%s",
91 4188
                    VXID(ObjGetXID(wrk, oc)), EXP_Dttl(req, oc),
92 4188
                    oc->grace, oc->keep,
93 4188
                    fetch_progress, sep, clen);
94 4188
        } else {
95 85058
                VSLb(req->vsl, SLT_Hit, "%ju %.6f %.6f %.6f",
96 42529
                    VXID(ObjGetXID(wrk, oc)), EXP_Dttl(req, oc),
97 42529
                    oc->grace, oc->keep);
98
        }
99 46717
}
100
101
const char *
102 154272
Req_LogStart(const struct worker *wrk, struct req *req)
103
{
104
        const char *ci, *cp, *endpname;
105
106 154272
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
107 154272
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
108 154272
        CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC);
109
110 154272
        ci = SES_Get_String_Attr(req->sp, SA_CLIENT_IP);
111 154272
        cp = SES_Get_String_Attr(req->sp, SA_CLIENT_PORT);
112 154272
        CHECK_OBJ_NOTNULL(req->sp->listen_sock, LISTEN_SOCK_MAGIC);
113 154272
        endpname = req->sp->listen_sock->name;
114 154272
        AN(endpname);
115 154272
        VSLb(req->vsl, SLT_ReqStart, "%s %s %s", ci, cp, endpname);
116
117 154272
        return (ci);
118
}
119
120
/*--------------------------------------------------------------------
121
 * Alloc/Free a request
122
 */
123
124
struct req *
125 122632
Req_New(struct sess *sp, const struct req *preq)
126
{
127
        struct pool *pp;
128
        struct req *req;
129
        uint16_t nhttp;
130
        unsigned sz, hl;
131
        char *p, *e;
132
133 122632
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
134 122632
        pp = sp->pool;
135 122632
        CHECK_OBJ_NOTNULL(pp, POOL_MAGIC);
136 122632
        CHECK_OBJ_ORNULL(preq, REQ_MAGIC);
137
138 122632
        req = MPL_Get(pp->mpl_req, &sz);
139 122632
        AN(req);
140 122632
        req->magic = REQ_MAGIC;
141 122632
        req->sp = sp;
142
143 122632
        e = (char*)req + sz;
144 122632
        p = (char*)(req + 1);
145 122632
        p = (void*)PRNDUP(p);
146 122632
        assert(p < e);
147
148 122632
        nhttp = (uint16_t)cache_param->http_max_hdr;
149 122632
        hl = HTTP_estimate(nhttp);
150
151 122632
        req->http = HTTP_create(p, nhttp, hl);
152 122632
        p += hl;
153 122632
        p = (void*)PRNDUP(p);
154 122632
        assert(p < e);
155
156 122632
        req->http0 = HTTP_create(p, nhttp, hl);
157 122632
        p += hl;
158 122632
        p = (void*)PRNDUP(p);
159 122632
        assert(p < e);
160
161 122632
        req->resp = HTTP_create(p, nhttp, hl);
162 122632
        p += hl;
163 122632
        p = (void*)PRNDUP(p);
164 122632
        assert(p < e);
165
166 122632
        sz = cache_param->vsl_buffer;
167 122632
        VSL_Setup(req->vsl, p, sz);
168 122632
        p += sz;
169 122632
        p = (void*)PRNDUP(p);
170
171 122632
        req->vfc = (void*)p;
172 122632
        INIT_OBJ(req->vfc, VFP_CTX_MAGIC);
173 122632
        p = (void*)PRNDUP(p + sizeof(*req->vfc));
174
175 122632
        req->vdc = (void*)p;
176 122632
        ZERO_OBJ(req->vdc, sizeof *req->vdc);
177 122632
        p = (void*)PRNDUP(p + sizeof(*req->vdc));
178
179 122632
        req->htc = (void*)p;
180 122632
        INIT_OBJ(req->htc, HTTP_CONN_MAGIC);
181 122632
        req->htc->doclose = SC_NULL;
182 122632
        p = (void*)PRNDUP(p + sizeof(*req->htc));
183
184 122632
        if (UNLIKELY(preq != NULL))
185 14640
                req->top = preq->top;
186
        else {
187 107992
                req->top = (void*)p;
188 107992
                INIT_OBJ(req->top, REQTOP_MAGIC);
189 107992
                req->top->topreq = req;
190 107992
                p = (void*)PRNDUP(p + sizeof(*req->top));
191
        }
192
193 122632
        assert(p < e);
194
195 122632
        WS_Init(req->ws, "req", p, e - p);
196
197 122632
        req->t_first = NAN;
198 122632
        req->t_prev = NAN;
199 122632
        req->t_req = NAN;
200 122632
        req->req_step = R_STP_TRANSPORT;
201 122632
        req->doclose = SC_NULL;
202 122632
        req->max_restarts = cache_param->max_restarts;
203
204 122632
        return (req);
205
}
206
207
void
208 122244
Req_Release(struct req *req)
209
{
210
        struct sess *sp;
211
        struct pool *pp;
212
213 122244
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
214
215
        /* Make sure the request counters have all been zeroed */
216
#define ACCT(foo) \
217
        AZ(req->acct.foo);
218
#include "tbl/acct_fields_req.h"
219
220 122244
        AZ(req->vcl);
221 122244
        if (!IS_NO_VXID(req->vsl->wid))
222 80
                VSL_End(req->vsl);
223
#ifdef ENABLE_WORKSPACE_EMULATOR
224
        WS_Rollback(req->ws, 0);
225
#endif
226 122244
        TAKE_OBJ_NOTNULL(sp, &req->sp, SESS_MAGIC);
227
        pp = sp->pool;
228 122244
        CHECK_OBJ_NOTNULL(pp, POOL_MAGIC);
229 122244
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
230
        MPL_AssertSane(req);
231
        VSL_Flush(req->vsl, 0);
232
        MPL_Free(pp->mpl_req, req);
233
}
234
235
/*----------------------------------------------------------------------
236
 * TODO:
237
 * - check for code duplication with cnt_recv_prep
238
 * - re-check if complete
239
 * - XXX should PRIV_TOP use vcl0?
240
 * - XXX PRIV_TOP does not get rolled back, should it for !IS_TOPREQ ?
241
 */
242
243
void
244 7556
Req_Rollback(VRT_CTX)
245
{
246
        struct req *req;
247
248 7556
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
249 7556
        req = ctx->req;
250 7556
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
251
252 7556
        if (IS_TOPREQ(req))
253 7439
                VCL_TaskLeave(ctx, req->top->privs);
254 7556
        VCL_TaskLeave(ctx, req->privs);
255 7556
        VCL_TaskEnter(req->privs);
256 7556
        if (IS_TOPREQ(req))
257 7429
                VCL_TaskEnter(req->top->privs);
258 7556
        HTTP_Clone(req->http, req->http0);
259 7556
        req->vdp_filter_list = NULL;
260 7556
        req->vfp_filter_list = NULL;
261 7556
        req->vcf = NULL;
262 7556
        if (WS_Overflowed(req->ws))
263 400
                req->wrk->stats->ws_client_overflow++;
264 7556
        AN(req->ws_req);
265 7556
        WS_Rollback(req->ws, req->ws_req);
266 7556
}
267
268
/*----------------------------------------------------------------------
269
 * TODO: remove code duplication with cnt_recv_prep
270
 */
271
272
void
273 166127
Req_Cleanup(struct sess *sp, struct worker *wrk, struct req *req)
274
{
275
276 166127
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
277 166127
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
278 166127
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
279 166127
        assert(sp == req->sp);
280 166127
        if (IS_TOPREQ(req))
281 151482
                AZ(req->top->vcl0);
282
283 166127
        AZ(req->director_hint);
284 166127
        req->restarts = 0;
285
286 166127
        if (req->vcl != NULL)
287 135731
                VCL_Recache(wrk, &req->vcl);
288
289
        /* Charge and log byte counters */
290 166127
        if (!IS_NO_VXID(req->vsl->wid)) {
291 159925
                Req_AcctLogCharge(wrk->stats, req);
292 159925
                if (!IS_SAME_VXID(req->vsl->wid, sp->vxid))
293 153811
                        VSL_End(req->vsl);
294
                else
295 6114
                        req->vsl->wid = NO_VXID; /* ending an h2 stream 0 */
296 159925
        }
297
298 166127
        if (!isnan(req->t_prev) && req->t_prev > 0. && req->t_prev > sp->t_idle)
299 150567
                sp->t_idle = req->t_prev;
300
        else
301 15560
                sp->t_idle = W_TIM_real(wrk);
302
303 166127
        req->t_first = NAN;
304 166127
        req->t_prev = NAN;
305 166127
        req->t_req = NAN;
306 166127
        req->req_body_status = NULL;
307
308 166127
        req->hash_always_miss = 0;
309 166127
        req->hash_ignore_busy = 0;
310 166127
        req->hash_ignore_vary = 0;
311 166127
        req->esi_level = 0;
312 166127
        req->is_hit = 0;
313 166127
        req->req_step = R_STP_TRANSPORT;
314 166127
        req->vcf = NULL;
315 166127
        req->doclose = SC_NULL;
316 166127
        req->htc->doclose = SC_NULL;
317 166127
        req->htc->body_status = NULL;
318
319 166127
        if (WS_Overflowed(req->ws))
320 6680
                wrk->stats->ws_client_overflow++;
321
322 166127
        wrk->seen_methods = 0;
323
324 166127
        VDP_Fini(req->vdc);
325 166127
}
326
327
/*----------------------------------------------------------------------
328
 */
329
330
void v_matchproto_(vtr_req_fail_f)
331 1240
Req_Fail(struct req *req, stream_close_t reason)
332
{
333 1240
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
334
335 1240
        AN(req->transport->req_fail);
336 1240
        req->transport->req_fail(req, reason);
337 1240
}