~ubuntu-branches/ubuntu/lucid/varnish/lucid-updates

« back to all changes in this revision

Viewing changes to bin/varnishd/cache_vrt.c

  • Committer: Bazaar Package Importer
  • Author(s): Stig Sandbeck Mathisen
  • Date: 2010-03-24 13:26:08 UTC
  • mfrom: (0.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20100324132608-4uzkavctn26bdwyi
Tags: 2.1.0-1
* New upstream version
* Fix small error in man/vcl.7so

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*-
2
2
 * Copyright (c) 2006 Verdens Gang AS
3
 
 * Copyright (c) 2006-2008 Linpro AS
 
3
 * Copyright (c) 2006-2009 Linpro AS
4
4
 * All rights reserved.
5
5
 *
6
6
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
26
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
27
 * SUCH DAMAGE.
28
28
 *
29
 
 * $Id: cache_vrt.c 4280 2009-10-08 09:17:03Z tfheen $
30
 
 *
31
29
 * Runtime support for compiled VCL programs
32
30
 */
33
31
 
34
32
#include "config.h"
35
33
 
 
34
#include "svnid.h"
 
35
SVNID("$Id: cache_vrt.c 4538 2010-02-08 18:09:49Z phk $")
 
36
 
36
37
#include <sys/types.h>
37
38
#include <sys/socket.h>
38
39
 
53
54
#include "hash_slinger.h"
54
55
#include "cache_backend.h"
55
56
 
56
 
void *vrt_magic_string_end = &vrt_magic_string_end;
57
 
char vrt_hostname[255] = "";
 
57
/*XXX: sort of a hack, improve the Tcl code in the compiler to avoid */
 
58
/*lint -save -esym(818,sp) */
 
59
 
 
60
const void * const vrt_magic_string_end = &vrt_magic_string_end;
 
61
static char vrt_hostname[255] = "";
58
62
 
59
63
/*--------------------------------------------------------------------*/
60
64
 
63
67
{
64
68
 
65
69
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
66
 
        WSL(sp->wrk, SLT_Debug, 0, "VCL_error(%u, %s)", code, reason ? 
 
70
        WSL(sp->wrk, SLT_Debug, 0, "VCL_error(%u, %s)", code, reason ?
67
71
            reason : "(null)");
68
72
        sp->err_code = code ? code : 503;
69
73
        sp->err_reason = reason ? reason : http_StatusMessage(sp->err_code);
102
106
                hp = sp->http;
103
107
                break;
104
108
        case HDR_BEREQ:
105
 
                hp = sp->bereq->http;
 
109
                hp = sp->wrk->bereq;
 
110
                break;
 
111
        case HDR_BERESP:
 
112
                hp = sp->wrk->beresp;
106
113
                break;
107
114
        case HDR_RESP:
108
 
                hp = sp->http;
 
115
                hp = sp->wrk->resp;
109
116
                break;
110
117
        case HDR_OBJ:
111
118
                hp = sp->obj->http;
149
156
                if (b + x < e)
150
157
                        memcpy(b, h, x);
151
158
                b += x;
152
 
                if (b + 1 < e)
153
 
                        *b++ = ' ';
 
159
                if (b < e)
 
160
                        *b = ' ';
 
161
                b++;
154
162
        }
155
 
        while (p != vrt_magic_string_end) {
 
163
        while (p != vrt_magic_string_end && b < e) {
156
164
                if (p == NULL)
157
165
                        p = "(null)";
158
166
                x = strlen(p);
161
169
                b += x;
162
170
                p = va_arg(ap, const char *);
163
171
        }
164
 
        if (b + 1 < e)
165
 
                *b++ = '\0';
 
172
        if (b < e)
 
173
                *b = '\0';
 
174
        b++;
166
175
        if (b > e) {
167
176
                WS_Release(hp->ws, 0);
168
177
                return (NULL);
244
253
VRT_DO_HDR(req,   request,      sp->http,               HTTP_HDR_REQ)
245
254
VRT_DO_HDR(req,   url,          sp->http,               HTTP_HDR_URL)
246
255
VRT_DO_HDR(req,   proto,        sp->http,               HTTP_HDR_PROTO)
247
 
VRT_DO_HDR(bereq, request,      sp->bereq->http,        HTTP_HDR_REQ)
248
 
VRT_DO_HDR(bereq, url,          sp->bereq->http,        HTTP_HDR_URL)
249
 
VRT_DO_HDR(bereq, proto,        sp->bereq->http,        HTTP_HDR_PROTO)
 
256
VRT_DO_HDR(bereq, request,      sp->wrk->bereq,         HTTP_HDR_REQ)
 
257
VRT_DO_HDR(bereq, url,          sp->wrk->bereq,         HTTP_HDR_URL)
 
258
VRT_DO_HDR(bereq, proto,        sp->wrk->bereq,         HTTP_HDR_PROTO)
250
259
VRT_DO_HDR(obj,   proto,        sp->obj->http,          HTTP_HDR_PROTO)
251
260
VRT_DO_HDR(obj,   response,     sp->obj->http,          HTTP_HDR_RESPONSE)
252
 
VRT_DO_HDR(resp,  proto,        sp->http,               HTTP_HDR_PROTO)
253
 
VRT_DO_HDR(resp,  response,     sp->http,               HTTP_HDR_RESPONSE)
 
261
VRT_DO_HDR(resp,  proto,        sp->wrk->resp,          HTTP_HDR_PROTO)
 
262
VRT_DO_HDR(resp,  response,     sp->wrk->resp,          HTTP_HDR_RESPONSE)
 
263
VRT_DO_HDR(beresp,  proto,      sp->wrk->beresp,        HTTP_HDR_PROTO)
 
264
VRT_DO_HDR(beresp,  response,   sp->wrk->beresp,        HTTP_HDR_RESPONSE)
254
265
 
255
266
/*--------------------------------------------------------------------*/
256
267
 
270
281
        http_SetH(sp->obj->http, HTTP_HDR_STATUS, p);
271
282
}
272
283
 
 
284
/* Add an objecthead to the saintmode list for the (hopefully) relevant
 
285
 * backend. Some double-up asserting here to avoid assert-errors when there
 
286
 * is no object.
 
287
 */
 
288
void
 
289
VRT_l_beresp_saintmode(const struct sess *sp, double a)
 
290
{
 
291
        struct trouble *new;
 
292
        struct trouble *tr;
 
293
        struct trouble *tr2;
 
294
 
 
295
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
 
296
        if (!sp->vbe)
 
297
                return;
 
298
        CHECK_OBJ_NOTNULL(sp->vbe, VBE_CONN_MAGIC);
 
299
        if (!sp->vbe->backend)
 
300
                return;
 
301
        CHECK_OBJ_NOTNULL(sp->vbe->backend, BACKEND_MAGIC);
 
302
        if (!sp->objhead)
 
303
                return;
 
304
        CHECK_OBJ_NOTNULL(sp->objhead, OBJHEAD_MAGIC);
 
305
 
 
306
        /* Setting a negative holdoff period is a mistake. Detecting this
 
307
         * when compiling the VCL would be better.
 
308
         */
 
309
        assert(a > 0);
 
310
 
 
311
        ALLOC_OBJ(new, TROUBLE_MAGIC);
 
312
        AN(new);
 
313
        new->target = (uintptr_t)sp->objhead;
 
314
        new->timeout = sp->t_req + a;
 
315
 
 
316
        /* Insert the new item on the list before the first item with a
 
317
         * timeout at a later date (ie: sort by which entry will time out
 
318
         * from the list
 
319
         */
 
320
        Lck_Lock(&sp->vbe->backend->mtx);
 
321
        VTAILQ_FOREACH_SAFE(tr, &sp->vbe->backend->troublelist, list, tr2) {
 
322
                if (tr->timeout < new->timeout) {
 
323
                        VTAILQ_INSERT_BEFORE(tr, new, list);
 
324
                        new = NULL;
 
325
                        break;
 
326
                }
 
327
        }
 
328
 
 
329
        /* Insert the item at the end if the list is empty or all other
 
330
         * items have a longer timeout.
 
331
         */
 
332
        if (new)
 
333
                VTAILQ_INSERT_TAIL(&sp->vbe->backend->troublelist, new, list);
 
334
 
 
335
        Lck_Unlock(&sp->vbe->backend->mtx);
 
336
}
 
337
 
273
338
int
274
339
VRT_r_obj_status(const struct sess *sp)
275
340
{
278
343
        /* XXX: use http_GetStatus() */
279
344
        if (sp->obj->http->status)
280
345
                return (sp->obj->http->status);
 
346
        AN(sp->obj->http->hd[HTTP_HDR_STATUS].b);
281
347
        return (atoi(sp->obj->http->hd[HTTP_HDR_STATUS].b));
282
348
}
283
349
 
287
353
        char *p;
288
354
 
289
355
        assert(num >= 100 && num <= 999);
290
 
        p = WS_Alloc(sp->http->ws, 4);
 
356
        p = WS_Alloc(sp->wrk->ws, 4);
291
357
        if (p == NULL)
292
358
                WSP(sp, SLT_LostHeader, "%s", "resp.status");
293
359
        else
294
360
                sprintf(p, "%d", num);
295
 
        http_SetH(sp->http, HTTP_HDR_STATUS, p);
 
361
        http_SetH(sp->wrk->resp, HTTP_HDR_STATUS, p);
296
362
}
297
363
 
298
364
int
299
365
VRT_r_resp_status(const struct sess *sp)
300
366
{
301
367
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
302
 
        CHECK_OBJ_NOTNULL(sp->http, HTTP_MAGIC);
303
 
        return (atoi(sp->http->hd[HTTP_HDR_STATUS].b));
304
 
}
 
368
        CHECK_OBJ_NOTNULL(sp->wrk->resp, HTTP_MAGIC);
 
369
        return (atoi(sp->wrk->resp->hd[HTTP_HDR_STATUS].b));
 
370
}
 
371
 
 
372
/*--------------------------------------------------------------------*/
 
373
 
 
374
#define VBEREQ(dir, type,onm,field)                                     \
 
375
void                                                                    \
 
376
VRT_l_##dir##_##onm(const struct sess *sp, type a)                      \
 
377
{                                                                       \
 
378
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);                              \
 
379
        sp->wrk->field = a;                                             \
 
380
}                                                                       \
 
