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