You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by da...@apache.org on 2009/12/17 19:20:09 UTC

svn commit: r891819 - /webservices/axis2/trunk/c/src/core/transport/http/sender/http_sender.c

Author: damitha
Date: Thu Dec 17 18:20:08 2009
New Revision: 891819

URL: http://svn.apache.org/viewvc?rev=891819&view=rev
Log:
Keep alive implementation memory leak fix and removing code redundancy by abstracting into functions

Modified:
    webservices/axis2/trunk/c/src/core/transport/http/sender/http_sender.c

Modified: webservices/axis2/trunk/c/src/core/transport/http/sender/http_sender.c
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/c/src/core/transport/http/sender/http_sender.c?rev=891819&r1=891818&r2=891819&view=diff
==============================================================================
--- webservices/axis2/trunk/c/src/core/transport/http/sender/http_sender.c (original)
+++ webservices/axis2/trunk/c/src/core/transport/http/sender/http_sender.c Thu Dec 17 18:20:08 2009
@@ -54,6 +54,12 @@
     axis2_bool_t keep_alive;
 };
 
+typedef struct axis2_http_connection_struct
+{
+    axutil_array_list_t *closed_list;
+    axis2_http_client_t *http_client;
+} axis2_http_connection_struct_t;
+
 #ifndef AXIS2_LIBCURL_ENABLED
 static void
 axis2_http_sender_add_header_list(
@@ -137,7 +143,32 @@
     axis2_http_simple_request_t * request,
     axis2_char_t * header_data);
 
-static void AXIS2_CALL
+static axutil_hash_t *
+axis2_http_sender_connection_map_create(
+    const axutil_env_t *env,
+    axis2_msg_ctx_t *msg_ctx);
+
+static void
+axis2_http_sender_connection_map_add_to_closed_list(
+        axutil_hash_t *connection_map,
+        const axutil_env_t *env,
+        axis2_msg_ctx_t *msg_ctx,
+        axis2_http_client_t *http_client);
+
+static void
+axis2_http_sender_connection_map_add(
+        axutil_hash_t *connection_map,
+        const axutil_env_t *env,
+        axis2_msg_ctx_t *msg_ctx,
+        axis2_http_client_t *http_client);
+
+static axis2_http_client_t *
+axis2_http_sender_connection_map_get(
+        axutil_hash_t *connection_map, 
+        const axutil_env_t *env,
+        axis2_msg_ctx_t *msg_ctx);
+
+static void 
 axis2_http_sender_connection_map_free(
     void *cm_void,
     const axutil_env_t *env);
@@ -364,21 +395,20 @@
     if(sender->keep_alive && !axis2_msg_ctx_get_server_side(msg_ctx, env))
     {
         axutil_property_t *connection_map_property = NULL;
-        axis2_endpoint_ref_t *endpoint = NULL;
 
         connection_map_property = axis2_conf_ctx_get_property(conf_ctx, env, 
                 AXIS2_HTTP_CONNECTION_MAP);
         if(!connection_map_property)
         {
-            connection_map = axutil_hash_make(env);
+            connection_map = axis2_http_sender_connection_map_create(env, msg_ctx);
             if(!connection_map)
             {
                 AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
                 return AXIS2_FAILURE;
             }
-            connection_map_property = axutil_property_create_with_args(env, 
-                AXIS2_SCOPE_SESSION, 1, axis2_http_sender_connection_map_free, 
-                connection_map);
+            
+            connection_map_property = axutil_property_create_with_args(env, AXIS2_SCOPE_SESSION, 
+                AXIS2_TRUE, axis2_http_sender_connection_map_free, connection_map);
             axis2_conf_ctx_set_property(conf_ctx, env, AXIS2_HTTP_CONNECTION_MAP, 
                 connection_map_property);
 
@@ -388,29 +418,7 @@
             connection_map = axutil_property_get_value(connection_map_property, env);
             if(connection_map)
             {
-                endpoint = axis2_msg_ctx_get_to(msg_ctx, env);
-                if(endpoint)
-                {
-                    const axis2_char_t *address = NULL;
-
-                    address = axis2_endpoint_ref_get_address(endpoint, env);
-                    if(address)
-                    {
-                        axutil_url_t *url = NULL;
-                        url = axutil_url_parse_string(env, address);
-                        if(url)
-                        {
-                            axis2_char_t *server = axutil_url_get_server(url, env);
-                            if(server)
-                            {
-                                /* We reuse this http client */
-                                sender->client = axutil_hash_get(connection_map, server, 
-                                    AXIS2_HASH_KEY_STRING);
-                            }
-                            axutil_url_free(url, env);
-                        }
-                    }
-                }
+                sender->client = axis2_http_sender_connection_map_get(connection_map, env, msg_ctx);
             }
         }
         if(!axutil_strcasecmp(sender->http_version, AXIS2_HTTP_HEADER_PROTOCOL_10))
@@ -427,7 +435,6 @@
         AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "sender->client creation failed for url %s", url);
         return AXIS2_FAILURE;
     }