381
                                                                        \
 
382
type                                                                    \
 
383
VRT_r_##dir##_##onm(const struct sess *sp)                              \
 
384
{                                                                       \
 
385
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);                              \
 
386
        return (sp->wrk->field);                                        \
 
387
}
 
388
 
 
389
VBEREQ(beresp, unsigned, cacheable, cacheable)
 
390
VBEREQ(beresp, double, grace, grace)
 
391
 
 
392
/*--------------------------------------------------------------------
 
393
 * XXX: Working relative to t_req is maybe not the right thing, we could
 
394
 * XXX: have spent a long time talking to the backend since then.
 
395
 * XXX: It might make sense to cache a timestamp as "current time"
 
396
 * XXX: before vcl_recv (== t_req) and vcl_fetch.
 
397
 * XXX: On the other hand, that might lead to inconsistent behaviour
 
398
 * XXX: where an object expires while we are running VCL code, and
 
399
 * XXX: and that may not be a good idea either.
 
400
 * XXX: See also related t_req use in cache_hash.c
 
401
 */
 
402
 
 
403
void
 
404
VRT_l_beresp_ttl(const struct sess *sp, double a)
 
405
{
 
406
 
 
407
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
 
408
        WSP(sp, SLT_TTL, "%u VCL %.0f %.0f", sp->xid, a, sp->t_req);
 
409
        /*
 
410
         * If people set obj.ttl = 0s, they don't expect it to be cacheable
 
411
         * any longer, but it will still be for up to 1s - epsilon because
 
412
         * of the rounding to seconds.
 
413
         * We special case and make sure that rounding does not surprise.
 
414
         */
 
415
        if (a <= 0)
 
416
                sp->wrk->ttl = sp->t_req - 1;
 
417
        else
 
418
                sp->wrk->ttl = sp->t_req + a;
 
419
}
 
