[master] b1f8725 Turn the guts of http1_wait() into a more general and protocol independent SES_RxReq() function.

Poul-Henning Kamp phk at FreeBSD.org
Wed Mar 25 13:32:01 CET 2015


commit b1f87256d1cfcc08442ab9518653a1a520f84bf7
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Wed Mar 25 12:30:39 2015 +0000

    Turn the guts of http1_wait() into a more general and protocol
    independent SES_RxReq() function.
    
    Eliminate timeout_req and rely on timeout_idle to do the job.
    (Length of this timeout still under debate on -dev)

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index 615b830..1db2fa5 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -677,6 +677,10 @@ struct sess {
 
 /* Prototypes etc ----------------------------------------------------*/
 
+/* Cross file typedefs */
+
+typedef enum htc_status_e htc_complete_f(struct http_conn *);
+
 /* cache_acceptor.c */
 void VCA_Init(void);
 void VCA_Shutdown(void);
@@ -853,7 +857,7 @@ enum sess_close http_DoConnection(struct http *hp);
 
 /* cache_http1_proto.c */
 
-enum htc_status_e HTTP1_Complete(struct http_conn *htc);
+htc_complete_f HTTP1_Complete;
 uint16_t HTTP1_DissectRequest(struct http_conn *htc, struct http *hp);
 uint16_t HTTP1_DissectResponse(struct http *sp, struct http_conn *htc);
 unsigned HTTP1_Write(const struct worker *w, const struct http *hp, const int*);
@@ -985,18 +989,22 @@ task_func_t SES_Proto_Sess;
 task_func_t SES_Proto_Req;
 
 enum htc_status_e {
-	HTC_S_EMPTY =		-4,
+	HTC_S_CLOSE =		-4,
 	HTC_S_TIMEOUT =		-3,
 	HTC_S_OVERFLOW =	-2,
 	HTC_S_EOF =		-1,
-	HTC_S_OK =		0,
-	HTC_S_COMPLETE =	 1
+	HTC_S_EMPTY =		 0,
+	HTC_S_MORE =		 1,
+	HTC_S_COMPLETE =	 2,
+	HTC_S_IDLE =		 3,
 };
 
 void SES_RxInit(struct http_conn *htc, struct ws *ws,
     unsigned maxbytes, unsigned maxhdr);
 void SES_RxReInit(struct http_conn *htc);
 enum htc_status_e SES_Rx(struct http_conn *htc, double tmo);
+enum htc_status_e SES_RxReq(const struct worker *, struct req *,
+    htc_complete_f *func);
 
 #define SESS_ATTR(UP, low, typ, len)				\
 	int SES_Get_##low(const struct sess *sp, typ *dst);	\
diff --git a/bin/varnishd/cache/cache_session.c b/bin/varnishd/cache/cache_session.c
index 5ee4cfb..e03f909 100644
--- a/bin/varnishd/cache/cache_session.c
+++ b/bin/varnishd/cache/cache_session.c
@@ -234,7 +234,65 @@ SES_Rx(struct http_conn *htc, double tmo)
 		return (HTC_S_EOF);
 	htc->rxbuf_e += i;
 	*htc->rxbuf_e = '\0';
-	return (HTC_S_OK);
+	return (HTC_S_MORE);
+}
+
+/*----------------------------------------------------------------------
+ * Receive a request/packet/whatever, with timeouts
+ */
+
+enum htc_status_e
+SES_RxReq(const struct worker *wrk, struct req *req, htc_complete_f *func)
+{
+	double tmo;
+	double now, when;
+	struct sess *sp;
+	enum htc_status_e hs;
+
+	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
+	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
+	sp = req->sp;
+	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+
+	AZ(isnan(sp->t_idle));
+	assert(isnan(req->t_first));
+
+	when = sp->t_idle + cache_param->timeout_idle;
+	tmo = cache_param->timeout_linger;
+	while (1) {
+		hs = SES_Rx(req->htc, tmo);
+		now = VTIM_real();
+		if (hs == HTC_S_EOF) {
+			WS_ReleaseP(req->htc->ws, req->htc->rxbuf_b);
+			return (HTC_S_CLOSE);
+		}
+		if (hs == HTC_S_OVERFLOW) {
+			WS_ReleaseP(req->htc->ws, req->htc->rxbuf_b);
+			return (HTC_S_OVERFLOW);
+		}
+		hs = func(req->htc);
+		if (hs == HTC_S_COMPLETE) {
+			/* Got it, run with it */
+			if (isnan(req->t_first))
+				req->t_first = now;
+			req->t_req = now;
+			return (HTC_S_COMPLETE);
+		}
+		if (when < now)
+			return (HTC_S_TIMEOUT);
+		if (hs == HTC_S_MORE) {
+			/* Working on it */
+			if (isnan(req->t_first))
+				req->t_first = now;
+			tmo = when - now;
+			continue;
+		}
+		assert(hs == HTC_S_EMPTY);
+		/* Nothing but whitespace */
+		tmo = sp->t_idle + cache_param->timeout_linger - now;
+		if (tmo < 0)
+			return (HTC_S_IDLE);
+	}
 }
 
 /*--------------------------------------------------------------------
@@ -422,13 +480,16 @@ SES_Wait(struct sess *sp)
 	 * XXX: waiter_epoll prevents us from zeroing the struct because
 	 * XXX: it keeps state across calls.
 	 */
