You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
400 lines
9.1 KiB
400 lines
9.1 KiB
|
|
/* libdax_msgs |
|
Message handling facility of libdax. |
|
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL |
|
*/ |
|
|
|
#include <stdio.h> |
|
#include <sys/types.h> |
|
#include <unistd.h> |
|
#include <string.h> |
|
#include <stdlib.h> |
|
#include <errno.h> |
|
#include <sys/time.h> |
|
|
|
/* 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 *) malloc(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->driveno= -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 *driveno, |
|
int flag) |
|
{ |
|
*timestamp= item->timestamp; |
|
*process_id= item->process_id; |
|
*driveno= item->driveno; |
|
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 *) malloc(sizeof(struct libdax_msgs)); |
|
if(o==NULL) |
|
return(-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); |
|
} |
|
|
|
|
|
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); |
|
|
|
#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_set_severities(struct libdax_msgs *m, int queue_severity, |
|
int print_severity, char *print_id, int flag) |
|
{ |
|
m->queue_severity= queue_severity; |
|
m->print_severity= print_severity; |
|
strncpy(m->print_id,print_id,80); |
|
m->print_id[80]= 0; |
|
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__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,"FATAL",5)==0) |
|
*severity= LIBDAX_MSGS_SEV_FATAL; |
|
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,"ALL",3)==0) |
|
*severity= LIBDAX_MSGS_SEV_ALL; |
|
else { |
|
*severity= LIBDAX_MSGS_SEV_NEVER; |
|
return(0); |
|
} |
|
return(1); |
|
} |
|
|
|
|
|
int libdax_msgs__sev_to_text(int severity, char **severity_name, |
|
int flag) |
|
{ |
|
if(flag&1) { |
|
*severity_name= |
|
"NEVER\nFATAL\nSORRY\nWARNING\nHINT\nNOTE\nUPDATE\nDEBUG\nALL"; |
|
return(1); |
|
} |
|
*severity_name= ""; |
|
if(severity>=LIBDAX_MSGS_SEV_NEVER) |
|
*severity_name= "NEVER"; |
|
else if(severity>=LIBDAX_MSGS_SEV_FATAL) |
|
*severity_name= "FATAL"; |
|
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_ALL) |
|
*severity_name= "ALL"; |
|
else { |
|
*severity_name= ""; |
|
return(0); |
|
} |
|
return(1); |
|
} |
|
|
|
|
|
int libdax_msgs_submit(struct libdax_msgs *m, int driveno, 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->driveno= driveno; |
|
item->error_code= error_code; |
|
item->severity= severity; |
|
item->priority= priority; |
|
if(msg_text!=NULL) { |
|
item->msg_text= malloc(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); |
|
} |
|
|
|
|