New API call Xorriso_start_msg_watcher()

This commit is contained in:
Thomas Schmitt 2012-09-14 17:52:21 +00:00
parent fcc00d4311
commit eaa501c9ec
10 changed files with 407 additions and 9 deletions

View File

@ -300,7 +300,9 @@ Xorriso_pull_outlists;
Xorriso_push_outlists;
Xorriso_read_rc;
Xorriso_set_problem_status;
Xorriso_start_msg_watcher;
Xorriso_startup_libraries;
Xorriso_stop_msg_watcher;
local: *;
};

View File

@ -656,6 +656,19 @@ int Xorriso_lst_get_last(struct Xorriso_lsT *entry, struct Xorriso_lsT **last,
}
int Xorriso_lst_concat(struct Xorriso_lsT *first, struct Xorriso_lsT *second,
int flag)
{
struct Xorriso_lsT *last;
Xorriso_lst_get_last(first, &last, 0);
if(last != NULL)
last->next= second;
if(second != NULL)
second->prev= last;
return(1);
}
/* --------------------------- End Xorriso_lsT ---------------------------- */

View File

@ -133,6 +133,9 @@ int Xorriso_lst_detach_text(struct Xorriso_lsT *entry, int flag);
int Xorriso_lst_get_last(struct Xorriso_lsT *entry, struct Xorriso_lsT **last,
int flag);
int Xorriso_lst_concat(struct Xorriso_lsT *first, struct Xorriso_lsT *second,
int flag);
int Exclusions_new(struct ExclusionS **o, int flag);

View File

@ -321,6 +321,11 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag)
m->lib_msg_queue_lock_ini= 0;
m->result_msglists_lock_ini= 0;
m->write_to_channel_lock_ini= 0;
m->msg_watcher_lock_ini= 0;
m->msg_watcher_state= 0;
m->msgw_result_handler= NULL;
m->msgw_info_handler= NULL;
m->msgw_stack_handle= -1;
m->msglist_stackfill= 0;
m->status_history_max= Xorriso_status_history_maX;
m->scsi_log= 0;
@ -454,6 +459,10 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag)
if(ret != 0)
goto failure;
m->problem_status_lock_ini= 1;
ret= pthread_mutex_init(&(m->msg_watcher_lock), NULL);
if(ret != 0)
goto failure;
m->msg_watcher_lock_ini= 1;
if(leafname != NULL)
free(leafname);
@ -545,6 +554,8 @@ int Xorriso_destroy(struct XorrisO **xorriso, int flag)
pthread_mutex_destroy(&(m->write_to_channel_lock));
if(m->problem_status_lock_ini)
pthread_mutex_destroy(&(m->problem_status_lock));
if(m->msg_watcher_lock_ini)
pthread_mutex_destroy(&(m->msg_watcher_lock));
free((char *) m);
*xorriso= NULL;

View File

