varnish-cache/bin/varnishd/cache/cache_fetch.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2015 Varnish Software AS
4
 * All rights reserved.
5
 *
6
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29
30
#include "config.h"
31
32
#include "cache_varnishd.h"
33
#include "cache_filter.h"
34
#include "cache_objhead.h"
35
#include "hash/hash_slinger.h"
36
#include "storage/storage.h"
37
#include "vcl.h"
38
#include "vtim.h"
39
40
/*--------------------------------------------------------------------
41
 * Allocate an object, with fall-back to Transient.
42
 * XXX: This somewhat overlaps the stuff in stevedore.c
43
 * XXX: Should this be merged over there ?
44
 */
45
46
static int
47 6580
vbf_allocobj(struct busyobj *bo, unsigned l)
48
{
49
        struct objcore *oc;
50
        const struct stevedore *stv;
51
        vtim_dur lifetime;
52
53 6580
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
54 6580
        oc = bo->fetch_objcore;
55 6580
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
56
57 6580
        lifetime = oc->ttl + oc->grace + oc->keep;
58
59 6580
        if (bo->uncacheable || lifetime < cache_param->shortlived)
60 2672
                stv = stv_transient;
61
        else
62 3908
                stv = bo->storage;
63
64 6580
        bo->storage = NULL;
65
66 6580
        if (stv == NULL)
67 4
                return (0);
68
69 6576
        if (STV_NewObject(bo->wrk, bo->fetch_objcore, stv, l))
70 6559
                return (1);
71
72 16
        if (stv == stv_transient)
73 8
                return (0);
74
75
        /*
76
         * Try to salvage the transaction by allocating a shortlived object
77
         * on Transient storage.
78
         */
79
80 8
        if (oc->ttl > cache_param->shortlived)
81 8
                oc->ttl = cache_param->shortlived;
82 8
        oc->grace = 0.0;
83 8
        oc->keep = 0.0;
84 8
        return (STV_NewObject(bo->wrk, bo->fetch_objcore, stv_transient, l));
85
}
86
87
/*--------------------------------------------------------------------
88
 * Turn the beresp into a obj
89
 */
90
91
static int
92 6580
vbf_beresp2obj(struct busyobj *bo)
93
{
94
        unsigned l, l2;
95
        const char *b;
96
        uint8_t *bp;
97 6580
        struct vsb *vary = NULL;
98 6580
        int varyl = 0;
99
100 6580
        l = 0;
101
102
        /* Create Vary instructions */
103 6580
        if (!(bo->fetch_objcore->flags & OC_F_PRIVATE)) {
104 4428
                varyl = VRY_Create(bo, &vary);
105 4428
                if (varyl > 0) {
106 748
                        AN(vary);
107 748
                        assert(varyl == VSB_len(vary));
108 748
                        l += PRNDUP((intptr_t)varyl);
109 3680
                } else if (varyl < 0) {
110
                        /*
111
                         * Vary parse error
112
                         * Complain about it, and make this a pass.
113
                         */
114 20
                        VSLb(bo->vsl, SLT_Error,
115
                            "Illegal 'Vary' header from backend, "
116
                            "making this a pass.");
117 20
                        bo->uncacheable = 1;
118 20
                        AZ(vary);
119
                } else
120
                        /* No vary */
121 3660
                        AZ(vary);
122
        }
123
124 6580
        l2 = http_EstimateWS(bo->beresp,
125 6580
            bo->uncacheable ? HTTPH_A_PASS : HTTPH_A_INS);
126 6580
        l += l2;
127
128 6580
        if (bo->uncacheable)
129 2396
                bo->fetch_objcore->flags |= OC_F_PASS;
130
131 6580
        if (!vbf_allocobj(bo, l)) {
132 12
                if (vary != NULL)
133 0
                        VSB_destroy(&vary);
134 12
                AZ(vary);
135 12
                return (-1);
136
        }
137
138 6567
        if (vary != NULL) {
139 748
                AN(ObjSetAttr(bo->wrk, bo->fetch_objcore, OA_VARY, varyl,
140
                        VSB_data(vary)));
141 748
                VSB_destroy(&vary);
142
        }
143
144 6567
        AZ(ObjSetU32(bo->wrk, bo->fetch_objcore, OA_VXID, VXID(bo->vsl->wid)));
145
146
        /* for HTTP_Encode() VSLH call */
147 6568
        bo->beresp->logtag = SLT_ObjMethod;
148
149
        /* Filter into object */
150 6568
        bp = ObjSetAttr(bo->wrk, bo->fetch_objcore, OA_HEADERS, l2, NULL);
151 6568
        AN(bp);
152 6568
        HTTP_Encode(bo->beresp, bp, l2,
153 6568
            bo->uncacheable ? HTTPH_A_PASS : HTTPH_A_INS);
154
155 6568
        if (http_GetHdr(bo->beresp, H_Last_Modified, &b))
156 136
                AZ(ObjSetDouble(bo->wrk, bo->fetch_objcore, OA_LASTMODIFIED,
157
                    VTIM_parse(b)));
158
        else
159 6432
                AZ(ObjSetDouble(bo->wrk, bo->fetch_objcore, OA_LASTMODIFIED,
160
                    floor(bo->fetch_objcore->t_origin)));
161
162 6568
        return (0);
163
}
164
165
/*--------------------------------------------------------------------
166
 * Copy req->bereq and release req if no body
167
 */
