httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Eric Prud'hommeaux" <>
Subject Re: appending to the content brigade
Date Fri, 24 Aug 2001 19:42:33 GMT
On Fri, Aug 24, 2001 at 02:43:28PM -0400, Cliff Woolley wrote:
> On Fri, 24 Aug 2001, Eric Prud'hommeaux wrote:
> > I'm implementing a content filter which wraps the content in multipart
> > mime. I can generate a separator, my data, separator, original payload
> > and separator. The problem is that if I just concatonate the brigades,
> > I end up with an EOS before my final separator.
> All you have to do is delete the EOS bucket and then do your concat.
> That's a constant time operation as opposed to a foreach loop which is a
> linear time operation.

I figured there was some way to leverage off the end pointer but had
spaced on the existence of APR_BUCKET_REMOVE(e).

> > This works (the final bucket gets sent down the wire) but, if I
> > understand the meaning of EOS I won't get into heaven this way.
> Yeah, that's definitely bad news.

Is THE RULE that one should assume the end of data if one receives
an EOS even if there are more buckets in the brigade?

> > I figured I could copy all but the EOS from the original payload to
> > the new brigade:
> >
> > -    APR_BRIGADE_CONCAT(bsend, bPayload);
> > +    APR_BRIGADE_FOREACH(e, bPayload) {
> > +	if (!APR_BUCKET_IS_EOS(e))
> > +	    APR_BRIGADE_INSERT_TAIL(bsend, e);
> > +    }
> This is broken because you're modifying the list pointers of e, which
> APR_BRIGADE_FOREACH() doesn't support.  The foreach macro uses e->next to
> determine what the next bucket in bPayload is at the end of each
> iteration, so you have to treat e as essentially const.  What you'd want
> to do is something more like this:
>     while (!APR_BRIGADE_EMPTY(bPayload)) {
>         e = APR_BRIGADE_FIRST(bPayload);
>         if (!APR_BUCKET_IS_EOS(e)) {
>             APR_BUCKET_REMOVE(e);
>             APR_BRIGADE_INSERT_TAIL(bsend, e);
>         }
>     }
> You have to do the remove before inserting into bsend so that the bPayload
> ring remains consistent.
> But like I said, this is a linear time operation, when you can do it in
> constant time, like this:
>     eos = APR_BRIGADE_LAST(bPayload);
>     if (APR_BUCKET_IS_EOS(eos)) {
>         APR_BUCKET_REMOVE(eos);
>     }
>     else {
>         eos = apr_bucket_eos_create();
>     }
>     APR_BRIGADE_CONCAT(bsend, bPayload);
>     /* apr_brigade_destroy(bPayload); */
>     e = apr_bucket_pool_create(boundary, boundryLength, r->pool);
>     APR_BRIGADE_INSERT_TAIL(bsend, e);
>     APR_BRIGADE_INSERT_TAIL(bsend, eos);

worky, thank you kindly.

> Note that if the last bucket is not eos, depending on how your filter is
> supposed to work that might be an indication that you need to stash the
> brigade away until you DO get an eos, because the content you're wrapping
> with your mime headers hasn't all arrived yet.  Alternatively, you can
> send down what you have now but a lack of eos means you shouldn't tack on
> your boundary stuff yet.

Is a filter guaranteed to get an EOS?

> > The byterange filter uses some function calls to
> > copy pieces of the brigade. Is this the sanctioned approach?
> I assume you're talking about apr_brigade_partition() or
> apr_brigade_split()... you definitely don't need partition here (which
> splits the brigade at a given byte offset).  apr_brigade_split() is
> useful when you want to send part of the data you have in a single brigade
> and hang onto the rest, but I doubt you'll need that here either.
> There are plenty of uses of apr_brigade_split() in the core filters that
> you can look at as an example.

Oops, I forgot to include the code snippet to which I was
referring. From ap_byterange_filter:

            if (apr_bucket_copy(ec, &foo) != APR_SUCCESS) {
                apr_bucket_read(ec, &str, &len, APR_BLOCK_READ);
                foo = apr_bucket_heap_create(str, len, 0, NULL);

I assume there's no reason to do this if it doesn't accompany some
fragmentation of ec.

> Hope this helps!  Let me know if you have more questions.

Quite well, thank you kindly. I'm hacking up some docs to pass your
help on. apr_buckets.h has func descriptions but I'd like to make a
sybling of _Hook_Functions_ [1] with THE RULES and some common



Feel free to forward this message to any list for any purpose other than
email address distribution.

View raw message