From 1a684c064bae07a60c44d32265bd4a04493c4696 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Sat, 15 Sep 2012 17:04:32 +0000 Subject: [PATCH] New API call Xorriso_peek_outlists() --- libisoburn/trunk/libisoburn/libisoburn.ver | 1 + libisoburn/trunk/xorriso/base_obj.c | 8 ++ libisoburn/trunk/xorriso/parse_exec.c | 20 ++- libisoburn/trunk/xorriso/text_io.c | 140 ++++++++++++++++--- libisoburn/trunk/xorriso/xorriso.h | 27 ++++ libisoburn/trunk/xorriso/xorriso_private.h | 3 + libisoburn/trunk/xorriso/xorriso_timestamp.h | 2 +- 7 files changed, 175 insertions(+), 26 deletions(-) diff --git a/libisoburn/trunk/libisoburn/libisoburn.ver b/libisoburn/trunk/libisoburn/libisoburn.ver index f2449fd4..a35121b4 100644 --- a/libisoburn/trunk/libisoburn/libisoburn.ver +++ b/libisoburn/trunk/libisoburn/libisoburn.ver @@ -292,6 +292,7 @@ Xorriso_option_write_type; Xorriso_option_xattr; Xorriso_option_zisofs; Xorriso_parse_line; +Xorriso_peek_outlists; Xorriso_prescan_args; Xorriso_process_errfile; Xorriso_process_msg_queues; diff --git a/libisoburn/trunk/xorriso/base_obj.c b/libisoburn/trunk/xorriso/base_obj.c index a737c992..0392ac57 100644 --- a/libisoburn/trunk/xorriso/base_obj.c +++ b/libisoburn/trunk/xorriso/base_obj.c @@ -328,6 +328,8 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag) m->msgw_info_handler= NULL; m->msgw_info_handle= NULL; m->msgw_stack_handle= -1; + m->msgw_msg_pending= 0; + m->msgw_fetch_lock_ini= 0; m->msglist_stackfill= 0; m->status_history_max= Xorriso_status_history_maX; m->scsi_log= 0; @@ -465,6 +467,10 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag) if(ret != 0) goto failure; m->msg_watcher_lock_ini= 1; + ret= pthread_mutex_init(&(m->msgw_fetch_lock), NULL); + if(ret != 0) + goto failure; + m->msgw_fetch_lock_ini= 1; if(leafname != NULL) free(leafname); @@ -558,6 +564,8 @@ int Xorriso_destroy(struct XorrisO **xorriso, int flag) pthread_mutex_destroy(&(m->problem_status_lock)); if(m->msg_watcher_lock_ini) pthread_mutex_destroy(&(m->msg_watcher_lock)); + if(m->msgw_fetch_lock_ini) + pthread_mutex_destroy(&(m->msgw_fetch_lock)); free((char *) m); *xorriso= NULL; diff --git a/libisoburn/trunk/xorriso/parse_exec.c b/libisoburn/trunk/xorriso/parse_exec.c index 49e3a6c6..7a8cfdfd 100644 --- a/libisoburn/trunk/xorriso/parse_exec.c +++ b/libisoburn/trunk/xorriso/parse_exec.c @@ -1726,7 +1726,7 @@ next_command:; /* Test setup for for Xorriso_push_outlists() et.al. */ { - int stack_handle = -1, line_count; + int stack_handle = -1, line_count= 0; struct Xorriso_lsT *result_list, *info_list; int Xorriso_process_msg_lists(struct XorrisO *xorriso, struct Xorriso_lsT *result_list, @@ -1736,12 +1736,11 @@ next_command:; (*idx)++; if(strcmp(arg1, "push") == 0) { ret= Xorriso_push_outlists(xorriso, &stack_handle, 3); - fprintf(stderr, "xorriso -test: Xorriso_push() = %d, handle = %d\n", + fprintf(stderr, "xorriso -test: 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); + fprintf(stderr, "xorriso -test: pull = %d\n", ret); if(ret > 0) { ret= Xorriso_process_msg_lists(xorriso, result_list, info_list, &line_count, 0); @@ -1751,8 +1750,7 @@ next_command:; } } 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); + fprintf(stderr, "xorriso -test: fetch = %d\n", ret); if(ret > 0) { ret= Xorriso_process_msg_lists(xorriso, result_list, info_list, &line_count, 0); @@ -1760,6 +1758,16 @@ next_command:; "xorriso -test: Xorriso_process_msg_lists() = %d, line_count = %d\n", ret, line_count); } + } else if(strcmp(arg1, "peek") == 0) { + ret= Xorriso_peek_outlists(xorriso, -1, 0, 0); + fprintf(stderr, "xorriso -test: peek = %d\n", ret); + } else if(strcmp(arg1, "sleep_peek") == 0) { + usleep(1000000); + ret= Xorriso_peek_outlists(xorriso, -1, 0, 0); + fprintf(stderr, "xorriso -test: sleep_peek = %d\n", ret); + } else if(strcmp(arg1, "peek_loop") == 0) { + ret= Xorriso_peek_outlists(xorriso, -1, 3, 4); + fprintf(stderr, "xorriso -test: peek_loop = %d\n", ret); } else if(strcmp(arg1, "start") == 0) { ret= Xorriso_start_msg_watcher(xorriso, NULL, NULL, NULL, NULL, 0); fprintf(stderr, "xorriso -test: Xorriso_start_msg_watcher() = %d\n", ret); diff --git a/libisoburn/trunk/xorriso/text_io.c b/libisoburn/trunk/xorriso/text_io.c index c4343199..fc2dc1f5 100644 --- a/libisoburn/trunk/xorriso/text_io.c +++ b/libisoburn/trunk/xorriso/text_io.c @@ -522,44 +522,76 @@ ex:; } -static int Xorriso_lock_outlists(struct XorrisO *xorriso, int flag) +/* @param flag bit0= no error message in case of failure +*/ +static int Xorriso_obtain_lock(struct XorrisO *xorriso, + pthread_mutex_t *lock_handle, + char *purpose, int flag) { int ret; static int complaints= 0, complaint_limit= 5; - ret= pthread_mutex_lock(&(xorriso->result_msglists_lock)); + ret= pthread_mutex_lock(lock_handle); if(ret != 0) { + if(flag & 1) + return(-1); /* Cannot report failure through the failing message output system */ complaints++; - if(complaints < complaint_limit) + if(complaints <= complaint_limit) fprintf(stderr, - "xorriso : pthread_mutex_lock() for outlists returns %d\n", - ret); + "xorriso : pthread_mutex_lock() for %s returns %d\n", + purpose, ret); return(-1); } return(1); } -static int Xorriso_unlock_outlists(struct XorrisO *xorriso, int flag) +/* @param flag bit0= no error message in case of failure +*/ +static int Xorriso_release_lock(struct XorrisO *xorriso, + pthread_mutex_t *lock_handle, + char *purpose, int flag) { int ret; static int complaints= 0, complaint_limit= 5; - ret= pthread_mutex_unlock(&(xorriso->result_msglists_lock)); + ret= pthread_mutex_unlock(lock_handle); if(ret != 0) { + if(flag & 1) + return(0); /* Cannot report failure through the failing message output system */ complaints++; - if(complaints < complaint_limit) + if(complaints <= complaint_limit) fprintf(stderr, - "xorriso : pthread_mutex_unlock() for outlists returns %d\n", - ret); + "xorriso : pthread_mutex_unlock() for %s returns %d\n", + purpose, ret); return(0); } return(1); } +static int Xorriso_lock_outlists(struct XorrisO *xorriso, int flag) +{ + int ret; + + ret= Xorriso_obtain_lock(xorriso, &(xorriso->result_msglists_lock), + "outlists", 0); + return(ret); +} + + +static int Xorriso_unlock_outlists(struct XorrisO *xorriso, int flag) +{ + int ret; + + ret= Xorriso_release_lock(xorriso, &(xorriso->result_msglists_lock), + "outlists", 0); + return(ret); +} + + static int Xorriso_write_to_msglist(struct XorrisO *xorriso, struct Xorriso_lsT **xorriso_msglist, char *text, int flag) @@ -850,13 +882,6 @@ int Xorriso_fetch_outlists(struct XorrisO *xorriso, int stack_handle, #ifdef Xorriso_fetch_with_msg_queueS - /* >>> This would need more locking around - xorriso->problem_status= sev; - Probably also locking of - Xorriso_info(), Xorriso_result - because unredirected output could collide. - */ - ret= Xorriso_process_msg_queues(xorriso, 0); if(ret <= 0) goto ex; @@ -896,6 +921,59 @@ ex:; } +int Xorriso_peek_outlists(struct XorrisO *xorriso, int stack_handle, + int timeout, int flag) +{ + int ret, locked= 0, yes= 0; + static int u_wait= 19000; + time_t start_time; + + if((flag & 3) == 0) + flag|= 3; + if(stack_handle == -1) + stack_handle= xorriso->msglist_stackfill - 1; + start_time= time(NULL); + +try_again:; + ret= Xorriso_obtain_lock(xorriso, &(xorriso->msgw_fetch_lock), + "message watcher fetch operation", 0); + if(ret <= 0) + {yes= -2; goto ex;} + locked= 1; + + yes= 0; + if(stack_handle < 0 || stack_handle >= xorriso->msglist_stackfill) + {yes= -1; goto ex;} + if(flag & 1) + yes|= (xorriso->result_msglists[stack_handle] != NULL); + if(flag & 2) + yes|= (xorriso->info_msglists[stack_handle] != NULL); + if(xorriso->msg_watcher_state == 2 && xorriso->msgw_msg_pending) + yes|= 2; + + ret= Xorriso_release_lock(xorriso, &(xorriso->msgw_fetch_lock), + "message watcher fetch operation", 0); + if(ret <= 0) + {yes= -2; goto ex;} + locked= 0; + + if(yes && (flag & 4)) { + usleep(u_wait); + if(time(NULL) <= start_time + timeout) + goto try_again; + } + +ex:; + if(locked) { + ret= Xorriso_release_lock(xorriso, &(xorriso->msgw_fetch_lock), + "message watcher fetch operation", 0); + if(ret <= 0 && yes >= 0) + yes= -2; + } + return(yes); +} + + int Xorriso_pull_outlists(struct XorrisO *xorriso, int stack_handle, struct Xorriso_lsT **result_list, struct Xorriso_lsT **info_list, int flag) @@ -1025,18 +1103,31 @@ static void *Xorriso_msg_watcher(void *state_pt) if(xorriso->msg_watcher_state == 3) break; + Xorriso_obtain_lock(xorriso, &(xorriso->msgw_fetch_lock), + "message watcher fetch operation", 1); + xorriso->msgw_msg_pending= 1; ret= Xorriso_fetch_outlists(xorriso, -1, &result_list, &info_list, 3); - if(ret < 0) - break; if(ret > 0) { /* Process fetched lines */ + xorriso->msgw_msg_pending= 2; + Xorriso_release_lock(xorriso, &(xorriso->msgw_fetch_lock), + "message watcher fetch operation", 1); ret= Xorriso_process_msg_lists(xorriso, result_list, info_list, &line_count, 0); + xorriso->msgw_msg_pending= 0; Xorriso_lst_destroy_all(&result_list, 0); Xorriso_lst_destroy_all(&info_list, 0); if(ret < 0) break; + } else { + xorriso->msgw_msg_pending= 0; + Xorriso_release_lock(xorriso, &(xorriso->msgw_fetch_lock), + "message watcher fetch operation", 1); } + xorriso->msgw_msg_pending= 0; + + if(ret < 0) + break; if(line_count < sleep_thresh) usleep(u_wait); @@ -1179,13 +1270,24 @@ int Xorriso_stop_msg_watcher(struct XorrisO *xorriso, int flag) usleep(u_wait); } + Xorriso_obtain_lock(xorriso, &(xorriso->msgw_fetch_lock), + "message watcher fetch operation", 1); + xorriso->msgw_msg_pending= 1; ret= Xorriso_pull_outlists(xorriso, xorriso->msgw_stack_handle, &result_list, &info_list, 0); if(ret > 0) { + xorriso->msgw_msg_pending= 2; + Xorriso_release_lock(xorriso, &(xorriso->msgw_fetch_lock), + "message watcher fetch operation", 1); Xorriso_process_msg_lists(xorriso, result_list, info_list, &line_count, 0); + xorriso->msgw_msg_pending= 0; Xorriso_lst_destroy_all(&result_list, 0); Xorriso_lst_destroy_all(&info_list, 0); + } else { + xorriso->msgw_msg_pending= 0; + Xorriso_release_lock(xorriso, &(xorriso->msgw_fetch_lock), + "message watcher fetch operation", 1); } xorriso->msgw_result_handler= NULL; diff --git a/libisoburn/trunk/xorriso/xorriso.h b/libisoburn/trunk/xorriso/xorriso.h index 9b436a63..5dcb5473 100644 --- a/libisoburn/trunk/xorriso/xorriso.h +++ b/libisoburn/trunk/xorriso/xorriso.h @@ -628,6 +628,33 @@ int Xorriso_fetch_outlists(struct XorrisO *xorriso, int stack_handle, struct Xorriso_lsT **info_list, int flag); +/** Inquire whether messages are pending in redirected result and info channel. + This may be used to determine whether a concurrent message watcher already + has obtained all pending messages. + @since 1.2.6 + @param xorriso The environment handle + @param stack_handle An id number returned by Xorriso_push_outlists() + and not yet revoked by Xorriso_pull_outlists(). + Submit -1 to address the most recent valid id. + @param timeout Number of seconds after which to return despite + flag bit 2 + @param flag Bitfield for control purposes + bit0= fetch result channel + bit1= fetch info channel + bit2= wait and retry until return is 0 or -1 + If bit0 and bit1 are 0, both channels get fetched. + @return If > 0: + bit0= messages are pending in outlists + bit1= message watcher is processing fetched messages + Else: + 0= no messages are pending anywhere + -1= inappropriate stack_handle + -2= locking failed +*/ +int Xorriso_peek_outlists(struct XorrisO *xorriso, int stack_handle, + int timeout, int flag); + + /** Disable the redirection given by stack_handle. If it was the current receiver of messages then switch output to the next older redirection resp. to the normal channels if no redirections are stacked any more. diff --git a/libisoburn/trunk/xorriso/xorriso_private.h b/libisoburn/trunk/xorriso/xorriso_private.h index 45a4fefa..afe00f2b 100644 --- a/libisoburn/trunk/xorriso/xorriso_private.h +++ b/libisoburn/trunk/xorriso/xorriso_private.h @@ -587,6 +587,9 @@ struct XorrisO { /* the global context of xorriso */ int (*msgw_info_handler)(void *handle, char *text); void *msgw_info_handle; int msgw_stack_handle; + int msgw_msg_pending; /* 0=no, 1=fetching(i.e. maybe) , 2=yes */ + int msgw_fetch_lock_ini; + pthread_mutex_t msgw_fetch_lock; int status_history_max; /* for -status long_history */ diff --git a/libisoburn/trunk/xorriso/xorriso_timestamp.h b/libisoburn/trunk/xorriso/xorriso_timestamp.h index 7dc65092..3eee3d6c 100644 --- a/libisoburn/trunk/xorriso/xorriso_timestamp.h +++ b/libisoburn/trunk/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2012.09.15.095146" +#define Xorriso_timestamP "2012.09.15.170346"