From 3e4eb0a22404d1c35da33bef70d99546c7e47a9e Mon Sep 17 00:00:00 2001 From: edgrif <edgrif> Date: Mon, 22 Mar 2004 13:35:14 +0000 Subject: [PATCH] Add code to call the global init function for each server protocol. Since these functions must usually only be called once this is all done via a mutex protected list. --- src/zmapThreads/zmapSlave.c | 108 ++++++++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 4 deletions(-) diff --git a/src/zmapThreads/zmapSlave.c b/src/zmapThreads/zmapSlave.c index b3665b7b8..e468226af 100755 --- a/src/zmapThreads/zmapSlave.c +++ b/src/zmapThreads/zmapSlave.c @@ -26,15 +26,18 @@ * Description: * Exported functions: See XXXXXXXXXXXXX.h * HISTORY: - * Last edited: Mar 11 15:56 2004 (edgrif) + * Last edited: Mar 22 13:10 2004 (edgrif) * Created: Thu Jul 24 14:37:26 2003 (edgrif) - * CVS info: $Id: zmapSlave.c,v 1.3 2004-03-12 15:59:27 edgrif Exp $ + * CVS info: $Id: zmapSlave.c,v 1.4 2004-03-22 13:35:14 edgrif Exp $ *------------------------------------------------------------------- */ /* With some additional calls in the zmapConn code I could get rid of the need for * the private header here...... */ +#include <strings.h> +#include <pthread.h> +#include <ZMap/zmapUtils.h> #include <zmapConn_P.h> #include <ZMap/zmapServer.h> #include <zmapSlave_P.h> @@ -44,8 +47,35 @@ enum {ZMAP_SLAVE_REQ_BUFSIZE = 512} ; +/* Some protocols have global init/cleanup functions that must only be called once, this type/list + * allows us to do this. */ +typedef struct +{ + char *protocol ; + gboolean init_called ; + void *global_init_data ; + gboolean cleanup_called ; +} ZMapProtocolInitStruct, *ZMapProtocolInit ; + +typedef struct +{ + pthread_mutex_t mutex ; /* Protects access to init/cleanup list. */ + GList *protocol_list ; /* init/cleanup list. */ +} ZMapProtocolInitListStruct, *ZMapProtocolInitList ; + + + static void cleanUpThread(void *thread_args) ; +static void protocolGlobalInitFunc(ZMapProtocolInitList protocols, char *protocol, + void **global_init_data) ; +static int findProtocol(gconstpointer list_protocol, gconstpointer protocol) ; + + + +/* Set up the list, note the special pthread macro that makes sure mutex is set up before + * any threads can use it. */ +static ZMapProtocolInitListStruct protocol_init_G = {PTHREAD_MUTEX_INITIALIZER, NULL} ; @@ -61,6 +91,7 @@ static void cleanUpThread(void *thread_args) ; void *zmapNewThread(void *thread_args) { zmapThreadCB thread_cb ; + void *global_init_data ; ZMapConnection connection = (ZMapConnection)thread_args ; ZMapRequest thread_state = &(connection->request) ; int status ; @@ -84,7 +115,15 @@ void *zmapNewThread(void *thread_args) * cleanup routine is called. */ pthread_cleanup_push(cleanUpThread, (void *)thread_cb) ; - if (!zMapServerCreateConnection(&(thread_cb->server), connection->machine, connection->port, + + /* Check if we need to call the global init function of the protocol, this is a + * function that should only be called once. */ + protocolGlobalInitFunc(&protocol_init_G, connection->protocol, &global_init_data) ; + + + /* Create the connection block for this specific server connection. */ + if (!zMapServerCreateConnection(&(thread_cb->server), global_init_data, + connection->machine, connection->port, connection->protocol, "any", "any")) { thread_cb->thread_died = TRUE ; @@ -137,6 +176,7 @@ void *zmapNewThread(void *thread_args) { static int failure = 0 ; char *server_command ; + int reply_len = 0 ; /* Is it an error to not have a sequence ????? */ if (!sequence) @@ -148,7 +188,7 @@ void *zmapNewThread(void *thread_args) "gif seqget %s ; seqfeatures", sequence) ; if (!zMapServerRequest(thread_cb->server, thread_cb->server_request->str, - &(thread_cb->server_reply))) + &(thread_cb->server_reply), &reply_len)) { thread_cb->thread_died = TRUE ; @@ -275,3 +315,63 @@ static void cleanUpThread(void *thread_args) } + +/* Static/global list of protocols and whether their global init/cleanup functions have been + * called. These are functions that must only be called once. */ +static void protocolGlobalInitFunc(ZMapProtocolInitList protocols, char *protocol, + void **global_init_data_out) +{ + int status ; + GList *curr_ptr ; + ZMapProtocolInit init ; + + if ((status = pthread_mutex_lock(&(protocols->mutex))) != 0) + { + ZMAPFATALSYSERR(status, "%s", "protocolGlobalInitFunc() mutex lock") ; + } + + /* If we don't find the protocol in the list then add it, initialised to FALSE. */ + if (!(curr_ptr = g_list_find_custom(protocols->protocol_list, protocol, findProtocol))) + { + init = (ZMapProtocolInit)g_new(ZMapProtocolInitStruct, 1) ; + init->protocol = g_strdup(protocol) ; + init->init_called = init->cleanup_called = FALSE ; + init->global_init_data = NULL ; + + protocols->protocol_list = g_list_prepend(protocols->protocol_list, init) ; + } + else + init = curr_ptr->data ; + + /* Call the init routine if its not been called yet and either way return the global_init_data. */ + if (!init->init_called) + { + if (!zMapServerGlobalInit(protocol, &(init->global_init_data))) + ZMAPFATALERR("Initialisation call for %s protocol failed.", protocol) ; + + init->init_called = TRUE ; + } + + *global_init_data_out = init->global_init_data ; + + if ((status = pthread_mutex_unlock(&(protocols->mutex))) != 0) + { + ZMAPFATALSYSERR(status, "%s", "protocolGlobalInitFunc() mutex unlock") ; + } + + return ; +} + +/* Compare a protocol in the list with the supplied one. Just a straight string + * comparison currently. */ +static int findProtocol(gconstpointer list_data, gconstpointer custom_data) +{ + int result ; + char *list_protocol = ((ZMapProtocolInit)list_data)->protocol, *protocol = (char *)custom_data ; + + result = strcasecmp(list_protocol, protocol) ; + + return result ; +} + + -- GitLab