ctx->sent += total;
ctx->data_sent += data_len;
ctx->rem_data = rem_data + blksz;
+ appctx->to_forward -= data_len;
return total;
}
return total;
}
-
-static void ff_cache_skip_tlr_blk(struct appctx *appctx, uint32_t info, struct shared_block *shblk, unsigned int offset)
-{
- struct cache_appctx *ctx = appctx->svcctx;
- struct cache_flt_conf *cconf = appctx->rule->arg.act.p[0];
- struct shared_context *shctx = shctx_ptr(cconf->c.cache);
- unsigned int max, total;
- uint32_t blksz;
-
- blksz = (info & 0xff) + ((info >> 8) & 0xfffff);
- total = 4;
- while (blksz) {
- max = MIN(blksz, shctx->block_size - offset);
- offset += max;
- blksz -= max;
- total += max;
- if (blksz || offset == shctx->block_size) {
- shblk = LIST_NEXT(&shblk->list, typeof(shblk), list);
- offset = 0;
- }
- }
- ctx->offset = offset;
- ctx->next = shblk;
- ctx->sent += total;
-}
-
static unsigned int ff_cache_dump_data_blk(struct appctx *appctx, struct buffer *buf, unsigned int len,
uint32_t info, struct shared_block *shblk, unsigned int offset)
{
ctx->sent += total;
ctx->data_sent += data_len;
ctx->rem_data = rem_data + blksz;
+ appctx->to_forward -= data_len;
return total;
}
-static __maybe_unused size_t ff_cache_dump_msg(struct appctx *appctx, struct buffer *buf, unsigned int len)
+static size_t ff_cache_dump_msg(struct appctx *appctx, struct buffer *buf, unsigned int len)
{
struct cache_appctx *ctx = appctx->svcctx;
struct cache_entry *cache_ptr = ctx->entry;
add_data_blk:
ret = ff_cache_dump_data_blk(appctx, buf, len, info, shblk, offset);
}
- else if (type == HTX_BLK_TLR) {
- ff_cache_skip_tlr_blk(appctx, info, shblk, offset);
- BUG_ON(ctx->sent != first->len - sizeof(*cache_ptr));
- ret = 0;
- }
- else {
- sc_ep_clr(appctx_sc(appctx), SE_FL_MAY_FASTFWD);
+ else
ret = 0;
- }
if (!ret)
break;
return 1;
}
+static size_t http_cache_fastfwd(struct appctx *appctx, struct buffer *buf, size_t count, unsigned int flags)
+{
+ struct cache_appctx *ctx = appctx->svcctx;
+ struct cache_entry *cache_ptr = ctx->entry;
+ struct shared_block *first = block_ptr(cache_ptr);
+ size_t ret;
+
+ BUG_ON(!appctx->to_forward || count > appctx->to_forward);
+
+ ret = ff_cache_dump_msg(appctx, buf, count);
+
+ if (!appctx->to_forward) {
+ se_fl_clr(appctx->sedesc, SE_FL_MAY_FASTFWD);
+ if (ctx->sent == first->len - sizeof(*cache_ptr)) {
+ applet_set_eoi(appctx);
+ applet_set_eos(appctx);
+ BUG_ON(ctx->data_sent != cache_ptr->body_size);
+ appctx->st0 = HTX_CACHE_END;
+ }
+ }
+ return ret;
+}
+
static void http_cache_io_handler(struct appctx *appctx)
{
struct cache_appctx *ctx = appctx->svcctx;
if (applet_fl_test(appctx, APPCTX_FL_OUTBLK_ALLOC|APPCTX_FL_OUTBLK_FULL))
goto exit;
+ if (se_fl_test(appctx->sedesc, SE_FL_MAY_FASTFWD))
+ goto exit;
if (!appctx_get_buf(appctx, &appctx->outbuf)) {
appctx->flags |= APPCTX_FL_OUTBLK_ALLOC;
if (find_http_meth(istptr(meth), istlen(meth)) == HTTP_METH_HEAD || ctx->send_notmodified)
appctx->st0 = HTX_CACHE_EOM;
else {
+ if (!(global.tune.no_zero_copy_fwd & (NO_ZERO_COPY_FWD|NO_ZERO_COPY_FWD_CACHE)))
+ se_fl_set(appctx->sedesc, SE_FL_MAY_FASTFWD);
+
+ appctx->to_forward = cache_ptr->body_size;
len = first->len - sizeof(*cache_ptr) - ctx->sent;
appctx->st0 = HTX_CACHE_DATA;
}
goto out;
}
}
+ BUG_ON(appctx->to_forward);
BUG_ON(ctx->data_sent != cache_ptr->body_size);
appctx->st0 = HTX_CACHE_EOM;
}
/* no more data are expected. */
res_htx->flags |= HTX_FL_EOM;
applet_set_eoi(appctx);
+ se_fl_clr(appctx->sedesc, SE_FL_MAY_FASTFWD);
appctx->st0 = HTX_CACHE_END;
}
/* eat the whole request */
b_reset(&appctx->inbuf);
applet_fl_clr(appctx, APPCTX_FL_INBLK_FULL);
+ appctx->sedesc->iobuf.flags &= ~IOBUF_FL_FF_BLOCKED;
return;
error:
.fct = http_cache_io_handler,
.rcv_buf = appctx_rcv_buf,
.snd_buf = appctx_snd_buf,
+ .fastfwd = http_cache_fastfwd,
.release = http_cache_applet_release,
};