source: bin/varnishd/cache/cache_vrt_var.c @ ef74b8

Revision ef74b8, 14.1 KB checked in by Poul-Henning Kamp <phk@…>, 2 years ago (diff)

Move the busyobj reference from worker to req

  • Property mode set to 100644
Line 
1/*-
2 * Copyright (c) 2006 Verdens Gang AS
3 * Copyright (c) 2006-2011 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 * Runtime support for compiled VCL programs
30 */
31#include "config.h"
32
33#include <stdio.h>
34#include <stdlib.h>
35
36#include "cache.h"
37#include "common/heritage.h"
38
39#include "cache_backend.h"
40#include "vrt_obj.h"
41#include "vtcp.h"
42#include "vtim.h"
43
44static char vrt_hostname[255] = "";
45
46/*--------------------------------------------------------------------*/
47
48static void
49vrt_do_string(const struct http *hp, int fld,
50    const char *err, const char *p, va_list ap)
51{
52        char *b;
53
54        AN(hp);
55        b = VRT_String(hp->ws, NULL, p, ap);
56        if (b == NULL || *b == '\0') {
57                VSLb(hp->vsl, SLT_LostHeader, "%s", err);
58        } else {
59                http_SetH(hp, fld, b);
60        }
61        va_end(ap);
62}
63
64#define VRT_DO_HDR(obj, hdr, http, fld)                         \
65void                                                            \
66VRT_l_##obj##_##hdr(const struct sess *sp, const char *p, ...)  \
67{                                                               \
68        va_list ap;                                             \
69                                                                \
70        (void)sp;                                               \
71        va_start(ap, p);                                        \
72        vrt_do_string(http, fld, #obj "." #hdr, p, ap);         \
73        va_end(ap);                                             \
74}                                                               \
75                                                                \
76const char *                                                    \
77VRT_r_##obj##_##hdr(const struct sess *sp)                      \
78{                                                               \
79        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);                      \
80        CHECK_OBJ_NOTNULL(http, HTTP_MAGIC);                    \
81        return (http->hd[fld].b);                               \
82}
83
84VRT_DO_HDR(req,   request,      sp->req->http,          HTTP_HDR_REQ)
85VRT_DO_HDR(req,   url,          sp->req->http,          HTTP_HDR_URL)
86VRT_DO_HDR(req,   proto,        sp->req->http,          HTTP_HDR_PROTO)
87VRT_DO_HDR(bereq, request,      sp->req->busyobj->bereq,        HTTP_HDR_REQ)
88VRT_DO_HDR(bereq, url,          sp->req->busyobj->bereq,        HTTP_HDR_URL)
89VRT_DO_HDR(bereq, proto,        sp->req->busyobj->bereq,        HTTP_HDR_PROTO)
90VRT_DO_HDR(obj,   proto,        sp->req->obj->http,     HTTP_HDR_PROTO)
91VRT_DO_HDR(obj,   response,     sp->req->obj->http,     HTTP_HDR_RESPONSE)
92VRT_DO_HDR(resp,  proto,        sp->req->resp,          HTTP_HDR_PROTO)
93VRT_DO_HDR(resp,  response,     sp->req->resp,          HTTP_HDR_RESPONSE)
94VRT_DO_HDR(beresp,  proto,      sp->req->busyobj->beresp,       HTTP_HDR_PROTO)
95VRT_DO_HDR(beresp,  response,   sp->req->busyobj->beresp, HTTP_HDR_RESPONSE)
96
97/*--------------------------------------------------------------------*/
98
99#define VRT_DO_STATUS(obj, http)                                \
100void                                                            \
101VRT_l_##obj##_status(const struct sess *sp, int num)            \
102{                                                               \
103                                                                \
104        assert(num >= 100 && num <= 999);                       \
105        http->status = (uint16_t)num;                           \
106}                                                               \
107                                                                \
108int                                                             \
109VRT_r_##obj##_status(const struct sess *sp)                     \
110{                                                               \
111                                                                \
112        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);                      \
113        return(http->status);                                   \
114}
115
116VRT_DO_STATUS(obj, sp->req->obj->http)
117VRT_DO_STATUS(beresp, sp->req->busyobj->beresp)
118VRT_DO_STATUS(resp, sp->req->resp)
119
120/*--------------------------------------------------------------------*/
121
122/* XXX: review this */
123/* Add an objecthead to the saintmode list for the (hopefully) relevant
124 * backend. Some double-up asserting here to avoid assert-errors when there
125 * is no object.
126 */
127void
128VRT_l_beresp_saintmode(const struct sess *sp, double a)
129{
130        struct trouble *new;
131        struct trouble *tr;
132        struct trouble *tr2;
133        struct vbc *vbc;
134
135        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
136        CHECK_OBJ_NOTNULL(sp->req->busyobj, BUSYOBJ_MAGIC);
137        vbc = sp->req->busyobj->vbc;
138        if (!vbc)
139                return;
140        CHECK_OBJ_NOTNULL(vbc, VBC_MAGIC);
141        if (!vbc->backend)
142                return;
143        CHECK_OBJ_NOTNULL(vbc->backend, BACKEND_MAGIC);
144        if (!sp->req->objcore)
145                return;
146        CHECK_OBJ_NOTNULL(sp->req->objcore, OBJCORE_MAGIC);
147
148        /* Setting a negative holdoff period is a mistake. Detecting this
149         * when compiling the VCL would be better.
150         */
151        assert(a > 0);
152
153        ALLOC_OBJ(new, TROUBLE_MAGIC);
154        AN(new);
155        new->target = (uintptr_t)(sp->req->objcore->objhead);
156        new->timeout = sp->t_req + a;
157
158        /* Insert the new item on the list before the first item with a
159         * timeout at a later date (ie: sort by which entry will time out
160         * from the list
161         */
162        Lck_Lock(&vbc->backend->mtx);
163        VTAILQ_FOREACH_SAFE(tr, &vbc->backend->troublelist, list, tr2) {
164                if (tr->timeout < new->timeout) {
165                        VTAILQ_INSERT_BEFORE(tr, new, list);
166                        new = NULL;
167                        break;
168                }
169        }
170
171        /* Insert the item at the end if the list is empty or all other
172         * items have a longer timeout.
173         */
174        if (new)
175                VTAILQ_INSERT_TAIL(&vbc->backend->troublelist, new, list);
176
177        Lck_Unlock(&vbc->backend->mtx);
178}
179
180/*--------------------------------------------------------------------*/
181
182#define VBERESP(dir, type, onm, field)                                  \
183void                                                                    \
184VRT_l_##dir##_##onm(const struct sess *sp, type a)                      \
185{                                                                       \
186        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);                              \
187        sp->req->field = a;                                             \
188}                                                                       \
189                                                                        \
190type                                                                    \
191VRT_r_##dir##_##onm(const struct sess *sp)                              \
192{                                                                       \
193        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);                              \
194        return (sp->req->field);                                        \
195}
196
197VBERESP(beresp, unsigned, do_esi, busyobj->do_esi)
198VBERESP(beresp, unsigned, do_gzip, busyobj->do_gzip)
199VBERESP(beresp, unsigned, do_gunzip, busyobj->do_gunzip)
200VBERESP(beresp, unsigned, do_stream, busyobj->do_stream)
201VBERESP(beresp, unsigned, do_pass, busyobj->do_pass)
202
203/*--------------------------------------------------------------------*/
204
205const char *
206VRT_r_client_identity(const struct sess *sp)
207{
208        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
209        if (sp->req->client_identity != NULL)
210                return (sp->req->client_identity);
211        else
212                return (sp->addr);
213}
214
215void
216VRT_l_client_identity(const struct sess *sp, const char *str, ...)
217{
218        va_list ap;
219        char *b;
220
221        va_start(ap, str);
222        b = VRT_String(sp->req->http->ws, NULL, str, ap);
223        va_end(ap);
224        sp->req->client_identity = b;
225}
226
227/*--------------------------------------------------------------------*/
228
229#define BEREQ_TIMEOUT(which)                                    \
230void __match_proto__()                                          \
231VRT_l_bereq_##which(struct sess *sp, double num)                \
232{                                                               \
233                                                                \
234        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);                      \
235        CHECK_OBJ_NOTNULL(sp->req->busyobj, BUSYOBJ_MAGIC);     \
236        sp->req->busyobj->which = (num > 0.0 ? num : 0.0);      \
237}                                                               \
238                                                                \
239double __match_proto__()                                        \
240VRT_r_bereq_##which(struct sess *sp)                            \
241{                                                               \
242                                                                \
243        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);                      \
244        CHECK_OBJ_NOTNULL(sp->req->busyobj, BUSYOBJ_MAGIC);     \
245        return(sp->req->busyobj->which);                        \
246}
247
248BEREQ_TIMEOUT(connect_timeout)
249BEREQ_TIMEOUT(first_byte_timeout)
250BEREQ_TIMEOUT(between_bytes_timeout)
251
252/*--------------------------------------------------------------------*/
253
254const char *
255VRT_r_beresp_backend_name(const struct sess *sp)
256{
257
258        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
259        CHECK_OBJ_NOTNULL(sp->req->busyobj->vbc, VBC_MAGIC);
260        return(sp->req->busyobj->vbc->backend->vcl_name);
261}
262
263struct sockaddr_storage *
264VRT_r_beresp_backend_ip(const struct sess *sp)
265{
266
267        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
268        CHECK_OBJ_NOTNULL(sp->req->busyobj->vbc, VBC_MAGIC);
269        return(sp->req->busyobj->vbc->addr);
270}
271
272int
273VRT_r_beresp_backend_port(const struct sess *sp)
274{
275
276        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
277        CHECK_OBJ_NOTNULL(sp->req->busyobj->vbc, VBC_MAGIC);
278        return (VTCP_port(sp->req->busyobj->vbc->addr));
279}
280
281const char * __match_proto__()
282VRT_r_beresp_storage(struct sess *sp)
283{
284        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
285        if (sp->req->storage_hint != NULL)
286                return (sp->req->storage_hint);
287        else
288                return (NULL);
289}
290
291void __match_proto__()
292VRT_l_beresp_storage(struct sess *sp, const char *str, ...)
293{
294        va_list ap;
295        char *b;
296
297        va_start(ap, str);
298        b = VRT_String(sp->req->busyobj->ws, NULL, str, ap);
299        va_end(ap);
300        sp->req->storage_hint = b;
301}
302
303/*--------------------------------------------------------------------*/
304
305void
306VRT_l_req_backend(const struct sess *sp, struct director *be)
307{
308        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
309        sp->req->director = be;
310}
311
312struct director *
313VRT_r_req_backend(const struct sess *sp)
314{
315        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
316        return (sp->req->director);
317}
318
319/*--------------------------------------------------------------------*/
320
321void
322VRT_l_req_esi(const struct sess *sp, unsigned process_esi)
323{
324        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
325        /*
326         * Only allow you to turn of esi in the main request
327         * else everything gets confused
328         */
329        if(sp->req->esi_level == 0)
330                sp->req->disable_esi = !process_esi;
331}
332
333unsigned
334VRT_r_req_esi(const struct sess *sp)
335{
336        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
337        return (!sp->req->disable_esi);
338}
339
340int
341VRT_r_req_esi_level(const struct sess *sp)
342{
343
344        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
345        return(sp->req->esi_level);
346}
347
348/*--------------------------------------------------------------------*/
349
350unsigned __match_proto__()
351VRT_r_req_can_gzip(struct sess *sp)
352{
353
354        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
355        return (RFC2616_Req_Gzip(sp->req->http));
356}
357
358
359/*--------------------------------------------------------------------*/
360
361int
362VRT_r_req_restarts(const struct sess *sp)
363{
364
365        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
366        return (sp->req->restarts);
367}
368
369/*--------------------------------------------------------------------
370 * NB: TTL is relative to when object was created, whereas grace and
371 * keep are relative to ttl.
372 */
373
374#define VRT_DO_EXP(which, exp, fld, offset, extra)              \
375                                                                \
376void __match_proto__()                                          \
377VRT_l_##which##_##fld(struct sess *sp, double a)                \
378{                                                               \
379                                                                \
380        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);                      \
381        if (a > 0.)                                             \
382                a += offset;                                    \
383        EXP_Set_##fld(&exp, a);                                 \
384        extra;                                                  \
385}                                                               \
386                                                                \
387double __match_proto__()                                        \
388VRT_r_##which##_##fld(struct sess *sp)                          \
389{                                                               \
390                                                                \
391        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);                      \
392        return(EXP_Get_##fld(&exp) - offset);                   \
393}
394
395static void
396vrt_wsp_exp(const struct sess *sp, unsigned xid, const struct exp *e)
397{
398        VSLb(sp->req->vsl, SLT_TTL, "%u VCL %.0f %.0f %.0f %.0f %.0f",
399            xid, e->ttl - (sp->t_req - e->entered), e->grace, e->keep,
400            sp->t_req, e->age + (sp->t_req - e->entered));
401}
402
403VRT_DO_EXP(req, sp->req->exp, ttl, 0, )
404VRT_DO_EXP(req, sp->req->exp, grace, 0, )
405VRT_DO_EXP(req, sp->req->exp, keep, 0, )
406
407VRT_DO_EXP(obj, sp->req->obj->exp, grace, 0,
408   EXP_Rearm(sp->req->obj);
409   vrt_wsp_exp(sp, sp->req->obj->xid, &sp->req->obj->exp);)
410VRT_DO_EXP(obj, sp->req->obj->exp, ttl, (sp->t_req - sp->req->obj->exp.entered),
411   EXP_Rearm(sp->req->obj);
412   vrt_wsp_exp(sp, sp->req->obj->xid, &sp->req->obj->exp);)
413VRT_DO_EXP(obj, sp->req->obj->exp, keep, 0,
414   EXP_Rearm(sp->req->obj);
415   vrt_wsp_exp(sp, sp->req->obj->xid, &sp->req->obj->exp);)
416
417VRT_DO_EXP(beresp, sp->req->busyobj->exp, grace, 0,
418   vrt_wsp_exp(sp, sp->req->xid, &sp->req->busyobj->exp);)
419VRT_DO_EXP(beresp, sp->req->busyobj->exp, ttl, 0,
420   vrt_wsp_exp(sp, sp->req->xid, &sp->req->busyobj->exp);)
421VRT_DO_EXP(beresp, sp->req->busyobj->exp, keep, 0,
422   vrt_wsp_exp(sp, sp->req->xid, &sp->req->busyobj->exp);)
423
424/*--------------------------------------------------------------------
425 * req.xid
426 */
427
428const char * __match_proto__()
429VRT_r_req_xid(struct sess *sp)
430{
431        char *p;
432        int size;
433        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
434
435        size = snprintf(NULL, 0, "%u", sp->req->xid) + 1;
436        AN(p = WS_Alloc(sp->req->http->ws, size));
437        assert(snprintf(p, size, "%u", sp->req->xid) < size);
438        return (p);
439}
440
441/*--------------------------------------------------------------------*/
442
443#define REQ_BOOL(hash_var)                                      \
444void __match_proto__()                                          \
445VRT_l_req_##hash_var(struct sess *sp, unsigned val)             \
446{                                                               \
447                                                                \
448        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);                      \
449        sp->req->hash_var = val ? 1 : 0;                                \
450}                                                               \
451                                                                \
452unsigned __match_proto__()                                      \
453VRT_r_req_##hash_var(struct sess *sp)                           \
454{                                                               \
455                                                                \
456        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);                      \
457        return(sp->req->hash_var);                                      \
458}
459
460REQ_BOOL(hash_ignore_busy)
461REQ_BOOL(hash_always_miss)
462
463/*--------------------------------------------------------------------*/
464
465struct sockaddr_storage *
466VRT_r_client_ip(struct sess *sp)
467{
468
469        return (&sp->sockaddr);
470}
471
472struct sockaddr_storage *
473VRT_r_server_ip(struct sess *sp)
474{
475        int i;
476
477        if (sp->mysockaddr.ss_family == AF_UNSPEC) {
478                i = getsockname(sp->fd,
479                    (void*)&sp->mysockaddr, &sp->mysockaddrlen);
480                assert(VTCP_Check(i));
481        }
482
483        return (&sp->mysockaddr);
484}
485
486const char*
487VRT_r_server_identity(struct sess *sp)
488{
489        (void)sp;
490
491        if (heritage.identity[0] != '\0')
492                return (heritage.identity);
493        else
494                return (heritage.name);
495}
496
497
498const char*
499VRT_r_server_hostname(struct sess *sp)
500{
501        (void)sp;
502
503        if (vrt_hostname[0] == '\0')
504                AZ(gethostname(vrt_hostname, sizeof(vrt_hostname)));
505
506        return (vrt_hostname);
507}
508
509/*--------------------------------------------------------------------
510 * XXX: This is pessimistically silly
511 */
512
513int
514VRT_r_server_port(struct sess *sp)
515{
516        int i;
517
518        if (sp->mysockaddr.ss_family == AF_UNSPEC) {
519                i = getsockname(sp->fd,
520                    (void*)&sp->mysockaddr, &sp->mysockaddrlen);
521                assert(VTCP_Check(i));
522        }
523        return (VTCP_port(&sp->mysockaddr));
524}
525
526/*--------------------------------------------------------------------*/
527
528int
529VRT_r_obj_hits(const struct sess *sp)
530{
531
532        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
533        CHECK_OBJ_NOTNULL(sp->req->obj, OBJECT_MAGIC);  /* XXX */
534        return (sp->req->obj->hits);
535}
536
537double
538VRT_r_obj_lastuse(const struct sess *sp)
539{
540
541        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
542        CHECK_OBJ_NOTNULL(sp->req->obj, OBJECT_MAGIC);  /* XXX */
543        return (VTIM_real() - sp->req->obj->last_use);
544}
545
546unsigned
547VRT_r_req_backend_healthy(const struct sess *sp)
548{
549        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
550        CHECK_OBJ_NOTNULL(sp->req->director, DIRECTOR_MAGIC);
551        return (VDI_Healthy(sp->req->director, sp));
552}
553
Note: See TracBrowser for help on using the repository browser.