So, here is a hackish patch to allow easier building of custom core output filters, for places like the Event MPM.
It uses the APR optional functions to optionally register a function to replace the C-O-F. I found it useful as a start to doing the write completion inside the Event MPM. -Paul
Index: server/mpm/experimental/event/event.c =================================================================== --- server/mpm/experimental/event/event.c (revision 230720) +++ server/mpm/experimental/event/event.c (working copy) @@ -168,6 +168,9 @@ static apr_pollset_t *event_pollset; +extern apr_status_t ap_mpm_custom_write_filter(ap_filter_t *f, + apr_bucket_brigade *bb); + /* The structure used to pass unique initialization info to each thread */ typedef struct { @@ -336,6 +339,9 @@ case AP_MPMQ_IS_ASYNC: *result = 1; return APR_SUCCESS; + case AP_MPMQ_CUSTOM_WRITE: + *result = 1; + return APR_SUCCESS; case AP_MPMQ_HARD_LIMIT_DAEMONS: *result = server_limit; return APR_SUCCESS; @@ -543,6 +549,7 @@ return listener_may_exit; } + /***************************************************************** * Child process main loop. */ @@ -2138,6 +2145,8 @@ * to retrieve it, so register as REALLY_FIRST */ ap_hook_pre_config(worker_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST); + + APR_REGISTER_OPTIONAL_FN(ap_mpm_custom_write_filter); } static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, Index: server/mpm/experimental/event/Makefile.in =================================================================== --- server/mpm/experimental/event/Makefile.in (revision 230720) +++ server/mpm/experimental/event/Makefile.in (working copy) @@ -1,5 +1,5 @@ LTLIBRARY_NAME = libevent.la -LTLIBRARY_SOURCES = event.c fdqueue.c pod.c +LTLIBRARY_SOURCES = event.c event_filters.c fdqueue.c pod.c include $(top_srcdir)/build/ltlib.mk Index: server/mpm/experimental/event/event_filters.c =================================================================== --- server/mpm/experimental/event/event_filters.c (revision 0) +++ server/mpm/experimental/event/event_filters.c (revision 0) @@ -0,0 +1,30 @@ +/* Copyright 2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_buckets.h" +#include "apr_errno.h" +#include "apr_support.h" +#include "httpd.h" +#include "http_connection.h" +#include "util_filter.h" + +apr_status_t ap_mpm_custom_write_filter(ap_filter_t *f, + apr_bucket_brigade *bb) +{ + /* write you own C-O-F here */ + return ap_core_output_filter(f, bb); +} + Index: server/core.c =================================================================== --- server/core.c (revision 230720) +++ server/core.c (working copy) @@ -21,6 +21,7 @@ #include "apr_hash.h" #include "apr_thread_proc.h" /* for RLIMIT stuff */ #include "apr_hooks.h" +#include "apr_optional.h" #define APR_WANT_IOVEC #define APR_WANT_STRFUNC @@ -48,6 +49,7 @@ #include "mod_core.h" #include "mod_proxy.h" #include "ap_listen.h" +#include "ap_mpm.h" #include "mod_so.h" /* for ap_find_loaded_module_symbol */ @@ -90,10 +92,13 @@ /* Handles for core filters */ AP_DECLARE_DATA ap_filter_rec_t *ap_subreq_core_filter_handle; AP_DECLARE_DATA ap_filter_rec_t *ap_core_output_filter_handle; +AP_DECLARE_DATA ap_filter_rec_t *ap_core_mpm_write_filter_handle; AP_DECLARE_DATA ap_filter_rec_t *ap_content_length_filter_handle; AP_DECLARE_DATA ap_filter_rec_t *ap_net_time_filter_handle; AP_DECLARE_DATA ap_filter_rec_t *ap_core_input_filter_handle; +static APR_OPTIONAL_FN_TYPE(ap_mpm_custom_write_filter) *mpm_write_func; + /* magic pointer for ErrorDocument xxx "default" */ static char errordocument_default; @@ -3676,9 +3681,25 @@ static int core_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) { + int mpm_write = 0; + logio_add_bytes_out = APR_RETRIEVE_OPTIONAL_FN(ap_logio_add_bytes_out); ident_lookup = APR_RETRIEVE_OPTIONAL_FN(ap_ident_lookup); + if (ap_mpm_query(AP_MPMQ_CUSTOM_WRITE, &mpm_write) == APR_SUCCESS + && mpm_write == 1) { + mpm_write_func = APR_RETRIEVE_OPTIONAL_FN(ap_mpm_custom_write_filter); + + ap_core_output_filter_handle = + ap_register_output_filter("CORE", mpm_write_func, + NULL, AP_FTYPE_NETWORK); + } + else { + ap_core_output_filter_handle = + ap_register_output_filter("CORE", ap_core_output_filter, + NULL, AP_FTYPE_NETWORK); + } + ap_set_version(pconf); ap_setup_make_content_type(pconf); return OK; @@ -3853,7 +3874,10 @@ ap_set_module_config(net->c->conn_config, &core_module, csd); ap_add_input_filter_handle(ap_core_input_filter_handle, net, NULL, net->c); - ap_add_output_filter_handle(ap_core_output_filter_handle, net, NULL, net->c); + + ap_add_output_filter_handle(ap_core_output_filter_handle, net, + NULL, net->c); + return DONE; } @@ -3898,9 +3922,8 @@ ap_content_length_filter_handle = ap_register_output_filter("CONTENT_LENGTH", ap_content_length_filter, NULL, AP_FTYPE_PROTOCOL); - ap_core_output_filter_handle = - ap_register_output_filter("CORE", ap_core_output_filter, - NULL, AP_FTYPE_NETWORK); + + ap_subreq_core_filter_handle = ap_register_output_filter("SUBREQ_CORE", ap_sub_req_output_filter, NULL, AP_FTYPE_CONTENT_SET); Index: include/ap_mpm.h =================================================================== --- include/ap_mpm.h (revision 230720) +++ include/ap_mpm.h (working copy) @@ -141,6 +141,7 @@ #define AP_MPMQ_MAX_DAEMONS 12 /* Max # of daemons by config */ #define AP_MPMQ_MPM_STATE 13 /* starting, running, stopping */ #define AP_MPMQ_IS_ASYNC 14 /* MPM can process async connections */ +#define AP_MPMQ_CUSTOM_WRITE 15 /* MPM uses a custom output filter */ /** * Query a property of the current MPM. Index: include/util_filter.h =================================================================== --- include/util_filter.h (revision 230720) +++ include/util_filter.h (working copy) @@ -584,6 +584,11 @@ /** Filter is incompatible with "Cache-Control: no-transform" */ #define AP_FILTER_PROTO_TRANSFORM 0x20 +#include "apr_optional.h" + +APR_DECLARE_OPTIONAL_FN(apr_status_t, ap_mpm_custom_write_filter, + (ap_filter_t *f, apr_bucket_brigade *b)); + #ifdef __cplusplus } #endif