TSP: The Transport Sample Protocol



Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

tsp_session.c

Go to the documentation of this file.
00001 
00039 #ifdef __OpenBSD__
00040 #include <machine/types.h> 
00041 #include <machine/endian.h>
00042 #endif /* __OpenBSD__ */
00043 
00044 #include "tsp_sys_headers.h"
00045 
00046 #include "tsp_session.h"
00047 #include "tsp_group_algo.h"
00048 #include "tsp_data_sender.h"
00049 #include "tsp_datapool.h"
00050 
00051 
00052 #define TSP_GET_SESSION(session, channel_id, ret) \
00053 { \
00054         if( 0 == (session = TSP_get_session(channel_id) ) ) \
00055         { \
00056                 STRACE_ERROR(("Unable to get session for channel_id=%u",channel_id)) \
00057                 return ret; \
00058         } \
00059 }
00060 
00061 struct TSP_session_data_t 
00062 {
00063         
00064   version_id_t version_id;
00065     
00066   TSP_groups_t groups;
00067     
00068   TSP_data_sender_t sender;
00069 
00070   int data_link_broken; 
00072   TSP_datapool_t datapool;
00073 
00075   GLU_handle_t glu_h;
00076 
00078   int symbols_number;
00079         
00080 };
00081 
00082 typedef struct TSP_session_data_t TSP_session_data_t;
00083 
00084 /* OBJET SESSION */
00085 struct TSP_session_t 
00086 {
00087         
00088   channel_id_t channel_id;
00089         
00090   TSP_session_data_t* session_data;
00091         
00092 };
00093 
00094 typedef struct TSP_session_t TSP_session_t;
00095 
00096 static TSP_session_t X_session_t[TSP_MAX_CLIENT_NUMBER];
00097 
00099 int X_session_nb = 0;
00100 
00102 static channel_id_t X_count_channel_id = 0;
00103 
00104 static int X_initialized = FALSE;
00105 
00106 static pthread_mutex_t X_session_list_mutex = PTHREAD_MUTEX_INITIALIZER;
00107 
00108 
00109 static TSP_session_t* TSP_get_session(channel_id_t channel_id)
00110 {
00111         
00112   TSP_session_t* session = 0;
00113   int i = 0;
00114         
00115   for( i = 0 ;  i < X_session_nb ; i++)
00116     {
00117       if( X_session_t[i].channel_id == channel_id )
00118         {
00119           assert(X_session_t[i].session_data);
00120           session = &(X_session_t[i]);
00121           break;                        
00122         }
00123     }
00124         
00125   if( 0 == session )
00126     { 
00127       STRACE_ERROR(("No session found for channel_id=%u", channel_id));
00128 
00129     }
00130         
00131   return session ;
00132 }
00133 
00134 static void TSP_session_close_session(channel_id_t channel_id)
00135 {
00136   int i;
00137   int ret = FALSE;
00138 
00139   for( i = 0 ;  i < X_session_nb ; i++)
00140     {
00141       if( X_session_t[i].channel_id == channel_id )
00142         {
00143           assert(X_session_t[i].session_data);
00144           free(X_session_t[i].session_data);
00145           /* Fill the hole with latest element */
00146           X_session_t[i] = X_session_t[X_session_nb - 1];
00147           X_session_nb--;
00148           ret = TRUE;
00149           break;                        
00150         }
00151     }   
00152 
00153   if(!ret)
00154     {
00155       STRACE_WARNING(("Unable to find session number %d", channel_id));
00156     }
00157 
00158 }
00159 
00160 static  void TSP_session_destroy_symbols_table(TSP_session_t* session)
00161 {
00162   /* If there was a local datapool, we erase it */
00163   if(session->session_data->datapool)
00164     {
00165       TSP_local_datapool_destroy(session->session_data->datapool);
00166       session->session_data->datapool = 0;
00167     }
00168   
00169   /* erase the group table */
00170   TSP_group_algo_destroy_symbols_table(session->session_data->groups);
00171 }
00172 
00173 
00174 void TSP_session_init(void)
00175 {
00176   if( FALSE == X_initialized )
00177     {
00178       /* Mise a 0 de la zone memoire */
00179       memset(X_session_t, 0, TSP_MAX_CLIENT_NUMBER*sizeof(TSP_session_t));
00180       X_initialized = TRUE;
00181     }
00182 }
00183 
00184 
00185 void TSP_session_close_session_by_channel(channel_id_t channel_id)
00186 {
00187   TSP_LOCK_MUTEX(&X_session_list_mutex,);
00188 
00189   TSP_session_close_session(channel_id);
00190 
00191   TSP_UNLOCK_MUTEX(&X_session_list_mutex,);
00192 }
00193 
00194 int TSP_session_get_nb_session(void)
00195 {
00196   int client_number;
00197 
00198   TSP_LOCK_MUTEX(&X_session_list_mutex,-1);
00199   
00200   client_number = X_session_nb;
00201   
00202   TSP_UNLOCK_MUTEX(&X_session_list_mutex,-1);
00203 
00204   return client_number;
00205 }
00206 
00207 int TSP_add_session(channel_id_t* new_channel_id, GLU_handle_t glu_h)
00208 {
00209   channel_id_t channel_id = (channel_id_t)(UNDEFINED_CHANNEL_ID);
00210   
00211   TSP_sample_symbol_info_list_t symbol_list;
00212 
00213   *new_channel_id = 0;
00214         
00215   TSP_LOCK_MUTEX(&X_session_list_mutex,FALSE);
00216 
00217   /* Is there room left for the new session ? */
00218   if( X_session_nb == TSP_MAX_CLIENT_NUMBER)
00219     {
00220       STRACE_ERROR(("Max session number reached : %d", TSP_MAX_CLIENT_NUMBER));
00221       return FALSE;
00222     }
00223 
00224   
00225   /* Create a new channel Id*/
00226   channel_id = X_count_channel_id++;
00227   
00228   STRACE_DEBUG(("I've found room in X_session_t for the new session. Id in X_session_t is %d", X_session_nb));
00229   *new_channel_id = channel_id;
00230   
00231   /* The position is always X_session_nb, 'coz' any holes in array are filled during session removal 
00232    see : TSP_close_session_by_channel */
00233   X_session_t[X_session_nb].session_data = calloc(1, sizeof(TSP_session_data_t));
00234   X_session_t[X_session_nb].channel_id = *new_channel_id;
00235   TSP_CHECK_ALLOC(X_session_t[X_session_nb].session_data, FALSE);
00236   
00237   /* Intialize members */
00238   X_session_t[X_session_nb].session_data->data_link_broken = FALSE;
00239   X_session_t[X_session_nb].session_data->datapool = 0; 
00240   X_session_t[X_session_nb].session_data->glu_h = glu_h; 
00241 
00242   /* Get symbols number */
00243   if(!GLU_get_sample_symbol_info_list(glu_h,&symbol_list))
00244     {
00245       STRACE_ERROR(("Function GLU_get_sample_symbol_info_list failed"));
00246       return FALSE;
00247     }
00248     X_session_t[X_session_nb].session_data->symbols_number = symbol_list.TSP_sample_symbol_info_list_t_len; 
00249 
00250   /* OK, there's a new session*/
00251   X_session_nb++;
00252   
00253   STRACE_INFO(("New consumer connected : channel_id=%u", *new_channel_id ));
00254         
00255   TSP_UNLOCK_MUTEX(&X_session_list_mutex,FALSE);
00256 
00257   return TRUE;
00258 }
00259 
00260 
00261 void TSP_session_destroy_symbols_table_by_channel(channel_id_t channel_id)
00262 {
00263   TSP_session_t* session = 0;
00264    
00265   TSP_LOCK_MUTEX(&X_session_list_mutex,);    
00266   TSP_GET_SESSION(session, channel_id,); 
00267 
00268   TSP_session_destroy_symbols_table(session);  
00269 
00270   TSP_UNLOCK_MUTEX(&X_session_list_mutex,);
00271 
00272 }
00273 
00274 
00275 int TSP_session_create_symbols_table_by_channel(const TSP_request_sample_t* req_sample,
00276                                                 TSP_answer_sample_t* ans_sample)
00277 
00278 {
00279   int ret = FALSE;
00280   TSP_session_t* session = 0;
00281   TSP_datapool_t target_datapool = 0;    
00282 
00283   TSP_LOCK_MUTEX(&X_session_list_mutex,FALSE);
00284 
00285   TSP_GET_SESSION(session, req_sample->channel_id, FALSE)
00286 
00287   /* The functions could have been called several time, so clean up first */
00288   TSP_session_destroy_symbols_table(session);    
00289     
00290   /* Use global datapool */
00291   target_datapool = TSP_global_datapool_get_instance();
00292 
00293   /* Creating group table*/
00294   ret  = TSP_group_algo_create_symbols_table(&(req_sample->symbols),
00295                                              &(ans_sample->symbols), 
00296                                              &(session->session_data->groups),
00297                                              target_datapool);   
00298   
00299   /* Set total group number */
00300   if(ret)
00301     {
00302       ans_sample->provider_group_number = 
00303         TSP_group_algo_get_group_number(session->session_data->groups);
00304     }
00305   else
00306     {
00307       STRACE_ERROR(("Function TSP_group_algo_create_symbols_table failed"));
00308 
00309     }
00310     
00311   TSP_UNLOCK_MUTEX(&X_session_list_mutex,FALSE);
00312 
00313   return ret;
00314 }
00315 
00316 void TSP_session_create_symbols_table_by_channel_free_call(TSP_answer_sample_t* ans_sample)
00317 {
00318     TSP_group_algo_create_symbols_table_free_call(&ans_sample->symbols);
00319 }
00320 
00321 int  TSP_session_get_sample_symbol_info_list_by_channel(channel_id_t channel_id,
00322                                                         TSP_sample_symbol_info_list_t* symbol_list)
00323 {
00324 
00325   TSP_session_t* session;
00326   int ret;
00327 
00328   TSP_LOCK_MUTEX(&X_session_list_mutex,FALSE);
00329         
00330   TSP_GET_SESSION(session, channel_id, FALSE);
00331 
00332   ret = GLU_get_sample_symbol_info_list(session->session_data->glu_h, symbol_list);
00333   
00334   TSP_UNLOCK_MUTEX(&X_session_list_mutex,FALSE);
00335   
00336   return ret;
00337 
00338 }
00339 
00340 int TSP_session_send_msg_ctrl_by_channel(channel_id_t channel_id, TSP_msg_ctrl_t msg_ctrl)
00341 {
00342   TSP_session_t* session;
00343   int ret;
00344 
00345   /* The mutex can not be kept 'coz' we are going to block other sessions */
00346   /* So, be carefull : the session must not be suppressed when the send is active */
00347   TSP_LOCK_MUTEX(&X_session_list_mutex,-1);
00348   TSP_GET_SESSION(session, channel_id,-1);
00349   TSP_UNLOCK_MUTEX(&X_session_list_mutex,-1);
00350 
00351   if( (session->session_data->data_link_broken == FALSE) 
00352       &&  session->session_data->groups
00353       &&  session->session_data->sender)
00354     {
00355       if(!TSP_data_sender_send_msg_ctrl(session->session_data->sender, msg_ctrl))
00356 
00357         {
00358           STRACE_WARNING(("Data link broken for session No %d",channel_id ));
00359           session->session_data->data_link_broken = TRUE;
00360         }
00361     }
00362 
00363   ret = !(session->session_data->data_link_broken);
00364   return ret;
00365   
00366 }
00367 
00368 int TSP_session_send_data_by_channel(channel_id_t channel_id, time_stamp_t t)
00369 {
00370 
00371   TSP_session_t* session;
00372   int ret;
00373 
00374   /* The mutex can not be kept 'coz' we are going to block other sessions */
00375   /*So, warning : the session must not be suppressed when the send is active */
00376   TSP_LOCK_MUTEX(&X_session_list_mutex,-1);
00377   TSP_GET_SESSION(session, channel_id,-1);
00378   TSP_UNLOCK_MUTEX(&X_session_list_mutex,-1);
00379 
00380   if( (session->session_data->data_link_broken == FALSE) 
00381       &&  session->session_data->groups
00382       &&  session->session_data->sender)
00383     {
00384       if(!TSP_data_sender_send(session->session_data->sender, 
00385                                session->session_data->groups, 
00386                                t))
00387         {
00388           STRACE_WARNING(("Data link broken for session No %d",channel_id ));
00389           session->session_data->data_link_broken = TRUE;
00390           
00391         }
00392     }
00393   
00394   ret = !(session->session_data->data_link_broken);
00395   return ret;
00396 
00397 }
00398 
00399 void TSP_session_all_session_send_data(time_stamp_t t)
00400 {
00401   int i;
00402 
00403   TSP_LOCK_MUTEX(&X_session_list_mutex,);
00404 
00405   for( i = 0 ; i< X_session_nb ; i++)
00406     {
00407     
00408       if( X_session_t[i].session_data->groups /* The sample request was done */
00409           && X_session_t[i].session_data->sender /* The sample request init was done */
00410           && (X_session_t[i].session_data->data_link_broken == FALSE))
00411         {
00412           if(!TSP_data_sender_send(X_session_t[i].session_data->sender, 
00413                                    X_session_t[i].session_data->groups, 
00414                                    t))
00415             {
00416               STRACE_WARNING(("Data link broken for session No %d",X_session_t[i].channel_id ));
00417               X_session_t[i].session_data->data_link_broken = TRUE;               
00418             }
00419         }
00420     }
00421 
00422   TSP_UNLOCK_MUTEX(&X_session_list_mutex,);
00423 
00424 }
00425 
00426 
00427 void TSP_session_all_session_send_msg_ctrl(TSP_msg_ctrl_t msg_ctrl)
00428 {
00429   int i;
00430 
00431   TSP_LOCK_MUTEX(&X_session_list_mutex,);
00432 
00433   for( i = 0 ; i< X_session_nb ; i++)
00434     {
00435       if( X_session_t[i].session_data->groups /* The sample request was done */
00436           && X_session_t[i].session_data->sender /* The sample request init was done */
00437           && (X_session_t[i].session_data->data_link_broken == FALSE))
00438         {
00439 
00440           if(!TSP_data_sender_send_msg_ctrl(X_session_t[i].session_data->sender, msg_ctrl))
00441             {
00442               STRACE_WARNING(("Data link broken for session No %d",X_session_t[i].channel_id ));
00443               X_session_t[i].session_data->data_link_broken = TRUE;           
00444             }     
00445         }
00446     }
00447 
00448   TSP_UNLOCK_MUTEX(&X_session_list_mutex,);
00449 }
00450 
00451 
00452 int TSP_session_create_data_sender_by_channel(channel_id_t channel_id, int no_fifo)
00453 {
00454 
00455   TSP_session_t* session;
00456   int ret = TRUE;
00457   int ringbuf_size;
00458 
00459   TSP_LOCK_MUTEX(&X_session_list_mutex,FALSE);
00460         
00461   TSP_GET_SESSION(session, channel_id, FALSE);
00462 
00463   session->session_data->sender = 0;
00464 
00465   /* Calculate fifo depth */
00466   if(no_fifo)
00467     {
00468       ringbuf_size = 0;
00469     }
00470   else
00471     {
00472       /* There is one single data pool, ask for a ringbuf to the socket layer */
00473       /* We calculate it with the server frequency */
00474       double base_frequency = GLU_get_base_frequency();
00475        if( base_frequency > 0 )
00476         {
00477           ringbuf_size = TSP_STREAM_SENDER_RINGBUF_SIZE * base_frequency;
00478           
00479           STRACE_DEBUG(("Stream sender ringbuf size will be : %d items (i.e. %d secondes)",
00480                        ringbuf_size,
00481                        TSP_STREAM_SENDER_RINGBUF_SIZE));
00482         }
00483       else
00484         {
00485           STRACE_ERROR(("GLU return base frequency = %f", base_frequency));
00486           ret = FALSE;
00487         }
00488     }
00489 
00490   /*--------------------*/
00491   /* Create data sender */
00492   /*--------------------*/
00493   if(ret)
00494     {
00495       int max_group_size = TSP_group_algo_get_biggest_group_size(session->session_data->groups);
00496       session->session_data->sender = TSP_data_sender_create(ringbuf_size, max_group_size);      
00497 
00498       if(0 != session->session_data->sender)
00499         {
00500           /* If there's no fifo, we must start a new thread per client, because there's one
00501              datapool per client */
00502           if (no_fifo)
00503             {
00504               ret = TRUE; /*No more ... TSP_local_datapool_start_thread(session->session_data->datapool);*/
00505               if(!ret)
00506                 {
00507                   STRACE_ERROR(("Unable to launch local datapool worker thread"));
00508                 }
00509             }
00510         }
00511       else
00512         {
00513           ret = FALSE;
00514           STRACE_ERROR(("function TSP_data_sender_create failed"));
00515       
00516         }
00517     }
00518   
00519   TSP_UNLOCK_MUTEX(&X_session_list_mutex,FALSE);
00520   
00521   return ret;
00522 
00523 }
00524 
00525 int TSP_session_destroy_data_sender_by_channel(channel_id_t channel_id, int stop_local_thread)
00526 {
00527   TSP_session_t* session;
00528   int ret = TRUE;
00529 
00530   TSP_LOCK_MUTEX(&X_session_list_mutex,FALSE);
00531         
00532   TSP_GET_SESSION(session, channel_id, FALSE);
00533 
00534   /* Stop the session */
00535   TSP_data_sender_stop(session->session_data->sender);
00536 
00537   /* For a pasive server we must wait for the session thread to end */
00538   if(stop_local_thread)
00539     {
00540       /*TSP_local_datapool_wait_for_end_thread(session->session_data->datapool);*/
00541     }
00542   
00543   TSP_data_sender_destroy(session->session_data->sender);
00544   session->session_data->sender = 0;
00545 
00546   TSP_UNLOCK_MUTEX(&X_session_list_mutex,FALSE);
00547 
00548   return ret;
00549 
00550 
00551 }
00552 
00553 const char* TSP_session_get_data_address_string_by_channel(channel_id_t channel_id)
00554 {
00555 
00556   TSP_session_t* session;
00557   const char* data_address;
00558 
00559   TSP_LOCK_MUTEX(&X_session_list_mutex,FALSE);
00560 
00561         
00562   TSP_GET_SESSION(session, channel_id, FALSE);
00563 
00564   data_address = TSP_data_sender_get_data_address_string(session->session_data->sender);
00565     
00566   TSP_UNLOCK_MUTEX(&X_session_list_mutex,FALSE);
00567 
00568   STRACE_IO(("-->OUT data_address='%s'",data_address ));
00569 
00570     
00571   return data_address;
00572 
00573 }
00574 
00575 
00576 int TSP_session_is_consumer_connected_by_channel(channel_id_t channel_id)
00577 {
00578   TSP_session_t* session;
00579   int consumer_is_connected;
00580     
00581   TSP_LOCK_MUTEX(&X_session_list_mutex,FALSE);
00582   TSP_GET_SESSION(session, channel_id, FALSE);
00583 
00584   consumer_is_connected = TSP_data_sender_is_consumer_connected(session->session_data->sender);
00585 
00586   TSP_UNLOCK_MUTEX(&X_session_list_mutex,FALSE);
00587 
00588   return consumer_is_connected;
00589 
00590 }
00591 
00592 
00593 int TSP_session_get_symbols_global_index_by_channel(channel_id_t channel_id,
00594                                                    TSP_sample_symbol_info_list_t* symbol_list)
00595 {
00596   TSP_session_t* session;
00597   TSP_sample_symbol_info_list_t origin_sym_list;
00598   int i,j;
00599   int ret = TRUE;
00600     
00601   TSP_LOCK_MUTEX(&X_session_list_mutex,FALSE);
00602   TSP_GET_SESSION(session, channel_id, FALSE);
00603 
00604   /* Get the original GLU symbol list */
00605    if(!GLU_get_sample_symbol_info_list(session->session_data->glu_h, &origin_sym_list))
00606     {
00607       STRACE_ERROR(("Function GLU_get_sample_symbol_info_list failed"));
00608       return FALSE;
00609     }
00610 
00611    /* For each requested symbols, check by name, and find the provider global index */
00612 
00613    for( i = 0 ; i < symbol_list->TSP_sample_symbol_info_list_t_len ; i++)
00614      {
00615        int found = FALSE;
00616        TSP_sample_symbol_info_t* looked_for = &(symbol_list->TSP_sample_symbol_info_list_t_val[i]);
00617        
00618        for( j = 0 ; j < origin_sym_list.TSP_sample_symbol_info_list_t_len ; j++)
00619          {
00620            TSP_sample_symbol_info_t* compared = &(origin_sym_list.TSP_sample_symbol_info_list_t_val[j]);
00621            if(!strcmp(looked_for->name, compared->name))
00622              {
00623                found = TRUE;
00624                looked_for->provider_global_index = compared->provider_global_index;
00625              }
00626            if(found) break;
00627          }
00628        if(!found)
00629          {
00630            ret = FALSE;
00631            STRACE_INFO(("Unable to find symbol '%s'",  looked_for->name));
00632            break;          
00633          }
00634      }
00635    
00636   TSP_UNLOCK_MUTEX(&X_session_list_mutex,FALSE);
00637 
00638   return ret;
00639 
00640 }
00641 
00642 int TSP_session_get_garbage_session(channel_id_t* channel_id)
00643 {
00644   int i;
00645   int found = FALSE;
00646         
00647   TSP_LOCK_MUTEX(&X_session_list_mutex,FALSE);
00648   
00649   for( i = 0 ;  i < X_session_nb ; i++)
00650     {
00651       /* FIXME : here the criteria for a dirty session is 'the data
00652          link is broken', but there are plenty of criteria that should be
00653          added (like 'timeout on idle consumer', and so on) */
00654       if( X_session_t[i].session_data->data_link_broken == TRUE )
00655         {
00656           found = TRUE;
00657           *channel_id = X_session_t[i].channel_id;
00658           break;
00659         }
00660     }
00661         
00662   TSP_UNLOCK_MUTEX(&X_session_list_mutex,FALSE);
00663 
00664   return found ;
00665 }
Framework Home Page.

Beware !! TSP wave is coming...