diff options
Diffstat (limited to 'main.cc')
-rw-r--r-- | main.cc | 106 |
1 files changed, 66 insertions, 40 deletions
@@ -1,4 +1,4 @@ -/* Plzip - A parallel compressor compatible with lzip +/* Plzip - Parallel compressor compatible with lzip Copyright (C) 2009 Laszlo Ersek. Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz. @@ -96,13 +96,11 @@ const mode_t usr_rw = S_IRUSR | S_IWUSR; const mode_t all_rw = usr_rw | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; mode_t outfd_mode = usr_rw; bool delete_output_on_interrupt = false; -pthread_t main_thread; -pid_t main_thread_pid; void show_help( const long num_online ) { - std::printf( "%s - A parallel compressor compatible with lzip.\n", Program_name ); + std::printf( "%s - Parallel compressor compatible with lzip.\n", Program_name ); std::printf( "\nUsage: %s [options] [files]\n", invocation_name ); std::printf( "\nOptions:\n" " -h, --help display this help and exit\n" @@ -262,12 +260,13 @@ int open_instream( const char * const name, struct stat * const in_statsp, const bool can_read = ( i == 0 && ( S_ISBLK( mode ) || S_ISCHR( mode ) || S_ISFIFO( mode ) || S_ISSOCK( mode ) ) ); - if( i != 0 || ( !S_ISREG( mode ) && ( !to_stdout || !can_read ) ) ) + const bool no_ofile = to_stdout || ( program_mode == m_test ); + if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || !no_ofile ) ) ) { if( verbosity >= 0 ) std::fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n", program_name, name, - ( can_read && !to_stdout ) ? + ( can_read && !no_ofile ) ? " and '--stdout' was not specified" : "" ); close( infd ); infd = -1; @@ -340,22 +339,6 @@ bool check_tty( const int infd, const Mode program_mode ) } -void cleanup_and_fail( const int retval ) - { - if( delete_output_on_interrupt ) - { - delete_output_on_interrupt = false; - if( verbosity >= 0 ) - std::fprintf( stderr, "%s: Deleting output file '%s', if it exists.\n", - program_name, output_filename.c_str() ); - if( outfd >= 0 ) { close( outfd ); outfd = -1; } - if( std::remove( output_filename.c_str() ) != 0 && errno != ENOENT ) - show_error( "WARNING: deletion of output file (apparently) failed." ); - } - std::exit( retval ); - } - - // Set permissions, owner and times. void close_and_set_permissions( const struct stat * const in_statsp ) { @@ -382,13 +365,10 @@ void close_and_set_permissions( const struct stat * const in_statsp ) } -extern "C" void signal_handler( int sig ) +extern "C" void signal_handler( int ) { - if( !pthread_equal( pthread_self(), main_thread ) ) - kill( main_thread_pid, sig ); - if( sig != SIGUSR1 && sig != SIGUSR2 ) - show_error( "Control-C or similar caught, quitting." ); - cleanup_and_fail( ( sig != SIGUSR2 ) ? 1 : 2 ); + show_error( "Control-C or similar caught, quitting." ); + cleanup_and_fail( 1 ); } @@ -405,14 +385,6 @@ void set_signals() int verbosity = 0; -// This can be called from any thread, main thread or sub-threads alike, -// since they all call common helper functions that call fatal() in case -// of an error. -// -void fatal( const int retval ) - { signal_handler( ( retval != 2 ) ? SIGUSR1 : SIGUSR2 ); } - - void Pretty_print::operator()( const char * const msg ) const { if( verbosity >= 0 ) @@ -456,6 +428,60 @@ void internal_error( const char * const msg ) } +// This can be called from any thread, main thread or sub-threads alike, +// since they all call common helper functions that call cleanup_and_fail() +// in case of an error. +// +void cleanup_and_fail( const int retval ) + { + // only one thread can delete and exit + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + + pthread_mutex_lock( &mutex ); // ignore errors to avoid loop + if( delete_output_on_interrupt ) + { + delete_output_on_interrupt = false; + if( verbosity >= 0 ) + std::fprintf( stderr, "%s: Deleting output file '%s', if it exists.\n", + program_name, output_filename.c_str() ); + if( outfd >= 0 ) { close( outfd ); outfd = -1; } + if( std::remove( output_filename.c_str() ) != 0 && errno != ENOENT ) + show_error( "WARNING: deletion of output file (apparently) failed." ); + } + std::exit( retval ); + } + + +void show_progress( const int packet_size, + const Pretty_print * const p, + const struct stat * const in_statsp ) + { + static unsigned long long cfile_size = 0; // file_size / 100 + static unsigned long long pos = 0; + static const Pretty_print * pp = 0; + static pthread_mutex_t mutex; + + if( p ) // initialize static vars + { + if( !pp ) xinit( &mutex ); // init mutex only once + pos = 0; pp = p; + cfile_size = ( in_statsp && S_ISREG( in_statsp->st_mode ) ) ? + in_statsp->st_size / 100 : 0; + return; + } + if( pp ) + { + xlock( &mutex ); + pos += packet_size; + if( cfile_size > 0 ) + std::fprintf( stderr, "%4llu%%", pos / cfile_size ); + std::fprintf( stderr, " %.1f MB\r", pos / 1000000.0 ); + pp->reset(); (*pp)(); // restore cursor position + xunlock( &mutex ); + } + } + + int main( const int argc, const char * const argv[] ) { // Mapping from gzip/bzip2 style 1..9 compression modes @@ -486,8 +512,6 @@ int main( const int argc, const char * const argv[] ) bool recompress = false; bool to_stdout = false; invocation_name = argv[0]; - main_thread = pthread_self(); - main_thread_pid = getpid(); if( LZ_version()[0] != LZ_version_string[0] ) internal_error( "bad library version" ); @@ -598,8 +622,6 @@ int main( const int argc, const char * const argv[] ) if( !to_stdout && program_mode != m_test && ( filenames_given || default_output_filename.size() ) ) set_signals(); - std::signal( SIGUSR1, signal_handler ); - std::signal( SIGUSR2, signal_handler ); Pretty_print pp( filenames ); @@ -668,9 +690,13 @@ int main( const int argc, const char * const argv[] ) if( verbosity >= 1 ) pp(); int tmp; if( program_mode == m_compress ) + { + show_progress( 0, &pp, in_statsp ); // initialize static vars + if( verbosity >= 2 ) show_progress( 0 ); // show initial zero size tmp = compress( data_size, encoder_options.dictionary_size, encoder_options.match_len_limit, num_workers, infd, outfd, pp, debug_level ); + } else tmp = decompress( num_workers, infd, outfd, pp, debug_level, program_mode == m_test, infd_isreg ); |