OK.. this time I sent a test before posting... and the post still has
problems.... it seems the list server (or something) is wrapping long
lines..... how do I deal with this?


----------------------------
  .-.    | Steven Velez
  oo|    | Software Engineer
 /`'\    | alventive
(\_;/)   | 678-202-2226






-----Original Message-----
From: Steven Velez [mailto:svelez@;alventive.com]
Sent: Tuesday, November 12, 2002 12:23 PM
To: 'Tomcat Developers List'
Subject: RE: [PATCH] Fixing Interoperability problem in iis connector


This should, hopefully, be correctly formatted.


Index: isapi.dsp
===================================================================
RCS file:
/home/cvspublic/jakarta-tomcat-connectors/jk/native/iis/isapi.dsp,v
retrieving revision 1.9
diff -u -r1.9 isapi.dsp
--- isapi.dsp   9 Apr 2002 23:06:52 -0000       1.9
+++ isapi.dsp   12 Nov 2002 16:58:07 -0000
@@ -170,6 +170,10 @@
 
 SOURCE=..\common\jk_worker.c
 # End Source File
+# Begin Source File
+
+SOURCE=.\req_info.c
+# End Source File
 # End Group
 # Begin Group "Header Files"
 
@@ -265,6 +269,10 @@
 # Begin Source File
 
 SOURCE=..\common\jk_worker.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\req_info.h
 # End Source File
 # End Group
 # Begin Group "Resource Files"
Index: jk_isapi_plugin.c
===================================================================
RCS file:
/home/cvspublic/jakarta-tomcat-connectors/jk/native/iis/jk_isapi_plugin.c,v
retrieving revision 1.18
diff -u -r1.18 jk_isapi_plugin.c
--- jk_isapi_plugin.c   25 Sep 2002 00:49:40 -0000      1.18
+++ jk_isapi_plugin.c   12 Nov 2002 16:58:07 -0000
@@ -78,6 +78,8 @@
 #include "jk_worker.h"
 #include "jk_uri_worker_map.h"
 
+#include "req_info.h"
+
 #define VERSION_STRING "Jakarta/ISAPI/" JK_VERSTRING
 
 #define DEFAULT_WORKER_NAME ("ajp13")
@@ -109,6 +111,8 @@
 #define URI_SELECT_UNPARSED_VERB    ("unparsed")
 #define URI_SELECT_ESCAPED_VERB     ("escaped")
 
+#define SHMEM_REQUEST_INFO_TAG  ("use_shared_mem")
+
 #define BAD_REQUEST            -1
 #define BAD_PATH               -2
 #define MAX_SERVERNAME                 128
@@ -142,6 +146,17 @@
     }           \
 }\
 
+#define GET_REQ_INFO_VALUE(ri, name, var) { \
+    char *temp; \
+    if (temp = rinfo_get_##name (ri)) \
+    { \
+        (var) = jk_pool_strdup(&private_data->p, temp); \
+    } else { \
+        (var) = NULL; \
+    } \
+} \
+
+
 static char  ini_file_name[MAX_PATH];
 static int   using_ini_file = JK_FALSE;
 static int   is_inited = JK_FALSE;
@@ -159,6 +174,7 @@
 static int  log_level = JK_LOG_EMERG_LEVEL;
 static char worker_file[MAX_PATH * 2];
 static char worker_mount_file[MAX_PATH * 2];
+static int  shmem_enabled = JK_FALSE;
 
 #define URI_SELECT_OPT_PARSED       0
 #define URI_SELECT_OPT_UNPARSED     1
@@ -670,6 +686,7 @@
         char Host[INTERNET_MAX_URL_LENGTH]="";
         char Port[INTERNET_MAX_URL_LENGTH]="";
         char Translate[INTERNET_MAX_URL_LENGTH];
+        char target_uri_buff[INTERNET_MAX_URL_LENGTH]="";
                BOOL (WINAPI * GetHeader) 
                        (struct _HTTP_FILTER_CONTEXT * pfc, LPSTR lpszName,
LPVOID lpvBuffer, LPDWORD lpdwSize );
                BOOL (WINAPI * SetHeader) 
@@ -681,6 +698,8 @@
         DWORD szHost = sizeof(Host);
         DWORD szPort = sizeof(Port);
         DWORD szTranslate = sizeof(Translate);
+               request_information_t *p_request_info = NULL;
+        request_info_name_t info_name = 0;
 
                if (iis5) {
 
GetHeader=((PHTTP_FILTER_AUTH_COMPLETE_INFO)pvNotification)->GetHeader;
@@ -700,11 +719,13 @@
         /*
          * Just in case somebody set these headers in the request!
          */
-        SetHeader(pfc, URI_HEADER_NAME, NULL);
-        SetHeader(pfc, QUERY_HEADER_NAME, NULL);
-        SetHeader(pfc, WORKER_HEADER_NAME, NULL);
-        SetHeader(pfc, TOMCAT_TRANSLATE_HEADER_NAME, NULL);
-        
+        if (!shmem_enabled) {
+            SetHeader(pfc, URI_HEADER_NAME, NULL);
+            SetHeader(pfc, QUERY_HEADER_NAME, NULL);
+            SetHeader(pfc, WORKER_HEADER_NAME, NULL);
+            SetHeader(pfc, TOMCAT_TRANSLATE_HEADER_NAME, NULL);
+        }
+
         if (!GetHeader(pfc, "url", (LPVOID)uri, (LPDWORD)&sz)) {
             jk_log(logger, JK_LOG_ERROR, 
                    "HttpFilterProc error while getting the url\n");
@@ -802,14 +823,30 @@
                     forwardURI = uri;
                 }
 
-                if(!AddHeader(pfc, URI_HEADER_NAME, forwardURI) || 
-                   ( (query != NULL && strlen(query) > 0)
-                           ? !AddHeader(pfc, QUERY_HEADER_NAME, query) :
FALSE ) || 
-                   !AddHeader(pfc, WORKER_HEADER_NAME, worker) ||
-                   !SetHeader(pfc, "url", extension_uri)) {
-                    jk_log(logger, JK_LOG_ERROR, 
-                           "HttpFilterProc error while adding request
headers\n");
-                    return SF_STATUS_REQ_ERROR;
+                if (!shmem_enabled) {
+                    if(!AddHeader(pfc, URI_HEADER_NAME, forwardURI) || 
+                       ( (query != NULL && strlen(query) > 0)
+                               ? !AddHeader(pfc, QUERY_HEADER_NAME, query)
: FALSE ) || 
+                       !AddHeader(pfc, WORKER_HEADER_NAME, worker) ||
+                       !SetHeader(pfc, "url", extension_uri)) {
+                        jk_log(logger, JK_LOG_ERROR, 
+                               "HttpFilterProc error while adding request
headers\n");
+                        return SF_STATUS_REQ_ERROR;
+                    }
+                }
+                else {
+                    p_request_info = rinfo_new();
+                    if (p_request_info == NULL) {
+                        jk_log(logger, JK_LOG_ERROR, "HttpFilterProc failed
allocating memory "
+                               "for request information\n");
+                        return SF_STATUS_REQ_ERROR;
+                    }
+
+                    rinfo_set_uri(p_request_info, forwardURI);
+                    if (query != NULL && strlen(query) > 0) {
+                           rinfo_set_query_string(p_request_info, query);
+                    }
+                    rinfo_set_worker(p_request_info, worker);
                 }
                                
                 /* Move Translate: header to a temporary header so
@@ -821,9 +858,33 @@
                     if (!AddHeader(pfc, TOMCAT_TRANSLATE_HEADER_NAME,
Translate)) {
                         jk_log(logger, JK_LOG_ERROR, 
                           "HttpFilterProc error while adding
Tomcat-Translate headers\n");
+                        rinfo_delete(p_request_info);
                         return SF_STATUS_REQ_ERROR;
                     }
-                SetHeader(pfc, "Translate:", NULL);
+
+                    SetHeader(pfc, "Translate:", NULL);
+                }
+
+
+                if (shmem_enabled) {
+                    if ((info_name = rinfo_map_insert(p_request_info)) ==
REQUEST_INFO_ERR_NAME) {
+                        rinfo_delete(p_request_info);
+                        jk_log(logger, JK_LOG_ERROR, 
+                               "HttpFilterProc failed to set the request
info\n");
+                        return SF_STATUS_REQ_ERROR;
+                    }
+                
+                    if (!SetHeader(pfc, "url", 
+                                   rinfo_append_name_to_uri(extension_uri,
info_name, 
+
target_uri_buff, 
+
INTERNET_MAX_URL_LENGTH)
+                                   )) {
+
+                        rinfo_delete(p_request_info);
+                        jk_log(logger, JK_LOG_ERROR, 
+                               "HttpFilterProc error while adding request
headers\n");
+                        return SF_STATUS_REQ_ERROR;
+                    }    
                 }
             } else {
                 jk_log(logger, JK_LOG_DEBUG, 
@@ -961,6 +1022,12 @@
                        uri_worker_map_free(&uw_map, logger);
                        is_mapread = JK_FALSE;
                }
+
+        if (shmem_enabled)
+        {
+                   rinfo_close_map();
+        }
+
         wc_close(logger);
         if (logger) {
             jk_close_file_logger(&logger);
@@ -1023,6 +1090,10 @@
     jk_log(logger, JK_LOG_DEBUG, "Using worker file %s.\n", worker_file);
     jk_log(logger, JK_LOG_DEBUG, "Using worker mount file %s.\n",
worker_mount_file);
     jk_log(logger, JK_LOG_DEBUG, "Using uri select %d.\n",
uri_select_option);
+    if (shmem_enabled) {
+        jk_log(logger, JK_LOG_DEBUG, "Using shared memory to pass
information from "
+               "the filter to the extension.\n");
+    }
 
     if (map_alloc(&map)) {
         if (map_read_properties(map, worker_mount_file)) {
@@ -1079,6 +1150,11 @@
         }
     }
 
+       if (rc && shmem_enabled)
+       {
+               rc = rinfo_init_map(logger);
+       }
+
     return rc;
 }
 
@@ -1108,6 +1184,32 @@
     return -1;
 }
 
+
+int parse_enable_shmem(const char *shmem)
+{
+    char *shmem_indicators[] = {"on", "true", "enable", NULL};
+    int ret =  JK_FALSE;
+    int sh_mem_int = 0;
+    char **cur_indicator = shmem_indicators;
+
+    if (sscanf(shmem, "%d", &sh_mem_int) != EOF && sh_mem_int)
+    {
+        ret = JK_TRUE;
+    } 
+    
+
+    while (!ret && *cur_indicator)
+    {
+        if (stricmp(shmem, *(cur_indicator++)) == 0)
+        {
+            ret = JK_TRUE;
+        }
+    }
+
+    return ret;
+}
+
+
 static int read_registry_init_data(void)
 {
     char tmpbuf[INTERNET_MAX_URL_LENGTH];
@@ -1162,6 +1264,10 @@
                 ok = JK_FALSE;
             }
         }
+        tmp = map_get_string(map, SHMEM_REQUEST_INFO_TAG, NULL);
+        if (tmp) {
+            shmem_enabled = parse_enable_shmem(tmp);
+        }
     
     } else {
         rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
@@ -1230,6 +1336,13 @@
             }
         }
 
+        if (get_registry_config_parameter(hkey,
+                                          SHMEM_REQUEST_INFO_TAG,
+                                          tmpbuf,
+                                          sizeof(tmpbuf))) {
+            shmem_enabled = parse_enable_shmem(tmpbuf);
+        }
+
         RegCloseKey(hkey);
     }    
     return ok;
@@ -1263,6 +1376,8 @@
                            char **worker_name) 
 {
     char huge_buf[16 * 1024]; /* should be enough for all */
+    request_information_t *preq_info = NULL;
+    request_info_name_t name = 0;
 
     DWORD huge_buf_sz;
 
@@ -1272,17 +1387,40 @@
     s->read = read;
     s->write = write;
 
-    GET_SERVER_VARIABLE_VALUE(HTTP_WORKER_HEADER_NAME, (*worker_name));

-    GET_SERVER_VARIABLE_VALUE(HTTP_URI_HEADER_NAME, s->req_uri);     
-    GET_SERVER_VARIABLE_VALUE(HTTP_QUERY_HEADER_NAME, s->query_string);

-
-    if (s->req_uri == NULL) {
-        s->query_string = private_data->lpEcb->lpszQueryString;
-        *worker_name    = DEFAULT_WORKER_NAME;
-        GET_SERVER_VARIABLE_VALUE("URL", s->req_uri);       
-        if (unescape_url(s->req_uri) < 0)
+    if (! shmem_enabled) {
+        GET_SERVER_VARIABLE_VALUE(HTTP_WORKER_HEADER_NAME, (*worker_name));

+        GET_SERVER_VARIABLE_VALUE(HTTP_URI_HEADER_NAME, s->req_uri);     
+        GET_SERVER_VARIABLE_VALUE(HTTP_QUERY_HEADER_NAME, s->query_string);

+
+        if (s->req_uri == NULL) {
+            s->query_string = private_data->lpEcb->lpszQueryString;
+            *worker_name    = DEFAULT_WORKER_NAME;
+            GET_SERVER_VARIABLE_VALUE("URL", s->req_uri);       
+            if (unescape_url(s->req_uri) < 0)
+                return JK_FALSE;
+            getparents(s->req_uri);
+        }
+    }
+    else {
+
+        if ((name =
rinfo_name_from_query(private_data->lpEcb->lpszQueryString)) ==
+            REQUEST_INFO_ERR_NAME) {
+
+            jk_log(logger, JK_LOG_ERROR, "Failed to read request name from
"
+                   "query string\n");
             return JK_FALSE;
-        getparents(s->req_uri);
+        }
+
+        if (!(preq_info = rinfo_map_remove_at(name))) {
+
+            jk_log(logger, JK_LOG_ERROR, "Failed to find and remove the
named "
+                   "request: %d.\n", name);
+            return JK_FALSE;
+        }
+
+        GET_REQ_INFO_VALUE(preq_info, worker, (*worker_name));
+        GET_REQ_INFO_VALUE(preq_info, uri, s->req_uri);
+        GET_REQ_INFO_VALUE(preq_info, query_string, s->query_string);
     }
     
     GET_SERVER_VARIABLE_VALUE("AUTH_TYPE", s->auth_type);
@@ -1406,7 +1544,10 @@
             unsigned len_of_http_prefix = strlen("HTTP_");
             BOOL need_content_length_header = (s->content_length == 0);
             
-            cnt -= 2; /* For our two special headers */
+            if (!shmem_enabled) {
+                cnt -= 2; /* For our two special headers */
+            }
+
             /* allocate an extra header slot in case we need to add a
content-length header */
             s->headers_names  = jk_pool_alloc(&private_data->p, (cnt + 1) *
sizeof(char *));
             s->headers_values = jk_pool_alloc(&private_data->p, (cnt + 1) *
sizeof(char *));







File: /home/cvspublic/jakarta-tomcat-connectors/jk/native/iis/req_info.h
/* =========================================================================
*
 *
*
 *                 The Apache Software License,  Version 1.1
*
 *
*
 *          Copyright (c) 1999-2001 The Apache Software Foundation.
*
 *                           All rights reserved.
*
 *
*
 * =========================================================================
*
 *
*
 * Redistribution and use in source and binary forms,  with or without modi-
*
 * fication, are permitted provided that the following conditions are met:
*
 *
*
 * 1. Redistributions of source code  must retain the above copyright notice
*
 *    notice, this list of conditions and the following disclaimer.
*
 *
*
 * 2. Redistributions  in binary  form  must  reproduce the  above copyright
*
 *    notice,  this list of conditions  and the following  disclaimer in the
*
 *    documentation and/or other materials provided with the distribution.
*
 *
*
 * 3. The end-user documentation  included with the redistribution,  if any,
*
 *    must include the following acknowlegement:
*
 *
*
 *       "This product includes  software developed  by the Apache  Software
*
 *        Foundation <http://www.apache.org/>."
*
 *
*
 *    Alternately, this acknowlegement may appear in the software itself, if
*
 *    and wherever such third-party acknowlegements normally appear.
*
 *
*
 * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software
*
 *    Foundation"  must not be used  to endorse or promote  products derived
*
 *    from this  software without  prior  written  permission.  For  written
*
 *    permission, please contact <[EMAIL PROTECTED]>.
*
 *
*
 * 5. Products derived from this software may not be called "Apache" nor may
*
 *    "Apache" appear in their names without prior written permission of the
*
 *    Apache Software Foundation.
*
 *
*
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES
*
 * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY
*
 * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL
*
 * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY
*
 * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL
*
 * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS
*
 * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION)
*
 * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT,
*
 * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*
 * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE
*
 * POSSIBILITY OF SUCH DAMAGE.
*
 *
*
 * =========================================================================
*
 *
*
 * This software  consists of voluntary  contributions made  by many indivi-
*
 * duals on behalf of the  Apache Software Foundation.  For more information
*
 * on the Apache Software Foundation, please see <http://www.apache.org/>.
*
 *
*
 * =========================================================================
*/

/***************************************************************************
 * Description: Utilities to to keep track of request information          *
 * Author:      Steven Velez <[EMAIL PROTECTED]>                        *

 * Version:     $Revision:     $                                           *
 
***************************************************************************/


#ifndef REQ_INFO_H
#define REQ_INFO_H

#include "jk_pool.h"
#include "jk_logger.h"

#ifdef __cpluplus
extern "C"
{
#endif

/*
 * The information 'class' that will store information
 * for a particular request.  This information will be set in the filter
 * and read in the extension.
 */
struct _request_information
{
    /* The name of the worker selected by the filter.
     * Relaces "TOMCATWORKER:" */
    char *worker_name;
    /* The uri of the original request.
     * Replaces "TOMCATURI:" */
        char *uri;
    /* The query string of the original request.  
     * Replaces "TOMCATQUERY:" */
        char *query_string;

    /** For keeping track of the various allocations of member data */
    jk_pool_t p;
    jk_pool_atom_t buff[BIG_POOL_SIZE];
};
typedef struct _request_information request_information_t;
typedef unsigned long request_info_name_t;

#define REQUEST_INFO_ERR_NAME (0)

/* Management functions to intialize and destroy a global request info map
*/
int rinfo_init_map(jk_logger_t *log);
int rinfo_close_map();

/* Insert a request information object in the map */
request_info_name_t rinfo_map_insert(request_information_t * ri);
/* Find the request information object related to the given request.
 * This function returns 'NULL' if the object can not be found */
request_information_t *rinfo_map_at(request_info_name_t req);
/* Find the requwst information object related to the give request.
 * This function will also remove the object from the map. */
request_information_t *rinfo_map_remove_at(request_info_name_t req);

/* utility function to append a request info name to a uri 
 * the return value of the function is a pointer to the caller-supplied
 * buffer */
char *rinfo_append_name_to_uri(char *uri, request_info_name_t req,
                                               char *buff, size_t size);
/* Utiltity function to retreive a request info name from 
 * a query string */
request_info_name_t rinfo_name_from_query(char *query);

/* Object lifetime management functions... these should be used to 
 * create and destroy a request_info object */
request_information_t *rinfo_new();
void rinfo_delete(request_information_t * ri);

/* functions to set data in the request info object.  These functions
 * duplicate the parameters, so it will remain the responsibility of
 * the caller to manage the memory pointed to in the second parameter. */
void rinfo_set_worker(request_information_t * ri, char *name);
void rinfo_set_uri(request_information_t * ri, char *uri);
void rinfo_set_query_string(request_information_t * ri, char *qs);

/* functions to access data in the request info object.
 * They return poitners to internal buffers, so callers should not
manipulate
 * them directly. */
char *rinfo_get_worker(request_information_t * ri);
char *rinfo_get_uri(request_information_t * ri);
char *rinfo_get_query_string(request_information_t * ri);

#ifdef __cplusplus
}
#endif
#endif





File: /home/cvspublic/jakarta-tomcat-connectors/jk/native/iis/req_info.c
/* =========================================================================
*
 *
*
 *                 The Apache Software License,  Version 1.1
*
 *
*
 *          Copyright (c) 1999-2001 The Apache Software Foundation.
*
 *                           All rights reserved.
*
 *
*
 * =========================================================================
*
 *
*
 * Redistribution and use in source and binary forms,  with or without modi-
*
 * fication, are permitted provided that the following conditions are met:
*
 *
*
 * 1. Redistributions of source code  must retain the above copyright notice
*
 *    notice, this list of conditions and the following disclaimer.
*
 *
*
 * 2. Redistributions  in binary  form  must  reproduce the  above copyright
*
 *    notice,  this list of conditions  and the following  disclaimer in the
*
 *    documentation and/or other materials provided with the distribution.
*
 *
*
 * 3. The end-user documentation  included with the redistribution,  if any,
*
 *    must include the following acknowlegement:
*
 *
*
 *       "This product includes  software developed  by the Apache  Software
*
 *        Foundation <http://www.apache.org/>."
*
 *
*
 *    Alternately, this acknowlegement may appear in the software itself, if
*
 *    and wherever such third-party acknowlegements normally appear.
*
 *
*
 * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software
*
 *    Foundation"  must not be used  to endorse or promote  products derived
*
 *    from this  software without  prior  written  permission.  For  written
*
 *    permission, please contact <[EMAIL PROTECTED]>.
*
 *
*
 * 5. Products derived from this software may not be called "Apache" nor may
*
 *    "Apache" appear in their names without prior written permission of the
*
 *    Apache Software Foundation.
*
 *
*
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES
*
 * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY
*
 * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL
*
 * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY
*
 * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL
*
 * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS
*
 * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION)
*
 * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT,
*
 * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*
 * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE
*
 * POSSIBILITY OF SUCH DAMAGE.
*
 *
*
 * =========================================================================
*
 *
*
 * This software  consists of voluntary  contributions made  by many indivi-
*
 * duals on behalf of the  Apache Software Foundation.  For more information
*
 * on the Apache Software Foundation, please see <http://www.apache.org/>.
*
 *
*
 * =========================================================================
*/

/***************************************************************************
 * Description: Utilities to to keep track of request information          *
 * Author:      Steven Velez <[EMAIL PROTECTED]>                        *

 * Version:     $Revision:     $                                           *
 
***************************************************************************/

#include "req_info.h"
#include "jk_mt.h"
#include "jk_util.h"

#include <limits.h>
#include <stddef.h>

/*
 * A node defination for a linked list
 * that will implement a custom map data structure.
 * I am using this as opposed to the jk_map because we need more
 * precise control of memory allocation for the sake of iffeciency since 
 * this will be used as a global structure.
 */
static struct _request_map_node
{
    request_info_name_t name;
    request_information_t *ri;
    struct _request_map_node *next;
};

/* use a define instead of a typedef so that this definition
 * will not be accessible outside this file */
#define NODE_T struct _request_map_node
/* The querystring variable that will hold a request_info_name */
#define QUERY_VAR "REQ_INFO_NAME"

#if defined(_DEBUG)
/* Helper macros for logging */
#define LOG_CRIT_SEC(action, result) {\
    if (!result) { \
        jk_log(logger, JK_LOG_INFO, "Did not " #action \
               " the critical section\n"); \
    } \
} \

#define LOG_ENTER(func_name) { \
    jk_log(logger, JK_LOG_DEBUG, "--> ENTERING " #func_name " <---\n");\
}\

#define LOG_EXIT(func_name) { \
    jk_log(logger, JK_LOG_DEBUG, "--> EXITING " #func_name " <---\n");\
}\

#else
#define LOG_CRIT_SEC(action, result) 
#define LOG_ENTER(func_name) 
#define LOG_EXIT(func_name) 
#endif


/* The root of the map */
static NODE_T *g_map_head = NULL;
/* The insertion point of the map */
static NODE_T *g_map_tail = NULL;
/* Synchronization structure */
static JK_CRIT_SEC g_crit_sec;
/* The next name value */
static request_info_name_t g_next_name = 0;
/* logging object */
jk_logger_t *logger = NULL;

int rinfo_init_map(jk_logger_t *l)
{
    int success = JK_FALSE;
    LOG_ENTER(rinfo_init_map);

    if (l == NULL) {
        LOG_EXIT(rinfo_init_map);
        return JK_FALSE;
    }
    logger = l;

    JK_INIT_CS(&g_crit_sec, success);
    if (success == JK_FALSE) {
        jk_log(logger, JK_LOG_ERROR, "Failed to initialize the map critical
"
               "section\n");
        LOG_EXIT(rinfo_init_map);
        return JK_FALSE;
    }

    g_map_head = NULL;
    g_map_tail = g_map_head;

    LOG_EXIT(rinfo_init_map);
    return JK_TRUE;
}


int rinfo_close_map()
{
    int success = JK_FALSE;
    NODE_T *pcurrent = g_map_head;
    NODE_T *ptemp = NULL;
    LOG_ENTER(rinfo_init_map);

    /* remove the current entries */
    JK_ENTER_CS(&g_crit_sec, success);
    if (success == JK_FALSE) {
            /* we are in big trouble; however, I guess a memory leak on
shutdown 
         * is better than a crash */
        jk_log(logger, JK_LOG_INFO, "Did not obtain a critical section
object "
               "for freeing map resources.\n");
        LOG_EXIT(rinfo_init_map);
            return JK_FALSE;
    }

    while (pcurrent != NULL) {
        rinfo_delete(pcurrent->ri);
        ptemp = pcurrent;
        pcurrent = pcurrent->next;

        if (ptemp != NULL) {
                free((void *) ptemp);
        }
    }

    g_map_head = NULL;
    g_map_tail = NULL;

    JK_LEAVE_CS(&g_crit_sec, success);
    LOG_CRIT_SEC(leave, success);

    /* get rid of the critical section */
    JK_DELETE_CS(&g_crit_sec, success);
    if (!success) {
        jk_log(logger, JK_LOG_INFO, "Failed to delete critical section
object "
               "after freeing map resources.\n");
    }

    LOG_EXIT(rinfo_init_map);
    return JK_TRUE;
}


request_info_name_t rinfo_map_insert(request_information_t * ri)
{
    int success = JK_FALSE;
    request_info_name_t new_name = REQUEST_INFO_ERR_NAME;
    NODE_T *new_node = NULL;
    LOG_ENTER(rinfo_map_insert);

    JK_ENTER_CS(&g_crit_sec, success);
    if (success == JK_FALSE) {
        LOG_CRIT_SEC(enter, success);
        LOG_EXIT(rinfo_map_insert);
        return REQUEST_INFO_ERR_NAME;
    }

    g_next_name = (++g_next_name) % ULONG_MAX;
    g_next_name = REQUEST_INFO_ERR_NAME == g_next_name ? 
                  g_next_name++ : g_next_name;
    new_name = g_next_name;

    new_node = (NODE_T *) malloc(sizeof(NODE_T));
    if (new_node == NULL) {
        jk_log(logger, JK_LOG_EMERG, "Failed to allocate memory for a "
               "new map entry\n");

        JK_LEAVE_CS(&g_crit_sec, success);
        LOG_CRIT_SEC(leave, success);

        LOG_EXIT(rinfo_map_insert);
        return REQUEST_INFO_ERR_NAME;
    }

    new_node->name = new_name;
    new_node->ri = ri;
    new_node->next = NULL;

    if (g_map_head == NULL) {
        g_map_head = new_node;
    }
    else {
        g_map_tail->next = new_node;
    }

    g_map_tail = new_node;

    jk_log(logger, JK_LOG_DEBUG, "Added req: %d\nhead = 0x%x tail = 0x%x\n",

           new_name, g_map_head, g_map_tail);
    JK_LEAVE_CS(&g_crit_sec, success);
    LOG_CRIT_SEC(leave, success);

    LOG_EXIT(rinfo_map_insert);
    return new_name;
}


/* centralize the retrieval of data */
static NODE_T **internal_map_at(request_info_name_t req)
{
    NODE_T **ppreturn = NULL;
    NODE_T **ppcurrent = &g_map_head;

    while (*ppcurrent) {
        if ((*ppcurrent)->name == req) {
            ppreturn = ppcurrent;
            break;
        }

        ppcurrent = &((*ppcurrent)->next);
    }

    if (!ppreturn) {
        jk_log(logger, JK_LOG_DEBUG, "Did not find info named: %d\n",
               req);
    }

    return ppreturn;
}


request_information_t *rinfo_map_at(request_info_name_t req)
{
    int success = JK_FALSE;
    NODE_T **ppresult = NULL;
    LOG_ENTER(rinfo_map_at);

    JK_ENTER_CS(&g_crit_sec, success);
    if (success == JK_FALSE) {
        LOG_CRIT_SEC(enter, success);
        LOG_EXIT(rinfo_map_at);
        return NULL;
    }

    ppresult = internal_map_at(req);

    JK_LEAVE_CS(&g_crit_sec, success);
    LOG_CRIT_SEC(leave, success);

    LOG_EXIT(rinfo_map_at);
    return ppresult ? (*ppresult)->ri : NULL;
}


request_information_t *rinfo_map_remove_at(request_info_name_t req)
{
    int success = JK_FALSE;
    NODE_T **ppresult = NULL;
    NODE_T *ptemp;
    request_information_t *preturn = NULL;
    LOG_ENTER(rinfo_map_remove_at);

    JK_ENTER_CS(&g_crit_sec, success);
    if (success == JK_FALSE) {
        LOG_CRIT_SEC(enter, success);
        LOG_EXIT(rinfo_map_remove_at);
        return NULL;
    }

    ppresult = internal_map_at(req);
    if (ppresult) {
       jk_log(logger, JK_LOG_DEBUG, "Removing request: %d\nhead = 0x%x tail
= 0x%x\n", 
              req, g_map_head, g_map_tail);

        preturn = (*ppresult)->ri;
        
        /*
         * This removal part is a little tricky, so here I try to explain
it.
         * If someone finds out that it's not doing what it's supposed to,
         * then keep these notes in mind.
         *
         * What we are getting from the search function is not a
         * pointer to a node, but instead a pointer to a pointer to a node.
         * The reasoning for this return value is so that the node can be
         * removed without having to return two pointers:  a pointer to the
         * found node and a pointer to the node before that.  In my opinion,
         * this allows for a more graceful implementation... even though the
         * pointer stuff is a little hard to manage.
         *
         * So, it's established that we have a pointer to a pointer.
         * To remove the node, we first need to create a temporary reference
to
         * it. A simple pointer will do here.  We just don't want to lose a
         * handle on the node.  Once we have safely stored a reference to
the
         * node, we check to see if the found node is the last node in list.
         * If it is, then we check for the special case: that there is a 
         * one-element list. The tail pointer is zeroed.  In the more
general
         * case (the list is two or more nodes long), we need to back the 
         * tail up.  Since what we have is a pointer to a pointer to a node,
         * we can't just assign the value of ppresult to the tail.  We need
to
         * find the memory location of the node that contains the "next" 
         * pointer that ppresult is pointing to.  We use the the offsetof
         * macro to find out how far back from the next pointer the node 
         * pointer needs to be. Then we calculate the location of the node
         * pointer based on the location of the next pointer.  This should 
         * be safe because the search function can only return a pointer to 
         * head or to a next field (which is in a node) and we already
checked
         * for the first case.
         *
         * Once we deal with the tail, the rest just falls out.  The value
         * of the pointer that ppresult points to (be it head or next
field),
         * is reassigned to point to the next node in the list.
         *
         * The node is then deleted.
         */
        ptemp = *ppresult;
        if (ptemp == g_map_tail) {
            if (g_map_tail == g_map_head) {
                g_map_tail = NULL;
            } 
            else {
                g_map_tail = (NODE_T *)(
                    ((jk_uintptr_t)(ppresult)) - offsetof(NODE_T, next));
            }
        }

        *ppresult = (*ppresult)->next;

        free((void *) ptemp);

       jk_log(logger, JK_LOG_DEBUG, "Removed request: %d\nhead = 0x%x tail =
0x%x\n", req, 
              g_map_head, g_map_tail);
    }

    JK_LEAVE_CS(&g_crit_sec, success);
    LOG_CRIT_SEC(leave, success);

    LOG_EXIT(rinfo_map_remove_at);
    return preturn;
}


char *rinfo_append_name_to_uri(char *uri, request_info_name_t req,
                                               char *buff, size_t size)
{
        char sep = '?';
    LOG_ENTER(rinfo_append_name_to_uri);

        if (buff == NULL) {
        LOG_EXIT(rinfo_append_name_to_uri);
        return NULL;
        }

        if (strchr(uri, sep)) {
        sep = '&';
        }

        snprintf(buff, size, "%s%c" QUERY_VAR "=%d", uri, sep, req);

    LOG_EXIT(rinfo_append_name_to_uri);
        return buff;
}


request_info_name_t rinfo_name_from_query(char *query)
{
    int numconverted = 0;
    request_info_name_t name = REQUEST_INFO_ERR_NAME;
    LOG_ENTER(rinfo_name_from_query);

    query = strstr(query, QUERY_VAR);
    if (!query) {
        jk_log(logger, JK_LOG_ERROR, "Did not find the variable \""
            QUERY_VAR "\" in the query string.\n");
        LOG_EXIT(rinfo_name_from_query);
        return REQUEST_INFO_ERR_NAME;
    }

    if (sscanf(query, QUERY_VAR "=%d", &name) != 1) {
        jk_log(logger, JK_LOG_ERROR, "Query string could not be scanned "
               "for a name.\n");
        LOG_EXIT(rinfo_name_from_query);
        return REQUEST_INFO_ERR_NAME;
    }

    LOG_EXIT(rinfo_name_from_query);
    return name;
}


/* Create a new request info object */
request_information_t *rinfo_new()
{
    request_information_t *pinfo =
        (request_information_t *) malloc(sizeof(request_information_t));
    LOG_ENTER(rinfo_new);

    if (pinfo == NULL) {
        jk_log(logger, JK_LOG_EMERG, "Failed to allocate memory for a "
               "new request information object.\n");
        LOG_EXIT(rinfo_new);
        return NULL;
    }

    memset((void *) pinfo, 0, sizeof(request_information_t));
    jk_open_pool(&pinfo->p, pinfo->buff, sizeof(pinfo->buff));

    LOG_EXIT(rinfo_new);
    return pinfo;
}


/* destroy a request info object */
void rinfo_delete(request_information_t * ri)
{
    LOG_ENTER(rinfo_delete);

    if (ri == NULL) {
        LOG_EXIT(rinfo_delete);
        return;
    }

    jk_close_pool(&ri->p);
    free((void *) ri);

    /* This is not sufficient, caller must do this too */
    ri = NULL;

    LOG_EXIT(rinfo_delete);
}


/* helper to set string memebers */
static internal_set_string(request_information_t * ri, char **member,
                           char *value)
{
    if (value) {
        *member = jk_pool_strdup(&ri->p, value);
    }
    else {
        *member = NULL;
    }
}

void rinfo_set_worker(request_information_t * ri, char *name)
{
    LOG_ENTER(rinfo_set_worker);

    /* protection */
    if (ri == NULL) {
        LOG_EXIT(rinfo_set_worker);
        return;
    }

    internal_set_string(ri, &(ri->worker_name), name);

    LOG_EXIT(rinfo_set_worker);
}


void rinfo_set_uri(request_information_t * ri, char *uri)
{
    LOG_ENTER(rinfo_set_uri);

    /* protection */
    if (ri == NULL) {
        LOG_EXIT(rinfo_set_uri);
        return;
    }

    internal_set_string(ri, &(ri->uri), uri);

    LOG_EXIT(rinfo_set_uri);
}


void rinfo_set_query_string(request_information_t * ri, char *qs)
{
    LOG_ENTER(rinfo_set_query_string);

    /* protection */
    if (ri == NULL) {
        LOG_EXIT(rinfo_set_query_string);
        return;
    }

    internal_set_string(ri, &(ri->query_string), qs);

    LOG_EXIT(rinfo_set_query_string);
}


char *rinfo_get_worker(request_information_t * ri)
{
    LOG_ENTER(rinfo_get_worker);

    if (ri == NULL) {
        LOG_EXIT(rinfo_get_worker);
        return NULL;
    }

    jk_log(logger, JK_LOG_DEBUG, "Retreived: %s\n", ri->worker_name);
    LOG_EXIT(rinfo_get_worker);
    return ri->worker_name;
}


char *rinfo_get_uri(request_information_t * ri)
{
    LOG_ENTER(rinfo_get_uri);

    if (ri == NULL) {
        LOG_EXIT(rinfo_get_uri);
        return NULL;
    }

    jk_log(logger, JK_LOG_DEBUG, "Retreived: %s\n", ri->uri);
    LOG_EXIT(rinfo_get_uri);
    return ri->uri;
}


char *rinfo_get_query_string(request_information_t * ri)
{
    LOG_ENTER(rinfo_get_query_string);

    if (ri == NULL) {
        LOG_EXIT(rinfo_get_query_string);
        return NULL;
    }

    jk_log(logger, JK_LOG_DEBUG, "Retreived: %s\n", ri->query_string);
    LOG_EXIT(rinfo_get_query_string);
    return ri->query_string;
}




----------------------------
  .-.    | Steven Velez
  oo|    | Software Engineer
 /`'\    | alventive
(\_;/)   | 678-202-2226






-----Original Message-----
From: Steven Velez [mailto:svelez@;alventive.com]
Sent: Tuesday, November 12, 2002 12:15 PM
To: 'Tomcat Developers List'
Subject: RE: [PATCH] Fixing Interoperability problem in iis connector


:( My mail client warpped the code inappropriately.. I will remedy this and
re-post.

Thanks,
Steven

----------------------------
  .-.    | Steven Velez
  oo|    | Software Engineer
 /`'\    | alventive
(\_;/)   | 678-202-2226



-----Original Message-----
From: Steven Velez [mailto:svelez@;alventive.com]
Sent: Tuesday, November 12, 2002 12:15 PM
To: 'Tomcat Developers List'
Subject: RE: [PATCH] Fixing Interoperability problem in iis connector


:( My mail client warpped the code inappropriately.. I will remedy this and
re-post.

Thanks,
Steven

Reply via email to