Usage of the shadow field in ngx_buf_t?

Brian Pane brianp at brianp.net
Sun Dec 6 03:06:57 MSK 2009


On Thu, Dec 3, 2009 at 11:14 PM, Igor Sysoev <igor at sysoev.ru> wrote:
[...]

> As it was already said, you should mark a buf as consumed:
>
>   buf->pos = buf->last;
>

Thanks.  What is the right thing to do if a body filter consumes
only part of a buf and sets aside the rest for later?

SSI filtering is an example of what I'm thinking of.  There might
be an incomplete SSI directive at the end of a buf, so the SSI
parser needs to output everything prior to that directive and
set aside the incomplete directive to finish parsing later when
it has more data.

If a body filter is only able to process part of a buf, is it safe
to do this:

ngx_int_t
my_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
  my_module_ctx *my_ctx = ngx_http_get_module_loc_conf(r, my_module);
  u_char *split;
  ngx_buf_t *setaside_buf;

  /* Do some parsing of the content in buf to find the point at
     which we need to split it.  Everything prior to split can be
     output immediately.  Everything after split needs to be
     saved until later. */
  split = [some point between in->buf->pos and in->buf->last];

  /* Create a new buf holding everything after the split point*/
  setaside_buf = ngx_calloc_buf(r->pool);
  setaside_buf->pos = split;
  setaside_buf->last = in->buf->last;

  /* Terminate the original buf at the split point */
  in->buf->last = split;

  /* Save everything after the split point */
  my_ctx->setaside = setaside_buf;

  /* Output everything before the split point */
  return ngx_next_body_filter(r, in);
}

And assuming that code is safe, what does the body filter need
to do later when it finally finishes processing the data in the
setaside_buf?  I imagine it needs to somehow tell the Nginx
core that it's done holding onto that buf.

My prior experience with this sort of thing is in Apache 2, where
the buckets (Apache's equivalent to Nginx's bufs) use reference
counts, so the right way to split a buffer is to increment its
reference count when splitting and decrement the reference
count after using the setaside portion.  What's the equivalent
idiom in Nginx?

I know I can avoid this issue entirely if I make a copy of
the data after the split point and set in->buf->pos=in->buf->last
to release the original buf, but I want to do zero-copy. :-)

Thanks,
-Brian
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://nginx.org/pipermail/nginx-devel/attachments/20091205/9b4c91bd/attachment.html>


More information about the nginx-devel mailing list