> -----Original Message-----
> From: Graham Leggett 
> Sent: Dienstag, 29. Oktober 2013 00:47
> To: dev@httpd.apache.org
> Subject: [Patch] mod_ssl write completion
> 
> Hi all,
> 
> I was on the wrong track with regards mod_ssl and the flush-on-eos, the
> patch below to mod_ssl echoes a similar strategy the core output filter
> uses to enter write completion mode.
> 
> The idea is that if the brigade to be written contains an EOS bucket but
> not a flush bucket, we can safely set aside the buckets and when event is
> present enter write completion. As soon as we do see a flush bucket, or if
> we have previously set aside we write as normal. Because we only trigger
> this behaviour when we see an EOS bucket we only set aside once per
> request, which should keep RAM use bounded, and leave generators that
> stream unbounded data unaffected.
> 
> This should in theory make most mod_ssl requests behave similarly to
> normal requests with respect to async behaviour. A typical response
> contains a file bucket and eos, which will be immediately set aside and
> enter write completion. Proxied responses should enter write completion
> when the last bucket is produced, which could be the whole response if
> ProxyIOBufferSize is set large enough. Cached responses also contain just
> a (file or heap) bucket and eos, so should also benefit. Any content
> generator that sends the EOS bucket separately from the data won't
> benefit, but we can fix any of those separately.
> 
> All the SSL tests pass with this patch, but more eyes welcome.
> 
> Index: modules/ssl/ssl_engine_io.c
> ===================================================================
> --- modules/ssl/ssl_engine_io.c       (revision 1536348)
> +++ modules/ssl/ssl_engine_io.c       (working copy)
>  typedef struct {
> @@ -1675,6 +1677,62 @@
>          return ssl_io_filter_error(f, bb, status);
>      }
> 
> +    /* We now try and take advantage of write completion in async mpms.
> +     * If our brigade contains an EOS bucket and no flush buckets, set
> +     * aside the whole brigade and leave early. We will get called again
> +     * during write completion, at which point we'll do the actual write.
> +     */
> +    if (f->c->cs) {
> +
> +        if (!filter_ctx->bb) {
> +            filter_ctx->bb = apr_brigade_create(f->c->pool, f->c-
> >bucket_alloc);
> +        }
> +
> +        if (!APR_BRIGADE_EMPTY(filter_ctx->bb)) {
> +
> +            APR_BRIGADE_PREPEND(bb, filter_ctx->bb);
> +
> +            f->c->data_in_output_filters--;
> +            ap_assert(f->c->data_in_output_filters >= 0);
> +
> +        }
> +        else {
> +            apr_bucket *bucket;
> +            int found = 0;
> +
> +            if (filter_ctx->deferred_write_pool) {
> +                apr_pool_clear(filter_ctx->deferred_write_pool);
> +            }
> +
> +            /* EOS, but no flush */
> +            for (bucket = APR_BRIGADE_FIRST(bb);
> +                    bucket != APR_BRIGADE_SENTINEL(bb); bucket =
> +                            APR_BUCKET_NEXT(bucket)) {
> +                if (APR_BUCKET_IS_EOS(bucket)) {
> +                    found = 1;
> +                }
> +                if (APR_BUCKET_IS_FLUSH(bucket)) {
> +                    found = 0;
> +                    break;
> +                }
> +            }
> +
> +            /* leave early */
> +            if (found) {
> +                if (!filter_ctx->deferred_write_pool) {
> +                    apr_pool_create(&filter_ctx->deferred_write_pool,
> +                            f->c->pool);
> +                    apr_pool_tag(filter_ctx->deferred_write_pool,
> +                            "ssl_deferred_write");
> +                }
> +                status = ap_save_brigade(f, &(filter_ctx->bb), &bb,
> +                        filter_ctx->deferred_write_pool);

When will this saved brigade handed over to the core output filter?
How will it be triggered? IMHO the WRITE_COMPLETION only calls the core output 
filter.

> +                f->c->data_in_output_filters++;
> +                return APR_SUCCESS;
> +            }
> +        }
> +    }
> +
>      while (!APR_BRIGADE_EMPTY(bb)) {
>          apr_bucket *bucket = APR_BRIGADE_FIRST(bb);
> 
> Index: server/core_filters.c
> ===================================================================
> --- server/core_filters.c     (revision 1536348)
> +++ server/core_filters.c     (working copy)
> @@ -413,7 +413,8 @@
>          else {
>              bb = ctx->buffered_bb;
>          }
> -        c->data_in_output_filters = 0;
> +        c->data_in_output_filters--;

Why do you switch from a boolean flag to a counter?

Regards

Rüdiger

Reply via email to