+	if (VTCP_nonblocking(sp->fd)) {
+		SES_Delete(sp, SC_REM_CLOSE, NAN);
+		return;
+	}
 	sp->waited.magic = WAITED_MAGIC;
 	sp->waited.fd = sp->fd;
 	sp->waited.ptr = sp;
 	sp->waited.idle = sp->t_idle;
-	if (Wait_Enter(pp->http1_waiter, &sp->waited)) {
+	if (Wait_Enter(pp->http1_waiter, &sp->waited))
 		SES_Delete(sp, SC_PIPE_OVERFLOW, NAN);
-	}
 }
 
 /*--------------------------------------------------------------------
diff --git a/bin/varnishd/common/params.h b/bin/varnishd/common/params.h
index 4c9c3ed..72b74d6 100644
--- a/bin/varnishd/common/params.h
+++ b/bin/varnishd/common/params.h
@@ -111,7 +111,6 @@ struct params {
 
 	double			timeout_linger;
 	double			timeout_idle;
-	double			timeout_req;
 	double			pipe_timeout;
 	double			send_timeout;
 	double			idle_send_timeout;
diff --git a/bin/varnishd/http1/cache_http1_fetch.c b/bin/varnishd/http1/cache_http1_fetch.c
index bae29c5..7b108d2 100644
--- a/bin/varnishd/http1/cache_http1_fetch.c
+++ b/bin/varnishd/http1/cache_http1_fetch.c
@@ -154,7 +154,7 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, const char *def_host)
 	first = 1;
 	do {
 		hs = SES_Rx(htc, 0);
-		if (hs == HTC_S_OK)
+		if (hs == HTC_S_MORE)
 			hs = HTTP1_Complete(htc);
 		if (hs == HTC_S_OVERFLOW) {
 			WS_ReleaseP(htc->ws, htc->rxbuf_b);
diff --git a/bin/varnishd/http1/cache_http1_fsm.c b/bin/varnishd/http1/cache_http1_fsm.c
index 1976d6c..0f1d46c 100644
--- a/bin/varnishd/http1/cache_http1_fsm.c
+++ b/bin/varnishd/http1/cache_http1_fsm.c
@@ -51,89 +51,39 @@
 static enum req_fsm_nxt
 http1_wait(struct sess *sp, struct worker *wrk, struct req *req)
 {
-	double tmo;
-	double now, when;
-	enum sess_close why = SC_NULL;
 	enum htc_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));
+	AZ(req->vcl);
+	AZ(req->esi_level);
 
-	tmo = cache_param->timeout_linger;
-	while (1) {
-		hs = SES_Rx(req->htc, tmo);
-		now = VTIM_real();
-		if (hs == HTC_S_EOF) {
-			WS_ReleaseP(req->htc->ws, req->htc->rxbuf_b);
-			why = SC_REM_CLOSE;
-			break;
-		}
-		if (hs == HTC_S_OVERFLOW) {
-			WS_ReleaseP(req->htc->ws, req->htc->rxbuf_b);
-			why = SC_RX_OVERFLOW;
-			break;
-		}
-		hs = HTTP1_Complete(req->htc);
-		if (hs == HTC_S_OK) {
-			/* Working on it */
-			if (isnan(req->t_first))
-				/* Record first byte received time stamp */
-				req->t_first = now;
-			when = req->t_first + cache_param->timeout_req;
-			tmo = when - now;
-			if (tmo <= 0) {
-				why = SC_RX_TIMEOUT;
-				break;
-			}
-			continue;
-		}
-		if (hs == HTC_S_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 +=
-			    req->htc->rxbuf_e - req->htc->rxbuf_b;
-			return (REQ_FSM_MORE);
-		}
-		assert(hs == HTC_S_EMPTY);
-		/* Nothing but whitespace */
-		when = sp->t_idle + cache_param->timeout_idle;
-		if (when < now) {
-			why = SC_RX_TIMEOUT;
-			break;
+	hs = SES_RxReq(wrk, req, HTTP1_Complete);
+	if (hs < HTC_S_EMPTY) {
+		req->acct.req_hdrbytes += req->htc->rxbuf_e - req->htc->rxbuf_b;
+		CNT_AcctLogCharge(wrk->stats, req);
+		SES_ReleaseReq(req);
+		switch(hs) {
+		case HTC_S_CLOSE: SES_Delete(sp, SC_REM_CLOSE, 0.0); break;
+		case HTC_S_TIMEOUT: SES_Delete(sp, SC_RX_TIMEOUT, 0.0); break;
+		case HTC_S_OVERFLOW: SES_Delete(sp, SC_RX_OVERFLOW, 0.0); break;
+		case HTC_S_EOF: SES_Delete(sp, SC_REM_CLOSE, 0.0); break;
+		default: WRONG("htc_status (bad)");
 		}
-		when = sp->t_idle + cache_param->timeout_linger;
-		tmo = when - now;
-		if (tmo > 0)
-			continue;
-
+		return (REQ_FSM_DONE);
+	}
+	if (hs == HTC_S_COMPLETE) {
+		req->acct.req_hdrbytes +=
+		    req->htc->rxbuf_e - req->htc->rxbuf_b;
+		return (REQ_FSM_MORE);
+	}
+	if (hs == HTC_S_IDLE) {
 		wrk->stats->sess_herd++;
 		SES_ReleaseReq(req);
-		if (VTCP_nonblocking(sp->fd)) {
-			why = SC_REM_CLOSE;
-			break;
-		}
 		SES_Wait(sp);
 		return (REQ_FSM_DONE);
 	}
-	req->acct.req_hdrbytes += req->htc->rxbuf_e - req->htc->rxbuf_b;
-	CNT_AcctLogCharge(wrk->stats, req);
-	SES_ReleaseReq(req);
-	assert(why != SC_NULL);
-	SES_Delete(sp, why, now);
-	return (REQ_FSM_DONE);
+	WRONG("htc_status (nonbad)");
 }
 
 /*----------------------------------------------------------------------
diff --git a/bin/varnishd/http1/cache_http1_proto.c b/bin/varnishd/http1/cache_http1_proto.c
index 28cbc0f..c99ec30 100644
--- a/bin/varnishd/http1/cache_http1_proto.c
+++ b/bin/varnishd/http1/cache_http1_proto.c
@@ -61,7 +61,7 @@ const int HTTP1_Resp[3] = {
  * Check if we have a complete HTTP request or response yet
  */
 
