Commit f7a5d684 authored by Tollef Fog Heen's avatar Tollef Fog Heen

Merge r5101: Do groundwork for retry-once-on-connection closed

Rework the FetchHdr() and surroundings a litle bit, to get us a return
value that indicates if a failure should be retried.

Condition for retry is that the connection is recycled and fails
before we receive any data from the other end.

(The actual retry is not implemented yet)


git-svn-id: http://www.varnish-cache.org/svn/branches/2.1@5312 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 5e1595df
......@@ -455,6 +455,8 @@ struct vbe_conn {
struct backend *backend;
int fd;
uint8_t recycled;
/* Timeouts */
double first_byte_timeout;
double between_bytes_timeout;
......
......@@ -78,6 +78,7 @@ VBE_ReleaseConn(struct vbe_conn *vc)
assert(vc->backend == NULL);
assert(vc->fd < 0);
vc->recycled = 0;
if (params->cache_vbe_conns) {
Lck_Lock(&VBE_mtx);
VTAILQ_INSERT_HEAD(&vbe_conns, vc, list);
......@@ -339,11 +340,15 @@ vbe_GetVbe(struct sess *sp, struct backend *bp)
VSL_stats->backend_reuse += 1;
WSP(sp, SLT_Backend, "%d %s %s",
vc->fd, sp->director->vcl_name, bp->vcl_name);
vc->recycled = 1;
return (vc);
}
VSL_stats->backend_toolate++;
sp->vbe = vc;
VBE_CloseFd(sp);
WSL(sp->wrk, SLT_BackendClose, vc->fd, "%s", bp->vcl_name);
TCP_close(&vc->fd);
VBE_DropRefConn(bp);
vc->backend = NULL;
VBE_ReleaseConn(vc);
}
if (!vbe_Healthy(sp->t_req, (uintptr_t)sp->objhead, bp)) {
......
......@@ -325,7 +325,15 @@ FetchReqBody(struct sess *sp)
return (0);
}
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------
* Send request, and receive the HTTP protocol response, but not the
* response body.
*
* Return value:
* -1 failure, not retryable
* 0 success
* 1 failure which can be retried.
*/
int
FetchHdr(struct sess *sp)
......@@ -334,35 +342,38 @@ FetchHdr(struct sess *sp)
struct worker *w;
char *b;
struct http *hp;
int retry = -1;
int i;
double tmo;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
w = sp->wrk;
AN(sp->director);
AZ(sp->obj);
if (sp->objcore != NULL) { /* pass has no objcore */
CHECK_OBJ_NOTNULL(sp->objcore, OBJCORE_MAGIC);
AN(sp->objhead); /* details in hash_slinger.h */
AN(sp->objcore->flags & OC_F_BUSY);
}
/* Transmit request */
w = sp->wrk;
hp = sp->wrk->bereq;
sp->vbe = VBE_GetFd(NULL, sp);
if (sp->vbe == NULL) {
WSP(sp, SLT_FetchError, "no backend connection");
return (__LINE__);
return (-1);
}
vc = sp->vbe;
if (vc->recycled)
retry = 1;
/*
* Now that we know our backend, we can set a default Host:
* header if one is necessary.
* XXX: This possibly ought to go into the default VCL
* header if one is necessary. This cannot be done in the VCL
* because the backend may be chosen by a director.
*/
if (!http_GetHdr(hp, H_Host, &b))
VBE_AddHostHeader(sp);
......@@ -374,10 +385,11 @@ FetchHdr(struct sess *sp)
/* Deal with any message-body the request might have */
i = FetchReqBody(sp);
if (WRW_FlushRelease(w) || i > 0) {
WSP(sp, SLT_FetchError, "backend write error: %d", errno);
WSP(sp, SLT_FetchError, "backend write error: %d (%s)",
errno, strerror(errno));
VBE_CloseFd(sp);
/* XXX: other cleanup ? */
return (__LINE__);
return (retry);
}
/* Checkpoint the shmlog here */
......@@ -391,23 +403,31 @@ FetchHdr(struct sess *sp)
HTC_Init(sp->wrk->htc, sp->wrk->ws, vc->fd);
TCP_set_read_timeout(vc->fd, vc->first_byte_timeout);
tmo = vc->first_byte_timeout;
do {
i = HTC_Rx(sp->wrk->htc);
if (i < 0) {
WSP(sp, SLT_FetchError, "http first read error: %d %d (%s)",
i, errno, strerror(errno));
VBE_CloseFd(sp);
/* XXX: other cleanup ? */
/* Retryable if we never received anything */
return (i == -1 ? retry : -1);
}
TCP_set_read_timeout(vc->fd, vc->between_bytes_timeout);
while (i == 0) {
i = HTC_Rx(sp->wrk->htc);
if (i < 0) {
WSP(sp, SLT_FetchError,
"http read error: %d (%s)", errno, strerror(errno));
"http first read error: %d %d (%s)",
i, errno, strerror(errno));
VBE_CloseFd(sp);
/* XXX: other cleanup ? */
return (__LINE__);
}
if (vc->between_bytes_timeout != tmo) {
TCP_set_read_timeout(vc->fd, vc->between_bytes_timeout);
tmo = vc->between_bytes_timeout;
return (-1);
}
} while (i == 0);
}
hp = sp->wrk->beresp;
......@@ -415,7 +435,7 @@ FetchHdr(struct sess *sp)
WSP(sp, SLT_FetchError, "http format error");
VBE_CloseFd(sp);
/* XXX: other cleanup ? */
return (__LINE__);
return (-1);
}
return (0);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment