From phk at projects.linpro.no Mon May 1 07:53:21 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 1 May 2006 09:53:21 +0200 (CEST) Subject: r157 - trunk/varnish-cache/bin/varnishd Message-ID: <20060501075321.242E61ED6CE@projects.linpro.no> Author: phk Date: 2006-05-01 09:53:21 +0200 (Mon, 01 May 2006) New Revision: 157 Modified: trunk/varnish-cache/bin/varnishd/cache_fetch.c Log: Centralize "Connection: close" handling from the backend. Loop until we have the entire chunk in chunked encoding Modified: trunk/varnish-cache/bin/varnishd/cache_fetch.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-04-25 09:32:14 UTC (rev 156) +++ trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-05-01 07:53:21 UTC (rev 157) @@ -67,13 +67,8 @@ assert(i == st->len); hash->deref(sp->obj); + return (0); - if (http_GetHdr(sp->http, "Connection", &b) && - !strcasecmp(b, "close")) { - return (1); - } else { - return (0); - } } static int @@ -130,11 +125,13 @@ p += e - b; u -= e - b; } - if (u > 0) { + while (u > 0) { i = read(fd, p, u); + assert(i > 0); + u -= i; + p += i; if (0) printf("u = %u i = %d\n", u, i); - assert(i == u); } if (0) printf("Store:\n%#H\n", st->ptr, st->len); @@ -151,12 +148,7 @@ hash->deref(sp->obj); - if (http_GetHdr(sp->http, "Connection", &b) && - !strcasecmp(b, "close")) { - return (1); - } else { - return (0); - } + return (0); } /*--------------------------------------------------------------------*/ @@ -208,6 +200,9 @@ cls = 0; } + if (http_GetHdr(hp, "Connection", &b) && !strcasecmp(b, "close")) + cls = 1; + if (cls) VBE_ClosedFd(fd_token); else From phk at projects.linpro.no Mon May 1 07:54:13 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 1 May 2006 09:54:13 +0200 (CEST) Subject: r158 - trunk/varnish-cache/bin/varnishd Message-ID: <20060501075413.6697C1ED6D3@projects.linpro.no> Author: phk Date: 2006-05-01 09:54:13 +0200 (Mon, 01 May 2006) New Revision: 158 Modified: trunk/varnish-cache/bin/varnishd/cache_backend.c Log: Add yet another thread with an event engine to monitor idle backend connections and clean them out if the backend closes. Modified: trunk/varnish-cache/bin/varnishd/cache_backend.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_backend.c 2006-05-01 07:53:21 UTC (rev 157) +++ trunk/varnish-cache/bin/varnishd/cache_backend.c 2006-05-01 07:54:13 UTC (rev 158) @@ -1,5 +1,25 @@ /* * $Id$ + * + * Manage backend connections. + * + * For each backend ip number we maintain a shadow backend structure so + * that backend connections can be reused across VCL changes. + * + * For each IP we maintain a list of busy and free backend connections, + * and free connections are monitored to detect if the backend closes + * the connection. + * + * We recycle backend connections in most recently used order to minimize + * the number of open connections to any one backend. + * + * XXX: + * I'm not happy about recycling always going through the monitor thread + * but not doing so is slightly more tricky: A connection might be reused + * several times before the monitor thread got around to it, and it would + * have to double check if it had already armed the event for that connection. + * Hopefully this is nowhere close to a performance issue, but if it is, + * it can be optimized at the expense of more complex code. */ #include @@ -15,24 +35,27 @@ #include #include #include +#include +#include + #include "libvarnish.h" #include "shmlog.h" #include "vcl_lang.h" #include "cache.h" -/* - * The internal backend structure for managing connection pools per - * backend. We need to shadow the backend stucture from the VCL - * in order let connections live across VCL switches. - */ +/* A backend connection */ struct vbe_conn { TAILQ_ENTRY(vbe_conn) list; struct vbe *vbe; int fd; + struct event ev; + int inuse; }; +/* A backend IP */ + struct vbe { unsigned ip; TAILQ_ENTRY(vbe) list; @@ -45,6 +68,10 @@ static pthread_mutex_t vbemtx; +static pthread_t vbe_thread; +static struct event_base *vbe_evb; +static int vbe_pipe[2]; + /*-------------------------------------------------------------------- * XXX: we should not call getaddrinfo() every time, we should cache * and apply round-robin with blacklisting of entries that do not respond @@ -89,44 +116,96 @@ return; } -/*--------------------------------------------------------------------*/ +/*-------------------------------------------------------------------- + * When backend connections have been used, they are passed to us through + * the vbe_pipe. If fd == -1 it has been closed and will be reclaimed, + * otherwise arm an event to monitor if the backend closes and recycle. + */ -int -tst_fd(int fd) +static void +vbe_rdp(int fd, short event __unused, void *arg __unused) { - fd_set r,w,e; + struct vbe_conn *vc; int i; - struct timeval tv; - char c; - FD_ZERO(&r); - FD_ZERO(&w); - FD_ZERO(&e); - FD_SET(fd, &r); - FD_SET(fd, &w); - FD_SET(fd, &e); - tv.tv_sec = 0; - tv.tv_usec = 0; - i = select(fd + 1, &r, &w, &e, &tv); - printf("tst_fd fd %d i %d flag %d/%d/%d\n", - fd, i, FD_ISSET(fd, &r), FD_ISSET(fd, &w), FD_ISSET(fd, &e)); - if (FD_ISSET(fd, &r)) { - i = read(fd, &c, 1); - if (i == 0) - return (1); + i = read(fd, &vc, sizeof vc); + assert(i == sizeof vc); + AZ(pthread_mutex_lock(&vbemtx)); + TAILQ_REMOVE(&vc->vbe->bconn, vc, list); + if (vc->fd < 0) { + free(vc); + } else { + vc->inuse = 0; + event_add(&vc->ev, NULL); + TAILQ_INSERT_HEAD(&vc->vbe->fconn, vc, list); } - return (0); + AZ(pthread_mutex_unlock(&vbemtx)); } -/*--------------------------------------------------------------------*/ +/*-------------------------------------------------------------------- + * A backend connection became ready. This can happen if it was reused + * in which case we unarm the event and get out of the way, or if the + * backend closed the connection in which case we clean up. + */ +static void +vbe_rdf(int fd, short event __unused, void *arg) +{ + struct vbe_conn *vc; + int j; + + vc = arg; + AZ(pthread_mutex_lock(&vbemtx)); + if (vc->inuse) { + event_del(&vc->ev); + AZ(pthread_mutex_unlock(&vbemtx)); + return; + } + AZ(ioctl(vc->fd, FIONREAD, &j)); + VSL(SLT_BackendClose, vc->fd, "Remote (%d chars)", j); + TAILQ_REMOVE(&vc->vbe->fconn, vc, list); + AZ(pthread_mutex_unlock(&vbemtx)); + event_del(&vc->ev); + close(vc->fd); + free(vc); +} + +/* Backend monitoring thread -----------------------------------------*/ + +static void * +vbe_main(void *priv __unused) +{ + struct event pev; + + vbe_evb = event_init(); + assert(vbe_evb != NULL); + + AZ(pipe(vbe_pipe)); + + memset(&pev, 0, sizeof pev); + event_set(&pev, vbe_pipe[0], EV_READ | EV_PERSIST, vbe_rdp, NULL); + event_base_set(vbe_evb, &pev); + event_add(&pev, NULL); + + event_base_loop(vbe_evb, 0); + + assert(__LINE__ == 0); + return (NULL); +} + +/* Get a backend connection ------------------------------------------ + * + * First locate the backend shadow, if necessary by creating one. + * If there are free connections, use the first, otherwise build a + * new connection. + */ + int VBE_GetFd(struct backend *bp, void **ptr) { struct vbe *vp; struct vbe_conn *vc; -again: AZ(pthread_mutex_lock(&vbemtx)); vp = bp->vbe; if (vp == NULL) { @@ -146,55 +225,54 @@ /* XXX: check nconn vs backend->maxcon */ vc = TAILQ_FIRST(&vp->fconn); if (vc != NULL) { + vc->inuse = 1; TAILQ_REMOVE(&vp->fconn, vc, list); TAILQ_INSERT_TAIL(&vp->bconn, vc, list); AZ(pthread_mutex_unlock(&vbemtx)); - if (tst_fd(vc->fd)) { - VBE_ClosedFd(vc); - goto again; - } } else { vc = calloc(sizeof *vc, 1); assert(vc != NULL); vc->vbe = vp; vc->fd = -1; + vc->inuse = 1; TAILQ_INSERT_TAIL(&vp->bconn, vc, list); AZ(pthread_mutex_unlock(&vbemtx)); connect_to_backend(vc, bp); + event_set(&vc->ev, vc->fd, EV_READ | EV_PERSIST, vbe_rdf, vc); + event_base_set(vbe_evb, &vc->ev); } *ptr = vc; return (vc->fd); } -/*--------------------------------------------------------------------*/ +/* Close a connection ------------------------------------------------*/ void VBE_ClosedFd(void *ptr) { struct vbe_conn *vc; + int i; vc = ptr; VSL(SLT_BackendClose, vc->fd, ""); close(vc->fd); - AZ(pthread_mutex_lock(&vbemtx)); - TAILQ_REMOVE(&vc->vbe->bconn, vc, list); - AZ(pthread_mutex_unlock(&vbemtx)); - free(vc); + vc->fd = -1; + i = write(vbe_pipe[1], &vc, sizeof vc); + assert(i == sizeof vc); } -/*--------------------------------------------------------------------*/ +/* Recycle a connection ----------------------------------------------*/ void VBE_RecycleFd(void *ptr) { struct vbe_conn *vc; + int i; vc = ptr; VSL(SLT_BackendReuse, vc->fd, ""); - AZ(pthread_mutex_lock(&vbemtx)); - TAILQ_REMOVE(&vc->vbe->bconn, vc, list); - TAILQ_INSERT_HEAD(&vc->vbe->fconn, vc, list); - AZ(pthread_mutex_unlock(&vbemtx)); + i = write(vbe_pipe[1], &vc, sizeof vc); + assert(i == sizeof vc); } /*--------------------------------------------------------------------*/ @@ -204,4 +282,5 @@ { AZ(pthread_mutex_init(&vbemtx, NULL)); + AZ(pthread_create(&vbe_thread, NULL, vbe_main, NULL)); } From phk at projects.linpro.no Mon May 1 10:55:27 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 1 May 2006 12:55:27 +0200 (CEST) Subject: r159 - trunk/varnish-cache/bin/varnishd Message-ID: <20060501105527.DCFDB1ED69E@projects.linpro.no> Author: phk Date: 2006-05-01 12:55:27 +0200 (Mon, 01 May 2006) New Revision: 159 Modified: trunk/varnish-cache/bin/varnishd/cache.h trunk/varnish-cache/bin/varnishd/cache_acceptor.c trunk/varnish-cache/bin/varnishd/cache_fetch.c trunk/varnish-cache/bin/varnishd/cache_http.c trunk/varnish-cache/bin/varnishd/cache_main.c trunk/varnish-cache/bin/varnishd/cache_pass.c trunk/varnish-cache/bin/varnishd/cache_pool.c Log: Add INCOMPL() macro to mark missing code. Add http_HdrIs() to check if we have a given header and if we do if it has a given value. Use it. Ignore SIGPIPE since SO_NOSIGPIPE doesn't work reliably, (but set it on accepted TCP connections anyway). Update passing to match fetching, including a chunked encoding method. Modified: trunk/varnish-cache/bin/varnishd/cache.h =================================================================== --- trunk/varnish-cache/bin/varnishd/cache.h 2006-05-01 07:54:13 UTC (rev 158) +++ trunk/varnish-cache/bin/varnishd/cache.h 2006-05-01 10:55:27 UTC (rev 159) @@ -83,6 +83,7 @@ struct http *http_New(void); void http_Delete(struct http *hp); int http_GetHdr(struct http *hp, const char *hdr, char **ptr); +int http_HdrIs(struct http *hp, const char *hdr, const char *val); int http_GetTail(struct http *hp, unsigned len, char **b, char **e); int http_GetURL(struct http *hp, char **b); void http_RecvHead(struct http *hp, int fd, struct event_base *eb, http_callback_f *func, void *arg); @@ -108,6 +109,10 @@ void VSLR(enum shmlogtag tag, unsigned id, const char *b, const char *e); void VSL(enum shmlogtag tag, unsigned id, const char *fmt, ...); #define HERE() VSL(SLT_Debug, 0, "HERE: %s(%d)", __func__, __LINE__) +#define INCOMPL() do { \ + VSL(SLT_Debug, 0, "INCOMPLETE AT: %s(%d)", __func__, __LINE__); \ + assert(__LINE__ == 0); \ + } while (0) #endif /* cache_vcl.c */ Modified: trunk/varnish-cache/bin/varnishd/cache_acceptor.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_acceptor.c 2006-05-01 07:54:13 UTC (rev 158) +++ trunk/varnish-cache/bin/varnishd/cache_acceptor.c 2006-05-01 10:55:27 UTC (rev 159) @@ -58,6 +58,7 @@ struct sockaddr addr; struct sess *sp; char port[10]; + int i; (void)arg; sm = calloc(sizeof *sm, 1); @@ -76,6 +77,8 @@ free(sp); return; } + i = 1; + AZ(setsockopt(sp->fd, SOL_SOCKET, SO_NOSIGPIPE, &i, sizeof i)); AZ(getnameinfo(&addr, l, sp->addr, VCA_ADDRBUFSIZE, port, sizeof port, NI_NUMERICHOST | NI_NUMERICSERV)); Modified: trunk/varnish-cache/bin/varnishd/cache_fetch.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-05-01 07:54:13 UTC (rev 158) +++ trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-05-01 10:55:27 UTC (rev 159) @@ -165,9 +165,7 @@ VSL(SLT_Handling, sp->fd, "Fetch fd %d", fd); hp = http_New(); -HERE(); http_BuildSbuf(1, w->sb, sp->http); -HERE(); i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb)); assert(i == sbuf_len(w->sb)); @@ -190,12 +188,11 @@ assert(sp->handling == HND_Insert); - if (http_GetHdr(hp, "Content-Length", &b)) { + if (http_GetHdr(hp, "Content-Length", &b)) cls = fetch_straight(w, sp, fd, hp, b); - } else if (http_GetHdr(hp, "Transfer-Encoding", &b) && - !strcasecmp(b, "chunked")) { + else if (http_HdrIs(hp, "Transfer-Encoding", "chunked")) cls = fetch_chunked(w, sp, fd, hp); - } else { + else { VSL(SLT_Debug, fd, "No transfer"); cls = 0; } Modified: trunk/varnish-cache/bin/varnishd/cache_http.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_http.c 2006-05-01 07:54:13 UTC (rev 158) +++ trunk/varnish-cache/bin/varnishd/cache_http.c 2006-05-01 10:55:27 UTC (rev 159) @@ -102,6 +102,19 @@ } int +http_HdrIs(struct http *hp, const char *hdr, const char *val) +{ + char *p; + + if (!http_GetHdr(hp, hdr, &p)) + return (0); + assert(p != NULL); + if (!strcasecmp(p, val)) + return (1); + return (0); +} + +int http_GetURL(struct http *hp, char **b) { if (hp->url == NULL) @@ -346,6 +359,7 @@ sbuf_cat(sb, " "); sbuf_cat(sb, hp->proto); } else { + printf("resp = %d\n", resp); assert(resp == 1 || resp == 2); } sbuf_cat(sb, "\r\n"); Modified: trunk/varnish-cache/bin/varnishd/cache_main.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_main.c 2006-05-01 07:54:13 UTC (rev 158) +++ trunk/varnish-cache/bin/varnishd/cache_main.c 2006-05-01 10:55:27 UTC (rev 159) @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -103,6 +104,9 @@ struct cli *cli; int i; + /* XXX: SO_NOSIGPIPE does not work reliably :-( */ + signal(SIGPIPE, SIG_IGN); + setbuf(stdout, NULL); setbuf(stderr, NULL); printf("Child starts\n"); Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-05-01 07:54:13 UTC (rev 158) +++ trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-05-01 10:55:27 UTC (rev 159) @@ -22,25 +22,146 @@ #include "vcl_lang.h" #include "cache.h" + /*--------------------------------------------------------------------*/ + +static int +pass_straight(struct worker *w, struct sess *sp, int fd, struct http *hp, char *bi) +{ + int i, j; + char *b, *e; + off_t cl; + unsigned c; + char buf[BUFSIZ]; + + if (bi != NULL) + cl = strtoumax(bi, NULL, 0); + else + cl = (1<<30); /* XXX */ + + i = fcntl(fd, F_GETFL); /* XXX ? */ + i &= ~O_NONBLOCK; + i = fcntl(fd, F_SETFL, i); + + while (cl != 0) { + c = cl; + if (c > sizeof buf) + c = sizeof buf; + if (http_GetTail(hp, c, &b, &e)) { + i = e - b; + j = write(sp->fd, b, i); + assert(i == j); + cl -= i; + continue; + } + i = read(fd, buf, c); + if (i == 0 && bi == NULL) + return (1); + assert(i > 0); + j = write(sp->fd, buf, i); + assert(i == j); + cl -= i; + } + return (0); +} + + +/*--------------------------------------------------------------------*/ + +static int +pass_chunked(struct worker *w, struct sess *sp, int fd, struct http *hp) +{ + int i, j; + char *b, *q, *e; + char *p; + unsigned u; + char buf[BUFSIZ]; + char *bp, *be; + + i = fcntl(fd, F_GETFL); /* XXX ? */ + i &= ~O_NONBLOCK; + i = fcntl(fd, F_SETFL, i); + + bp = buf; + be = buf + sizeof buf; + p = buf; + while (1) { + if (http_GetTail(hp, be - bp, &b, &e)) { + memcpy(bp, b, e - b); + bp += e - b; + } else { + /* XXX: must be safe from backend */ + i = read(fd, bp, be - bp); + assert(i > 0); + bp += i; + } + /* buffer valid from p to bp */ + + u = strtoul(p, &q, 16); + if (q == NULL || (*q != '\n' && *q != '\r')) { + INCOMPL(); + /* XXX: move bp to buf start, get more */ + } + if (*q == '\r') + q++; + assert(*q == '\n'); + q++; + if (u == 0) + break; + + j = q - p; + i = write(sp->fd, q, j); + assert(i == j); + + p = q; + + while (u > 0) { + j = u; + if (bp == p) { + bp = p = buf; + break; + } + if (bp - p < j) + j = bp - p; + i = write(sp->fd, p, j); + assert(i == j); + p += j; + u -= i; + } + while (u > 0) { + if (http_GetTail(hp, u, &b, &e)) { + j = e - b; + i = write(sp->fd, q, j); + assert(i == j); + u -= j; + } else + break; + } + while (u > 0) { + j = u; + if (j > sizeof buf) + j = sizeof buf; + i = read(fd, buf, j); + assert(i > 0); + j = write(sp->fd, buf, i); + assert(j == i); + u -= i; + } + } + return (0); +} + + +/*--------------------------------------------------------------------*/ void PassSession(struct worker *w, struct sess *sp) { - int fd, i, j; + int fd, i; void *fd_token; - struct sess sp2; - char buf[BUFSIZ]; - off_t cl; + struct http *hp; char *b; + int cls; - if (http_GetHdr(sp->http, "Connection", &b) && !strcmp(b, "close")) { - /* - * If client wants only this one request, piping is safer - * and cheaper - */ - PipeSession(w, sp); - return; - } fd = VBE_GetFd(sp->backend, &fd_token); assert(fd != -1); @@ -50,69 +171,35 @@ /* XXX: copy any contents */ - memset(&sp2, 0, sizeof sp2); - sp2.rd_e = &w->e1; - sp2.fd = fd; /* * XXX: It might be cheaper to avoid the event_engine and simply * XXX: read(2) the header */ - http_RecvHead(sp2.http, sp2.fd, w->eb, NULL, NULL); + hp = http_New(); + http_RecvHead(hp, fd, w->eb, NULL, NULL); event_base_loop(w->eb, 0); - http_Dissect(sp2.http, sp2.fd, 2); + http_Dissect(hp, fd, 2); - http_BuildSbuf(2, w->sb, sp2.http); + http_BuildSbuf(2, w->sb, hp); i = write(sp->fd, sbuf_data(w->sb), sbuf_len(w->sb)); assert(i == sbuf_len(w->sb)); - assert(__LINE__ == 0); - cl = j = 0; - *buf = 0; - -#if 0 - if (sp2.http.H_Content_Length != NULL) { - cl = strtoumax(sp2.http.H_Content_Length, NULL, 0); - i = fcntl(sp2.fd, F_GETFL); - i &= ~O_NONBLOCK; - i = fcntl(sp2.fd, F_SETFL, i); - assert(i != -1); - i = sp2.rcv_len - sp2.rcv_ptr; - if (i > 0) { - j = write(sp->fd, sp2.rcv + sp2.rcv_ptr, i); - assert(j == i); - cl -= i; - sp2.rcv_ptr += i; - } - while (cl > 0) { - j = sizeof buf; - if (j > cl) - j = cl; - i = recv(sp2.fd, buf, j, 0); - assert(i >= 0); - if (i > 0) { - cl -= i; - j = write(sp->fd, buf, i); - assert(j == i); - } else if (i == 0) { - break; - } - } - assert(cl == 0); + if (http_GetHdr(hp, "Content-Length", &b)) + cls = pass_straight(w, sp, fd, hp, b); + else if (http_HdrIs(hp, "Connection", "close")) + cls = pass_straight(w, sp, fd, hp, NULL); + else if (http_HdrIs(hp, "Transfer-Encoding", "chunked")) + cls = pass_chunked(w, sp, fd, hp); + else { + INCOMPL(); + cls = 1; } - if (sp2.http.H_Connection != NULL && - !strcmp(sp2.http.H_Connection, "close")) { - close(fd); + if (http_GetHdr(hp, "Connection", &b) && !strcasecmp(b, "close")) + cls = 1; + + if (cls) VBE_ClosedFd(fd_token); - } else { + else VBE_RecycleFd(fd_token); - } - - /* XXX: this really belongs in the acceptor */ - if (sp->rcv_len > sp->rcv_ptr) - memmove(sp->rcv, sp->rcv + sp->rcv_ptr, - sp->rcv_len - sp->rcv_ptr); - sp->rcv_len -= sp->rcv_ptr; - sp->rcv_ptr = 0; -#endif } Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-05-01 07:54:13 UTC (rev 158) +++ trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-05-01 10:55:27 UTC (rev 159) @@ -126,6 +126,7 @@ sp->handling = HND_Lookup; sp->vcl->recv_func(sp); + sp->handling = HND_Pass; for (done = 0; !done; ) { switch(sp->handling) { From phk at projects.linpro.no Mon May 1 12:27:10 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 1 May 2006 14:27:10 +0200 (CEST) Subject: r160 - trunk/varnish-cache/bin/varnishd Message-ID: <20060501122710.4112D1ED6E5@projects.linpro.no> Author: phk Date: 2006-05-01 14:27:10 +0200 (Mon, 01 May 2006) New Revision: 160 Modified: trunk/varnish-cache/bin/varnishd/cache.h Log: add missing extern Modified: trunk/varnish-cache/bin/varnishd/cache.h =================================================================== --- trunk/varnish-cache/bin/varnishd/cache.h 2006-05-01 10:55:27 UTC (rev 159) +++ trunk/varnish-cache/bin/varnishd/cache.h 2006-05-01 12:27:10 UTC (rev 160) @@ -91,7 +91,7 @@ void http_BuildSbuf(int resp, struct sbuf *sb, struct http *hp); /* cache_main.c */ -pthread_mutex_t sessmtx; +extern pthread_mutex_t sessmtx; /* cache_pass.c */ void PassSession(struct worker *w, struct sess *sp); From phk at projects.linpro.no Mon May 1 12:27:30 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 1 May 2006 14:27:30 +0200 (CEST) Subject: r161 - trunk/varnish-cache/bin/varnishd Message-ID: <20060501122730.4D38F1ED6E9@projects.linpro.no> Author: phk Date: 2006-05-01 14:27:30 +0200 (Mon, 01 May 2006) New Revision: 161 Modified: trunk/varnish-cache/bin/varnishd/cache_backend.c Log: Keep track of how many connections we have open Modified: trunk/varnish-cache/bin/varnishd/cache_backend.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_backend.c 2006-05-01 12:27:10 UTC (rev 160) +++ trunk/varnish-cache/bin/varnishd/cache_backend.c 2006-05-01 12:27:30 UTC (rev 161) @@ -133,6 +133,7 @@ AZ(pthread_mutex_lock(&vbemtx)); TAILQ_REMOVE(&vc->vbe->bconn, vc, list); if (vc->fd < 0) { + vc->vbe->nconn--; free(vc); } else { vc->inuse = 0; @@ -236,6 +237,7 @@ vc->fd = -1; vc->inuse = 1; TAILQ_INSERT_TAIL(&vp->bconn, vc, list); + vp->nconn++; AZ(pthread_mutex_unlock(&vbemtx)); connect_to_backend(vc, bp); event_set(&vc->ev, vc->fd, EV_READ | EV_PERSIST, vbe_rdf, vc); From phk at projects.linpro.no Mon May 1 12:27:51 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 1 May 2006 14:27:51 +0200 (CEST) Subject: r162 - trunk/varnish-cache/bin/varnishd Message-ID: <20060501122751.4639C1ED6E5@projects.linpro.no> Author: phk Date: 2006-05-01 14:27:51 +0200 (Mon, 01 May 2006) New Revision: 162 Modified: trunk/varnish-cache/bin/varnishd/varnishd.c Log: bandaid for name-clash Modified: trunk/varnish-cache/bin/varnishd/varnishd.c =================================================================== --- trunk/varnish-cache/bin/varnishd/varnishd.c 2006-05-01 12:27:30 UTC (rev 161) +++ trunk/varnish-cache/bin/varnishd/varnishd.c 2006-05-01 12:27:51 UTC (rev 162) @@ -138,8 +138,9 @@ "config.load %s %s", av[2], vf); } +/* XXX: m prefix to avoid name clash */ static void -cli_func_config_load(struct cli *cli, char **av, void *priv __unused) +m_cli_func_config_load(struct cli *cli, char **av, void *priv __unused) { char *vf; struct sbuf *sb; @@ -226,7 +227,7 @@ { CLI_URL_QUERY, cli_func_passthrough, NULL }, { CLI_URL_PURGE, cli_func_passthrough, NULL }, { CLI_URL_STATUS, cli_func_passthrough, NULL }, - { CLI_CONFIG_LOAD, cli_func_config_load, NULL }, + { CLI_CONFIG_LOAD, m_cli_func_config_load, NULL }, { CLI_CONFIG_INLINE, cli_func_config_inline, NULL }, { CLI_CONFIG_UNLOAD, cli_func_passthrough, NULL }, { CLI_CONFIG_LIST, cli_func_passthrough, NULL }, From phk at projects.linpro.no Mon May 1 12:28:27 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 1 May 2006 14:28:27 +0200 (CEST) Subject: r163 - trunk/varnish-cache/bin/varnishd Message-ID: <20060501122827.B48471ED6F0@projects.linpro.no> Author: phk Date: 2006-05-01 14:28:27 +0200 (Mon, 01 May 2006) New Revision: 163 Added: trunk/varnish-cache/bin/varnishd/flint.lnt trunk/varnish-cache/bin/varnishd/flint.sh Log: Add FlexeLint files Added: trunk/varnish-cache/bin/varnishd/flint.lnt =================================================================== --- trunk/varnish-cache/bin/varnishd/flint.lnt 2006-05-01 12:27:51 UTC (rev 162) +++ trunk/varnish-cache/bin/varnishd/flint.lnt 2006-05-01 12:28:27 UTC (rev 163) @@ -0,0 +1,44 @@ +-passes=3 + +// Review all below this line + +-printf_code( H, void *, unsigned) +-printf_code( ju, long long unsigned) + +-e763 // Redundant declaration for symbol '...' previously declared + + +-e737 // Loss of sign in promotion from int to unsigned int +-e715 // Symbol 'arg' (line 43) not referenced +-e818 // Pointer parameter '...' could be declared as pointing to const + +-e534 // Ignoring return value of function +-e767 // macro 'LIST_INIT' was defined differently + +-e506 // Constant value boolean +-e527 // Unreachable code at token 'return' +-e732 // Loss of sign (arg. no. 2) (int to unsigned int) +-e774 // Boolean within 'if' always evaluates to False +-e713 // Loss of precision (assignment) (unsigned long long to long long) +-e574 // Signed-unsigned mix with relational + +-e525 // Negative indentation from line 90 +-e539 // Did not expect positive indentation +-e725 // Expected positive indentation from line 136 +-e734 // Loss of precision (assignment) (31 bits to 8 bits) +-e747 // Significant prototype coercion (arg. no. 2) long +-e712 // Loss of precision (assignment) (long long to + + +-e785 // Too few initializers for aggregate + +-e766 // Header file '../../include/libvarnish.h' not used in module + +-e773 // Expression-like macro 'VCL_FARGS' not parenthesized + +-e788 // enum constant 'HND_Unclass' not used within defaulted switch + +-e716 // while(1) ... +-e641 // Converting enum 'cli_status_e' to int + +-e786 // String concatenation within initializer Added: trunk/varnish-cache/bin/varnishd/flint.sh =================================================================== --- trunk/varnish-cache/bin/varnishd/flint.sh 2006-05-01 12:27:51 UTC (rev 162) +++ trunk/varnish-cache/bin/varnishd/flint.sh 2006-05-01 12:28:27 UTC (rev 163) @@ -0,0 +1,9 @@ +#!/bin/sh + +flexelint \ + -I/usr/include \ + -I. \ + -I../../include \ + -I../../contrib/libevent \ + flint.lnt \ + *.c From phk at projects.linpro.no Mon May 1 12:45:20 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 1 May 2006 14:45:20 +0200 (CEST) Subject: r164 - trunk/varnish-cache/bin/varnishd Message-ID: <20060501124520.B859E1ED6F3@projects.linpro.no> Author: phk Date: 2006-05-01 14:45:20 +0200 (Mon, 01 May 2006) New Revision: 164 Modified: trunk/varnish-cache/bin/varnishd/cache.h trunk/varnish-cache/bin/varnishd/cache_acceptor.c Log: Add vca_write() and vca_flush(), two functions which will attempt to use writev() if possible. vca_flush() must be called before any memory previosly given to vca_write is overwritten, and after the last call to vca_write() Modified: trunk/varnish-cache/bin/varnishd/cache.h =================================================================== --- trunk/varnish-cache/bin/varnishd/cache.h 2006-05-01 12:28:27 UTC (rev 163) +++ trunk/varnish-cache/bin/varnishd/cache.h 2006-05-01 12:45:20 UTC (rev 164) @@ -63,6 +63,8 @@ /* cache_acceptor.c */ +void vca_write(struct sess *sp, void *ptr, size_t len); +void vca_flush(struct sess *sp); void *vca_main(void *arg); void vca_retire_session(struct sess *sp); void vca_recycle_session(struct sess *sp); Modified: trunk/varnish-cache/bin/varnishd/cache_acceptor.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_acceptor.c 2006-05-01 12:28:27 UTC (rev 163) +++ trunk/varnish-cache/bin/varnishd/cache_acceptor.c 2006-05-01 12:45:20 UTC (rev 164) @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -32,13 +33,60 @@ static struct event pipe_e; static int pipes[2]; +#define SESS_IOVS 5 + static struct event accept_e[2 * HERITAGE_NSOCKS]; struct sessmem { struct sess s; struct event e; + struct iovec iov[SESS_IOVS]; + int niov; + size_t liov; }; +/*-------------------------------------------------------------------- + * Write data to client + * We try to use writev() if possible in order to minimize number of + * syscalls made and packets sent. It also just might allow the worker + * thread to complete the request without holding stuff locked. + */ + +void +vca_flush(struct sess *sp) +{ + int i; + + if (sp->fd < 0 || sp->mem->niov == 0) + return; + i = writev(sp->fd, sp->mem->iov, sp->mem->niov); + if (i != sp->mem->liov) { + VSL(SLT_SessionClose, sp->fd, "Premature %d of %d", + i, sp->mem->liov); + close(sp->fd); + sp->fd = -1; + } + sp->mem->liov = 0; + sp->mem->niov = 0; +} + +void +vca_write(struct sess *sp, void *ptr, size_t len) +{ + + if (sp->fd < 0 || len == 0) + return; + if (sp->mem->niov == SESS_IOVS) + vca_flush(sp); + if (sp->fd < 0) + return; + sp->mem->iov[sp->mem->niov].iov_base = ptr; + sp->mem->iov[sp->mem->niov++].iov_len = len; + sp->mem->liov += len; +} + +/*--------------------------------------------------------------------*/ + static void pipe_f(int fd, short event, void *arg) { From phk at projects.linpro.no Mon May 1 12:51:48 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 1 May 2006 14:51:48 +0200 (CEST) Subject: r165 - trunk/varnish-cache/bin/varnishd Message-ID: <20060501125148.88D3F1ED6F4@projects.linpro.no> Author: phk Date: 2006-05-01 14:51:48 +0200 (Mon, 01 May 2006) New Revision: 165 Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c Log: Use vca_write/vca_flush Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-05-01 12:45:20 UTC (rev 164) +++ trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-05-01 12:51:48 UTC (rev 165) @@ -28,7 +28,7 @@ static int pass_straight(struct worker *w, struct sess *sp, int fd, struct http *hp, char *bi) { - int i, j; + int i; char *b, *e; off_t cl; unsigned c; @@ -49,8 +49,7 @@ c = sizeof buf; if (http_GetTail(hp, c, &b, &e)) { i = e - b; - j = write(sp->fd, b, i); - assert(i == j); + vca_write(sp, b, i); cl -= i; continue; } @@ -58,8 +57,8 @@ if (i == 0 && bi == NULL) return (1); assert(i > 0); - j = write(sp->fd, buf, i); - assert(i == j); + vca_write(sp, buf, i); + vca_flush(sp); cl -= i; } return (0); @@ -109,9 +108,7 @@ if (u == 0) break; - j = q - p; - i = write(sp->fd, q, j); - assert(i == j); + vca_write(sp, p, q - p); p = q; @@ -123,29 +120,28 @@ } if (bp - p < j) j = bp - p; - i = write(sp->fd, p, j); - assert(i == j); + vca_write(sp, p, j); p += j; - u -= i; + u -= j; } while (u > 0) { if (http_GetTail(hp, u, &b, &e)) { j = e - b; - i = write(sp->fd, q, j); - assert(i == j); + vca_write(sp, q, j); u -= j; } else break; } + vca_flush(sp); while (u > 0) { j = u; if (j > sizeof buf) j = sizeof buf; i = read(fd, buf, j); assert(i > 0); - j = write(sp->fd, buf, i); - assert(j == i); + vca_write(sp, buf, i); u -= i; + vca_flush(sp); } } return (0); @@ -181,8 +177,7 @@ http_Dissect(hp, fd, 2); http_BuildSbuf(2, w->sb, hp); - i = write(sp->fd, sbuf_data(w->sb), sbuf_len(w->sb)); - assert(i == sbuf_len(w->sb)); + vca_write(sp, sbuf_data(w->sb), sbuf_len(w->sb)); if (http_GetHdr(hp, "Content-Length", &b)) cls = pass_straight(w, sp, fd, hp, b); @@ -194,6 +189,7 @@ INCOMPL(); cls = 1; } + vca_flush(sp); if (http_GetHdr(hp, "Connection", &b) && !strcasecmp(b, "close")) cls = 1; From phk at projects.linpro.no Mon May 1 12:59:12 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 1 May 2006 14:59:12 +0200 (CEST) Subject: r166 - trunk/varnish-cache/bin/varnishd Message-ID: <20060501125912.CCF901ED6F4@projects.linpro.no> Author: phk Date: 2006-05-01 14:59:12 +0200 (Mon, 01 May 2006) New Revision: 166 Modified: trunk/varnish-cache/bin/varnishd/cache_fetch.c Log: Use vca_write/vca_flush Modified: trunk/varnish-cache/bin/varnishd/cache_fetch.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-05-01 12:51:48 UTC (rev 165) +++ trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-05-01 12:59:12 UTC (rev 166) @@ -60,12 +60,10 @@ } http_BuildSbuf(2, w->sb, hp); - i = write(sp->fd, sbuf_data(w->sb), sbuf_len(w->sb)); - assert(i == sbuf_len(w->sb)); + vca_write(sp, sbuf_data(w->sb), sbuf_len(w->sb)); + vca_write(sp, st->ptr, st->len); + vca_flush(sp); - i = write(sp->fd, st->ptr, st->len); - assert(i == st->len); - hash->deref(sp->obj); return (0); @@ -90,8 +88,6 @@ while (1) { bp = buf; if (http_GetTail(hp, be - bp, &b, &e)) { -if (0) -printf("Tail: (H)\n%#H\n", b, e - b); memcpy(bp, b, e - b); bp += e - b; } else { @@ -100,8 +96,6 @@ bp += i; } u = strtoul(buf, &q, 16); -if (0) -printf("Buf: u %u q %p buf %p\n%#H\n", u, q, buf, buf, bp - buf); if (q == NULL || (*q != '\n' && *q != '\r')) continue; if (*q == '\r') @@ -119,8 +113,6 @@ p += bp - q; u -= bp - q; if (http_GetTail(hp, u, &b, &e)) { -if (0) -printf("Tail: (B)\n%#H\n", b, e - b); memcpy(p, b, e - b); p += e - b; u -= e - b; @@ -130,21 +122,15 @@ assert(i > 0); u -= i; p += i; -if (0) -printf("u = %u i = %d\n", u, i); } -if (0) -printf("Store:\n%#H\n", st->ptr, st->len); } http_BuildSbuf(2, w->sb, hp); - i = write(sp->fd, sbuf_data(w->sb), sbuf_len(w->sb)); - assert(i == sbuf_len(w->sb)); + vca_write(sp, sbuf_data(w->sb), sbuf_len(w->sb)); - TAILQ_FOREACH(st, &sp->obj->store, list) { - i = write(sp->fd, st->ptr, st->len); - assert(i == st->len); - } + TAILQ_FOREACH(st, &sp->obj->store, list) + vca_write(sp, st->ptr, st->len); + vca_flush(sp); hash->deref(sp->obj); From phk at projects.linpro.no Mon May 1 12:59:34 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 1 May 2006 14:59:34 +0200 (CEST) Subject: r167 - trunk/varnish-cache/bin/varnishd Message-ID: <20060501125934.500091ED6F9@projects.linpro.no> Author: phk Date: 2006-05-01 14:59:34 +0200 (Mon, 01 May 2006) New Revision: 167 Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c Log: Use vca_write/vca_flush Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-05-01 12:59:12 UTC (rev 166) +++ trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-05-01 12:59:34 UTC (rev 167) @@ -69,7 +69,6 @@ DeliverSession(struct worker *w, struct sess *sp) { char buf[BUFSIZ]; - int i, j; struct storage *st; sprintf(buf, @@ -78,13 +77,10 @@ "Content-Length: %u\r\n" "\r\n", sp->obj->len); - j = strlen(buf); - i = write(sp->fd, buf, j); - assert(i == j); - TAILQ_FOREACH(st, &sp->obj->store, list) { - i = write(sp->fd, st->ptr, st->len); - assert(i == st->len); - } + vca_write(sp, buf, strlen(buf)); + TAILQ_FOREACH(st, &sp->obj->store, list) + vca_write(sp, st->ptr, st->len); + vca_flush(sp); return (1); } @@ -126,7 +122,6 @@ sp->handling = HND_Lookup; sp->vcl->recv_func(sp); - sp->handling = HND_Pass; for (done = 0; !done; ) { switch(sp->handling) {