varnish-cache/bin/varnishd/cache/cache_fetch.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
#include "storage/storage.h"
37
#include "vcl.h"
38
#include "vtim.h"
39
#include "vcc_interface.h"
40
41
#define FETCH_STEPS \
42
        FETCH_STEP(mkbereq,           MKBEREQ) \
43
        FETCH_STEP(retry,             RETRY) \
44
        FETCH_STEP(startfetch,        STARTFETCH) \
45
        FETCH_STEP(condfetch,         CONDFETCH) \
46
        FETCH_STEP(fetch,             FETCH) \
47
        FETCH_STEP(fetchbody,         FETCHBODY) \
48
        FETCH_STEP(fetchend,          FETCHEND) \
49
        FETCH_STEP(error,             ERROR) \
50
        FETCH_STEP(fail,              FAIL) \
51
        FETCH_STEP(done,              DONE)
52
53
typedef const struct fetch_step *vbf_state_f(struct worker *, struct busyobj *);
54
55
struct fetch_step {
56
        const char      *name;
57
        vbf_state_f     *func;
58 3706
};
59 3706
60 3706
#define FETCH_STEP(l, U) \
61 3706
    static vbf_state_f vbf_stp_##l; \
62
    static const struct fetch_step F_STP_##U[1] = {{ .name = "Fetch Step " #l, .func = vbf_stp_##l, }};
63
FETCH_STEPS
64
#undef FETCH_STEP
65
66
static hdr_t const H_X_Varnish = HDR("X-Varnish");
67
68
/*--------------------------------------------------------------------
69
 * Allocate an object, with fall-back to Transient.
70
 * XXX: This somewhat overlaps the stuff in stevedore.c
71
 * XXX: Should this be merged over there ?
72
 */
73
74
static int
75 4500
vbf_allocobj(struct busyobj *bo, unsigned l)
76
{
77
        struct objcore *oc;
78
        const struct stevedore *stv;
79
        vtim_dur lifetime;
80
81 4500
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
82 4500
        oc = bo->fetch_objcore;
83 4500
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
84
85 4500
        lifetime = oc->ttl + oc->grace + oc->keep;
86
87 4500
        if (bo->uncacheable) {
88 1774
                stv = stv_transient;
89 1774
                bo->wrk->stats->beresp_uncacheable++;
90 1774
        }
91 2726
        else if (lifetime < cache_param->shortlived) {
92 254
                stv = stv_transient;
93 254
                bo->wrk->stats->beresp_shortlived++;
94 254
        }
95
        else
96 2472
                stv = bo->storage;
97
98 4500
        bo->storage = NULL;
99
100 4500
        if (stv == NULL)
101 2
                return (0);
102
103 4498
        if (STV_NewObject(bo->wrk, oc, stv, l))
104 4484
                return (1);
105
106 14
        if (stv == stv_transient)
107 8
                return (0);
108
109
        /*
110
         * Try to salvage the transaction by allocating a shortlived object
111
         * on Transient storage.
112
         */
113
114 6
        oc->ttl = vmin_t(float, oc->ttl, cache_param->shortlived);
115 6
        oc->grace = 0.0;
116 6
        oc->keep = 0.0;
117 6
        return (STV_NewObject(bo->wrk, oc, stv_transient, l));
118 4500
}
119
120
static void
121 4050
vbf_cleanup(struct busyobj *bo)
122
{
123
        struct vfp_ctx *vfc;
124
125 4050
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
126 4050
        vfc = bo->vfc;
127 4050
        CHECK_OBJ_NOTNULL(vfc, VFP_CTX_MAGIC);
128
129 4050
        bo->acct.beresp_bodybytes += VFP_Close(vfc);
130 4050
        bo->vfp_filter_list = NULL;
131
132 4050
        if (bo->director_state != DIR_S_NULL)
133 4034
                VDI_Finish(bo);
134 4050
}
135
136
void
137 18
Bereq_Rollback(VRT_CTX)
138
{
139
        struct busyobj *bo;
140
141 18
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
142 18
        bo = ctx->bo;
143 18
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
144
145 18
        if (bo->htc != NULL) {
146 16
                assert(bo->htc->body_status != BS_TAKEN);
147 16
                if (bo->htc->body_status != BS_NONE)
148 2
                        bo->htc->doclose = SC_RESP_CLOSE;
149 16
        }
150
151 18
        vbf_cleanup(bo);
152 18
        VCL_TaskLeave(ctx, bo->privs);
153 18
        VCL_TaskEnter(bo->privs);
154 18
        HTTP_Clone(bo->bereq, bo->bereq0);
155 18
        bo->vfp_filter_list = NULL;
156 18
        bo->err_reason = NULL;
157 18
        AN(bo->ws_bo);
158 18
        WS_Rollback(bo->ws, bo->ws_bo);
159 18
}
160
161
/*--------------------------------------------------------------------
162
 * Turn the beresp into a obj
163
 */
164
165
static int
166 4500
vbf_beresp2obj(struct busyobj *bo)
167
{
168
        unsigned l, l2;
169
        const char *b;
170
        uint8_t *bp;
171 4500
        struct vsb *vary = NULL;
172 4500
        int varyl = 0;
173
        struct objcore *oc;
174
175 4500
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
176 4500
        oc = bo->fetch_objcore;
177 4500
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
178
179 4500
        l = 0;
180
181
        /* Create Vary instructions */
182 4500
        if (!(oc->flags & OC_F_PRIVATE)) {
183 2930
                varyl = VRY_Create(bo, &vary);
184 2930
                if (varyl > 0) {
185 430
                        AN(vary);
186 430
                        assert(varyl == VSB_len(vary));
187 430
                        l += PRNDUP((intptr_t)varyl);
188 2930
                } else if (varyl < 0) {
189
                        /*
190
                         * Vary parse error
191
                         * Complain about it, and make this a pass.
192
                         */
193 10
                        VSLb(bo->vsl, SLT_Error,
194
                            "Illegal 'Vary' header from backend, "
195
                            "making this a pass.");
196 10
                        bo->uncacheable = 1;
197 10
                        AZ(vary);
198 10
                } else
199
                        /* No vary */
200 2490
                        AZ(vary);
201 2930
        }
202
203 9000
        l2 = http_EstimateWS(bo->beresp,
204 4500
            bo->uncacheable ? HTTPH_A_PASS : HTTPH_A_INS);
205 4500
        l += l2;
206
207 4500
        if (bo->uncacheable)
208 1774
                oc->flags |= OC_F_HFM;
209
210 4500
        if (!vbf_allocobj(bo, l)) {
211 12
                if (vary != NULL)
212 0
                        VSB_destroy(&vary);
213 12
                AZ(vary);
214 12
                return (VFP_Error(bo->vfc, "Could not get storage"));
215
        }
216
217 4488
        if (vary != NULL) {
218 430
                AN(ObjSetAttr(bo->wrk, oc, OA_VARY, varyl, VSB_data(vary)));
219 430
                VSB_destroy(&vary);
220 430
        }
221
222 4488
        AZ(ObjSetXID(bo->wrk, oc, bo->vsl->wid));
223
224
        /* for HTTP_Encode() VSLH call */
225 4488
        bo->beresp->logtag = SLT_ObjMethod;
226
227
        /* Filter into object */
228 4488
        bp = ObjSetAttr(bo->wrk, oc, OA_HEADERS, l2, NULL);
229 4488
        AN(bp);
230 8976
        HTTP_Encode(bo->beresp, bp, l2,
231 4488
            bo->uncacheable ? HTTPH_A_PASS : HTTPH_A_INS);
232
233 4488
        if (http_GetHdr(bo->beresp, H_Last_Modified, &b))
234 86
                AZ(ObjSetDouble(bo->wrk, oc, OA_LASTMODIFIED, VTIM_parse(b)));
235
        else
236 4402
                AZ(ObjSetDouble(bo->wrk, oc, OA_LASTMODIFIED,
237
                    floor(oc->t_origin)));
238
239 4488
        return (0);
240 4500
}
241
242
/*--------------------------------------------------------------------
243
 * Copy req->bereq and release req if no body
244
 */
