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

Reply via email to