struct vbe_conn * VBE_GetVbe(struct sess *sp, struct backend *bp) { struct vbe_conn *vc; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC); /* first look for vbe_conn's we can recycle */ while (1) { Lck_Lock(&bp->mtx); vc = VTAILQ_FIRST(&bp->connlist); if (vc != NULL) { bp->refcount++; assert(vc->backend == bp); assert(vc->fd >= 0); VTAILQ_REMOVE(&bp->connlist, vc, list); } Lck_Unlock(&bp->mtx); if (vc == NULL) break; if (VBE_CheckFd(vc->fd)) { /* XXX locking of stats */ VSL_stats->backend_reuse += 1; VSL_stats->backend_conn++; WSP(sp, SLT_Backend, "%d %s %s", vc->fd, sp->director->vcl_name, bp->vcl_name); return (vc); } sp->vbe = vc; VBE_ClosedFd(sp); } if (!bp->healthy) { VSL_stats->backend_unhealthy++; return (NULL); } if (bp->max_conn > 0 && bp->n_conn >= bp->max_conn) { VSL_stats->backend_busy++; return (NULL); } vc = VBE_NewConn(); assert(vc->fd == -1); AZ(vc->backend); vc->fd = bes_conn_try(sp, bp); if (vc->fd < 0) { VBE_ReleaseConn(vc); VSL_stats->backend_fail++; return (NULL); } vc->backend = bp; VSL_stats->backend_conn++; WSP(sp, SLT_Backend, "%d %s %s", vc->fd, sp->director->vcl_name, bp->vcl_name); return (vc); }
void PipeSession(struct sess *sp) { struct vbe_conn *vc; struct worker *w; struct pollfd fds[2]; int i; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC); w = sp->wrk; sp->vbe = VBE_GetFd(NULL, sp); if (sp->vbe == NULL) return; vc = sp->vbe; (void)TCP_blocking(vc->fd); WRW_Reserve(w, &vc->fd); sp->acct_req.hdrbytes += http_Write(w, sp->wrk->bereq, 0); if (sp->htc->pipeline.b != NULL) sp->acct_req.bodybytes += WRW_Write(w, sp->htc->pipeline.b, Tlen(sp->htc->pipeline)); i = WRW_FlushRelease(w); if (i) { vca_close_session(sp, "pipe"); VBE_ClosedFd(sp); return; } sp->t_resp = TIM_real(); memset(fds, 0, sizeof fds); // XXX: not yet (void)TCP_linger(vc->fd, 0); fds[0].fd = vc->fd; fds[0].events = POLLIN | POLLERR; // XXX: not yet (void)TCP_linger(sp->fd, 0); fds[1].fd = sp->fd; fds[1].events = POLLIN | POLLERR; while (fds[0].fd > -1 || fds[1].fd > -1) { fds[0].revents = 0; fds[1].revents = 0; i = poll(fds, 2, params->pipe_timeout * 1000); if (i < 1) break; if (fds[0].revents && rdf(vc->fd, sp->fd)) { (void)shutdown(vc->fd, SHUT_RD); (void)shutdown(sp->fd, SHUT_WR); fds[0].events = 0; fds[0].fd = -1; } if (fds[1].revents && rdf(sp->fd, vc->fd)) { (void)shutdown(sp->fd, SHUT_RD); (void)shutdown(vc->fd, SHUT_WR); fds[1].events = 0; fds[1].fd = -1; } } if (fds[0].fd >= 0) { (void)shutdown(vc->fd, SHUT_RD); (void)shutdown(sp->fd, SHUT_WR); } if (fds[1].fd >= 0) { (void)shutdown(sp->fd, SHUT_RD); (void)shutdown(vc->fd, SHUT_WR); } vca_close_session(sp, "pipe"); VBE_ClosedFd(sp); }