245
246
static const struct fetch_step * v_matchproto_(vbf_state_f)
247 4546
vbf_stp_mkbereq(struct worker *wrk, struct busyobj *bo)
248
{
249
        const char *q;
250
        struct objcore *oc;
251
252 4546
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
253 4546
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
254 4546
        CHECK_OBJ_NOTNULL(bo->req, REQ_MAGIC);
255 4546
        oc = bo->fetch_objcore;
256 4546
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
257
258 4546
        assert(oc->boc->state == BOS_INVALID);
259 4546
        AZ(bo->storage);
260
261 4546
        HTTP_Setup(bo->bereq0, bo->ws, bo->vsl, SLT_BereqMethod);
262 9092
        http_FilterReq(bo->bereq0, bo->req->http,
263 4546
            bo->uncacheable ? HTTPH_R_PASS : HTTPH_R_FETCH);
264
265 4546
        if (bo->uncacheable)
266 1568
                AZ(bo->stale_oc);
267
        else {
268 2978
                http_ForceField(bo->bereq0, HTTP_HDR_METHOD, "GET");
269 2978
                if (cache_param->http_gzip_support)
270 2968
                        http_ForceHeader(bo->bereq0, H_Accept_Encoding, "gzip");
271
        }
272 4546
        http_ForceField(bo->bereq0, HTTP_HDR_PROTO, "HTTP/1.1");
273
274 4618
        if (bo->stale_oc != NULL &&
275 308
            ObjCheckFlag(bo->wrk, bo->stale_oc, OF_IMSCAND) &&
276 80
            (bo->stale_oc->boc != NULL || ObjGetLen(wrk, bo->stale_oc) != 0)) {
277 76
                AZ(bo->stale_oc->flags & (OC_F_HFM|OC_F_PRIVATE));
278 76
                q = RFC2616_Strong_LM(NULL, wrk, bo->stale_oc);
279 76
                if (q != NULL)
280 52
                        http_PrintfHeader(bo->bereq0,
281 26
                            "If-Modified-Since: %s", q);
282 76
                q = HTTP_GetHdrPack(bo->wrk, bo->stale_oc, H_ETag);
283 76
                if (q != NULL)
284 104
                        http_PrintfHeader(bo->bereq0,
285 52
                            "If-None-Match: %s", q);
286 76
        }
287
288 4546
        http_CopyHome(bo->bereq0);
289 4546
        HTTP_Setup(bo->bereq, bo->ws, bo->vsl, SLT_BereqMethod);
290 4546
        bo->ws_bo = WS_Snapshot(bo->ws);
291 4546
        HTTP_Clone(bo->bereq, bo->bereq0);
292
293 4546
        if (bo->req->req_body_status->avail == 0) {
294 4364
                VBO_SetState(bo->wrk, bo, BOS_REQ_DONE);
295 4546
        } else if (bo->req->req_body_status == BS_CACHED) {
296 46
                AN(bo->req->body_oc);
297 46
                bo->bereq_body = bo->req->body_oc;
298 46
                HSH_Ref(bo->bereq_body);
299 46
                VBO_SetState(bo->wrk, bo, BOS_REQ_DONE);
300 46
        }
301 4546
        return (F_STP_STARTFETCH);
302
}
303
304
/*--------------------------------------------------------------------
305
 * Start a new VSL transaction and try again
306
 * Prepare the busyobj and fetch processors
307
 */
308
309
static const struct fetch_step * v_matchproto_(vbf_state_f)
310 72
vbf_stp_retry(struct worker *wrk, struct busyobj *bo)
311
{
312 72
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
313 72
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
314
315 72
        assert(bo->fetch_objcore->boc->state <= BOS_REQ_DONE);
316
317 72
        if (bo->no_retry != NULL) {
318 8
                VSLb(bo->vsl, SLT_Error,
319 4
                    "Retry not possible, %s", bo->no_retry);
320 4
                return (F_STP_FAIL);
321
        }
322
323 68
        VSLb_ts_busyobj(bo, "Retry", W_TIM_real(wrk));
324
325
        /* VDI_Finish (via vbf_cleanup) must have been called before */
326 68
        assert(bo->director_state == DIR_S_NULL);
327
328
        /* reset other bo attributes - See VBO_GetBusyObj */
329 68
        bo->storage = NULL;
330 68
        bo->do_esi = 0;
331 68
        bo->do_stream = 1;
332 68
        bo->was_304 = 0;
333 68
        bo->err_code = 0;
334 68
        bo->err_reason = NULL;
335 68
        bo->connect_timeout = NAN;
336 68
        bo->first_byte_timeout = NAN;
337 68
        bo->between_bytes_timeout = NAN;
338 68
        if (bo->htc != NULL)
339 0
                bo->htc->doclose = SC_NULL;
340
341
        // XXX: BereqEnd + BereqAcct ?
342 68
        VSL_ChgId(bo->vsl, "bereq", "retry", VXID_Get(wrk, VSL_BACKENDMARKER));
343 68
        VSLb_ts_busyobj(bo, "Start", bo->t_prev);
344 68
        http_VSL_log(bo->bereq);
345
346 68
        return (F_STP_STARTFETCH);
347 72
}
348
349
/*--------------------------------------------------------------------
350
 * 304 setup logic
351
 */
