From: phk Date: Thu, 20 Sep 2007 08:16:01 +0000 (+0000) Subject: Go over the simple backend and make it more readable. X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=79e1b8c36ef17418d8a6d39136145efa641c199c;p=varnish Go over the simple backend and make it more readable. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@1964 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/varnish-cache/bin/varnishd/cache_backend_simple.c b/varnish-cache/bin/varnishd/cache_backend_simple.c index 1822d5dd..ffb71547 100644 --- a/varnish-cache/bin/varnishd/cache_backend_simple.c +++ b/varnish-cache/bin/varnishd/cache_backend_simple.c @@ -28,10 +28,6 @@ * * $Id$ * - * - * XXX: When we switch VCL we can have vbe_conn's dangling from - * XXX: the backends no longer used. When the VCL's refcount - * XXX: drops to zero we should zap them. */ #include @@ -62,64 +58,97 @@ struct bes { TAILQ_HEAD(, vbe_conn) connlist; }; -/*--------------------------------------------------------------------*/ - +/*-------------------------------------------------------------------- + * Try to get a socket connected to one of the addresses on the list. + * We start from the cached "last good" address and try all items on + * the list exactly once. + * If a new DNS lookup is made while we try, we start over and try the + * new list exactly once. + */ static int bes_conn_try_list(struct sess *sp, struct bes *bes) { struct addrinfo *ai, *from; - struct sockaddr_storage ss; - int fam, sockt, proto; - socklen_t alen; int s, loops; - char abuf1[TCP_ADDRBUFSIZE], abuf2[TCP_ADDRBUFSIZE]; - char pbuf1[TCP_PORTBUFSIZE], pbuf2[TCP_PORTBUFSIZE]; unsigned myseq; + CHECK_OBJ_NOTNULL(bes, BES_MAGIC); + if (bes->addr == NULL) + return (-1); + AN(bes->last_addr); + /* Called with lock held */ myseq = bes->dnsseq; loops = 0; - from = bes->last_addr; - for (ai = from; ai != NULL && (loops != 1 || ai != from);) { - fam = ai->ai_family; - sockt = ai->ai_socktype; - proto = ai->ai_protocol; - alen = ai->ai_addrlen; - assert(alen <= sizeof ss); - memcpy(&ss, ai->ai_addr, alen); - UNLOCK(&sp->backend->mtx); - s = socket(fam, sockt, proto); - if (s >= 0 && connect(s, (void *)&ss, alen)) { - AZ(close(s)); - s = -1; - } - if (s >= 0) { - TCP_myname(s, abuf1, sizeof abuf1, pbuf1, sizeof pbuf1); - TCP_name((void*)&ss, alen, - abuf2, sizeof abuf2, pbuf2, sizeof pbuf2); - WSL(sp->wrk, SLT_BackendOpen, s, "%s %s %s %s %s", - sp->backend->vcl_name, abuf1, pbuf1, abuf2, pbuf2); - } - LOCK(&sp->backend->mtx); - if (s >= 0) { + ai = from = bes->last_addr; + while (1) { + + /* NB: releases/acquires lock */ + s = VBE_TryConnect(sp, ai); + + if (s >= 0) { + /* Update cached "last good" if still valid */ if (myseq == bes->dnsseq) bes->last_addr = ai; return (s); } + if (myseq != bes->dnsseq) { + /* A DNS-lookup happended, try again from start */ loops = 0; from = bes->last_addr; ai = from; } else { + /* Try next one */ ai = ai->ai_next; if (ai == NULL) { loops++; ai = bes->addr; } } + if (loops == 1 && ai == from) + return (-1); } - return (-1); +} + +/*--------------------------------------------------------------------*/ + +static const char * +bes_dns_lookup(struct backend *bp) +{ + struct addrinfo *res, hint, *old; + struct bes *bes; + int error; + + CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC); + CAST_OBJ_NOTNULL(bes, bp->priv, BES_MAGIC); + + bes->dnstime = TIM_mono(); + + /* Let go of lock while we do sleepable stuff */ + UNLOCK(&bp->mtx); + + memset(&hint, 0, sizeof hint); + hint.ai_family = PF_UNSPEC; + hint.ai_socktype = SOCK_STREAM; + res = NULL; + error = getaddrinfo(bes->hostname, + bes->portname == NULL ? "http" : bes->portname, + &hint, &res); + LOCK(&bp->mtx); + if (error) { + if (res != NULL) + freeaddrinfo(res); + return(gai_strerror(error)); + } + bes->dnsseq++; + old = bes->addr; + bes->last_addr = res; + bes->addr = res; + if (old != NULL) + freeaddrinfo(old); + return (NULL); } /*--------------------------------------------------------------------*/ @@ -129,8 +158,6 @@ bes_conn_try(struct sess *sp, struct backend *bp) { int s; struct bes *bes; - struct addrinfo *res, hint, *old; - int error; CAST_OBJ_NOTNULL(bes, bp->priv, BES_MAGIC); @@ -148,31 +175,7 @@ bes_conn_try(struct sess *sp, struct backend *bp) return (-1); } - /* Then do another lookup to catch DNS changes */ - bes->dnstime = TIM_mono(); - UNLOCK(&bp->mtx); - - memset(&hint, 0, sizeof hint); - hint.ai_family = PF_UNSPEC; - hint.ai_socktype = SOCK_STREAM; - res = NULL; - error = getaddrinfo(bes->hostname, - bes->portname == NULL ? "http" : bes->portname, - &hint, &res); - if (error) { - if (res != NULL) - freeaddrinfo(res); - printf("getaddrinfo: %s\n", gai_strerror(error)); /* XXX */ - LOCK(&bp->mtx); - } else { - LOCK(&bp->mtx); - bes->dnsseq++; - old = bes->addr; - bes->last_addr = res; - bes->addr = res; - if (old != NULL) - freeaddrinfo(old); - } + (void)bes_dns_lookup(bp); /* And try the entire list */ s = bes_conn_try_list(sp, bes); @@ -363,6 +366,7 @@ VRT_init_simple_backend(struct backend **bp, struct vrt_simple_backend *t) { struct backend *b; struct bes *bes; + const char *p; /* * Scan existing backends to see if we can recycle one of them. @@ -402,5 +406,16 @@ VRT_init_simple_backend(struct backend **bp, struct vrt_simple_backend *t) AN(t->host); REPLACE(bes->hostname, t->host); + /* + * The VCL compiler already did a lookup, but we'll do another one + * here, just in case... + */ + LOCK(&b->mtx); + p = bes_dns_lookup(b); + UNLOCK(&b->mtx); + if (p != NULL) + printf("Warning: could not lookup backend %s (%s:%s): %s", + t->name, t->host, t->port, p); + *bp = b; }