/* libdax_msgs Message handling facility of libdax. Copyright (C) 2006 - 2010 Thomas Schmitt , provided under GPL version 2 or later. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include #include #include #include #include #include #include #include /* Only this single source module is entitled to do this */ #define LIBDAX_MSGS_H_INTERNAL 1 /* All participants in the messaging system must do this */ #include "libdax_msgs.h" /* ----------------------------- libdax_msgs_item ------------------------- */ static int libdax_msgs_item_new(struct libdax_msgs_item **item, struct libdax_msgs_item *link, int flag) { int ret; struct libdax_msgs_item *o; struct timeval tv; struct timezone tz; (*item)= o= (struct libdax_msgs_item *) calloc(1, sizeof(struct libdax_msgs_item)); if(o==NULL) return(-1); o->timestamp= 0.0; ret= gettimeofday(&tv,&tz); if(ret==0) o->timestamp= tv.tv_sec+0.000001*tv.tv_usec; o->process_id= getpid(); o->origin= -1; o->severity= LIBDAX_MSGS_SEV_ALL; o->priority= LIBDAX_MSGS_PRIO_ZERO; o->error_code= 0; o->msg_text= NULL; o->os_errno= 0; o->prev= link; o->next= NULL; if(link!=NULL) { if(link->next!=NULL) { link->next->prev= o; o->next= link->next; } link->next= o; } return(1); } /** Detaches item from its queue and eventually readjusts start, end pointers of the queue */ int libdax_msgs_item_unlink(struct libdax_msgs_item *o, struct libdax_msgs_item **chain_start, struct libdax_msgs_item **chain_end, int flag) { if(o->prev!=NULL) o->prev->next= o->next; if(o->next!=NULL) o->next->prev= o->prev; if(chain_start!=NULL) if(*chain_start == o) *chain_start= o->next; if(chain_end!=NULL) if(*chain_end == o) *chain_end= o->prev; o->next= o->prev= NULL; return(1); } int libdax_msgs_item_destroy(struct libdax_msgs_item **item, int flag) { struct libdax_msgs_item *o; o= *item; if(o==NULL) return(0); libdax_msgs_item_unlink(o,NULL,NULL,0); if(o->msg_text!=NULL) free((char *) o->msg_text); free((char *) o); *item= NULL; return(1); } int libdax_msgs_item_get_msg(struct libdax_msgs_item *item, int *error_code, char **msg_text, int *os_errno, int flag) { *error_code= item->error_code; *msg_text= item->msg_text; *os_errno= item->os_errno; return(1); } int libdax_msgs_item_get_origin(struct libdax_msgs_item *item, double *timestamp, pid_t *process_id, int *origin, int flag) { *timestamp= item->timestamp; *process_id= item->process_id; *origin= item->origin; return(1); } int libdax_msgs_item_get_rank(struct libdax_msgs_item *item, int *severity, int *priority, int flag) { *severity= item->severity; *priority= item->priority; return(1); } /* ------------------------------- libdax_msgs ---------------------------- */ int libdax_msgs_new(struct libdax_msgs **m, int flag) { struct libdax_msgs *o; (*m)= o= (struct libdax_msgs *) calloc(1, sizeof(struct libdax_msgs)); if(o==NULL) return(-1); o->refcount= 1; o->oldest= NULL; o->youngest= NULL; o->count= 0; o->queue_severity= LIBDAX_MSGS_SEV_ALL; o->print_severity= LIBDAX_MSGS_SEV_NEVER; strcpy(o->print_id,"libdax: "); #ifndef LIBDAX_MSGS_SINGLE_THREADED pthread_mutex_init(&(o->lock_mutex),NULL); #endif return(1); } static int libdax_msgs_lock(struct libdax_msgs *m, int flag) { #ifndef LIBDAX_MSGS_SINGLE_THREADED int ret; ret= pthread_mutex_lock(&(m->lock_mutex)); if(ret!=0) return(0); #endif return(1); } static int libdax_msgs_unlock(struct libdax_msgs *m, int flag) { #ifndef LIBDAX_MSGS_SINGLE_THREADED int ret; ret= pthread_mutex_unlock(&(m->lock_mutex)); if(ret!=0) return(0); #endif return(1); } int libdax_msgs_destroy(struct libdax_msgs **m, int flag) { struct libdax_msgs *o; struct libdax_msgs_item *item, *next_item; o= *m; if(o==NULL) return(0); if(o->refcount > 1) { if(libdax_msgs_lock(*m,0)<=0) return(-1); o->refcount--; libdax_msgs_unlock(*m,0); *m= NULL; return(1); } #ifndef LIBDAX_MSGS_SINGLE_THREADED if(pthread_mutex_destroy(&(o->lock_mutex))!=0) { pthread_mutex_unlock(&(o->lock_mutex)); pthread_mutex_destroy(&(o->lock_mutex)); } #endif for(item= o->oldest; item!=NULL; item= next_item) { next_item= item->next; libdax_msgs_item_destroy(&item,0); } free((char *) o); *m= NULL; return(1); } int libdax_msgs_refer(struct libdax_msgs **pt, struct libdax_msgs *m, int flag) { if(libdax_msgs_lock(m,0)<=0) return(0); m->refcount++; *pt= m; libdax_msgs_unlock(m,0); return(1); } int libdax_msgs_set_severities(struct libdax_msgs *m, int queue_severity, int print_severity, char *print_id, int flag) { if(libdax_msgs_lock(m,0)<=0) return(0); m->queue_severity= queue_severity; m->print_severity= print_severity; strncpy(m->print_id,print_id,80); m->print_id[80]= 0; libdax_msgs_unlock(m,0); return(1); } int libdax_msgs__text_to_sev(char *severity_name, int *severity, int flag) { if(strncmp(severity_name,"NEVER",5)==0) *severity= LIBDAX_MSGS_SEV_NEVER; else if(strncmp(severity_name,"ABORT",5)==0) *severity= LIBDAX_MSGS_SEV_ABORT; else if(strncmp(severity_name,"FATAL",5)==0) *severity= LIBDAX_MSGS_SEV_FATAL; else if(strncmp(severity_name,"FAILURE",7)==0) *severity= LIBDAX_MSGS_SEV_FAILURE; else if(strncmp(severity_name,"MISHAP",6)==0) *severity= LIBDAX_MSGS_SEV_MISHAP; else if(strncmp(severity_name,"SORRY",5)==0) *severity= LIBDAX_MSGS_SEV_SORRY; else if(strncmp(severity_name,"WARNING",7)==0) *severity= LIBDAX_MSGS_SEV_WARNING; else if(strncmp(severity_name,"HINT",4)==0) *severity= LIBDAX_MSGS_SEV_HINT; else if(strncmp(severity_name,"NOTE",4)==0) *severity= LIBDAX_MSGS_SEV_NOTE; else if(strncmp(severity_name,"UPDATE",6)==0) *severity= LIBDAX_MSGS_SEV_UPDATE; else if(strncmp(severity_name,"DEBUG",5)==0) *severity= LIBDAX_MSGS_SEV_DEBUG; else if(strncmp(severity_name,"ERRFILE",7)==0) *severity= LIBDAX_MSGS_SEV_ERRFILE; else if(strncmp(severity_name,"ALL",3)==0) *severity= LIBDAX_MSGS_SEV_ALL; else { *severity= LIBDAX_MSGS_SEV_ALL; return(0); } return(1); } int libdax_msgs__sev_to_text(int severity, char **severity_name, int flag) { if(flag&1) { *severity_name= "NEVER\nABORT\nFATAL\nFAILURE\nMISHAP\nSORRY\nWARNING\nHINT\nNOTE\nUPDATE\nDEBUG\nERRFILE\nALL"; return(1); } *severity_name= ""; if(severity>=LIBDAX_MSGS_SEV_NEVER) *severity_name= "NEVER"; else if(severity>=LIBDAX_MSGS_SEV_ABORT) *severity_name= "ABORT"; else if(severity>=LIBDAX_MSGS_SEV_FATAL) *severity_name= "FATAL"; else if(severity>=LIBDAX_MSGS_SEV_FAILURE) *severity_name= "FAILURE"; else if(severity>=LIBDAX_MSGS_SEV_MISHAP) *severity_name= "MISHAP"; else if(severity>=LIBDAX_MSGS_SEV_SORRY) *severity_name= "SORRY"; else if(severity>=LIBDAX_MSGS_SEV_WARNING) *severity_name= "WARNING"; else if(severity>=LIBDAX_MSGS_SEV_HINT) *severity_name= "HINT"; else if(severity>=LIBDAX_MSGS_SEV_NOTE) *severity_name= "NOTE"; else if(severity>=LIBDAX_MSGS_SEV_UPDATE) *severity_name= "UPDATE"; else if(severity>=LIBDAX_MSGS_SEV_DEBUG) *severity_name= "DEBUG"; else if(severity>=LIBDAX_MSGS_SEV_ERRFILE) *severity_name= "ERRFILE"; else if(severity>=LIBDAX_MSGS_SEV_ALL) *severity_name= "ALL"; else { *severity_name= ""; return(0); } return(1); } int libdax_msgs_submit(struct libdax_msgs *m, int origin, int error_code, int severity, int priority, char *msg_text, int os_errno, int flag) { int ret; char *textpt,*sev_name,sev_text[81]; struct libdax_msgs_item *item= NULL; if(severity >= m->print_severity) { if(msg_text==NULL) textpt= ""; else textpt= msg_text; sev_text[0]= 0; ret= libdax_msgs__sev_to_text(severity,&sev_name,0); if(ret>0) sprintf(sev_text,"%s : ",sev_name); fprintf(stderr,"%s%s%s\n",m->print_id,sev_text,textpt); if(os_errno!=0) { ret= libdax_msgs_lock(m,0); if(ret<=0) return(-1); fprintf(stderr,"%s( Most recent system error: %d '%s' )\n", m->print_id,os_errno,strerror(os_errno)); libdax_msgs_unlock(m,0); } } if(severity < m->queue_severity) return(0); ret= libdax_msgs_lock(m,0); if(ret<=0) return(-1); ret= libdax_msgs_item_new(&item,m->youngest,0); if(ret<=0) goto failed; item->origin= origin; item->error_code= error_code; item->severity= severity; item->priority= priority; if(msg_text!=NULL) { item->msg_text= calloc(1, strlen(msg_text)+1); if(item->msg_text==NULL) goto failed; strcpy(item->msg_text,msg_text); } item->os_errno= os_errno; if(m->oldest==NULL) m->oldest= item; m->youngest= item; m->count++; libdax_msgs_unlock(m,0); /* fprintf(stderr,"libdax_experimental: message submitted to queue (now %d)\n", m->count); */ return(1); failed:; libdax_msgs_item_destroy(&item,0); libdax_msgs_unlock(m,0); return(-1); } int libdax_msgs_obtain(struct libdax_msgs *m, struct libdax_msgs_item **item, int severity, int priority, int flag) { int ret; struct libdax_msgs_item *im, *next_im= NULL; *item= NULL; ret= libdax_msgs_lock(m,0); if(ret<=0) return(-1); for(im= m->oldest; im!=NULL; im= next_im) { for(; im!=NULL; im= next_im) { next_im= im->next; if(im->severity>=severity) break; libdax_msgs_item_unlink(im,&(m->oldest),&(m->youngest),0); libdax_msgs_item_destroy(&im,0); /* severity too low: delete */ } if(im==NULL) break; if(im->priority>=priority) break; } if(im==NULL) {ret= 0; goto ex;} libdax_msgs_item_unlink(im,&(m->oldest),&(m->youngest),0); *item= im; ret= 1; ex:; libdax_msgs_unlock(m,0); return(ret); } int libdax_msgs_destroy_item(struct libdax_msgs *m, struct libdax_msgs_item **item, int flag) { int ret; ret= libdax_msgs_lock(m,0); if(ret<=0) return(-1); ret= libdax_msgs_item_destroy(item,0); libdax_msgs_unlock(m,0); return(ret); }