<div class="gmail_quote">On Thu, Dec 3, 2009 at 11:14 PM, Igor Sysoev <span dir="ltr"><<a href="mailto:igor@sysoev.ru">igor@sysoev.ru</a>></span> wrote:</div><div class="gmail_quote">[...]<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div><div></div><div class="h5">As it was already said, you should mark a buf as consumed:</div></div>
<br>
buf->pos = buf->last;<br></blockquote><div><br></div><div>Thanks. What is the right thing to do if a body filter consumes</div><div>only part of a buf and sets aside the rest for later?</div><div><br></div><div>
SSI filtering is an example of what I'm thinking of. There might</div><div>be an incomplete SSI directive at the end of a buf, so the SSI</div><div>parser needs to output everything prior to that directive and</div>
<div>
set aside the incomplete directive to finish parsing later when</div><div>it has more data.</div><div><br></div><div>If a body filter is only able to process part of a buf, is it safe</div><div>to do this:</div><div><br>
</div>
<div>ngx_int_t</div><div>my_body_filter(ngx_http_request_t *r, ngx_chain_t *in)</div><div>{</div><div> my_module_ctx *my_ctx = ngx_http_get_module_loc_conf(r, my_module);</div><div> u_char *split;</div><div> ngx_buf_t *setaside_buf;</div>
<div><br></div><div> /* Do some parsing of the content in buf to find the point at</div><div> which we need to split it. Everything prior to split can be</div><div> output immediately. Everything after split needs to be</div>
<div> saved until later. */</div><div> split = [some point between in->buf->pos and in->buf->last];</div><div><br></div><div> /* Create a new buf holding everything after the split point*/</div><div> setaside_buf = ngx_calloc_buf(r->pool);</div>
<div> setaside_buf->pos = split;</div><div> setaside_buf->last = in->buf->last;</div><div><br></div><div> /* Terminate the original buf at the split point */</div><div> in->buf->last = split;</div><div>
<br></div><div> /* Save everything after the split point */</div><div> my_ctx->setaside = setaside_buf;</div><div><br></div><div> /* Output everything before the split point */</div><div> return ngx_next_body_filter(r, in);</div>
<div>}</div><div><br></div><div>And assuming that code is safe, what does the body filter need</div><div>to do later when it finally finishes processing the data in the</div><div>setaside_buf? I imagine it needs to somehow tell the Nginx</div>
<div>core that it's done holding onto that buf.</div><div><br></div><div>My prior experience with this sort of thing is in Apache 2, where</div><div>the buckets (Apache's equivalent to Nginx's bufs) use reference</div>
<div>counts, so the right way to split a buffer is to increment its</div><div>reference count when splitting and decrement the reference</div><div>count after using the setaside portion. What's the equivalent</div><div>
idiom in Nginx?</div><div><br></div><div>I know I can avoid this issue entirely if I make a copy of</div><div>the data after the split point and set in->buf->pos=in->buf->last</div><div>to release the original buf, but I want to do zero-copy. :-)</div>
<div><br></div><div>Thanks,</div><div>-Brian</div><div><br></div></div>