[master] d057bf9 Nils patch for retrying partial fetches, with minor changes by me.
Poul-Henning Kamp
phk at FreeBSD.org
Tue Dec 16 22:36:45 CET 2014
commit d057bf951796de1acc0359613ebb50e4fc891a0f
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Tue Dec 16 21:35:15 2014 +0000
Nils patch for retrying partial fetches, with minor changes by me.
Fixes #1638
Fixes #1641
diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c
index f74a5c0..a5b083f 100644
--- a/bin/varnishd/cache/cache_fetch.c
+++ b/bin/varnishd/cache/cache_fetch.c
@@ -213,17 +213,37 @@ vbf_stp_mkbereq(const struct worker *wrk, struct busyobj *bo)
/*--------------------------------------------------------------------
* Start a new VSL transaction and try again
+ * Prepare the busyobj and fetch processors
*/
static enum fetch_step
vbf_stp_retry(struct worker *wrk, struct busyobj *bo)
{
+ struct vfp_ctx *vfc;
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
+ vfc = bo->vfc;
+ CHECK_OBJ_NOTNULL(vfc, VFP_CTX_MAGIC);
+
+ assert(bo->state == BOS_REQ_DONE);
VSLb_ts_busyobj(bo, "Retry", W_TIM_real(wrk));
+ /* VDI_Finish must have been called before */
+ assert(bo->director_state == DIR_S_NULL);
+ bo->doclose = SC_NULL;
+
+ /* reset other bo attributes - See VBO_GetBusyObj */
+ bo->storage_hint = NULL;
+ bo->do_esi = 0;
+ bo->do_stream = 1;
+
+ /* reset fetch processors */
+ vfc->failed = 0;
+ VFP_Close(vfc);
+ VFP_Setup(vfc);
+
// XXX: BereqEnd + BereqAcct ?
VSL_ChgId(bo->vsl, "bereq", "retry", VXID_Get(wrk, VSL_BACKENDMARKER));
VSLb_ts_busyobj(bo, "Start", bo->t_prev);
@@ -405,11 +425,12 @@ vbf_stp_startfetch(struct worker *wrk, struct busyobj *bo)
if (wrk->handling == VCL_RET_RETRY) {
bo->doclose = SC_RESP_CLOSE;
- VDI_Finish(bo->director_resp, bo->wrk, bo);
- bo->doclose = SC_NULL;
- bo->retries++;
- if (bo->retries <= cache_param->max_retries)
+ if (bo->director_state != DIR_S_NULL)
+ VDI_Finish(bo->director_resp, bo->wrk, bo);
+
+ if (bo->retries++ < cache_param->max_retries)
return (F_STP_RETRY);
+
VSLb(bo->vsl, SLT_VCL_Error,
"Too many retries, delivering 503");
assert(bo->director_state == DIR_S_NULL);
@@ -608,7 +629,7 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)
assert(bo->refcount >= 1);
- assert (bo->state == BOS_REQ_DONE);
+ assert(bo->state == BOS_REQ_DONE);
if (bo->do_stream) {
HSH_Unbusy(wrk, bo->fetch_objcore);
@@ -766,8 +787,14 @@ vbf_stp_error(struct worker *wrk, struct busyobj *bo)
if (wrk->handling == VCL_RET_RETRY) {
VSB_delete(bo->synth_body);
bo->synth_body = NULL;
+
+ bo->doclose = SC_RESP_CLOSE;
+ if (bo->director_state != DIR_S_NULL)
+ VDI_Finish(bo->director_resp, bo->wrk, bo);
+
if (bo->retries++ < cache_param->max_retries)
return (F_STP_RETRY);
+
return (F_STP_FAIL);
}
diff --git a/bin/varnishtest/tests/r01638.vtc b/bin/varnishtest/tests/r01638.vtc
new file mode 100644
index 0000000..2ddebbb
--- /dev/null
+++ b/bin/varnishtest/tests/r01638.vtc
@@ -0,0 +1,49 @@
+varnishtest "Test retry of straight insufficient bytes pass-fetch : do_stream = false"
+
+server s1 {
+ rxreq
+ txresp -hdr "Content-Length: 10000" -nolen -bodylen 5000
+}
+
+server s2 {
+ rxreq
+ txresp -bodylen 5
+}
+
+server s1 -start
+server s2 -start
+
+varnish v1 -vcl+backend {
+ sub vcl_recv {
+ return (pass);
+ }
+ sub vcl_backend_fetch {
+ set bereq.between_bytes_timeout = 10s;
+ if (bereq.retries == 0) {
+ set bereq.backend = s1;
+ } else {
+ set bereq.backend = s2;
+ }
+ }
+ sub vcl_backend_response {
+ set beresp.do_stream = false;
+ }
+ sub vcl_backend_error {
+ if (bereq.retries == 0) {
+ return (retry);
+ } else {
+ return (deliver);
+ }
+ }
+} -start
+
+client c1 {
+ timeout 10
+ txreq -url "/"
+ rxresp
+ expect resp.status == 200
+ expect resp.bodylen == 5
+} -run
+
+server s1 -wait
+server s2 -wait
diff --git a/bin/varnishtest/tests/r01641.vtc b/bin/varnishtest/tests/r01641.vtc
new file mode 100644
index 0000000..1dddc85
--- /dev/null
+++ b/bin/varnishtest/tests/r01641.vtc
@@ -0,0 +1,49 @@
+varnishtest "Test retry of straight insufficient bytes pass-fetch : do_esi = true"
+
+server s1 {
+ rxreq
+ txresp -hdr "Content-Length: 10000" -nolen -bodylen 5000
+}
+
+server s2 {
+ rxreq
+ txresp -bodylen 5
+}
+
+server s1 -start
+server s2 -start
+
+varnish v1 -vcl+backend {
+ sub vcl_recv {
+ return (pass);
+ }
+ sub vcl_backend_fetch {
+ set bereq.between_bytes_timeout = 10s;
+ if (bereq.retries == 0) {
+ set bereq.backend = s1;
+ } else {
+ set bereq.backend = s2;
+ }
+ }
+ sub vcl_backend_response {
+ set beresp.do_esi = true;
+ }
+ sub vcl_backend_error {
+ if (bereq.retries == 0) {
+ return (retry);
+ } else {
+ return (deliver);
+ }
+ }
+} -start
+
+client c1 {
+ timeout 10
+ txreq -url "/"
+ rxresp
+ expect resp.status == 200
+ expect resp.bodylen == 5
+} -run
+
+server s1 -wait
+server s2 -wait
More information about the varnish-commit
mailing list