420
 
 
421
double
 
422
VRT_r_beresp_ttl(const struct sess *sp)
 
423
{
 
424
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
 
425
        return (sp->wrk->ttl - sp->t_req);
 
426
}
 
427
 
 
428
void
 
429
VRT_l_beresp_status(const struct sess *sp, int num)
 
430
{
 
431
        char *p;
 
432
 
 
433
        assert(num >= 100 && num <= 999);
 
434
        p = WS_Alloc(sp->wrk->beresp->ws, 4);
 
435
        if (p == NULL)
 
436
                WSP(sp, SLT_LostHeader, "%s", "obj.status");
 
437
        else
 
438
                sprintf(p, "%d", num);
 
439
        http_SetH(sp->wrk->beresp, HTTP_HDR_STATUS, p);
 
440
}
 
441
 
 
442
int
 
443
VRT_r_beresp_status(const struct sess *sp)
 
444
{
 
445
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
 
446
        /* XXX: use http_GetStatus() */
 
447
        if (sp->wrk->beresp->status)
 
448
                return (sp->wrk->beresp->status);
 
449
        AN(sp->wrk->beresp->hd[HTTP_HDR_STATUS].b);
 
450
        return (atoi(sp->wrk->beresp->hd[HTTP_HDR_STATUS].b));
 
451
}
 