168
169
static enum fetch_step
170 6564
vbf_stp_mkbereq(struct worker *wrk, struct busyobj *bo)
171
{
172
        const char *q;
173
174 6564
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
175 6564
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
176 6564
        CHECK_OBJ_NOTNULL(bo->req, REQ_MAGIC);
177
178 6564
        assert(bo->fetch_objcore->boc->state == BOS_INVALID);
179 6564
        AZ(bo->storage);
180
181 6564
        HTTP_Setup(bo->bereq0, bo->ws, bo->vsl, SLT_BereqMethod);
182 6564
        http_FilterReq(bo->bereq0, bo->req->http,
183 6564
            bo->do_pass ? HTTPH_R_PASS : HTTPH_R_FETCH);
184
185 6564
        if (bo->do_pass)
186 2148
                AZ(bo->stale_oc);
187
        else {
188 4416
                http_ForceField(bo->bereq0, HTTP_HDR_METHOD, "GET");
189 4416
                if (cache_param->http_gzip_support)
190 4396
                        http_ForceHeader(bo->bereq0, H_Accept_Encoding, "gzip");
191
        }
192 6564
        http_ForceField(bo->bereq0, HTTP_HDR_PROTO, "HTTP/1.1");
193 6564
        http_CopyHome(bo->bereq0);
194
195 6780
        if (bo->stale_oc != NULL &&
196 292
            ObjCheckFlag(bo->wrk, bo->stale_oc, OF_IMSCAND) &&
197 144
            (bo->stale_oc->boc != NULL || ObjGetLen(wrk, bo->stale_oc) != 0)) {
198 76
                AZ(bo->stale_oc->flags & (OC_F_PASS|OC_F_PRIVATE));
199 76
                q = HTTP_GetHdrPack(bo->wrk, bo->stale_oc, H_Last_Modified);
200 76
                if (q != NULL)
201 32
                        http_PrintfHeader(bo->bereq0,
202
                            "If-Modified-Since: %s", q);
203 76
                q = HTTP_GetHdrPack(bo->wrk, bo->stale_oc, H_ETag);
204 76
                if (q != NULL)
205 52
                        http_PrintfHeader(bo->bereq0,
206
                            "If-None-Match: %s", q);
207
        }
208
209 6564
        HTTP_Setup(bo->bereq, bo->ws, bo->vsl, SLT_BereqMethod);
210 6564
        bo->ws_bo = WS_Snapshot(bo->ws);
211 6564
        HTTP_Copy(bo->bereq, bo->bereq0);
212
213 6564
        if (bo->req->req_body_status == REQ_BODY_NONE) {
214 6432
                bo->req = NULL;
215 6432
                ObjSetState(bo->wrk, bo->fetch_objcore, BOS_REQ_DONE);
216
        }
217 6564
        return (F_STP_STARTFETCH);
218
}
219
220
/*--------------------------------------------------------------------
221
 * Start a new VSL transaction and try again
222
 * Prepare the busyobj and fetch processors
223
 */
224
225
static enum fetch_step
226 112
vbf_stp_retry(struct worker *wrk, struct busyobj *bo)
227
{
228 112
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
229 112
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
230
231 112
        assert(bo->fetch_objcore->boc->state <= BOS_REQ_DONE);
232
233 112
        VSLb_ts_busyobj(bo, "Retry", W_TIM_real(wrk));
234
235
        /* VDI_Finish must have been called before */
236 112
        assert(bo->director_state == DIR_S_NULL);
237
238
        /* reset other bo attributes - See VBO_GetBusyObj */
239 112
        bo->storage = NULL;
240 112
        bo->do_esi = 0;
241 112
        bo->do_stream = 1;
242 112
        bo->filter_list = NULL;
243 112
        bo->was_304 = 0;
244
245
        // XXX: BereqEnd + BereqAcct ?
246 112
        VSL_ChgId(bo->vsl, "bereq", "retry", VXID_Get(wrk, VSL_BACKENDMARKER));
247 112
        VSLb_ts_busyobj(bo, "Start", bo->t_prev);
248 112
        http_VSL_log(bo->bereq);
249
250 112
        return (F_STP_STARTFETCH);
251
}
252
253
/*--------------------------------------------------------------------
254
 * Setup bereq from bereq0, run vcl_backend_fetch
255
 */