@ -1724,7 +1724,57 @@ next_command:;
} else if(strcmp(cmd,"test")==0) { /* This option does not exist. */
/* install temporary test code here */;
/* Test setup for for Xorriso_push_outlists() et.al. */
{
int stack_handle = -1, line_count;
struct Xorriso_lsT *result_list, *info_list;
int Xorriso_process_msg_lists(struct XorrisO *xorriso,
struct Xorriso_lsT *result_list,
struct Xorriso_lsT *info_list,
int *line_count, int flag);
(*idx)++;
if(strcmp(arg1, "push") == 0) {
ret= Xorriso_push_outlists(xorriso, &stack_handle, 3);
fprintf(stderr, "xorriso -test: Xorriso_push() = %d, handle = %d\n",
ret, stack_handle);
} else if(strcmp(arg1, "pull") == 0) {
ret= Xorriso_pull_outlists(xorriso, -1, &result_list, &info_list, 0);
fprintf(stderr, "xorriso -test: Xorriso_push() = %d, handle = %d\n",
ret, stack_handle);
if(ret > 0) {
ret= Xorriso_process_msg_lists(xorriso, result_list, info_list,
&line_count, 0);
fprintf(stderr,
"xorriso -test: Xorriso_process_msg_lists() = %d, line_count = %d\n",
ret, line_count);
}
} else if(strcmp(arg1, "fetch") == 0) {
ret= Xorriso_fetch_outlists(xorriso, -1, &result_list, &info_list, 0);
fprintf(stderr, "xorriso -test: Xorriso_fetch() = %d, handle = %d\n",
ret, stack_handle);
if(ret > 0) {
ret= Xorriso_process_msg_lists(xorriso, result_list, info_list,
&line_count, 0);
fprintf(stderr,
"xorriso -test: Xorriso_process_msg_lists() = %d, line_count = %d\n",
ret, line_count);
}
} else if(strcmp(arg1, "start") == 0) {
ret= Xorriso_start_msg_watcher(xorriso, NULL, NULL, 0);
fprintf(stderr, "xorriso -test: Xorriso_start_msg_watcher() = %d\n", ret);
} else if(strcmp(arg1, "stop") == 0) {
ret= Xorriso_stop_msg_watcher(xorriso, 0);
fprintf(stderr, "xorriso -test: Xorriso_stop_msg_watcher() = %d\n", ret);
} else {
fprintf(stderr, "xorriso -test: unknwon mode: %s\n", arg1);
}
ret= 0;
}
/* Test setup for Xorriso_parse_line */
if(0){
int pargc, pflag, max_words;
char **pargv= NULL, *pline, *prefix, *separators;

View File

@ -906,19 +906,30 @@ int Xorriso_pull_outlists(struct XorrisO *xorriso, int stack_handle,
if(ret > 0)
locked= 1;
if(stack_handle == -1)
stack_handle= xorriso->msglist_stackfill - 1;
if(stack_handle < 0 || stack_handle >= xorriso->msglist_stackfill) {
Xorriso_msgs_submit(xorriso, 0,
"Program error: Wrong message output redirection stack handle",
0, "FATAL", 0);
ret= -1; goto ex;
}
*result_list= xorriso->result_msglists[stack_handle];
*info_list= xorriso->info_msglists[stack_handle];
for(i = stack_handle + 1; i < xorriso->msglist_stackfill - 1; i++) {
xorriso->result_msglists[i - 1]= xorriso->result_msglists[i];
xorriso->info_msglists[i - 1]= xorriso->info_msglists[i];
/* Concatenate all redirections above stack_handle */
*result_list= NULL;
*info_list= NULL;
for(i = stack_handle; i < xorriso->msglist_stackfill; i++) {
if(*result_list == NULL)
*result_list= xorriso->result_msglists[i];
else
Xorriso_lst_concat(*result_list, xorriso->result_msglists[i], 0);
if(*info_list == NULL)
*info_list= xorriso->info_msglists[i];
else
Xorriso_lst_concat(*info_list, xorriso->info_msglists[i], 0);
}
xorriso->msglist_stackfill--;
xorriso->msglist_stackfill= stack_handle;
ret= 1;
ex:;
if(locked)
@ -927,6 +938,260 @@ ex:;
}
int Xorriso_result_handler_stdout(struct XorrisO *xorriso, char *text)
{
printf("%s", text);
fflush(stdout);
return(1);
}
int Xorriso_info_handler_stderr(struct XorrisO *xorriso, char *text)
{
if(xorriso->stderr_fp != NULL) {
fprintf(xorriso->stderr_fp, "%s", text);
fflush(xorriso->stderr_fp);
} else {
fprintf(stderr, "%s", text);
fflush(stderr);
}
return(1);
}
int Xorriso_process_msg_lists(struct XorrisO *xorriso,
struct Xorriso_lsT *result_list,
struct Xorriso_lsT *info_list,
int *line_count, int flag)
{
struct Xorriso_lsT *lpt;
int ret;
int (*handler)(struct XorrisO *xorriso, char *text);
handler= xorriso->msgw_result_handler;
if(handler == NULL)
handler= Xorriso_result_handler_stdout;
for(lpt= result_list; lpt != NULL; lpt= lpt->next) {
(*line_count)++;
ret= (*handler)(xorriso, Xorriso_lst_get_text(lpt, 0));
if(ret < 0)
return(-1);
}
handler= xorriso->msgw_info_handler;
if(handler == NULL)
handler= Xorriso_info_handler_stderr;
for(lpt= info_list; lpt != NULL; lpt= lpt->next) {
(*line_count)++;
ret= (*handler)(xorriso, Xorriso_lst_get_text(lpt, 0));
if(ret < 0)
return(-1);
}
return(1);
}
static void *Xorriso_msg_watcher(void *state_pt)
{
struct XorrisO *xorriso;
int ret, u_wait= 10000, line_count, sleep_thresh= 20;
struct Xorriso_lsT *result_list= NULL, *info_list= NULL;
static int debug_sev= 0;
xorriso= (struct XorrisO *) state_pt;
if(debug_sev == 0)
Xorriso__text_to_sev("DEBUG", &debug_sev, 0);
xorriso->msg_watcher_state= 2;
if(xorriso->msgw_info_handler != NULL &&
debug_sev < xorriso->report_about_severity &&
debug_sev < xorriso->abort_on_severity)
(*xorriso->msgw_info_handler)(xorriso,
"xorriso : DEBUG : Concurrent message watcher started\n");
while(1) {
line_count= 0;
/* Watch out for end request in xorriso */
if(xorriso->msg_watcher_state == 3)
break;
ret= Xorriso_fetch_outlists(xorriso, -1, &result_list, &info_list, 3);
if(ret < 0)
break;
if(ret > 0) {
/* Process fetched lines */
ret= Xorriso_process_msg_lists(xorriso, result_list, info_list,
&line_count, 0);
Xorriso_lst_destroy_all(&result_list, 0);
Xorriso_lst_destroy_all(&info_list, 0);
if(ret < 0)
break;
}
if(line_count < sleep_thresh)
usleep(u_wait);
}
if(xorriso->msgw_info_handler != NULL &&
debug_sev < xorriso->report_about_severity &&
debug_sev < xorriso->abort_on_severity)
(*xorriso->msgw_info_handler)(xorriso,
"xorriso : DEBUG : Concurrent message watcher ended\n");
xorriso->msg_watcher_state= 0;
return(NULL);
}
int Xorriso_start_msg_watcher(struct XorrisO *xorriso,
int (*result_handler)(struct XorrisO *xorriso, char *text),
int (*info_handler)(struct XorrisO *xorriso, char *text),
int flag)
{
int ret, u_wait= 1000, locked= 0, pushed= 0, uret, line_count= 0;
struct Xorriso_lsT *result_list= NULL, *info_list= NULL;
pthread_attr_t attr;
pthread_attr_t *attr_pt = NULL;
pthread_t thread;
ret= pthread_mutex_lock(&(xorriso->msg_watcher_lock));
if(ret != 0) {
Xorriso_msgs_submit(xorriso, 0,
"Cannot aquire mutex lock for managing concurrent message watcher",
ret, "FATAL", 0);
ret= -1; goto ex;
}
locked= 1;
/* Check for running watcher */
if(xorriso->msg_watcher_state > 0) {
sprintf(xorriso->info_text,
"There is already a concurrent message watcher running");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
ret= 0; goto ex;
}
ret= Xorriso_push_outlists(xorriso, &(xorriso->msgw_stack_handle), 3);
if(ret <= 0)
goto ex;
pushed= 1;
/* Register watcher */
xorriso->msgw_result_handler= result_handler;
xorriso->msgw_info_handler= info_handler;
xorriso->msg_watcher_state= 1;
/* Start thread */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
attr_pt= &attr;
ret= pthread_create(&thread, attr_pt, Xorriso_msg_watcher, xorriso);
if(ret != 0) {
sprintf(xorriso->info_text,
"Cannot create thread for concurrent message watcher");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
ret= 0; goto ex;
}
/* Wait until watcher has indicated start */
while(xorriso->msg_watcher_state == 1) {
/* >>> have a timeout ? */;
usleep(u_wait);
}
ret= 1;
ex:;
if(ret <= 0 && pushed) {
uret= Xorriso_pull_outlists(xorriso, xorriso->msgw_stack_handle,
&result_list, &info_list, 0);
if(uret > 0) {
xorriso->msgw_result_handler= NULL;
xorriso->msgw_info_handler= NULL;
Xorriso_process_msg_lists(xorriso, result_list, info_list,
&line_count, 0);
Xorriso_lst_destroy_all(&result_list, 0);
Xorriso_lst_destroy_all(&info_list, 0);
}
}
if(locked) {
uret= pthread_mutex_unlock(&(xorriso->msg_watcher_lock));
if(uret != 0) {
Xorriso_msgs_submit(xorriso, 0,
"Cannot release mutex lock for managing concurrent message watcher",
uret, "FATAL", 0);
ret= -1;
}
}
return(ret);
}
/* @param flag bit0= do not complain loudly if no wather is active
*/
int Xorriso_stop_msg_watcher(struct XorrisO *xorriso, int flag)
{
int ret, u_wait= 1000, locked= 0, uret, line_count= 0;
struct Xorriso_lsT *result_list= NULL, *info_list= NULL;
if((flag & 1) && xorriso->msg_watcher_state != 2)
/* Roughly tolerate non-running watcher */
{ret= 0; goto ex;}
ret= pthread_mutex_lock(&(xorriso->msg_watcher_lock));
if(ret != 0) {
Xorriso_msgs_submit(xorriso, 0,
"Cannot aquire mutex lock for managing concurrent message watcher",
ret, "FATAL", 0);
ret= -1; goto ex;
}
locked= 1;
/* Check for running watcher */
if(xorriso->msg_watcher_state != 2) {
sprintf(xorriso->info_text,
"There is no concurrent message watcher running");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY", 0);
ret= 0; goto ex;
}
/* Inform watcher of desire to stop it */
xorriso->msg_watcher_state= 3;
/* Wait until watcher has indicated its end */
while(xorriso->msg_watcher_state != 0) {
/* >>> have a timeout ? */;
usleep(u_wait);
}
ret= Xorriso_pull_outlists(xorriso, xorriso->msgw_stack_handle,
&result_list, &info_list, 0);
if(ret > 0) {
Xorriso_process_msg_lists(xorriso, result_list, info_list,
&line_count, 0);
Xorriso_lst_destroy_all(&result_list, 0);
Xorriso_lst_destroy_all(&info_list, 0);
}
xorriso->msgw_result_handler= NULL;
xorriso->msgw_info_handler= NULL;
ret= 1;
ex:;
if(locked) {
uret= pthread_mutex_unlock(&(xorriso->msg_watcher_lock));
if(uret != 0) {
Xorriso_msgs_submit(xorriso, 0,
"Cannot release mutex lock for managing concurrent message watcher",
uret, "FATAL", 0);
ret= -1;
}
}
return(ret);
}
int Xorriso_result(struct XorrisO *xorriso, int flag)
/*
bit0= no considerations or computations or dialog. Just put out.

View File

@ -580,8 +580,9 @@ struct Xorriso_lsT;
and the Xorriso_option_pkt_output() protocol will not be applied.
@param xorriso The environment handle
@param stack_handle returns an id number which is unique as long as
its redirection is stacked. It may be re-used after
its redirection was pulled from the stack.
its redirection is stacked. Do not interpret it and
do not use it after its redirection was pulled from
the stack.
@param flag Bitfield for control purposes
bit0= redirect result channel
bit1= redirect info channel
@ -635,6 +636,7 @@ int Xorriso_fetch_outlists(struct XorrisO *xorriso, int stack_handle,
@param stack_handle An id number returned by Xorriso_push_outlists()
and not yet revoked by Xorriso_pull_outlists().
This handle is invalid after the call.
Submit -1 to address the most recent valid id.
@param result_list Result and mark messages (usually directed to stdout)
@param info_list Info and mark messages (usually directed to stderr)
@param flag unused yet, submit 0
@ -645,6 +647,46 @@ int Xorriso_pull_outlists(struct XorrisO *xorriso, int stack_handle,
struct Xorriso_lsT **info_list, int flag);
/** Redirect output by Xorriso_push_outlists() and start a thread which
fetches this output and performs a call of a given function with each
message that is obtained.
@since 1.2.6
@param xorriso The environment handle
@param result_handler Pointer to the function which shall be called with
each result message. A NULL pointer causes output
to be directed to stdout.
The function should use the pointer xorriso with
outmost caution, because nearly all API calls are not
thread-safe and may not be used. Best is to use it
only to distinguish the callers if more than one
struct XorrisO is in use by the application.
@param info_handler Pointer to the function which shall be called with
each info message. A NULL pointer causes output to
be directed to stderr resp. to -as mkisofs -log-file.
The same caution is needed as with result_handler.
@param flag unused yet, submit 0
@return 1 on success, <=0 if failure (e.g. there is already
a watcher active)
*/
int Xorriso_start_msg_watcher(struct XorrisO *xorriso,
int (*result_handler)(struct XorrisO *xorriso, char *text),
int (*info_handler)(struct XorrisO *xorriso, char *text),
int flag);
/** Revoke output redirection by Xorriso_start_msg_watcher() and end the
watcher thread. If text messages are delivered when Xorriso_pull_outlists()
is called, then they get put out through the active handler functions.
@since 1.2.6
@param xorriso The environment handle
@param flag Bitfield for control purposes:
bit0= do not issue SORRY message if no message
watcher is active
@return 1 on success, <=0 if failure
*/
int Xorriso_stop_msg_watcher(struct XorrisO *xorriso, int flag);
/** Obtain the text message from the current list item.
@param entry The current list item
@param flag unused yet, submit 0

View File

@ -274,6 +274,7 @@ int main(int argc, char **argv)
{ret= 6; goto emergency_exit;}
end_successfully:; /* normal shutdown, including eventual -commit */
Xorriso_stop_msg_watcher(xorriso, 1);
Xorriso_process_msg_queues(xorriso, 0);
if(Xorriso_change_is_pending(xorriso, 1))
Xorriso_option_end(xorriso, 2);

View File

@ -575,6 +575,17 @@ struct XorrisO { /* the global context of xorriso */
int write_to_channel_lock_ini;
pthread_mutex_t write_to_channel_lock;
int msg_watcher_lock_ini;
pthread_mutex_t msg_watcher_lock;
int msg_watcher_state; /* 0= inactive
1= registered
2= started
3= request to end
*/
int (*msgw_result_handler)(struct XorrisO *xorriso, char *text);
int (*msgw_info_handler)(struct XorrisO *xorriso, char *text);
int msgw_stack_handle;
int status_history_max; /* for -status long_history */
/* 0= no logging of SCSI commands, 1= to stderr */

View File

@ -1 +1 @@
#define Xorriso_timestamP "2012.09.13.130910"
#define Xorriso_timestamP "2012.09.14.175104"