void SES_Delete(struct sess *sp, const char *reason, double now) { struct acct *b; struct worker *wrk; struct sesspool *pp; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); pp = sp->sesspool; CHECK_OBJ_NOTNULL(pp, SESSPOOL_MAGIC); AN(pp->pool); wrk = sp->wrk; CHECK_OBJ_ORNULL(wrk, WORKER_MAGIC); if (reason != NULL) SES_Close(sp, reason); if (isnan(now)) now = VTIM_real(); assert(!isnan(sp->t_open)); assert(sp->fd < 0); if (sp->req != NULL) { AZ(sp->req->vcl); SES_ReleaseReq(sp); } if (*sp->addr == '\0') strcpy(sp->addr, "-"); if (*sp->port == '\0') strcpy(sp->addr, "-"); b = &sp->acct_ses; VSL(SLT_StatSess, sp->vsl_id, "%s %s %.0f %ju %ju %ju %ju %ju %ju %ju", sp->addr, sp->port, now - sp->t_open, b->sess, b->req, b->pipe, b->pass, b->fetch, b->hdrbytes, b->bodybytes); MPL_Free(pp->mpl_sess, sp); }
void SES_Delete(struct sess *sp, const char *reason, double now) { struct acct *b; struct sessmem *sm; struct worker *wrk; struct sesspool *pp; pp = ses_getpool(sp); sm = sp->mem; CHECK_OBJ_NOTNULL(sm, SESSMEM_MAGIC); wrk = sp->wrk; CHECK_OBJ_ORNULL(wrk, WORKER_MAGIC); if (reason != NULL) SES_Close(sp, reason); if (isnan(now)) now = VTIM_real(); assert(!isnan(sp->t_open)); assert(sp->fd < 0); if (sp->req != NULL) { AZ(sp->req->vcl); SES_ReleaseReq(sp); } if (*sp->addr == '\0') strcpy(sp->addr, "-"); if (*sp->port == '\0') strcpy(sp->addr, "-"); b = &sp->acct_ses; VSL(SLT_StatSess, sp->vsl_id, "%s %s %.0f %ju %ju %ju %ju %ju %ju %ju", sp->addr, sp->port, now - sp->t_open, b->sess, b->req, b->pipe, b->pass, b->fetch, b->hdrbytes, b->bodybytes); if (sm->workspace != cache_param->sess_workspace || sm->nhttp != (uint16_t)cache_param->http_max_hdr || pp->nsess > cache_param->max_sess) { free(sm); Lck_Lock(&pp->mtx); if (wrk != NULL) wrk->stats.sessmem_free++; else pp->dly_free_cnt++; pp->nsess--; Lck_Unlock(&pp->mtx); } else { /* Clean and prepare for reuse */ ses_setup(sm); Lck_Lock(&pp->mtx); if (wrk != NULL) { wrk->stats.sessmem_free += pp->dly_free_cnt; pp->dly_free_cnt = 0; } VTAILQ_INSERT_HEAD(&pp->freelist, sm, list); Lck_Unlock(&pp->mtx); } }
static enum req_fsm_nxt http1_wait(struct sess *sp, struct worker *wrk, struct req *req) { int j, tmo; struct pollfd pfd[1]; double now, when; enum sess_close why = SC_NULL; enum http1_status_e hs; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); assert(req->sp == sp); AZ(req->vcl); AZ(req->esi_level); AZ(isnan(sp->t_idle)); assert(isnan(req->t_first)); assert(isnan(req->t_prev)); assert(isnan(req->t_req)); tmo = (int)(1e3 * cache_param->timeout_linger); while (1) { pfd[0].fd = sp->fd; pfd[0].events = POLLIN; pfd[0].revents = 0; j = poll(pfd, 1, tmo); assert(j >= 0); now = VTIM_real(); if (j != 0) hs = HTTP1_Rx(req->htc); else hs = HTTP1_Complete(req->htc); if (hs == HTTP1_COMPLETE) { /* Got it, run with it */ if (isnan(req->t_first)) req->t_first = now; if (isnan(req->t_req)) req->t_req = now; req->acct.req_hdrbytes += Tlen(req->htc->rxbuf); return (REQ_FSM_MORE); } else if (hs == HTTP1_ERROR_EOF) { why = SC_REM_CLOSE; break; } else if (hs == HTTP1_OVERFLOW) { why = SC_RX_OVERFLOW; break; } else if (hs == HTTP1_ALL_WHITESPACE) { /* Nothing but whitespace */ when = sp->t_idle + cache_param->timeout_idle; if (when < now) { why = SC_RX_TIMEOUT; break; } when = sp->t_idle + cache_param->timeout_linger; tmo = (int)(1e3 * (when - now)); if (when < now || tmo == 0) { wrk->stats->sess_herd++; SES_ReleaseReq(req); WAIT_Enter(sp); return (REQ_FSM_DONE); } } else { /* Working on it */ if (isnan(req->t_first)) /* Record first byte received time stamp */ req->t_first = now; when = sp->t_idle + cache_param->timeout_req; tmo = (int)(1e3 * (when - now)); if (when < now || tmo == 0) { why = SC_RX_TIMEOUT; break; } } } req->acct.req_hdrbytes += Tlen(req->htc->rxbuf); CNT_AcctLogCharge(wrk->stats, req); SES_ReleaseReq(req); assert(why != SC_NULL); SES_Delete(sp, why, now); return (REQ_FSM_DONE); }
static enum http1_cleanup_ret http1_cleanup(struct sess *sp, struct worker *wrk, struct req *req) { CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); CHECK_OBJ_ORNULL(req->vcl, VCL_CONF_MAGIC); req->director_hint = NULL; req->restarts = 0; AZ(req->esi_level); if (req->vcl != NULL) { if (wrk->vcl != NULL) VCL_Rel(&wrk->vcl); wrk->vcl = req->vcl; req->vcl = NULL; } /* Charge and log byte counters */ AN(req->vsl->wid); CNT_AcctLogCharge(wrk->stats, req); req->req_bodybytes = 0; req->resp_hdrbytes = 0; req->resp_bodybytes = 0; VSL_End(req->vsl); if (!isnan(req->t_prev) && req->t_prev > 0.) sp->t_idle = req->t_prev; else sp->t_idle = W_TIM_real(wrk); req->t_first = NAN; req->t_prev = NAN; req->t_req = NAN; req->req_body_status = REQ_BODY_INIT; req->hash_always_miss = 0; req->hash_ignore_busy = 0; if (sp->fd >= 0 && req->doclose != SC_NULL) SES_Close(sp, req->doclose); if (sp->fd < 0) { wrk->stats->sess_closed++; AZ(req->vcl); SES_ReleaseReq(req); SES_Delete(sp, SC_NULL, NAN); return (SESS_DONE_RET_GONE); } WS_Reset(req->ws, NULL); WS_Reset(wrk->aws, NULL); if (HTTP1_Reinit(req->htc) == HTTP1_COMPLETE) { AZ(req->vsl->wid); req->t_first = req->t_req = sp->t_idle; wrk->stats->sess_pipeline++; req->acct.req_hdrbytes += Tlen(req->htc->rxbuf); return (SESS_DONE_RET_START); } else { if (Tlen(req->htc->rxbuf)) wrk->stats->sess_readahead++; return (SESS_DONE_RET_WAIT); } }