-
     /* configure proxy settings if we have set so
      */
 
@@ -1453,10 +1460,15 @@
                 axutil_property_t *connection_map_property = NULL;
                 axutil_hash_t *connection_map = NULL;
                 axis2_conf_ctx_t *conf_ctx = NULL;
-
                 connection_header_present = AXIS2_TRUE;
                 connection_header_value = axis2_http_header_get_value(header, env);
                 conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env);
+                /** 
+                 * Put the http client into message context. Is this neccessary?
+                 */
+                property = axutil_property_create_with_args(env, AXIS2_SCOPE_REQUEST, 
+                        AXIS2_FALSE, axis2_http_client_free_void_arg, sender->client);
+                axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_HTTP_CLIENT, property);
                 connection_map_property = axis2_conf_ctx_get_property(conf_ctx, env, 
                     AXIS2_HTTP_CONNECTION_MAP);
 
@@ -1469,85 +1481,21 @@
                  */
                 if(connection_header_value && !axutil_strcasecmp(connection_header_value, "close"))
                 {
-                    axis2_endpoint_ref_t *endpoint = NULL;
                     if(connection_map)
                     {
-                        endpoint = axis2_msg_ctx_get_to(msg_ctx, env);
-                        if(endpoint)
-                        {
-                            const axis2_char_t *address = NULL;
-                            address = axis2_endpoint_ref_get_address(endpoint, env);
-                            if(address)
-                            {
-                                axutil_url_t *url = NULL;
-                                url = axutil_url_parse_string(env, address);
-                                if(url)
-                                {
-                                    axis2_char_t *server = NULL;
-                                    server = axutil_url_get_server(url, env);
-                                    if(server)
-                                    {
-                                        axis2_http_client_t *http_client = NULL;
-                                        /* We remove any connection set for this endpoint */
-                                        http_client = axutil_hash_get(connection_map, server, 
-                                            AXIS2_HASH_KEY_STRING);
-                                        if(http_client)
-                                        {
-                                            /* Dont' free http client here. It is freed by 
-                                             * op_client 
-                                             */
-                                            axutil_hash_set(connection_map, server, 
-                                                AXIS2_HASH_KEY_STRING, NULL);
-                                        }
-                                    }
-                                    axutil_url_free(url, env);
-                                }
-                            }
-                        } /* End if endpoint */
-                    } /* End if connection_map */
-                } /* End if connection header has value close */
-                else if(connection_header_value && !axutil_strcasecmp(connection_header_value, "Keep-Alive"))
-                {
-                    /* We add the connection to connection map for reuse */
-                    axis2_endpoint_ref_t *endpoint = NULL;
-                    endpoint = axis2_msg_ctx_get_to(msg_ctx, env);
-                    if(endpoint)
-                    {
-                        const axis2_char_t *address = NULL;
-                        address = axis2_endpoint_ref_get_address(endpoint, env);
-                        if(address)
-                        {
-                            axutil_url_t *url = NULL;
-                            url = axutil_url_parse_string(env, address);
-                            if(url)
-                            {
-                                axis2_char_t *server = NULL;
-                                server = axutil_url_get_server(url, env);
-                                if(server)
-                                {
-                                    /** 
-                                     * We put the http client into message context so that we 
-                                     * can free it once the processing is done at client side.
-                                     */
-                                    property = axutil_property_create_with_args(env, 
-                                        AXIS2_SCOPE_REQUEST, 0, axis2_http_client_free_void_arg, 
-                                        sender->client);
-                                    axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_HTTP_CLIENT, 
-                                            property);
-                                    /**
-                                     * If keep alive enabled we store the http client for reuse.
-                                     */
-                                    if(connection_map)
-                                    {
-                                        axutil_hash_set(connection_map, axutil_strdup(env, 
-                                            server), AXIS2_HASH_KEY_STRING, sender->client);
-                                    }
-                                }
-                                axutil_url_free(url, env);
-                            } /* end if url */
-                        } /* end if address */
-                    } /* end if endpoint */
-                } /* End if connection header is Keep-Alive */
+                        axis2_http_sender_connection_map_add_to_closed_list(connection_map, env, 
+                                msg_ctx, sender->client);
+                    } 
+                } 
+                else if(connection_header_value && !axutil_strcasecmp(connection_header_value, 
+                            "Keep-Alive"))
+                {
+                    if(connection_map)
+                    {
+                        axis2_http_sender_connection_map_add(connection_map, env, 
+                            msg_ctx, sender->client);    
+                    }
+                } 
             } /* End if name is connection */
         } /* End if name of the header present */
     }
