source: bin/varnishd/cache_vrt.c @ dd076c2

Revision dd076c2, 11.8 KB checked in by Poul-Henning Kamp <phk@…>, 7 years ago (diff)

Privatize the "simple" aspect of the simple backend.

Move the VRT initializer for simple backends home.

Add a backend method to get hostname. This may be a hack.

Move fields private to "simple" to its private structure.

Add cleanup method to backend, so we can collect the garbage.

git-svn-id:  http://www.varnish-cache.org/svn/trunk/varnish-cache@1895 d4fa192b-c00b-0410-8231-f00ffab90ce4

  • Property mode set to 100644
Line 
1/*-
2 * Copyright (c) 2006 Verdens Gang AS
3 * Copyright (c) 2006-2007 Linpro 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 * $Id$
30 *
31 * Runtime support for compiled VCL programs
32 */
33
34#include <sys/types.h>
35#include <sys/socket.h>
36
37#include <netinet/in.h>
38
39#include <stdio.h>
40#include <string.h>
41#include <stdlib.h>
42#include <stdarg.h>
43
44#include "shmlog.h"
45#include "heritage.h"
46#include "vrt.h"
47#include "vrt_obj.h"
48#include "vcl.h"
49#include "cache.h"
50
51/*--------------------------------------------------------------------*/
52
53void
54VRT_error(struct sess *sp, unsigned code, const char *reason)
55{
56
57        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
58        WSL(sp->wrk, SLT_Debug, 0, "VCL_error(%u, %s)", code, reason);
59        sp->err_code = code;
60        sp->err_reason = reason;
61}
62
63/*--------------------------------------------------------------------*/
64
65void
66VRT_count(struct sess *sp, unsigned u)
67{
68
69        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
70        if (params->vcl_trace)
71                WSL(sp->wrk, SLT_VCL_trace, sp->fd, "%u %d.%d", u,
72                    sp->vcl->ref[u].line, sp->vcl->ref[u].pos);
73}
74
75/*--------------------------------------------------------------------*/
76
77static struct http *
78vrt_selecthttp(struct sess *sp, enum gethdr_e where)
79{
80        struct http *hp;
81
82        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
83        switch (where) {
84        case HDR_REQ:
85                hp = sp->http;
86                break;
87        case HDR_BEREQ:
88                hp = sp->bereq->http;
89                break;
90        case HDR_RESP:
91                hp = sp->http;
92                break;
93        case HDR_OBJ:
94                hp = &sp->obj->http;
95                break;
96        default:
97                INCOMPL();
98        }
99        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
100        return (hp);
101}
102
103char *
104VRT_GetHdr(struct sess *sp, enum gethdr_e where, const char *n)
105{
106        char *p;
107        struct http *hp;
108
109        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
110        hp = vrt_selecthttp(sp, where);
111        if (!http_GetHdr(hp, n, &p))
112                return (NULL);
113        return (p);
114}
115
116/*--------------------------------------------------------------------*/
117
118static char *
119vrt_assemble_string(struct http *hp, const char *h, const char *p, va_list ap)
120{
121        char *b, *e;
122        unsigned u, x;
123
124        u = WS_Reserve(hp->ws, 0);
125        e = b = hp->ws->f;
126        e += u;
127        if (h != NULL) {
128                x = strlen(h);
129                if (b + x < e)
130                        memcpy(b, h, x);
131                b += x;
132                if (b + 1 < e) 
133                        *b++ = ' ';
134        }
135        while (p != NULL) {
136                x = strlen(p);
137                if (b + x < e)
138                        memcpy(b, p, x);
139                b += x;
140                p = va_arg(ap, const char *);
141        }
142        if (b + 1 < e) 
143                *b++ = '\0';
144        if (b > e) {
145                WS_Release(hp->ws, 0);
146                return (NULL);
147        } else {
148                e = b;
149                b = hp->ws->f;
150                WS_Release(hp->ws, 1 + e - b);
151                return (b);
152        }
153}
154
155/*--------------------------------------------------------------------*/
156
157void
158VRT_SetHdr(struct sess *sp , enum gethdr_e where, const char *hdr, const char *p, ...)
159{
160        struct http *hp;
161        va_list ap;
162        char *b;
163
164        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
165        hp = vrt_selecthttp(sp, where);
166        va_start(ap, p);
167        if (p == NULL) {
168                http_Unset(hp, hdr);
169        } else {
170                b = vrt_assemble_string(hp, hdr + 1, p, ap);
171                if (b == NULL) {
172                        VSL(SLT_LostHeader, sp->fd, hdr + 1);
173                } else {
174                        http_Unset(hp, hdr);
175                        http_SetHeader(sp->wrk, sp->fd, hp, b);
176                }
177        }
178        va_end(ap);
179}
180
181/*--------------------------------------------------------------------*/
182
183static void
184vrt_do_string(struct worker *w, int fd, struct http *hp, int fld, const char *err, const char *p, va_list ap)
185{
186        char *b;
187
188        AN(p);
189        AN(hp);
190        b = vrt_assemble_string(hp, NULL, p, ap);
191        if (b == NULL) {
192                WSL(w, SLT_LostHeader, fd, err);
193        } else {
194                http_SetH(hp, fld, b);
195        }
196        va_end(ap);
197}
198
199#define VRT_DO_HDR(obj, hdr, http, fld)                         \
200void                                                            \
201VRT_l_##obj##_##hdr(struct sess *sp, const char *p, ...)        \
202{                                                               \
203        va_list ap;                                             \
204                                                                \
205        AN(p);                                                  \
206        va_start(ap, p);                                        \
207        vrt_do_string(sp->wrk, sp->fd,                          \
208            http, fld, #obj "." #hdr, p, ap);                   \
209        va_end(ap);                                             \
210}
211
212VRT_DO_HDR(req,   request,      sp->http,               HTTP_HDR_REQ)
213VRT_DO_HDR(req,   url,          sp->http,               HTTP_HDR_URL)
214VRT_DO_HDR(req,   proto,        sp->http,               HTTP_HDR_PROTO)
215VRT_DO_HDR(bereq, request,      sp->bereq->http,        HTTP_HDR_REQ)
216VRT_DO_HDR(bereq, url,          sp->bereq->http,        HTTP_HDR_URL)
217VRT_DO_HDR(bereq, proto,        sp->bereq->http,        HTTP_HDR_PROTO)
218VRT_DO_HDR(obj,   proto,        &sp->obj->http,         HTTP_HDR_PROTO)
219VRT_DO_HDR(obj,   response,     &sp->obj->http,         HTTP_HDR_RESPONSE)
220VRT_DO_HDR(resp,  proto,        sp->http,               HTTP_HDR_PROTO)
221VRT_DO_HDR(resp,  response,     sp->http,               HTTP_HDR_RESPONSE)
222
223void
224VRT_l_obj_status(struct sess *sp, int num)
225{
226        char *p;
227
228        assert(num >= 100 && num <= 999);
229        p = WS_Alloc(sp->obj->http.ws, 4);
230        if (p == NULL)
231                WSL(sp->wrk, SLT_LostHeader, sp->fd, "obj.status");
232        else
233                sprintf(p, "%d", num);
234        http_SetH(&sp->obj->http, HTTP_HDR_STATUS, p);
235}
236
237int
238VRT_r_obj_status(struct sess *sp)
239{
240        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
241        CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
242        return (atoi(sp->obj->http.hd[HTTP_HDR_STATUS].b));
243}
244
245void
246VRT_l_resp_status(struct sess *sp, int num)
247{
248        char *p;
249
250        assert(num >= 100 && num <= 999);
251        p = WS_Alloc(sp->http->ws, 4);
252        if (p == NULL)
253                WSL(sp->wrk, SLT_LostHeader, sp->fd, "resp.status");
254        else
255                sprintf(p, "%d", num);
256        http_SetH(sp->http, HTTP_HDR_STATUS, p);
257}
258
259/*--------------------------------------------------------------------*/
260
261void
262VRT_handling(struct sess *sp, unsigned hand)
263{
264
265        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
266        assert(!(hand & (hand -1)));    /* must be power of two */
267        sp->handling = hand;
268}
269
270/*--------------------------------------------------------------------
271 * XXX: Working relative to t_req is maybe not the right thing, we could
272 * XXX: have spent a long time talking to the backend since then.
273 * XXX: It might make sense to cache a timestamp as "current time"
274 * XXX: before vcl_recv (== t_req) and vcl_fetch.
275 * XXX: On the other hand, that might lead to inconsistent behaviour
276 * XXX: where an object expires while we are running VCL code, and
277 * XXX: and that may not be a good idea either.
278 * XXX: See also related t_req use in cache_hash.c
279 */
280
281void
282VRT_l_obj_ttl(struct sess *sp, double a)
283{
284
285        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
286        CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);       /* XXX */
287        WSL(sp->wrk, SLT_TTL, sp->fd, "%u VCL %.0f %.0f",
288            sp->obj->xid, a, sp->t_req);
289        if (a < 0)
290                a = 0;
291        sp->obj->ttl = sp->t_req + a;
292        if (sp->obj->heap_idx != 0)
293                EXP_TTLchange(sp->obj);
294}
295
296double
297VRT_r_obj_ttl(struct sess *sp)
298{
299        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
300        CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);       /* XXX */
301        return (sp->obj->ttl - sp->t_req);
302}
303
304/*--------------------------------------------------------------------*/
305
306#define VOBJ(type,onm,field)                                            \
307void                                                                    \
308VRT_l_obj_##onm(struct sess *sp, type a)                                \
309{                                                                       \
310        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);                              \
311        CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);       /* XXX */       \
312        sp->obj->field = a;                                             \
313}                                                                       \
314                                                                        \
315type                                                                    \
316VRT_r_obj_##onm(struct sess *sp)                                        \
317{                                                                       \
318        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);                              \
319        CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);       /* XXX */       \
320        return (sp->obj->field);                                        \
321}
322
323VOBJ(unsigned, valid, valid)
324VOBJ(unsigned, cacheable, cacheable)
325
326/*--------------------------------------------------------------------*/
327
328void
329VRT_l_req_backend(struct sess *sp, struct backend *be)
330{
331        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
332        sp->backend = be;
333}
334
335struct backend *
336VRT_r_req_backend(struct sess *sp)
337{
338        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
339        return (sp->backend);
340}
341
342/*--------------------------------------------------------------------*/
343
344#define  VREQ(n1, n2)                                   \
345const char *                                            \
346VRT_r_req_##n1(struct sess *sp)                         \
347{                                                       \
348        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);              \
349        CHECK_OBJ_NOTNULL(sp->http, HTTP_MAGIC);        \
350        return (sp->http->hd[n2].b);                    \
351}
352
353VREQ(request, HTTP_HDR_REQ)
354VREQ(url, HTTP_HDR_URL)
355VREQ(proto, HTTP_HDR_PROTO)
356
357/*--------------------------------------------------------------------*/
358
359const char *
360VRT_r_resp_proto(struct sess *sp)
361{
362        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
363        CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
364        return (sp->obj->http.hd[HTTP_HDR_PROTO].b);
365}
366
367const char *
368VRT_r_resp_response(struct sess *sp)
369{
370        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
371        CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
372        return (sp->obj->http.hd[HTTP_HDR_RESPONSE].b);
373}
374
375int
376VRT_r_resp_status(struct sess *sp)
377{
378        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
379        CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
380        return (atoi(sp->obj->http.hd[HTTP_HDR_STATUS].b));
381}
382
383/*--------------------------------------------------------------------*/
384
385struct sockaddr *
386VRT_r_client_ip(struct sess *sp)
387{
388
389        return (sp->sockaddr);
390}
391
392struct sockaddr *
393VRT_r_server_ip(struct sess *sp)
394{
395
396        if (sp->mysockaddr->sa_family == AF_UNSPEC)
397                AZ(getsockname(sp->fd, sp->mysockaddr, &sp->mysockaddrlen));
398
399        return (sp->mysockaddr);
400}
401
402/*--------------------------------------------------------------------
403 * Add an element to the array/list of hash bits.
404 */
405
406void
407VRT_l_req_hash(struct sess *sp, const char *str)
408{
409        int l;
410
411        if (str == NULL)
412                str = "";
413        l = strlen(str);
414
415        /*
416         * XXX: handle this by bouncing sp->vcl->nhashcount when it fails
417         * XXX: and dispose of this request either by reallocating the
418         * XXX: hashptr (if possible) or restarting/error the request
419         */
420        xxxassert(sp->ihashptr < sp->nhashptr);
421
422        sp->hashptr[sp->ihashptr] = str;
423        sp->hashptr[sp->ihashptr + 1] = str + l;
424        sp->ihashptr += 2;
425        sp->lhashptr += l + 1;
426}
427
428/*--------------------------------------------------------------------*/
429
430double
431VRT_r_now(struct sess *sp)
432{
433
434        (void)sp;
435        return (TIM_mono());
436}
437
438double
439VRT_r_obj_lastuse(struct sess *sp)
440{
441
442        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
443        CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);       /* XXX */
444        return (TIM_mono() - sp->obj->lru_stamp);
445}
446
447int
448VRT_r_backend_health(struct sess *sp)
449{
450       
451        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
452        CHECK_OBJ_NOTNULL(sp->backend, BACKEND_MAGIC);
453        return sp->backend->health;
454}
455
456/*--------------------------------------------------------------------*/
457
458char *
459VRT_IP_string(struct sess *sp, struct sockaddr *sa)
460{
461        char h[64], p[8], *q;
462        socklen_t len = 0;
463
464        /* XXX can't rely on sockaddr.sa_len */
465        switch (sa->sa_family) {
466        case AF_INET:
467                len = sizeof(struct sockaddr_in);
468                break;
469        case AF_INET6:
470                len = sizeof(struct sockaddr_in6);
471                break;
472        }
473        XXXAN(len);
474        TCP_name(sa, len, h, sizeof h, p, sizeof p);
475        q = WS_Alloc(sp->http->ws, strlen(h) + strlen(p) + 2);
476        AN(q);
477        strcpy(q, h);
478        strcat(q, ":");
479        strcat(q, p);
480        return (q);
481}
482
483char *
484VRT_int_string(struct sess *sp, int num)
485{
486        char *p;
487        int size = 10;
488       
489        p = WS_Alloc(sp->http->ws, size);
490        AN(p);
491        snprintf(p, size, "%d", num);
492        return (p);
493}
494
495/*--------------------------------------------------------------------*/
496
497void
498VRT_purge(const char *regexp, int hash)
499{
500       
501        AddBan(regexp, hash);
502}
503
504/*--------------------------------------------------------------------
505 * Simple stuff
506 */
507
508int
509VRT_strcmp(const char *s1, const char *s2)
510{
511        return (strcmp(s1, s2));
512}
513
514
515/*--------------------------------------------------------------------
516 * Backend stuff
517 */
518
519void
520VRT_fini_backend(struct backend *b)
521{
522
523        VBE_DropRef(b); 
524}
Note: See TracBrowser for help on using the repository browser.