summaryrefslogtreecommitdiffstats
path: root/main.cc
diff options
context:
space:
mode:
Diffstat (limited to 'main.cc')
-rw-r--r--main.cc475
1 files changed, 176 insertions, 299 deletions
diff --git a/main.cc b/main.cc
index b2bf014..18ed642 100644
--- a/main.cc
+++ b/main.cc
@@ -1,6 +1,6 @@
/* Plzip - A parallel version of the lzip data compressor
Copyright (C) 2009 Laszlo Ersek.
- Copyright (C) 2009 Antonio Diaz Diaz.
+ Copyright (C) 2009, 2010 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -29,14 +29,14 @@
#include <cerrno>
#include <climits>
#include <csignal>
-#include <cstdarg> /* va_list */
+#include <cstdarg>
#include <cstddef>
-#include <cstdio> /* flockfile() */
+#include <cstdio>
#include <cstdlib>
-#include <cstring> /* strerror() */
+#include <cstring>
#include <string>
#include <vector>
-#include <fcntl.h> /* open() */
+#include <fcntl.h>
#include <stdint.h>
#include <pthread.h>
#include <unistd.h>
@@ -63,8 +63,6 @@
#endif
void internal_error( const char * msg );
-int readblock( const int fd, char * buf, const int size ) throw();
-int writeblock( const int fd, const char * buf, const int size ) throw();
namespace {
@@ -72,7 +70,7 @@ namespace {
const char * invocation_name = 0;
const char * const Program_name = "Plzip";
const char * const program_name = "plzip";
-const char * const program_year = "2009";
+const char * const program_year = "2010";
struct { const char * from; const char * to; } const known_extensions[] = {
{ ".lz", "" },
@@ -89,7 +87,6 @@ enum Mode { m_compress = 0, m_decompress, m_test };
std::string output_filename;
int outhandle = -1;
-int verbosity = 0;
bool delete_output_on_interrupt = false;
class Pretty_print
@@ -137,13 +134,13 @@ void show_help() throw()
// std::printf( " -b, --member-size=<n> set member size limit in bytes\n" );
std::printf( " -c, --stdout send output to standard output\n" );
std::printf( " -d, --decompress decompress\n" );
-// std::printf( " -f, --force overwrite existing output files\n" );
-// std::printf( " -k, --keep keep (don't delete) input files\n" );
-// std::printf( " -m, --match-length=<n> set match length limit in bytes [80]\n" );
+ std::printf( " -f, --force overwrite existing output files\n" );
+ std::printf( " -k, --keep keep (don't delete) input files\n" );
+ std::printf( " -m, --match-length=<n> set match length limit in bytes [80]\n" );
std::printf( " -n, --threads=<n> set the number of (de)compression threads\n" );
-// std::printf( " -o, --output=<file> if reading stdin, place the output into <file>\n" );
+ std::printf( " -o, --output=<file> if reading stdin, place the output into <file>\n" );
std::printf( " -q, --quiet suppress all messages\n" );
-// std::printf( " -s, --dictionary-size=<n> set dictionary size limit in bytes [8MiB]\n" );
+ std::printf( " -s, --dictionary-size=<n> set dictionary size limit in bytes [8MiB]\n" );
// std::printf( " -S, --volume-size=<n> set volume size limit in bytes\n" );
std::printf( " -t, --test test compressed file integrity\n" );
std::printf( " -v, --verbose be verbose (a 2nd -v gives more)\n" );
@@ -159,7 +156,7 @@ void show_help() throw()
std::printf( "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" );
std::printf( "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n" );
std::printf( "\nReport bugs to lzip-bug@nongnu.org\n" );
- std::printf( "Lzip home page: http://www.nongnu.org/lzip/lzip.html\n" );
+ std::printf( "Plzip home page: http://www.nongnu.org/lzip/plzip.html\n" );
}
@@ -209,7 +206,7 @@ long long getnum( const char * ptr, const int bs = 0,
break;
case 'k': if( factor == 1000 ) exponent = 1; else bad_multiplier = true;
break;
- default: bad_multiplier = true;
+ default : bad_multiplier = true;
}
if( bad_multiplier )
{
@@ -236,9 +233,10 @@ int get_dict_size( const char * arg ) throw()
{
char *tail;
int bits = std::strtol( arg, &tail, 0 );
- if( bits >= min_dictionary_bits && bits <= max_dictionary_bits && *tail == 0 )
+ if( bits >= LZ_min_dictionary_bits() &&
+ bits <= LZ_max_dictionary_bits() && *tail == 0 )
return ( 1 << bits );
- return getnum( arg, 0, min_dictionary_size, max_dictionary_size );
+ return getnum( arg, 0, LZ_min_dictionary_size(), LZ_max_dictionary_size() );
}
@@ -380,75 +378,59 @@ void cleanup_and_fail( const int retval ) throw()
// Set permissions, owner and times.
-void close_and_set_permissions( const struct stat * in_statsp, int * retvalp )
+void close_and_set_permissions( const struct stat * const in_statsp )
{
- int tmp = 0;
+ bool error = false;
if( in_statsp )
{
- if( fchmod( outhandle, in_statsp->st_mode ) != 0 ) tmp = 1;
- if( !tmp ) (void)fchown( outhandle, in_statsp->st_uid, in_statsp->st_gid );
+ if( fchmod( outhandle, in_statsp->st_mode ) != 0 ) error = true;
+ else (void)fchown( outhandle, in_statsp->st_uid, in_statsp->st_gid );
// fchown will in many cases return with EPERM, which can be safely ignored.
}
if( close( outhandle ) == 0 ) outhandle = -1;
else cleanup_and_fail( 1 );
delete_output_on_interrupt = false;
if( !in_statsp ) return;
- if( !tmp )
+ if( !error )
{
struct utimbuf t;
t.actime = in_statsp->st_atime;
t.modtime = in_statsp->st_mtime;
- if( utime( output_filename.c_str(), &t ) != 0 ) tmp = 1;
+ if( utime( output_filename.c_str(), &t ) != 0 ) error = true;
}
- if( tmp )
+ if( error )
{
- if( tmp > *retvalp ) *retvalp = tmp;
show_error( "I can't change output file attributes." );
- cleanup_and_fail( *retvalp );
+ cleanup_and_fail( 1 );
}
}
-int decompress( const int inhandle, const Pretty_print & pp,
- const bool testing )
+int do_decompress( LZ_Decoder * const decoder, const int inhandle,
+ const Pretty_print & pp, const bool testing )
{
- void * decoder = LZ_decompress_open();
- if( !decoder || LZ_decompress_errno( decoder ) != LZ_ok )
- {
- LZ_decompress_close( decoder );
- pp( "not enough memory. Find a machine with more memory" );
- return 1;
- }
- if( verbosity >= 1 ) pp();
-
const int in_buffer_size = 65536, out_buffer_size = 8 * in_buffer_size;
uint8_t in_buffer[in_buffer_size], out_buffer[out_buffer_size];
- int in_pos = 0, in_stream_pos = 0;
- bool finished = false;
+
+ if( verbosity >= 1 ) pp();
while( true )
{
- int in_size = 0;
- if( !finished )
+ int in_size = std::min( LZ_decompress_write_size( decoder ), in_buffer_size );
+ if( in_size > 0 )
{
- if( in_stream_pos == 0 )
- in_stream_pos = readblock( inhandle, (char *)in_buffer, in_buffer_size );
- if( in_pos < in_stream_pos )
- {
- in_size = LZ_decompress_write( decoder, in_buffer + in_pos, in_stream_pos - in_pos );
- in_pos += in_size;
- }
- if( in_pos >= in_stream_pos )
- {
- if( in_stream_pos < in_buffer_size )
- { finished = true; LZ_decompress_finish( decoder ); }
- in_stream_pos = 0; in_pos = 0;
- }
+ const int max_in_size = in_size;
+ in_size = readblock( inhandle, (char *)in_buffer, max_in_size );
+ if( in_size != max_in_size && errno )
+ { pp(); show_error( "read error", errno ); return 1; }
+ if( in_size == 0 ) LZ_decompress_finish( decoder );
+ else if( in_size != LZ_decompress_write( decoder, in_buffer, in_size ) )
+ internal_error( "library error (LZ_decompress_write)" );
}
int out_size = LZ_decompress_read( decoder, out_buffer, out_buffer_size );
// std::fprintf( stderr, "%5d in_size, %6d out_size.\n", in_size, out_size );
if( out_size < 0 )
{
- const LZ_errno lz_errno = LZ_decompress_errno( decoder );
+ const LZ_Errno lz_errno = LZ_decompress_errno( decoder );
if( lz_errno == LZ_header_error )
{
if( LZ_decompress_total_out_size( decoder ) > 0 )
@@ -461,15 +443,18 @@ int decompress( const int inhandle, const Pretty_print & pp,
pp( "not enough memory. Find a machine with more memory" );
return 1;
}
+ pp();
if( lz_errno == LZ_unexpected_eof )
{
if( verbosity >= 0 )
- { pp();
- std::fprintf( stderr, "file ends unexpectedly at pos %lld\n",
- LZ_decompress_total_in_size( decoder ) ); }
+ std::fprintf( stderr, "file ends unexpectedly at pos %lld\n",
+ LZ_decompress_total_in_size( decoder ) );
return 2;
}
- pp(); show_error( "read error", errno ); return 1;
+ if( verbosity >= 0 )
+ std::fprintf( stderr, "LZ_decompress_read error: %s.\n",
+ LZ_strerror( LZ_decompress_errno( decoder ) ) );
+ return 1;
}
else if( out_size > 0 && outhandle >= 0 )
{
@@ -478,17 +463,33 @@ int decompress( const int inhandle, const Pretty_print & pp,
{ pp(); show_error( "write error", errno ); return 1; }
}
if( LZ_decompress_finished( decoder ) == 1 ) break;
- if( finished && in_size == 0 && out_size == 0 )
+ if( in_size == 0 && out_size == 0 )
internal_error( "library error (LZ_decompress_read)" );
}
if( verbosity >= 1 )
{ if( testing ) std::fprintf( stderr, "ok\n" );
else std::fprintf( stderr, "done\n" ); }
- LZ_decompress_close( decoder );
return 0;
}
+int decompress( const int inhandle, const Pretty_print & pp,
+ const bool testing )
+ {
+ LZ_Decoder * const decoder = LZ_decompress_open();
+ int retval;
+
+ if( !decoder || LZ_decompress_errno( decoder ) != LZ_ok )
+ {
+ pp( "not enough memory" );
+ retval = 1;
+ }
+ else retval = do_decompress( decoder, inhandle, pp, testing );
+ LZ_decompress_close( decoder );
+ return retval;
+ }
+
+
extern "C" void signal_handler( int ) throw()
{
show_error( "Control-C or similar caught, quitting." );
@@ -506,6 +507,9 @@ void set_signals() throw()
} // end namespace
+int verbosity = 0;
+
+
void Pretty_print::operator()( const char * const msg ) const throw()
{
if( verbosity >= 0 )
@@ -523,6 +527,30 @@ void Pretty_print::operator()( const char * const msg ) const throw()
}
+void show_error( const char * msg, const int errcode, const bool help ) throw()
+ {
+ if( verbosity >= 0 )
+ {
+ if( msg && msg[0] != 0 )
+ {
+ std::fprintf( stderr, "%s: %s", program_name, msg );
+ if( errcode > 0 ) std::fprintf( stderr, ": %s", std::strerror( errcode ) );
+ std::fprintf( stderr, "\n" );
+ }
+ if( help && invocation_name && invocation_name[0] != 0 )
+ std::fprintf( stderr, "Try `%s --help' for more information.\n", invocation_name );
+ }
+ }
+
+
+void internal_error( const char * msg )
+ {
+ std::string s( "internal error: " ); s += msg;
+ show_error( s.c_str() );
+ std::exit( 3 );
+ }
+
+
/* Private stuff needed by fatal(). */
static pthread_t main_thread;
@@ -530,25 +558,21 @@ static pid_t pid;
/* Public utility variables and functions. */
-void *(*mallocf)(size_t size);
-void (*freef)(void *ptr);
-
/*
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(void)
+void fatal()
{
if( pthread_equal(pthread_self(), main_thread) )
cleanup_and_fail( 1 );
else
{
- if (0 == kill(pid, SIGUSR1))
+ if( 0 == kill(pid, SIGUSR1) )
pthread_exit(0);
}
- _exit(EXIT_FAILURE);
+ _exit( 1 );
}
@@ -572,67 +596,51 @@ fail(const char *fmt, int err, ...)
}
-void *
-xalloc(size_t size)
-{
- void *ret = (*mallocf)(size);
-
- if (0 == ret) {
- fail("(*mallocf)()", errno);
- }
-
- return ret;
-}
-
-
void
xinit(Cond *cond)
{
- int ret;
pthread_mutexattr_t attr;
- ret = pthread_mutexattr_init(&attr);
- if (0 != ret) {
+ int ret = pthread_mutexattr_init(&attr);
+ if( ret != 0 ) {
fail("pthread_mutexattr_init()", ret);
}
ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
- if (0 != ret) {
+ if( ret != 0 ) {
fail("pthread_mutexattr_settype()", ret);
}
ret = pthread_mutex_init(&cond->lock, &attr);
- if (0 != ret) {
+ if( ret != 0 ) {
fail("pthread_mutex_init()", ret);
}
ret = pthread_mutexattr_destroy(&attr);
- if (0 != ret) {
+ if( ret != 0 ) {
fail("pthread_mutexattr_destroy()", ret);
}
ret = pthread_cond_init(&cond->cond, 0);
- if (0 != ret) {
+ if( ret != 0 ) {
fail("pthread_cond_init()", ret);
}
- cond->ccount = 0lu;
- cond->wcount = 0lu;
+ cond->ccount = 0;
+ cond->wcount = 0;
}
void
xdestroy(Cond *cond)
{
- int ret;
-
- ret = pthread_cond_destroy(&cond->cond);
- if (0 != ret) {
+ int ret = pthread_cond_destroy(&cond->cond);
+ if( ret != 0 ) {
fail("pthread_cond_destroy()", ret);
}
ret = pthread_mutex_destroy(&cond->lock);
- if (0 != ret) {
+ if( ret != 0 ) {
fail("pthread_mutex_destroy()", ret);
}
}
@@ -641,10 +649,8 @@ xdestroy(Cond *cond)
void
xlock(Cond *cond)
{
- int ret;
-
- ret = pthread_mutex_lock(&cond->lock);
- if (0 != ret) {
+ int ret = pthread_mutex_lock(&cond->lock);
+ if( ret != 0 ) {
fail("pthread_mutex_lock()", ret);
}
}
@@ -661,10 +667,8 @@ xlock_pred(Cond *cond)
void
xunlock(Cond *cond)
{
- int ret;
-
- ret = pthread_mutex_unlock(&cond->lock);
- if (0 != ret) {
+ int ret = pthread_mutex_unlock(&cond->lock);
+ if( ret != 0 ) {
fail("pthread_mutex_unlock()", ret);
}
}
@@ -673,11 +677,9 @@ xunlock(Cond *cond)
void
xwait(Cond *cond)
{
- int ret;
-
++cond->wcount;
- ret = pthread_cond_wait(&cond->cond, &cond->lock);
- if (0 != ret) {
+ int ret = pthread_cond_wait(&cond->cond, &cond->lock);
+ if( ret != 0 ) {
fail("pthread_cond_wait()", ret);
}
++cond->ccount;
@@ -687,10 +689,8 @@ xwait(Cond *cond)
void
xsignal(Cond *cond)
{
- int ret;
-
- ret = pthread_cond_signal(&cond->cond);
- if (0 != ret) {
+ int ret = pthread_cond_signal(&cond->cond);
+ if( ret != 0 ) {
fail("pthread_cond_signal()", ret);
}
}
@@ -699,10 +699,8 @@ xsignal(Cond *cond)
void
xbroadcast(Cond *cond)
{
- int ret;
-
- ret = pthread_cond_broadcast(&cond->cond);
- if (0 != ret) {
+ int ret = pthread_cond_broadcast(&cond->cond);
+ if( ret != 0 ) {
fail("pthread_cond_broadcast()", ret);
}
}
@@ -711,10 +709,8 @@ xbroadcast(Cond *cond)
void
xcreate(pthread_t *thread, void *(*routine)(void *), void *arg)
{
- int ret;
-
- ret = pthread_create(thread, 0, routine, arg);
- if (0 != ret) {
+ int ret = pthread_create(thread, 0, routine, arg);
+ if( ret != 0 ) {
fail("pthread_create()", ret);
}
}
@@ -723,10 +719,8 @@ xcreate(pthread_t *thread, void *(*routine)(void *), void *arg)
void
xjoin(pthread_t thread)
{
- int ret;
-
- ret = pthread_join(thread, 0);
- if (0 != ret) {
+ int ret = pthread_join(thread, 0);
+ if( ret != 0 ) {
fail("pthread_join()", ret);
}
}
@@ -735,7 +729,7 @@ xjoin(pthread_t thread)
void
xraise(int sig)
{
- if (-1 == kill(pid, sig)) {
+ if( -1 == kill(pid, sig) ) {
fail("kill()", errno);
}
}
@@ -743,59 +737,11 @@ xraise(int sig)
/* Private stuff part 2. */
-struct Opts
-{
- unsigned num_worker; /* Start this many worker threads. */
- unsigned clidx; /* Compression level index in [0u .. 8u]. */
- int print_cctrs; /* Print condition variable counters. */
-};
-
-/* Backlog factor for all workers together. */
-static const unsigned blf = 3u;
-
-/* Separator characters in environment variable values. No escaping. */
-static const char envsep[] = " \t";
-
-
-static void *
-trace_malloc(size_t size)
-{
- void *ret;
- int save_errno = 0;
-
- ret = malloc(size);
- if (0 == ret) {
- save_errno = errno;
- }
-
- if (0 > fprintf(stderr, "%lu: malloc(%lu) == %p\n", (long unsigned)pid,
- (long unsigned)size, ret)
- ) {
- fatal();
- }
-
- if (0 == ret) {
- errno = save_errno;
- }
-
- return ret;
-}
-
-
-static void
-trace_free(void *ptr)
-{
- if (0 > fprintf(stderr, "%lu: free(%p)\n", (long unsigned)pid, ptr)) {
- fatal();
- }
- free(ptr);
-}
-
static void
xsigemptyset(sigset_t *set)
{
- if (-1 == sigemptyset(set)) {
+ if( -1 == sigemptyset(set) ) {
fail("sigemptyset()", errno);
}
}
@@ -804,7 +750,7 @@ xsigemptyset(sigset_t *set)
static void
xsigaddset(sigset_t *set, int signo)
{
- if (-1 == sigaddset(set, signo)) {
+ if( -1 == sigaddset(set, signo) ) {
fail("sigaddset()", errno);
}
}
@@ -813,10 +759,8 @@ xsigaddset(sigset_t *set, int signo)
static void
xsigmask(int how, const sigset_t *set, sigset_t *oset)
{
- int ret;
-
- ret = pthread_sigmask(how, set, oset);
- if (0 != ret) {
+ int ret = pthread_sigmask(how, set, oset);
+ if( ret != 0 ) {
fail("pthread_sigmask()", ret);
}
}
@@ -831,54 +775,35 @@ xsigaction(int sig, void (*handler)(int))
xsigemptyset(&act.sa_mask);
act.sa_flags = 0;
- if (-1 == sigaction(sig, &act, 0)) {
+ if( -1 == sigaction(sig, &act, 0) ) {
fail("sigaction()", errno);
}
}
-enum caught_sig
-{
- CS_INT = 1,
- CS_TERM,
- CS_USR1,
- CS_USR2
-};
+enum Caught_sig { CS_INT = 1, CS_TERM, CS_USR1, CS_USR2 };
static volatile sig_atomic_t caught_sig;
-static void
-sighandler(int sig)
-{
+extern "C" void sighandler( int sig )
+ {
/* sig_atomic_t is nowhere required to be able to hold signal values. */
- switch (sig) {
- case SIGINT:
- caught_sig = CS_INT;
- break;
-
- case SIGTERM:
- caught_sig = CS_TERM;
- break;
-
- case SIGUSR1:
- caught_sig = CS_USR1;
- break;
-
- case SIGUSR2:
- caught_sig = CS_USR2;
- break;
-
- default:
- assert(0);
+ switch( sig )
+ {
+ case SIGINT : caught_sig = CS_INT; break;
+ case SIGTERM: caught_sig = CS_TERM; break;
+ case SIGUSR1: caught_sig = CS_USR1; break;
+ case SIGUSR2: caught_sig = CS_USR2; break;
+ default: internal_error( "caught signal not in set" );
+ }
}
-}
-static void
-process( const Opts *opts, unsigned num_slot,
- int infd, int outfd, const Pretty_print & pp, const sigset_t *unblocked )
-{
+static void compress( const lzma_options & encoder_options, const int num_workers,
+ int debug_level, int num_slots, int infd, int outfd,
+ const Pretty_print & pp, const sigset_t *unblocked )
+ {
/*
We could wait for signals with either sigwait() or sigsuspend(). SUSv2
states about sigwait() that its effect on signal actions is unspecified.
@@ -896,18 +821,19 @@ process( const Opts *opts, unsigned num_slot,
13-OCT-2009 lacos
*/
- Plzip_arg muxer_arg;
- pthread_t muxer;
-
- if( verbosity >= 1 ) pp( "" );
+ if( verbosity >= 1 ) pp();
- muxer_arg.num_worker = opts->num_worker;
- muxer_arg.num_slot = num_slot;
- muxer_arg.clidx = opts->clidx;
- muxer_arg.print_cctrs = opts->print_cctrs;
+ Muxer_arg muxer_arg;
+ muxer_arg.dictionary_size = encoder_options.dictionary_size;
+ muxer_arg.match_len_limit = encoder_options.match_len_limit;
+ muxer_arg.num_workers = num_workers;
+ muxer_arg.num_slots = num_slots;
+ muxer_arg.debug_level = debug_level;
muxer_arg.infd = infd;
muxer_arg.outfd = outfd;
- xcreate(&muxer, plzip_wrap, &muxer_arg);
+
+ pthread_t muxer_thread;
+ xcreate(&muxer_thread, muxer, &muxer_arg);
/* Unblock signals, wait for them, then block them again. */
{
@@ -915,7 +841,7 @@ process( const Opts *opts, unsigned num_slot,
assert(-1 == ret && EINTR == errno);
}
- switch (caught_sig) {
+ switch( caught_sig ) {
case CS_INT:
case CS_TERM: // FIXME remove output file
{
@@ -951,16 +877,16 @@ process( const Opts *opts, unsigned num_slot,
assert(0);
}
- xjoin(muxer);
-}
+ xjoin(muxer_thread);
+ }
static void
sigs_mod(int block_n_catch, sigset_t *oset)
-{
+ {
void (*handler)(int);
- if (block_n_catch) {
+ if( block_n_catch ) {
sigset_t mask;
xsigemptyset(&mask);
@@ -981,33 +907,9 @@ sigs_mod(int block_n_catch, sigset_t *oset)
xsigaction(SIGUSR1, handler);
xsigaction(SIGUSR2, handler);
- if (!block_n_catch) {
+ if( !block_n_catch ) {
xsigmask(SIG_SETMASK, oset, 0);
}
-}
-
-
-void show_error( const char * msg, const int errcode, const bool help ) throw()
- {
- if( verbosity >= 0 )
- {
- if( msg && msg[0] != 0 )
- {
- std::fprintf( stderr, "%s: %s", program_name, msg );
- if( errcode > 0 ) std::fprintf( stderr, ": %s", std::strerror( errcode ) );
- std::fprintf( stderr, "\n" );
- }
- if( help && invocation_name && invocation_name[0] != 0 )
- std::fprintf( stderr, "Try `%s --help' for more information.\n", invocation_name );
- }
- }
-
-
-void internal_error( const char * msg )
- {
- std::string s( "internal error: " ); s += msg;
- show_error( s.c_str() );
- std::exit( 3 );
}
@@ -1050,7 +952,6 @@ int writeblock( const int fd, const char * buf, const int size ) throw()
int main( const int argc, const char * argv[] )
{
- Opts opts;
// Mapping from gzip/bzip2 style 1..9 compression modes
// to the corresponding LZMA compression modes.
const lzma_options option_mapping[] =
@@ -1065,7 +966,9 @@ int main( const int argc, const char * argv[] )
{ 1 << 24, 163 }, // -8
{ 1 << 25, 273 } }; // -9
lzma_options encoder_options = option_mapping[5]; // default = "-6"
+ int debug_level = 0;
int inhandle = -1;
+ int num_workers = 0; // Start this many worker threads
Mode program_mode = m_compress;
bool force = false;
bool keep_input_files = false;
@@ -1081,30 +984,15 @@ int main( const int argc, const char * argv[] )
main_thread = pthread_self();
pid = getpid();
- mallocf = malloc;
- freef = free;
-
xsigaction(SIGPIPE, SIG_IGN);
xsigaction(SIGXFSZ, SIG_IGN);
- /* Effectuate option defaults. */
- long max_worker = sysconf(_SC_THREAD_THREADS_MAX);
- if (-1L == max_worker) {
- max_worker = LONG_MAX;
- }
- if (UINT_MAX < (long unsigned)max_worker) {
- max_worker = UINT_MAX;
- }
- if (UINT_MAX / blf < (unsigned)max_worker) {
- max_worker = UINT_MAX / blf;
- }
- if ((size_t)-1 / sizeof(pthread_t) < (unsigned)max_worker) {
- max_worker = (size_t)-1 / sizeof(pthread_t);
- }
-
- opts.num_worker = 0u;
- opts.clidx = 5u;
- opts.print_cctrs = 0;
+ const int slots_per_worker = 2;
+ long max_workers = sysconf( _SC_THREAD_THREADS_MAX );
+ if( max_workers < 1 || max_workers > INT_MAX / slots_per_worker )
+ max_workers = INT_MAX / slots_per_worker;
+ if( max_workers > INT_MAX / (int)sizeof( pthread_t ) )
+ max_workers = INT_MAX / sizeof( pthread_t );
const Arg_parser::Option options[] =
{
@@ -1150,25 +1038,24 @@ int main( const int argc, const char * argv[] )
case '1': case '2': case '3':
case '4': case '5': case '6':
case '7': case '8': case '9':
- opts.clidx = code - '1';
encoder_options = option_mapping[code-'1']; break;
+ case 'b': break;
case 'c': to_stdout = true; break;
case 'd': program_mode = m_decompress; break;
- case 'D': { int debug_level = getnum( arg, 0, 0, 3 );
- if( debug_level & 1 ) opts.print_cctrs = 1;
- if( debug_level & 2 )
- { mallocf = trace_malloc; freef = trace_free; } }
+ case 'D': debug_level = getnum( arg, 0, 0, 3 );
break;
case 'f': force = true; break;
case 'h': show_help(); return 0;
case 'k': keep_input_files = true; break;
case 'm': encoder_options.match_len_limit =
- getnum( arg, 0, 5, 273 ); break;
+ getnum( arg, 0, LZ_min_match_len_limit(),
+ LZ_max_match_len_limit() ); break;
case 'o': default_output_filename = arg; break;
- case 'n': opts.num_worker = getnum( arg, 0, 1, max_worker ); break;
+ case 'n': num_workers = getnum( arg, 0, 1, max_workers ); break;
case 'q': verbosity = -1; break;
case 's': encoder_options.dictionary_size = get_dict_size( arg );
break;
+ case 'S': break;
case 't': program_mode = m_test; break;
case 'v': if( verbosity < 4 ) ++verbosity; break;
case 'V': show_version(); return 0;
@@ -1176,23 +1063,13 @@ int main( const int argc, const char * argv[] )
}
}
- if( opts.num_worker <= 0 )
+ if( num_workers <= 0 )
{
-#ifdef _SC_NPROCESSORS_ONLN
long num_online = sysconf( _SC_NPROCESSORS_ONLN );
- if( num_online <= 0 )
- {
- show_error( "number of online processors unavailable.", 0, true );
- fatal();
- }
- opts.num_worker = std::min( num_online, max_worker );
-#else
- show_error( "number of (de)compression threads not set.", 0, true );
- fatal();
-#endif
+ if( num_online <= 0 ) num_online = 2;
+ num_workers = std::min( num_online, max_workers );
}
- assert(UINT_MAX / blf >= opts.num_worker);
- unsigned num_slot = opts.num_worker * blf;
+ const int num_slots = num_workers * slots_per_worker;
bool filenames_given = false;
for( ; argind < parser.arguments(); ++argind )
@@ -1265,14 +1142,14 @@ int main( const int argc, const char * argv[] )
if( output_filename.size() && !to_stdout && program_mode != m_test )
delete_output_on_interrupt = true;
- const struct stat * in_statsp = input_filename.size() ? &in_stats : 0;
+ const struct stat * const in_statsp = input_filename.size() ? &in_stats : 0;
pp.set_name( input_filename );
int tmp = 0;
if( program_mode == m_compress )
{
sigset_t unblocked;
sigs_mod(1, &unblocked);
- process( &opts, num_slot, inhandle, outhandle, pp, &unblocked );
+ compress( encoder_options, num_workers, debug_level, num_slots, inhandle, outhandle, pp, &unblocked );
sigs_mod(0, &unblocked);
}
else
@@ -1281,7 +1158,7 @@ int main( const int argc, const char * argv[] )
if( tmp && program_mode != m_test ) cleanup_and_fail( retval );
if( delete_output_on_interrupt )
- close_and_set_permissions( in_statsp, &retval );
+ close_and_set_permissions( in_statsp );
if( input_filename.size() )
{
close( inhandle ); inhandle = -1;