diameter_peer.c File Reference


Detailed Description

CDiameterPeer General procedures for init/start-up/shut-down.

Author:
Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de

Definition in file diameter_peer.c.

#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include "utils.h"
#include "diameter_peer.h"
#include "config.h"
#include "acceptor.h"
#include "timer.h"
#include "peermanager.h"
#include "worker.h"
#include "api_process.h"
#include "transaction.h"
#include "session.h"
#include "../../pt.h"

Go to the source code of this file.

Functions

int dp_add_pid (pid_t pid)
 Add a pid to the local process list.
int dp_last_pid ()
 Returns the last pid in the local process list.
void dp_del_pid (pid_t pid)
 Delete a pid from the process list.
int diameter_peer_init (char *cfg_filename)
 Initialize the CDiameterPeer from a configuration file.
int diameter_peer_start (int blocking)
 Start the CDiameterPeer operations.
void diameter_peer_destroy ()
 Shutdown the CDiameterPeer nicely.

Variables

dp_configconfig = 0
 Configuration for this diameter peer.
int * shutdownx = 0
 whether a shutdown is in progress
gen_lock_t * shutdownx_lock
 lock used on shutdown
pid_t * dp_first_pid
 first pid that we started from
pid_list_head_tpid_list
 list of local processes
gen_lock_t * pid_list_lock
 lock for list of local processes
handler_listhandlers
 list of handlers
gen_lock_t * handlers_lock
 lock for list of handlers
int memlog


Function Documentation

int dp_add_pid ( pid_t  pid  )  [inline]

Add a pid to the local process list.

Parameters:
pid newly forked pid
Returns:
1 on success or 0 on error

Definition at line 95 of file diameter_peer.c.

References pid_list_head_t::head, LOG_NO_MEM, _pid_list_t::next, _pid_list_t::pid, pid_list, pid_list_lock, _pid_list_t::prev, and pid_list_head_t::tail.

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 }

int dp_last_pid (  )  [inline]

Returns the last pid in the local process list.

Definition at line 118 of file diameter_peer.c.

References _pid_list_t::pid, pid_list, pid_list_lock, and pid_list_head_t::tail.

Referenced by diameter_peer_destroy().

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 }

void dp_del_pid ( pid_t  pid  )  [inline]

Delete a pid from the process list.

Parameters:
pid - the pid to remove

Definition at line 132 of file diameter_peer.c.

References pid_list_head_t::head, _pid_list_t::next, _pid_list_t::pid, pid_list, pid_list_lock, _pid_list_t::prev, and pid_list_head_t::tail.

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 }

int diameter_peer_init ( char *  cfg_filename  ) 

Initialize the CDiameterPeer from a configuration file.

The file is kept as dtd. See configdtd.h for the DTD and ConfigExample.xml.

Parameters:
cfg_filename - file with the configuration
Returns:
1 on success, 0 on error

Definition at line 159 of file diameter_peer.c.

References api_callback(), cb_add(), config, dp_first_pid, free_dp_config(), handlers, handlers_lock, handler_list_t::head, pid_list_head_t::head, log_dp_config(), LOG_NO_MEM, _pid_list_t::next, parse_dp_config(), peer_manager_init(), pid_list, pid_list_lock, session_init(), shutdownx, shutdownx_lock, handler_list_t::tail, timer_cdp_init(), trans_init(), and worker_init().

Referenced by cdp_init().

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 
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     return 1;
00229     
00230 error:
00231     if (shutdownx) shm_free(shutdownx);
00232     if (config) free_dp_config(config);
00233     i = pid_list->head;
00234     while(i){
00235         j = i->next;
00236         shm_free(i);
00237         i = j;
00238     }
00239     shm_free(pid_list);
00240     lock_get(pid_list_lock);
00241     lock_destroy(pid_list_lock);
00242     lock_dealloc((void*)pid_list_lock);
00243     return 0;   
00244 
00245 }

int diameter_peer_start ( int  blocking  ) 

Start the CDiameterPeer operations.

It forks all the processes required.

Parameters:
blocking - if this is set, use the calling processes for the timer and never return; else fork a new one for the timer and return
Returns:
1 on success, 0 on error, never if blocking

Definition at line 255 of file diameter_peer.c.

References acceptor_process(), CDP_FOR_SER, config, dp_add_pid(), process_no, timer_process(), worker_process(), and dp_config::workers.