-enum htc_status_e
+enum htc_status_e __match_proto__(htc_complete_f)
 HTTP1_Complete(struct http_conn *htc)
 {
 	char *p;
@@ -85,7 +85,7 @@ HTTP1_Complete(struct http_conn *htc)
 	while (1) {
 		p = strchr(p, '\n');
 		if (p == NULL)
-			return (HTC_S_OK);
+			return (HTC_S_MORE);
 		p++;
 		if (*p == '\r')
 			p++;
diff --git a/bin/varnishd/mgt/mgt_param_tbl.c b/bin/varnishd/mgt/mgt_param_tbl.c
index 51120f6..071d7ed 100644
--- a/bin/varnishd/mgt/mgt_param_tbl.c
+++ b/bin/varnishd/mgt/mgt_param_tbl.c
@@ -172,16 +172,10 @@ struct parspec mgt_parspec[] = {
 	{ "timeout_idle", tweak_timeout, &mgt_param.timeout_idle,
 		"0", NULL,
 		"Idle timeout for client connections.\n"
-		"A connection is considered idle, until we receive"
-		" a non-white-space character on it.",
+		"A connection is considered idle, until we have"
+		"received the full request headers.",
 		0,
 		"5", "seconds" },
-	{ "timeout_req", tweak_timeout, &mgt_param.timeout_req,
-		"0", NULL,
-		"Max time to receive clients request headers, measured"
-		" from first non-white-space character to double CRNL.",
-		0,
-		"2", "seconds" },
 	{ "pipe_timeout", tweak_timeout, &mgt_param.pipe_timeout,
 		"0", NULL,
 		"Idle timeout for PIPE sessions. "



More information about the varnish-commit mailing list