352
353
static void
354 60
vbf_304_logic(struct busyobj *bo)
355
{
356
357 60
        AZ(bo->stale_oc->flags & (OC_F_HFM|OC_F_PRIVATE));
358 60
        if (ObjCheckFlag(bo->wrk, bo->stale_oc, OF_CHGCE)) {
359
                /*
360
                 * If a VFP changed C-E in the stored
361
                 * object, then don't overwrite C-E from
362
                 * the IMS fetch, and we must weaken any
363
                 * new ETag we get.
364
                 */
365 4
                RFC2616_Weaken_Etag(bo->beresp);
366 4
        }
367 60
        http_Unset(bo->beresp, H_Content_Encoding);
368 60
        http_Unset(bo->beresp, H_Content_Length);
369 60
        HTTP_Merge(bo->wrk, bo->stale_oc, bo->beresp);
370 60
}
371
372
/*--------------------------------------------------------------------
373
 * Setup bereq from bereq0, run vcl_backend_fetch
374
 */
375
376
static const struct fetch_step * v_matchproto_(vbf_state_f)
377 4614
vbf_stp_startfetch(struct worker *wrk, struct busyobj *bo)
378
{
379
        int i;
380
        const char *q;
381
        vtim_real now;
382 4614
        unsigned handling, skip_vbr = 0;
383
        struct objcore *oc;
384
385 4614
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
386 4614
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
387 4614
        oc = bo->fetch_objcore;
388 4614
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
389
390 4614
        AZ(bo->storage);
391 4614
        bo->storage = bo->uncacheable ? stv_transient : STV_next();
392
393 4614
        if (bo->retries > 0)
394 68
                http_Unset(bo->bereq, H_X_Varnish);
395
396 4614
        http_PrintfHeader(bo->bereq, "X-Varnish: %ju", VXID(bo->vsl->wid));
397
398 4614
        if (bo->bereq_body == NULL && bo->req == NULL)
399 4432
                http_Unset(bo->bereq, H_Content_Length);
400
401 4614
        VCL_backend_fetch_method(bo->vcl, wrk, NULL, bo, NULL);
402
403 4614
        if (wrk->vpi->handling == VCL_RET_ABANDON ||
404 4608
            wrk->vpi->handling == VCL_RET_FAIL)
405 13
                return (F_STP_FAIL);
406
407 4601
        assert (wrk->vpi->handling == VCL_RET_FETCH ||
408
            wrk->vpi->handling == VCL_RET_ERROR);
409
410 4601
        HTTP_Setup(bo->beresp, bo->ws, bo->vsl, SLT_BerespMethod);
411
412 4601
        assert(oc->boc->state <= BOS_REQ_DONE);
413
414 4601
        AZ(bo->htc);
415
416 4601
        VFP_Setup(bo->vfc, wrk);
417 4601
        bo->vfc->oc = oc;
418 4601
        bo->vfc->resp = bo->beresp;
419 4601
        bo->vfc->req = bo->bereq;
420
421 4601
        if (wrk->vpi->handling == VCL_RET_ERROR)
422 20
                return (F_STP_ERROR);
423
424 4581
        VSLb_ts_busyobj(bo, "Fetch", W_TIM_real(wrk));
425 4581
        i = VDI_GetHdr(bo);
426 4581
        if (bo->htc != NULL)
427 4048
                CHECK_OBJ_NOTNULL(bo->htc->doclose, STREAM_CLOSE_MAGIC);
428
429 4581
        bo->t_resp = now = W_TIM_real(wrk);
430 4581
        VSLb_ts_busyobj(bo, "Beresp", now);
431
432 4581
        if (i) {
433 530
                assert(bo->director_state == DIR_S_NULL);
434 530
                return (F_STP_ERROR);
435
        }
436
437 4051
        if (bo->htc != NULL && bo->htc->body_status == BS_ERROR) {
438 12
                bo->htc->doclose = SC_RX_BODY;
439 12
                vbf_cleanup(bo);
440 12
                VSLb(bo->vsl, SLT_Error, "Body cannot be fetched");
441 12
                assert(bo->director_state == DIR_S_NULL);
442 12
                return (F_STP_ERROR);
443
        }
444
445 4039
        if (!http_GetHdr(bo->beresp, H_Date, NULL)) {
446
                /*
447
                 * RFC 2616 14.18 Date: The Date general-header field
448
                 * represents the date and time at which the message was
449
                 * originated, having the same semantics as orig-date in
450
                 * RFC 822. ... A received message that does not have a
451
                 * Date header field MUST be assigned one by the recipient
452
                 * if the message will be cached by that recipient or
453
                 * gatewayed via a protocol which requires a Date.
454
                 *
455
                 * If we didn't get a Date header, we assign one here.
456
                 */
457 166
                http_TimeHeader(bo->beresp, "Date: ", now);
458 166
        }
459
460
        /*
461
         * These two headers can be spread over multiple actual headers
462
         * and we rely on their content outside of VCL, so collect them
463
         * into one line here.
464
         */
465 4039
        http_CollectHdr(bo->beresp, H_Cache_Control);
466 4039
        http_CollectHdr(bo->beresp, H_Vary);
467
468
        /* What does RFC2616 think about TTL ? */
469 8078
        RFC2616_Ttl(bo, now,
470 4039
            &oc->t_origin,
471 4039
            &oc->ttl,
472 4039
            &oc->grace,
473 4039
            &oc->keep);
474
475 4039
        AZ(bo->do_esi);
476 4039
        AZ(bo->was_304);
477
478 4039
        if (http_IsStatus(bo->beresp, 304) && !bo->uncacheable) {
479 76
                if (bo->stale_oc == NULL){
480 0
                        VSLb(bo->vsl, SLT_Error,
481
                            "304 response but not conditional fetch");
482 0
                        bo->htc->doclose = SC_RX_BAD;
483 0
                        vbf_cleanup(bo);
484 0
                        return (F_STP_ERROR);
485
                }
486 76
                bo->was_304 = 1;
487 76
                VCL_backend_refresh_method(bo->vcl, wrk, NULL, bo, NULL);
488 76
                switch (wrk->vpi->handling) {
489
                case VCL_RET_MERGE:
490 60
                        vbf_304_logic(bo);
491 60
                        break;
492
                case VCL_RET_BERESP:
493 4
                        http_SetStatus(bo->beresp, 200, NULL);
494 4
                        http_Unset(bo->beresp, H_Content_Length);
495 4
                        http_Unset(bo->beresp, H_Content_Encoding);
496 8
                        q = HTTP_GetHdrPack(wrk, bo->stale_oc,
497 4
                            H_Content_Length);
498 4
                        if (q != NULL) {
499 4
                                http_ForceHeader(bo->beresp,
500 2
                                    H_Content_Length, q);
501 2
                        }
502 8
                        q = HTTP_GetHdrPack(wrk, bo->stale_oc,
503 4
                            H_Content_Encoding);
504 4
                        if (q != NULL) {
505 0
                                http_ForceHeader(bo->beresp,
506 0
                                    H_Content_Encoding, q);
507 0
                        }
508 8
                        q = HTTP_GetHdrPack(wrk, bo->stale_oc,
509 4
                            H_Last_Modified);
510 4
                        if (q != NULL) {
511 0
                                http_ForceHeader(bo->beresp,
512 0
                                    H_Last_Modified, q);
513 0
                        }
514 4
                        q = HTTP_GetHdrPack(wrk, bo->stale_oc, H_ETag);
515 4
                        if (q != NULL)
516 4
                                http_ForceHeader(bo->beresp, H_ETag, q);
517 4
                        break;
518
                case VCL_RET_OBJ_STALE:
519 4
                        if (HTTP_Decode(bo->beresp, ObjGetAttr(bo->wrk,
520 2
                                bo->stale_oc, OA_HEADERS, NULL))) {
521 0
                                bo->htc->doclose = SC_RX_OVERFLOW;
522 0
                                vbf_cleanup(bo);
523 0
                                return (F_STP_ERROR);
524
                        }
525 2
                        break;
526
                case VCL_RET_RETRY:
527
                case VCL_RET_ERROR:
528
                case VCL_RET_ABANDON:
529
                case VCL_RET_FAIL:
530 10
                        skip_vbr = 1;
531 10
                        break;
532
                default:
533 0
                        WRONG("Illegal return from vcl_backend_refresh{}");
534 0
                }
535 76
        }
536
537 4039
        if (bo->htc != NULL && bo->htc->doclose == SC_NULL &&
538 3853
            http_GetHdrField(bo->bereq, H_Connection, "close", NULL))
539 26
                bo->htc->doclose = SC_REQ_CLOSE;
540 4039
        if (!skip_vbr)
541 4025
                VCL_backend_response_method(bo->vcl, wrk, NULL, bo, NULL);
542
543 4033
        if (bo->htc != NULL && bo->htc->doclose == SC_NULL &&
544 3808
            http_GetHdrField(bo->beresp, H_Connection, "close", NULL))
545 2
                bo->htc->doclose = SC_RESP_CLOSE;
546
547 4033
        if (VRG_CheckBo(bo) < 0) {
548 14
                if (bo->director_state != DIR_S_NULL)
549 12
                        VDI_Finish(bo);
550 14
                return (F_STP_ERROR);
551
        }
552
553 8029
        if (wrk->vpi->handling == VCL_RET_ABANDON ||
554 4014
            wrk->vpi->handling == VCL_RET_FAIL ||
555 4010
            wrk->vpi->handling == VCL_RET_ERROR) {
556
                /* do not count deliberately ending the backend connection as
557
                 * fetch failure
558
                 */
559 28
                handling = wrk->vpi->handling;
560 28
                if (bo->htc)
561 28
                        bo->htc->doclose = SC_RESP_CLOSE;
562 28
                vbf_cleanup(bo);
563 28
                wrk->vpi->handling = handling;
564
565 28
                if (wrk->vpi->handling == VCL_RET_ERROR)
566 18
                        return (F_STP_ERROR);
567
                else
568 10
                        return (F_STP_FAIL);
569
        }
570
571 3991
        if (wrk->vpi->handling == VCL_RET_RETRY) {
572 58
                if (bo->htc && bo->htc->body_status != BS_NONE)
573 14
                        bo->htc->doclose = SC_RESP_CLOSE;
574 58
                vbf_cleanup(bo);
575
576 58
                if (bo->retries++ < bo->max_retries)
577 54
                        return (F_STP_RETRY);
578
579 4
                VSLb(bo->vsl, SLT_VCL_Error,
580
                    "Too many retries, delivering 503");
581 4
                assert(bo->director_state == DIR_S_NULL);
582 4
                return (F_STP_ERROR);
583
        }
584
585 3933
        VSLb_ts_busyobj(bo, "Process", W_TIM_real(wrk));
586 3933
        assert(oc->boc->state <= BOS_REQ_DONE);
587 3933
        if (oc->boc->state != BOS_REQ_DONE)
588 80
                VBO_SetState(wrk, bo, BOS_REQ_DONE);
589
590 3933
        if (bo->do_esi)
591 620
                bo->do_stream = 0;
592 3933
        if (wrk->vpi->handling == VCL_RET_PASS) {
593 44
                oc->flags |= OC_F_HFP;
594 44
                bo->uncacheable = 1;
595 44
                wrk->vpi->handling = VCL_RET_DELIVER;
596 44
        }
597 3933
        if (!bo->uncacheable || !bo->do_stream)
598 2722
                oc->boc->transit_buffer = 0;
599 3933
        if (bo->uncacheable)
600 1487
                oc->flags |= OC_F_HFM;
601
602 3933
        assert(wrk->vpi->handling == VCL_RET_DELIVER);
603
604 3933
        return (bo->was_304 ? F_STP_CONDFETCH : F_STP_FETCH);
605 4608
}
606
607
/*--------------------------------------------------------------------
608
 */
