TSP: The Transport Sample Protocol



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

tsp_data_sender.c

Go to the documentation of this file.
00001 
00039 #include "tsp_sys_headers.h"
00040 #include <rpc/types.h>
00041 #include <rpc/xdr.h>
00042 
00043  
00044 #include "tsp_data_sender.h"
00045 
00046 #include "tsp_datastruct.h"
00047 
00048 #include "tsp_group_algo.h"
00049 #include "tsp_group_algo_data.h"
00050 
00051 #include "tsp_stream_sender.h"
00052 #include "tsp_const_def.h"
00053 
00054 #define TSP_XDR_BUF_SIZE 8192
00055 
00056 struct TSP_struct_data_sender_t
00057 {
00059   TSP_stream_sender_t stream_sender;  
00060 
00062   int use_fifo;
00063 
00065   TSP_stream_sender_ringbuf_t* out_fifo;
00066 
00068   TSP_stream_sender_item_t* out_item;
00069 
00071   int buffer_size;
00072 
00074   int fifo_full;
00075 
00076 
00077   
00078 };
00079 
00080 typedef struct TSP_struct_data_sender_t TSP_struct_data_sender_t;
00081 
00082 static u_int TSP_data_sender_double_encoder(void* v_double,  char* out_buf, u_int size)
00083 {
00084 
00085 #ifndef TSP_NO_XDR_ENCODE
00086 
00087   XDR xhandle;
00088    
00089   xdrmem_create(&xhandle, out_buf,  size, XDR_ENCODE);
00090   if( xdr_double(&xhandle, (double*)v_double) != TRUE)
00091     {
00092       STRACE_ERROR(("Function xdr_double failed"));
00093       return 0;
00094     }
00095   else
00096     {
00097       return xdr_getpos(&xhandle);
00098     }
00099 
00100 #else
00101 
00102   if(size < sizeof(double) )
00103     {
00104       STRACE_ERROR(("buffer is too small"));
00105       return 0;
00106     }
00107   else
00108     {
00109       *(uint64_t*)out_buf = TSP_ENCODE_DOUBLE_TO_UINT64(v_double);
00110       return (u_int)sizeof(double);
00111     }
00112 
00113 #endif /*TSP_NO_XDR_ENCODE*/
00114 
00115 }
00116 
00117 TSP_data_sender_t TSP_data_sender_create(int fifo_size, int max_group_size)
00118 {
00119     
00120   TSP_struct_data_sender_t* sender;
00121     
00122   STRACE_IO(("-->IN"));
00123 
00124   sender = (TSP_struct_data_sender_t*)calloc(1, sizeof(TSP_struct_data_sender_t));
00125   TSP_CHECK_ALLOC(sender, 0);
00126 
00127   /* init */
00128   sender->fifo_full = FALSE;
00129   sender->buffer_size = TSP_DATA_STREAM_MAX_BUFFER_SIZE(max_group_size);
00130 
00131   /* Create the sender stream with its fifo size*/
00132   sender->stream_sender = (TSP_data_sender_t)TSP_stream_sender_create(fifo_size, sender->buffer_size);
00133   if(sender->stream_sender)
00134     {      
00135       /* Check if the user wants any fifo */
00136       sender->use_fifo = fifo_size > 0 ? TRUE : FALSE ;
00137       if(sender->use_fifo)
00138         {
00139           sender->out_item = 0;
00140           sender->out_fifo = TSP_stream_sender_get_ringbuf(sender->stream_sender);
00141           assert( sender->out_fifo);
00142         }
00143       else
00144         {
00145           sender->out_fifo = 0;
00146           sender->out_item = TSP_stream_sender_get_buffer(sender->stream_sender);
00147           assert(sender->out_item);
00148          
00149         }
00150     }
00151   else
00152     {
00153       STRACE_ERROR(("Function TSP_stream_sender_create failed"));
00154       free(sender);
00155       sender = 0;
00156     }
00157   
00158 
00159     
00160   STRACE_IO(("-->OUT"));
00161 
00162     
00163   return sender;
00164 
00165 }
00166 
00167 void TSP_data_sender_destroy(TSP_data_sender_t sender)
00168 {
00169 
00170   TSP_struct_data_sender_t* data_sender = (TSP_struct_data_sender_t*)sender;
00171 
00172   STRACE_IO(("-->IN"));
00173   
00174   TSP_stream_sender_destroy(data_sender->stream_sender);
00175   free(data_sender);
00176 
00177   STRACE_IO(("-->OUT"));
00178 }
00179 
00180 void TSP_data_sender_stop(TSP_data_sender_t sender)
00181 {
00182 
00183   TSP_struct_data_sender_t* data_sender = (TSP_struct_data_sender_t*)sender;
00184 
00185   STRACE_IO(("-->IN"));
00186   
00187   TSP_stream_sender_stop(data_sender->stream_sender);
00188 
00189   STRACE_IO(("-->OUT"));
00190 }
00191 
00192 
00193 
00194 static TSP_stream_sender_item_t* TSP_data_sender_get_out_item(TSP_struct_data_sender_t* data_sender)
00195 {
00196 
00197   TSP_stream_sender_item_t* ret_item = 0;
00198   if(data_sender->use_fifo)
00199     {
00200       /* Check if fifo was full last time */
00201       if(!(data_sender->fifo_full))
00202         {
00203           /* Was not full. We try to take an element */
00204           ret_item = RINGBUF_PTR_PUTBYADDR(data_sender->out_fifo);
00205           if(!ret_item)
00206             {
00207               /* Arg! It is is full now */
00208               data_sender->fifo_full = TRUE;
00209             }
00210         }
00211       else
00212         {
00213           /* FIFO was full. We must wait for two available items :
00214              one for the error message, one for the next item */
00215           if( RINGBUF_PTR_ITEMS_LEFT(data_sender->out_fifo) > 2 )
00216             {
00217 
00218               /* not full anymore */
00219               data_sender->fifo_full = FALSE; 
00220 
00221               /* First, add the error message :  we do some recursive magic here ;),
00222                  there must not be any infinite loop...*/
00223               TSP_data_sender_send_msg_ctrl(data_sender,  TSP_MSG_CTRL_CONSUMER_DATA_LOST);
00224 
00225               /* And now there must be one item left */
00226               ret_item = RINGBUF_PTR_PUTBYADDR(data_sender->out_fifo);
00227               assert(ret_item);
00228             }
00229           else
00230             {
00231               data_sender->fifo_full = TRUE;      
00232             }
00233           
00234         }
00235     }
00236   else  /* not ringbuffer, use direct buffer */
00237     {
00238       ret_item = data_sender->out_item;
00239     }
00240 
00241   return ret_item;
00242 }
00243 
00244 static int TSP_data_sender_to_stream_sender(TSP_struct_data_sender_t* data_sender,
00245                                                    TSP_stream_sender_item_t* tosend)
00246 {
00247 
00248   /* First check for a valid connection */
00249   int ret = TSP_stream_sender_is_connection_ok(data_sender->stream_sender);
00250   if(ret)
00251     {
00252       if(data_sender->use_fifo)
00253         {
00254           /* we use a fifo */
00255           RINGBUF_PTR_PUTBYADDR_COMMIT(data_sender->out_fifo);
00256         }
00257       else
00258         {            
00259           /* no fifo. send data now */
00260           if(!TSP_stream_sender_send(data_sender->stream_sender,
00261                                      TSP_STREAM_SENDER_ITEM_BUF(tosend),
00262                                      tosend->len) )
00263             {
00264               STRACE_WARNING(("Function TSP_stream_sender_send failed "));
00265               ret = FALSE;
00266             }  
00267         }
00268     }
00269   return ret;
00270 }
00271 
00272 
00280 int TSP_data_sender_send_msg_ctrl(TSP_data_sender_t sender, TSP_msg_ctrl_t msg_ctrl)
00281 {
00282   TSP_struct_data_sender_t* data_sender = (TSP_struct_data_sender_t*)sender;
00283   int* buf_int = 0;
00284   int tsp_reserved_group;
00285   int ret = TRUE;
00286   TSP_stream_sender_item_t* tosend;
00287 
00288   /*---------------------------*/
00289   /* Traduce enum */
00290   switch(msg_ctrl)
00291     {
00292     case TSP_MSG_CTRL_EOF :
00293       tsp_reserved_group = TSP_RESERVED_GROUP_EOF;
00294       break;
00295     case TSP_MSG_CTRL_RECONF :
00296       tsp_reserved_group = TSP_RESERVED_GROUP_RECONF;
00297       break;
00298     case TSP_MSG_CTRL_GLU_DATA_LOST :
00299       tsp_reserved_group = TSP_RESERVED_GROUP_GLU_DATA_LOST;
00300       break;
00301     case TSP_MSG_CTRL_CONSUMER_DATA_LOST :
00302       tsp_reserved_group = TSP_RESERVED_GROUP_CONSUMER_DATA_LOST;
00303       break;
00304     default:
00305       STRACE_ERROR(("We should not be there..."));
00306       assert(0);
00307       return FALSE;
00308     }
00309 
00310   /* get out buffer if it is available */
00311   tosend = TSP_data_sender_get_out_item(data_sender);
00312     
00313   /* If it is not available, try net time */
00314 
00315   /* FIXME : uses packet format as described in the protocol spec */
00316   if(tosend)
00317     {
00318       buf_int = (int*)(TSP_STREAM_SENDER_ITEM_BUF(tosend));
00319       buf_int[0] = TSP_ENCODE_INT(-1); /* Dummy time stamp */
00320       buf_int[1] = TSP_ENCODE_INT(tsp_reserved_group);
00321   
00322       tosend->len = sizeof(int)*2;
00323 
00324       /* We send it */
00325       ret = TSP_data_sender_to_stream_sender(data_sender, tosend);
00326     }
00327   
00328   STRACE_IO(("-->OUT"));
00329   
00330   return ret;
00331  
00332 }
00333 
00341 int TSP_data_sender_send(TSP_data_sender_t _sender, TSP_groups_t _groups, time_stamp_t time_stamp) 
00342 {    
00343 
00344   TSP_struct_data_sender_t* data_sender = (TSP_struct_data_sender_t*)_sender;
00345   TSP_algo_table_t* groups_table = (TSP_algo_table_t*) _groups;
00346 
00347   char* buf_main;
00348   int* buf_int;
00349   char* buf_char;    
00350   TSP_algo_group_t* group;
00351   int group_index;
00352   int i;
00353   int ret = TRUE;
00354   int size;
00355   TSP_stream_sender_item_t* tosend;
00356 
00357   STRACE_IO(("-->IN"));
00358 
00359   group_index = time_stamp % groups_table->table_len;
00360   group = &(groups_table->groups[group_index]);
00361 
00362   /* get out buffer if it is available */
00363   tosend = TSP_data_sender_get_out_item(data_sender);
00364     
00365   /* If it is not available, try net time */
00366 
00367   /* FIXME : uses packet format as described in the protocol spec */
00368   if(tosend)
00369     {
00370       buf_main = TSP_STREAM_SENDER_ITEM_BUF(tosend);
00371       buf_int = (int*)(buf_main);
00372       *( buf_int++ ) = TSP_ENCODE_INT(time_stamp);
00373       *( buf_int++ ) = TSP_ENCODE_INT(group_index);
00374       buf_char = (char*)(buf_int);
00375 
00376   
00377       if( group->group_len > 0)
00378         {
00379           for( i = 0 ; i < group->group_len ; i++)
00380             {
00381               /* FIXME : gerer tous les types */
00382               /* avec la fonction d'encodage */
00383               STRACE_DEBUG(("Gr=%d V=%f", group_index, *(double*)(group->items[i].data)));
00384 
00385               /* Call encode function */
00386               assert(group->items[i].data_encoder);
00387               size = (group->items[i].data_encoder)(group->items[i].data,
00388                                                     buf_char,
00389                                                     data_sender->buffer_size - ( buf_char - buf_main) );
00390               if ( 0 == size )
00391                 {
00392                   STRACE_ERROR(("data_encoder failed"));            
00393                   ret = FALSE;
00394                   break;
00395                 }
00396           
00397               buf_char += size;
00398 
00399             } /*for*/
00400 
00401           /* We send it */
00402           tosend->len = buf_char - buf_main;
00403           ret = TSP_data_sender_to_stream_sender(data_sender, tosend);
00404         }
00405     }
00406     
00407   STRACE_IO(("-->OUT"));
00408   return ret;        
00409 }
00410 
00411 const char* TSP_data_sender_get_data_address_string(TSP_data_sender_t sender)
00412 {
00413   TSP_struct_data_sender_t* data_sender = (TSP_struct_data_sender_t*)sender;
00414   return TSP_stream_sender_get_data_address_string(data_sender->stream_sender);
00415 }
00416 
00417 TSP_data_encoder_t TSP_data_sender_get_double_encoder(void)
00418 {
00419   return TSP_data_sender_double_encoder;
00420 }
00421 
00422 
00423 
00424 int TSP_data_sender_is_consumer_connected(TSP_data_sender_t sender)
00425 {
00426    TSP_struct_data_sender_t* data_sender = (TSP_struct_data_sender_t*)sender;
00427 
00428    return TSP_stream_sender_is_client_connected(data_sender->stream_sender);
00429 }
Framework Home Page.

Beware !! TSP wave is coming...