VCL_VOID VRT_l_beresp_storage_hint(VRT_CTX, const char *str, ...) { const char *p; va_list ap; uintptr_t sn; VCL_STEVEDORE stv; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC); sn = WS_Snapshot(ctx->ws); va_start(ap, str); p = VRT_String(ctx->ws, NULL, str, ap); va_end(ap); if (p == NULL) { VSLb(ctx->vsl, SLT_LostHeader, "storage_hint"); WS_Reset(ctx->ws, sn); WS_MarkOverflow(ctx->ws); return; } stv = VRT_stevedore(p); if (stv != NULL) ctx->bo->storage = stv; WS_Reset(ctx->ws, sn); }
vmod_log(VRT_CTX, const char *fmt, ...) { const char *p; va_list ap; uintptr_t sn; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); sn = WS_Snapshot(ctx->ws); va_start(ap, fmt); p = VRT_String(ctx->ws, NULL, fmt, ap); va_end(ap); if (p == NULL) { WS_MarkOverflow(ctx->ws); WS_Reset(ctx->ws, sn); return; } AN(p); if (ctx->vsl != NULL) VSLb(ctx->vsl, SLT_VCL_Log, "%s", p); else VSL(SLT_VCL_Log, 0, "%s", p); WS_Reset(ctx->ws, sn); }
static int cnt_pipe(struct sess *sp) { CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp->vcl, VCL_CONF_MAGIC); sp->acct_req.pipe++; WS_Reset(sp->wrk->ws, NULL); sp->wrk->bereq = &sp->wrk->http[0]; http_Setup(sp->wrk->bereq, sp->wrk->ws); http_FilterHeader(sp, HTTPH_R_PIPE); VCL_pipe_method(sp); if (sp->handling == VCL_RET_ERROR) INCOMPL(); assert(sp->handling == VCL_RET_PIPE); PipeSession(sp); AZ(sp->wrk->wfd); sp->wrk->bereq = NULL; sp->step = STP_DONE; return (0); }
static int cnt_miss(struct sess *sp) { CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp->vcl, VCL_CONF_MAGIC); AZ(sp->obj); AN(sp->objcore); AN(sp->objhead); WS_Reset(sp->wrk->ws, NULL); sp->wrk->bereq = &sp->wrk->http[0]; http_Setup(sp->wrk->bereq, sp->wrk->ws); http_FilterHeader(sp, HTTPH_R_FETCH); VCL_miss_method(sp); switch(sp->handling) { case VCL_RET_ERROR: HSH_DerefObjCore(sp); sp->step = STP_ERROR; return (0); case VCL_RET_PASS: HSH_DerefObjCore(sp); sp->step = STP_PASS; return (0); case VCL_RET_FETCH: sp->step = STP_FETCH; return (0); case VCL_RET_RESTART: HSH_DerefObjCore(sp); INCOMPL(); default: WRONG("Illegal action in vcl_miss{}"); } }
static int cnt_pipe(struct sess *sp) { struct worker *wrk; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); wrk = sp->wrk; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(sp->vcl, VCL_CONF_MAGIC); AZ(wrk->busyobj); wrk->acct_tmp.pipe++; wrk->busyobj = VBO_GetBusyObj(wrk); WS_Reset(wrk->ws, NULL); wrk->busyobj = VBO_GetBusyObj(wrk); http_Setup(wrk->busyobj->bereq, wrk->ws); http_FilterHeader(sp, HTTPH_R_PIPE); VCL_pipe_method(sp); if (sp->handling == VCL_RET_ERROR) INCOMPL(); assert(sp->handling == VCL_RET_PIPE); PipeSession(sp); assert(WRW_IsReleased(wrk)); http_Setup(wrk->busyobj->bereq, NULL); VBO_DerefBusyObj(wrk, &wrk->busyobj); sp->step = STP_DONE; return (0); }
static int cnt_pass(struct sess *sp) { struct worker *wrk; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); wrk = sp->wrk; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(sp->vcl, VCL_CONF_MAGIC); AZ(wrk->obj); AZ(wrk->busyobj); wrk->busyobj = VBO_GetBusyObj(wrk); WS_Reset(wrk->ws, NULL); wrk->busyobj = VBO_GetBusyObj(wrk); http_Setup(wrk->busyobj->bereq, wrk->ws); http_FilterHeader(sp, HTTPH_R_PASS); wrk->connect_timeout = 0; wrk->first_byte_timeout = 0; wrk->between_bytes_timeout = 0; VCL_pass_method(sp); if (sp->handling == VCL_RET_ERROR) { http_Setup(wrk->busyobj->bereq, NULL); VBO_DerefBusyObj(wrk, &wrk->busyobj); sp->step = STP_ERROR; return (0); } assert(sp->handling == VCL_RET_PASS); wrk->acct_tmp.pass++; sp->sendbody = 1; sp->step = STP_FETCH; return (0); }
void VRT_Rollback(struct sess *sp) { HTTP_Copy(sp->http, sp->http0); WS_Reset(sp->ws, sp->ws_req); }
void VRT_Rollback(const struct vrt_ctx *ctx) { CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC); HTTP_Copy(ctx->req->http, ctx->req->http0); WS_Reset(ctx->req->ws, ctx->req->ws_req); }
void VRT_Rollback(VRT_CTX, const struct http *hp) { CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); if (hp == ctx->http_req) { CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC); HTTP_Copy(ctx->req->http, ctx->req->http0); WS_Reset(ctx->req->ws, ctx->req->ws_req); } else if (hp == ctx->http_bereq) { CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC); HTTP_Copy(ctx->bo->bereq, ctx->bo->bereq0); WS_Reset(ctx->bo->bereq->ws, ctx->bo->ws_bo); WS_Reset(ctx->bo->ws, ctx->bo->ws_bo); } else WRONG("VRT_Rollback 'hp' invalid"); }
void Req_Rollback(struct req *req) { VCL_TaskLeave(req->vcl, req->privs); VCL_TaskEnter(req->vcl, req->privs); HTTP_Clone(req->http, req->http0); if (WS_Overflowed(req->ws)) req->wrk->stats->ws_client_overflow++; WS_Reset(req->ws, req->ws_req); }
void vmod_workspace_reset(VRT_CTX, VCL_ENUM which) { struct ws *ws; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); ws = wsfind(ctx, which); WS_Assert(ws); WS_Reset(ws, debug_ws_snap); }
static void WRW_Release(struct worker *wrk) { struct wrw *wrw; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); wrw = wrk->wrw; wrk->wrw = NULL; CHECK_OBJ_NOTNULL(wrw, WRW_MAGIC); WS_Release(wrk->aws, 0); WS_Reset(wrk->aws, NULL); }
static void * server_bgthread(struct worker *wrk, void *priv) { struct vmod_fsdirector_file_system *fs; struct sockaddr_storage addr_s; socklen_t len; struct http_conn *htc; int fd; enum htc_status_e htc_status; CAST_OBJ_NOTNULL(fs, priv, VMOD_FSDIRECTOR_MAGIC); assert(fs->sock >= 0); htc = &fs->htc; fs->wrk = wrk; WS_Init(wrk->aws, fs->ws_name, malloc(WS_LEN), WS_LEN); while (1) { do { fd = accept(fs->sock, (void*)&addr_s, &len); } while (fd < 0 && errno == EAGAIN); if (fd < 0) { continue; } HTTP1_Init(htc, wrk->aws, fd, NULL, HTTP1_BUF, HTTP1_MAX_HDR); htc_status = HTTP1_Rx(htc); switch (htc_status) { case HTTP1_OVERFLOW: case HTTP1_ERROR_EOF: case HTTP1_ALL_WHITESPACE: case HTTP1_NEED_MORE: prepare_answer(htc, 400); prepare_body(htc); break; case HTTP1_COMPLETE: answer_appropriate(fs); break; } WS_Reset(wrk->aws, NULL); close(fd); } pthread_exit(0); NEEDLESS_RETURN(NULL); }
static void wrw_release(struct worker *wrk, uint64_t *pacc) { struct wrw *wrw; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); wrw = wrk->wrw; wrk->wrw = NULL; CHECK_OBJ_NOTNULL(wrw, WRW_MAGIC); if (pacc != NULL) *pacc += wrw->cnt; WS_Release(wrk->aws, 0); WS_Reset(wrk->aws, NULL); }
vmod_syslog(VRT_CTX, VCL_INT fac, const char *fmt, ...) { const char *p; va_list ap; uintptr_t sn; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); sn = WS_Snapshot(ctx->ws); va_start(ap, fmt); p = VRT_String(ctx->ws, NULL, fmt, ap); va_end(ap); if (p != NULL) syslog((int)fac, "%s", p); WS_Reset(ctx->ws, sn); }
unsigned V1L_FlushRelease(struct worker *wrk) { struct v1l *v1l; unsigned u; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); u = V1L_Flush(wrk); v1l = wrk->v1l; wrk->v1l = NULL; CHECK_OBJ_NOTNULL(v1l, V1L_MAGIC); WS_Release(v1l->ws, 0); WS_Reset(v1l->ws, v1l->res); return (u); }
void Req_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_NOTNULL(req->topreq, REQ_MAGIC); assert(sp == req->sp); AZ(req->vcl0); req->director_hint = NULL; req->restarts = 0; AZ(req->privs->magic); if (req->vcl != NULL) VCL_Recache(wrk, &req->vcl); /* Charge and log byte counters */ req_AcctLogCharge(wrk->stats, req); if (req->vsl->wid) VSL_End(req->vsl); if (!isnan(req->t_prev) && req->t_prev > 0. && req->t_prev > sp->t_idle) 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; req->esi_level = 0; req->is_hit = 0; if (WS_Overflowed(req->ws)) wrk->stats->ws_client_overflow++; WS_Reset(req->ws, 0); }
enum vgzret_e VGZ_Destroy(struct vgz **vgp) { struct vgz *vg; enum vgzret_e vr; int i; vg = *vgp; CHECK_OBJ_NOTNULL(vg, VGZ_MAGIC); *vgp = NULL; VSLb(vg->vsl, SLT_Gzip, "%s %jd %jd %jd %jd %jd", vg->id, (intmax_t)vg->vz.total_in, (intmax_t)vg->vz.total_out, (intmax_t)vg->vz.start_bit, (intmax_t)vg->vz.last_bit, (intmax_t)vg->vz.stop_bit); if (vg->tmp != NULL) WS_Reset(vg->tmp, vg->tmp_snapshot); if (vg->dir == VGZ_GZ) i = deflateEnd(&vg->vz); else i = inflateEnd(&vg->vz); if (vg->last_i == Z_STREAM_END && i == Z_OK) i = Z_STREAM_END; if (vg->m_buf) free(vg->m_buf); if (i == Z_OK) vr = VGZ_OK; else if (i == Z_STREAM_END) vr = VGZ_END; else if (i == Z_BUF_ERROR) vr = VGZ_STUCK; else { VSLb(vg->vsl, SLT_Gzip, "G(un)zip error: %d (%s)", i, vg->vz.msg); vr = VGZ_ERROR; } FREE_OBJ(vg); return (vr); }
static int cnt_pass(struct sess *sp) { CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp->vcl, VCL_CONF_MAGIC); AZ(sp->obj); WS_Reset(sp->wrk->ws, NULL); sp->wrk->bereq = &sp->wrk->http[0]; http_Setup(sp->wrk->bereq, sp->wrk->ws); http_FilterHeader(sp, HTTPH_R_PASS); VCL_pass_method(sp); if (sp->handling == VCL_RET_ERROR) { sp->step = STP_ERROR; return (0); } assert(sp->handling == VCL_RET_PASS); sp->acct_req.pass++; sp->sendbody = 1; sp->step = STP_FETCH; return (0); }
int VGZ_Destroy(struct vgz **vgp) { struct vgz *vg; int i; vg = *vgp; CHECK_OBJ_NOTNULL(vg, VGZ_MAGIC); *vgp = NULL; VSLb(vg->vsl, SLT_Gzip, "%s %jd %jd %jd %jd %jd", vg->id, (intmax_t)vg->vz.total_in, (intmax_t)vg->vz.total_out, (intmax_t)vg->vz.start_bit, (intmax_t)vg->vz.last_bit, (intmax_t)vg->vz.stop_bit); if (vg->tmp != NULL) WS_Reset(vg->tmp, vg->tmp_snapshot); if (vg->dir == VGZ_GZ) i = deflateEnd(&vg->vz); else i = inflateEnd(&vg->vz); if (vg->last_i == Z_STREAM_END && i == Z_OK) i = Z_STREAM_END; if (vg->m_buf) free(vg->m_buf); FREE_OBJ(vg); if (i == Z_OK) return (VGZ_OK); if (i == Z_STREAM_END) return (VGZ_END); if (i == Z_BUF_ERROR) return (VGZ_STUCK); return (VGZ_ERROR); }
static const char * sort_querystring(struct ws *ws, const char *uri) { if (uri == NULL) { return NULL; } char *query_string = strchr(uri, '?'); if (query_string == NULL) { return uri; } if (query_string[1] == '\0') { return truncate_querystring(ws, uri, query_string); } /* reserve some memory */ char *snapshot = WS_Snapshot(ws); char *sorted_uri = WS_Alloc(ws, strlen(uri) + 1); WS_Assert(ws); if (sorted_uri == NULL) { WS_Reset(ws, snapshot); return uri; } unsigned available = WS_Reserve(ws, 0); struct query_param *params = (struct query_param*) ws->f; struct query_param *end = params + available; /* initialize the params array */ int head = 10; if (¶ms[head + 1] > end) { head = 0; } if (¶ms[head + 1] > end) { WS_Release(ws, 0); WS_Reset(ws, snapshot); return uri; } int tail = head; int last_param = head; /* search and sort params */ bool sorted = true; char *c = query_string + 1; params[head].value = c; for (; *c != '\0' && ¶ms[tail+1] < end; c++) { if (*c != '&') { continue; } const char *current_param = c+1; params[last_param].length = c - params[last_param].value; if (head > 0 && compare_params(params[head].value, current_param) > -1) { sorted = false; params[--head].value = current_param; last_param = head; continue; } if (compare_params(params[tail].value, current_param) < 1) { params[++tail].value = current_param; last_param = tail; continue; } sorted = false; int i = tail++; params[tail] = params[i]; int previous = i-1; while (i > head && compare_params(params[previous].value, current_param) > -1) { params[i--] = params[previous--]; } params[i].value = current_param; last_param = i; } if (sorted == true || ¶ms[tail+1] >= end || tail - head < 1) { WS_Release(ws, 0); WS_Reset(ws, snapshot); return uri; } params[last_param].length = c - params[last_param].value; /* copy the url parts */ char *position = mempcpy(sorted_uri, uri, query_string - uri + 1); int count = tail-head; for (;count > 0; count--, ++head) { if (params[head].length > 0) { position = mempcpy(position, params[head].value, params[head].length); *position++ = '&'; } } if (params[head].length > 0) { position = mempcpy(position, params[head].value, params[head].length); } else { position--; } *position = '\0'; WS_Release(ws, 0); return sorted_uri; }
void Pool_Work_Thread(struct pool *pp, struct worker *wrk) { struct pool_task *tp; struct pool_task tpx, tps; int i; CHECK_OBJ_NOTNULL(pp, POOL_MAGIC); wrk->pool = pp; while (1) { Lck_Lock(&pp->mtx); CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); WS_Reset(wrk->aws, NULL); AZ(wrk->vsl); tp = VTAILQ_FIRST(&pp->front_queue); if (tp != NULL) { pp->lqueue--; VTAILQ_REMOVE(&pp->front_queue, tp, list); } else { tp = VTAILQ_FIRST(&pp->back_queue); if (tp != NULL) VTAILQ_REMOVE(&pp->back_queue, tp, list); } if ((tp == NULL && wrk->stats->summs > 0) || (wrk->stats->summs >= cache_param->wthread_stats_rate)) pool_addstat(pp->a_stat, wrk->stats); if (tp != NULL) { wrk->stats->summs++; } else if (pp->b_stat != NULL && pp->a_stat->summs) { /* Nothing to do, push pool stats into global pool */ tps.func = pool_stat_summ; tps.priv = pp->a_stat; pp->a_stat = pp->b_stat; pp->b_stat = NULL; tp = &tps; } else { /* Nothing to do: To sleep, perchance to dream ... */ if (isnan(wrk->lastused)) wrk->lastused = VTIM_real(); wrk->task.func = NULL; wrk->task.priv = wrk; VTAILQ_INSERT_HEAD(&pp->idle_queue, &wrk->task, list); do { i = Lck_CondWait(&wrk->cond, &pp->mtx, wrk->vcl == NULL ? 0 : wrk->lastused+60.); if (i == ETIMEDOUT) VCL_Rel(&wrk->vcl); } while (wrk->task.func == NULL); tpx = wrk->task; tp = &tpx; wrk->stats->summs++; } Lck_Unlock(&pp->mtx); if (tp->func == pool_kiss_of_death) break; do { memset(&wrk->task, 0, sizeof wrk->task); assert(wrk->pool == pp); tp->func(wrk, tp->priv); tpx = wrk->task; tp = &tpx; } while (tp->func != NULL); /* cleanup for next task */ wrk->seen_methods = 0; } wrk->pool = NULL; }
static int cnt_miss(struct sess *sp) { struct worker *wrk; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); wrk = sp->wrk; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(sp->vcl, VCL_CONF_MAGIC); AZ(wrk->obj); AN(wrk->objcore); CHECK_OBJ_NOTNULL(wrk->busyobj, BUSYOBJ_MAGIC); WS_Reset(wrk->ws, NULL); wrk->busyobj = VBO_GetBusyObj(wrk); http_Setup(wrk->busyobj->bereq, wrk->ws); http_FilterHeader(sp, HTTPH_R_FETCH); http_ForceGet(wrk->busyobj->bereq); if (cache_param->http_gzip_support) { /* * We always ask the backend for gzip, even if the * client doesn't grok it. We will uncompress for * the minority of clients which don't. */ http_Unset(wrk->busyobj->bereq, H_Accept_Encoding); http_SetHeader(wrk, sp->vsl_id, wrk->busyobj->bereq, "Accept-Encoding: gzip"); } wrk->connect_timeout = 0; wrk->first_byte_timeout = 0; wrk->between_bytes_timeout = 0; VCL_miss_method(sp); switch(sp->handling) { case VCL_RET_ERROR: AZ(HSH_Deref(wrk, wrk->objcore, NULL)); wrk->objcore = NULL; http_Setup(wrk->busyobj->bereq, NULL); VBO_DerefBusyObj(wrk, &wrk->busyobj); sp->step = STP_ERROR; return (0); case VCL_RET_PASS: AZ(HSH_Deref(wrk, wrk->objcore, NULL)); wrk->objcore = NULL; VBO_DerefBusyObj(wrk, &wrk->busyobj); sp->step = STP_PASS; return (0); case VCL_RET_FETCH: CHECK_OBJ_NOTNULL(wrk->busyobj, BUSYOBJ_MAGIC); sp->step = STP_FETCH; return (0); case VCL_RET_RESTART: AZ(HSH_Deref(wrk, wrk->objcore, NULL)); wrk->objcore = NULL; VBO_DerefBusyObj(wrk, &wrk->busyobj); INCOMPL(); default: WRONG("Illegal action in vcl_miss{}"); } }
static int cnt_done(struct sess *sp) { double dh, dp, da; int i; struct worker *wrk; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); wrk = sp->wrk; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_ORNULL(sp->vcl, VCL_CONF_MAGIC); AZ(wrk->obj); AZ(wrk->busyobj); sp->director = NULL; sp->restarts = 0; wrk->busyobj = NULL; SES_Charge(sp); /* If we did an ESI include, don't mess up our state */ if (sp->esi_level > 0) return (1); if (sp->vcl != NULL) { if (wrk->vcl != NULL) VCL_Rel(&wrk->vcl); wrk->vcl = sp->vcl; sp->vcl = NULL; } sp->t_end = W_TIM_real(wrk); WSP(sp, SLT_Debug, "PHK req %.9f resp %.9f end %.9f open %.9f", sp->t_req, sp->t_resp, sp->t_end, sp->t_open); if (sp->xid == 0) { // sp->t_req = sp->t_end; sp->t_resp = sp->t_end; } else { dp = sp->t_resp - sp->t_req; da = sp->t_end - sp->t_resp; dh = sp->t_req - sp->t_open; /* XXX: Add StatReq == StatSess */ /* XXX: Workaround for pipe */ if (sp->fd >= 0) { WSP(sp, SLT_Length, "%ju", (uintmax_t)sp->req_bodybytes); } WSP(sp, SLT_ReqEnd, "%u %.9f %.9f %.9f %.9f %.9f", sp->xid, sp->t_req, sp->t_end, dh, dp, da); } sp->xid = 0; WSL_Flush(wrk, 0); sp->t_open = sp->t_end; sp->t_resp = NAN; sp->req_bodybytes = 0; sp->t_req = NAN; sp->hash_always_miss = 0; sp->hash_ignore_busy = 0; if (sp->fd >= 0 && sp->doclose != NULL) { /* * This is an orderly close of the connection; ditch nolinger * before we close, to get queued data transmitted. */ // XXX: not yet (void)VTCP_linger(sp->fd, 0); SES_Close(sp, sp->doclose); } if (sp->fd < 0) { wrk->stats.sess_closed++; SES_Delete(sp, NULL); return (1); } if (wrk->stats.client_req >= cache_param->wthread_stats_rate) WRK_SumStat(wrk); /* Reset the workspace to the session-watermark */ WS_Reset(sp->ws, sp->ws_ses); WS_Reset(wrk->ws, NULL); i = HTC_Reinit(sp->htc); if (i == 1) { wrk->stats.sess_pipeline++; sp->step = STP_START; return (0); } if (Tlen(sp->htc->rxbuf)) { wrk->stats.sess_readahead++; sp->step = STP_WAIT; return (0); } if (cache_param->session_linger > 0) { wrk->stats.sess_linger++; sp->step = STP_WAIT; return (0); } wrk->stats.sess_herd++; Pool_Wait(sp); return (1); }
static int cnt_done(struct sess *sp) { double dh, dp, da; int i; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_ORNULL(sp->vcl, VCL_CONF_MAGIC); AZ(sp->obj); AZ(sp->vbe); sp->director = NULL; sp->restarts = 0; if (sp->vcl != NULL && sp->esis == 0) { if (sp->wrk->vcl != NULL) VCL_Rel(&sp->wrk->vcl); sp->wrk->vcl = sp->vcl; sp->vcl = NULL; } sp->t_end = TIM_real(); sp->wrk->lastused = sp->t_end; if (sp->xid == 0) { sp->t_req = sp->t_end; sp->t_resp = sp->t_end; } dp = sp->t_resp - sp->t_req; da = sp->t_end - sp->t_resp; dh = sp->t_req - sp->t_open; WSL(sp->wrk, SLT_ReqEnd, sp->id, "%u %.9f %.9f %.9f %.9f %.9f", sp->xid, sp->t_req, sp->t_end, dh, dp, da); sp->xid = 0; sp->t_open = sp->t_end; sp->t_resp = NAN; WSL_Flush(sp->wrk, 0); /* If we did an ESI include, don't mess up our state */ if (sp->esis > 0) return (1); sp->t_req = NAN; if (sp->fd >= 0 && sp->doclose != NULL) { /* * This is an orderly close of the connection; ditch nolinger * before we close, to get queued data transmitted. */ TCP_linger(sp->fd, 0); vca_close_session(sp, sp->doclose); } if (sp->fd < 0) { SES_Charge(sp); VSL_stats->sess_closed++; sp->wrk = NULL; SES_Delete(sp); return (1); } /* Reset the workspace to the session-watermark */ WS_Reset(sp->ws, sp->ws_ses); i = HTC_Reinit(sp->htc); if (i == 1) { VSL_stats->sess_pipeline++; sp->step = STP_START; return (0); } if (Tlen(sp->htc->rxbuf)) { VSL_stats->sess_readahead++; sp->step = STP_WAIT; return (0); } if (params->session_linger > 0) { VSL_stats->sess_linger++; sp->step = STP_WAIT; return (0); } VSL_stats->sess_herd++; SES_Charge(sp); sp->wrk = NULL; vca_return_session(sp); return (1); }
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); } }