609
610
static const struct fetch_step * v_matchproto_(vbf_state_f)
611 2204
vbf_stp_fetchbody(struct worker *wrk, struct busyobj *bo)
612
{
613
        ssize_t l;
614
        uint8_t *ptr;
615 2204
        enum vfp_status vfps = VFP_ERROR;
616
        ssize_t est;
617
        struct vfp_ctx *vfc;
618
        struct objcore *oc;
619
620 2204
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
621 2204
        vfc = bo->vfc;
622 2204
        CHECK_OBJ_NOTNULL(vfc, VFP_CTX_MAGIC);
623 2204
        oc = bo->fetch_objcore;
624 2204
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
625
626 2204
        AN(vfc->vfp_nxt);
627
628 2204
        est = bo->htc->content_length;
629 2204
        if (est < 0)
630 298
                est = 0;
631
632 2204
        do {
633 112101
                if (oc->flags & OC_F_CANCEL) {
634
                        /*
635
                         * A pass object and delivery was terminated
636
                         * We don't fail the fetch, in order for HitMiss
637
                         * objects to be created.
638
                         */
639 6
                        AN(oc->flags & OC_F_HFM);
640 6
                        VSLb(wrk->vsl, SLT_Debug,
641
                            "Fetch: Pass delivery abandoned");
642 6
                        bo->htc->doclose = SC_RX_BODY;
643 6
                        break;
644
                }
645 112095
                AZ(vfc->failed);
646 112095
                l = est;
647 112095
                assert(l >= 0);
648 112095
                if (VFP_GetStorage(vfc, &l, &ptr) != VFP_OK) {
649 10
                        bo->htc->doclose = SC_RX_BODY;
650 10
                        break;
651
                }
652
653 112085
                AZ(vfc->failed);
654 112085
                vfps = VFP_Suck(vfc, ptr, &l);
655 112085
                if (l >= 0 && vfps != VFP_ERROR) {
656 112019
                        VFP_Extend(vfc, l, vfps);
657 112019
                        if (est >= l)
658 5712
                                est -= l;
659
                        else
660 106307
                                est = 0;
661 112019
                }
662 112085
        } while (vfps == VFP_OK);
663
664 2202
        if (vfc->failed) {
665 74
                (void)VFP_Error(vfc, "Fetch pipeline failed to process");
666 74
                bo->htc->doclose = SC_RX_BODY;
667 74
                vbf_cleanup(bo);
668 74
                if (!bo->do_stream) {
669 42
                        assert(oc->boc->state < BOS_STREAM);
670
                        // XXX: doclose = ?
671 42
                        return (F_STP_ERROR);
672
                } else {
673 32
                        wrk->stats->fetch_failed++;
674 32
                        return (F_STP_FAIL);
675
                }
676
        }
677
678 2128
        return (F_STP_FETCHEND);
679 2202
}
680
681
static const struct fetch_step * v_matchproto_(vbf_state_f)
682 3870
vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)
683
{
684
        struct vrt_ctx ctx[1];
685
        struct objcore *oc;
686
687 3870
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
688 3870
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
689 3870
        oc = bo->fetch_objcore;
690 3870
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
691
692 3870
        assert(wrk->vpi->handling == VCL_RET_DELIVER);
693
694 3870
        if (bo->htc == NULL) {
695 4
                (void)VFP_Error(bo->vfc, "No backend connection (rollback?)");
696 4
                vbf_cleanup(bo);
697 4
                return (F_STP_ERROR);
698
        }
699
700
        /* No body -> done */
701 3866
        if (bo->htc->body_status == BS_NONE || bo->htc->content_length == 0) {
702 1508
                http_Unset(bo->beresp, H_Content_Encoding);
703 1508
                bo->do_gzip = bo->do_gunzip = 0;
704 1508
                bo->do_stream = 0;
705 1508
                bo->vfp_filter_list = "";
706 3866
        } else if (bo->vfp_filter_list == NULL) {
707 2346
                bo->vfp_filter_list = VBF_Get_Filter_List(bo);
708 2346
        }
709
710 3866
        if (bo->vfp_filter_list == NULL ||
711 3866
            VCL_StackVFP(bo->vfc, bo->vcl, bo->vfp_filter_list)) {
712 48
                (bo)->htc->doclose = SC_OVERLOAD;
713 48
                vbf_cleanup(bo);
714 48
                return (F_STP_ERROR);
715
        }
716
717 3818
        if (oc->flags & OC_F_PRIVATE)
718 1254
                AN(bo->uncacheable);
719
720 3818
        oc->boc->fetched_so_far = 0;
721
722 3818
        INIT_OBJ(ctx, VRT_CTX_MAGIC);
723 3818
        VCL_Bo2Ctx(ctx, bo);
724
725 3818
        if (VFP_Open(ctx, bo->vfc)) {
726 106
                (void)VFP_Error(bo->vfc, "Fetch pipeline failed to open");
727 106
                bo->htc->doclose = SC_RX_BODY;
728 106
                vbf_cleanup(bo);
729 106
                return (F_STP_ERROR);
730
        }
731
732 3712
        if (vbf_beresp2obj(bo)) {
733 6
                bo->htc->doclose = SC_RX_BODY;
734 6
                vbf_cleanup(bo);
735 6
                return (F_STP_ERROR);
736
        }
737
738
#define OBJ_FLAG(U, l, v)                                               \
739
        if (bo->vfc->obj_flags & OF_##U)                                \
740
                ObjSetFlag(bo->wrk, oc, OF_##U, 1);
741
#include "tbl/obj_attr.h"
742
743 3706
        if (!(oc->flags & OC_F_HFM) &&
744 2366
            http_IsStatus(bo->beresp, 200) && (
745 2330
              RFC2616_Strong_LM(bo->beresp, NULL, NULL) != NULL ||
746 2282
              http_GetHdr(bo->beresp, H_ETag, NULL)))
747 112
                ObjSetFlag(bo->wrk, oc, OF_IMSCAND, 1);
748
749 3706
        assert(oc->boc->refcount >= 1);
750
751 3706
        assert(oc->boc->state == BOS_REQ_DONE);
752
753 3706
        if (bo->do_stream)
754 1640
                VBO_SetState(wrk, bo, BOS_STREAM);
755
756
        VSLb(bo->vsl, SLT_Fetch_Body, "%u %s %s",
757
            bo->htc->body_status->nbr, bo->htc->body_status->name,
758
            bo->do_stream ? "stream" : "-");
759
760 3706
        if (bo->htc->body_status != BS_NONE) {
761 2202
                assert(bo->htc->body_status != BS_ERROR);
762 2202
                return (F_STP_FETCHBODY);
763
        }
764 1504
        AZ(bo->vfc->failed);
765
        return (F_STP_FETCHEND);
766
}
767
768
static const struct fetch_step * v_matchproto_(vbf_state_f)
769 3686
vbf_stp_fetchend(struct worker *wrk, struct busyobj *bo)
770
{
771
772
        struct objcore *oc;
773
774 3686
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
775 3686
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
776 3686
        oc = bo->fetch_objcore;
777 3686
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
778
779 3686
        AZ(bo->vfc->failed);
780
781
        /* Recycle the backend connection before setting BOS_FINISHED to
782
           give predictable backend reuse behavior for varnishtest */
783 3686
        vbf_cleanup(bo);
784
785 3686
        AZ(ObjSetU64(wrk, oc, OA_LEN, oc->boc->fetched_so_far));
786
787 3686
        if (bo->do_stream)
788 1660
                assert(oc->boc->state == BOS_STREAM);
789
        else
790 2026
                assert(oc->boc->state == BOS_REQ_DONE);
791
792 3686
        VBO_SetState(wrk, bo, BOS_FINISHED);
793 3686
        VSLb_ts_busyobj(bo, "BerespBody", W_TIM_real(wrk));
794 3686
        if (bo->stale_oc != NULL) {
795 304
                VSL(SLT_ExpKill, NO_VXID, "VBF_Superseded x=%ju n=%ju",
796 152
                    VXID(ObjGetXID(wrk, bo->stale_oc)),
797 152
                    VXID(ObjGetXID(wrk, bo->fetch_objcore)));
798 152
                HSH_Replace(bo->stale_oc, bo->fetch_objcore);
799 152
        }
800 3686
        return (F_STP_DONE);
801
}
802
803
/*--------------------------------------------------------------------
804
 */
805
806
struct vbf_objiter_priv {
807
        unsigned                magic;
808
#define VBF_OBITER_PRIV_MAGIC   0x3c272a17
809
        struct busyobj          *bo;
810
        // not yet allocated
811
        ssize_t         l;
812
        // current allocation
813
        uint8_t         *p;
814
        ssize_t         pl;
815
};
816
817
static int v_matchproto_(objiterate_f)
818 64
vbf_objiterate(void *priv, unsigned flush, const void *ptr, ssize_t len)
819
{
820
        struct vbf_objiter_priv *vop;
821
        ssize_t l;
822 64
        const uint8_t *ps = ptr;
823
824 64
        CAST_OBJ_NOTNULL(vop, priv, VBF_OBITER_PRIV_MAGIC);
825 64
        CHECK_OBJ_NOTNULL(vop->bo, BUSYOBJ_MAGIC);
826
827 64
        flush &= OBJ_ITER_END;
828
829 126
        while (len > 0) {
830 64
                if (vop->pl == 0) {
831 62
                        vop->p = NULL;
832 62
                        AN(vop->l);
833 62
                        vop->pl = vop->l;
834 124
                        if (VFP_GetStorage(vop->bo->vfc, &vop->pl, &vop->p)
835 62
                            != VFP_OK)
836 2
                                return (1);
837 60
                        if (vop->pl < vop->l)
838 4
                                vop->l -= vop->pl;
839
                        else
840 56
                                vop->l = 0;
841 60
                }
842 62
                AN(vop->pl);
843 62
                AN(vop->p);
844
845 62
                l = vmin(vop->pl, len);
846 62
                memcpy(vop->p, ps, l);
847 118
                VFP_Extend(vop->bo->vfc, l,
848 62
                           flush && l == len ? VFP_END : VFP_OK);
849 62
                ps += l;
850 62
                vop->p += l;
851 62
                len -= l;
852 62
                vop->pl -= l;
853
        }
854 62
        if (flush && vop->bo->vfc->failed == 0)
855 56
                AZ(vop->l);
856 62
        return (0);
857 64
}
858
859
static const struct fetch_step * v_matchproto_(vbf_state_f)
860 64
vbf_stp_condfetch(struct worker *wrk, struct busyobj *bo)
861
{
862
        struct boc *stale_boc;
863
        enum boc_state_e stale_state;
864
        struct objcore *oc, *stale_oc;
865
        struct vbf_objiter_priv vop[1];
866
867 64
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
868 64
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
869 64
        oc = bo->fetch_objcore;
870 64
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
871 64
        stale_oc = bo->stale_oc;
872 64
        CHECK_OBJ_NOTNULL(stale_oc, OBJCORE_MAGIC);
873
874 64
        stale_boc = HSH_RefBoc(stale_oc);
875 64
        CHECK_OBJ_ORNULL(stale_boc, BOC_MAGIC);
876 64
        if (stale_boc) {
877
                /* Wait for the stale object to become fully fetched, so
878
                 * that we can catch fetch errors, before we unbusy the
879
                 * new object. This serves two purposes. First it helps
880
                 * with request coalescing, and stops long chains of
881
                 * IMS-updated short-TTL objects all streaming from a
882
                 * single slow body fetch. Second it makes sure that all
883
                 * the object attributes are complete when we copy them
884
                 * (this would be an issue for ie OA_GZIPBITS). */
885 8
                VSLb(bo->vsl, SLT_Notice,
886
                    "vsl: Conditional fetch wait for streaming object");
887
                /* XXX: We should have a VCL controlled timeout here */
888 8
                ObjWaitState(stale_oc, BOS_FINISHED);
889 8
                stale_state = stale_boc->state;
890 8
                HSH_DerefBoc(bo->wrk, stale_oc);
891 8
                stale_boc = NULL;
892 8
                if (stale_state != BOS_FINISHED) {
893 4
                        assert(stale_state == BOS_FAILED);
894 4
                        AN(stale_oc->flags & OC_F_FAILED);
895 4
                }
896 8
        }
897
898 64
        AZ(stale_boc);
899 64
        if (stale_oc->flags & OC_F_FAILED) {
900 4
                (void)VFP_Error(bo->vfc, "Template object failed");
901 4
                vbf_cleanup(bo);
902 4
                wrk->stats->fetch_failed++;
903 4
                return (F_STP_FAIL);
904
        }
905
906 60
        if (vbf_beresp2obj(bo)) {
907 2
                vbf_cleanup(bo);
908 2
                wrk->stats->fetch_failed++;
909 2
                return (F_STP_FAIL);
910
        }
911
912 58
        if (ObjHasAttr(bo->wrk, stale_oc, OA_ESIDATA))
913 2
                AZ(ObjCopyAttr(bo->wrk, oc, stale_oc, OA_ESIDATA));
914
915 58
        AZ(ObjCopyAttr(bo->wrk, oc, stale_oc, OA_FLAGS));
916 58
        if (oc->flags & OC_F_HFM)
917 4
                ObjSetFlag(bo->wrk, oc, OF_IMSCAND, 0);
918 58
        AZ(ObjCopyAttr(bo->wrk, oc, stale_oc, OA_GZIPBITS));
919
920 58
        if (bo->do_stream)
921 56
                VBO_SetState(wrk, bo, BOS_STREAM);
922
923 58
        INIT_OBJ(vop, VBF_OBITER_PRIV_MAGIC);
924 58
        vop->bo = bo;
925 58
        vop->l = ObjGetLen(bo->wrk, stale_oc);
926 58
        if (ObjIterate(wrk, stale_oc, vop, vbf_objiterate, 0))
927 2
                (void)VFP_Error(bo->vfc, "Template object failed");
928
929 58
        if (bo->vfc->failed) {
930 2
                vbf_cleanup(bo);
931 2
                wrk->stats->fetch_failed++;
932 2
                return (F_STP_FAIL);
933
        }
934 56
        return (F_STP_FETCHEND);
935 64
}
936
937
/*--------------------------------------------------------------------
938
 * Create synth object
939
 *
940
 * replaces a stale object unless
941
 * - abandoning the bereq or
942
 * - leaving vcl_backend_error with return (deliver)
943
 *
944
 * We do want the stale replacement to avoid an object pileup with short ttl and
945
 * long grace/keep, yet there could exist cases where a cache object is
946
 * deliberately created to momentarily override a stale object.
947
 *
948
 * If this case exists, we should add a vcl veto (e.g. beresp.replace_stale with
949
 * default true)
950
 */
951
952
static const struct fetch_step * v_matchproto_(vbf_state_f)
953 803
vbf_stp_error(struct worker *wrk, struct busyobj *bo)
954
{
955
        ssize_t l, ll, o;
956
        vtim_real now;
957
        uint8_t *ptr;
958
        struct vsb *synth_body;
959
        struct objcore *stale, *oc;
960
961 803
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
962 803
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
963 803
        oc = bo->fetch_objcore;
964 803
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
965 803
        CHECK_OBJ_NOTNULL(oc->boc, BOC_MAGIC);
966 803
        assert(oc->boc->state < BOS_STREAM);
967 803
        assert(bo->director_state == DIR_S_NULL);
968
969 803
        if (wrk->vpi->handling != VCL_RET_ERROR)
970 766
                wrk->stats->fetch_failed++;
971
972 803
        now = W_TIM_real(wrk);
973 803
        VSLb_ts_busyobj(bo, "Error", now);
974
975 803
        if (oc->stobj->stevedore != NULL) {
976
                // replacing an already fetched object with a "synth" one
977 42
                assert(oc->boc->state < BOS_STREAM);
978 42
                oc->boc->fetched_so_far = 0;
979 42
                ObjFreeObj(bo->wrk, oc);
980 42
        }
981
982 803
        if (bo->storage == NULL)
983 48
                bo->storage = STV_next();
984
985
        // XXX: reset all beresp flags ?
986
987 803
        HTTP_Setup(bo->beresp, bo->ws, bo->vsl, SLT_BerespMethod);
988 803
        if (bo->err_code > 0)
989 128
                http_PutResponse(bo->beresp, "HTTP/1.1", bo->err_code,
990 64
                    bo->err_reason);
991
        else
992 739
                http_PutResponse(bo->beresp, "HTTP/1.1", 503,
993
                    "Backend fetch failed");
994
995 803
        http_TimeHeader(bo->beresp, "Date: ", now);
996 803
        http_SetHeader(bo->beresp, "Server: Varnish");
997
998 803
        stale = bo->stale_oc;
999 803
        oc->t_origin = now;
1000 803
        oc->ttl = 0;
1001 803
        oc->grace = 0;
1002 803
        oc->keep = 0;
1003
1004 803
        synth_body = VSB_new_auto();
1005 803
        AN(synth_body);
1006
1007 803
        VCL_backend_error_method(bo->vcl, wrk, NULL, bo, synth_body);
1008
1009 803
        AZ(VSB_finish(synth_body));
1010
1011 803
        if (wrk->vpi->handling == VCL_RET_ABANDON || wrk->vpi->handling == VCL_RET_FAIL) {
1012 55
                VSB_destroy(&synth_body);
1013 55
                return (F_STP_FAIL);
1014
        }
1015
1016 748
        if (wrk->vpi->handling == VCL_RET_RETRY) {
1017 20
                VSB_destroy(&synth_body);
1018 20
                if (bo->retries++ < bo->max_retries)
1019 18
                        return (F_STP_RETRY);
1020 2
                VSLb(bo->vsl, SLT_VCL_Error, "Too many retries, failing");
1021 2
                return (F_STP_FAIL);
1022
        }
1023
1024 728
        assert(wrk->vpi->handling == VCL_RET_DELIVER);
1025
1026 728
        assert(bo->vfc->wrk == bo->wrk);
1027 728
        assert(bo->vfc->oc == oc);
1028 728
        assert(bo->vfc->resp == bo->beresp);
1029 728
        assert(bo->vfc->req == bo->bereq);
1030
1031 728
        if (vbf_beresp2obj(bo)) {
1032 4
                VSB_destroy(&synth_body);
1033 4
                return (F_STP_FAIL);
1034
        }
1035
1036 724
        oc->boc->transit_buffer = 0;
1037
1038 724
        ll = VSB_len(synth_body);
1039 724
        o = 0;
1040 1350
        while (ll > 0) {
1041 628
                l = ll;
1042 628
                if (VFP_GetStorage(bo->vfc, &l, &ptr) != VFP_OK) {
1043 2
                        VSB_destroy(&synth_body);
1044 2
                        return (F_STP_FAIL);
1045
                }
1046 626
                l = vmin(l, ll);
1047 626
                memcpy(ptr, VSB_data(synth_body) + o, l);
1048 626
                VFP_Extend(bo->vfc, l, l == ll ? VFP_END : VFP_OK);
1049 626
                ll -= l;
1050 626
                o += l;
1051
        }
1052 722
        assert(o == VSB_len(synth_body));
1053 722
        AZ(ObjSetU64(wrk, oc, OA_LEN, o));
1054 722
        VSB_destroy(&synth_body);
1055 722
        if (stale != NULL && oc->ttl > 0)
1056 44
                HSH_Kill(stale);
1057 722
        VBO_SetState(wrk, bo, BOS_FINISHED);
1058 722
        return (F_STP_DONE);
1059 803
}
1060
1061
/*--------------------------------------------------------------------
1062
 */
1063
1064
static const struct fetch_step * v_matchproto_(vbf_state_f)
1065 136
vbf_stp_fail(struct worker *wrk, struct busyobj *bo)
1066
{
1067
        struct objcore *oc;
1068
1069 136
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1070 136
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
1071 136
        oc = bo->fetch_objcore;
1072 136
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1073
1074 136
        assert(oc->boc->state < BOS_FINISHED);
1075 136
        VBO_SetState(wrk, bo, BOS_FAILED);
1076 136
        HSH_Kill(oc);
1077 136
        return (F_STP_DONE);
1078
}
1079
1080
/*--------------------------------------------------------------------
1081
 */
1082
1083
static const struct fetch_step * v_matchproto_(vbf_state_f)
1084 0
vbf_stp_done(struct worker *wrk, struct busyobj *bo)
1085
{
1086
1087 0
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1088 0
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
1089 0
        WRONG("Just plain wrong");
1090 0
        NEEDLESS(return (F_STP_DONE));
1091
}
1092
1093
static void v_matchproto_(task_func_t)
1094 4546
vbf_fetch_thread(struct worker *wrk, void *priv)
1095
{
1096
        struct vrt_ctx ctx[1];
1097
        struct busyobj *bo;
1098
        struct objcore *oc;
1099
        const struct fetch_step *stp;
1100
1101 4546
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1102 4546
        CAST_OBJ_NOTNULL(bo, priv, BUSYOBJ_MAGIC);
1103 4546
        CHECK_OBJ_NOTNULL(bo->req, REQ_MAGIC);
1104 4546
        oc = bo->fetch_objcore;
1105 4546
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1106
1107 4546
        THR_SetBusyobj(bo);
1108 4546
        stp = F_STP_MKBEREQ;
1109 4546
        assert(isnan(bo->t_first));
1110 4546
        assert(isnan(bo->t_prev));
1111 4546
        VSLb_ts_busyobj(bo, "Start", W_TIM_real(wrk));
1112
1113 4546
        bo->wrk = wrk;
1114 4546
        wrk->vsl = bo->vsl;
1115
1116
#if 0
1117
        if (bo->stale_oc != NULL) {
1118
                CHECK_OBJ_NOTNULL(bo->stale_oc, OBJCORE_MAGIC);
1119
                /* We don't want the oc/stevedore ops in fetching thread */
1120
                if (!ObjCheckFlag(wrk, bo->stale_oc, OF_IMSCAND))
1121
                        (void)HSH_DerefObjCore(wrk, &bo->stale_oc, 0);
1122
        }
1123
#endif
1124
1125 4546
        VCL_TaskEnter(bo->privs);
1126 24539
        while (stp != F_STP_DONE) {
1127 19993
                CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
1128 19993
                assert(oc->boc->refcount >= 1);
1129 19993
                if (oc->boc->state < BOS_REQ_DONE)
1130 4726
                        AN(bo->req);
1131
                else
1132 15267
                        AZ(bo->req);
1133 19993
                AN(stp);
1134 19993
                AN(stp->name);
1135 19993
                AN(stp->func);
1136 19993
                stp = stp->func(wrk, bo);
1137
        }
1138
1139 4546
        assert(bo->director_state == DIR_S_NULL);
1140
1141 4546
        INIT_OBJ(ctx, VRT_CTX_MAGIC);
1142 4546
        VCL_Bo2Ctx(ctx, bo);
1143 4546
        VCL_TaskLeave(ctx, bo->privs);
1144 4546
        http_Teardown(bo->bereq);
1145 4546
        http_Teardown(bo->beresp);
1146
        // cannot make assumptions about the number of references here #3434
1147 4546
        if (bo->bereq_body != NULL)
1148 36
                (void)HSH_DerefObjCore(bo->wrk, &bo->bereq_body);
1149
1150 4546
        if (oc->boc->state == BOS_FINISHED) {
1151 4410
                AZ(oc->flags & OC_F_FAILED);
1152 8820
                VSLb(bo->vsl, SLT_Length, "%ju",
1153 4410
                    (uintmax_t)ObjGetLen(bo->wrk, oc));
1154 4410
        }
1155
        // AZ(oc->boc); // XXX
1156
1157 4546
        if (bo->stale_oc != NULL)
1158 308
                (void)HSH_DerefObjCore(wrk, &bo->stale_oc);
1159
1160 4546
        wrk->vsl = NULL;
1161 4546
        HSH_DerefBoc(wrk, oc);
1162 4546
        SES_Rel(bo->sp);
1163 4546
        VBO_ReleaseBusyObj(wrk, &bo);
1164 4546
        THR_SetBusyobj(NULL);
1165 4546
}
1166
1167
/*--------------------------------------------------------------------
1168
 */
1169
1170
void
1171 4548
VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc,
1172
    struct objcore *oldoc, enum vbf_fetch_mode_e mode)
1173
{
1174
        struct boc *boc;
1175
        struct busyobj *bo;
1176
        enum task_prio prio;
1177
        const char *how;
1178
1179 4548
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1180 4548
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1181 4548
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1182 4548
        CHECK_OBJ_ORNULL(oldoc, OBJCORE_MAGIC);
1183
1184 4548
        bo = VBO_GetBusyObj(wrk, req);
1185 4548
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
1186 4548
        AN(bo->vcl);
1187
1188 4548
        boc = HSH_RefBoc(oc);
1189 4548
        CHECK_OBJ_NOTNULL(boc, BOC_MAGIC);
1190 4548
        assert(boc->state < BOS_STREAM);
1191 4548
        boc->transit_buffer = cache_param->transit_buffer;
1192
1193 4548
        switch (mode) {
1194
        case VBF_PASS:
1195 1568
                prio = TASK_QUEUE_BO;
1196 1568
                how = "pass";
1197 1568
                bo->uncacheable = 1;
1198 1568
                break;
1199
        case VBF_NORMAL:
1200 2806
                prio = TASK_QUEUE_BO;
1201 2806
                how = "fetch";
1202 2806
                break;
1203
        case VBF_BACKGROUND:
1204 174
                prio = TASK_QUEUE_BG;
1205 174
                how = "bgfetch";
1206 174
                bo->is_bgfetch = 1;
1207 174
                break;
1208
        default:
1209 0
                WRONG("Wrong fetch mode");
1210 0
        }
1211
1212
#define REQ_BEREQ_FLAG(l, r, w, d) bo->l = req->l;
1213
#include "tbl/req_bereq_flags.h"
1214
1215
        VSLb(bo->vsl, SLT_Begin, "bereq %ju %s", VXID(req->vsl->wid), how);
1216
        VSLbs(bo->vsl, SLT_VCL_use, TOSTRAND(VCL_Name(bo->vcl)));
1217
        VSLb(req->vsl, SLT_Link, "bereq %ju %s", VXID(bo->vsl->wid), how);
1218
1219
        THR_SetBusyobj(bo);
1220
1221
        bo->sp = req->sp;
1222
        SES_Ref(bo->sp);
1223
1224
        oc->boc->vary = req->vary_b;
1225
        req->vary_b = NULL;
1226
1227
        HSH_Ref(oc);
1228 4548
        AZ(bo->fetch_objcore);
1229
        bo->fetch_objcore = oc;
1230
1231 4548
        AZ(bo->stale_oc);
1232 4548
        if (oldoc != NULL) {
1233 310
                assert(oldoc->refcnt > 0);
1234 310
                HSH_Ref(oldoc);
1235 310
                bo->stale_oc = oldoc;
1236 310
        }
1237
1238 4548
        AZ(bo->req);
1239
        bo->req = req;
1240
1241
        bo->fetch_task->priv = bo;
1242
        bo->fetch_task->func = vbf_fetch_thread;
1243
1244 4548
        if (Pool_Task(wrk->pool, bo->fetch_task, prio)) {
1245 4
                wrk->stats->bgfetch_no_thread++;
1246 4
                VSLb(bo->vsl, SLT_FetchError,
1247
                    "No thread available for bgfetch");
1248 4
                (void)vbf_stp_fail(req->wrk, bo);
1249 4
                if (bo->stale_oc != NULL)
1250 2
                        (void)HSH_DerefObjCore(wrk, &bo->stale_oc);
1251 4
                HSH_DerefBoc(wrk, oc);
1252 4
                SES_Rel(bo->sp);
1253 4
                THR_SetBusyobj(NULL);
1254 4
                VBO_ReleaseBusyObj(wrk, &bo);
1255 4
        } else {
1256 4544
                THR_SetBusyobj(NULL);
1257 4544
                bo = NULL; /* ref transferred to fetch thread */
1258 4544
                if (mode == VBF_BACKGROUND) {
1259 172
                        ObjWaitState(oc, BOS_REQ_DONE);
1260 172
                        (void)VRB_Ignore(req);
1261 172
                } else {
1262 4372
                        ObjWaitState(oc, BOS_STREAM);
1263 4372
                        AZ(oc->flags & OC_F_BUSY);
1264 4372
                        if (oc->boc->state == BOS_FAILED)
1265 54
                                AN(oc->flags & OC_F_FAILED);
1266
                }
1267
        }
1268 4548
        AZ(bo);
1269
        VSLb_ts_req(req, "Fetch", W_TIM_real(wrk));
1270 4548
        assert(oc->boc == boc);
1271
        HSH_DerefBoc(wrk, oc);
1272 4548
        if (mode == VBF_BACKGROUND)
1273 174
                (void)HSH_DerefObjCore(wrk, &oc);
1274
}