After writing Axis2/C with cbthead post , I was so curious to test same code with pthreads. As a result I came up with this modified echo sample which uses same svc client and environment among all threads. One thing to note is with cbthread, program worked well with 100,000 threads whereas with pthreads, it went out of memory around 370 threads. However pthreads is more portable, well tested and widespread thread library therefore it is more likely to use Axis2/C with pthreads. echo.c and Makefile can be obtained from here [1].
1. http://www.cs.utk.edu/~dpremala/pthread/
echo.c
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 <stdio.h> #include <stdlib.h> #include <axiom.h> #include <axis2_util.h> #include <axiom_soap.h> #include <axis2_client.h> #include <pthread.h> #define NTHREADS 10 axiom_node_t * build_om_payload_for_echo_svc(const axutil_env_t * env); typedef struct _ginfo{ pthread_mutex_t *lock; }ginfo_t; typedef struct _svcinfo { pthread_t pid; const axutil_env_t *env; axis2_svc_client_t *svc_client; }svc_info_t; svc_info_t **pthreads; ginfo_t *ginfo; static void svc_client_send_request (void *v); static void svc_client_finish_request (void *v); int main(int argc, char **argv) { const axutil_env_t *env = NULL; const axis2_char_t *address = NULL; axis2_endpoint_ref_t *endpoint_ref = NULL; axis2_options_t *options = NULL; const axis2_char_t *client_home = NULL; axis2_svc_client_t *svc_client = NULL; int i = 0; /* Set up the environment */ env = axutil_env_create_all("echo.log", AXIS2_LOG_LEVEL_TRACE); /* Set end point reference of echo service */ address = "http://localhost:9090/axis2/services/echo"; if (argc > 1) { if (axutil_strcmp(argv[1], "-h") == 0) { printf("Usage : %s [endpoint_url]\n", argv[0]); printf("use -h for help\n"); return 0; } else { address = argv[1]; } } printf("Using endpoint : %s\n", address); /* Create EPR with given address */ endpoint_ref = axis2_endpoint_ref_create(env, address); /* Setup options */ options = axis2_options_create(env); axis2_options_set_to(options, env, endpoint_ref); axis2_options_set_action(options, env, "http://ws.apache.org/axis2/c/samples/echoString"); /* Set up deploy folder. It is from the deploy folder, the configuration is picked up * using the axis2.xml file. * In this sample client_home points to the Axis2/C default deploy folder. The client_home can * be different from this folder on your system. For example, you may have a different folder * (say, my_client_folder) with its own axis2.xml file. my_client_folder/modules will have the * modules that the client uses */ client_home = AXIS2_GETENV("AXIS2C_HOME"); if (!client_home || !strcmp(client_home, "")) client_home = "../.."; /* Create service client */ svc_client = axis2_svc_client_create(env, client_home); if (!svc_client) { printf ("Error creating service client, Please check AXIS2C_HOME again\n"); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Stub invoke FAILED: Error code:" " %d :: %s", env->error->error_number, AXIS2_ERROR_GET_MESSAGE(env->error)); return -1; } /* Set service client options */ axis2_svc_client_set_options(svc_client, env, options); /* Engage addressing module */ axis2_svc_client_engage_module(svc_client, env, AXIS2_MODULE_ADDRESSING); pthreads = (svc_info_t **) malloc (sizeof (svc_info_t *) * NTHREADS); ginfo = (ginfo_t *) malloc (sizeof (ginfo_t)); if (!ginfo) { fprintf (stderr, "no enough memory\n"); exit (1); } ginfo->lock = (pthread_mutex_t *) malloc (sizeof (pthread_mutex_t)); if (!ginfo->lock) { fprintf (stderr, "no enough memory\n"); exit (1); } pthread_mutex_init (ginfo->lock, NULL); for (i = 0; i < NTHREADS; i++) { pthreads[i] = (svc_info_t *) malloc (sizeof (svc_info_t)); if (!pthreads[i]) { fprintf (stderr, "no enough memory\n"); exit (1); } pthreads[i]->env = env; pthreads[i]->svc_client = svc_client; if (pthread_create (&(pthreads[i]->pid), NULL, (void *)svc_client_send_request, (void *)pthreads[i])) { perror ("pthread creation"); exit (1); } } for (i = 0; i < NTHREADS; i++) { pthread_join (pthreads[i]->pid, NULL); } svc_client_finish_request ((void *)pthreads[0]); return 0; } /* build SOAP request message content using OM */ axiom_node_t * build_om_payload_for_echo_svc( const axutil_env_t * env) { axiom_node_t *echo_om_node = NULL; axiom_element_t *echo_om_ele = NULL; axiom_node_t *text_om_node = NULL; axiom_element_t *text_om_ele = NULL; axiom_namespace_t *ns1 = NULL; axis2_char_t *om_str = NULL; ns1 = axiom_namespace_create(env, "http://ws.apache.org/axis2/services/echo", "ns1"); echo_om_ele = axiom_element_create(env, NULL, "echoString", ns1, &echo_om_node); text_om_ele = axiom_element_create(env, echo_om_node, "text", NULL, &text_om_node); axiom_element_set_text(text_om_ele, env, "Hello World!", text_om_node); om_str = axiom_node_to_string(echo_om_node, env); if (om_str) { printf("\nSending OM : %s\n", om_str); AXIS2_FREE(env->allocator, om_str); om_str = NULL; } return echo_om_node; } static void svc_client_send_request (void *v) { svc_info_t *svcinfo; const axutil_env_t *env; axis2_svc_client_t *svc_client; axiom_node_t *payload = NULL; axiom_node_t *ret_node; svcinfo = (svc_info_t *)v; pthread_mutex_lock (ginfo->lock); env = svcinfo->env; svc_client = svcinfo->svc_client; /* Build the SOAP request message payload using OM API. */ payload = build_om_payload_for_echo_svc(env); /* Send request */ ret_node = axis2_svc_client_send_receive(svc_client, env, payload); if (ret_node) { axis2_char_t *om_str = NULL; om_str = axiom_node_to_string(ret_node, env); if (om_str) printf("\nReceived OM : %s\n", om_str); printf("\necho client invoke SUCCESSFUL!\n"); AXIS2_FREE(env->allocator, om_str); ret_node = NULL; } else { AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Stub invoke FAILED: Error code:" " %d :: %s", env->error->error_number, AXIS2_ERROR_GET_MESSAGE(env->error)); printf("echo client invoke FAILED!\n"); } pthread_mutex_unlock (ginfo->lock); } static void svc_client_finish_request (void *v) { svc_info_t *svcinfo; int i = 0; svcinfo = pthreads[0]; if (svcinfo->svc_client) { axis2_svc_client_free(svcinfo->svc_client, svcinfo->env); svcinfo->svc_client = NULL; } if (svcinfo->env) { axutil_env_free((axutil_env_t *) svcinfo->env); svcinfo->env = NULL; } for (i = 0; i < NTHREADS; i++) { free (pthreads[i]); } free (pthreads); pthread_mutex_destroy (ginfo->lock); free (ginfo); printf ("All threads finished \n"); }










