From 37cd2140d53396a57236dcab38abe3cba4b71c06 Mon Sep 17 00:00:00 2001 From: edgrif <edgrif> Date: Fri, 5 Dec 2008 09:46:09 +0000 Subject: [PATCH] major change from issuing one openload command to stepping through all stages one by one. Remove openload, change all requests to use new step interface. fix bug in terminate code. --- src/zmapView/zmapView.c | 1021 ++++++++++++++++++++++++++------------- 1 file changed, 680 insertions(+), 341 deletions(-) diff --git a/src/zmapView/zmapView.c b/src/zmapView/zmapView.c index 5e35722db..705d8e027 100755 --- a/src/zmapView/zmapView.c +++ b/src/zmapView/zmapView.c @@ -25,9 +25,9 @@ * Description: * Exported functions: See ZMap/zmapView.h * HISTORY: - * Last edited: Nov 7 14:09 2008 (rds) + * Last edited: Dec 4 10:36 2008 (edgrif) * Created: Thu May 13 15:28:26 2004 (edgrif) - * CVS info: $Id: zmapView.c,v 1.138 2008-11-07 17:15:39 rds Exp $ + * CVS info: $Id: zmapView.c,v 1.139 2008-12-05 09:46:09 edgrif Exp $ *------------------------------------------------------------------- */ @@ -47,6 +47,23 @@ #include <zmapView_P.h> +typedef struct +{ + GList *feature_sets ; + GList *required_styles ; + + char *database_path ; + + char *styles_list ; + char *styles_file ; + gboolean server_styles_have_mode ; + + ZMapFeatureContext context ; + + ZMapServerReqType last_request ; +} ConnectionDataStruct, *ConnectionData ; + + static ZMapView createZMapView(GtkWidget *xremote_widget, char *view_name, GList *sequences, void *app_data) ; static void destroyZMapView(ZMapView *zmap) ; @@ -66,16 +83,17 @@ static void viewSplitToPatternCB(ZMapWindow window, void *caller_data, void *win static void setZoomStatus(gpointer data, gpointer user_data); static void splitMagic(gpointer data, gpointer user_data); + static void startStateConnectionChecking(ZMapView zmap_view) ; #ifdef ED_G_NEVER_INCLUDE_THIS_CODE static void stopStateConnectionChecking(ZMapView zmap_view) ; #endif /* ED_G_NEVER_INCLUDE_THIS_CODE */ static gboolean checkStateConnections(ZMapView zmap_view) ; -static void loadDataConnections(ZMapView zmap_view) ; - -static void killGUI(ZMapView zmap_view) ; -static void killConnections(ZMapView zmap_view) ; +static gboolean dispatchContextRequests(ZMapView zmap_view, ZMapViewConnection view_con, ZMapServerReqAny req_any) ; +static gboolean processDataRequests(ZMapView zmap_view, ZMapViewConnection view_con, ZMapServerReqAny req_any) ; +static gboolean freeDataRequest(ZMapViewConnection view_con, ZMapServerReqAny req_any) ; +static gboolean processGetSeqRequests(ZMapView zmap_view, ZMapViewConnection view_con, ZMapServerReqAny req_any) ; static ZMapViewConnection createConnection(ZMapView zmap_view, ZMapURL url, char *format, @@ -85,6 +103,8 @@ static ZMapViewConnection createConnection(ZMapView zmap_view, gboolean sequence_server, gboolean writeback_server, char *sequence, int start, int end) ; static void destroyConnection(ZMapViewConnection *view_conn) ; +static void killGUI(ZMapView zmap_view) ; +static void killConnections(ZMapView zmap_view) ; static void resetWindows(ZMapView zmap_view) ; static void displayDataWindows(ZMapView zmap_view, @@ -104,8 +124,6 @@ static GList *string2StyleQuarks(char *feature_sets) ; static gboolean nextIsQuoted(char **text) ; #endif /* ED_G_NEVER_INCLUDE_THIS_CODE */ - - static gboolean justMergeContext(ZMapView view, ZMapFeatureContext *context_inout); static void justDrawContext(ZMapView view, ZMapFeatureContext diff_context); @@ -116,6 +134,7 @@ static void addAlignments(ZMapFeatureContext context) ; static gboolean mergeAndDrawContext(ZMapView view, ZMapFeatureContext context_inout); static void eraseAndUndrawContext(ZMapView view, ZMapFeatureContext context_inout); + #ifdef NOT_REQUIRED_ATM static gboolean getSequenceServers(ZMapView zmap_view, char *config_str) ; static void destroySeq2ServerCB(gpointer data, gpointer user_data_unused) ; @@ -124,10 +143,15 @@ static void destroySeq2Server(ZMapViewSequence2Server seq_2_server) ; static gboolean checkSequenceToServerMatch(GList *seq_2_server, ZMapViewSequence2Server target_seq_server) ; static gint findSequence(gconstpointer a, gconstpointer b) ; #endif /* NOT_REQUIRED_ATM */ + static void threadDebugMsg(ZMapThread thread, char *format_str, char *msg) ; static void killAllSpawned(ZMapView zmap_view); +static gboolean connections(ZMapView zmap_view, gboolean threads_have_died) ; + + + /* These callback routines are global because they are set just once for the lifetime of the @@ -153,6 +177,7 @@ ZMapWindowCallbacksStruct window_cbs_G = + /* * ------------------- External functions ------------------- */ @@ -305,6 +330,14 @@ gboolean zMapViewConnect(ZMapView zmap_view, char *config_str) { /* Probably we should indicate to caller what the problem was here.... * e.g. if we are resetting then say we are resetting etc.....again we need g_error here. */ + zMapLogCritical("GUI: %s", "cannot connect because not in init state.") ; + + result = FALSE ; + } + else if (zmap_view->step_list) + { + zMapLogCritical("GUI: %s", "View is already executing connection requests so cannot connect.") ; + result = FALSE ; } else @@ -326,18 +359,41 @@ gboolean zMapViewConnect(ZMapView zmap_view, char *config_str) { zMapConfigIniContextIncludeBuffer(context, config_str); - if ((settings_list = zMapConfigIniContextGetSources(context))) - result = TRUE; + settings_list = zMapConfigIniContextGetSources(context) ; zMapConfigIniContextDestroy(context); - context = NULL; + + context = NULL ; } /* Set up connections to the named servers. */ - if (result && (free_this_list = settings_list)) + if (settings_list) { + ZMapConfigSource current_server = NULL; int connections = 0 ; + free_this_list = settings_list ; + + current_server = (ZMapConfigSource)settings_list->data ; + + /* Create the step list that will be used to control obtaining the feature + * context from the multiple sources. */ + zmap_view->step_list = zmapViewStepListCreate(dispatchContextRequests, + processDataRequests, + freeDataRequest) ; + zmapViewStepListAddStep(zmap_view->step_list, ZMAP_SERVERREQ_CREATE) ; + zmapViewStepListAddStep(zmap_view->step_list, ZMAP_SERVERREQ_OPEN) ; + zmapViewStepListAddStep(zmap_view->step_list, ZMAP_SERVERREQ_GETSERVERINFO) ; + zmapViewStepListAddStep(zmap_view->step_list, ZMAP_SERVERREQ_FEATURESETS) ; + zmapViewStepListAddStep(zmap_view->step_list, ZMAP_SERVERREQ_STYLES) ; + zmapViewStepListAddStep(zmap_view->step_list, ZMAP_SERVERREQ_NEWCONTEXT) ; + zmapViewStepListAddStep(zmap_view->step_list, ZMAP_SERVERREQ_FEATURES) ; + + /* Should test for dna col here as well....should unify dna and other features.... */ + if (current_server->sequence) + zmapViewStepListAddStep(zmap_view->step_list, ZMAP_SERVERREQ_SEQUENCE) ; + + /* Current error handling policy is to connect to servers that we can and * report errors for those where we fail but to carry on and set up the ZMap * as long as at least one connection succeeds. */ @@ -346,19 +402,20 @@ gboolean zMapViewConnect(ZMapView zmap_view, char *config_str) int url_parse_error ; ZMapURL urlObj; ZMapViewConnection view_con ; - ZMapConfigSource current_server = NULL; - current_server = (ZMapConfigSource)settings_list->data; + current_server = (ZMapConfigSource)settings_list->data ; if (!current_server->url) { /* url is absolutely required. Go on to next stanza if there isn't one. * Done before anything else so as not to set seq/write servers to invalid locations */ + zMapLogWarning("GUI: %s", "No url specified in config source group.") ; - zMapLogWarning("GUI: %s", "computer says no url specified") ; continue ; } #ifdef NOT_REQUIRED_ATM + /* This will become redundant with step stuff..... */ + else if (!checkSequenceToServerMatch(zmap_view->sequence_2_server, &tmp_seq)) { /* If certain sequences must only be fetched from certain servers then make sure @@ -368,15 +425,17 @@ gboolean zMapViewConnect(ZMapView zmap_view, char *config_str) } #endif /* NOT_REQUIRED_ATM */ - /* Parse the url, only here if there is a url to parse */ - urlObj = url_parse(current_server->url, &url_parse_error); - if (!urlObj) + + /* Parse the url and create connection. */ + if (!(urlObj = url_parse(current_server->url, &url_parse_error))) { zMapLogWarning("GUI: url %s did not parse. Parse error < %s >\n", current_server->url, url_error(url_parse_error)) ; } - else if((view_con = createConnection(zmap_view, urlObj, + else + { + if ((view_con = createConnection(zmap_view, urlObj, (char *)current_server->format, current_server->timeout, (char *)current_server->version, @@ -389,31 +448,33 @@ gboolean zMapViewConnect(ZMapView zmap_view, char *config_str) zmap_view->sequence, zmap_view->start, zmap_view->end))) - { - /* Everything went well... replace current call */ - zmap_view->connection_list = g_list_append(zmap_view->connection_list, view_con) ; - connections++ ; - - if (current_server->sequence) - zmap_view->sequence_server = view_con ; - if (current_server->writeback) - zmap_view->writeback_server = view_con ; + { + /* Everything went well... replace current call */ + zmap_view->connection_list = g_list_append(zmap_view->connection_list, view_con) ; + connections++ ; + + + /* THESE NEED TO GO WHEN STEP LIST STUFF IS DONE PROPERLY.... */ + if (current_server->sequence) + zmap_view->sequence_server = view_con ; + if (current_server->writeback) + zmap_view->writeback_server = view_con ; + } + else + { + zMapLogWarning("GUI: url %s looks ok (host: %s\tport: %d)" + "but could not connect to server.", + urlObj->url, + urlObj->host, + urlObj->port) ; + } } - else - { - zMapLogWarning("GUI: url %s looks ok, host: %s\nport: %d....\n", - urlObj->url, - urlObj->host, - urlObj->port) ; - zMapLogWarning("Could not connect to server on %s, port %d", - urlObj->host, - urlObj->port) ; - } + + } - while((settings_list = g_list_next(settings_list))); + while ((settings_list = g_list_next(settings_list))); - /* NEED TO FREE THE SETTINGS_LIST NOW! */ /* Ought to return a gerror here........ */ if (!connections) @@ -422,7 +483,9 @@ gboolean zMapViewConnect(ZMapView zmap_view, char *config_str) zMapConfigSourcesFreeList(free_this_list); } else - result = FALSE; + { + result = FALSE; + } /* If at least one connection succeeded then we are up and running, if not then the zmap @@ -431,8 +494,13 @@ gboolean zMapViewConnect(ZMapView zmap_view, char *config_str) { zmap_view->state = ZMAPVIEW_LOADING ; - /* Start polling function that checks state of this view and its connections, note - * that at this stage there is no data to display. */ + /* Start the connections to the sources. */ + zmapViewStepListIter(zmap_view->step_list) ; + + /* Start polling function that checks state of this view and its connections, + * this will wait until the connections reply, process their replies and call + * zmapViewStepListIter() again. + */ startStateConnectionChecking(zmap_view) ; } else @@ -446,25 +514,6 @@ gboolean zMapViewConnect(ZMapView zmap_view, char *config_str) } -/* Is this ever called..... */ -/* Signal threads that we want data to stick into the ZMap */ -gboolean zMapViewLoad(ZMapView zmap_view) -{ - gboolean result = FALSE ; - - /* Perhaps we should return a "wrong state" warning here.... */ - if (zmap_view->state == ZMAPVIEW_CONNECTED) - { - zmapViewBusy(zmap_view, TRUE) ; - - loadDataConnections(zmap_view) ; - - result = TRUE ; - } - - return result ; -} - /* Copies an existing window in a view. * Returns the window on success, NULL on failure. */ @@ -1065,7 +1114,10 @@ gboolean zMapViewDestroy(ZMapView zmap_view) -/* Functions internal to zmapView package. */ + +/* + * Functions internal to zmapView package. + */ @@ -1444,6 +1496,7 @@ static void destroyZMapView(ZMapView *zmap_view_out) ZMapView zmap_view = *zmap_view_out ; g_free(zmap_view->sequence) ; + #ifdef NOT_REQUIRED_ATM if (zmap_view->sequence_2_server) { @@ -1452,6 +1505,7 @@ static void destroyZMapView(ZMapView *zmap_view_out) zmap_view->sequence_2_server = NULL ; } #endif /* NOT_REQUIRED_ATM */ + if (zmap_view->cwh_hash) zmapViewCWHDestroy(&(zmap_view->cwh_hash)); @@ -1466,6 +1520,8 @@ static void destroyZMapView(ZMapView *zmap_view_out) g_free(zmap_view->session_data) ; } + if (zmap_view->step_list) + zmapViewStepListDestroy(zmap_view->step_list) ; killAllSpawned(zmap_view); @@ -1478,6 +1534,12 @@ static void destroyZMapView(ZMapView *zmap_view_out) + +/* + * Connection control functions, interface to the data fetching threads. + */ + + /* Start the ZMapView GTK idle function (gets run when the GUI is doing nothing). */ static void startStateConnectionChecking(ZMapView zmap_view) @@ -1523,21 +1585,22 @@ static void stopStateConnectionChecking(ZMapView zmap_view) * NOTE that you cannot use a condvar here, if the connection thread signals us using a * condvar we will probably miss it, that just doesn't work, we have to pole for changes * and this is possible because this routine is called from the idle function of the GUI. + * * */ static gboolean checkStateConnections(ZMapView zmap_view) { gboolean call_again = TRUE ; /* Normally we want to called continuously. */ - GList* list_item ; - gboolean state_change = TRUE ; /* Records whehter state of view has changed. */ - gboolean threads_have_died = FALSE ; /* Records if any threads have died. */ + gboolean state_change = TRUE ; /* Has view state changed ?. */ + gboolean threads_have_died = FALSE ; /* Have any threads died ? */ /* should assert the zmapview_state here to save checking later..... */ if (zmap_view->connection_list) { + GList *list_item ; + list_item = g_list_first(zmap_view->connection_list) ; - /* should assert this as never null.... */ do { @@ -1557,295 +1620,463 @@ static gboolean checkStateConnections(ZMapView zmap_view) data = NULL ; err_msg = NULL ; + if (!(zMapThreadGetReplyWithData(thread, &reply, &data, &err_msg))) { threadDebugMsg(thread, "GUI: thread %s, cannot access reply from thread - %s\n", err_msg) ; /* should abort or dump here....or at least kill this connection. */ - } else { - #ifdef ED_G_NEVER_INCLUDE_THIS_CODE threadDebugMsg(thread, "GUI: thread %s, thread reply = %s\n", zMapVarGetReplyString(reply)) ; #endif /* ED_G_NEVER_INCLUDE_THIS_CODE */ - - if (reply == ZMAPTHREAD_REPLY_WAIT) + switch (reply) { - state_change = FALSE ; + case ZMAPTHREAD_REPLY_WAIT: + { + state_change = FALSE ; + + break ; + } + case ZMAPTHREAD_REPLY_GOTDATA: + case ZMAPTHREAD_REPLY_REQERROR: + { + ZMapServerReqAny req_any ; + ZMapViewConnectionRequest request ; + gboolean kill_connection = FALSE ; + + view_con->curr_request = ZMAPTHREAD_REQUEST_WAIT ; + + /* Recover the request from the thread data. */ + req_any = (ZMapServerReqAny)data ; + + /* Recover the stepRequest from the view connection and process the data from + * the request. */ + if (!(request = zmapViewStepListFindRequest(zmap_view->step_list, req_any->type, view_con))) + { + zMapLogCritical("Request of type %s for connection %s not found in view %s step list !", + zMapServerReqType2ExactStr(req_any->type), + view_con->url, + zmap_view->view_name) ; + + kill_connection = TRUE ; + } + else + { + if (reply == ZMAPTHREAD_REPLY_REQERROR) + { + /* This means the request failed for some reason. */ + threadDebugMsg(thread, "GUI: thread %s, request to server failed....\n", NULL) ; + + if (err_msg) + { + zMapLogCritical("Source \"%s\" has been terminated" + " because a request to it has failed," + " error was: %s", view_con->url, err_msg) ; + g_free(err_msg) ; + } + + kill_connection = TRUE ; + } + else + { + threadDebugMsg(thread, "GUI: thread %s, got data\n", NULL) ; + + /* Really we should only be loading stuff if we are LOADING.... */ + if (zmap_view->state != ZMAPVIEW_LOADING && zmap_view->state != ZMAPVIEW_LOADED) + { + threadDebugMsg(thread, "GUI: thread %s, got data but ZMap state is - %s\n", + zmapViewGetStatusAsStr(zMapViewGetStatus(zmap_view))) ; + } + + zmapViewStepListStepProcessRequest(zmap_view->step_list, zmap_view, request) ; + } + } + + if (kill_connection) + { + /* Remove request from all steps.... */ + zmapViewStepListStepRequestDeleteAll(zmap_view->step_list, request) ; + + /* Signal thread to die. */ + zMapThreadKill(thread) ; + } + + + /* Reset the reply from the slave. */ + zMapThreadSetReply(thread, ZMAPTHREAD_REPLY_WAIT) ; + + break ; + } + case ZMAPTHREAD_REPLY_DIED: + { + /* Thread has failed for some reason and we should clean up. */ + if (err_msg) + zMapWarning("%s", err_msg) ; + + threads_have_died = TRUE ; + + threadDebugMsg(thread, "GUI: thread %s has died so cleaning up....\n", NULL) ; + + /* We are going to remove an item from the list so better move on from + * this item. */ + list_item = g_list_next(list_item) ; + zmap_view->connection_list = g_list_remove(zmap_view->connection_list, view_con) ; + + destroyConnection(&view_con) ; + + break ; + } + case ZMAPTHREAD_REPLY_CANCELLED: + { + /* This happens when we have signalled the threads to die and they are + * replying to say that they have now died. */ + + threads_have_died = TRUE ; + + /* This means the thread was cancelled so we should clean up..... */ + threadDebugMsg(thread, "GUI: thread %s has been cancelled so cleaning up....\n", NULL) ; + + /* Warn the user ! */ + zMapWarning("Source \"%s\" has been cancelled, check log for details.", view_con->url) ; + + /* We are going to remove an item from the list so better move on from + * this item. */ + list_item = g_list_next(list_item) ; + zmap_view->connection_list = g_list_remove(zmap_view->connection_list, view_con) ; + + destroyConnection(&view_con) ; + + break ; + } + default: + { + zMapLogFatalLogicErr("switch(), unknown value: %d", reply) ; + + break ; + } } - else if (reply == ZMAPTHREAD_REPLY_GOTDATA) - { - view_con->curr_request = ZMAPTHREAD_REQUEST_WAIT ; + } + } + while ((list_item = g_list_next(list_item))) ; + } - /* Really we should only be loading stuff if we are LOADING.... */ - if (zmap_view->state == ZMAPVIEW_LOADING || zmap_view->state == ZMAPVIEW_LOADED) - { - ZMapServerReqAny req_any = (ZMapServerReqAny)data ; - threadDebugMsg(thread, "GUI: thread %s, got data\n", NULL) ; + /* Fiddly logic here as this could be combined with the following code that handles if we don't + * have any connections any more...but not so easy as some of the code below kills the zmap so. + * easier to do this here. */ + if (zmap_view->busy && !zmapAnyConnBusy(zmap_view->connection_list)) + zmapViewBusy(zmap_view, FALSE) ; - /* Reset the reply from the slave. */ - zMapThreadSetReply(thread, ZMAPTHREAD_REPLY_WAIT) ; - - /* Process the different types of data coming back. */ - switch (req_any->type) - { - case ZMAP_SERVERREQ_OPENLOAD: - { - ZMapServerReqGetFeatures features - = (ZMapServerReqGetFeatures)&(((ZMapServerReqOpenLoad)req_any)->features) ; - ZMapServerReqGetServerInfo get_info - = (ZMapServerReqGetServerInfo)&(((ZMapServerReqOpenLoad)req_any)->get_info) ; - /* got server info, so record in servers info. struct.... */ - /* AGH PROBLEM...WHICH SERVER RECORD GOES WITH WHICH SERVER.... */ + /* At this point if we have connections then we carry on looping looking for + * replies from the views. If there are no threads left then we need to examine + * our state and take action depending on whether we are dying or threads + * have died or whatever.... */ + if (zmap_view->connection_list) + { + /* Signal layer above us if view has changed state. */ + if (state_change) + (*(view_cbs_G->state_change))(zmap_view, zmap_view->app_data, NULL) ; - zmapViewSessionAddServerInfo(zmap_view->session_data, get_info->database_path_out) ; + /* Check for more connection steps and dispatch them or clear up if finished. */ + if ((zmap_view->step_list)) + { + /* If there were errors then all connections may have been removed from + * step list or if we have finished then destroy step_list. */ + if (zmapViewStepListAreConnections(zmap_view->step_list) && zmapViewStepListIsNext(zmap_view->step_list)) + { + zmapViewStepListIter(zmap_view->step_list) ; + } + else + { + zmapViewStepListDestroy(zmap_view->step_list) ; + zmap_view->step_list = NULL ; + } + } + } + else + { + /* NEW CODE */ + call_again = connections(zmap_view, threads_have_died) ; + } - getFeatures(zmap_view, features) ; + return call_again ; +} - zmap_view->connections_loaded++ ; - /* This will need to be more sophisticated, we will need to time - * connections out. */ - if (zmap_view->connections_loaded - == g_list_length(zmap_view->connection_list)) - zmap_view->state = ZMAPVIEW_LOADED ; - break ; - } - case ZMAP_SERVERREQ_GETSEQUENCE: - { - ZMapServerReqGetSequence get_sequence = (ZMapServerReqGetSequence)req_any ; - GPid blixem_pid ; - gboolean status ; - - /* Got the sequences so launch blixem. */ - if ((status = zmapViewCallBlixem(zmap_view, - get_sequence->orig_feature, - get_sequence->sequences, - get_sequence->flags, - &blixem_pid, - &(zmap_view->kill_blixems)))) - zmap_view->spawned_processes = g_list_append(zmap_view->spawned_processes, - GINT_TO_POINTER(blixem_pid)) ; - - break ; - } +/* This is _not_ a generalised dispatch function, it handles a sequence of requests that + * will end up fetching a feature context from a source. The steps are interdependent + * and data from one step must be available to the next. */ +static gboolean dispatchContextRequests(ZMapView zmap_view, ZMapViewConnection connection, ZMapServerReqAny req_any) +{ + gboolean result = FALSE ; + ConnectionData connect_data = (ConnectionData)(connection->request_data) ; - case ZMAP_SERVERREQ_GETSERVERINFO: - { - ZMapServerReqGetServerInfo get_info = (ZMapServerReqGetServerInfo)req_any ; + switch (req_any->type) + { + case ZMAP_SERVERREQ_CREATE: + case ZMAP_SERVERREQ_OPEN: + case ZMAP_SERVERREQ_GETSERVERINFO: + case ZMAP_SERVERREQ_FEATURESETS: + { - /* got server info, so record in servers info. struct.... */ - /* AGH PROBLEM...WHICH SERVER RECORD GOES WITH WHICH SERVER.... */ + break ; + } + case ZMAP_SERVERREQ_STYLES: + { + ZMapServerReqStyles get_styles = (ZMapServerReqStyles)req_any ; - zmapViewSessionAddServerInfo(zmap_view->session_data, get_info->database_path_out) ; + /* required styles comes from featuresets call. */ + get_styles->required_styles = connect_data->required_styles ; - break ; - } + break ; + } + case ZMAP_SERVERREQ_NEWCONTEXT: + { + ZMapServerReqNewContext new_context = (ZMapServerReqNewContext)req_any ; - case ZMAP_SERVERREQ_FEATURES: - case ZMAP_SERVERREQ_FEATURE_SEQUENCE: - case ZMAP_SERVERREQ_SEQUENCE: - { - getFeatures(zmap_view, (ZMapServerReqGetFeatures)req_any) ; + new_context->context = connect_data->context ; - break ; - } + break ; + } + case ZMAP_SERVERREQ_FEATURES: + { + ZMapServerReqGetFeatures get_features = (ZMapServerReqGetFeatures)req_any ; - default: - { - zMapLogFatal("Unknown request type: %d", req_any->type) ; /* Exit appl. */ - break ; - } - } + get_features->context = connect_data->context ; - /* Free the request block. */ - g_free(data) ; - } - else - threadDebugMsg(thread, "GUI: thread %s, got data but ZMap state is - %s\n", - zmapViewGetStatusAsStr(zMapViewGetStatus(zmap_view))) ; + if (!(connect_data->server_styles_have_mode)) + { + if (!zMapFeatureAnyAddModesToStyles((ZMapFeatureAny)(connect_data->context))) + { + printf("oh bother...\n") ; - } - else if (reply == ZMAPTHREAD_REPLY_REQERROR) - { - if (err_msg) - zMapWarning("%s", err_msg) ; +#ifdef ED_G_NEVER_INCLUDE_THIS_CODE + *err_msg_out = g_strdup_printf("Inferring Style modes from Features failed.") ; + thread_rc = ZMAPTHREAD_RETURNCODE_REQFAIL ; +#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */ - view_con->curr_request = ZMAPTHREAD_REQUEST_WAIT ; + } + } - /* Reset the reply from the slave. */ - zMapThreadSetReply(thread, ZMAPTHREAD_REPLY_WAIT) ; + break ; + } + case ZMAP_SERVERREQ_SEQUENCE: + { + ZMapServerReqGetFeatures get_features = (ZMapServerReqGetFeatures)req_any ; - /* This means the request failed for some reason. */ - threadDebugMsg(thread, "GUI: thread %s, request to server failed....\n", NULL) ; + get_features->context = connect_data->context ; - g_free(err_msg) ; - } - else if (reply == ZMAPTHREAD_REPLY_DIED) - { - /* This means the thread has failed for some reason and we should clean up. */ + break ; + } + default: + { + zMapLogFatalLogicErr("switch(), unknown value: %d", req_any->type) ; - if (err_msg) - zMapWarning("%s", err_msg) ; + break ; + } + } - threads_have_died = TRUE ; + result = TRUE ; - threadDebugMsg(thread, "GUI: thread %s has died so cleaning up....\n", NULL) ; - - /* We are going to remove an item from the list so better move on from - * this item. */ - list_item = g_list_next(list_item) ; - zmap_view->connection_list = g_list_remove(zmap_view->connection_list, view_con) ; + return result ; +} - destroyConnection(&view_con) ; - } - else if (reply == ZMAPTHREAD_REPLY_CANCELLED) - { - /* This happens when we have signalled the threads to die and they are - * replying to say that they have now died. */ - /* This means the thread was cancelled so we should clean up..... */ - threadDebugMsg(thread, "GUI: thread %s has been cancelled so cleaning up....\n", NULL) ; - /* We are going to remove an item from the list so better move on from - * this item. */ - list_item = g_list_next(list_item) ; - zmap_view->connection_list = g_list_remove(zmap_view->connection_list, view_con) ; +/* This is _not_ a generalised processing function, it handles a sequence of replies from + * a thread that build up a feature context from a source. The steps are interdependent + * and data from one step must be available to the next. */ +static gboolean processDataRequests(ZMapView zmap_view, ZMapViewConnection view_con, ZMapServerReqAny req_any) +{ + gboolean result = TRUE ; + ConnectionData connect_data = (ConnectionData)(view_con->request_data) ; - destroyConnection(&view_con) ; - } - } - } - while ((list_item = g_list_next(list_item))) ; - } + /* Process the different types of data coming back. */ + switch (req_any->type) + { + case ZMAP_SERVERREQ_CREATE: + case ZMAP_SERVERREQ_OPEN: + { + break ; + } + case ZMAP_SERVERREQ_GETSERVERINFO: + { + ZMapServerReqGetServerInfo get_info = (ZMapServerReqGetServerInfo)req_any ; + connect_data->database_path = get_info->database_path_out ; - /* Fiddly logic here as this could be combined with the following code that handles if we don't - * have any connections any more...but not so easy as some of the code below kills the zmap so. - * easier to do this here. */ - if (zmap_view->busy && !zmapAnyConnBusy(zmap_view->connection_list)) - zmapViewBusy(zmap_view, FALSE) ; + break ; + } + case ZMAP_SERVERREQ_FEATURESETS: + { + ZMapServerReqFeatureSets feature_sets = (ZMapServerReqFeatureSets)req_any ; + if (req_any->response == ZMAP_SERVERRESPONSE_OK) + { + /* Got the feature sets so record them in the server context. */ + connect_data->context->feature_set_names = feature_sets->feature_sets ; + } + else if (req_any->response == ZMAP_SERVERRESPONSE_UNSUPPORTED && feature_sets->feature_sets) + { + /* If server doesn't support checking feature sets then just use those supplied. */ + connect_data->context->feature_set_names = feature_sets->feature_sets ; - /* At this point if there are no threads left we need to examine our state and take action - * depending on whether we are dying or threads have died or whatever.... */ - if (zmap_view->connection_list) - { - /* Signal layer above us if view has changed state. */ - if (state_change) - (*(view_cbs_G->state_change))(zmap_view, zmap_view->app_data, NULL) ; - } - else - { - /* Change to a switch here.... */ + feature_sets->required_styles = g_list_copy(feature_sets->feature_sets) ; + } - if (zmap_view->state == ZMAPVIEW_INIT) - { - /* Nothing to do here I think.... */ + /* I don't know if we need these, can get from context. */ + connect_data->feature_sets = feature_sets->feature_sets ; + connect_data->required_styles = feature_sets->required_styles ; - } - else if (zmap_view->state == ZMAPVIEW_CONNECTING || zmap_view->state == ZMAPVIEW_CONNECTED - || zmap_view->state == ZMAPVIEW_LOADING || zmap_view->state == ZMAPVIEW_LOADED) - { + break ; + } + case ZMAP_SERVERREQ_STYLES: + { + ZMapServerReqStyles get_styles = (ZMapServerReqStyles)req_any ; + + connect_data->context->styles = get_styles->styles ; + + /* Will need to pass on the styles mode stuff further down here.... */ + + break ; + } + case ZMAP_SERVERREQ_NEWCONTEXT: + { + break ; + } + case ZMAP_SERVERREQ_FEATURES: + case ZMAP_SERVERREQ_SEQUENCE: + { + ZMapServerReqGetFeatures get_features = (ZMapServerReqGetFeatures)req_any ; + + /* ok...once we are here we can display stuff.... */ + if (req_any->type == connect_data->last_request) + { + /* Isn't there a problem here...which bit of info goes with which server ???? */ + zmapViewSessionAddServerInfo(zmap_view->session_data, connect_data->database_path) ; + + getFeatures(zmap_view, get_features) ; + + zmap_view->connections_loaded++ ; + + /* This will need to be more sophisticated, we will need to time + * connections out. */ + if (zmap_view->connections_loaded == g_list_length(zmap_view->connection_list)) + zmap_view->state = ZMAPVIEW_LOADED ; + } + + break ; + } - /* We should kill the ZMap here with an error message....or allow user to reload... */ - if (threads_have_died) - { - /* Threads have died because of their own errors....but the ZMap is not dying so - * reset state to init and we should return an error here....(but how ?), we - * should not be outputting messages....I think..... */ - zMapWarning("%s", "Cannot show ZMap because server connections have all died") ; #ifdef ED_G_NEVER_INCLUDE_THIS_CODE - killGUI(zmap_view) ; - destroyZMapView(zmap_view) ; -#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */ - /* need to reset here..... */ - call_again = FALSE ; - } - /* I don't think the "else" should be possible......so perhaps we should fail if that - * happens..... */ + /* needs incorporating into the above.... */ - zmap_view->state = ZMAPVIEW_INIT ; - } - else if (zmap_view->state == ZMAPVIEW_RESETTING) - { - /* zmap is ok but user has reset it and all threads have died so we need to stop - * checking.... */ - zmap_view->state = ZMAPVIEW_INIT ; + case ZMAP_SERVERREQ_FEATURES: + case ZMAP_SERVERREQ_FEATURE_SEQUENCE: + case ZMAP_SERVERREQ_SEQUENCE: + { + getFeatures(zmap_view, (ZMapServerReqGetFeatures)req_any) ; - /* Signal layer above us because the view has reset. */ - (*(view_cbs_G->state_change))(zmap_view, zmap_view->app_data, NULL) ; + break ; + } - call_again = FALSE ; - } - else if (zmap_view->state == ZMAPVIEW_DYING) - { - /* Tricky coding here: we need to destroy the view _before_ we notify the layer above us - * that the zmap_view has gone but we need to pass information from the view back, so we - * keep a temporary record of certain parts of the view. */ - ZMapView zmap_view_ref = zmap_view ; - void *app_data = zmap_view->app_data ; - /* view was waiting for threads to die, now they have we can free everything. */ - destroyZMapView(&zmap_view) ; + /* This should go once my changes are complete... */ + case ZMAP_SERVERREQ_OPENLOAD: + { + ZMapServerReqGetFeatures features + = (ZMapServerReqGetFeatures)&(((ZMapServerReqOpenLoad)req_any)->features) ; + ZMapServerReqGetServerInfo get_info + = (ZMapServerReqGetServerInfo)&(((ZMapServerReqOpenLoad)req_any)->get_info) ; - /* Signal layer above us that view has died. */ - (*(view_cbs_G->destroy))(zmap_view_ref, app_data, NULL) ; + /* got server info, so record in servers info. struct.... */ + /* AGH PROBLEM...WHICH SERVER RECORD GOES WITH WHICH SERVER.... */ - call_again = FALSE ; - } - } + zmapViewSessionAddServerInfo(zmap_view->session_data, get_info->database_path_out) ; - return call_again ; -} + getFeatures(zmap_view, features) ; + + zmap_view->connections_loaded++ ; + /* This will need to be more sophisticated, we will need to time + * connections out. */ + if (zmap_view->connections_loaded == g_list_length(zmap_view->connection_list)) + zmap_view->state = ZMAPVIEW_LOADED ; -static void loadDataConnections(ZMapView zmap_view) + break ; + } +#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */ + + default: + { + zMapLogFatalLogicErr("switch(), unknown value: %d", req_any->type) ; + result = FALSE ; + + break ; + } + } + + return result ; +} + +static gboolean freeDataRequest(ZMapViewConnection view_con, ZMapServerReqAny req_any) { + gboolean result = TRUE ; - if (zmap_view->connection_list) - { - GList* list_item ; + g_free(view_con->request_data) ; + view_con->request_data = NULL ; - list_item = g_list_first(zmap_view->connection_list) ; + zMapServerCreateRequestDestroy(req_any) ; - do - { - ZMapViewConnection view_con ; - ZMapThread thread ; + return result ; +} - ZMapServerReqGetFeatures req_features ; - view_con = list_item->data ; - thread = view_con->thread ; +/* Process get sequence requests. */ +static gboolean processGetSeqRequests(ZMapView zmap_view, ZMapViewConnection view_con, ZMapServerReqAny req_any) +{ + gboolean result = FALSE ; - /* Construct the request to get the features, if its the sequence server then - * get the sequence as well. */ - req_features = g_new0(ZMapServerReqGetFeaturesStruct, 1) ; - if (view_con->sequence_server) - req_features->type = ZMAP_SERVERREQ_FEATURE_SEQUENCE ; - else - req_features->type = ZMAP_SERVERREQ_FEATURES ; + if (req_any->type == ZMAP_SERVERREQ_GETSEQUENCE) + { + ZMapServerReqGetSequence get_sequence = (ZMapServerReqGetSequence)req_any ; + GPid blixem_pid ; + gboolean status ; + + /* Got the sequences so launch blixem. */ + if ((status = zmapViewCallBlixem(zmap_view, + get_sequence->orig_feature, + get_sequence->sequences, + get_sequence->flags, + &blixem_pid, + &(zmap_view->kill_blixems)))) + zmap_view->spawned_processes = g_list_append(zmap_view->spawned_processes, + GINT_TO_POINTER(blixem_pid)) ; - zMapThreadRequest(thread, req_features) ; + result = TRUE ; + } + else + { + zMapLogFatalLogicErr("wrong request type: %d", req_any->type) ; - } while ((list_item = g_list_next(list_item))) ; + result = FALSE ; } - return ; + + return result ; } @@ -1919,28 +2150,7 @@ static ZMapViewConnection createConnection(ZMapView zmap_view, ZMapThread thread ; gboolean status = TRUE ; gboolean dna_requested = FALSE ; - - - -#ifdef ED_G_NEVER_INCLUDE_THIS_CODE - /* User can specify styles in a file. If they don't we get them all and filter them - * according to the feature set name list if specified. */ - if (styles_file) - { - char *filepath ; - - if (!(filepath = zMapConfigDirFindFile(styles_file)) - || !(types = zMapFeatureTypeGetFromFile(filepath))) - { - zMapLogWarning("Could not read types from \"stylesfile\" %s", filepath) ; - status = FALSE ; - } - - if (filepath) - g_free(filepath) ; - } -#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */ - + ConnectionData connect_data ; /* User can specify feature set names that should be displayed in an ordered list. Order of @@ -1975,52 +2185,72 @@ static ZMapViewConnection createConnection(ZMapView zmap_view, * to decode the requests we send it and a terminate function. */ if (status && (thread = zMapThreadCreate(zMapServerRequestHandler, zMapServerTerminateHandler))) { - ZMapServerReqOpenLoad open_load = NULL ; + ZMapViewConnectionRequest request ; + ZMapFeatureContext context ; + ZMapServerReqAny req_any ; - /* Build the intial request. */ - open_load = g_new0(ZMapServerReqOpenLoadStruct, 1) ; - open_load->type = ZMAP_SERVERREQ_OPENLOAD ; - - open_load->open.url = url; - open_load->open.format = g_strdup(format) ; - open_load->open.timeout = timeout ; - open_load->open.version = g_strdup(version) ; - - open_load->context.context = createContext(sequence, start, end, req_featuresets) ; - - open_load->feature_sets.feature_sets = req_featuresets ; - - open_load->styles.styles_list = g_strdup(styles) ; - open_load->styles.styles_file = g_strdup(styles_file) ; - - /* NOTE, some slightly tricky logic here: if this is a sequence server AND dna has been - * requested then ask for the sequence, otherwise don't. Only one server can be a sequence server. */ - if (sequence_server && dna_requested) - open_load->features.type = ZMAP_SERVERREQ_FEATURE_SEQUENCE ; - else - open_load->features.type = ZMAP_SERVERREQ_FEATURES ; - - /* Send the request to the thread to open a connection and get the date. */ - zMapThreadRequest(thread, (void *)open_load) ; + /* Create the connection struct. */ view_con = g_new0(ZMapViewConnectionStruct, 1) ; + + /* THESE MUST GO ONCE STEP LIST SET UP PROPERLY..... */ view_con->sequence_server = sequence_server ; view_con->writeback_server = writeback_server ; + view_con->parent_view = zmap_view ; view_con->curr_request = ZMAPTHREAD_REQUEST_EXECUTE ; view_con->thread = thread ; + view_con->url = g_strdup(url->url) ; + + /* Create data specific to this step list...and set it in the connection. */ + context = createContext(sequence, start, end, req_featuresets) ; + + connect_data = g_new0(ConnectionDataStruct, 1) ; + connect_data->context = context ; + + view_con->request_data = connect_data ; + + + /* CHECK WHAT THIS IS ABOUT.... */ /* Record info. for this session. */ zmapViewSessionAddServer(zmap_view->session_data, url, format) ; + + /* Set up this connection in the step list. */ + req_any = zMapServerRequestCreate(ZMAP_SERVERREQ_CREATE, url, format, timeout, version) ; + request = zmapViewStepListAddServerReq(zmap_view->step_list, view_con, ZMAP_SERVERREQ_CREATE, req_any) ; + req_any = zMapServerRequestCreate(ZMAP_SERVERREQ_OPEN) ; + zmapViewStepListAddServerReq(zmap_view->step_list, view_con, ZMAP_SERVERREQ_OPEN, req_any) ; + req_any = zMapServerRequestCreate(ZMAP_SERVERREQ_GETSERVERINFO) ; + zmapViewStepListAddServerReq(zmap_view->step_list, view_con, ZMAP_SERVERREQ_GETSERVERINFO, req_any) ; + req_any = zMapServerRequestCreate(ZMAP_SERVERREQ_FEATURESETS, req_featuresets) ; + zmapViewStepListAddServerReq(zmap_view->step_list, view_con, ZMAP_SERVERREQ_FEATURESETS, req_any) ; + req_any = zMapServerRequestCreate(ZMAP_SERVERREQ_STYLES, styles, styles_file) ; + zmapViewStepListAddServerReq(zmap_view->step_list, view_con, ZMAP_SERVERREQ_STYLES, req_any) ; + req_any = zMapServerRequestCreate(ZMAP_SERVERREQ_NEWCONTEXT, context) ; + zmapViewStepListAddServerReq(zmap_view->step_list, view_con, ZMAP_SERVERREQ_NEWCONTEXT, req_any) ; + req_any = zMapServerRequestCreate(ZMAP_SERVERREQ_FEATURES) ; + zmapViewStepListAddServerReq(zmap_view->step_list, view_con, ZMAP_SERVERREQ_FEATURES, req_any) ; + if (sequence_server && dna_requested) + { + req_any = zMapServerRequestCreate(ZMAP_SERVERREQ_SEQUENCE) ; + zmapViewStepListAddServerReq(zmap_view->step_list, view_con, ZMAP_SERVERREQ_SEQUENCE, req_any) ; + } + + if (sequence_server && dna_requested) + connect_data->last_request = ZMAP_SERVERREQ_SEQUENCE ; + else + connect_data->last_request = ZMAP_SERVERREQ_FEATURES ; } + return view_con ; } @@ -2032,6 +2262,8 @@ static void destroyConnection(ZMapViewConnection *view_conn_ptr) zMapThreadDestroy(view_conn->thread) ; + g_free(view_conn->url) ; + /* Need to destroy the types array here....... */ g_free(view_conn) ; @@ -2293,12 +2525,12 @@ static void getFeatures(ZMapView zmap_view, ZMapServerReqGetFeatures feature_req zMapPrintTimer(NULL, "Got Features from Thread") ; /* Merge new data with existing data (if any). */ - if ((new_features = feature_req->feature_context_out)) + if ((new_features = feature_req->context)) { /* Truth means view->features == new_features i.e. first time round */ if(!mergeAndDrawContext(zmap_view, new_features)) { - new_features = feature_req->feature_context_out = NULL; + new_features = feature_req->context = NULL; } } @@ -2324,34 +2556,45 @@ static void commandCB(ZMapWindow window, void *caller_data, void *window_data) GList *local_sequences = NULL ; ZMapViewBlixemFlags flags = BLIXEM_NO_FLAG; - if(align_cmd->obey_protein_featuresets) + if (align_cmd->obey_protein_featuresets) flags |= BLIXEM_OBEY_PROTEIN_SETS; - if(align_cmd->obey_dna_featuresets) + if (align_cmd->obey_dna_featuresets) flags |= BLIXEM_OBEY_DNA_SETS; if ((status = zmapViewBlixemLocalSequences(view, align_cmd->feature, &local_sequences))) { if (!view->sequence_server) - zMapWarning("%s", "No sequence server was specified so cannot fetch raw sequences for blixem.") ; + { + zMapWarning("%s", "No sequence server was specified so cannot fetch raw sequences for blixem.") ; + } + else if (view->step_list) + { + zMapLogCritical("GUI: %s", "View is already executing connection requests" + " so cannot fetch local sequences for blixem.") ; + + } else { ZMapViewConnection view_con ; - ZMapThread thread ; - ZMapServerReqGetSequence req_sequences ; + ZMapViewConnectionRequest request ; + ZMapServerReqAny req_any ; view_con = view->sequence_server ; zMapAssert(view_con->sequence_server) ; - thread = view_con->thread ; + /* Create the step list that will be used to fetch the sequences. */ + view->step_list = zmapViewStepListCreate(NULL, processGetSeqRequests, NULL) ; + zmapViewStepListAddStep(view->step_list, ZMAP_SERVERREQ_GETSEQUENCE) ; + + /* Add the request to the step list. */ + req_any = zMapServerRequestCreate(ZMAP_SERVERREQ_GETSEQUENCE, + align_cmd->feature, local_sequences, flags) ; + request = zmapViewStepListAddServerReq(view->step_list, + view_con, ZMAP_SERVERREQ_GETSEQUENCE, req_any) ; - /* Construct the request to get the sequences. */ - req_sequences = g_new0(ZMapServerReqGetSequenceStruct, 1) ; - req_sequences->type = ZMAP_SERVERREQ_GETSEQUENCE ; - req_sequences->orig_feature = align_cmd->feature ; - req_sequences->sequences = local_sequences ; - req_sequences->flags = (int)flags; - zMapThreadRequest(thread, (void *)req_sequences) ; + /* Start the step list. */ + zmapViewStepListIter(view->step_list) ; } } else @@ -2721,3 +2964,99 @@ static void threadDebugMsg(ZMapThread thread, char *format_str, char *msg) return ; } + + +/* check whether there are live connections or not, return TRUE if there are, FALSE otherwise. */ +static gboolean connections(ZMapView zmap_view, gboolean threads_have_died) +{ + gboolean connections = FALSE ; + + switch (zmap_view->state) + { + case ZMAPVIEW_INIT: + { + /* Nothing to do here I think.... */ + connections = TRUE ; + break ; + } + case ZMAPVIEW_CONNECTING: + case ZMAPVIEW_CONNECTED: + case ZMAPVIEW_LOADING: + case ZMAPVIEW_LOADED: + { + /* We should kill the ZMap here with an error message....or allow user to reload... */ + + if (threads_have_died) + { + /* Threads have died because of their own errors....but the ZMap is not dying so + * reset state to init and we should return an error here....(but how ?), we + * should not be outputting messages....I think..... */ + zMapWarning("%s", "Cannot show ZMap because server connections have all died or been cancelled.") ; + zMapLogWarning("%s", "Cannot show ZMap because server connections have all died or been cancelled.") ; + +#ifdef ED_G_NEVER_INCLUDE_THIS_CODE + /* Should we kill the whole window ??? */ + + killGUI(zmap_view) ; + destroyZMapView(zmap_view) ; +#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */ + /* need to reset here..... */ + + + connections = FALSE ; + } + /* I don't think the "else" should be possible......so perhaps we should fail if that + * happens..... */ + + zmap_view->state = ZMAPVIEW_INIT ; + + break ; + } + case ZMAPVIEW_RESETTING: + { + /* zmap is ok but user has reset it and all threads have died so we need to stop + * checking.... */ + zmap_view->state = ZMAPVIEW_INIT ; + + /* Signal layer above us because the view has reset. */ + (*(view_cbs_G->state_change))(zmap_view, zmap_view->app_data, NULL) ; + + connections = FALSE ; + + break ; + } + case ZMAPVIEW_DYING: + { + /* Tricky coding here: we need to destroy the view _before_ we notify the layer above us + * that the zmap_view has gone but we need to pass information from the view back, so we + * keep a temporary record of certain parts of the view. */ + ZMapView zmap_view_ref = zmap_view ; + void *app_data = zmap_view->app_data ; + + /* view was waiting for threads to die, now they have we can free everything. */ + destroyZMapView(&zmap_view) ; + + /* Signal layer above us that view has died. */ + (*(view_cbs_G->destroy))(zmap_view_ref, app_data, NULL) ; + + connections = FALSE ; + + break ; + } + default: + { + zMapLogFatalLogicErr("switch(), unknown value: %d", zmap_view->state) ; + + break ; + } + } + + return connections ; +} + + + + + + + -- GitLab