> -----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