static enum fetch_step vbf_stp_error(struct worker *wrk, struct busyobj *bo) { ssize_t l, ll, o; double now; uint8_t *ptr; struct vsb *synth_body; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); CHECK_OBJ_NOTNULL(bo->fetch_objcore, OBJCORE_MAGIC); AN(bo->fetch_objcore->flags & OC_F_BUSY); assert(bo->director_state == DIR_S_NULL); wrk->stats->fetch_failed++; now = W_TIM_real(wrk); VSLb_ts_busyobj(bo, "Error", now); if (bo->fetch_objcore->stobj->stevedore != NULL) ObjFreeObj(bo->wrk, bo->fetch_objcore); if (bo->storage == NULL) bo->storage = STV_next(); // XXX: reset all beresp flags ? HTTP_Setup(bo->beresp, bo->ws, bo->vsl, SLT_BerespMethod); http_PutResponse(bo->beresp, "HTTP/1.1", 503, "Backend fetch failed"); http_TimeHeader(bo->beresp, "Date: ", now); http_SetHeader(bo->beresp, "Server: Varnish"); bo->fetch_objcore->t_origin = now; if (!VTAILQ_EMPTY(&bo->fetch_objcore->objhead->waitinglist)) { /* * If there is a waitinglist, it means that there is no * grace-able object, so cache the error return for a * short time, so the waiting list can drain, rather than * each objcore on the waiting list sequentially attempt * to fetch from the backend. */ bo->fetch_objcore->ttl = 1; bo->fetch_objcore->grace = 5; bo->fetch_objcore->keep = 5; } else { bo->fetch_objcore->ttl = 0; bo->fetch_objcore->grace = 0; bo->fetch_objcore->keep = 0; } synth_body = VSB_new_auto(); AN(synth_body); VCL_backend_error_method(bo->vcl, wrk, NULL, bo, synth_body); AZ(VSB_finish(synth_body)); if (wrk->handling == VCL_RET_ABANDON || wrk->handling == VCL_RET_FAIL) { VSB_destroy(&synth_body); return (F_STP_FAIL); } if (wrk->handling == VCL_RET_RETRY) { VSB_destroy(&synth_body); if (bo->retries++ < cache_param->max_retries) return (F_STP_RETRY); VSLb(bo->vsl, SLT_VCL_Error, "Too many retries, failing"); return (F_STP_FAIL); } assert(wrk->handling == VCL_RET_DELIVER); assert(bo->vfc->wrk == bo->wrk); assert(bo->vfc->oc == bo->fetch_objcore); assert(bo->vfc->resp == bo->beresp); assert(bo->vfc->req == bo->bereq); if (vbf_beresp2obj(bo)) { (void)VFP_Error(bo->vfc, "Could not get storage"); VSB_destroy(&synth_body); return (F_STP_FAIL); } ll = VSB_len(synth_body); o = 0; while (ll > 0) { l = ll; if (VFP_GetStorage(bo->vfc, &l, &ptr) != VFP_OK) break; if (l > ll) l = ll; memcpy(ptr, VSB_data(synth_body) + o, l); VFP_Extend(bo->vfc, l); ll -= l; o += l; } AZ(ObjSetU64(wrk, bo->fetch_objcore, OA_LEN, o)); VSB_destroy(&synth_body); HSH_Unbusy(wrk, bo->fetch_objcore); ObjSetState(wrk, bo->fetch_objcore, BOS_FINISHED); return (F_STP_DONE); }
static enum fetch_step vbf_stp_error(struct worker *wrk, struct busyobj *bo) { struct storage *st; ssize_t l; double now; char time_str[VTIM_FORMAT_SIZE]; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); now = W_TIM_real(wrk); VSLb_ts_busyobj(bo, "Error", now); AN(bo->fetch_objcore->flags & OC_F_BUSY); AZ(bo->synth_body); bo->synth_body = VSB_new_auto(); AN(bo->synth_body); // XXX: reset all beresp flags ? HTTP_Setup(bo->beresp, bo->ws, bo->vsl, SLT_BerespMethod); http_PutResponse(bo->beresp, "HTTP/1.1", 503, "Backend fetch failed"); VTIM_format(now, time_str); http_PrintfHeader(bo->beresp, "Date: %s", time_str); http_SetHeader(bo->beresp, "Server: Varnish"); bo->fetch_objcore->exp.t_origin = bo->t_prev; bo->fetch_objcore->exp.ttl = 0; bo->fetch_objcore->exp.grace = 0; bo->fetch_objcore->exp.keep = 0; VCL_backend_error_method(bo->vcl, wrk, NULL, bo, bo->bereq->ws); AZ(VSB_finish(bo->synth_body)); if (wrk->handling == VCL_RET_RETRY) { VSB_delete(bo->synth_body); bo->synth_body = NULL; if (bo->retries++ < cache_param->max_retries) return (F_STP_RETRY); bo->synth_body = NULL; return (F_STP_FAIL); } assert(wrk->handling == VCL_RET_DELIVER); VFP_Setup(bo->vfc); bo->vfc->bo = bo; bo->vfc->http = bo->beresp; bo->vfc->vsl = bo->vsl; if (vbf_beresp2obj(bo)) return (F_STP_FAIL); bo->vfc->body = bo->fetch_obj->body; l = VSB_len(bo->synth_body); if (l > 0) { st = VFP_GetStorage(bo->vfc, l); if (st != NULL) { if (st->space < l) { VSLb(bo->vsl, SLT_Error, "No space for %zd bytes of synth body", l); } else { memcpy(st->ptr, VSB_data(bo->synth_body), l); VBO_extend(bo, l); } } } VSB_delete(bo->synth_body); bo->synth_body = NULL; HSH_Unbusy(&wrk->stats, bo->fetch_objcore); VBO_setstate(bo, BOS_FINISHED); return (F_STP_DONE); }
static enum fetch_step vbf_stp_error(struct worker *wrk, struct busyobj *bo) { ssize_t l, ll, o; double now; uint8_t *ptr; struct vsb *synth_body; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); CHECK_OBJ_NOTNULL(bo->fetch_objcore, OBJCORE_MAGIC); assert(bo->director_state == DIR_S_NULL); if(bo->fetch_objcore->stobj->stevedore != NULL) ObjFreeObj(bo->wrk, bo->fetch_objcore); now = W_TIM_real(wrk); VSLb_ts_busyobj(bo, "Error", now); AN(bo->fetch_objcore->flags & OC_F_BUSY); synth_body = VSB_new_auto(); AN(synth_body); // XXX: reset all beresp flags ? HTTP_Setup(bo->beresp, bo->ws, bo->vsl, SLT_BerespMethod); http_PutResponse(bo->beresp, "HTTP/1.1", 503, "Backend fetch failed"); http_TimeHeader(bo->beresp, "Date: ", now); http_SetHeader(bo->beresp, "Server: Varnish"); EXP_Clr(&bo->fetch_objcore->exp); bo->fetch_objcore->exp.t_origin = bo->t_prev; VCL_backend_error_method(bo->vcl, wrk, NULL, bo, synth_body); AZ(VSB_finish(synth_body)); if (wrk->handling == VCL_RET_RETRY || wrk->handling == VCL_RET_ABANDON) { VSB_delete(synth_body); if (bo->director_state != DIR_S_NULL) { bo->htc->doclose = SC_RESP_CLOSE; VDI_Finish(bo->wrk, bo); } if (wrk->handling == VCL_RET_RETRY) { if (bo->retries++ < cache_param->max_retries) return (F_STP_RETRY); VSLb(bo->vsl, SLT_VCL_Error, "Too many retries, delivering 503"); } return (F_STP_FAIL); } assert(wrk->handling == VCL_RET_DELIVER); bo->vfc->bo = bo; bo->vfc->wrk = bo->wrk; bo->vfc->oc = bo->fetch_objcore; bo->vfc->http = bo->beresp; bo->vfc->esi_req = bo->bereq; if (vbf_beresp2obj(bo)) { VSB_delete(synth_body); return (F_STP_FAIL); } ll = VSB_len(synth_body); o = 0; while (ll > 0) { l = ll; if (VFP_GetStorage(bo->vfc, &l, &ptr) != VFP_OK) break; memcpy(ptr, VSB_data(synth_body) + o, l); VBO_extend(bo, l); ll -= l; o += l; } VSB_delete(synth_body); HSH_Unbusy(wrk, bo->fetch_objcore); VBO_setstate(bo, BOS_FINISHED); return (F_STP_DONE); }
static enum fetch_step vbf_stp_error(struct worker *wrk, struct busyobj *bo) { ssize_t l, ll, o; double now; uint8_t *ptr; char time_str[VTIM_FORMAT_SIZE]; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); assert(bo->director_state == DIR_S_NULL); now = W_TIM_real(wrk); VSLb_ts_busyobj(bo, "Error", now); AN(bo->fetch_objcore->flags & OC_F_BUSY); AZ(bo->synth_body); bo->synth_body = VSB_new_auto(); AN(bo->synth_body); // XXX: reset all beresp flags ? HTTP_Setup(bo->beresp, bo->ws, bo->vsl, SLT_BerespMethod); http_PutResponse(bo->beresp, "HTTP/1.1", 503, "Backend fetch failed"); VTIM_format(now, time_str); http_PrintfHeader(bo->beresp, "Date: %s", time_str); http_SetHeader(bo->beresp, "Server: Varnish"); bo->fetch_objcore->exp.t_origin = bo->t_prev; bo->fetch_objcore->exp.ttl = 0; bo->fetch_objcore->exp.grace = 0; bo->fetch_objcore->exp.keep = 0; VCL_backend_error_method(bo->vcl, wrk, NULL, bo, bo->bereq->ws); AZ(VSB_finish(bo->synth_body)); if (wrk->handling == VCL_RET_RETRY) { VSB_delete(bo->synth_body); bo->synth_body = NULL; if (bo->retries++ < cache_param->max_retries) return (F_STP_RETRY); return (F_STP_FAIL); } assert(wrk->handling == VCL_RET_DELIVER); VFP_Setup(bo->vfc); bo->vfc->bo = bo; bo->vfc->wrk = bo->wrk; bo->vfc->oc = bo->fetch_objcore; bo->vfc->http = bo->beresp; bo->vfc->esi_req = bo->bereq; if (vbf_beresp2obj(bo)) return (F_STP_FAIL); ll = VSB_len(bo->synth_body); o = 0; while (ll > 0) { l = ll; if (VFP_GetStorage(bo->vfc, &l, &ptr) != VFP_OK) break; memcpy(ptr, VSB_data(bo->synth_body) + o, l); VBO_extend(bo, l); ll -= l; o += l; } VSB_delete(bo->synth_body); bo->synth_body = NULL; HSH_Unbusy(wrk, bo->fetch_objcore); VBO_setstate(bo, BOS_FINISHED); return (F_STP_DONE); }