static enum fetch_step vbf_stp_startfetch(struct worker *wrk, struct busyobj *bo) { CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); AN(bo->director); AZ(bo->vbc); AZ(bo->should_close); AZ(bo->storage_hint); HTTP_Setup(bo->bereq, bo->ws, bo->vsl, HTTP_Bereq); HTTP_Copy(bo->bereq, bo->bereq0); VCL_backend_fetch_method(bo->vcl, wrk, NULL, bo, bo->bereq->ws); bo->uncacheable = bo->do_pass; http_PrintfHeader(bo->bereq, "X-Varnish: %u", bo->vsl->wid & VSL_IDENTMASK); if (wrk->handling == VCL_RET_ABANDON) { if (bo->req != NULL) vbf_release_req(bo); (void)VFP_Error(bo, "Abandoned in vcl_backend_fetch"); return (F_STP_DONE); } assert (wrk->handling == VCL_RET_FETCH); return (F_STP_FETCHHDR); }
static enum fetch_step vbf_stp_abandon(struct worker *wrk, struct busyobj *bo) { CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); assert(bo->state == BOS_FAILED); vbf_release_req(bo); VBO_DerefBusyObj(wrk, &bo); // XXX ? return (F_STP_DONE); }
static enum fetch_step vbf_stp_fetchhdr(struct worker *wrk, struct busyobj *bo) { int i; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); xxxassert (wrk->handling == VCL_RET_FETCH); HTTP_Setup(bo->beresp, bo->ws, bo->vsl, HTTP_Beresp); if (!bo->do_pass) vbf_release_req(bo); /* XXX: retry ?? */ assert(bo->state == BOS_INVALID); i = V1F_fetch_hdr(wrk, bo, bo->req); /* * If we recycle a backend connection, there is a finite chance * that the backend closed it before we get a request to it. * Do a single retry in that case. */ if (i == 1) { VSC_C_main->backend_retry++; i = V1F_fetch_hdr(wrk, bo, bo->req); } if (bo->do_pass) vbf_release_req(bo); /* XXX : retry ?? */ AZ(bo->req); if (i) { AZ(bo->vbc); bo->err_code = 503; http_SetH(bo->beresp, HTTP_HDR_PROTO, "HTTP/1.1"); http_SetResp(bo->beresp, "HTTP/1.1", 503, "Backend fetch failed"); http_SetHeader(bo->beresp, "Content-Length: 0"); http_SetHeader(bo->beresp, "Connection: close"); } else { AN(bo->vbc); } /* * These two headers can be spread over multiple actual headers * and we rely on their content outside of VCL, so collect them * into one line here. */ http_CollectHdr(bo->beresp, H_Cache_Control); http_CollectHdr(bo->beresp, H_Vary); /* * Figure out how the fetch is supposed to happen, before the * headers are adultered by VCL * NB: Also sets other wrk variables */ bo->htc.body_status = RFC2616_Body(bo, &wrk->stats); bo->err_code = http_GetStatus(bo->beresp); /* * What does RFC2616 think about TTL ? */ EXP_Clr(&bo->exp); bo->exp.entered = W_TIM_real(wrk); RFC2616_Ttl(bo); /* pass from vclrecv{} has negative TTL */ if (bo->fetch_objcore->objhead == NULL) bo->exp.ttl = -1.; AZ(bo->do_esi); VCL_backend_response_method(bo->vcl, wrk, NULL, bo, bo->beresp->ws); if (bo->do_esi) bo->do_stream = 0; if (wrk->handling == VCL_RET_DELIVER) return (F_STP_FETCH); if (wrk->handling == VCL_RET_RETRY) { assert(bo->state == BOS_INVALID); bo->retries++; if (bo->retries <= cache_param->max_retries) { VDI_CloseFd(&bo->vbc); return (F_STP_STARTFETCH); } // XXX: wrk->handling = VCL_RET_SYNTH; } return (F_STP_NOTYET); }
static enum fetch_step vbf_stp_fetchhdr(struct worker *wrk, struct busyobj *bo) { int i, do_ims; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); xxxassert (wrk->handling == VCL_RET_FETCH); HTTP_Setup(bo->beresp, bo->ws, bo->vsl, HTTP_Beresp); if (!bo->do_pass && bo->req != NULL) vbf_release_req(bo); /* XXX: retry ?? */ assert(bo->state <= BOS_REQ_DONE); i = V1F_fetch_hdr(wrk, bo, bo->req); /* * If we recycle a backend connection, there is a finite chance * that the backend closed it before we get a request to it. * Do a single retry in that case. */ if (i == 1) { VSC_C_main->backend_retry++; i = V1F_fetch_hdr(wrk, bo, bo->req); } if (bo->do_pass && bo->req != NULL) vbf_release_req(bo); /* XXX : retry ?? */ AZ(bo->req); if (i) { AZ(bo->vbc); make_it_503(bo); } else { AN(bo->vbc); } /* * These two headers can be spread over multiple actual headers * and we rely on their content outside of VCL, so collect them * into one line here. */ http_CollectHdr(bo->beresp, H_Cache_Control); http_CollectHdr(bo->beresp, H_Vary); /* * Figure out how the fetch is supposed to happen, before the * headers are adultered by VCL * NB: Also sets other wrk variables */ bo->htc.body_status = RFC2616_Body(bo, &wrk->stats); if (i && bo->htc.body_status == BS_LENGTH) bo->htc.body_status = BS_NONE; bo->err_code = http_GetStatus(bo->beresp); /* * What does RFC2616 think about TTL ? */ EXP_Clr(&bo->exp); RFC2616_Ttl(bo); /* private objects have negative TTL */ if (bo->fetch_objcore->flags & OC_F_PRIVATE) bo->exp.ttl = -1.; AZ(bo->do_esi); if (bo->ims_obj != NULL && bo->beresp->status == 304) { bo->beresp->status = 200; http_PrintfHeader(bo->beresp, "Content-Length: %jd", (intmax_t)bo->ims_obj->len); do_ims = 1; } else do_ims = 0; VCL_backend_response_method(bo->vcl, wrk, NULL, bo, bo->beresp->ws); if (bo->do_esi) bo->do_stream = 0; if (bo->do_pass) bo->fetch_objcore->flags |= OC_F_PASS; if (wrk->handling == VCL_RET_DELIVER) return (do_ims ? F_STP_CONDFETCH : F_STP_FETCH); if (wrk->handling == VCL_RET_RETRY) { assert(bo->state == BOS_REQ_DONE); bo->retries++; if (bo->retries <= cache_param->max_retries) { VDI_CloseFd(&bo->vbc); return (F_STP_STARTFETCH); } // XXX: wrk->handling = VCL_RET_SYNTH; } INCOMPL(); }