Referenced by cdp_child_init().

00256 {
00257     int pid;
00258     int k=0;
00259 
00260 
00261     /* Fork the acceptor process */
00262     #ifdef CDP_FOR_SER      
00263         pid = fork_process(1000,"cdp_acceptor",1);
00264     #else
00265         pid = fork();
00266     #endif
00267     if (pid==-1){
00268         LOG(L_CRIT,"ERROR:init_diameter_peer(): Error on fork() for acceptor!\n");
00269         return 0;
00270     }
00271     if (pid==0) {
00272         acceptor_process(config);
00273         LOG(L_CRIT,"ERROR:init_diameter_peer(): acceptor_process finished without exit!\n");
00274         exit(-1);       
00275     }else{
00276         dp_add_pid(pid);
00277     }
00278 
00279     /* fork workers */
00280     for(k=0;k<config->workers;k++){
00281         #ifdef CDP_FOR_SER      
00282             pid = fork_process(1001+k,"cdp_worker",1);
00283         #else
00284             pid = fork();
00285         #endif
00286         if (pid==-1){
00287             LOG(L_CRIT,"ERROR:init_diameter_peer(): Error on fork() for worker!\n");
00288             return 0;
00289         }
00290         if (pid==0) {
00291             srandom(time(0)*k);
00292             #ifdef CDP_FOR_SER
00293                 snprintf(pt[process_no].desc, MAX_PT_DESC,
00294                     "cdp worker child=%d", k );
00295             #endif  
00296             worker_process(k);
00297             LOG(L_CRIT,"ERROR:init_diameter_peer(): worker_process finished without exit!\n");
00298             exit(-1);       
00299         }else{
00300             dp_add_pid(pid);
00301         }
00302     }
00303                 
00304     /* fork/become timer */
00305     if (blocking) {
00306         dp_add_pid(getpid());
00307         timer_process(1);
00308     }       
00309     else{       
00310         #ifdef CDP_FOR_SER      
00311             pid = fork_process(1001,"cdp_timer",1);
00312         #else
00313             pid = fork();
00314         #endif
00315         if (pid==-1){
00316             LOG(L_CRIT,"ERROR:init_diameter_peer(): Error on fork() for timer!\n");
00317             return 0;
00318         }
00319         if (pid==0) {
00320             timer_process(0);
00321             LOG(L_CRIT,"ERROR:init_diameter_peer(): timer_process finished without exit!\n");
00322             exit(-1);       
00323         }else{          
00324             dp_add_pid(pid);
00325         }
00326     }
00327     
00328     return 1;
00329 }

void diameter_peer_destroy (  ) 

Shutdown the CDiameterPeer nicely.

It stops the workers, disconnects peers, drops timers and wait for all processes to exit.

Definition at line 337 of file diameter_peer.c.

References config, dp_del_pid(), dp_first_pid, dp_last_pid(), free_dp_config(), handlers, handlers_lock, handler_list_t::head, memlog, handler_t::next, peer_manager_destroy(), pid_list, pid_list_lock, session_destroy(), shutdownx, shutdownx_lock, pid_list_head_t::tail, timer_cdp_destroy(), worker_destroy(), and worker_poison_queue().

Referenced by cdp_exit().

