From d4ca67bae97344bf14a60af481a54368be54c4c6 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Mon, 2 Oct 2006 10:35:51 +0000 Subject: [PATCH] Implemented burn_abort() and made use of it --- trunk/cdrskin/cdrskin.c | 37 ++++++++++++- trunk/cdrskin/cdrskin_timestamp.h | 2 +- trunk/libburn/drive.c | 86 ++++++++++++++++++++++++++++--- trunk/libburn/drive.h | 4 +- trunk/libburn/libburn.h | 19 +++++++ trunk/libburn/libdax_msgs.c | 6 ++- trunk/libburn/libdax_msgs.h | 4 ++ 7 files changed, 147 insertions(+), 11 deletions(-) diff --git a/trunk/cdrskin/cdrskin.c b/trunk/cdrskin/cdrskin.c index 29ce4c8b..9a5ad470 100644 --- a/trunk/cdrskin/cdrskin.c +++ b/trunk/cdrskin/cdrskin.c @@ -167,6 +167,7 @@ or #define Cdrskin_libburn_has_convert_fs_adR 1 #define Cdrskin_libburn_has_convert_scsi_adR 1 #define Cdrskin_libburn_has_burn_msgS 1 +#define Cdrskin_libburn_has_burn_aborT 1 #endif #ifndef Cdrskin_libburn_versioN @@ -2633,10 +2634,20 @@ int Cdrskin_release_drive(struct CdrskiN *skin, int flag) */ int Cdrskin_abort_handler(struct CdrskiN *skin, int signum, int flag) { + +#ifdef Cdrskin_libburn_has_burn_aborT + + int ret; + +#else + int wait_grain= 100000,first_status= 1; + double start_time,last_time,current_time; + +#endif /* ! Cdrskin_libburn_has_burn_aborT */ + struct burn_progress p; enum burn_drive_status drive_status= BURN_DRIVE_GRABBING; - double start_time,last_time,current_time; if(getpid()!=skin->control_pid) { if(skin->verbosity>=Cdrskin_verbose_debuG) @@ -2660,6 +2671,27 @@ int Cdrskin_abort_handler(struct CdrskiN *skin, int signum, int flag) Cdrfifo_close_all(skin->fifo,0); #endif +#ifdef Cdrskin_libburn_has_burn_aborT + + /* Only for user info */ + if(skin->grabbed_drive!=NULL) + drive_status= burn_drive_get_status(skin->grabbed_drive,&p); + if(drive_status!=BURN_DRIVE_IDLE) { + fprintf(stderr,"cdrskin: ABORT : Abort processing depends on CD speed and buffer size\n"); + fprintf(stderr,"cdrskin: ABORT : Usually it is done with 4x speed after about a MINUTE\n"); + fprintf(stderr,"cdrskin: URGE : But wait at least the normal burning time before any kill -9\n"); + } + + ret= burn_abort(skin->abort_max_wait, burn_abort_pacifier, "cdrskin: "); + if(ret<=0) { + fprintf(stderr, + "\ncdrskin: ABORT : Cannot cancel burn session and release drive.\n"); + return(0); + } + fprintf(stderr,"\n"); + +#else /* Cdrskin_libburn_has_burn_aborT */ + if(skin->grabbed_drive!=NULL) { drive_status= burn_drive_get_status(skin->grabbed_drive,&p); if(drive_status!=BURN_DRIVE_IDLE && !skin->drive_is_grabbed) @@ -2751,6 +2783,9 @@ try_to_finish_lib:; fprintf(stderr,"cdrskin: ABORT : Trying to finish libburn.\n"); burn_finish(); } + +#endif /* ! Cdrskin_libburn_has_burn_aborT */ + fprintf(stderr, "cdrskin: ABORT : Drive is released and library is shut down now.\n"); fprintf(stderr, diff --git a/trunk/cdrskin/cdrskin_timestamp.h b/trunk/cdrskin/cdrskin_timestamp.h index ba36f450..6a9346d3 100644 --- a/trunk/cdrskin/cdrskin_timestamp.h +++ b/trunk/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2006.10.01.104140" +#define Cdrskin_timestamP "2006.10.02.103418" diff --git a/trunk/libburn/drive.c b/trunk/libburn/drive.c index 6ee6027e..99d692d4 100644 --- a/trunk/libburn/drive.c +++ b/trunk/libburn/drive.c @@ -27,9 +27,6 @@ extern struct libdax_msgs *libdax_messenger; static struct burn_drive drive_array[255]; static int drivetop = -1; -int burn_drive_is_open(struct burn_drive *d); -int burn_drive_convert_fs_adr_sub(char *path, char adr[], int *rec_count); - /* ts A60904 : ticket 62, contribution by elmom */ /* splitting former burn_drive_free() (which freed all, into two calls) */ @@ -527,13 +524,11 @@ void burn_drive_info_free(struct burn_drive_info drive_infos[]) burn_drive_free_all(); } -/* Experimental API call */ -int burn_drive_info_forget(struct burn_drive_info *info, int force) +/* ts A61001 : internal call */ +int burn_drive_forget(struct burn_drive *d, int force) { int occup; - struct burn_drive *d; - d = info->drive; occup = burn_drive_is_occupied(d); /* fprintf(stderr, "libburn: experimental: occup == %d\n",occup); @@ -556,6 +551,12 @@ int burn_drive_info_forget(struct burn_drive_info *info, int force) return 1; } +/* API call */ +int burn_drive_info_forget(struct burn_drive_info *info, int force) +{ + return burn_drive_forget(info->drive, force); +} + struct burn_disc *burn_drive_get_disc(struct burn_drive *d) { d->disc->refcnt++; @@ -954,3 +955,74 @@ int burn_drive_convert_fs_adr(char *path, char adr[]) return ret; } + +/** A pacifier function suitable for burn_abort. + @param handle If not NULL, a pointer to a text suitable for printf("%s") +*/ +int burn_abort_pacifier(void *handle, int patience, int elapsed) +{ + char *prefix= "libburn : "; + + if(handle!=NULL) + prefix= handle; + fprintf(stderr, + "\r%sABORT : Waiting for drive to finish since %d seconds (%d max)", + (char *) prefix, elapsed, patience); + return(1); +} + + +/** Abort any running drive operation and finis libburn. + @param patience Maximum number of seconds to wait for drives to finish + @param pacifier_func Function to produce appeasing messages. See + burn_abort_pacifier() for an example. + @return 1 ok, all went well + 0 had to leave a drive in unclean state + <0 severe error, do no use libburn again +*/ +int burn_abort(int patience, + int (*pacifier_func)(void *handle, int patience, int elapsed), + void *handle) +{ + int ret, i, occup, still_not_done= 1, pacifier_off= 0, first_round= 1; + unsigned long wait_grain= 100000; + time_t start_time, current_time, pacifier_time, end_time; + + current_time = start_time = pacifier_time = time(0); + end_time = start_time + patience; + while(current_time-end_time < patience) { + still_not_done = 0; + + for(i = 0; i < drivetop + 1; i++) { + occup = burn_drive_is_occupied(&(drive_array[i])); + if(occup == -2) + continue; + if(occup <= 10) { + burn_drive_forget(&(drive_array[i]), 1); + } else if(occup <= 100) { + if(first_round) + burn_drive_cancel(&(drive_array[i])); + still_not_done++; + } else if(occup <= 1000) { + still_not_done++; + } + } + first_round = 0; + + if(still_not_done == 0) + break; + usleep(wait_grain); + current_time = time(0); + if(current_time>pacifier_time) { + if(pacifier_func != NULL && !pacifier_off) { + ret = (*pacifier_func)(handle, patience, + current_time-start_time); + pacifier_off = (ret <= 0); + } + pacifier_time = current_time; + } + } + burn_finish(); + return(still_not_done == 0); +} + diff --git a/trunk/libburn/drive.h b/trunk/libburn/drive.h index 0adaa5eb..a0dd4cde 100644 --- a/trunk/libburn/drive.h +++ b/trunk/libburn/drive.h @@ -52,7 +52,9 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast); int burn_drive_get_block_types(struct burn_drive *d, enum burn_write_types write_type); -/* ts A60822 */ int burn_drive_is_open(struct burn_drive *d); +int burn_drive_is_occupied(struct burn_drive *d); +int burn_drive_forget(struct burn_drive *d, int force); +int burn_drive_convert_fs_adr_sub(char *path, char adr[], int *rec_count); #endif /* __DRIVE */ diff --git a/trunk/libburn/libburn.h b/trunk/libburn/libburn.h index aee20e98..5a5418f4 100644 --- a/trunk/libburn/libburn.h +++ b/trunk/libburn/libburn.h @@ -391,6 +391,25 @@ int burn_initialize(void); */ void burn_finish(void); + +/** Abort any running drive operation and finally call burn_finish(). + @param patience Maximum number of seconds to wait for drives to finish + @param pacifier_func If not NULL: a function to produce appeasing messages. + See burn_abort_pacifier() for an example. + @return 1 ok, all went well + 0 had to leave a drive in unclean state + <0 severe error, do no use libburn again +*/ +int burn_abort(int patience, + int (*pacifier_func)(void *handle, int patience, int elapsed), + void *handle); + +/** A pacifier function suitable for burn_abort. + @param handle If not NULL, a pointer to a text suitable for printf("%s") +*/ +int burn_abort_pacifier(void *handle, int patience, int elapsed); + + /** Set the verbosity level of the library. The default value is 0, which means that nothing is output on stderr. The more you increase this, the more debug output should be displayed on stderr for you. diff --git a/trunk/libburn/libdax_msgs.c b/trunk/libburn/libdax_msgs.c index 0e3cc883..5f179ae4 100644 --- a/trunk/libburn/libdax_msgs.c +++ b/trunk/libburn/libdax_msgs.c @@ -224,6 +224,8 @@ int libdax_msgs__text_to_sev(char *severity_name, int *severity, { 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,"SORRY",5)==0) @@ -253,12 +255,14 @@ int libdax_msgs__sev_to_text(int severity, char **severity_name, { if(flag&1) { *severity_name= - "NEVER\nFATAL\nSORRY\nWARNING\nHINT\nNOTE\nUPDATE\nDEBUG\nALL"; + "NEVER\nABORT\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_ABORT) + *severity_name= "ABORT"; else if(severity>=LIBDAX_MSGS_SEV_FATAL) *severity_name= "FATAL"; else if(severity>=LIBDAX_MSGS_SEV_SORRY) diff --git a/trunk/libburn/libdax_msgs.h b/trunk/libburn/libdax_msgs.h index efd10c6c..0d10a685 100644 --- a/trunk/libburn/libdax_msgs.h +++ b/trunk/libburn/libdax_msgs.h @@ -121,6 +121,10 @@ struct libdax_msgs_item; */ #define LIBDAX_MSGS_SEV_FATAL 0x70000000 +/** A message from an abort handler which will finally finish libburn +*/ +#define LIBDAX_MSGS_SEV_ABORT 0x71000000 + /** A severity to exclude resp. discard any possible message. Do not use this severity for submitting. */