| | varnish-cache/bin/varnishd/cache/cache_deliver_proc.c |
0 |
|
/*- |
1 |
|
* Copyright (c) 2006 Verdens Gang AS |
2 |
|
* Copyright (c) 2006-2015 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 |
|
#include "config.h" |
32 |
|
|
33 |
|
#include "cache_varnishd.h" |
34 |
|
#include "cache_filter.h" |
35 |
|
#include "cache_objhead.h" |
36 |
|
|
37 |
|
void |
38 |
240 |
VDP_Panic(struct vsb *vsb, const struct vdp_ctx *vdc) |
39 |
|
{ |
40 |
|
struct vdp_entry *vde; |
41 |
|
|
42 |
240 |
if (PAN_dump_struct(vsb, vdc, VDP_CTX_MAGIC, "vdc")) |
43 |
160 |
return; |
44 |
80 |
VSB_printf(vsb, "nxt = %p,\n", vdc->nxt); |
45 |
80 |
VSB_printf(vsb, "retval = %d,\n", vdc->retval); |
46 |
|
|
47 |
80 |
if (!VTAILQ_EMPTY(&vdc->vdp)) { |
48 |
40 |
VSB_cat(vsb, "filters = {\n"); |
49 |
40 |
VSB_indent(vsb, 2); |
50 |
120 |
VTAILQ_FOREACH(vde, &vdc->vdp, list) |
51 |
160 |
VSB_printf(vsb, "%s = %p { priv = %p }\n", |
52 |
80 |
vde->vdp->name, vde, vde->priv); |
53 |
40 |
VSB_indent(vsb, -2); |
54 |
40 |
VSB_cat(vsb, "},\n"); |
55 |
40 |
} |
56 |
|
|
57 |
80 |
VSB_indent(vsb, -2); |
58 |
80 |
VSB_cat(vsb, "},\n"); |
59 |
240 |
} |
60 |
|
|
61 |
|
/* |
62 |
|
* Ensure that transports have called VDP_Close() |
63 |
|
* to avoid leaks in VDPs |
64 |
|
*/ |
65 |
|
void |
66 |
156534 |
VDP_Fini(const struct vdp_ctx *vdc) |
67 |
|
{ |
68 |
156534 |
assert(VTAILQ_EMPTY(&vdc->vdp)); |
69 |
156534 |
} |
70 |
|
|
71 |
|
void |
72 |
223327 |
VDP_Init(struct vdp_ctx *vdc, struct worker *wrk, struct vsl_log *vsl, |
73 |
|
const struct req *req, const struct busyobj *bo, intmax_t *clen) |
74 |
|
{ |
75 |
223327 |
AN(vdc); |
76 |
223327 |
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); |
77 |
223327 |
AN(vsl); |
78 |
|
|
79 |
223327 |
AN(clen); |
80 |
|
|
81 |
223327 |
assert((req ? 1 : 0) ^ (bo ? 1 : 0)); |
82 |
|
|
83 |
223327 |
AN(clen); |
84 |
223327 |
assert(*clen >= -1); |
85 |
|
|
86 |
223327 |
INIT_OBJ(vdc, VDP_CTX_MAGIC); |
87 |
223327 |
VTAILQ_INIT(&vdc->vdp); |
88 |
223327 |
vdc->wrk = wrk; |
89 |
223327 |
vdc->vsl = vsl; |
90 |
223327 |
vdc->clen = clen; |
91 |
|
|
92 |
223327 |
if (req != NULL) { |
93 |
139767 |
CHECK_OBJ(req, REQ_MAGIC); |
94 |
139767 |
vdc->oc = req->objcore; |
95 |
139767 |
vdc->hp = req->resp; |
96 |
139767 |
} |
97 |
|
else { |
98 |
83560 |
CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); |
99 |
83560 |
vdc->oc = bo->bereq_body; |
100 |
83560 |
vdc->hp = bo->bereq; |
101 |
|
} |
102 |
223327 |
} |
103 |
|
|
104 |
|
/* VDP_bytes |
105 |
|
* |
106 |
|
* Pushes len bytes at ptr down the delivery processor list. |
107 |
|
* |
108 |
|
* This function picks and calls the next delivery processor from the |
109 |
|
* list. The return value is the return value of the delivery |
110 |
|
* processor. Upon seeing a non-zero return value, that lowest value |
111 |
|
* observed is latched in ->retval and all subsequent calls to |
112 |
|
* VDP_bytes will return that value directly without calling the next |
113 |
|
* processor. |
114 |
|
* |
115 |
|
* VDP_END marks the end of successful processing, it is issued by |
116 |
|
* VDP_DeliverObj() and may also be sent downstream by processors ending the |
117 |
|
* stream (for return value != 0) |
118 |
|
* |
119 |
|
* VDP_END must at most be received once per processor, so any VDP sending it |
120 |
|
* downstream must itself not forward it a second time. |
121 |
|
* |
122 |
|
* Valid return values (of VDP_bytes and any VDP function): |
123 |
|
* r < 0: Error, breaks out early on an error condition |
124 |
|
* r == 0: Continue |
125 |
|
* r > 0: Stop, breaks out early without error condition |
126 |
|
*/ |
127 |
|
|
128 |
|
int |
129 |
320156 |
VDP_bytes(struct vdp_ctx *vdc, enum vdp_action act, |
130 |
|
const void *ptr, ssize_t len) |
131 |
|
{ |
132 |
|
int retval; |
133 |
|
struct vdp_entry *vdpe; |
134 |
|
|
135 |
320156 |
CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC); |
136 |
320156 |
if (vdc->retval) |
137 |
958 |
return (vdc->retval); |
138 |
319198 |
vdpe = vdc->nxt; |
139 |
319198 |
CHECK_OBJ_NOTNULL(vdpe, VDP_ENTRY_MAGIC); |
140 |
|
|
141 |
|
/* at most one VDP_END call */ |
142 |
319198 |
assert(vdpe->end == VDP_NULL); |
143 |
|
|
144 |
319198 |
if (act == VDP_NULL) |
145 |
17090 |
assert(len > 0); |
146 |
302108 |
else if (act == VDP_END) |
147 |
108282 |
vdpe->end = VDP_END; |
148 |
|
else |
149 |
193826 |
assert(act == VDP_FLUSH); |
150 |
|
|
151 |
|
/* Call the present layer, while pointing to the next layer down */ |
152 |
319198 |
vdc->nxt = VTAILQ_NEXT(vdpe, list); |
153 |
319198 |
vdpe->calls++; |
154 |
319198 |
vdc->bytes_done = len; |
155 |
319198 |
retval = vdpe->vdp->bytes(vdc, act, &vdpe->priv, ptr, len); |
156 |
319198 |
vdpe->bytes_in += vdc->bytes_done; |
157 |
319198 |
if (retval && (vdc->retval == 0 || retval < vdc->retval)) |
158 |
2183 |
vdc->retval = retval; /* Latch error value */ |
159 |
319198 |
vdc->nxt = vdpe; |
160 |
319198 |
return (vdc->retval); |
161 |
320156 |
} |
162 |
|
|
163 |
|
int |
164 |
201681 |
VDP_Push(VRT_CTX, struct vdp_ctx *vdc, struct ws *ws, const struct vdp *vdp, |
165 |
|
void *priv) |
166 |
|
{ |
167 |
|
struct vdp_entry *vdpe; |
168 |
|
|
169 |
201681 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
170 |
201681 |
CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC); |
171 |
201681 |
CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC); |
172 |
201681 |
CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC); |
173 |
201681 |
AN(vdc->clen); |
174 |
201681 |
assert(*vdc->clen >= -1); |
175 |
201681 |
AN(ws); |
176 |
201681 |
AN(vdp); |
177 |
201681 |
AN(vdp->name); |
178 |
|
|
179 |
201681 |
if (vdc->retval) |
180 |
0 |
return (vdc->retval); |
181 |
|
|
182 |
201681 |
if (DO_DEBUG(DBG_PROCESSORS)) |
183 |
0 |
VSLb(vdc->vsl, SLT_Debug, "VDP_push(%s)", vdp->name); |
184 |
|
|
185 |
201681 |
vdpe = WS_Alloc(ws, sizeof *vdpe); |
186 |
201681 |
if (vdpe == NULL) { |
187 |
5120 |
AZ(vdc->retval); |
188 |
5120 |
vdc->retval = -1; |
189 |
5120 |
return (vdc->retval); |
190 |
|
} |
191 |
196561 |
INIT_OBJ(vdpe, VDP_ENTRY_MAGIC); |
192 |
196561 |
vdpe->vdp = vdp; |
193 |
196561 |
vdpe->priv = priv; |
194 |
196561 |
VTAILQ_INSERT_TAIL(&vdc->vdp, vdpe, list); |
195 |
196561 |
vdc->nxt = VTAILQ_FIRST(&vdc->vdp); |
196 |
|
|
197 |
196561 |
AZ(vdc->retval); |
198 |
196561 |
if (vdpe->vdp->init != NULL) |
199 |
25479 |
vdc->retval = vdpe->vdp->init(ctx, vdc, &vdpe->priv); |
200 |
196561 |
vdc->oc = NULL; |
201 |
|
|
202 |
196561 |
if (vdc->retval > 0) { |
203 |
880 |
VTAILQ_REMOVE(&vdc->vdp, vdpe, list); |
204 |
880 |
vdc->nxt = VTAILQ_FIRST(&vdc->vdp); |
205 |
880 |
vdc->retval = 0; |
206 |
880 |
} |
207 |
195681 |
else if (vdc->retval == 0) |
208 |
195361 |
AN(vdp->bytes); |
209 |
196561 |
return (vdc->retval); |
210 |
201681 |
} |
211 |
|
|
212 |
|
uint64_t |
213 |
223295 |
VDP_Close(struct vdp_ctx *vdc, struct objcore *oc, struct boc *boc) |
214 |
|
{ |
215 |
|
struct vdp_entry *vdpe; |
216 |
223295 |
uint64_t rv = 0; |
217 |
|
|
218 |
223295 |
CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC); |
219 |
223295 |
CHECK_OBJ_NOTNULL(vdc->wrk, WORKER_MAGIC); |
220 |
223295 |
CHECK_OBJ_ORNULL(oc, OBJCORE_MAGIC); |
221 |
223295 |
CHECK_OBJ_ORNULL(boc, BOC_MAGIC); |
222 |
|
|
223 |
418928 |
while (!VTAILQ_EMPTY(&vdc->vdp)) { |
224 |
195633 |
vdpe = VTAILQ_FIRST(&vdc->vdp); |
225 |
195633 |
rv = vdpe->bytes_in; |
226 |
391266 |
VSLb(vdc->vsl, SLT_VdpAcct, "%s %ju %ju", vdpe->vdp->name, |
227 |
195633 |
(uintmax_t)vdpe->calls, (uintmax_t)rv); |
228 |
195633 |
if (vdc->retval >= 0) |
229 |
191694 |
AN(vdpe); |
230 |
195633 |
if (vdpe != NULL) { |
231 |
195632 |
CHECK_OBJ(vdpe, VDP_ENTRY_MAGIC); |
232 |
195632 |
if (vdpe->vdp->fini != NULL) |
233 |
36758 |
AZ(vdpe->vdp->fini(vdc, &vdpe->priv)); |
234 |
195632 |
AZ(vdpe->priv); |
235 |
195632 |
VTAILQ_REMOVE(&vdc->vdp, vdpe, list); |
236 |
195632 |
} |
237 |
195633 |
vdc->nxt = VTAILQ_FIRST(&vdc->vdp); |
238 |
|
#ifdef VDP_PEDANTIC_ARMED |
239 |
|
// enable when we are confident to get VDP_END right |
240 |
|
if (vdc->nxt == NULL && vdc->retval >= 0) |
241 |
|
assert(vdpe->end == VDP_END); |
242 |
|
#endif |
243 |
|
} |
244 |
223293 |
if (oc != NULL) |
245 |
139735 |
HSH_Cancel(vdc->wrk, oc, boc); |
246 |
223293 |
return (rv); |
247 |
|
} |
248 |
|
|
249 |
|
/*--------------------------------------------------------------------*/ |
250 |
|
|
251 |
|
int v_matchproto_(objiterate_f) |
252 |
162259 |
VDP_ObjIterate(void *priv, unsigned flush, const void *ptr, ssize_t len) |
253 |
|
{ |
254 |
|
enum vdp_action act; |
255 |
|
|
256 |
162259 |
if (flush == 0) |
257 |
6290 |
act = VDP_NULL; |
258 |
155969 |
else if ((flush & OBJ_ITER_END) != 0) |
259 |
93556 |
act = VDP_END; |
260 |
|
else |
261 |
62413 |
act = VDP_FLUSH; |
262 |
|
|
263 |
162259 |
return (VDP_bytes(priv, act, ptr, len)); |
264 |
|
} |
265 |
|
|
266 |
|
|
267 |
|
int |
268 |
91079 |
VDP_DeliverObj(struct vdp_ctx *vdc, struct objcore *oc) |
269 |
|
{ |
270 |
|
int r, final; |
271 |
|
|
272 |
91079 |
CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC); |
273 |
91079 |
CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); |
274 |
91079 |
CHECK_OBJ_NOTNULL(vdc->wrk, WORKER_MAGIC); |
275 |
91079 |
AN(vdc->vsl); |
276 |
91079 |
AZ(vdc->oc); |
277 |
91079 |
vdc->hp = NULL; |
278 |
91079 |
vdc->clen = NULL; |
279 |
91079 |
final = oc->flags & OC_F_TRANSIENT ? 1 : 0; |
280 |
91079 |
r = ObjIterate(vdc->wrk, oc, vdc, VDP_ObjIterate, final); |
281 |
91079 |
if (r < 0) |
282 |
1541 |
return (r); |
283 |
89538 |
return (0); |
284 |
91079 |
} |