@@ -1564,6 +1512,14 @@
         axutil_hash_t *connection_map = NULL;
         axis2_conf_ctx_t *conf_ctx = NULL;
         conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env);
+
+        /** 
+         * We put the http client into message context so that we can free it once the 
+         * processing is done at client side.
+         */
+        property = axutil_property_create_with_args(env, AXIS2_SCOPE_REQUEST, AXIS2_FALSE, 
+                axis2_http_client_free_void_arg, sender->client);
+        axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_HTTP_CLIENT, property);
         connection_map_property = axis2_conf_ctx_get_property(conf_ctx, env, 
                 AXIS2_HTTP_CONNECTION_MAP);
         if(connection_map_property)
@@ -1574,80 +1530,20 @@
         {
             if(connection_map)
             {
-                axis2_endpoint_ref_t *endpoint = NULL;
-                endpoint = axis2_msg_ctx_get_to(msg_ctx, env);
-                if(endpoint)
-                {
-                    const axis2_char_t *address = NULL;
-                    address = axis2_endpoint_ref_get_address(endpoint, env);
-                    if(address)
-                    {
-                        axutil_url_t *url =  NULL;
-                        url = axutil_url_parse_string(env, address);
-                        if(url)
-                        {
-                            axis2_char_t *server = NULL;
-                            server = axutil_url_get_server(url, env);
-                            if(server)
-                            {
-                                axis2_http_client_t *http_client = NULL;
-                                /* We remove any connection set for this endpoint */
-                                http_client = axutil_hash_get(connection_map, server, 
-                                        AXIS2_HASH_KEY_STRING);
-                                if(http_client)
-                                {
-                                    /* Dont' free http client here. It is freed by op_client */
-                                    axutil_hash_set(connection_map, axutil_strdup(env, server),
-                                            AXIS2_HASH_KEY_STRING, NULL);
-                                }
-                            }
-                            axutil_url_free(url, env);
-                        }
-                    } /* end if address */
-                } /* end if endpoint */
+                axis2_http_sender_connection_map_add_to_closed_list(connection_map, env, msg_ctx, 
+                        sender->client);
             }
         } /* End if http version 1.0 */
         else if(!axutil_strcasecmp(sender->http_version, AXIS2_HTTP_HEADER_PROTOCOL_11))
         {
-            /* We add the connection to connection map for reuse */
-            axis2_endpoint_ref_t *endpoint = NULL;
-            endpoint = axis2_msg_ctx_get_to(msg_ctx, env);
-            if(endpoint)
-            {
-                const axis2_char_t *address = NULL;
-                address = axis2_endpoint_ref_get_address(endpoint, env);
-                if(address)
-                {
-                    axutil_url_t *url = NULL;
-                    url = axutil_url_parse_string(env, address);
-                    if(url)
-                    {
-                        axis2_char_t *server = NULL;
-                        server = axutil_url_get_server(url, env);
-                        if(server)
-                        {
-                            /** 
-                             * We put the http client into message context so that we 
-                             * can free it once the processing is done at client side.
-                             */
-                            property = axutil_property_create_with_args(env, 
-                                AXIS2_SCOPE_REQUEST, 0, axis2_http_client_free_void_arg, 
-                                sender->client);
-                            axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_HTTP_CLIENT, 
-                                    property);
-                            /**
-                             * If keep alive enabled we store the http client for reuse.
-                             */
-                            if(connection_map)
-                            {
-                                axutil_hash_set(connection_map, axutil_strdup(env, 
-                                    server), AXIS2_HASH_KEY_STRING, sender->client);
-                            }
-                        }
-                        axutil_url_free(url, env);
-                    } /* end if url */
-                } /* end if address */
-            } /* end if endpoint */
+            /**
+             * If keep alive enabled we store the http client for reuse.
+             */
+            if(connection_map)
+            {
+                axis2_http_sender_connection_map_add(connection_map, env, msg_ctx, 
+                        sender->client);
+            }
         } /* End if http version 1.1 */
     } /* End if !connection_header_present */
 
