diameter_peer.c

Go to the documentation of this file.
00001 
00055 #include <stdlib.h>
00056 #include <sys/wait.h> 
00057 #include <signal.h>
00058 #include <stdio.h>
00059 
00060 #include "utils.h"
00061 #include "diameter_peer.h"
00062 
00063 #include "config.h"
00064 #include "acceptor.h"
00065 #include "timer.h"
00066 #include "peermanager.h"
00067 #include "worker.h"
00068 #include "api_process.h"
00069 #include "transaction.h"
00070 #include "session.h"
00071 
00072 #ifdef CDP_FOR_SER
00073     #include "../../pt.h"
00074 #endif
00075 
00076 dp_config *config=0;        
00078 int *shutdownx=0;           
00079 gen_lock_t *shutdownx_lock; 
00081 pid_t *dp_first_pid;        
00083 pid_list_head_t *pid_list;  
00084 gen_lock_t *pid_list_lock;  
00086 extern handler_list *handlers;      
00087 extern gen_lock_t *handlers_lock;   
00095 inline int dp_add_pid(pid_t pid)
00096 {
00097     pid_list_t *n;
00098     lock_get(pid_list_lock);
00099     n = shm_malloc(sizeof(pid_list_t));
00100     if (!n){
00101         LOG_NO_MEM("shm",sizeof(pid_list_t));
00102         lock_release(pid_list_lock);
00103         return 0;
00104     }
00105     n->pid = pid;
00106     n->next = 0;
00107     n->prev = pid_list->tail;
00108     if (!pid_list->head) pid_list->head = n;
00109     if (pid_list->tail) pid_list->tail->next = n;
00110     pid_list->tail = n;
00111     lock_release(pid_list_lock);
00112     return 1;
00113 }
00114 
00118 inline int dp_last_pid()
00119 {
00120     int pid;
00121     lock_get(pid_list_lock);
00122     if (pid_list->tail) pid = pid_list->tail->pid;
00123     else pid = -1;
00124     lock_release(pid_list_lock);
00125     return pid;
00126 }
00127 
00132 inline void dp_del_pid(pid_t pid)
00133 {   
00134     pid_list_t *i;
00135     lock_get(pid_list_lock);
00136     i = pid_list->head;
00137     if (!i) {
00138         lock_release(pid_list_lock);
00139         return;
00140     }
00141     while(i && i->pid!=pid) i = i->next;
00142     if (i){
00143         if (i->prev) i->prev->next = i->next;
00144         else pid_list->head = i->next;
00145         if (i->next) i->next->prev = i->prev;
00146         else pid_list->tail = i->prev;
00147         shm_free(i);
00148     }
00149     lock_release(pid_list_lock);
00150 }
00151 
00152 
00159 int diameter_peer_init(char *cfg_filename)
00160 {   
00161     pid_list_t *i,*j;
00162 
00163     config = parse_dp_config(cfg_filename);
00164     if (!config) {
00165         LOG(L_ERR,"ERROR:init_diameter_peer(): Error loading configuration file. Aborting...\n");
00166         goto error;
00167     }
00168     log_dp_config(L_INFO,config);
00169     
00170     dp_first_pid = shm_malloc(sizeof(pid_t));
00171     if (!dp_first_pid){
00172         LOG_NO_MEM("shm",sizeof(pid_t));
00173         goto error;
00174     }
00175     *dp_first_pid = getpid();
00176     
00177     shutdownx = shm_malloc(sizeof(int));
00178     if (!shutdownx){
00179         LOG_NO_MEM("shm",sizeof(int));
00180         goto error;
00181     }
00182     *shutdownx = 0;
00183     
00184     shutdownx_lock = lock_alloc();
00185     if (!shutdownx_lock){
00186         LOG_NO_MEM("shm",sizeof(gen_lock_t));
00187         goto error;
00188     }
00189     shutdownx_lock = lock_init(shutdownx_lock);
00190 
00191     handlers_lock = lock_alloc();
00192     if (!handlers_lock){
00193         LOG_NO_MEM("shm",sizeof(gen_lock_t));
00194         goto error;
00195     }
00196     handlers_lock = lock_init(handlers_lock);
00197 
00198     handlers = shm_malloc(sizeof(handler_list));
00199     if (!handlers){
00200         LOG_NO_MEM("shm",sizeof(handler_list));
00201         goto error;
00202     }
00203     handlers->head=0;
00204     handlers->tail=0;
00205 
00206     /* init the pid list */
00207     pid_list = shm_malloc(sizeof(pid_list_head_t));
00208     pid_list_lock = lock_alloc();
00209     pid_list_lock = lock_init(pid_list_lock);
00210 
00211     /* init shared mem pointers before forking */
00212     timer_cdp_init();
00213     worker_init();
00214 
00215     /* init the peer manager */
00216     peer_manager_init(config);
00217     
00218     /* init the session */
00219     if (!session_init()) goto error;
00220     
00221 #ifdef CDP_FOR_SER
00222     /* init diameter transactions */
00223     trans_init();
00224     
00225     /* add callback for messages - used to implement the API */
00226     cb_add(api_callback,0);
00227         
00228 #endif
00229     
00230     return 1;
00231     
00232 error:
00233     if (shutdownx) shm_free(shutdownx);
00234     if (config) free_dp_config(config);
00235     i = pid_list->head;
00236     while(i){
00237         j = i->next;
00238         shm_free(i);
00239         i = j;
00240     }
00241     shm_free(pid_list);
00242     lock_get(pid_list_lock);
00243     lock_destroy(pid_list_lock);
00244     lock_dealloc((void*)pid_list_lock);
00245     return 0;   
00246 
00247 }
00248 
00249 
00257 int diameter_peer_start(int blocking)
00258 {
00259     int pid;
00260     int k=0;
00261 
00262 
00263     /* Fork the acceptor process */
00264     #ifdef CDP_FOR_SER      
00265         pid = fork_process(1000,"cdp_acceptor",1);
00266     #else
00267         pid = fork();
00268     #endif
00269     if (pid==-1){
00270         LOG(L_CRIT,"ERROR:init_diameter_peer(): Error on fork() for acceptor!\n");
00271         return 0;
00272     }
00273     if (pid==0) {
00274         acceptor_process(config);
00275         LOG(L_CRIT,"ERROR:init_diameter_peer(): acceptor_process finished without exit!\n");
00276         exit(-1);       
00277     }else{
00278         dp_add_pid(pid);
00279     }
00280 
00281     /* fork workers */
00282     for(k=0;k<config->workers;k++){
00283         #ifdef CDP_FOR_SER      
00284             pid = fork_process(1001+k,"cdp_worker",1);
00285         #else
00286             pid = fork();
00287         #endif
00288         if (pid==-1){
00289             LOG(L_CRIT,"ERROR:init_diameter_peer(): Error on fork() for worker!\n");
00290             return 0;
00291         }
00292         if (pid==0) {
00293             srandom(time(0)*k);
00294             #ifdef CDP_FOR_SER
00295                 snprintf(pt[process_no].desc, MAX_PT_DESC,
00296                     "cdp worker child=%d", k );
00297             #endif  
00298             worker_process(k);
00299             LOG(L_CRIT,"ERROR:init_diameter_peer(): worker_process finished without exit!\n");
00300             exit(-1);       
00301         }else{
00302             dp_add_pid(pid);
00303         }
00304     }
00305                 
00306     /* fork/become timer */
00307     if (blocking) {
00308         dp_add_pid(getpid());
00309         timer_process(1);
00310     }       
00311     else{       
00312         #ifdef CDP_FOR_SER      
00313             pid = fork_process(1001,"cdp_timer",1);
00314         #else
00315             pid = fork();
00316         #endif
00317         if (pid==-1){
00318             LOG(L_CRIT,"ERROR:init_diameter_peer(): Error on fork() for timer!\n");
00319             return 0;
00320         }
00321         if (pid==0) {
00322             timer_process(0);
00323             LOG(L_CRIT,"ERROR:init_diameter_peer(): timer_process finished without exit!\n");
00324             exit(-1);       
00325         }else{          
00326             dp_add_pid(pid);
00327         }
00328     }
00329     
00330     return 1;
00331 }
00332 
00333 extern int memlog;
00334 
00339 void diameter_peer_destroy()
00340 {
00341     int pid,status;
00342     handler *h;
00343     
00344     lock_get(shutdownx_lock);
00345     if (*shutdownx) {
00346         /* already other process is cleaning stuff */
00347         lock_release(shutdownx_lock);           
00348         return;
00349     }else {
00350         /* indicating that we are shuting down */
00351         *shutdownx = 1;
00352         lock_release(shutdownx_lock);
00353     }
00354 
00355 
00356     worker_poison_queue();
00357 
00358     /* wait for all childs to clean up nicely (acceptor, receiver, timer, workers) */
00359     LOG(L_INFO,"INFO:destroy_diameter_peer(): Terminating all childs...\n");
00360     while(pid_list->tail){
00361         pid = dp_last_pid();
00362         if (pid<=0||pid==getpid()){
00363             dp_del_pid(pid);
00364             continue;
00365         }
00366         LOG(L_INFO,"INFO:destroy_diameter_peer(): Waiting for child [%d] to terminate...\n",pid);
00367         if (waitpid(pid,&status,0)<0){
00368             dp_del_pid(pid);
00369             continue;
00370         }
00371         if (!WIFEXITED(status) /*|| WIFSIGNALED(status)*/){
00372             worker_poison_queue();
00373             sleep(1);           
00374         } else {
00375             dp_del_pid(pid);
00376         }
00377 
00378     }
00379     LOG(L_INFO,"INFO:destroy_diameter_peer(): All processes terminated. Cleaning up.\n");
00380     
00381     /* clean upt the timer */
00382     timer_cdp_destroy();
00383     
00384     /* cleaning up workers */
00385     worker_destroy();
00386     
00387     /* cleaning peer_manager */
00388     peer_manager_destroy();
00389     
00390     /* cleaning up sessions */
00391     session_destroy();
00392 
00393     /* cleaning up global vars */
00394 /*  lock_get(pid_list_lock);*/
00395     shm_free(dp_first_pid);
00396     shm_free(pid_list);
00397     lock_destroy(pid_list_lock);
00398     lock_dealloc((void*)pid_list_lock);
00399     
00400     shm_free(shutdownx);
00401     
00402     lock_destroy(shutdownx_lock);
00403     lock_dealloc((void*)shutdownx_lock);
00404     
00405     lock_get(handlers_lock);
00406     while(handlers->head){
00407         h = handlers->head->next;
00408         shm_free(handlers->head);
00409         handlers->head = h;
00410     }
00411     lock_destroy(handlers_lock);
00412     lock_dealloc((void*)handlers_lock);
00413     shm_free(handlers);
00414         
00415     free_dp_config(config); 
00416     LOG(L_CRIT,"INFO:destroy_diameter_peer(): Bye Bye from C Diameter Peer test\n");
00417 
00418 #ifndef CDP_FOR_SER
00419     #ifdef PKG_MALLOC
00420         LOG(memlog, "Memory status (pkg):\n");
00421         //pkg_status();
00422         #ifdef pkg_sums
00423             pkg_sums();
00424         #endif 
00425     #endif
00426     #ifdef SHM_MEM
00427         LOG(memlog, "Memory status (shm):\n");
00428         //shm_status();
00429         #ifdef shm_sums
00430             shm_sums();
00431         #endif 
00432         /* zero all shmem alloc vars that we still use */
00433         shm_mem_destroy();
00434     #endif
00435 #endif  
00436 }
00437 
00438 

Generated on Tue Jul 29 04:19:11 2008 for Open IMS Core CSCFs by  doxygen 1.5.2