#include "hash_slinger.h"
+/* Backend Connection ------------------------------------------------*/
+
+struct vbe_conn {
+ TAILQ_ENTRY(vbe_conn) list;
+ struct vbe *vbe;
+ int fd;
+ struct event ev;
+ int inuse;
+};
+
/* Storage -----------------------------------------------------------*/
struct storage {
/* cache_backend.c */
void VBE_Init(void);
-int VBE_GetFd(struct backend *bp, void **ptr, unsigned xid);
-void VBE_ClosedFd(void *ptr);
-void VBE_RecycleFd(void *ptr);
+struct vbe_conn *VBE_GetFd(struct backend *bp, unsigned xid);
+void VBE_ClosedFd(struct vbe_conn *vc);
+void VBE_RecycleFd(struct vbe_conn *vc);
/* cache_ban.c */
void BAN_Init(void);
#include "shmlog.h"
#include "cache.h"
-/* 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 {
* new connection.
*/
-int
-VBE_GetFd(struct backend *bp, void **ptr, unsigned xid)
+struct vbe_conn *
+VBE_GetFd(struct backend *bp, unsigned xid)
{
struct vbe *vp;
struct vbe_conn *vc;
vp->nconn++;
AZ(pthread_mutex_unlock(&vbemtx));
connect_to_backend(vc, bp);
- VSL_stats->backend_conn++;
- event_set(&vc->ev, vc->fd, EV_READ | EV_PERSIST, vbe_rdf, vc);
- event_base_set(vbe_evb, &vc->ev);
+ if (vc->fd < 0) {
+ AZ(pthread_mutex_lock(&vbemtx));
+ TAILQ_REMOVE(&vc->vbe->bconn, vc, list);
+ vp->nconn--;
+ AZ(pthread_mutex_unlock(&vbemtx));
+ free(vc);
+ vc = NULL;
+ } else {
+ VSL_stats->backend_conn++;
+ event_set(&vc->ev, vc->fd, EV_READ | EV_PERSIST, vbe_rdf, vc);
+ event_base_set(vbe_evb, &vc->ev);
+ }
}
- *ptr = vc;
- VSL(SLT_BackendXID, vc->fd, "%u", xid);
- return (vc->fd);
+ if (vc != NULL)
+ VSL(SLT_BackendXID, vc->fd, "%u", xid);
+ return (vc);
}
/* Close a connection ------------------------------------------------*/
void
-VBE_ClosedFd(void *ptr)
+VBE_ClosedFd(struct vbe_conn *vc)
{
- struct vbe_conn *vc;
int i;
- vc = ptr;
VSL(SLT_BackendClose, vc->fd, "");
close(vc->fd);
vc->fd = -1;
/* Recycle a connection ----------------------------------------------*/
void
-VBE_RecycleFd(void *ptr)
+VBE_RecycleFd(struct vbe_conn *vc)
{
- struct vbe_conn *vc;
int i;
VSL_stats->backend_recycle++;
- vc = ptr;
VSL(SLT_BackendReuse, vc->fd, "");
i = write(vbe_pipe[1], &vc, sizeof vc);
assert(i == sizeof vc);
int
FetchSession(struct worker *w, struct sess *sp)
{
- int fd, i, cls;
- void *fd_token;
+ int i, cls;
+ struct vbe_conn *vc;
struct http *hp;
char *b;
int body;
sp->obj->xid = sp->xid;
- fd = VBE_GetFd(sp->backend, &fd_token, sp->xid);
- if (fd == -1)
- fd = VBE_GetFd(sp->backend, &fd_token, sp->xid);
- assert(fd != -1); /* XXX: handle this */
- VSL(SLT_Backend, sp->fd, "%d %s", fd, sp->backend->vcl_name);
+ vc = VBE_GetFd(sp->backend, sp->xid);
+ if (vc == NULL)
+ vc = VBE_GetFd(sp->backend, sp->xid);
+ assert(vc != NULL); /* XXX: handle this */
+ VSL(SLT_Backend, sp->fd, "%d %s", vc->fd, sp->backend->vcl_name);
hp = http_New();
- http_BuildSbuf(fd, Build_Fetch, w->sb, sp->http);
- i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb));
+ http_BuildSbuf(vc->fd, Build_Fetch, w->sb, sp->http);
+ i = write(vc->fd, sbuf_data(w->sb), sbuf_len(w->sb));
assert(i == sbuf_len(w->sb));
time(&sp->t_req);
* XXX: It might be cheaper to avoid the event_engine and simply
* XXX: read(2) the header
*/
- http_RecvHead(hp, fd, w->eb, NULL, NULL);
+ http_RecvHead(hp, vc->fd, w->eb, NULL, NULL);
event_base_loop(w->eb, 0);
time(&sp->t_resp);
- assert(http_Dissect(hp, fd, 2) == 0);
+ assert(http_Dissect(hp, vc->fd, 2) == 0);
body = RFC2616_cache_policy(sp, hp);
http_BuildSbuf(sp->fd, Build_Reply, w->sb, hp);
if (body) {
if (http_GetHdr(hp, "Content-Length", &b))
- cls = fetch_straight(w, sp, fd, hp, b);
+ cls = fetch_straight(w, sp, vc->fd, hp, b);
else if (http_HdrIs(hp, "Transfer-Encoding", "chunked"))
- cls = fetch_chunked(w, sp, fd, hp);
+ cls = fetch_chunked(w, sp, vc->fd, hp);
else
- cls = fetch_eof(w, sp, fd, hp);
+ cls = fetch_eof(w, sp, vc->fd, hp);
sbuf_printf(w->sb, "Content-Length: %u\r\n", sp->obj->len);
} else
cls = 0;
cls = 1;
if (cls)
- VBE_ClosedFd(fd_token);
+ VBE_ClosedFd(vc);
else
- VBE_RecycleFd(fd_token);
+ VBE_RecycleFd(vc);
HSH_Unbusy(sp->obj);
if (!sp->obj->cacheable)
void
PassSession(struct worker *w, struct sess *sp)
{
- int fd, i;
- void *fd_token;
+ int i;
+ struct vbe_conn *vc;
struct http *hp;
char *b;
int cls;
- fd = VBE_GetFd(sp->backend, &fd_token, sp->xid);
- assert(fd != -1);
+ vc = VBE_GetFd(sp->backend, sp->xid);
+ assert(vc != NULL);
- http_BuildSbuf(fd, Build_Pass, w->sb, sp->http);
- i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb));
+ http_BuildSbuf(vc->fd, Build_Pass, w->sb, sp->http);
+ i = write(vc->fd, sbuf_data(w->sb), sbuf_len(w->sb));
assert(i == sbuf_len(w->sb));
/* XXX: copy any contents */
* XXX: read(2) the header
*/
hp = http_New();
- http_RecvHead(hp, fd, w->eb, NULL, NULL);
+ http_RecvHead(hp, vc->fd, w->eb, NULL, NULL);
event_base_loop(w->eb, 0);
- http_Dissect(hp, fd, 2);
+ http_Dissect(hp, vc->fd, 2);
http_BuildSbuf(sp->fd, Build_Reply, w->sb, hp);
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);
+ cls = pass_straight(w, sp, vc->fd, hp, b);
else if (http_HdrIs(hp, "Connection", "close"))
- cls = pass_straight(w, sp, fd, hp, NULL);
+ cls = pass_straight(w, sp, vc->fd, hp, NULL);
else if (http_HdrIs(hp, "Transfer-Encoding", "chunked"))
- cls = pass_chunked(w, sp, fd, hp);
+ cls = pass_chunked(w, sp, vc->fd, hp);
else {
INCOMPL();
cls = 1;
cls = 1;
if (cls)
- VBE_ClosedFd(fd_token);
+ VBE_ClosedFd(vc);
else
- VBE_RecycleFd(fd_token);
+ VBE_RecycleFd(vc);
}
void
PipeSession(struct worker *w, struct sess *sp)
{
- int fd, i;
- void *fd_token;
+ int i;
+ struct vbe_conn *vc;
struct edir e1, e2;
char *b, *e;
- fd = VBE_GetFd(sp->backend, &fd_token, sp->xid);
- assert(fd != -1);
+ vc = VBE_GetFd(sp->backend, sp->xid);
+ assert(vc != NULL);
- http_BuildSbuf(fd, Build_Pipe, w->sb, sp->http);
- i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb));
+ http_BuildSbuf(vc->fd, Build_Pipe, w->sb, sp->http);
+ i = write(vc->fd, sbuf_data(w->sb), sbuf_len(w->sb));
assert(i == sbuf_len(w->sb));
if (http_GetTail(sp->http, 99999999, &b, &e) && b != e) { /* XXX */
- i = write(fd, b, e - b);
+ i = write(vc->fd, b, e - b);
if (i != e - b) {
- close (fd);
+ close (vc->fd);
vca_close_session(sp, "pipe");
- VBE_ClosedFd(fd_token);
+ VBE_ClosedFd(vc);
}
}
- e1.fd = fd;
+ e1.fd = vc->fd;
e2.fd = sp->fd;
event_set(&e1.ev, sp->fd, EV_READ | EV_PERSIST, rdf, &e1);
event_base_set(w->eb, &e1.ev);
- event_set(&e2.ev, fd, EV_READ | EV_PERSIST, rdf, &e2);
+ event_set(&e2.ev, vc->fd, EV_READ | EV_PERSIST, rdf, &e2);
event_base_set(w->eb, &e2.ev);
event_add(&e1.ev, NULL);
event_add(&e2.ev, NULL);
event_base_loop(w->eb, 0);
- close (fd);
vca_close_session(sp, "pipe");
- VBE_ClosedFd(fd_token);
+ VBE_ClosedFd(vc);
}