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); }
static struct vbc * vbe_GetVbe(struct busyobj *bo, struct vdi_simple *vs) { struct vbc *vc; struct backend *bp; CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); CHECK_OBJ_NOTNULL(vs, VDI_SIMPLE_MAGIC); bp = vs->backend; CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC); /* first look for vbc'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); AN(vc->addr); VTAILQ_REMOVE(&bp->connlist, vc, list); } Lck_Unlock(&bp->mtx); if (vc == NULL) break; if (vbe_CheckFd(vc->fd)) { /* XXX locking of stats */ VSC_C_main->backend_reuse += 1; VSLb(bo->vsl, SLT_Backend, "%d %s %s", vc->fd, bo->director->vcl_name, bp->display_name); vc->vdis = vs; vc->recycled = 1; return (vc); } VSC_C_main->backend_toolate++; VSLb(bo->vsl, SLT_BackendClose, "%d %s toolate", vc->fd, bp->display_name); /* Checkpoint log to flush all info related to this connection before the OS reuses the FD */ VSL_Flush(bo->vsl, 0); VTCP_close(&vc->fd); VBE_DropRefConn(bp); vc->backend = NULL; VBE_ReleaseConn(vc); } if (!VBE_Healthy(bp, NULL)) { VSC_C_main->backend_unhealthy++; return (NULL); } if (vs->vrt->max_connections > 0 && bp->n_conn >= vs->vrt->max_connections) { VSC_C_main->backend_busy++; return (NULL); } vc = vbe_NewConn(); assert(vc->fd == -1); AZ(vc->backend); bes_conn_try(bo, vc, vs); if (vc->fd < 0) { VBE_ReleaseConn(vc); VSC_C_main->backend_fail++; return (NULL); } vc->backend = bp; VSC_C_main->backend_conn++; VSLb(bo->vsl, SLT_Backend, "%d %s %s", vc->fd, bo->director->vcl_name, bp->display_name); vc->vdis = vs; return (vc); }