]> err.no Git - varnish/commitdiff
Go over the simple backend and make it more readable.
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Thu, 20 Sep 2007 08:16:01 +0000 (08:16 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Thu, 20 Sep 2007 08:16:01 +0000 (08:16 +0000)
git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@1964 d4fa192b-c00b-0410-8231-f00ffab90ce4

varnish-cache/bin/varnishd/cache_backend_simple.c

index 1822d5ddf5de30849517c1c9855ff72d293aa5ee..ffb71547118044ab9be5c0fb466a4ef2ad736801 100644 (file)
  *
  * $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 <sys/types.h>
@@ -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;
 }