256
257
static enum fetch_step
258 6676
vbf_stp_startfetch(struct worker *wrk, struct busyobj *bo)
259
{
260
        int i;
261
        vtim_real now;
262
263 6676
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
264 6676
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
265
266 6676
        AZ(bo->storage);
267 6676
        bo->storage = bo->do_pass ? stv_transient : STV_next();
268
269 6676
        if (bo->retries > 0)
270 112
                http_Unset(bo->bereq, "\012X-Varnish:");
271
272 6676
        http_PrintfHeader(bo->bereq, "X-Varnish: %u", VXID(bo->vsl->wid));
273
274 6676
        VCL_backend_fetch_method(bo->vcl, wrk, NULL, bo, NULL);
275
276 6676
        bo->uncacheable = bo->do_pass;
277 6676
        if (wrk->handling == VCL_RET_ABANDON || wrk->handling == VCL_RET_FAIL)
278 28
                return (F_STP_FAIL);
279
280 6648
        assert (wrk->handling == VCL_RET_FETCH);
281
282 6648
        HTTP_Setup(bo->beresp, bo->ws, bo->vsl, SLT_BerespMethod);
283
284 6648
        assert(bo->fetch_objcore->boc->state <= BOS_REQ_DONE);
285
286 6648
        AZ(bo->htc);
287
288 6648
        VFP_Setup(bo->vfc, wrk);
289 6648
        bo->vfc->oc = bo->fetch_objcore;
290 6648
        bo->vfc->resp = bo->beresp;
291 6648
        bo->vfc->req = bo->bereq;
292
293 6648
        i = VDI_GetHdr(bo);
294
295 6648
        now = W_TIM_real(wrk);
296 6648
        VSLb_ts_busyobj(bo, "Beresp", now);
297
298 6648
        if (i) {
299 472
                assert(bo->director_state == DIR_S_NULL);
300 472
                return (F_STP_ERROR);
301
        }
302
303 6176
        http_VSL_log(bo->beresp);
304
305 6176
        if (bo->htc->body_status == BS_ERROR) {
306 24
                bo->htc->doclose = SC_RX_BODY;
307 24
                VDI_Finish(bo);
308 24
                VSLb(bo->vsl, SLT_Error, "Body cannot be fetched");
309 24
                assert(bo->director_state == DIR_S_NULL);
310 24
                return (F_STP_ERROR);
311
        }
312
313 6152
        if (!http_GetHdr(bo->beresp, H_Date, NULL)) {
314
                /*
315
                 * RFC 2616 14.18 Date: The Date general-header field
316
                 * represents the date and time at which the message was
317
                 * originated, having the same semantics as orig-date in
318
                 * RFC 822. ... A received message that does not have a
319
                 * Date header field MUST be assigned one by the recipient
320
                 * if the message will be cached by that recipient or
321
                 * gatewayed via a protocol which requires a Date.
322
                 *
323
                 * If we didn't get a Date header, we assign one here.
324
                 */
325 6112
                http_TimeHeader(bo->beresp, "Date: ", now);
326
        }
327
328
        /*
329
         * These two headers can be spread over multiple actual headers
330
         * and we rely on their content outside of VCL, so collect them
331
         * into one line here.
332
         */
333 6152
        http_CollectHdr(bo->beresp, H_Cache_Control);
334 6152
        http_CollectHdr(bo->beresp, H_Vary);
335
336 6152
        if (bo->fetch_objcore->flags & OC_F_PRIVATE) {
337
                /* private objects have negative TTL */
338 1896
                bo->fetch_objcore->t_origin = now;
339 1896
                bo->fetch_objcore->ttl = -1.;
340 1896
                bo->fetch_objcore->grace = 0;
341 1896
                bo->fetch_objcore->keep = 0;
342
        } else {
343
                /* What does RFC2616 think about TTL ? */
344 17024
                RFC2616_Ttl(bo, now,
345 4256
                    &bo->fetch_objcore->t_origin,
346 4256
                    &bo->fetch_objcore->ttl,
347 4256
                    &bo->fetch_objcore->grace,
348 4256
                    &bo->fetch_objcore->keep
349
                    );
350
        }
351
352 6152
        AZ(bo->do_esi);
353 6152
        AZ(bo->was_304);
354
355 6152
        if (http_IsStatus(bo->beresp, 304)) {
356 168
                if (bo->stale_oc != NULL &&
357 76
                    ObjCheckFlag(bo->wrk, bo->stale_oc, OF_IMSCAND)) {
358 72
                        AZ(bo->stale_oc->flags & (OC_F_PASS|OC_F_PRIVATE));
359 72
                        if (ObjCheckFlag(bo->wrk, bo->stale_oc, OF_CHGGZIP)) {
360
                                /*
361
                                 * If we changed the gzip status of the object
362
                                 * the stored Content_Encoding controls we
363
                                 * must weaken any new ETag we get.
364
                                 */
365 8
                                http_Unset(bo->beresp, H_Content_Encoding);
366 8
                                RFC2616_Weaken_Etag(bo->beresp);
367
                        }
368 72
                        http_Unset(bo->beresp, H_Content_Length);
369 72
                        HTTP_Merge(bo->wrk, bo->stale_oc, bo->beresp);
370 72
                        assert(http_IsStatus(bo->beresp, 200));
371 72
                        bo->was_304 = 1;
372 20
                } else if (!bo->do_pass) {
373
                        /*
374
                         * Backend sent unallowed 304
375
                         */
376 4
                        VSLb(bo->vsl, SLT_Error,
377
                            "304 response but not conditional fetch");
378 4
                        bo->htc->doclose = SC_RX_BAD;
379 4
                        VDI_Finish(bo);
380 4
                        return (F_STP_ERROR);
381
                }
382
        }
383
384 6148
        VCL_backend_response_method(bo->vcl, wrk, NULL, bo, NULL);
385
386 6144
        if (wrk->handling == VCL_RET_ABANDON || wrk->handling == VCL_RET_FAIL) {
387 20
                bo->htc->doclose = SC_RESP_CLOSE;
388 20
                VDI_Finish(bo);
389 20
                return (F_STP_FAIL);
390
        }
391
392 6124
        if (wrk->handling == VCL_RET_RETRY) {
393 80
                if (bo->htc->body_status != BS_NONE)
394 28
                        bo->htc->doclose = SC_RESP_CLOSE;
395 80
                if (bo->director_state != DIR_S_NULL)
396 80
                        VDI_Finish(bo);
397
398 80
                if (bo->retries++ < cache_param->max_retries)
399 76
                        return (F_STP_RETRY);
400
401 4
                VSLb(bo->vsl, SLT_VCL_Error,
402
                    "Too many retries, delivering 503");
403 4
                assert(bo->director_state == DIR_S_NULL);
404 4
                return (F_STP_ERROR);
405
        }
406
407 6044
        assert(bo->fetch_objcore->boc->state <= BOS_REQ_DONE);
408 6044
        if (bo->fetch_objcore->boc->state != BOS_REQ_DONE) {
409 88
                bo->req = NULL;
410 88
                ObjSetState(wrk, bo->fetch_objcore, BOS_REQ_DONE);
411
        }
412
413 6044
        if (bo->do_esi)
414 700
                bo->do_stream = 0;
415 6044
        if (wrk->handling == VCL_RET_PASS) {
416 44
                bo->fetch_objcore->flags |= OC_F_HFP;
417 44
                bo->uncacheable = 1;
418 44
                wrk->handling = VCL_RET_DELIVER;
419
        }
420 6044
        if (bo->do_pass || bo->uncacheable)
421 2088
                bo->fetch_objcore->flags |= OC_F_PASS;
422
423 6044
        assert(wrk->handling == VCL_RET_DELIVER);
424
425 6044
        return (bo->was_304 ? F_STP_CONDFETCH : F_STP_FETCH);
426
}
427
428
/*--------------------------------------------------------------------
429
 */
