diff options
author | Yann Ylavic <ylavic@apache.org> | 2018-09-03 10:27:40 +0000 |
---|---|---|
committer | Yann Ylavic <ylavic@apache.org> | 2018-09-03 10:27:40 +0000 |
commit | ee0e1be9c3fb5e25cd14dabd6e3b8b6870ca3e98 (patch) | |
tree | 4d5a58c9a058e8470033acd64cc70aedcdd5d10f /server/util_filter.c | |
parent | fa321ddeba38b0cd5f8bf55ce4306a8006c9e39c (diff) | |
download | httpd-ee0e1be9c3fb5e25cd14dabd6e3b8b6870ca3e98.tar.gz |
util_filter: split pending filters ring in two: input and output ones.
Pending input and output are now maintained separately in respectively
c->pending_input_filters and c->pending_output_filters, which improves
both performances and debug-ability.
Also, struct ap_filter_ring is made opaque, it's only used by util_filter
and this will allow us to later change it e.g. to a dual ring+apr_hash to
avoid quadratic search in ap_filter_prepare_brigade().
MMN major bumped due to the change in conn_rec (this is trunk only code
anyway for now).
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1839933 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'server/util_filter.c')
-rw-r--r-- | server/util_filter.c | 66 |
1 files changed, 38 insertions, 28 deletions
diff --git a/server/util_filter.c b/server/util_filter.c index e2952958da..e253369455 100644 --- a/server/util_filter.c +++ b/server/util_filter.c @@ -51,6 +51,8 @@ #undef APLOG_MODULE_INDEX #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX +APR_RING_HEAD(ap_filter_ring, ap_filter_t); + typedef struct filter_trie_node filter_trie_node; typedef struct { @@ -713,7 +715,8 @@ AP_DECLARE(int) ap_filter_prepare_brigade(ap_filter_t *f, apr_pool_t **p) { apr_pool_t *pool; ap_filter_t *next, *e; - ap_filter_t *found = NULL; + ap_filter_ring_t **ref, *pendings; + int found = 0; pool = f->r ? f->r->pool : f->c->pool; if (p) { @@ -728,33 +731,40 @@ AP_DECLARE(int) ap_filter_prepare_brigade(ap_filter_t *f, apr_pool_t **p) return DECLINED; } - /* Pending reads/writes must happen in the same order as input/output - * filters, so find the first "next" filter already in place and insert - * before it, if any, otherwise insert last. + if (f->frec->direction == AP_FILTER_INPUT) { + ref = &f->c->pending_input_filters; + } + else { + ref = &f->c->pending_output_filters; + } + pendings = *ref; + + /* Pending reads/writes must happen in the reverse order of the actual + * in/output filters (in/outer most first), though we still maintain the + * ring in the same "next" order as filters (walking is backward). So find + * the first f->next filter already in place and insert before if + * any, otherwise insert last. */ - if (f->c->pending_filters) { + if (pendings) { for (next = f->next; next && !found; next = next->next) { - for (e = APR_RING_FIRST(f->c->pending_filters); - e != APR_RING_SENTINEL(f->c->pending_filters, - ap_filter_t, pending); + for (e = APR_RING_FIRST(pendings); + e != APR_RING_SENTINEL(pendings, ap_filter_t, pending); e = APR_RING_NEXT(e, pending)) { if (e == next) { - found = e; + APR_RING_INSERT_BEFORE(e, f, pending); + found = 1; break; } } } } else { - f->c->pending_filters = apr_palloc(f->c->pool, - sizeof(*f->c->pending_filters)); - APR_RING_INIT(f->c->pending_filters, ap_filter_t, pending); + pendings = apr_palloc(f->c->pool, sizeof(ap_filter_ring_t)); + APR_RING_INIT(pendings, ap_filter_t, pending); + *ref = pendings; } - if (found) { - APR_RING_INSERT_BEFORE(found, f, pending); - } - else { - APR_RING_INSERT_TAIL(f->c->pending_filters, f, ap_filter_t, pending); + if (!found) { + APR_RING_INSERT_TAIL(pendings, f, ap_filter_t, pending); } return OK; @@ -998,7 +1008,7 @@ AP_DECLARE_NONSTD(int) ap_filter_output_pending(conn_rec *c) apr_bucket_brigade *bb; ap_filter_t *f; - if (!c->pending_filters) { + if (!c->pending_output_filters) { return DECLINED; } @@ -1009,11 +1019,11 @@ AP_DECLARE_NONSTD(int) ap_filter_output_pending(conn_rec *c) * to be relevant in the previous ones (e.g. ap_request_core_filter() * won't pass its buckets if its next filters yield already). */ - for (f = APR_RING_LAST(c->pending_filters); - f != APR_RING_SENTINEL(c->pending_filters, ap_filter_t, pending); + for (f = APR_RING_LAST(c->pending_output_filters); + f != APR_RING_SENTINEL(c->pending_output_filters, + ap_filter_t, pending); f = APR_RING_PREV(f, pending)) { - if (f->frec->direction == AP_FILTER_OUTPUT && f->bb - && !APR_BRIGADE_EMPTY(f->bb)) { + if (f->bb && !APR_BRIGADE_EMPTY(f->bb)) { apr_status_t rv; rv = ap_pass_brigade(f, bb); @@ -1038,24 +1048,24 @@ AP_DECLARE_NONSTD(int) ap_filter_input_pending(conn_rec *c) { ap_filter_t *f; - if (!c->pending_filters) { + if (!c->pending_input_filters) { return DECLINED; } - for (f = APR_RING_LAST(c->pending_filters); - f != APR_RING_SENTINEL(c->pending_filters, ap_filter_t, pending); + for (f = APR_RING_LAST(c->pending_input_filters); + f != APR_RING_SENTINEL(c->pending_input_filters, + ap_filter_t, pending); f = APR_RING_PREV(f, pending)) { - if (f->frec->direction == AP_FILTER_INPUT && f->bb) { + if (f->bb) { apr_bucket *e = APR_BRIGADE_FIRST(f->bb); - /* if there is at least one non-morphing bucket + /* if there is a leading non-morphing bucket * in place, then we have data pending */ if (e != APR_BRIGADE_SENTINEL(f->bb) && e->length != (apr_size_t)(-1)) { return OK; } - } } |