|
42 | 42 | #include "vbm.h" |
43 | 43 |
|
44 | 44 | #include "cache_director.h" |
| 45 | +#include "cache_transport.h" |
45 | 46 | #include "cache_vcl.h" |
46 | 47 | #include "vcc_interface.h" |
47 | 48 |
|
@@ -521,6 +522,40 @@ VRT_VCL_Allow_Discard(struct vclref **refp) |
521 | 522 | FREE_OBJ(ref); |
522 | 523 | } |
523 | 524 |
|
| 525 | +/*-------------------------------------------------------------------- |
| 526 | + */ |
| 527 | + |
| 528 | +static int |
| 529 | +req_poll(struct worker *wrk, struct req *req) |
| 530 | +{ |
| 531 | + struct req *top; |
| 532 | + |
| 533 | + /* NB: Since a fail transition leads to vcl_synth, the request may be |
| 534 | + * short-circuited twice. |
| 535 | + */ |
| 536 | + if (req->req_reset) { |
| 537 | + wrk->vpi->handling = VCL_RET_FAIL; |
| 538 | + return (-1); |
| 539 | + } |
| 540 | + |
| 541 | + top = req->top->topreq; |
| 542 | + CHECK_OBJ_NOTNULL(top, REQ_MAGIC); |
| 543 | + CHECK_OBJ_NOTNULL(top->transport, TRANSPORT_MAGIC); |
| 544 | + |
| 545 | + if (!FEATURE(FEATURE_VCL_REQ_RESET)) |
| 546 | + return (0); |
| 547 | + if (top->transport->poll == NULL) |
| 548 | + return (0); |
| 549 | + if (top->transport->poll(top) >= 0) |
| 550 | + return (0); |
| 551 | + |
| 552 | + VSLb_ts_req(req, "Reset", W_TIM_real(wrk)); |
| 553 | + wrk->stats->req_reset++; |
| 554 | + wrk->vpi->handling = VCL_RET_FAIL; |
| 555 | + req->req_reset = 1; |
| 556 | + return (-1); |
| 557 | +} |
| 558 | + |
524 | 559 | /*-------------------------------------------------------------------- |
525 | 560 | * Method functions to call into VCL programs. |
526 | 561 | * |
@@ -552,6 +587,8 @@ vcl_call_method(struct worker *wrk, struct req *req, struct busyobj *bo, |
552 | 587 | CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC); |
553 | 588 | CHECK_OBJ_NOTNULL(req->vcl, VCL_MAGIC); |
554 | 589 | CHECK_OBJ_NOTNULL(req->top, REQTOP_MAGIC); |
| 590 | + if (req_poll(wrk, req)) |
| 591 | + return; |
555 | 592 | VCL_Req2Ctx(&ctx, req); |
556 | 593 | } |
557 | 594 | assert(ctx.now != 0); |
|
0 commit comments