00338 {
00339     int pid,status;
00340     handler *h;
00341     
00342     lock_get(shutdownx_lock);
00343     if (*shutdownx) {
00344         /* already other process is cleaning stuff */
00345         lock_release(shutdownx_lock);           
00346         return;
00347     }else {
00348         /* indicating that we are shuting down */
00349         *shutdownx = 1;
00350         lock_release(shutdownx_lock);
00351     }
00352 
00353 
00354     worker_poison_queue();
00355 
00356     /* wait for all childs to clean up nicely (acceptor, receiver, timer, workers) */
00357     LOG(L_INFO,"INFO:destroy_diameter_peer(): Terminating all childs...\n");
00358     while(pid_list->tail){
00359         pid = dp_last_pid();
00360         if (pid<=0||pid==getpid()){
00361             dp_del_pid(pid);
00362             continue;
00363         }
00364         LOG(L_INFO,"INFO:destroy_diameter_peer(): Waiting for child [%d] to terminate...\n",pid);
00365         if (waitpid(pid,&status,0)<0){
00366             dp_del_pid(pid);
00367             continue;
00368         }
00369         if (!WIFEXITED(status) /*|| WIFSIGNALED(status)*/){
00370             worker_poison_queue();
00371             sleep(1);           
00372         } else {
00373             dp_del_pid(pid);
00374         }
00375 
00376     }
00377     LOG(L_INFO,"INFO:destroy_diameter_peer(): All processes terminated. Cleaning up.\n");
00378     
00379     /* clean upt the timer */
00380     timer_cdp_destroy();
00381     
00382     /* cleaning up workers */
00383     worker_destroy();
00384     
00385     /* cleaning peer_manager */
00386     peer_manager_destroy();
00387     
00388     /* cleaning up sessions */
00389     session_destroy();
00390 
00391     /* cleaning up global vars */
00392 /*  lock_get(pid_list_lock);*/
00393     shm_free(dp_first_pid);
00394     shm_free(pid_list);
00395     lock_destroy(pid_list_lock);
00396     lock_dealloc((void*)pid_list_lock);
00397     
00398     shm_free(shutdownx);
00399     
00400     lock_destroy(shutdownx_lock);
00401     lock_dealloc((void*)shutdownx_lock);
00402     
00403     lock_get(handlers_lock);
00404     while(handlers->head){
00405         h = handlers->head->next;
00406         shm_free(handlers->head);
00407         handlers->head = h;
00408     }
00409     lock_destroy(handlers_lock);
00410     lock_dealloc((void*)handlers_lock);
00411     shm_free(handlers);
00412         
00413     free_dp_config(config); 
00414     LOG(L_CRIT,"INFO:destroy_diameter_peer(): Bye Bye from C Diameter Peer test\n");
00415 
00416 #ifndef CDP_FOR_SER
00417     #ifdef PKG_MALLOC
00418         LOG(memlog, "Memory status (pkg):\n");
00419         //pkg_status();
00420         #ifdef pkg_sums
00421             pkg_sums();
00422         #endif 
00423     #endif
00424     #ifdef SHM_MEM
00425         LOG(memlog, "Memory status (shm):\n");
00426         //shm_status();
00427         #ifdef shm_sums
00428             shm_sums();
00429         #endif 
00430         /* zero all shmem alloc vars that we still use */
00431         shm_mem_destroy();
00432     #endif
00433 #endif  
00434 }


Variable Documentation

dp_config* config = 0

Configuration for this diameter peer.

Definition at line 76 of file diameter_peer.c.

int* shutdownx = 0

whether a shutdown is in progress

Definition at line 78 of file diameter_peer.c.

Referenced by accept_loop(), cdp_lock_get(), cdp_lock_release(), diameter_peer_destroy(), diameter_peer_init(), put_task(), receive_loop(), select_recv(), take_task(), timer_loop(), and worker_process().

gen_lock_t* shutdownx_lock

lock used on shutdown

Definition at line 79 of file diameter_peer.c.

Referenced by diameter_peer_destroy(), and diameter_peer_init().

pid_t* dp_first_pid

first pid that we started from

Definition at line 81 of file diameter_peer.c.

Referenced by diameter_peer_destroy(), and diameter_peer_init().

pid_list_head_t* pid_list

list of local processes

Definition at line 83 of file diameter_peer.c.

Referenced by diameter_peer_destroy(), diameter_peer_init(), dp_add_pid(), dp_del_pid(), and dp_last_pid().

gen_lock_t* pid_list_lock

lock for list of local processes

Definition at line 84 of file diameter_peer.c.

Referenced by diameter_peer_destroy(), diameter_peer_init(), dp_add_pid(), dp_del_pid(), and dp_last_pid().

handler_list* handlers

list of handlers

Definition at line 60 of file api_process.c.

Referenced by AAAAddRequestHandler(), AAAAddResponseHandler(), api_callback(), diameter_peer_destroy(), and diameter_peer_init().

gen_lock_t* handlers_lock

lock for list of handlers

Definition at line 61 of file api_process.c.

Referenced by AAAAddRequestHandler(), AAAAddResponseHandler(), api_callback(), diameter_peer_destroy(), and diameter_peer_init().

int memlog

Referenced by destroy_memory(), diameter_peer_destroy(), init_memory(), receiver_process(), timer_process(), and worker_process().


Generated on Sun Oct 12 04:10:23 2008 for Open IMS Core CSCFs by  doxygen 1.5.2