452
 
305
453
 
306
454
void
307
455
VRT_l_bereq_connect_timeout(struct sess *sp, double num)
308
456
{
309
457
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
310
 
        sp->connect_timeout = (num > 0 ? num : 0);
 
458
        sp->wrk->connect_timeout = (num > 0 ? num : 0);
311
459
}
312
460
 
313
461
double
314
462
VRT_r_bereq_connect_timeout(struct sess *sp)
315
463
{
316
464
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
317
 
        return sp->connect_timeout;
 
465
        return (sp->wrk->connect_timeout);
318
466
}
319
467
 
320
468
void
321
469
VRT_l_bereq_first_byte_timeout(struct sess *sp, double num)
322
470
{
323
471
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
324
 
        sp->first_byte_timeout = (num > 0 ? num : 0);
 
472
        sp->wrk->first_byte_timeout = (num > 0 ? num : 0);
325
473
}
326
474
 
327
475
double
328
476
VRT_r_bereq_first_byte_timeout(struct sess *sp)
329
477
{
330
478
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
331
 
        return sp->first_byte_timeout;
 
479
        return (sp->wrk->first_byte_timeout);
332
480
}
333
481
 
334
482
void
335
483
VRT_l_bereq_between_bytes_timeout(struct sess *sp, double num)
336
484
{
337
485
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
338
 
        sp->between_bytes_timeout = (num > 0 ? num : 0);
 
486
        sp->wrk->between_bytes_timeout = (num > 0 ? num : 0);
339
487
}
340
488
 
341
489
double
342
490
VRT_r_bereq_between_bytes_timeout(struct sess *sp)
343
491
{
344
492
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
345
 
        return sp->between_bytes_timeout;
 
493
        return (sp->wrk->between_bytes_timeout);
346
494
}
347
495
 
348
496
/*--------------------------------------------------------------------*/
373
521
 
374
522
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
375
523
        CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);       /* XXX */
 
524
        if (sp->obj->objcore == NULL)
 
525
                return;
376
526
        WSP(sp, SLT_TTL, "%u VCL %.0f %.0f",
377
527
            sp->obj->xid, a, sp->t_req);
378
528
        /*
393
543
{
394
544
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
395
545
        CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);       /* XXX */
 
546
        if (sp->obj->objcore == NULL)
 
547
                return (0.0);
396
548
        return (sp->obj->ttl - sp->t_req);
397
549
}
398
550
 
424
576
 
425
577
/*--------------------------------------------------------------------*/
426
578
 
427
 
/* XXX: the VCL_info messages has unexpected fractions on the ttl */
428
 
 
429
 
void
430
 
VRT_l_obj_prefetch(const struct sess *sp, double a)
431
 
{
432
 
 
433
 
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
434
 
        CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);       /* XXX */
435
 
        sp->obj->prefetch = 0.0;
436
 
        if (a == 0.0)
437
 
                sp->obj->prefetch = a;
438
 
        else if (a > 0.0 && a + sp->t_req <= sp->obj->ttl)
439
 
                sp->obj->prefetch = a + sp->t_req;
440
 
        else if (a < 0.0 && a + sp->obj->ttl > sp->t_req)
441
 
                sp->obj->prefetch = a;
442
 
        else if (a > 0.0)
443
 
                WSL(sp->wrk, SLT_VCL_info, sp->id,
444
 
                    "XID %u: obj.prefetch (%g) after TTL (%g), ignored.",
445
 
                    sp->obj->xid, a, sp->obj->ttl - sp->t_req);
446
 
        else /* if (a < 0.0) */
447
 
                WSL(sp->wrk, SLT_VCL_info, sp->id,
448
 
                    "XID %u: obj.prefetch (%g) less than ttl (%g), ignored.",
449
 
                    sp->obj->xid, a, sp->obj->ttl - sp->t_req);
