diff options
author | Yann Ylavic <ylavic@apache.org> | 2021-08-20 09:36:19 +0000 |
---|---|---|
committer | Yann Ylavic <ylavic@apache.org> | 2021-08-20 09:36:19 +0000 |
commit | 324ae13e8ee714c2c7a8377d98ea6f9aa1722428 (patch) | |
tree | a9b244c19bbc71c535ab01cb0b79722ce0963b01 /server/util_filter.c | |
parent | 8f8793bcc6e5b3c369d336c148003ba1f63df606 (diff) | |
download | httpd-324ae13e8ee714c2c7a8377d98ea6f9aa1722428.tar.gz |
core: follow up to r1891148: WC bucket defaulting to FLUSH bucket.
Define WC bucket semantics as:
/**
* @brief Write Completion (WC) bucket
*
* A WC bucket is a FLUSH bucket with special ->data == &ap_bucket_wc_data,
* still both AP_BUCKET_IS_WC() and APR_BUCKET_IS_FLUSH() hold for them so
* they have the same semantics for most filters, namely:
* Everything produced before shall be passed to the next filter, including
* the WC/FLUSH bucket itself.
* The distinction between WC and FLUSH buckets is only for filters that care
* about write completion (calling ap_filter_reinstate_brigade() with non-NULL
* flush_upto), those can setaside WC buckets and the preceding data provided
* they have first determined that the next filter(s) have pending data
* already, usually by calling ap_filter_should_yield(f->next).
*/
The only filters that care about write completion for now are
ap_core_output_filter() and ssl_io_filter_output(), which try to fill
in the pipe as much as possible, using ap_filter_reinstate_brigade(&flush_upto)
to determine whether they should flush (blocking) or setaside their remaining
data.
So ap_filter_reinstate_brigade() is made to not treat WC as FLUSH buckets and
keep the above filters working as before (and correctly w.r.t. above WC bucket
semantics).
* include/ap_mmn.h, include/util_filter.h:
Axe specific ap_bucket_type_wc and define global &ap_bucket_wc_data address to
mark WC buckets checked by AP_BUCKET_IS_WC().
* server/util_filter.c (ap_filter_reinstate_brigade):
Don't treat WC buckets as FLUSH buckets.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1892468 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'server/util_filter.c')
-rw-r--r-- | server/util_filter.c | 45 |
1 files changed, 20 insertions, 25 deletions
diff --git a/server/util_filter.c b/server/util_filter.c index ff33bfde21..8c278293cf 100644 --- a/server/util_filter.c +++ b/server/util_filter.c @@ -976,7 +976,9 @@ AP_DECLARE(apr_status_t) ap_filter_setaside_brigade(ap_filter_t *f, e = next) { next = APR_BUCKET_NEXT(e); - /* Strip WC buckets added by ap_filter_output_pending(). */ + /* WC buckets will be added back by ap_filter_output_pending() + * at the tail. + */ if (AP_BUCKET_IS_WC(e)) { apr_bucket_delete(e); continue; @@ -1069,6 +1071,7 @@ AP_DECLARE(apr_status_t) ap_filter_reinstate_brigade(ap_filter_t *f, int eor_buckets_in_brigade, opaque_buckets_in_brigade; struct ap_filter_private *fp = f->priv; core_server_config *conf; + int is_flush; ap_log_cerror(APLOG_MARK, APLOG_TRACE6, 0, f->c, "reinstate %s brigade to %s brigade in '%s' %sput filter", @@ -1132,7 +1135,15 @@ AP_DECLARE(apr_status_t) ap_filter_reinstate_brigade(ap_filter_t *f, bucket = next) { next = APR_BUCKET_NEXT(bucket); - if (AP_BUCKET_IS_EOR(bucket)) { + /* When called with flush_upto != NULL, we assume that the caller does + * the right thing to potentially setaside WC buckets (per semantics), + * so we don't treat them as FLUSH(_upto) here. + */ + is_flush = (APR_BUCKET_IS_FLUSH(bucket) && !AP_BUCKET_IS_WC(bucket)); + if (is_flush) { + /* handled below */ + } + else if (AP_BUCKET_IS_EOR(bucket)) { eor_buckets_in_brigade++; } else if (bucket->length == (apr_size_t)-1) { @@ -1145,14 +1156,14 @@ AP_DECLARE(apr_status_t) ap_filter_reinstate_brigade(ap_filter_t *f, } } - if (APR_BUCKET_IS_FLUSH(bucket) + if (is_flush || (memory_bytes_in_brigade > conf->flush_max_threshold) || (conf->flush_max_pipelined >= 0 && eor_buckets_in_brigade > conf->flush_max_pipelined)) { /* this segment of the brigade MUST be sent before returning. */ if (APLOGctrace6(f->c)) { - char *reason = APR_BUCKET_IS_FLUSH(bucket) ? + char *reason = is_flush ? "FLUSH bucket" : (memory_bytes_in_brigade > conf->flush_max_threshold) ? "max threshold" : "max requests in pipeline"; @@ -1400,22 +1411,15 @@ AP_DECLARE(void) ap_filter_protocol(ap_filter_t *f, unsigned int flags) f->frec->proto_flags = flags ; } +/* Write Completion (WC) bucket implementation */ -static apr_status_t wc_bucket_read(apr_bucket *b, const char **str, - apr_size_t *len, apr_read_type_e block) -{ - *str = NULL; - *len = 0; - return APR_SUCCESS; -} +AP_DECLARE_DATA const char ap_bucket_wc_data; AP_DECLARE(apr_bucket *) ap_bucket_wc_make(apr_bucket *b) { - b->length = 0; - b->start = 0; - b->data = NULL; - b->type = &ap_bucket_type_wc; - + /* FLUSH bucket with special ->data mark (instead of NULL) */ + b = apr_bucket_flush_make(b); + b->data = (void *)&ap_bucket_wc_data; return b; } @@ -1428,12 +1432,3 @@ AP_DECLARE(apr_bucket *) ap_bucket_wc_create(apr_bucket_alloc_t *list) b->list = list; return ap_bucket_wc_make(b); } - -AP_DECLARE_DATA const apr_bucket_type_t ap_bucket_type_wc = { - "WC", 5, APR_BUCKET_METADATA, - apr_bucket_destroy_noop, - wc_bucket_read, - apr_bucket_setaside_noop, - apr_bucket_split_notimpl, - apr_bucket_simple_copy -}; |