Buffer reuse like gzip filter module, with pre-configured number of buffers
hanzhai
nginx-forum at forum.nginx.org
Wed Jun 1 12:22:16 UTC 2022
Hi Maxim,
Thanks for your reply. Your guide made me understand thoroughly the role of
calling ngx_http_next_body_filter(r, NULL) in the gzip module which helped a
lot. The buffer now can be reused but I still got one issue that confused me
a lot.
I got curl: (18) transfer closed with outstanding read data remaining error
when I access the path the code modified. I captured packets through tcpdump
and the last packet containing the response was marked as Malformed Packet.
Here's the code:
if (ctx->nomem) {
if (ngx_http_next_body_filter(r, NULL) == NGX_ERROR) {
goto failed;
}
ngx_chain_t *cl = NULL;
ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &cl,
(ngx_buf_tag_t) &ngx_http_my_filter_module);
ctx->nomem = 0;
flush = 0;
} else {
flush = ctx->busy ? 1 : 0;
}
for (;;) {
/* cycle while we can write to a client */
for (;;) {
/* cycle while there is data to insert into the beginning */
rc = ngx_http_my_get_buf(r, ctx);
if (rc == NGX_DECLINED) {
break;
}
if (rc == NGX_ERROR) {
goto failed;
}
/* there are buffers to write data */
// rc = operation to copy 64 kb data to the ctx->out_buf;
ctx->out_buf->last = ctx->out_buf->pos + 64 * 4096;
ngx_chain_t *cl = ngx_alloc_chain_link(r->pool);
if (cl == NULL) {
goto failed;
}
cl->buf = ctx->out_buf;
cl->next = NULL;
*ctx->last_out = cl;
ctx->last_out = &cl->next;
if (rc == OK) {
ctx->stage = DONE;
break;
}
/* rc == NGX_AGAIN */
}
if (ctx->out == NULL && !flush) {
return ctx->busy ? NGX_AGAIN : NGX_OK;
}
ngx_chain_t *a = ctx->out;
while (a) {
if (ngx_buf_size(a->buf)) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "beign: %*s,
end: %*s",
10, a->buf->pos, 10, a->buf->last - 10); // add logging to make
sure the buf is complete, all buf were logged
}
a = a->next;
}
rc = ngx_http_next_body_filter(r, ctx->out);
if (rc == NGX_ERROR) {
goto failed;
}
ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &ctx->out,
(ngx_buf_tag_t) &ngx_http_my_filter_module);
ctx->last_out = &ctx->out;
ctx->nomem = 0;
flush = 0;
if (ctx->stage == DONE) {
return rc;
}
}
static ngx_int_t ngx_http_my_get_buf(ngx_http_request_t *r,
ngx_http_my_ctx_t *ctx) {
ngx_chain_t *cl;
ngx_http_my_loc_conf_t *conf = ngx_http_get_module_loc_conf(r,
ngx_http_my_filter_module);
if (ctx->free) {
cl = ctx->free;
ctx->out_buf = cl->buf;
ctx->free = cl->next;
ngx_free_chain(r->pool, cl);
} else if (ctx->bufs < conf->bufs.num) {
ctx->out_buf = ngx_create_temp_buf(r->pool, conf->bufs.size);
if (ctx->out_buf == NULL) {
return NGX_ERROR;
}
ctx->out_buf->tag = (ngx_buf_tag_t) &ngx_http_my_filter_module;
ctx->out_buf->recycled = 1;
ctx->bufs++;
} else {
ctx->nomem = 1;
return NGX_DECLINED;
}
return NGX_OK;
}
Posted at Nginx Forum: https://forum.nginx.org/read.php?2,294374,294385#msg-294385
More information about the nginx
mailing list