TSP: The Transport Sample Protocol



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

bb_core.c

Go to the documentation of this file.
00001 
00037 #include <string.h>
00038 #include <stdlib.h>
00039 #include <sys/types.h>
00040 #include <sys/mman.h>
00041 #include <fcntl.h>
00042 #include <sys/stat.h>
00043 #include <errno.h>
00044 #include <unistd.h>
00045 #include <assert.h>
00046 #include <ctype.h>
00047 
00048 #include <sys/ipc.h>
00049 #include <sys/shm.h>
00050 #include <sys/sem.h>
00051 #include <sys/msg.h>
00052 
00053 #include <bb_core.h>
00054 #include <bb_utils.h>
00055 #include "tsp_abs_types.h"
00056 
00060 static const char* E_BB_2STRING[] = {"NoAType 0",
00061                                      "double", 
00062                                      "float", 
00063                                      "int8_t",
00064                                      "int16_t",
00065                                      "int32_t",
00066                                      "int64_t",
00067                                      "uint8_t",
00068                                      "uint16_t",
00069                                      "uint32_t",
00070                                      "uint64_t",
00071                                      "char",
00072                                      "uchar",
00073                                      "UserType",
00074                                      "NotAType end"};
00075 
00076 int32_t 
00077 bb_size(const int32_t n_data, const int32_t data_size) {
00078   /* The SHM segment os sized to:
00079    *  BB structure size +
00080    *  data descriptor array size +
00081    *  data zone size
00082    */
00083   return (sizeof(S_BB_T) + 
00084     sizeof(S_BB_DATADESC_T)*n_data +
00085     sizeof(char)*data_size);
00086 } /* end of bb_size */
00087 
00088 int32_t 
00089 bb_find(volatile S_BB_T* bb, const char* var_name) {
00090   
00091   int32_t retval;  
00092   int32_t i;
00093     
00094   retval = -1;
00095   assert(bb);
00096   for (i=0; i< bb->n_data;++i) {
00097     if (!strncmp(var_name,(bb_data_desc(bb)[i]).name,VARNAME_MAX_SIZE+1)) {
00098       retval = i;
00099       break;
00100     }
00101   } /* end for */
00102   
00103   return retval;
00104 } /* end of  bb_find */
00105 
00106 S_BB_DATADESC_T* 
00107 bb_data_desc(volatile S_BB_T* bb) {
00108   
00109   S_BB_DATADESC_T* retval;  
00110   
00111   retval = NULL;
00112   assert(bb);
00113   retval = (S_BB_DATADESC_T*) ((char*)(bb) + bb->data_desc_offset);
00114   
00115   return retval;
00116 } /* end of bb_data_desc */
00117 
00118 void* 
00119 bb_data(volatile S_BB_T* bb) {
00120   
00121   void* retval;  
00122   
00123   retval = NULL;
00124   assert(bb);
00125   retval = (char*)(bb) + bb->data_offset;
00126   
00127   return retval;
00128 } /* end of bb_data_desc */
00129 
00130 double
00131 bb_double_of(void* value, E_BB_TYPE_T bbtype) {
00132 
00133   double retval;
00134 
00135   retval = 0.0;
00136 
00137   switch (bbtype) {
00138   case E_BB_DOUBLE: 
00139     retval = *((double*)value);
00140     break;
00141   case E_BB_FLOAT:
00142     retval = *((float*)value);
00143     break;
00144   case E_BB_INT8:
00145     retval = *((int8_t*)value);
00146     break; 
00147   case E_BB_INT16:
00148     retval = *((int16_t*)value);
00149     break; 
00150   case E_BB_INT32:
00151     retval = *((int32_t*)value);
00152     break; 
00153   case E_BB_INT64:
00154     retval = *((int64_t*)value);
00155     break; 
00156   case E_BB_UINT8:
00157     retval = *((uint8_t*)value);
00158     break;  
00159   case E_BB_UINT16:
00160     retval = *((uint16_t*)value);
00161     break;
00162   case E_BB_UINT32:
00163     retval = *((uint32_t*)value);
00164     break;      
00165   case E_BB_UINT64:
00166     retval = *((uint64_t*)value);
00167     break;      
00168   case E_BB_CHAR:
00169   case E_BB_UCHAR:
00170   case E_BB_USER:
00171     /* FIXME could not convert set 0.0 */
00172     retval = 0.0;
00173     break; 
00174   default:
00175     retval = 0.0;
00176     break;
00177   }
00178 
00179   return retval;
00180 } /* end of bb_double_of */
00181 
00182 int32_t 
00183 bb_data_initialise(volatile S_BB_T* bb, S_BB_DATADESC_T* data_desc,void* default_value) {
00184   
00185   int32_t retval;  
00186   char* data;
00187   int32_t i;
00188   
00189   assert(data_desc);
00190   /* on recupere l'adresse de la donnee dans le BB */
00191   data = (char*)bb_data(bb) + data_desc->data_offset;
00192   retval = E_OK;
00193   for (i=0; i< data_desc->dimension; ++i) {
00194     switch (data_desc->type) {
00195     case E_BB_DOUBLE: 
00196       ((double*) data)[i] = default_value ? *((double *) default_value) : 0.0;
00197       break;
00198     case E_BB_FLOAT:
00199       ((float*) data)[i] = default_value ? *((float *) default_value) : 0.0;
00200       break;
00201     case E_BB_INT16:
00202       ((int16_t*) data)[i] = default_value ? *((short *) default_value) : 0;
00203       break; 
00204     case E_BB_INT32:
00205       ((int32_t*) data)[i] = default_value ? *((int *) default_value) : 0;
00206       break; 
00207     case E_BB_INT64:
00208       ((int64_t*) data)[i] = default_value ? *((long *) default_value) : 0;
00209       break; 
00210     case E_BB_UINT16:
00211       ((uint16_t*) data)[i] = default_value ? *((unsigned short *) default_value) : 0;
00212       break;
00213     case E_BB_UINT32:
00214       ((uint32_t*) data)[i] = default_value ? *((unsigned int *) default_value) : 0;
00215       break;    
00216     case E_BB_UINT64:
00217       ((uint64_t*) data)[i] = default_value ? *((unsigned long *) default_value) : 0;
00218       break;    
00219     case E_BB_CHAR:
00220       ((char *) data)[i] = default_value ? *((char *) default_value) : '\0';
00221       break;
00222     case E_BB_USER:
00223       if (NULL == default_value) {
00224         memset(data + (data_desc->type)*i,0,data_desc->type);
00225       } else {
00226         memcpy(data + (data_desc->type)*i,default_value,data_desc->type);
00227       }
00228       break; 
00229     default:
00230       retval = E_NOK;
00231       break;
00232     }
00233   } 
00234   
00235   return retval;
00236 } /* end of bb_data_initialise */
00237 
00238 int32_t
00239 bb_value_write(volatile S_BB_T* bb, S_BB_DATADESC_T data_desc,const char* value, int32_t idx) {
00240 
00241   char* data;
00242   int retval;
00243   int hexval;
00244   assert(bb);
00245   
00246   if ((NULL != strstr(value,"0x")) | 
00247       (NULL != strstr(value,"0X"))
00248       ) {
00249     hexval = 1;
00250   } else {
00251     hexval = 0;
00252   }
00253 
00254   /* on recupere l'adresse de la donnee dans le BB */
00255   data = (char*)bb_data(bb) + data_desc.data_offset;
00256   switch (data_desc.type) {
00257     case E_BB_DOUBLE: 
00258       ((double *)data)[idx] = atof(value);
00259       break;
00260     case E_BB_FLOAT:
00261       ((float *)data)[idx] = atof(value);
00262       break;
00263     case E_BB_INT16:
00264       ((int16_t*)data)[idx] = strtol(value,(char **)NULL,hexval ? 16 : 10);
00265       break; 
00266     case E_BB_INT32:
00267       ((int32_t*)data)[idx] = strtol(value,(char **)NULL,hexval ? 16 : 10);
00268       break; 
00269     case E_BB_INT64:
00270       ((int64_t*)data)[idx] = strtoll(value,(char **)NULL,hexval ? 16 : 10);
00271       break; 
00272     case E_BB_UINT16:
00273       ((uint16_t*)data)[idx] = strtoul(value,(char **)NULL,hexval ? 16 : 10);
00274       break;
00275     case E_BB_UINT32:
00276       ((uint32_t*)data)[idx] = strtoul(value,(char **)NULL,hexval ? 16 : 10);
00277       break;    
00278     case E_BB_UINT64:
00279       ((uint64_t*)data)[idx] = strtoull(value,(char **)NULL,hexval ? 16 : 10);
00280       break;    
00281     case E_BB_CHAR:
00282       retval = E_NOK;
00283       break;
00284     case E_BB_USER:
00285       retval = E_NOK;
00286       break; 
00287     default:
00288       retval = E_NOK;
00289       break;
00290     }
00291   return retval;
00292 }
00293 
00294 int32_t
00295 bb_data_header_print(S_BB_DATADESC_T data_desc, FILE* pf, int32_t idx) {
00296 
00297   fprintf(pf,"---------- < %s > ----------\n",data_desc.name);
00298   fprintf(pf,"  type        = %d  (%s)\n",data_desc.type,E_BB_2STRING[data_desc.type]);
00299   fprintf(pf,"  dimension   = %d  \n",data_desc.dimension);
00300   fprintf(pf,"  type_size   = %d  \n",data_desc.type_size);
00301   fprintf(pf,"  data_offset = %ld \n",data_desc.data_offset);
00302   if (idx>=0) {
00303     fprintf(pf,"  value[%d] = ",idx);
00304   } else {
00305     fprintf(pf,"  value = ");
00306   }
00307   if (data_desc.dimension > 1) {
00308     fprintf(pf," [ ");
00309   } 
00310   if (idx>=0) {
00311     fprintf(pf,"... ");
00312   }
00313   return 0;
00314 } /* end of bb_data_header_print */
00315 
00316 int32_t
00317 bb_data_footer_print(S_BB_DATADESC_T data_desc, FILE* pf, int32_t idx) {
00318 
00319   if (idx>=0) {
00320     fprintf(pf,"... ");
00321   }  
00322   if (data_desc.dimension > 1) {
00323     fprintf(pf,"]");
00324   }  
00325   fprintf(pf,"\n");    
00326   fprintf(pf,"---------- ---------- ----------\n");
00327 
00328   return 0;
00329 } /* end of bb_data_footer_print */
00330 
00331 int32_t 
00332 bb_value_print(volatile S_BB_T* bb, S_BB_DATADESC_T data_desc, FILE* pf, int32_t idx) {
00333   
00334   int32_t i,j,ibeg,iend;
00335   char* data;
00336   assert(bb);
00337   /* on recupere l'adresse de la donnee dans le BB */
00338   data = (char*)bb_data(bb) + data_desc.data_offset;
00339   
00340   if (idx>=0) {
00341     ibeg=idx;
00342     iend=idx+1;
00343   } else {
00344     ibeg=0;
00345     iend=data_desc.dimension;
00346   }
00347 
00348   for (i=ibeg; i< iend; ++i) {
00349     
00350     switch (data_desc.type) {
00351     case E_BB_DOUBLE: 
00352       fprintf(pf,"%1.16f ",((double*) data)[i]);
00353       break;
00354     case E_BB_FLOAT:
00355       fprintf(pf,"%f ",((float*) data)[i]);
00356       break;
00357     case E_BB_INT16:
00358       fprintf(pf,"%d ",((int16_t*) data)[i]);
00359       break; 
00360     case E_BB_INT32:
00361       fprintf(pf,"%d ",((int32_t*) data)[i]);
00362       break; 
00363     case E_BB_INT64:
00364       fprintf(pf,"%lld ",((int64_t*) data)[i]);
00365       break; 
00366     case E_BB_UINT16:
00367       fprintf(pf,"0x%x ",((uint16_t*) data)[i]);
00368       break;
00369     case E_BB_UINT32:
00370       fprintf(pf,"0x%x ",((uint32_t*) data)[i]);
00371       break;    
00372     case E_BB_UINT64:
00373       fprintf(pf,"0x%llx ",((uint64_t*) data)[i]);
00374       break;    
00375     case E_BB_CHAR:
00376       fprintf(pf,"0x%02x<%c> ",((char*) data)[i],
00377               isprint(((char*) data)[i]) ? ((char*) data)[i] : '?');
00378       break;
00379     case E_BB_USER:
00380       for (j=0; j<data_desc.type_size; ++j) {
00381         fprintf(pf,"0x%02x ",((uint8_t*) data)[i*data_desc.type_size+j]);
00382       }
00383       break; 
00384     default:
00385       fprintf(pf,"0x%x ",((char*) data)[i]);
00386       break;
00387     }
00388   } 
00389   return 0;
00390 } /* end of bb_value_print */
00391 
00392 int32_t 
00393 bb_data_print(volatile S_BB_T* bb, S_BB_DATADESC_T data_desc, FILE* pf) {
00394 
00395   bb_data_header_print(data_desc,pf,-1);
00396   bb_value_print(bb,data_desc,pf,-1);
00397   bb_data_footer_print(data_desc,pf,-1);
00398   return E_OK;
00399 } /* end of bb_data_print */
00400 
00401 int32_t 
00402 bb_create(S_BB_T** bb, 
00403                const char* pc_bb_name,
00404                int32_t n_data,
00405                int32_t data_size) {
00406 
00407   
00408   int32_t retcode;
00409   char* name_shm;
00410   char* name_sem;
00411   char* name_msg;
00412   int32_t  fd_shm;
00413   int32_t  mmap_size;
00414   char syserr[MAX_SYSMSG_SIZE];
00415   union semun u_sem_ctrl;
00416   struct sembuf s_semop;
00417   
00418   assert(bb);
00419   retcode = E_OK;  
00420   name_shm = bb_utils_build_shm_name(pc_bb_name);
00421   name_sem = NULL;
00422   name_msg = NULL;
00423   bb_logMsg(BB_LOG_INFO,"BlackBoard::bb_create", 
00424               "Create BB <%s>.",pc_bb_name);
00425   fd_shm      = 0;
00426   mmap_size = 0;
00427 
00428   /* open+create du segment SHM SysV */
00429   if (name_shm!=NULL) {
00430     /* On dimensionne le segment shm a
00431      * la taille d'une structure de BB +
00432      * la taille du tableau descripteur de donnee +
00433      * la taille de la zone de donnee
00434      */
00435     mmap_size = bb_size(n_data,data_size);    
00436     fd_shm = shmget(bb_utils_ntok(name_shm), mmap_size, IPC_CREAT|IPC_EXCL|BB_SHM_ACCESS_RIGHT);        
00437   } else {
00438     retcode = E_NOK;
00439   }
00440   if((retcode==E_OK) && (-1==fd_shm)) {
00441     strncpy(syserr,strerror(errno),MAX_SYSMSG_SIZE);
00442     bb_logMsg(BB_LOG_SEVERE,"BlackBoard::bb_create", 
00443                 "Cannot open shm segment <%s key = 0x%x> (%s)",
00444                 name_shm, bb_utils_ntok(name_shm), syserr);
00445     retcode = E_NOK; 
00446   }
00447 
00448   if (E_OK == retcode) {
00449     *bb = (S_BB_T*) shmat(fd_shm,NULL,0);
00450   }
00451 
00452   if ((E_OK == retcode) && ((void *)-1 == *bb)) {
00453     strncpy(syserr,strerror(errno),MAX_SYSMSG_SIZE);
00454     bb_logMsg(BB_LOG_SEVERE,"BlackBoard::bb_create", 
00455                 "Cannot attach shm segment (%s)",syserr);
00456     retcode = E_NOK; 
00457   } 
00458   /* On initialise la structure comme il se doit */
00459   if (E_OK == retcode) {
00460     /* RAZ de la mémoire allouee */
00461     memset(*bb,0,mmap_size);        
00462     strncpy((*bb)->name,pc_bb_name,BB_NAME_MAX_SIZE+1);
00463     (*bb)->max_data_desc_size = n_data;
00464     (*bb)->data_desc_offset = sizeof(S_BB_T);
00465     
00466     (*bb)->n_data = 0;
00467     (*bb)->max_data_size = data_size;
00468     (*bb)->data_offset = (*bb)->data_desc_offset + 
00469                             ((*bb)->max_data_desc_size)*sizeof(S_BB_DATADESC_T);    
00470     (*bb)->data_free_offset = 0;  
00471     (*bb)->destroyed = 0;
00472   }
00473   /* On initialise la structure comme il se doit */
00474 
00475   /* Initialisation du semaphore d'acces au BB */
00476   if (E_OK == retcode) {
00477     name_sem = bb_utils_build_sem_name((*bb)->name);
00478     (*bb)->semid = semget(bb_utils_ntok(name_sem),1,
00479                                IPC_CREAT|IPC_EXCL|BB_SEM_ACCESS_RIGHT);
00480     
00481     if (-1==((*bb)->semid)) {
00482       strncpy(syserr,strerror(errno),MAX_SYSMSG_SIZE);
00483       bb_logMsg(BB_LOG_SEVERE,"BlackBoard::bb_create", 
00484                 "Cannot create semaphore <%s key = 0x%x> (%s)",
00485                 name_sem, bb_utils_ntok(name_sem), syserr);
00486       retcode = E_NOK; 
00487     } else {
00488       u_sem_ctrl.val = 2;
00489       if (-1 == semctl((*bb)->semid,0,SETVAL,u_sem_ctrl)) {
00490         strncpy(syserr,strerror(errno),MAX_SYSMSG_SIZE);
00491         bb_logMsg(BB_LOG_SEVERE,"BlackBoard::bb_create", 
00492                     "Cannot initialise semaphore <%s key = 0x%x> (%s)",
00493                     name_sem, bb_utils_ntok(name_sem), syserr);
00494         retcode = E_NOK;
00495       }
00496     }
00497     /* appeler 1 fois semop pour eviter
00498      * les races conditions entre le createur
00499      * du sémaphore et les clients (cf UNPV2 pages 284--285)
00500      */
00501     if (E_OK == retcode) {
00502       s_semop.sem_num = 0; 
00503       s_semop.sem_op  = -1; 
00504       s_semop.sem_flg = 0; 
00505       semop((*bb)->semid,&s_semop,1);
00506     }    
00507     free(name_sem);
00508 
00509     /* Initialisation de la queue de message liee au BB */
00510     if (E_OK == retcode) {     
00511       name_msg = bb_utils_build_msg_name((*bb)->name);
00512       (*bb)->msgid = msgget(bb_utils_ntok(name_msg),
00513                                  IPC_CREAT|IPC_EXCL|BB_MSG_ACCESS_RIGHT);
00514       
00515       if (-1==((*bb)->msgid)) {
00516         strncpy(syserr,strerror(errno),MAX_SYSMSG_SIZE);
00517         bb_logMsg(BB_LOG_SEVERE,"BlackBoard::bb_create", 
00518                     "Cannot message queue <%s key = 0x%x> (%s)",
00519                     name_msg, bb_utils_ntok(name_msg), syserr);
00520         retcode = E_NOK; 
00521       } 
00522     }
00523     free(name_msg);
00524   }
00525   free(name_shm);
00526 
00527   
00528   return retcode;
00529 } /* end of bb_create */
00530 
00531 int32_t 
00532 bb_destroy(S_BB_T** bb) {
00533   
00534   int32_t retcode;
00535   char syserr[MAX_SYSMSG_SIZE];
00536   char* name_shm;
00537   int32_t fd_shm;
00538   int32_t local_semid;
00539   int32_t local_msgid;
00540   
00541   retcode = E_OK;
00542   assert(bb);
00543   assert(*bb);  
00544   bb_logMsg(BB_LOG_INFO,"BlackBoard::bb_destroy", 
00545                 "Destroy BB <%s>.",(*bb)->name);
00546   name_shm = bb_utils_build_shm_name((*bb)->name);
00547   /* 
00548    * On signale la destruction en cours pour les processes qui
00549    * resteraient attachés
00550    */
00551   (*bb)->destroyed = 1;
00552 
00553   /* On mémorise les IDs
00554    * des semaphore et autres queue de message
00555    * pour les détruire après la destruction de la SHM
00556    */
00557   local_semid = (*bb)->semid;
00558   local_msgid = (*bb)->msgid;
00559   
00560   /* On programme la destruction du segment SHM */
00561   fd_shm = shmget(bb_utils_ntok(name_shm),0,BB_SHM_ACCESS_RIGHT);
00562   if (-1 == shmctl(fd_shm,IPC_RMID,NULL)) {
00563     strncpy(&syserr[0],strerror(errno),MAX_SYSMSG_SIZE);
00564     bb_logMsg(BB_LOG_SEVERE,"BlackBoard::bb_destroy", 
00565                 "SHM Destroy failed (%s)",syserr);
00566     retcode = E_NOK;
00567   }
00568   free(name_shm);
00569   
00570   /* on se detache de façon a provoquer la destruction */
00571   if (E_OK == retcode) {
00572     if (-1 == shmdt(*bb)) {
00573       strncpy(&syserr[0],strerror(errno),MAX_SYSMSG_SIZE);
00574       bb_logMsg(BB_LOG_SEVERE,"BlackBoard::bb_destroy", 
00575                 "SHM detach failed (%s)",syserr);
00576       retcode = E_NOK;
00577     }
00578   }
00579   /* FIXME doit-on prendre le semaphore avant de le détruire ?? */
00580   /* On programme la destruction du SEMAPHORE */
00581   semctl(local_semid,0,IPC_RMID);
00582   /* On programme la destruction de la QUEUE DE MESSAGE */
00583   msgctl(local_msgid,IPC_RMID,NULL);
00584   *bb = NULL;
00585     
00586   return retcode;
00587 } /* end of bb_destroy */
00588 
00589 int32_t 
00590 bb_lock(volatile S_BB_T* bb) {
00591   
00592   int32_t retcode;
00593   char syserr[MAX_SYSMSG_SIZE];
00594   struct sembuf s_semop;
00595   
00596   assert(bb);
00597   s_semop.sem_num = 0; 
00598   s_semop.sem_op  = -1; 
00599   s_semop.sem_flg = SEM_UNDO;   
00600   if (-1 == semop(bb->semid,&s_semop,1)) {
00601     strncpy(syserr,strerror(errno),MAX_SYSMSG_SIZE);
00602     if (EINVAL == errno) {
00603       bb_logMsg(BB_LOG_WARNING, "BlackBoard::bb_lock",
00604                   "Is BB semaphore destroyed?");
00605     }
00606     else { 
00607       bb_logMsg(BB_LOG_SEVERE,"BlackBoard::bb_lock", 
00608                   "semop failed (%s)", syserr);
00609     }
00610     retcode = E_NOK;
00611   } else {
00612     retcode = E_OK; 
00613   }
00614   
00615   return retcode;
00616 } /* end of bb_lock */
00617 
00618 int32_t 
00619 bb_unlock(volatile S_BB_T* bb) {
00620   
00621   int32_t retcode;
00622   char syserr[MAX_SYSMSG_SIZE];
00623   struct sembuf s_semop;
00624     
00625   s_semop.sem_num = 0; 
00626   s_semop.sem_op  = 1; 
00627   s_semop.sem_flg = SEM_UNDO;   
00628   if (-1 == semop(bb->semid,&s_semop,1)) {
00629     strncpy(syserr,strerror(errno),MAX_SYSMSG_SIZE);
00630     if (EINVAL == errno) {
00631       bb_logMsg(BB_LOG_WARNING, "BlackBoard::bb_unlock",
00632                   "Semaphore du BB detruit");
00633     }
00634     bb_logMsg(BB_LOG_SEVERE,"BlackBoard::bb_unlock", 
00635                 "semop failed (%s)", syserr);
00636     retcode = E_NOK;
00637   } else {
00638     retcode = E_OK; 
00639   }
00640   
00641   return retcode;
00642 } /* end of bb_unlock */
00643 
00644 
00645 int32_t 
00646 bb_attach(S_BB_T** bb, const char* pc_bb_name) {
00647     
00648   int32_t retcode;
00649   char syserr[MAX_SYSMSG_SIZE];
00650   char* name_shm;
00651   int32_t  fd_shm;
00652   
00653   retcode = E_OK;
00654   fd_shm  = 0;
00655   assert(bb);
00656   
00657   name_shm = bb_utils_build_shm_name(pc_bb_name);
00658 /*   bb_logMsg(BB_LOG_INFO,"BlackBoard::bb_attach",  */
00659 /*       "Attachement au BB <%s>.",pc_bb_name); */
00660   if (name_shm!=NULL) {
00661     /* On recupere l'acces au SHM */
00662     fd_shm = shmget(bb_utils_ntok(name_shm), 0, BB_SHM_ACCESS_RIGHT);        
00663   } else {
00664     retcode = E_NOK;
00665   }
00666   if((E_OK==retcode) && (-1==fd_shm)) {
00667     strncpy(syserr,strerror(errno),MAX_SYSMSG_SIZE);
00668     bb_logMsg(BB_LOG_SEVERE,"BlackBoard::bb_attach", 
00669               "Cannot open shm segment <%s key = 0x%x> (%s)",
00670               name_shm, bb_utils_ntok(name_shm), syserr);
00671   
00672     retcode = E_NOK; 
00673   }
00674   free(name_shm);
00675 
00676   if (E_OK == retcode) {
00677     *bb = (S_BB_T*) shmat(fd_shm,NULL,0);
00678   }
00679   if ((E_OK == retcode) && ((void *)-1 == *bb)) {
00680     strncpy(syserr,strerror(errno),MAX_SYSMSG_SIZE);
00681     bb_logMsg(BB_LOG_SEVERE,"BlackBoard::bb_attach", 
00682                 "Cannot attach shm segment (%s)",syserr);
00683     retcode = E_NOK; 
00684   }   
00685   
00686   return retcode;
00687 } /* end of bb_attach */
00688 
00689 int32_t 
00690 bb_detach(S_BB_T** bb) {
00691   
00692   int32_t retcode;
00693   char syserr[MAX_SYSMSG_SIZE];
00694   
00695   retcode = E_OK;
00696   assert(bb);
00697   assert(*bb);
00698 /*   bb_logMsg(BB_LOG_INFO,"BlackBoard::bb_detach",  */
00699 /*            "Detachement du BB <%s>.",(*bb)->name); */
00700 
00701   if (-1 == shmdt(*bb)) {
00702     strncpy(&syserr[0],strerror(errno),MAX_SYSMSG_SIZE);
00703     bb_logMsg(BB_LOG_SEVERE,"BlackBoard::bb_detach", 
00704                 "SHM detach failed (%s)",syserr);
00705     retcode = E_NOK;
00706   }
00707 
00708   *bb = NULL;
00709   
00710   return retcode;
00711 } /* end of bb_detach */
00712 
00713 void* 
00714 bb_publish(volatile S_BB_T *bb, S_BB_DATADESC_T* data_desc) {
00715   
00716   void* retval;
00717   int32_t nedeed_size;
00718 
00719   retval = NULL;
00720   assert(bb);
00721   assert(data_desc);
00722   
00723   /* Verify that the published data is not already published
00724    * (key unicity)
00725    */
00726   bb_lock(bb);
00727   if (bb_find(bb,data_desc->name) != -1) {
00728      bb_logMsg(BB_LOG_FINER,"BlackBoard::bb_publish",
00729                "Key <%s> already exists in blackboard (automatic subscribe)!!",data_desc->name);
00730     bb_unlock(bb);
00731     retval = bb_subscribe(bb,data_desc);
00732     bb_lock(bb);
00733   } else {
00734     /* calcul de la taille demandee */
00735     nedeed_size = data_desc->type_size*data_desc->dimension;    
00736     /* verification espace disponible dans BB */
00737     if (bb->n_data >= bb->max_data_desc_size) {
00738       bb_logMsg(BB_LOG_SEVERE,"BlackBoard::bb_publish", 
00739                 "No more room in BB data descriptor!! [current n_data=%d]",
00740                 bb->n_data);
00741       /* verification taille donnee allouable */
00742     } else if ((bb->max_data_size-bb->data_free_offset) < nedeed_size) {
00743       bb_logMsg(BB_LOG_SEVERE,"BlackBoard::bb_publish", 
00744                 "No more room in BB data zone!! [left <%d> byte(s) out of <%d> required]",
00745                 bb->max_data_size-bb->data_free_offset,nedeed_size);
00746     } else {     
00747       /* Calcule de l'adresse libre */
00748       retval = (char*) bb_data(bb) + bb->data_free_offset;
00749       /* Mise a jour descripteur en retour */
00750       data_desc->data_offset = bb->data_free_offset;
00751       /* Mise a jour prochaine @ libre */
00752       bb->data_free_offset  = bb->data_free_offset + nedeed_size;
00753       /* Mise a jour descripteur de donnee */
00754       bb_data_desc(bb)[bb->n_data] = *data_desc;
00755       /* On augmente le nombre de donnees */
00756       bb->n_data++;
00757     }
00758     /* initialisation à des valeurs par defaut */
00759     bb_data_initialise(bb,data_desc,NULL);
00760   }    
00761   /* no init in case of automatic subscribe */  
00762   bb_unlock(bb);  
00763   return retval;
00764 } /* end of bb_publish */
00765 
00766 
00767 void* 
00768 bb_subscribe(volatile S_BB_T *bb, 
00769              S_BB_DATADESC_T* data_desc) {
00770   
00771   void* retval;
00772   int32_t  idx;
00773   
00774   retval = NULL;
00775   assert(bb);
00776   assert(data_desc);
00777   
00778   /* on cherche la donnee publiee par sa clef */
00779   bb_lock(bb);
00780   idx = bb_find(bb,data_desc->name);
00781   if (idx==-1) {
00782     retval = NULL;      
00783   } else {
00784     data_desc->type            = (bb_data_desc(bb)[idx]).type;
00785     data_desc->dimension       = (bb_data_desc(bb)[idx]).dimension;
00786     data_desc->type_size       = (bb_data_desc(bb)[idx]).type_size;
00787     data_desc->data_offset     = (bb_data_desc(bb)[idx]).data_offset;
00788     retval = (char*) bb_data(bb) + data_desc->data_offset;
00789   }
00790   bb_unlock(bb);
00791 
00792   return retval;
00793 } /* end of bb_subscribe */
00794 
00795 
00796 int32_t 
00797 bb_dump(volatile S_BB_T *bb,FILE* p_filedesc) {  
00798   
00799   int32_t retcode;
00800   /* char syserr[MAX_SYSMSG_SIZE]; */
00801   int32_t i;
00802 
00803   
00804   retcode = E_OK;
00805   assert(bb);
00806   fprintf(p_filedesc,"============= <[begin] BlackBoard [%s] [begin] > ===============\n",
00807           bb->name);
00808   fprintf(p_filedesc,"  @start blackboard    = 0x%x\n",(unsigned int) (bb));
00809   fprintf(p_filedesc,"  stored data          = %d / %d [max desc]\n",
00810           bb->n_data,
00811           bb->max_data_desc_size);
00812   fprintf(p_filedesc,"  free data size       = %ld / %ld\n",
00813           bb->max_data_size - bb->data_free_offset + 1,
00814           bb->max_data_size);  
00815   fprintf(p_filedesc,"  @data_desc           = 0x%x\n",
00816           (unsigned int) (bb_data_desc(bb)));
00817   fprintf(p_filedesc,"  @data                = 0x%x\n",
00818           (unsigned int) (bb_data(bb)));
00819   fprintf(p_filedesc,"================ < [begin] Data [begin] > ==================\n");
00820   for (i=0;i<bb->n_data;++i) {
00821     bb_data_print(bb,bb_data_desc(bb)[i],p_filedesc);
00822   }
00823   fprintf(p_filedesc,"================== < [end] Data [end] > ====================\n");
00824   fprintf(p_filedesc,"============== < [end] BlackBoard [%s] [end] > ================\n",
00825           bb->name);
00826   
00827   return retcode;
00828 } /* end of bb_dump */
00829 
00830 int32_t
00831 bb_get_nb_max_item(volatile S_BB_T *bb) {
00832   
00833   int32_t retval;  
00834   
00835   
00836   retval = -1;
00837   assert(bb);
00838   
00839   retval = bb->max_data_desc_size;
00840   
00841   return retval;
00842 }
00843 
00844 int32_t
00845 bb_get_nb_item(volatile S_BB_T *bb) {
00846 
00847   
00848   int32_t retval;  
00849   
00850   
00851   retval = -1;
00852   assert(bb);
00853   
00854   retval = bb->n_data;
00855   
00856   return retval;
00857 }
00858 
00859 int32_t
00860 bb_get_mem_size(volatile S_BB_T *bb) {
00861 
00862   
00863   int32_t retval;  
00864   
00865   
00866   retval = -1;
00867   assert(bb);
00868   
00869   retval = bb_size(bb->max_data_desc_size,
00870                         bb->max_data_size);
00871   
00872   return retval;
00873 }
00874 
00875 int32_t 
00876 bb_shadow_get(S_BB_T *bb_shadow,
00877                    volatile S_BB_T *bb_src) {
00878   
00879   int32_t retcode;
00880 
00881   bb_lock(bb_src);
00882 
00883   
00884   assert(bb_src);
00885   assert(bb_shadow);
00886   retcode = E_OK;
00887   /* copie brutale du BB */
00888   memcpy(bb_shadow,
00889          (void*)bb_src,
00890          bb_get_mem_size(bb_src));
00891   /* On degage ce qui est inutilisable dans le shadow bb */
00892   bb_shadow->semid    = -1;
00893   
00894   bb_unlock(bb_src);
00895   
00896   return retcode;
00897 }
00898 
00899 int32_t 
00900 bb_shadow_update_data(S_BB_T *bb_shadow,
00901                       volatile S_BB_T *bb_src) {  
00902   int32_t retcode;
00903   
00904   assert(bb_src);
00905   assert(bb_shadow);
00906   retcode = E_OK;
00907   bb_lock(bb_src);
00908   /* copie brutale du contenu la zone de donnée 
00909    * (utile, on ne copie pas la zone non utilisée) */
00910   memcpy(bb_data(bb_shadow),
00911          bb_data(bb_src),
00912          bb_shadow->data_free_offset);
00913   bb_unlock(bb_src);
00914   
00915   return retcode;
00916 } /* end of bb_shadow_update_data */
00917 
00918 
00919 int32_t
00920 bb_msg_id(volatile S_BB_T *bb) {
00921     
00922   int32_t retval;
00923   
00924   assert(bb);
00925   retval = bb->msgid;  
00926   return retval;
00927 }
00928 
00929 int32_t 
00930 bb_snd_msg(volatile S_BB_T *bb,
00931                 S_BB_MSG_T* msg) {
00932   
00933   int32_t retcode;
00934   char syserr[MAX_SYSMSG_SIZE];
00935   struct msqid_ds mystat;
00936   
00937   retcode = E_OK;
00938   assert(bb);
00939   /* do not flood message queue if no one read it !!*/
00940   retcode  = msgctl(bb->msgid,IPC_STAT,&mystat);
00941   if (!(mystat.__msg_cbytes > 2*MSG_BB_MAX_SIZE)) {
00942     /* Non blocking send */
00943     retcode = msgsnd(bb->msgid,msg,MSG_BB_MAX_SIZE,IPC_NOWAIT);
00944     if (-1 == retcode) {
00945       retcode = E_NOK;
00946       strncpy(syserr,strerror(errno),MAX_SYSMSG_SIZE);
00947       if (EAGAIN == errno) {
00948         /*bb_logMsg(BB_LOG_WARNING,
00949           "Blackboard::bb_snd_msg",
00950           "Envoi du message impossible (queue pleine) <%s>",
00951           syserr);
00952         */
00953       } else {
00954         bb_logMsg(BB_LOG_SEVERE,
00955                   "Blackboard::bb_snd_msg",
00956                   "Cannot send message <%s>",
00957                   syserr);
00958       } 
00959     }
00960   } else {
00961     /* NOP */
00962 /*     bb_logMsg(BB_LOG_WARNING, */
00963 /*            "Blackboard::bb_snd_msg", */
00964 /*            "Cannot send msg <%d> bytes already queued>",mystat.__msg_cbytes); */
00965   }
00966   
00967   return retcode;
00968 } /* end of bb_snd_msg */
00969 
00970 
00971 int32_t 
00972 bb_rcv_msg(volatile S_BB_T *bb,
00973                 S_BB_MSG_T* msg) {
00974     
00975   int32_t retcode;
00976   char syserr[MAX_SYSMSG_SIZE];
00977   int32_t  i_cont;
00978   
00979   retcode = E_OK;
00980   assert(bb);
00981 
00982   i_cont = 1;
00983   /* Réception bloquante */
00984   while (i_cont) {  
00985     retcode = msgrcv(bb->msgid,msg,MSG_BB_MAX_SIZE,msg->mtype,MSG_NOERROR);
00986     /* On sort de la boucle si on a pas pris un signal */
00987     if ((-1 != retcode) || (EINTR != errno)) {
00988       i_cont = 0;
00989     }
00990   }
00991   if (-1 == retcode) {
00992     retcode = E_NOK;
00993     /* The identifier removed case and INTR
00994      * should not generate a log message 
00995      * FIXME on devrait pouvoir faire mieux que ça.
00996      */
00997     if ((EIDRM != errno) && (EINTR != errno)) {
00998       strncpy(syserr,strerror(errno),MAX_SYSMSG_SIZE);
00999       bb_logMsg(BB_LOG_SEVERE,
01000                 "Blackboard::bb_rcv_msg",
01001                 "Cannot receive messsage <%s>",
01002                 syserr);
01003     }
01004   } 
01005   
01006   return retcode;
01007 } /* end of bb_rcv_msg */
Framework Home Page.

Beware !! TSP wave is coming...