@@ -3296,7 +3192,188 @@
     return sender->keep_alive;
 }
 
-static void AXIS2_CALL
+static axutil_hash_t *
+axis2_http_sender_connection_map_create(
+    const axutil_env_t *env,
+    axis2_msg_ctx_t *msg_ctx)
+{
+    axutil_hash_t *connection_map = NULL;
+    connection_map = axutil_hash_make(env);
+    if(!connection_map)
+    {
+        AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+    }
+    if(connection_map)
+    {
+        axis2_http_connection_struct_t *connections = NULL;
+        axis2_endpoint_ref_t *endpoint = NULL;
+        connections = AXIS2_MALLOC(env->allocator, sizeof(axis2_http_connection_struct_t));
+        if(connections)
+        {
+            connections->closed_list = axutil_array_list_create(env, 0);
+            if(!connections->closed_list)
+            {
+                if(connections->closed_list)
+                {
+                    axutil_array_list_free(connections->closed_list, env);
+                }
+                axutil_hash_free(connection_map, env);
+                connection_map = NULL;
+                AXIS2_FREE(env->allocator, connections);
+                connections = NULL;
+                AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+                return NULL;
+            }
+        }
+        else
+        {
+            axutil_hash_free(connection_map, env);
+            connection_map = NULL;
+            AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+            return NULL;
+        }
+        endpoint = axis2_msg_ctx_get_to(msg_ctx, env);
+        if(endpoint)
+        {
+            const axis2_char_t *address = NULL;
+            address = axis2_endpoint_ref_get_address(endpoint, env);
+            if(address)
+            {
+                axutil_url_t *url = NULL;
+                url = axutil_url_parse_string(env, address);
+                if(url)
+                {
+                    axis2_char_t *server = axutil_url_get_server(url, env);
+                    if(server)
+                    {
+                        AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "damserver:%s", server);
+                        axutil_hash_set(connection_map, axutil_strdup(env, server), 
+                                AXIS2_HASH_KEY_STRING, connections);
+                    }
+                    axutil_url_free(url, env);
+                }
+            }
+        }
+        else
+        {
+            axutil_hash_free(connection_map, env);
+            connection_map = NULL;
+        }
+    } /* end if connection_map */
+    return connection_map;
+}
+
+static void
+axis2_http_sender_connection_map_add_to_closed_list(
+        axutil_hash_t *connection_map,
+        const axutil_env_t *env,
+        axis2_msg_ctx_t *msg_ctx,
+        axis2_http_client_t *http_client)
+{
+    axis2_endpoint_ref_t *endpoint = NULL;
+    endpoint = axis2_msg_ctx_get_to(msg_ctx, env);
+    if(endpoint)
+    {
+        const axis2_char_t *address = NULL;
+        address = axis2_endpoint_ref_get_address(endpoint, env);
+        if(address)
+        {
+            axutil_url_t *url = NULL;
+            url = axutil_url_parse_string(env, address);
+            if(url)
+            {
+                axis2_char_t *server = axutil_url_get_server(url, env);
+                if(server)
+                {
+                    axis2_http_connection_struct_t *connections = NULL;
+                    connections = axutil_hash_get(connection_map, server, 
+                        AXIS2_HASH_KEY_STRING);
+                    if(connections)
+                    {
+                        connections->http_client = NULL;
+                        axutil_array_list_add(connections->closed_list, env, http_client);
+                    }
+                }
+                axutil_url_free(url, env);
+            }
+        }
+    }
+}
+
+static void
+axis2_http_sender_connection_map_add(
+        axutil_hash_t *connection_map,
+        const axutil_env_t *env,
+        axis2_msg_ctx_t *msg_ctx,
+        axis2_http_client_t *http_client)
+{
+    axis2_endpoint_ref_t *endpoint = NULL;
+    endpoint = axis2_msg_ctx_get_to(msg_ctx, env);
+    if(endpoint)
+    {
+        const axis2_char_t *address = NULL;
+        address = axis2_endpoint_ref_get_address(endpoint, env);
+        if(address)
+        {
+            axutil_url_t *url = NULL;
+            url = axutil_url_parse_string(env, address);
+            if(url)
+            {
+                axis2_char_t *server = axutil_url_get_server(url, env);
+                if(server)
+                {
+                    axis2_http_connection_struct_t *connections = NULL;
+                    connections = axutil_hash_get(connection_map, server, 
+                        AXIS2_HASH_KEY_STRING);
+                    if(connections)
+                    {
+                        connections->http_client = http_client;
+                    }
+                }
+                axutil_url_free(url, env);
+            }
+        }
+    }
+}
+
+static axis2_http_client_t *
+axis2_http_sender_connection_map_get(
+        axutil_hash_t *connection_map, 
+        const axutil_env_t *env,
+        axis2_msg_ctx_t *msg_ctx)
+{
+    axis2_http_client_t *http_client = NULL;
+    axis2_endpoint_ref_t *endpoint = NULL;
+    endpoint = axis2_msg_ctx_get_to(msg_ctx, env);
+    if(endpoint)
+    {
+        const axis2_char_t *address = NULL;
+        address = axis2_endpoint_ref_get_address(endpoint, env);
+        if(address)
+        {
+            axutil_url_t *url = NULL;
+            url = axutil_url_parse_string(env, address);
+            if(url)
+            {
+                axis2_char_t *server = axutil_url_get_server(url, env);
+                if(server)
+                {
+                    axis2_http_connection_struct_t *connections = NULL;
+                    connections = axutil_hash_get(connection_map, server, 
+                        AXIS2_HASH_KEY_STRING);
+                    if(connections)
+                    {
+                        http_client = connections->http_client;
+                    }
+                }
+                axutil_url_free(url, env);
+            }
+        }
+    }
+    return http_client;
+}
+
+static void 
 axis2_http_sender_connection_map_free(
     void *cm_void,
     const axutil_env_t *env)