430
431
static enum fetch_step
432 3671
vbf_stp_fetchbody(struct worker *wrk, struct busyobj *bo)
433
{
434
        ssize_t l;
435
        uint8_t *ptr;
436 3671
        enum vfp_status vfps = VFP_ERROR;
437
        ssize_t est;
438
        struct vfp_ctx *vfc;
439
440 3671
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
441 3671
        vfc = bo->vfc;
442 3671
        CHECK_OBJ_NOTNULL(vfc, VFP_CTX_MAGIC);
443
444 3671
        AN(vfc->vfp_nxt);
445
446 3671
        est = bo->htc->content_length;
447 3671
        if (est < 0)
448 476
                est = 0;
449
450
        do {
451 220163
                if (vfc->oc->flags & OC_F_ABANDON) {
452
                        /*
453
                         * A pass object and delivery was terminated
454
                         * We don't fail the fetch, in order for HitMiss
455
                         * objects to be created.
456
                         */
457 5
                        AN(vfc->oc->flags & OC_F_PASS);
458 5
                        VSLb(wrk->vsl, SLT_Debug,
459
                            "Fetch: Pass delivery abandoned");
460 5
                        bo->htc->doclose = SC_RX_BODY;
461 5
                        break;
462
                }
463 220158
                AZ(vfc->failed);
464 220158
                l = est;
465 220158
                assert(l >= 0);
466 220158
                if (VFP_GetStorage(vfc, &l, &ptr) != VFP_OK) {
467 12
                        bo->htc->doclose = SC_RX_BODY;
468 12
                        break;
469
                }
470
471 220147
                AZ(vfc->failed);
472 220147
                vfps = VFP_Suck(vfc, ptr, &l);
473 220147
                if (l > 0 && vfps != VFP_ERROR) {
474 217673
                        bo->acct.beresp_bodybytes += l;
475 217673
                        VFP_Extend(vfc, l);
476 217673
                        if (est >= l)
477 5581
                                est -= l;
478
                        else
479 212092
                                est = 0;
480
                }
481 220147
        } while (vfps == VFP_OK);
482
483 3672
        if (vfc->failed) {
484 120
                (void)VFP_Error(vfc, "Fetch pipeline failed to process");
485 120
                bo->htc->doclose = SC_RX_BODY;
486 120
                VFP_Close(vfc);
487 120
                VDI_Finish(bo);
488 120
                if (!bo->do_stream) {
489 80
                        assert(bo->fetch_objcore->boc->state < BOS_STREAM);
490
                        // XXX: doclose = ?
491 80
                        return (F_STP_ERROR);
492
                } else {
493 40
                        wrk->stats->fetch_failed++;
494 40
                        return (F_STP_FAIL);
495
                }
496
        }
497
498 3552
        ObjTrimStore(wrk, vfc->oc);
499 3551
        return (F_STP_FETCHEND);
500
}
501
static enum fetch_step
502 5976
vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)
503
{
504
        const char *p;
505
506 5976
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
507 5976
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
508 5976
        CHECK_OBJ_NOTNULL(bo->fetch_objcore, OBJCORE_MAGIC);
509
510 5976
        assert(wrk->handling == VCL_RET_DELIVER);
511
512
        /* No body -> done */
513 5976
        if (bo->htc->body_status == BS_NONE || bo->htc->content_length == 0) {
514 2280
                http_Unset(bo->beresp, H_Content_Encoding);
515 2280
                bo->do_gzip = bo->do_gunzip = 0;
516 2280
                bo->do_stream = 0;
517 2280
                bo->filter_list = "";
518 3696
        } else if (bo->filter_list == NULL) {
519 3680
                bo->filter_list = VBF_Get_Filter_List(bo);
520
        }
521
522 11944
        if (bo->filter_list == NULL ||
523 5968
            VCL_StackVFP(bo->vfc, bo->vcl, bo->filter_list)) {
524 20
                (bo)->htc->doclose = SC_OVERLOAD;
525 20
                VDI_Finish(bo);
526 20
                return (F_STP_ERROR);
527
        }
528
529 5956
        if (bo->fetch_objcore->flags & OC_F_PRIVATE)
530 1848
                AN(bo->uncacheable);
531
532 5956
        bo->fetch_objcore->boc->len_so_far = 0;
533
534 5956
        if (VFP_Open(bo->vfc)) {
535 4
                (void)VFP_Error(bo->vfc, "Fetch pipeline failed to open");
536 4
                bo->htc->doclose = SC_RX_BODY;
537 4
                VDI_Finish(bo);
538 4
                return (F_STP_ERROR);
539
        }
540
541 5952
        if (vbf_beresp2obj(bo)) {
542 8
                (void)VFP_Error(bo->vfc, "Could not get storage");
543 8
                bo->htc->doclose = SC_RX_BODY;
544 8
                VFP_Close(bo->vfc);
545 8
                VDI_Finish(bo);
546 8
                return (F_STP_ERROR);
547
        }
548
549
#define OBJ_FLAG(U, l, v)                                               \
550
        if (bo->vfc->obj_flags & OF_##U)                                \
551
                ObjSetFlag(bo->wrk, bo->fetch_objcore, OF_##U, 1);
552
#include "tbl/obj_attr.h"
553
554 9808
        if (!(bo->fetch_objcore->flags & OC_F_PASS) &&
555 7664
            http_IsStatus(bo->beresp, 200) && (
556 7524
              http_GetHdr(bo->beresp, H_Last_Modified, &p) ||
557 3724
              http_GetHdr(bo->beresp, H_ETag, &p)))
558 168
                ObjSetFlag(bo->wrk, bo->fetch_objcore, OF_IMSCAND, 1);
559
560 5944
        assert(bo->fetch_objcore->boc->refcount >= 1);
561
562 5944
        assert(bo->fetch_objcore->boc->state == BOS_REQ_DONE);
563
564 5944
        if (bo->do_stream) {
565 2800
                ObjSetState(wrk, bo->fetch_objcore, BOS_PREP_STREAM);
566 2800
                HSH_Unbusy(wrk, bo->fetch_objcore);
567 2800
                ObjSetState(wrk, bo->fetch_objcore, BOS_STREAM);
568
        }
569
570 17832
        VSLb(bo->vsl, SLT_Fetch_Body, "%u %s %s",
571 11888
            bo->htc->body_status, body_status_2str(bo->htc->body_status),
572 5944
            bo->do_stream ? "stream" : "-");
573
574 5943
        if (bo->htc->body_status != BS_NONE) {
575 3671
                assert(bo->htc->body_status != BS_ERROR);
576 3671
                return (F_STP_FETCHBODY);
577
        }
578 2272
        AZ(bo->vfc->failed);
579 2272
        return (F_STP_FETCHEND);
580
}
581
582
static enum fetch_step
583 5887
vbf_stp_fetchend(struct worker *wrk, struct busyobj *bo)
584
{
585
586 5887
        AZ(bo->vfc->failed);
587 5887
        VFP_Close(bo->vfc);
588
589 5888
        AZ(ObjSetU64(wrk, bo->fetch_objcore, OA_LEN,
590
            bo->fetch_objcore->boc->len_so_far));
591
592 5888
        if (bo->do_stream)
593 2820
                assert(bo->fetch_objcore->boc->state == BOS_STREAM);
594
        else {
595 3068
                assert(bo->fetch_objcore->boc->state == BOS_REQ_DONE);
596 3068
                HSH_Unbusy(wrk, bo->fetch_objcore);
597
        }
598
599
        /* Recycle the backend connection before setting BOS_FINISHED to
600
           give predictable backend reuse behavior for varnishtest */
601 5888
        VDI_Finish(bo);
602
603 5888
        ObjSetState(wrk, bo->fetch_objcore, BOS_FINISHED);
604 5888
        VSLb_ts_busyobj(bo, "BerespBody", W_TIM_real(wrk));
605 5888
        if (bo->stale_oc != NULL)
606 188
                HSH_Kill(bo->stale_oc);
607 5888
        return (F_STP_DONE);
608
}
609
610
/*--------------------------------------------------------------------
611
 */
612
613
static int v_matchproto_(objiterate_f)
614 76
vbf_objiterator(void *priv, unsigned flush, const void *ptr, ssize_t len)
615
{
616
        struct busyobj *bo;
617
        ssize_t l;
618 76
        const uint8_t *ps = ptr;
619
        uint8_t *pd;
620
621 76
        CAST_OBJ_NOTNULL(bo, priv, BUSYOBJ_MAGIC);
622
        (void)flush;
623
624 228
        while (len > 0) {
625 76
                l = len;
626 76
                if (VFP_GetStorage(bo->vfc, &l, &pd) != VFP_OK)
627 0
                        return (1);
628 76
                if (len < l)
629 0
                        l = len;
630 76
                memcpy(pd, ps, l);
631 76
                VFP_Extend(bo->vfc, l);
632 76
                ps += l;
633 76
                len -= l;
634
        }
635 76
        return (0);
636
}
637
638
static enum fetch_step
639 68
vbf_stp_condfetch(struct worker *wrk, struct busyobj *bo)
640
{
641
642 68
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
643 68
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
644
645 68
        AZ(vbf_beresp2obj(bo));
646
647 68
        if (ObjHasAttr(bo->wrk, bo->stale_oc, OA_ESIDATA))
648 4
                AZ(ObjCopyAttr(bo->wrk, bo->fetch_objcore, bo->stale_oc,
649
                    OA_ESIDATA));
650
651 68
        AZ(ObjCopyAttr(bo->wrk, bo->fetch_objcore, bo->stale_oc, OA_FLAGS));
652 68
        ObjSetFlag(bo->wrk, bo->fetch_objcore, OF_IMSCAND, 0);
653 68
        AZ(ObjCopyAttr(bo->wrk, bo->fetch_objcore, bo->stale_oc, OA_GZIPBITS));
654
655 68
        if (bo->do_stream) {
656 64
                ObjSetState(wrk, bo->fetch_objcore, BOS_PREP_STREAM);
657 64
                HSH_Unbusy(wrk, bo->fetch_objcore);
658 64
                ObjSetState(wrk, bo->fetch_objcore, BOS_STREAM);
659
        }
660
661 68
        if (ObjIterate(wrk, bo->stale_oc, bo, vbf_objiterator, 0))
662 4
                (void)VFP_Error(bo->vfc, "Template object failed");
663
664 68
        if (bo->stale_oc->flags & OC_F_FAILED)
665 4
                (void)VFP_Error(bo->vfc, "Template object failed");
666 68
        if (bo->vfc->failed) {
667 4
                VDI_Finish(bo);
668 4
                wrk->stats->fetch_failed++;
669 4
                return (F_STP_FAIL);
670
        }
671 64
        return (F_STP_FETCHEND);
672
}
673
674
/*--------------------------------------------------------------------
675
 * Create synth object
676
 */
677
678
static enum fetch_step
679 616
vbf_stp_error(struct worker *wrk, struct busyobj *bo)
680
{
681
        ssize_t l, ll, o;
682
        vtim_real now;
683
        uint8_t *ptr;
684
        struct vsb *synth_body;
685
686 616
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
687 616
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
688 616
        CHECK_OBJ_NOTNULL(bo->fetch_objcore, OBJCORE_MAGIC);
689 616
        AN(bo->fetch_objcore->flags & OC_F_BUSY);
690 616
        assert(bo->director_state == DIR_S_NULL);
691
692 616
        wrk->stats->fetch_failed++;
693
694 616
        now = W_TIM_real(wrk);
695 616
        VSLb_ts_busyobj(bo, "Error", now);
696
697 616
        if (bo->fetch_objcore->stobj->stevedore != NULL)
698 80
                ObjFreeObj(bo->wrk, bo->fetch_objcore);
699
700 616
        if (bo->storage == NULL)
701 88
                bo->storage = STV_next();
702
703
        // XXX: reset all beresp flags ?
704
705 616
        HTTP_Setup(bo->beresp, bo->ws, bo->vsl, SLT_BerespMethod);
706 616
        http_PutResponse(bo->beresp, "HTTP/1.1", 503, "Backend fetch failed");
707 616
        http_TimeHeader(bo->beresp, "Date: ", now);
708 616
        http_SetHeader(bo->beresp, "Server: Varnish");
709
710 616
        bo->fetch_objcore->t_origin = now;
711 616
        if (!VTAILQ_EMPTY(&bo->fetch_objcore->objhead->waitinglist)) {
712
                /*
713
                 * If there is a waitinglist, it means that there is no
714
                 * grace-able object, so cache the error return for a
715
                 * short time, so the waiting list can drain, rather than
716
                 * each objcore on the waiting list sequentially attempt
717
                 * to fetch from the backend.
718
                 */
719 0
                bo->fetch_objcore->ttl = 1;
720 0
                bo->fetch_objcore->grace = 5;
721 0
                bo->fetch_objcore->keep = 5;
722
        } else {
723 616
                bo->fetch_objcore->ttl = 0;
724 616
                bo->fetch_objcore->grace = 0;
725 616
                bo->fetch_objcore->keep = 0;
726
        }
727
728 616
        synth_body = VSB_new_auto();
729 616
        AN(synth_body);
730
731 616
        VCL_backend_error_method(bo->vcl, wrk, NULL, bo, synth_body);
732
733 616
        AZ(VSB_finish(synth_body));
734
735 616
        if (wrk->handling == VCL_RET_ABANDON || wrk->handling == VCL_RET_FAIL) {
736 12
                VSB_destroy(&synth_body);
737 12
                return (F_STP_FAIL);
738
        }
739
740 604
        if (wrk->handling == VCL_RET_RETRY) {
741 44
                VSB_destroy(&synth_body);
742 44
                if (bo->retries++ < cache_param->max_retries)
743 36
                        return (F_STP_RETRY);
744 8
                VSLb(bo->vsl, SLT_VCL_Error, "Too many retries, failing");
745 8
                return (F_STP_FAIL);
746
        }
747
748 560
        assert(wrk->handling == VCL_RET_DELIVER);
749
750 560
        assert(bo->vfc->wrk == bo->wrk);
751 560
        assert(bo->vfc->oc == bo->fetch_objcore);
752 560
        assert(bo->vfc->resp == bo->beresp);
753 560
        assert(bo->vfc->req == bo->bereq);
754
755 560
        if (vbf_beresp2obj(bo)) {
756 4
                (void)VFP_Error(bo->vfc, "Could not get storage");
757 4
                VSB_destroy(&synth_body);
758 4
                return (F_STP_FAIL);
759
        }
760
761 556
        ll = VSB_len(synth_body);
762 556
        o = 0;
763 1660
        while (ll > 0) {
764 548
                l = ll;
765 548
                if (VFP_GetStorage(bo->vfc, &l, &ptr) != VFP_OK)
766 0
                        break;
767 548
                if (l > ll)
768 4
                        l = ll;
769 548
                memcpy(ptr, VSB_data(synth_body) + o, l);
770 548
                VFP_Extend(bo->vfc, l);
771 548
                ll -= l;
772 548
                o += l;
773
        }
774 556
        AZ(ObjSetU64(wrk, bo->fetch_objcore, OA_LEN, o));
775 556
        VSB_destroy(&synth_body);
776 556
        HSH_Unbusy(wrk, bo->fetch_objcore);
777 556
        ObjSetState(wrk, bo->fetch_objcore, BOS_FINISHED);
778 556
        return (F_STP_DONE);
779
}
780
781
/*--------------------------------------------------------------------
782
 */
783
784
static enum fetch_step
785 116
vbf_stp_fail(struct worker *wrk, const struct busyobj *bo)
786
{
787 116
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
788 116
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
789 116
        CHECK_OBJ_NOTNULL(bo->fetch_objcore, OBJCORE_MAGIC);
790
791 116
        assert(bo->fetch_objcore->boc->state < BOS_FINISHED);
792 116
        HSH_Fail(bo->fetch_objcore);
793 116
        if (!(bo->fetch_objcore->flags & OC_F_BUSY))
794 44
                HSH_Kill(bo->fetch_objcore);
795 116
        ObjSetState(wrk, bo->fetch_objcore, BOS_FAILED);
796 116
        return (F_STP_DONE);
797
}
798
799
/*--------------------------------------------------------------------
800
 */
801
802
static enum fetch_step
803 0
vbf_stp_done(void)
804
{
805 0
        WRONG("Just plain wrong");
806
        NEEDLESS(return(F_STP_DONE));
807
}
808
809
static void v_matchproto_(task_func_t)
810 6564
vbf_fetch_thread(struct worker *wrk, void *priv)
811
{
812
        struct busyobj *bo;
813
        enum fetch_step stp;
814
815 6564
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
816 6564
        CAST_OBJ_NOTNULL(bo, priv, BUSYOBJ_MAGIC);
817 6564
        CHECK_OBJ_NOTNULL(bo->req, REQ_MAGIC);
818 6564
        CHECK_OBJ_NOTNULL(bo->fetch_objcore, OBJCORE_MAGIC);
819
820 6564
        THR_SetBusyobj(bo);
821 6564
        stp = F_STP_MKBEREQ;
822 6564
        assert(isnan(bo->t_first));
823 6564
        assert(isnan(bo->t_prev));
824 6564
        VSLb_ts_busyobj(bo, "Start", W_TIM_real(wrk));
825
826 6564
        bo->wrk = wrk;
827 6564
        wrk->vsl = bo->vsl;
828
829
#if 0
830
        if (bo->stale_oc != NULL) {
831
                CHECK_OBJ_NOTNULL(bo->stale_oc, OBJCORE_MAGIC);
832
                /* We don't want the oc/stevedore ops in fetching thread */
833
                if (!ObjCheckFlag(wrk, bo->stale_oc, OF_IMSCAND))
834
                        (void)HSH_DerefObjCore(wrk, &bo->stale_oc, 0);
835
        }
836
#endif
837
838 6564
        VCL_TaskEnter(bo->vcl, bo->privs);
839 6564
        while (stp != F_STP_DONE) {
840 29685
                CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
841 29686
                assert(bo->fetch_objcore->boc->refcount >= 1);
842 29686
                if (bo->fetch_objcore->boc->state < BOS_REQ_DONE)
843 6776
                        AN(bo->req);
844
                else
845 22910
                        AZ(bo->req);
846 29686
                switch (stp) {
847
#define FETCH_STEP(l, U, arg)                                           \
848
                case F_STP_##U:                                         \
849
                        stp = vbf_stp_##l arg;                          \
850
                        break;
851
#include "tbl/steps.h"
852
                default:
853 0
                        WRONG("Illegal fetch_step");
854
                }
855
        }
856
857 6560
        assert(bo->director_state == DIR_S_NULL);
858
859 6560
        VCL_TaskLeave(bo->vcl, bo->privs);
860 6560
        http_Teardown(bo->bereq);
861 6560
        http_Teardown(bo->beresp);
862
863 6560
        if (bo->fetch_objcore->boc->state == BOS_FINISHED) {
864 6444
                AZ(bo->fetch_objcore->flags & OC_F_FAILED);
865 6444
                VSLb(bo->vsl, SLT_Length, "%ju",
866 6444
                    (uintmax_t)ObjGetLen(bo->wrk, bo->fetch_objcore));
867
        }
868
        // AZ(bo->fetch_objcore->boc);  // XXX
869
870 6560
        if (bo->stale_oc != NULL)
871 216
                (void)HSH_DerefObjCore(wrk, &bo->stale_oc, 0);
872
873 6560
        wrk->vsl = NULL;
874 6560
        HSH_DerefBoc(wrk, bo->fetch_objcore);
875 6560
        SES_Rel(bo->sp);
876 6560
        VBO_ReleaseBusyObj(wrk, &bo);
877 6560
        THR_SetBusyobj(NULL);
878 6560
}
879
880
/*--------------------------------------------------------------------
881
 */
882
883
void
884 6564
VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc,
885
    struct objcore *oldoc, enum vbf_fetch_mode_e mode)
886
{
887
        struct boc *boc;
888
        struct busyobj *bo;
889
        const char *how;
890
891 6564
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
892 6564
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
893 6564
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
894 6564
        AN(oc->flags & OC_F_BUSY);
895 6564
        CHECK_OBJ_ORNULL(oldoc, OBJCORE_MAGIC);
896
897 6564
        bo = VBO_GetBusyObj(wrk, req);
898 6564
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
899
900 6564
        boc = HSH_RefBoc(oc);
901 6564
        CHECK_OBJ_NOTNULL(boc, BOC_MAGIC);
902
903 6564
        switch (mode) {
904
        case VBF_PASS:
905 2148
                how = "pass";
906 2148
                bo->do_pass = 1;
907 2148
                break;
908
        case VBF_NORMAL:
909 4356
                how = "fetch";
910 4356
                break;
911
        case VBF_BACKGROUND:
912 60
                how = "bgfetch";
913 60
                bo->is_bgfetch = 1;
914 60
                break;
915
        default:
916 0
                WRONG("Wrong fetch mode");
917
        }
918
919 6564
        VSLb(bo->vsl, SLT_Begin, "bereq %u %s", VXID(req->vsl->wid), how);
920 6564
        VSLb(req->vsl, SLT_Link, "bereq %u %s", VXID(bo->vsl->wid), how);
921
922 6564
        THR_SetBusyobj(bo);
923
924 6564
        bo->sp = req->sp;
925 6564
        SES_Ref(bo->sp);
926
927 6564
        AN(bo->vcl);
928
929 6564
        oc->boc->vary = req->vary_b;
930 6564
        req->vary_b = NULL;
931
932 6564
        HSH_Ref(oc);
933 6564
        AZ(bo->fetch_objcore);
934 6564
        bo->fetch_objcore = oc;
935
936 6564
        AZ(bo->stale_oc);
937 6564
        if (oldoc != NULL) {
938 216
                assert(oldoc->refcnt > 0);
939 216
                HSH_Ref(oldoc);
940 216
                bo->stale_oc = oldoc;
941
        }
942
943 6564
        AZ(bo->req);
944 6564
        bo->req = req;
945
946 6564
        bo->fetch_task.priv = bo;
947 6564
        bo->fetch_task.func = vbf_fetch_thread;
948
949 6564
        if (Pool_Task(wrk->pool, &bo->fetch_task, TASK_QUEUE_BO)) {
950 0
                wrk->stats->fetch_no_thread++;
951 0
                (void)vbf_stp_fail(req->wrk, bo);
952 0
                if (bo->stale_oc != NULL)
953 0
                        (void)HSH_DerefObjCore(wrk, &bo->stale_oc, 0);
954 0
                HSH_DerefBoc(wrk, oc);
955 0
                SES_Rel(bo->sp);
956 0
                VBO_ReleaseBusyObj(wrk, &bo);
957
        } else {
958 6564
                bo = NULL; /* ref transferred to fetch thread */
959 6564
                if (mode == VBF_BACKGROUND) {
960 60
                        ObjWaitState(oc, BOS_REQ_DONE);
961 60
                        (void)VRB_Ignore(req);
962
                } else {
963 6504
                        ObjWaitState(oc, BOS_STREAM);
964 6500
                        if (oc->boc->state == BOS_FAILED) {
965 68
                                AN((oc->flags & OC_F_FAILED));
966
                        } else {
967 6432
                                AZ(oc->flags & OC_F_BUSY);
968
                        }
969
                }
970
        }
971 6560
        AZ(bo);
972 6560
        VSLb_ts_req(req, "Fetch", W_TIM_real(wrk));
973 6560
        assert(oc->boc == boc);
974 6560
        HSH_DerefBoc(wrk, oc);
975 6560
        if (mode == VBF_BACKGROUND)
976 60
                (void)HSH_DerefObjCore(wrk, &oc, HSH_RUSH_POLICY);
977 6560
        THR_SetBusyobj(NULL);
978 6560
}