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)
eJzFe+tzG0e2H/1YewU/JD+1a8t2i6IkkALxfpIiTYo9M3iDBEBRlChBg5kBOSKAgQYAKdq0pRk8
CfAlUqLEhy2/Nsmm9l7v9d5btalKJVX5C3K/5EsqVfmW2n8g+ZrTA5CWbEp26t6qqCBgHt2nT5/u
Puf3O92k5Xj/kGVxcNC82GUxL8YuBvr6RtkCN3PaYl/sci4KvFiQ5C7HYlqYE9JdtsW0NN1lX8yy
GQHe5qWizJGLAitPCwVyIXKzQmFw0ALi3C1xlCZiX6wmNckWpGy+y6OJTxRkQeiyLlrNQ1bL4pCN
fBJdFs9iXoB3muCELMyJeVHKgiIWu8fpgCJdlkULSJByQjYhSxJp3Gq2mm2eISupbl7k0lJeSJAW
huyLQw5SwdoFvdJq8KIscKDWAumFIM8JsibvQAYUty5aLIeUdy1mJL6YFvKHVfAcWkHMcukiLzxZ
Qeuko63lj6WhDHSgpa7tEGnQsZa+pkwuo3XplyVaiVE1ifbDJLoek2ial+RZzRi2J/pmWXQfUtVq
e7yqcCsnyGJGyBbY9JMCnqqZ7WBoHPtjmRLTMBsO0cmU4m8WhaJg5LSOPKmd89dXnzmkuuvJ6s5D
qrd+ftr4U3tmb42i9pbN5dILiYJwq8AL6QKr9dZmXUxa3UmXO8mlzA6rjU/ZHBbBlkx6OLeF9XBm
S7LLarHBEgp3dPz3zP/oflexdWxMdtz5tKMSuvdyh+LcuPjXjv/y3nZsThJ5xOYSWu8SYjYlwXLh
Fri0kMhJUlqf4h9/VUA9P94ZdOgX/rE5WZNC6rV+D6R36z59RquPNYJ+WrEfRv2xJarZvG0Tjydp
dzodSafTlXQLvJlNunnO4XaxLidntltsz7Sqk0jgrS5BcJgdLsHGeTyOpN1i55Ks055ysqzVI5AV
am1Z9a5po+eVWx1NS8edWx3V55rG/1+WPNQcWmc8dosl6XG7eM7uSbnNdpsNjGKz2F0CL7BWh/BM
c7iIBHfSYrFYWSjOepx2T9LGuVOcwINZHSlBSLq6LDa3o2WP8v+cK/9txNE407F0uuNex/+eWkJ3
KmMd//W2cifaUcoo/1wsd0yUG+6O9bPKf+M7FL/yv3x3ygMd6v+ZUf72etvJoU7S0Xwxl5PkAtgy
J0uckM8nOCmbhcUBPlzPFWUZnIT2yIDyEjfb3d82n5hC+pOPv+8d5PJocRHpf/qwdzBfYAsCGhhA
I5FwOBGLD8epRNAXZqhodzf69LHxMPUgLKTYYrpgktI8gjWNksIMOydKMuox6R4fogS8TLSG4SkK
H6j6GRLSeUHT+NfpNuKlRgKJKDU2TsXiRFMKbobx8IUg9aS+8zMwA/7Vpe7PQTFbAN/GwvwDVw2T
EUyiXUrFQv8hxcnwkDjcKpGAYKwnjwzozGMVu39FzfxBzSc7lmTB2C132zv4dHnayMjCL0yn/zdF
ntaDz3RP/v74LzweDA6PJjA1EhyOUnpNOgxKMZ8odD9bSbgkyx31cPvDYjKhGTbLw1C3dUAcmMJo
NOp+qjhUyvMtBeECDZCWCCpqARHSTEqc1nMwSUgrrVsYIE6ShXaZdvfIZCWC51mAXSkJJoOUgO92
+3rSOwNpwoAs3WSeDY9GE7HxkREqFnt8Mj1lWWtV2y21V8cTdQ5fW/sVtG9ZKBTl7OPt9us+0+l+
yeQ/l/pzc0PRtJidBoSSnW5VOGj7wDWDL2ZlYkhyd/DyqfGgBQkSj4e6J+v+vDuHunrNUTtSds7s
sdpZlnW6bYLVmrKZwcW7OZvVajY7f0SFh2FMq+dpQMwEuD1b0PDbL4MWd7sRQLLmJxCRzfVs+a1v
DRx5fkU7nmfELa1tsIeLd3IWiyfJcamkIwUWcbsEF+Ajt8VjZa1ugPJOWzuQV1YKlfUPzcudHUo1
1NGxoFRvdNx9Tam/8HXHRWXHeqd0rWNM2XPdqZzvKCj/vHhHne4o/e115btUe3yePjefsaAPm7fm
XzVbf62DeLwykrlWexDM4JlcOHAaKVnKoMJMy4ugHyUiMd9WS+ARrHV00CwsgNaybAc/0k47GGg/
WWle8zHtp3Crh8623M8TgehXxqGW4mkxXxCyAllpaQg+CzkBcFABhOgPe9O931QuxRu5tEgcPM8W
2LYeYAVfAU3LAltIL6C8mMmlxZQo5DVDAEUVOVSQUBE8EItIfx9zshD6igKaEWRB14PEApoX02li
UhADiAVsJWYRTHBRZjUralbNC7DGs5xgRMiXQkkZ3DbKCvNtK6KWn84jViZFswXSNlFEWxRwBWq2
hoBF5JJNimmxsIC4GYFEocKMmN+XpCmT1LROi9MzhR+BCgexYlpAvUTwgtYz0kJWyvbOCkKOTYtz
wr6Q/Z4WJJ5dAJUnxMIMSMxKcoZNo5YxDVr1luIHrbaUA1uJ2X1ZLEoJ8ygDBcS8AJOLh15mF+ZB
7hNTqD1YP9pNmzqtSNVyHFpY6h0kyiY0bfejDjp3MOt+9MYtmyUyRfALiTRoqd+P3tqj9tojfjUK
iC/hC8eoaDwRH/YF9Wf2S86ABENLM4O2LrTFBO0a9i2UIDNvf2rnCq15XcyD2uaDxTbM84j4eTKm
ZH4CejCi+IxAphYMN5sGW+Q1y7WGO79vEplrL6J2rQTL83qtyP4TEqIPJvm+Gj/rfTF7aP/3XUhr
CPt+2hJKsWK6KAudjwEbzS9dGGcSwzFiLj3R8MkYf4hLI37nXy0C/8iAUA6ss9/7/l8ToJNFDQyx
aTBHghfyBVla0LclPP7u8Jie+zGa54r5mafG79yTkdtySLw+CFBWG1B3l8vmcXGCzZxi7W6rWXA6
LE7BbHaxGlV1arEUYpVtEQbl8Rho208jmbTmtWxTAr57LU8Lm6TEkGtfpq3LrYlsqeR4UpopxM4K
5I1RzGoKtCW3qtqfqPoTRUwt+GjM2H9e0fHMNuEusZ+g+VlV5xNVXU+tyudzP6/sembl8AQTHs+0
O/zzyu4nKtt/3jK5M2ZmH6/59BGwtkb1acjFlkh0OSwtVNLR/Vz3H3X7tLhLX5DAF8ociOs2JYti
mjflcwInsmloXKc7fKLZNArvsfFA2q02J8fxnD3JJp2c4ErxbjvHWQEaPVslO6hkNbcpfody40Ol
6wfc8T3Gqle/7neuhZQOPEQpx7ex4lOjSkeNz6ZR2yxIyJJ4oMVEEqbQgS1QcgHxLVJNnMMwhP9E
KILHg5Se5IYNEGDTOaLHFaBZyRtQKQ9XsGiLHDy6ojlkmGZX4V+3Tjc6HPeCE/fFW2kjAwpLBTEF
EVkLHRCOWQjw8Dgr0VAq5n2KtezEWqyH83AOlnNzVovd5bILNqsjyZodDmfK4TG7U8+2lgOsZYOK
bXP944WV2ebxO1PYr1CDDf/vmOtVbK1gSWGul7D/L1SWuY4vqYzStR5ULpaYSay+vUydqNADq8zk
RiBUxo4lrIw0mFNY4ZZCKa/6ohoqHbsHd/8BqyHsJDanlKSKFYu/dFqlM99g5aUKvK5QZiVaOoEv
bYcrr5bCFYTV3yvRir0UqXxEVcbjlfe8ldkStsQqc/XRCqpFq0byH5feUseqV8tQoYkr6BFVHVLo
Wvc/gV6+6vkVXB1WYvWXq5H6yTKuv1Ol62dqOF6h6icVqvK+erE2h9WxunfpnWidwvUIrkt0va92
qf55ja6/f3mph6m/51/yK7icWWXqR6tMRVL89UCFafTX6fpLgXq+xDRkha77a7gxXvU2FhSsfBCq
H6EbRpVpfKKG6r+vc81TgXpfrBml6pFo047rk/7mhL95nqnPlOlmV9W7/HHJ1/ioQi3NqHT92AbT
OFul6skS3RAmGhkFGqkztaC3MVyhG/1qaOV6KVhjqOap+PKQgptdzPKVcnBZxHWu5m32+qo6Ba9e
oxvXFKhPV9M1evXzMrNq9i39rgSlQw2fd60LN99agRtq+dNavHaVSAk3joWWMqElXKLq/XC/TK32
K96lJL1uptfO0k1dCczjb75BrWO62aleXrFcXJmseBue0ZUFqnlaia0ewevnlLHlIe/6eVAJ1/rK
vnUpunxcwesjUBcUBsupuHlUYdbepZQT6mTzucDauyBNoTfO0HdH6M2XVGrNXvKvXvNuvqwwm8eg
v77NF/HmmdDd0yCmgDc+wdWzNab2AV73lsKbCSgT2UyolzbHvRtz1OZldWwzGbo3CI/D9wZD996N
3Btr4oalwqx+hu+e2qLXXXgjkLn/5hJ9/7Ulqnw6sHkcr36uYLWoeLdeK2PFpOK1CF43q/TWKQWX
Zu/TtWl8/+Oyd+vFBlYFXJssUfcGK/TWW2Ameus86bN/DfvuvoofvKrQaxPKeG1q3Vf/Da5MbtIP
X61TG6cCd8/6Nz6uMmsXmeYpekksBx+Gq3h5lKmmS74HgSp+eBleUOvnmIezSnjdSW+/632Y3/A+
FKHPdsW/fY6usxVmSaKWx+COV6mGl6kfq0408wpu6Mv0g1PU9pVmcJvF94MV6uEk3rLBs8DO5Sb8
qGDtu/jhUBVeKIGd57w7utro7rFrO4wyup2jVs3jO4t4+0Xv9hzevkntOkCV4M7n9O5F78MgvScq
wZ3LOIhrL5e8q6NgrhL+4nlvuQ9WBEspZ2jFpAR3L9TwgzNgOEyVLRWqerSGm0eq1Beu2ugX/f7N
39VxY6JCK3Q19MV5vDUY2Pn80hfPgwrBzXdCe5xv+XjNt3vMt6Fn9m74d55X8c4rRBnlXJlSOVjO
4Z3nleD2zbGdiRJ+cFShd9K4bC3Hdwr+eqhMLb83/uhVb9Pu+yqgBFbfh8UVeORQfI9GQ+v+wFc3
vc23vI9ux7/WMRufKhe/8vu+jke+Pl4LfR337vZFdkcU39rL4Z1jePfSpeZ539cf4+1T4Z1g6It+
/MhPP0qV8HK4hL+J8Xsn4FvBj64y3568uIcjj94DEeE9rhLZXZzY6wY1vd9yYIngXu7S3qWxb28x
G58Evjnn3cvBh/ru9OS2Q726Pebddk7svB1u0r4dt+/R7SHvjg9sz+yeagR2LaNfL0S+uz393dzl
747wf3g1+l3XkPLCV28zD05d//ojZmc49kfTta+vRHbfwPeOz31jCDU/8/6RG4p8s1CGIsy3J0p4
OwrDc6NMfdUFs0W9/S3vuzuvhr87Hv53RoX+IlCD3qh4NUJVu5k/iaXgl32Xty7A7A5tsYk/nPZv
c5F/c6tKfWnEDzNj341f/LdD7B9epfdyWPsE/tQ/tjxL/91tqnGNaRrrVCO1xvxpDjypynz/nErf
H2l67w6XqNLHYDdm06LSilXFGwx9d1gBX1KOND5cDTe83oagUn/+CFdPj355/dLqqPf789T3g6G9
E7F/eBnvBJepv+dv1LpV5u+mGt6atcx8H4TXVXCnuDzewF++iRtFunZbZbb6Q//weQl/O3b1h7cU
75f05YZRifzwMjSc+QFN/OU93w/T/u+f9/7wIiwq/O0tBcdxY4z+wRr+83Hqh5e8fz6uUH9G+B/f
LAHjGZFyC7JGPi0ej6fXajY7COFBwzkWGCuKSanCPKE+tFTM8i2SDPxUBOaTFjkhCywa+BYLlBbY
IwRYkSMQAuhiTxCABFSBgA7U56Ig561GM9J3AkVZkIooAww8KxXa1BawBonqEPo5IVcg+IOTCMln
gYUDXwVCOyklCyw8Z+FNbgFJKcQWZgqFXJ/JND8/b2SNkjxtApwX9I1QQA97obHxLGAaQtZuFgHH
8ATDpNl5dloW4KYgzctiAbgHwBQeeKEsJosFMQ+9Y7OocziGfLFOdGE45osZJnxxb2Q8jiaGo9Hh
cNxHxVAkSpIh2Bf3RcJwR6Ph8CQK+MLYgATQVgMxOWgzJqQkDfalRA4az04XWWD10xLAnCy0jXKC
nBHzhGTzaTEDRjXpdKce21ppZ3eNM52ZTJYHagx8C6hgQeKkdJvJtMhQHkgUEDPoQprgo4Ig61qg
jtDAFlLbZ3QJPBwfRol+3SlAdGJWQOFI3EdPJkLDl1qJnJjvMoXcZo9TR5IzUKgN5IDXJQo9KBMC
q0I3xvpHtNwC4VYoMwrfYraAMlSWBwqJRvp1QNoIJeyh0gJJHnIzrAy18xzSNt56OJLOEVqYT496
cgak8cd8N8yd3ACnsTu9+IkgpfTd+jO9gwZkMZsNGpM0t/gatAP2yQO/JAw0wydyrJwBRg6XBr6Y
ySwYWHla39Pdyp/D095BIuaMhWS+24xaz7UzbiC2F/XIJPdG2HhyAXRLFlMpQb5ytQdx2saPtj01
MNANF5/ptL0MdBIshg3sdCeS5QEkQ4n+BBD3XLEAhdCAlloxmUCDYo7nZoAG5JMzBgSE/CIVTVwY
j01qeTPDRNQXp8AC3QebVwIvgSY9pt7BgUOTbiTVxgiFdsYL1oOWGtTrDSDFgMzd3WgQmREYMyHI
siTrh0eDEQYGORowIC0vAIX60Ol8p4Ek2mC5ZdhsQZrtRJ1goZNZtkC2J7hMTt9JGHSnodtMcl0J
lELyQk7K6fU9Pd1nHssmoJgA/iGXkHPA6AspPbF0JxSEGQTUIc0uCPyUPJUFQQk5lQaR6DOYHbDw
DQK4DrKrA+vmlsAVEZayZ2E8ilmYzGIWFimbngFLJwUhy4HL4YWCkF4wtnMCJhOoxZ/Ms3OpLCD7
gpCBiTQAr/gi6JhixYKETNruhJQTMxmBF7UcomzoLKbTxTRP9kbyxkhgBB6S/ZnkgmwEGj3Hwnrk
81euIpIy0chKgg4OM/rO0U6DlDWgaCw6kgAfQHdGi1J2RvoUfab7TBamSXJTTsxI0myezXkjkUAi
5MOY7M4NwJiF8XAUW82x+Dh95MgR8L69BxSrKGfARxoK6LP+p/Cd1ikCW5JL2W1um8PhdnJO3uVy
2Dir2W5hHXzKxXLP5jtO4DsWp8Pd5jvfvlQZrJnvjF3tWKO67gg+a4lWPH+hAMerryjMh8t+tWOd
UT9awmquBNfwoVRc9luqcfXTPawcLWN1HijNELyoUSUeq5eWqfILXjUNnOaFpbT6KS6/FjCPKjkF
KlSxKjYipZB6sWy5UuZruPxGUnErVyu4slCZAchT8Z64S5UiK1h5l6q9VMYfYAOA/bNLuNa/Qdem
qlTt6t2pSghKwutlf+20r26mqnaFVqKhWidVNy/7yvPBevfylXq+wtRl31LHWN1xtR6YqmeSS6/X
aHUK1+NQb3TJUaLr099QzeeqdPOVdaZxbbJxYyfQjDeuNa9VAs1rkebrgeZLweYHird+S/FZy5Hm
aWig5G9kgs3Xgeb0kTrLnzbDK2/C8zVf8yh5sDIBpvoQ9Aw0EtTqUW8j411FodXe5ujqCXo1vALV
/z0R6C/9Hno926RW3l4NrnmYVVRcFe/iqmPo8tqJda62SFftt+pnlcn6deZu/NrS87ENwydLDt/G
m5c30PWNj4dGGk5gOAsq3RxVx5btN5tvxu51DU00LwbvUZPLHrCKvDzpu0dNrbwN39KKh7lHXVqR
vA/eG1KOrh69sW6FIkNK15p7CD/8pBao3qSXHGBYuua6UhYu7z7n2zDQ1bkq1dXwL08CRTKUQrvB
mV1KubmbodYilHoOED2oX5uvLTAN5zK1+QEpz8zXsDrkVV4pUbsA82sRdm9SCe99UKV3Lyu4drsO
/1X6ywtLdHMSZNBbFHyYvZtK6O47Cr18rUpVTtWYL6eYZgJA8yeVyN4HzG42+EVo4W7PkOr6wuTb
uRHdvYl3bzI7C/Q3s97q4ikUEjlZygNOAdc5J6QlCKooVijyooRGZYkkIxBNwEUvCrMZYaDzIP3U
CY9GWW6WxOTIfFaQB87bB3UM2ZxgydbABZK2MQDykTNsQYMwBP04jWaz7hTqAU8dIbETUYAD4BYi
N4oPR5n45CiFOifErM2K9Lfczm6EF7JsRuR6g2J2FgXFpMzKC53IfMtsMVt1uhGaIaEnKqQF8Li6
kyFwpsMMBSAMnCN8CEpiyT4GBM39vJcRxSWUhChDfD8Kh4YDlGF/k4C6Rc5ioBBq+XQeycUsMqWQ
ESp3GicBe3EAcVqoZEHDUwRiFKHL8zNCNtvK9IgZFoyKQDckZcELQ4vttExf56iUz4vJGQl8cZ7s
c7Ay0pNtfb4bAxqZvgBOMAu2GI1GRtEwRPH5UUEewUIO/DTx4FApxnEJ1NkZlCDKjwKOGxkdHeDS
RnD/ulA8OJAR+WhsZEDmdCd9NEKdXXrQo7sTIi8AMgqNg08M0SOJiBZmE1iUUaePHHNoeXchTg4R
+qazZD98GGMQjkxZKS1NQyQIYWSasCFTxIpMGEbJF7ZZO8OtPDnc4MgEwD4TDaW4yEIvMl0WkcmH
Oo1GE3zawKwzL3NpMQlBXe4lgIufIok+UHw+MwuICV5ZzTboADKlYZDtZg8y8RdiIzbrQDLPAcIK
wFWaTIVZQIFC2mY1QpV8MZlfgNiR6ZsXs7w0n4dK6TQywTjMgPn7fDa3E5kAWfSZ8hKo2DdkNE7B
R8pPTV0A4w/zvGyUhZQBlJSF1mZtXxZ6zEOtXKEPXul0J6lgjLLwzKUID9eAX+mYdqRTp4tFxqMj
1IDRCPCNADIjOz/bBiKJOEC7kWK+IGV60QgBbVEhr/NlwfadnagPdem7feE49kW7OyPjuiNQEfUC
Guls4c8WjegkCEg2zgAmOTy2acefBJfDbbO4PDzvEJycYHa4PFaLzWG3JAUzb3E7nh3bXCTzeXCG
ruPbjvql+vCdEO4oUa8sUa/gM3+lPqxgM6N0LFPTVXy5TAfoaQUvrtCBEn59C/+2hs24oxp8u4w7
FTq25E14FcsD7Coz6oJKnVf9ikeBJ0zpaGWs9Ppd/Ftf6agyVvqgFi9xvpKVGQmqp6Fs/zql3qbL
w4qv9Mr6lfIxWj0RLZuq8JCpfBgovXKt/DusXoAI+ypWTsMPV6UUCZc6lEg5OF7xlINqXzlQuVbC
725SFZ6qfvSQqc404qXnfeXfjZX9wdoHVyrdo5WFUqDmrsarNytDyus1XW0oVdNFa3m/ehb/VsHV
qOqr8IxybB2rUXDJJ5lPlGjDVWVUcwlXWNw8ArI3cSO9glV/2aeexw33fW9Df6lxsxpovqZidS7Y
NCi4MU41hfHm2CZWXJtUibrczNcjzSOjTX3Jv+xSqJWT8BJiqKBEl4FmsnTj5gqtnl9iltNMdUrF
y6cvKp5gBitxunkdHpYyqy/hiuBVjlSZ1fQSXpmvXF59ybd6kmlORJZ/A6H3NXh+D9DDJ2vjpdj6
W6XQek/ps3VPJQrXeI3G64bA6kvehnlmLUWVz8FTphzcoZavpNbGcUXEa5kqtda9ijdPMWs90DxW
chW8Ms5cD6wZmZJBpZb5qm/TBKLmS7jqx41ZsE501bs5GMhQldNV770xhfHTG79RcSPPNGK08kYF
g3qGQLOfOV+nmlkIhheCg+P3pkrX7hVKkf7Rhh56BMBJ8qq/rdNbb/jv3WxSCipT6osq3N7HzeHK
6P13yvT900rsvjG8dQTfH5W23qfVc+FKfBmXHSVqs3OsIuDmNf/WzRK99Tmu5ar8g+NMCZcYlaK2
hoNbDhVXzQpVHa/g5tXLDzJ0Cc8+fN37MEedL+H7N1XqITV534ibXSq9fV6lHgx6732qUsqH3vsv
4K2b9HamenHn/RK9Gby204935rKri2COVe/Dc9TWnG93wruLYGJcUfBm30pwx0tvFRXv3hvUeYUp
XaO3b5eZPRe9ma349nz4Ie3d8/lrH4B1FWLhvecbeO8teuv02N4J+ou3mD07WInZvhm+bwQZtzNb
R/z3R+e3hkqBrU9Gq0cquBBUjjHbb5TwiTJuvotXj4FJ31zCZuqhp+S7/37Jf/9GlXpEbn2PPi4x
W8+XcGOGfvQO8+Ub/i19FT98Jfg2/vJzvDvBPBhkKknVVx0o4xV76briquMvMwp+pMebUazCIDa7
lqivzoBUlbrf06SXORWMWvbvLlKrx+vUw7zXQN27xihWautqg9oMUQ9v4Z1zXuUNuKC338TVcX+V
9qkn6Ifvqr5vXkgqvfjrz2klVjoFAQ4LXJpkRrSt9WLyAMprBxMkssNO9n0KrcMHp8DHjl8ALxkD
RjGlO9KlpyJBXyzejXSAOApnyfb1WSSleCRk50RZyhIXbkRtFNAKPPn9PRjUOiev5Q1AkRxJhYCT
zoMvBrIyEYkGuqemtI0yoDJcQTvMf7aVYsmH2FltIzuNsgJwKYIpINKf1WRDoOFbm93kjACbJJGc
5CnIxrkBQj0J5loiBRr1hUegU5eOnAMeE56IxLr3d9pYmZsxZYXCfBTY4XjcF0yl2WnAItBoCoI0
YArgUUd6cxCRxFsIfhLZeeMMpmhg0vxMdtYI4SpIjm0AdcxykgzQRxZJUgkoIEEZiGSgUqBBlApS
gAdACzEl3CQwATBCJ08wSCdCYEdeTOmyEoiTW9iqCNgGeDygn3AwRKAVdLAF9vJnyTbWWXFOyKYz
rWMfaQEAZTLNZmcB01HxBLxA+jzAy/luIzQJEhLh4RB15MgA0sBkL4wPh4zIgKnYSNQ3SlJD8E6L
f8D1Y3ALND7ajShuRkKhs72tbX+D7lQ87iU5gAFfO1MkAOYE2gpRWBZ5cjoD2gB+77QHgEGOBEh+
hpyK0sEEkReocDw6mYhNhqCtBGDLkVFZuCUWLvniUr6gHTkZ8VIDCA2PxyPj4WBkGBvQaIwax5HR
KEWFslp27RIewWyBRWAq7ShRNl8wscZbPGckWJEX80myOVcotHf+xsM+AHcjI1oiaUAWDAiwQOSC
n2AAkzHouwB4Bm5hDWg5HsQmoTNGAgkzACOK+bOms+SAi8xyJE91Skf7glQsISVv5Ak0l4Drsyjd
gskAYOEKPlxOhoUGNpZQWmIBek3p0Ex++mw+P40G4DKdm+L2M5nGwq3CcHZBZNNIzBAwnEfT0qUh
I9yQlCGP8guZJFkuwq0jIJocJxLYLKcnk4QkAEmarbuvDxFoo9PBwMNnPMdnBZIw0p3KpVlOHxO0
Iz4AivN9fXlERwA+6Y5M9XTpfWEYpmCwe8o6NdVj7AHc/glMWrnAiumzGoAX87ojT6H42tFAQEEC
CxRfsAkpp9kpmC1O1plKOngrJ7iEpPPZMMitUXzX/gaw4zUgfP6O/xh47Y/4tZ1QTP1x8z3N9qF8
WiK+KOYlqb9AN+qViTOBjoNdSDaGbF+j3nYqsZclmbveuTYRSktQLhTBibFxapxKBDGA7W4dBqc2
AgsznIhrCwf8XXvLXUeOkYjknIwuD6MPRhlgn2IHN7GD05xyJ5NuNunwCBaP22K1cFaz2yGYSarD
6bAdnF60Pnl60eLc/xMcU+u4inGm9cc6v3RSkRR65lFFq3YSxO4RUkne4kg5reaUw+WwJe2C1eJO
2m0pB8+m7F0Wl7ll/v/00n8+8aryZsdfrR134Kdy6a/Gf+lpwYOH5ATRv+SYzsHDQ0eg1VOH3WpP
ejwOm4e3C5wZpgOXsnG2JAyFwNntnPYnThandRHJFrvD4x7Kp8UMrJsbnIAWEdlK6DU7e61WZHH2
2a19VjuCe2DPrTONEFiMulZNzzNruvrs7v2awHNg4jx27nFG4gkHThWz2j2rnbUjtDev0VVytoEc
su6yumFACRfpLQAhnu3V0ui9M1Ka7yXSBgetMJWsrb9h0xhkoa9vPCuSyc6mTzsXu+yLZGl02RZl
YQ5uikWRJ+d6TI9L3f+DtS6bc9GW5CBauzzQixTba7ZZzL3ulMPSK7CCh0sJHOuyuAe7rYtPle1e
NGnuqv3damB/DpMWLLaUCwbH0Wt3JZOtFmCwnL2pFGt3mEnm3unucvw6Tfqe6Eef1ov/C5HZFxY=
==== END SVK PATCH BLOCK ====