@@ -3309,7 +3386,7 @@
     for(hi = axutil_hash_first(ht, env); hi; hi = axutil_hash_next(env, hi))
     {
         axis2_char_t *name = NULL;
-        void *value = NULL;
+        axis2_http_connection_struct_t *value = NULL;
 
         axutil_hash_this(hi, &key, NULL, &val);
         name = (axis2_char_t *) key;
@@ -3317,10 +3394,27 @@
         {
             AXIS2_FREE(env->allocator, name);
         }
-        value = (axis2_http_client_t *) val;
+        value = (axis2_http_connection_struct_t *) val;
         if(value)
         {
-            axis2_http_client_free(value, env);
+            int i = 0, size = 0;
+            size = axutil_array_list_size(value->closed_list, env);
+            for(i = 0; i < size; i++)
+            {
+                axis2_http_client_t *http_client = NULL;
+                http_client = (axis2_http_client_t *) axutil_array_list_get(value->closed_list, env, 
+                        i);
+                if(http_client)
+                {
+                    axis2_http_client_free(http_client, env);
+                }
+            }
+            axutil_array_list_free(value->closed_list, env);
+            if(value->http_client)
+            {
+                axis2_http_client_free(value->http_client, env);
+            }
+            AXIS2_FREE(env->allocator, value);
         }
     }
     axutil_hash_free(ht, env);