I sent an email to the list a little over a week ago about adding the ability for a protocol handler to keep a TCP connection open for notifications, but then free in the worker thread back to MPM. No one responded, so I have created a basic patch to allow this, and patched the event and worker mpm's to allow this.
First, I added two new methods to the ap_mpm.h: AP_DECLARE(apr_status_t) ap_mpm_close_connection(conn_rec *connection); AP_DECLARE(apr_status_t) ap_mpm_reprocess_connection(conn_rec *connection); I made very few changes to event.c, but a couple more to worker.c, but all in all the patch set was relatively small. The behavior is slightly different between the two. I have also started working on the winnt mpm, but I haven't finished it for both code paths. I have _thought_ about changing the above methods to: AP_DECLARE(apr_status_t) ap_mpm_close_connection(conn_rec *connection); AP_DECLARE(apr_status_t) ap_mpm_reprocess_connection(conn_rec *connection); AP_DECLARE(apr_status_t) ap_mpm_requeue_connection(conn_rec *connection); Where the ap_mpm_requeue_connection would requeue, such as the event mpm, to be processed by another thread, but then have ap_mpm_reprocess_connection, use the current thread of execution. To make it clearer to a protocol modules what will happen in the mpm. I also added a really lame example module called mod_queue, that allows you to push and pop on a queue. I would really appreciate any feedback. I would like to get a change like this accepted into the main apache code. Thanks. -Joey
==== Patch <apache-trunk-proto-hold-conn> level 1 Source: 3bcefa79-22fa-0310-8f51-eae9cfeca718:/apache-trunk:14965 Target: 13f79535-47bb-0310-9956-ffa450edef68:/httpd/httpd/trunk:202039 (http://svn.apache.org/repos/asf/httpd/httpd/trunk) Log: [EMAIL PROTECTED]: jce | 2005-06-22 16:42:24 -0600 starting. [EMAIL PROTECTED]: jce | 2005-06-22 16:47:48 -0600 Added connection hoding functionality and sample mod... === server/mpm/worker/fdqueue.c ================================================================== --- server/mpm/worker/fdqueue.c (revision 202039) +++ server/mpm/worker/fdqueue.c (patch apache-trunk-proto-hold-conn level 1) @@ -80,12 +80,9 @@ return APR_SUCCESS; } -apr_status_t ap_queue_info_set_idle(fd_queue_info_t *queue_info, - apr_pool_t *pool_to_recycle) +void ap_queue_info_recycle_pool(fd_queue_info_t *queue_info, + apr_pool_t *pool_to_recycle) { - apr_status_t rv; - int prev_idlers; - /* If we have been given a pool to recycle, atomically link * it into the queue_info's list of recycled pools */ @@ -103,7 +100,16 @@ } } } +} +apr_status_t ap_queue_info_set_idle(fd_queue_info_t *queue_info, + apr_pool_t *pool_to_recycle) +{ + apr_status_t rv; + int prev_idlers; + + ap_queue_info_recycle_pool(queue_info, pool_to_recycle); + /* Atomically increment the count of idle workers */ for (;;) { prev_idlers = queue_info->idlers; === server/mpm/worker/fdqueue.h ================================================================== --- server/mpm/worker/fdqueue.h (revision 202039) +++ server/mpm/worker/fdqueue.h (patch apache-trunk-proto-hold-conn level 1) @@ -38,6 +38,8 @@ apr_status_t ap_queue_info_wait_for_idler(fd_queue_info_t *queue_info, apr_pool_t **recycled_pool); apr_status_t ap_queue_info_term(fd_queue_info_t *queue_info); +void ap_queue_info_recycle_pool(fd_queue_info_t *queue_info, + apr_pool_t *pool_to_recycle); struct fd_queue_elem_t { apr_socket_t *sd; === server/mpm/worker/worker.c ================================================================== --- server/mpm/worker/worker.c (revision 202039) +++ server/mpm/worker/worker.c (patch apache-trunk-proto-hold-conn level 1) @@ -30,6 +30,7 @@ #include "apr_thread_mutex.h" #include "apr_proc_mutex.h" #include "apr_poll.h" +#include "apr_support.h" #define APR_WANT_STRFUNC #include "apr_want.h" @@ -519,8 +520,20 @@ current_conn = ap_run_create_connection(p, ap_server_conf, sock, conn_id, sbh, bucket_alloc); if (current_conn) { - ap_process_connection(current_conn, sock); - ap_lingering_close(current_conn); + ap_process_connection(current_conn, sock); + if (!current_conn->cs || (current_conn->cs->state == CONN_STATE_LINGER)) { + /* Default/old mpm behavior */ + ap_mpm_close_connection(current_conn); + } else if (current_conn->cs->state == CONN_STATE_CHECK_REQUEST_LINE_READABLE) { + while (current_conn->cs->state == CONN_STATE_CHECK_REQUEST_LINE_READABLE) { + apr_interval_time_t old_timeout; + apr_socket_timeout_get(sock, &old_timeout); + apr_socket_timeout_set(sock, current_conn->base_server->timeout); + ap_mpm_reprocess_connection(current_conn); + apr_socket_timeout_set(sock, old_timeout); + } + } + } } @@ -800,7 +813,6 @@ int thread_slot = ti->tid; apr_socket_t *csd = NULL; apr_bucket_alloc_t *bucket_alloc; - apr_pool_t *last_ptrans = NULL; apr_pool_t *ptrans; /* Pool for per-transaction stuff */ apr_status_t rv; int is_idle = 0; @@ -813,8 +825,7 @@ while (!workers_may_exit) { if (!is_idle) { - rv = ap_queue_info_set_idle(worker_queue_info, last_ptrans); - last_ptrans = NULL; + rv = ap_queue_info_set_idle(worker_queue_info, NULL); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, "ap_queue_info_set_idle failed. Attempting to " @@ -866,8 +877,6 @@ process_socket(ptrans, csd, process_slot, thread_slot, bucket_alloc); worker_sockets[thread_slot] = NULL; requests_this_child--; /* FIXME: should be synchronized - aaron */ - apr_pool_clear(ptrans); - last_ptrans = ptrans; } ap_update_child_status_from_indexes(process_slot, thread_slot, @@ -877,6 +886,25 @@ return NULL; } +AP_DECLARE(apr_status_t) ap_mpm_reprocess_connection(conn_rec *c) { + // handle timeout case... + apr_socket_t *csd; + csd = ap_get_module_config(c->conn_config, &core_module); + if (apr_wait_for_io_or_timeout(NULL, csd, 1) == APR_SUCCESS) { + ap_process_connection(c, csd); + } else { + ap_mpm_close_connection(c); + } + return APR_SUCCESS; +} + +AP_DECLARE(apr_status_t) ap_mpm_close_connection(conn_rec *c) { + ap_lingering_close(c); + apr_pool_clear(c->pool); + ap_queue_info_recycle_pool(worker_queue_info, c->pool); + return APR_SUCCESS; +} + static int check_signal(int signum) { switch (signum) { === server/mpm/experimental/event/event.c ================================================================== --- server/mpm/experimental/event/event.c (revision 202039) +++ server/mpm/experimental/event/event.c (patch apache-trunk-proto-hold-conn level 1) @@ -556,14 +556,11 @@ long conn_id = ID_FROM_CHILD_THREAD(my_child_num, my_thread_num); int csd; int rc; - apr_time_t time_now = 0; ap_sb_handle_t *sbh; ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num); apr_os_sock_get(&csd, sock); - time_now = apr_time_now(); - if (cs == NULL) { /* This is a new connection */ cs = apr_pcalloc(p, sizeof(conn_state_t)); @@ -630,43 +627,58 @@ } if (cs->state == CONN_STATE_LINGER) { - ap_lingering_close(c); - apr_bucket_alloc_destroy(cs->bucket_alloc); - apr_pool_clear(p); - ap_push_pool(worker_queue_info, p); - return 1; + return ap_mpm_close_connection(c); } else if (cs->state == CONN_STATE_CHECK_REQUEST_LINE_READABLE) { - apr_status_t rc; - listener_poll_type *pt = (listener_poll_type *) cs->pfd.client_data; + ap_mpm_reprocess_connection(c); + } + return 0; +} - /* It greatly simplifies the logic to use a single timeout value here - * because the new element can just be added to the end of the list and - * it will stay sorted in expiration time sequence. If brand new - * sockets are sent to the event thread for a readability check, this - * will be a slight behavior change - they use the non-keepalive - * timeout today. With a normal client, the socket will be readable in - * a few milliseconds anyway. - */ - cs->expiration_time = ap_server_conf->keep_alive_timeout + time_now; - apr_thread_mutex_lock(timeout_mutex); - APR_RING_INSERT_TAIL(&timeout_head, cs, conn_state_t, timeout_list); +AP_DECLARE(apr_status_t) ap_mpm_reprocess_connection(conn_rec *c) { + apr_status_t rc; + /* start timeout from the time connection is returned for reprocessing + */ + apr_time_t time_now = apr_time_now(); - pt->status = 0; - /* Add work to pollset. These are always read events */ - rc = apr_pollset_add(event_pollset, &cs->pfd); + c->cs->state = CONN_STATE_CHECK_REQUEST_LINE_READABLE; + listener_poll_type *pt = (listener_poll_type *) c->cs->pfd.client_data; - apr_thread_mutex_unlock(timeout_mutex); + /* It greatly simplifies the logic to use a single timeout value here + * because the new element can just be added to the end of the list and + * it will stay sorted in expiration time sequence. If brand new + * sockets are sent to the event thread for a readability check, this + * will be a slight behavior change - they use the non-keepalive + * timeout today. With a normal client, the socket will be readable in + * a few milliseconds anyway. + */ + c->cs->expiration_time = ap_server_conf->keep_alive_timeout + time_now; + apr_thread_mutex_lock(timeout_mutex); + APR_RING_INSERT_TAIL(&timeout_head, c->cs, conn_state_t, timeout_list); - if (rc != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf, - "process_socket: apr_pollset_add failure"); - AP_DEBUG_ASSERT(rc == APR_SUCCESS); - } + pt->status = 0; + /* Add work to pollset. These are always read events */ + rc = apr_pollset_add(event_pollset, &c->cs->pfd); + + apr_thread_mutex_unlock(timeout_mutex); + + if (rc != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf, + "process_socket: apr_pollset_add failure"); + AP_DEBUG_ASSERT(rc == APR_SUCCESS); } - return 0; + return rc; } +AP_DECLARE(apr_status_t) ap_mpm_close_connection(conn_rec *c) { + apr_pool_t * p = c->cs->p; + ap_lingering_close(c); + apr_bucket_alloc_destroy(c->cs->bucket_alloc); + apr_pool_clear(p); + ap_push_pool(worker_queue_info, p); + return 1; +} + /* requests_this_child has gone to zero or below. See if the admin coded "MaxRequestsPerChild 0", and keep going in that case. Doing it this way simplifies the hot path in worker_thread */ === modules/queue/Makefile.in ================================================================== --- modules/queue/Makefile.in (revision 202039) +++ modules/queue/Makefile.in (patch apache-trunk-proto-hold-conn level 1) @@ -0,0 +1,3 @@ + +include $(top_srcdir)/build/special.mk + === modules/queue/config.m4 ================================================================== --- modules/queue/config.m4 (revision 202039) +++ modules/queue/config.m4 (patch apache-trunk-proto-hold-conn level 1) @@ -0,0 +1,9 @@ +dnl modules enabled in this directory by default + +dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, config]]]]) + +APACHE_MODPATH_INIT(queue) + +APACHE_MODULE(queue, Notify server example, , , no) + +APACHE_MODPATH_FINISH === modules/queue/mod_queue.c ================================================================== --- modules/queue/mod_queue.c (revision 202039) +++ modules/queue/mod_queue.c (patch apache-trunk-proto-hold-conn level 1) @@ -0,0 +1,201 @@ +/* Copyright 1999-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 "ap_config.h" +#include "ap_mmn.h" +#include "httpd.h" +#include "http_log.h" +#include "http_config.h" +#include "http_connection.h" +#include "http_protocol.h" +#include "apr_queue.h" +#include "apr_buckets.h" +#include "apr_strings.h" +#include "ap_mpm.h" +#include "util_filter.h" + +module AP_MODULE_DECLARE_DATA queue_module; +#define NOTIFY_MAX_LINE_SIZE 8096 +typedef struct { + apr_queue_t* mMessageQueue; + apr_queue_t* mClientQueue; + apr_pool_t* mPool; + int mEnabled; +} QueueConfig; + +typedef struct { + request_rec* request; + apr_pool_t* pool; +} ClientElement; + +typedef struct { + char* message; + apr_pool_t* pool; +} MessageElement; + +static void *create_queue_server_config(apr_pool_t *p, server_rec *s) +{ + QueueConfig *pConfig = apr_pcalloc(p, sizeof(*pConfig)); + apr_queue_create(&pConfig->mMessageQueue, 100, p); + apr_queue_create(&pConfig->mClientQueue, 100, p); + apr_pool_create(&pConfig->mPool, p); + pConfig->mEnabled = 0; + return pConfig; +} + +static const char *queue_on(cmd_parms *cmd, void *dummy, int arg) +{ + QueueConfig *pConfig = (QueueConfig*)ap_get_module_config(cmd->server->module_config, &queue_module); + pConfig->mEnabled = 1; + return NULL; +} + +static int process_queue_connection(conn_rec *c) +{ + apr_status_t status = -1; + request_rec *r; + apr_pool_t *p; + apr_size_t read_bytes; + char buffer[NOTIFY_MAX_LINE_SIZE]; + MessageElement* message; + ClientElement* client; + if (c->cs == NULL) { + c->cs = apr_palloc(c->pool, sizeof(*c->cs)); + } + + QueueConfig *pConfig = ap_get_module_config(c->base_server->module_config, + &queue_module); + if (!pConfig->mEnabled) { + return DECLINED; + } + + apr_pool_create(&p, c->pool); + apr_pool_tag(p, "request"); + r = apr_pcalloc(p, sizeof(request_rec)); + r->pool = p; + r->connection = c; + r->server = c->base_server; + + r->proto_output_filters = c->output_filters; + r->output_filters = r->proto_output_filters; + r->proto_input_filters = c->input_filters; + r->input_filters = r->proto_input_filters; + + //ap_update_child_status(c->sbh, SERVER_BUSY_READ, NULL); + //ap_update_child_status(c->sbh, SERVER_BUSY_WRITE, r); + + /* Default the connection state to default to reuse */ + c->cs->state = CONN_STATE_CHECK_REQUEST_LINE_READABLE; + + /* Get a single line of input from the client */ + if ((read_bytes = ap_getline(buffer, NOTIFY_MAX_LINE_SIZE, r, 0)) > 0 ) + { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server, "request: %s", buffer); + char* data; + char* command = apr_strtok(buffer, " ", &data); + if (command != NULL) { + if ( apr_strnatcasecmp("push", command) == 0) { + int sent_message = 0; + if (apr_queue_trypop(pConfig->mClientQueue, (void**)&client) == APR_SUCCESS) { + // Send data to client + ap_rprintf(client->request, "popped delayed: %s\r\n", data); + if (ap_rflush(client->request) == APR_SUCCESS) { + sent_message = 1; + ap_rprintf(r, "message sent\r\n"); + ap_rflush(r); + } + /* ap_mpm_reprocess_connection is mpm_specific, and may use the + * current thread for execution. Don't call until the initial + * connection has been serciced completely. + */ + ap_mpm_reprocess_connection(client->request->connection); + apr_pool_destroy(client->pool); + } + // if message not sendable queue + if (!sent_message) { + // save off data for next client + apr_pool_t* temp_pool; + apr_pool_create(&temp_pool, pConfig->mPool); + message = apr_palloc(temp_pool, sizeof(*message)); + message->pool = temp_pool; + message->message = apr_pstrdup(message->pool, data); + if ((status = apr_queue_trypush(pConfig->mMessageQueue, message)) != APR_SUCCESS) { + // queue failed to push + ap_rprintf(r, "message push/send failed\r\n"); + apr_pool_destroy(message->pool); + } else { + ap_rprintf(r, "message queued\r\n"); + } + ap_rflush(r); + apr_pool_destroy(r->pool); + } + } + else if ( apr_strnatcasecmp("pop", command) == 0) { + if ( apr_queue_trypop(pConfig->mMessageQueue, (void**)&message) == APR_SUCCESS) { + // Send data to client + ap_rprintf(r, "popped immediatly: %s\r\n", message->message); + ap_rflush(r); + apr_pool_destroy(message->pool); + apr_pool_destroy(r->pool); + } else { + // save off data for next client + apr_pool_t* temp_pool; + apr_pool_create(&temp_pool, pConfig->mPool); + client = apr_palloc(temp_pool, sizeof(*client)); + client->pool = temp_pool; + client->request = r; + if ((status = apr_queue_trypush(pConfig->mClientQueue, client)) != APR_SUCCESS) { + // queue failed to push + ap_rprintf( r,"client queue full, couldn't wait for messages.\r\n"); + apr_pool_destroy(message->pool); + return OK; + } + // Currently handled by protocol handler... + c->cs->state = CONN_STATE_READ_REQUEST_LINE; + } + } + else { + ap_rprintf(r, "invalid command\r\n"); + ap_rflush(r); + apr_pool_destroy(r->pool); + } + } + } + return OK; +} + +static const command_rec queue_cmds[] = +{ + AP_INIT_FLAG("ProtocolQueue", queue_on, NULL, RSRC_CONF, + "Run an queue server on this host"), + { NULL } +}; + +static void register_hooks(apr_pool_t *p) +{ + ap_hook_process_connection(process_queue_connection, NULL, NULL, + APR_HOOK_MIDDLE); +} + +module AP_MODULE_DECLARE_DATA queue_module = { + STANDARD20_MODULE_STUFF, + NULL, /* create per-directory config structure */ + NULL, /* merge per-directory config structures */ + create_queue_server_config, /* create per-server config structure */ + NULL, /* merge per-server config structures */ + queue_cmds, /* command apr_table_t */ + register_hooks /* register hooks */ +}; === modules/queue/mod_queue.dsp ================================================================== --- modules/queue/mod_queue.dsp (revision 202039) +++ modules/queue/mod_queue.dsp (patch apache-trunk-proto-hold-conn level 1) @@ -0,0 +1,128 @@ +# Microsoft Developer Studio Project File - Name="mod_queue" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_queue - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_queue.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_queue.mak" CFG="mod_queue - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_queue - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_queue - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_queue - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_queue_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /machine:I386 /out:"Release/mod_queue.so" /base:@..\..\os\win32\BaseAddr.ref,mod_queue.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_queue.so" /base:@..\..\os\win32\BaseAddr.ref,mod_queue.so /opt:ref + +!ELSEIF "$(CFG)" == "mod_queue - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_queue_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_queue.so" /base:@..\..\os\win32\BaseAddr.ref,mod_queue.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_queue.so" /base:@..\..\os\win32\BaseAddr.ref,mod_queue.so + +!ENDIF + +# Begin Target + +# Name "mod_queue - Win32 Release" +# Name "mod_queue - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_queue.c +# End Source File +# Begin Source File + +SOURCE=.\mod_queue.rc +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\win32ver.awk + +!IF "$(CFG)" == "mod_queue - Win32 Release" + +# PROP Ignore_Default_Tool 1 +# Begin Custom Build - Creating Version Resource +InputPath=..\..\build\win32\win32ver.awk + +".\mod_queue.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + awk -f ../../build/win32/win32ver.awk mod_queue.so "queue_module for Apache" ../../include/ap_release.h > .\mod_queue.rc + +# End Custom Build + +!ELSEIF "$(CFG)" == "mod_queue - Win32 Debug" + +# PROP Ignore_Default_Tool 1 +# Begin Custom Build - Creating Version Resource +InputPath=..\..\build\win32\win32ver.awk + +".\mod_queue.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + awk -f ../../build/win32/win32ver.awk mod_queue.so "queue_module for Apache" ../../include/ap_release.h > .\mod_queue.rc + +# End Custom Build + +!ENDIF + +# End Source File +# End Target +# End Project === modules/queue/NWGNUmakefile ================================================================== --- modules/queue/NWGNUmakefile (revision 202039) +++ modules/queue/NWGNUmakefile (patch apache-trunk-proto-hold-conn level 1) @@ -0,0 +1,261 @@ +# +# Declare the sub-directories to be built here +# + +SUBDIRS = \ + $(EOLIST) + +# +# Get the 'head' of the build environment. This includes default targets and +# paths to tools +# + +include $(AP_WORK)\build\NWGNUhead.inc + +# +# build this level's files + +# +# Make sure all needed macro's are defined +# + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(AP_WORK)/include \ + $(NWOS) \ + $(AP_WORK)/modules/arch/netware \ + $(APR)/include \ + $(APRUTIL)/include \ + $(APR) \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + -prefix pre_nw.h \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = queue + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = Apache $(VERSION_STR) Echo Module + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = Echo Module + +# +# If this is specified, it will override VERSION value in +# $(AP_WORK)\build\NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = 8192 + + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = _LibCPrelude + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = _LibCPostlude + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If these are specified it will be used by the link '-flags' directive +# +NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled +# by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/queue.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/mod_queue.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + libcpre.o \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override $(NWOS)\copyright.txt. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @$(APR)/aprlib.imp \ + @$(NWOS)/httpd.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + queue_module \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(AP_WORK)\build\NWGNUhead.inc for examples) +# +install :: nlms FORCE + copy $(OBJDIR)\*.nlm $(INSTALL)\Apache2\modules\*.* + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(AP_WORK)\build\NWGNUtail.inc + + + === modules/queue/modules.mk ================================================================== --- modules/queue/modules.mk (revision 202039) +++ modules/queue/modules.mk (patch apache-trunk-proto-hold-conn level 1) @@ -0,0 +1,5 @@ +mod_queue.la: mod_queue.slo + $(SH_LINK) -rpath $(libexecdir) -module -avoid-version mod_queue.lo $(MOD_QUEUE_LDADD) +DISTCLEAN_TARGETS = modules.mk +static = +shared = mod_queue.la === include/ap_mpm.h ================================================================== --- include/ap_mpm.h (revision 202039) +++ include/ap_mpm.h (patch apache-trunk-proto-hold-conn level 1) @@ -151,6 +151,10 @@ */ AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result); +AP_DECLARE(apr_status_t) ap_mpm_reprocess_connection(conn_rec *connection); + +AP_DECLARE(apr_status_t) ap_mpm_close_connection(conn_rec *connection); + /* Defining GPROF when compiling uses the moncontrol() function to * disable gprof profiling in the parent, and enable it only for * request processing in children (or in one_process mode). It's ==== BEGIN SVK PATCH BLOCK ==== Version: svk 1.00 (linux) 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 ==== END SVK PATCH BLOCK ====