示例#1
0
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);

}
示例#2
0
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);
	}
}