450
 
        EXP_Rearm(sp->obj);
451
 
}
452
 
 
453
 
double
454
 
VRT_r_obj_prefetch(const struct sess *sp)
455
 
{
456
 
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
457
 
        CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);       /* XXX */
458
 
        return (sp->obj->prefetch - sp->t_req);
459
 
}
460
 
 
461
 
/*--------------------------------------------------------------------*/
462
 
 
463
579
#define VOBJ(type,onm,field)                                            \
464
580
void                                                                    \
465
581
VRT_l_obj_##onm(const struct sess *sp, type a)                          \
594
710
 
595
711
        if (heritage.identity[0] != '\0')
596
712
                return heritage.identity;
597
 
        else 
 
713
        else
598
714
                return heritage.name;
599
715
}
600
716
 
605
721
        (void)sp;
606
722
 
607
723
        if (vrt_hostname[0] == '\0')
608
 
                gethostname(vrt_hostname, 255);
609
 
        
610
 
        return (const char*) &vrt_hostname;
 
724
                AZ(gethostname(vrt_hostname, 255));
 
725
 
 
726
        return (vrt_hostname);
611
727
}
612
728
 
613
729
int
663
779
        return (TIM_real() - sp->obj->last_use);
664
780
}
665
781
 
666
 
const char *
667
 
VRT_r_obj_hash(const struct sess *sp)
668
 
{
669
 
 
670
 
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
671
 
        if (sp->obj == NULL)
672
 
                return (NULL);
673
 
        CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
674
 
        if (sp->obj->objhead == NULL)
675
 
                return (NULL);
676
 
        CHECK_OBJ_NOTNULL(sp->obj->objhead, OBJHEAD_MAGIC);
677
 
        return (sp->obj->objhead->hash);
678
 
}
679
 
 
680
782
unsigned
681
783
VRT_r_req_backend_healthy(const struct sess *sp)
682
784
{
683
785
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
684
786
        CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
685
 
        return (sp->director->healthy(sp));
 
787
        return (VBE_Healthy_sp(sp, sp->director));
686
788
}
687
789
 
688
790
/*--------------------------------------------------------------------*/
740
842
        return (p);
741
843
}
742
844
 
 
845
char *
 
846
VRT_time_string(const struct sess *sp, double t)
 
847
{
 
848
        char *p;
 
849
 
 
850
        AN(p = WS_Alloc(sp->http->ws, TIM_FORMAT_SIZE));
 
851
        TIM_format(t, p);
 
852
        return p;
 
853
}
 
854
 
743
855
const char *
744
856
VRT_backend_string(struct sess *sp)
745
857
{
761
873
 
762
874
/*--------------------------------------------------------------------*/
763
875
 
 
876
void
 
877
VRT_ESI(struct sess *sp)
 
878
{
 
879
 
 
880
        if (sp->cur_method != VCL_MET_FETCH) {
 
881
                /* XXX: we should catch this at compile time */
 
882
                WSP(sp, SLT_VCL_error,
 
883
                    "esi can only be called from vcl_fetch");
 
884
                return;
 
885
        }
 
886
 
 
887
        sp->wrk->do_esi = 1;
 
888
}
 
889
 
 
890
/*--------------------------------------------------------------------*/
 
891
 
764
892
/*lint -e{818} sp could be const */
765
893
void
766
894
VRT_panic(struct sess *sp, const char *str, ...)
834
962
                a1 = va_arg(ap, char *);
835
963
                good = 1;
836
964
        }
837
 
        if (!good) 
 
965
        if (!good)
838
966
                /* XXX: report error how ? */
839
967
                BAN_Free(b);
840
968
        else
844
972
/*--------------------------------------------------------------------*/
845
973
 
846
974
void
847
 
VRT_purge_string(struct sess *sp, char *str, ...)
 
975
VRT_purge_string(struct sess *sp, const char *str, ...)
848
976
{
849
977
        char *p, *a1, *a2, *a3;
850
978
        char **av;
887
1015
                if (strcmp(av[i++], "&&"))
888
1016
                        break;
889
1017
        }
890
 
        if (!good) 
 
1018
        if (!good)
891
1019
                /* XXX: report error how ? */
892
1020
                BAN_Free(b);
893
1021
        else
914
1042
        (void)memmove(dst, src, len);
915
1043
}
916
1044
 
 
1045
/*lint -restore */