Adding upstream version 1.1~pre1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
4bce01c02a
commit
e7c68f81ff
17 changed files with 356 additions and 277 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
2013-07-20 Antonio Diaz Diaz <antonio@gnu.org>
|
||||||
|
|
||||||
|
* Version 1.1-pre1 released.
|
||||||
|
* Show progress of compression at verbosity level 2 (-vv).
|
||||||
|
* SIGUSR1 and SIGUSR2 are no more used to signal a fatal error.
|
||||||
|
|
||||||
2013-05-29 Antonio Diaz Diaz <antonio@gnu.org>
|
2013-05-29 Antonio Diaz Diaz <antonio@gnu.org>
|
||||||
|
|
||||||
* Version 1.0 released.
|
* Version 1.0 released.
|
||||||
|
|
6
INSTALL
6
INSTALL
|
@ -1,7 +1,7 @@
|
||||||
Requirements
|
Requirements
|
||||||
------------
|
------------
|
||||||
You will need a C++ compiler and the lzlib compression library installed.
|
You will need a C++ compiler and the lzlib compression library installed.
|
||||||
I use gcc 4.8.0 and 3.3.6, but the code should compile with any
|
I use gcc 4.8.1 and 3.3.6, but the code should compile with any
|
||||||
standards compliant compiler.
|
standards compliant compiler.
|
||||||
Lzlib must be version 1.0 or newer.
|
Lzlib must be version 1.0 or newer.
|
||||||
Gcc is available at http://gcc.gnu.org.
|
Gcc is available at http://gcc.gnu.org.
|
||||||
|
@ -12,9 +12,9 @@ Procedure
|
||||||
---------
|
---------
|
||||||
1. Unpack the archive if you have not done so already:
|
1. Unpack the archive if you have not done so already:
|
||||||
|
|
||||||
lzip -cd plzip[version].tar.lz | tar -xf -
|
tar -xf plzip[version].tar.lz
|
||||||
or
|
or
|
||||||
gzip -cd plzip[version].tar.gz | tar -xf -
|
lzip -cd plzip[version].tar.lz | tar -xf -
|
||||||
|
|
||||||
This creates the directory ./plzip[version] containing the source from
|
This creates the directory ./plzip[version] containing the source from
|
||||||
the main archive.
|
the main archive.
|
||||||
|
|
16
NEWS
16
NEWS
|
@ -1,15 +1,5 @@
|
||||||
Changes in version 1.0:
|
Changes in version 1.1:
|
||||||
|
|
||||||
Scalability of compression (max number of useful worker threads) has
|
Plzip now shows the progress of compression at verbosity level 2 (-vv).
|
||||||
been increased.
|
|
||||||
|
|
||||||
Scalability when decompressing from/to regular files has been increased.
|
Signals "SIGUSR1" and "SIGUSR2" are no more used to signal a fatal error.
|
||||||
|
|
||||||
The number of worker threads is now limited to the number of members in
|
|
||||||
the input file when decompressing from a regular file.
|
|
||||||
|
|
||||||
"configure" now accepts options with a separate argument.
|
|
||||||
|
|
||||||
The target "install-as-lzip" has been added to the Makefile.
|
|
||||||
|
|
||||||
The target "install-bin" has been added to the Makefile.
|
|
||||||
|
|
49
README
49
README
|
@ -1,21 +1,40 @@
|
||||||
Description
|
Description
|
||||||
|
|
||||||
Plzip is a massively parallel (multi-threaded), lossless data compressor
|
Plzip is a massively parallel (multi-threaded), lossless data compressor
|
||||||
based on the lzlib compression library, with very safe integrity
|
based on the lzlib compression library, with a user interface similar to
|
||||||
checking and a user interface similar to the one of bzip2, gzip or lzip.
|
the one of lzip, bzip2 or gzip.
|
||||||
|
|
||||||
Plzip is intended for faster compression/decompression of big files on
|
Plzip can compress/decompress large files on multiprocessor machines
|
||||||
multiprocessor machines, which makes it specially well suited for
|
much faster than lzip, at the cost of a slightly reduced compression
|
||||||
distribution of big software files and large scale data archiving. On
|
ratio. On files large enough (several GB), plzip can use hundreds of
|
||||||
files big enough (several GB), plzip can use hundreds of processors.
|
processors. On files of only a few MB it is better to use lzip.
|
||||||
|
|
||||||
Plzip uses the lzip file format; the files produced by plzip are fully
|
|
||||||
compatible with lzip-1.4 or newer, and can be rescued with lziprecover.
|
|
||||||
|
|
||||||
Plzip uses the same well-defined exit status values used by lzip and
|
Plzip uses the same well-defined exit status values used by lzip and
|
||||||
bzip2, which makes it safer when used in pipes or scripts than
|
bzip2, which makes it safer when used in pipes or scripts than
|
||||||
compressors returning ambiguous warning values, like gzip.
|
compressors returning ambiguous warning values, like gzip.
|
||||||
|
|
||||||
|
Plzip uses the lzip file format; the files produced by plzip are fully
|
||||||
|
compatible with lzip-1.4 or newer, and can be rescued with lziprecover.
|
||||||
|
|
||||||
|
The lzip file format is designed for long-term data archiving and
|
||||||
|
provides very safe integrity checking. The member trailer stores the
|
||||||
|
32-bit CRC of the original data, the size of the original data and the
|
||||||
|
size of the member. These values, together with the value remaining in
|
||||||
|
the range decoder and the end-of-stream marker, provide a 4 factor
|
||||||
|
integrity checking which guarantees that the decompressed version of the
|
||||||
|
data is identical to the original. This guards against corruption of the
|
||||||
|
compressed data, and against undetected bugs in plzip (hopefully very
|
||||||
|
unlikely). The chances of data corruption going undetected are
|
||||||
|
microscopic. Be aware, though, that the check occurs upon decompression,
|
||||||
|
so it can only tell you that something is wrong. It can't help you
|
||||||
|
recover the original uncompressed data.
|
||||||
|
|
||||||
|
If you ever need to recover data from a damaged lzip file, try the
|
||||||
|
lziprecover program. Lziprecover makes lzip files resistant to bit-flip
|
||||||
|
(one of the most common forms of data corruption), and provides data
|
||||||
|
recovery capabilities, including error-checked merging of damaged copies
|
||||||
|
of a file.
|
||||||
|
|
||||||
Plzip replaces every file given in the command line with a compressed
|
Plzip replaces every file given in the command line with a compressed
|
||||||
version of itself, with the name "original_name.lz". Each compressed
|
version of itself, with the name "original_name.lz". Each compressed
|
||||||
file has the same modification date, permissions, and, when possible,
|
file has the same modification date, permissions, and, when possible,
|
||||||
|
@ -33,18 +52,6 @@ or more compressed files. The result is the concatenation of the
|
||||||
corresponding uncompressed files. Integrity testing of concatenated
|
corresponding uncompressed files. Integrity testing of concatenated
|
||||||
compressed files is also supported.
|
compressed files is also supported.
|
||||||
|
|
||||||
As a self-check for your protection, plzip stores in the member trailer
|
|
||||||
the 32-bit CRC of the original data, the size of the original data and
|
|
||||||
the size of the member. These values, together with the value remaining
|
|
||||||
in the range decoder and the end-of-stream marker, provide a very safe 4
|
|
||||||
factor integrity checking which guarantees that the decompressed version
|
|
||||||
of the data is identical to the original. This guards against corruption
|
|
||||||
of the compressed data, and against undetected bugs in plzip (hopefully
|
|
||||||
very unlikely). The chances of data corruption going undetected are
|
|
||||||
microscopic. Be aware, though, that the check occurs upon decompression,
|
|
||||||
so it can only tell you that something is wrong. It can't help you
|
|
||||||
recover the original uncompressed data.
|
|
||||||
|
|
||||||
|
|
||||||
Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
|
|
||||||
|
|
54
compress.cc
54
compress.cc
|
@ -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 Laszlo Ersek.
|
||||||
Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
|
|
||||||
|
@ -80,61 +80,70 @@ int writeblock( const int fd, const uint8_t * const buf, const int size )
|
||||||
void xinit( pthread_mutex_t * const mutex )
|
void xinit( pthread_mutex_t * const mutex )
|
||||||
{
|
{
|
||||||
const int errcode = pthread_mutex_init( mutex, 0 );
|
const int errcode = pthread_mutex_init( mutex, 0 );
|
||||||
if( errcode ) { show_error( "pthread_mutex_init", errcode ); fatal(); }
|
if( errcode )
|
||||||
|
{ show_error( "pthread_mutex_init", errcode ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void xinit( pthread_cond_t * const cond )
|
void xinit( pthread_cond_t * const cond )
|
||||||
{
|
{
|
||||||
const int errcode = pthread_cond_init( cond, 0 );
|
const int errcode = pthread_cond_init( cond, 0 );
|
||||||
if( errcode ) { show_error( "pthread_cond_init", errcode ); fatal(); }
|
if( errcode )
|
||||||
|
{ show_error( "pthread_cond_init", errcode ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xdestroy( pthread_mutex_t * const mutex )
|
void xdestroy( pthread_mutex_t * const mutex )
|
||||||
{
|
{
|
||||||
const int errcode = pthread_mutex_destroy( mutex );
|
const int errcode = pthread_mutex_destroy( mutex );
|
||||||
if( errcode ) { show_error( "pthread_mutex_destroy", errcode ); fatal(); }
|
if( errcode )
|
||||||
|
{ show_error( "pthread_mutex_destroy", errcode ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void xdestroy( pthread_cond_t * const cond )
|
void xdestroy( pthread_cond_t * const cond )
|
||||||
{
|
{
|
||||||
const int errcode = pthread_cond_destroy( cond );
|
const int errcode = pthread_cond_destroy( cond );
|
||||||
if( errcode ) { show_error( "pthread_cond_destroy", errcode ); fatal(); }
|
if( errcode )
|
||||||
|
{ show_error( "pthread_cond_destroy", errcode ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xlock( pthread_mutex_t * const mutex )
|
void xlock( pthread_mutex_t * const mutex )
|
||||||
{
|
{
|
||||||
const int errcode = pthread_mutex_lock( mutex );
|
const int errcode = pthread_mutex_lock( mutex );
|
||||||
if( errcode ) { show_error( "pthread_mutex_lock", errcode ); fatal(); }
|
if( errcode )
|
||||||
|
{ show_error( "pthread_mutex_lock", errcode ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xunlock( pthread_mutex_t * const mutex )
|
void xunlock( pthread_mutex_t * const mutex )
|
||||||
{
|
{
|
||||||
const int errcode = pthread_mutex_unlock( mutex );
|
const int errcode = pthread_mutex_unlock( mutex );
|
||||||
if( errcode ) { show_error( "pthread_mutex_unlock", errcode ); fatal(); }
|
if( errcode )
|
||||||
|
{ show_error( "pthread_mutex_unlock", errcode ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xwait( pthread_cond_t * const cond, pthread_mutex_t * const mutex )
|
void xwait( pthread_cond_t * const cond, pthread_mutex_t * const mutex )
|
||||||
{
|
{
|
||||||
const int errcode = pthread_cond_wait( cond, mutex );
|
const int errcode = pthread_cond_wait( cond, mutex );
|
||||||
if( errcode ) { show_error( "pthread_cond_wait", errcode ); fatal(); }
|
if( errcode )
|
||||||
|
{ show_error( "pthread_cond_wait", errcode ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xsignal( pthread_cond_t * const cond )
|
void xsignal( pthread_cond_t * const cond )
|
||||||
{
|
{
|
||||||
const int errcode = pthread_cond_signal( cond );
|
const int errcode = pthread_cond_signal( cond );
|
||||||
if( errcode ) { show_error( "pthread_cond_signal", errcode ); fatal(); }
|
if( errcode )
|
||||||
|
{ show_error( "pthread_cond_signal", errcode ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xbroadcast( pthread_cond_t * const cond )
|
void xbroadcast( pthread_cond_t * const cond )
|
||||||
{
|
{
|
||||||
const int errcode = pthread_cond_broadcast( cond );
|
const int errcode = pthread_cond_broadcast( cond );
|
||||||
if( errcode ) { show_error( "pthread_cond_broadcast", errcode ); fatal(); }
|
if( errcode )
|
||||||
|
{ show_error( "pthread_cond_broadcast", errcode ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -317,10 +326,10 @@ extern "C" void * csplitter( void * arg )
|
||||||
for( bool first_post = true; ; first_post = false )
|
for( bool first_post = true; ; first_post = false )
|
||||||
{
|
{
|
||||||
uint8_t * const data = new( std::nothrow ) uint8_t[data_size];
|
uint8_t * const data = new( std::nothrow ) uint8_t[data_size];
|
||||||
if( !data ) { pp( mem_msg ); fatal(); }
|
if( !data ) { pp( mem_msg ); cleanup_and_fail(); }
|
||||||
const int size = readblock( infd, data, data_size );
|
const int size = readblock( infd, data, data_size );
|
||||||
if( size != data_size && errno )
|
if( size != data_size && errno )
|
||||||
{ pp(); show_error( "Read error", errno ); fatal(); }
|
{ pp(); show_error( "Read error", errno ); cleanup_and_fail(); }
|
||||||
|
|
||||||
if( size > 0 || first_post ) // first packet may be empty
|
if( size > 0 || first_post ) // first packet may be empty
|
||||||
{
|
{
|
||||||
|
@ -365,7 +374,7 @@ extern "C" void * cworker( void * arg )
|
||||||
|
|
||||||
const int max_compr_size = 42 + packet->size + ( ( packet->size + 7 ) / 8 );
|
const int max_compr_size = 42 + packet->size + ( ( packet->size + 7 ) / 8 );
|
||||||
uint8_t * const new_data = new( std::nothrow ) uint8_t[max_compr_size];
|
uint8_t * const new_data = new( std::nothrow ) uint8_t[max_compr_size];
|
||||||
if( !new_data ) { pp( mem_msg ); fatal(); }
|
if( !new_data ) { pp( mem_msg ); cleanup_and_fail(); }
|
||||||
const int dict_size = std::max( LZ_min_dictionary_size(),
|
const int dict_size = std::max( LZ_min_dictionary_size(),
|
||||||
std::min( dictionary_size, packet->size ) );
|
std::min( dictionary_size, packet->size ) );
|
||||||
LZ_Encoder * const encoder =
|
LZ_Encoder * const encoder =
|
||||||
|
@ -376,7 +385,7 @@ extern "C" void * cworker( void * arg )
|
||||||
pp( mem_msg );
|
pp( mem_msg );
|
||||||
else
|
else
|
||||||
internal_error( "invalid argument to encoder" );
|
internal_error( "invalid argument to encoder" );
|
||||||
fatal();
|
cleanup_and_fail();
|
||||||
}
|
}
|
||||||
|
|
||||||
int written = 0;
|
int written = 0;
|
||||||
|
@ -403,7 +412,7 @@ extern "C" void * cworker( void * arg )
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "LZ_compress_read error: %s.\n",
|
std::fprintf( stderr, "LZ_compress_read error: %s.\n",
|
||||||
LZ_strerror( LZ_compress_errno( encoder ) ) );
|
LZ_strerror( LZ_compress_errno( encoder ) ) );
|
||||||
fatal();
|
cleanup_and_fail();
|
||||||
}
|
}
|
||||||
new_pos += rd;
|
new_pos += rd;
|
||||||
if( new_pos > max_compr_size )
|
if( new_pos > max_compr_size )
|
||||||
|
@ -412,8 +421,9 @@ extern "C" void * cworker( void * arg )
|
||||||
}
|
}
|
||||||
|
|
||||||
if( LZ_compress_close( encoder ) < 0 )
|
if( LZ_compress_close( encoder ) < 0 )
|
||||||
{ pp( "LZ_compress_close failed" ); fatal(); }
|
{ pp( "LZ_compress_close failed" ); cleanup_and_fail(); }
|
||||||
|
|
||||||
|
if( verbosity >= 2 && packet->size > 0 ) show_progress( packet->size );
|
||||||
packet->data = new_data;
|
packet->data = new_data;
|
||||||
packet->size = new_pos;
|
packet->size = new_pos;
|
||||||
courier.collect_packet( packet );
|
courier.collect_packet( packet );
|
||||||
|
@ -441,7 +451,7 @@ void muxer( Packet_courier & courier, const Pretty_print & pp, const int outfd )
|
||||||
{
|
{
|
||||||
const int wr = writeblock( outfd, opacket->data, opacket->size );
|
const int wr = writeblock( outfd, opacket->data, opacket->size );
|
||||||
if( wr != opacket->size )
|
if( wr != opacket->size )
|
||||||
{ pp(); show_error( "Write error", errno ); fatal(); }
|
{ pp(); show_error( "Write error", errno ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
delete[] opacket->data;
|
delete[] opacket->data;
|
||||||
delete opacket;
|
delete opacket;
|
||||||
|
@ -475,7 +485,7 @@ int compress( const int data_size, const int dictionary_size,
|
||||||
pthread_t splitter_thread;
|
pthread_t splitter_thread;
|
||||||
int errcode = pthread_create( &splitter_thread, 0, csplitter, &splitter_arg );
|
int errcode = pthread_create( &splitter_thread, 0, csplitter, &splitter_arg );
|
||||||
if( errcode )
|
if( errcode )
|
||||||
{ show_error( "Can't create splitter thread", errcode ); fatal(); }
|
{ show_error( "Can't create splitter thread", errcode ); cleanup_and_fail(); }
|
||||||
|
|
||||||
Worker_arg worker_arg;
|
Worker_arg worker_arg;
|
||||||
worker_arg.courier = &courier;
|
worker_arg.courier = &courier;
|
||||||
|
@ -484,12 +494,12 @@ int compress( const int data_size, const int dictionary_size,
|
||||||
worker_arg.match_len_limit = match_len_limit;
|
worker_arg.match_len_limit = match_len_limit;
|
||||||
|
|
||||||
pthread_t * worker_threads = new( std::nothrow ) pthread_t[num_workers];
|
pthread_t * worker_threads = new( std::nothrow ) pthread_t[num_workers];
|
||||||
if( !worker_threads ) { pp( mem_msg ); fatal(); }
|
if( !worker_threads ) { pp( mem_msg ); cleanup_and_fail(); }
|
||||||
for( int i = 0; i < num_workers; ++i )
|
for( int i = 0; i < num_workers; ++i )
|
||||||
{
|
{
|
||||||
errcode = pthread_create( worker_threads + i, 0, cworker, &worker_arg );
|
errcode = pthread_create( worker_threads + i, 0, cworker, &worker_arg );
|
||||||
if( errcode )
|
if( errcode )
|
||||||
{ show_error( "Can't create worker threads", errcode ); fatal(); }
|
{ show_error( "Can't create worker threads", errcode ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
muxer( courier, pp, outfd );
|
muxer( courier, pp, outfd );
|
||||||
|
@ -498,13 +508,13 @@ int compress( const int data_size, const int dictionary_size,
|
||||||
{
|
{
|
||||||
errcode = pthread_join( worker_threads[i], 0 );
|
errcode = pthread_join( worker_threads[i], 0 );
|
||||||
if( errcode )
|
if( errcode )
|
||||||
{ show_error( "Can't join worker threads", errcode ); fatal(); }
|
{ show_error( "Can't join worker threads", errcode ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
delete[] worker_threads;
|
delete[] worker_threads;
|
||||||
|
|
||||||
errcode = pthread_join( splitter_thread, 0 );
|
errcode = pthread_join( splitter_thread, 0 );
|
||||||
if( errcode )
|
if( errcode )
|
||||||
{ show_error( "Can't join splitter thread", errcode ); fatal(); }
|
{ show_error( "Can't join splitter thread", errcode ); cleanup_and_fail(); }
|
||||||
|
|
||||||
if( verbosity >= 1 )
|
if( verbosity >= 1 )
|
||||||
{
|
{
|
||||||
|
|
18
configure
vendored
18
configure
vendored
|
@ -1,14 +1,14 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# configure script for Plzip - A parallel compressor compatible with lzip
|
# configure script for Plzip - Parallel compressor compatible with lzip
|
||||||
# Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
# Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
#
|
#
|
||||||
# This configure script is free software: you have unlimited permission
|
# This configure script is free software: you have unlimited permission
|
||||||
# to copy, distribute and modify it.
|
# to copy, distribute and modify it.
|
||||||
|
|
||||||
pkgname=plzip
|
pkgname=plzip
|
||||||
pkgversion=1.0
|
pkgversion=1.1-pre1
|
||||||
progname=plzip
|
progname=plzip
|
||||||
srctrigger=doc/plzip.texinfo
|
srctrigger=doc/${pkgname}.texinfo
|
||||||
|
|
||||||
# clear some things potentially inherited from environment.
|
# clear some things potentially inherited from environment.
|
||||||
LC_ALL=C
|
LC_ALL=C
|
||||||
|
@ -100,14 +100,14 @@ while [ $# != 0 ] ; do
|
||||||
*=* | *-*-*) ;;
|
*=* | *-*-*) ;;
|
||||||
*)
|
*)
|
||||||
echo "configure: unrecognized option: '${option}'" 1>&2
|
echo "configure: unrecognized option: '${option}'" 1>&2
|
||||||
echo "Try 'configure --help' for more information."
|
echo "Try 'configure --help' for more information." 1>&2
|
||||||
exit 1 ;;
|
exit 1 ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Check if the option took a separate argument
|
# Check if the option took a separate argument
|
||||||
if [ "${arg2}" = yes ] ; then
|
if [ "${arg2}" = yes ] ; then
|
||||||
if [ $# != 0 ] ; then args="${args} \"$1\"" ; shift
|
if [ $# != 0 ] ; then args="${args} \"$1\"" ; shift
|
||||||
else echo "configure: Missing argument to \"${option}\"" 1>&2
|
else echo "configure: Missing argument to '${option}'" 1>&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
@ -125,10 +125,8 @@ if [ -z "${srcdir}" ] ; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -r "${srcdir}/${srctrigger}" ] ; then
|
if [ ! -r "${srcdir}/${srctrigger}" ] ; then
|
||||||
exec 1>&2
|
echo "configure: Can't find sources in ${srcdir} ${srcdirtext}" 1>&2
|
||||||
echo
|
echo "configure: (At least ${srctrigger} is missing)." 1>&2
|
||||||
echo "configure: Can't find sources in ${srcdir} ${srcdirtext}"
|
|
||||||
echo "configure: (At least ${srctrigger} is missing)."
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -166,7 +164,7 @@ echo "CXXFLAGS = ${CXXFLAGS}"
|
||||||
echo "LDFLAGS = ${LDFLAGS}"
|
echo "LDFLAGS = ${LDFLAGS}"
|
||||||
rm -f Makefile
|
rm -f Makefile
|
||||||
cat > Makefile << EOF
|
cat > Makefile << EOF
|
||||||
# Makefile for Plzip - A parallel compressor compatible with lzip
|
# Makefile for Plzip - Parallel compressor compatible with lzip
|
||||||
# Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
# Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
# This file was generated automatically by configure. Do not edit.
|
# This file was generated automatically by configure. Do not edit.
|
||||||
#
|
#
|
||||||
|
|
|
@ -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 Laszlo Ersek.
|
||||||
Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ extern "C" void * dworker_o( void * arg )
|
||||||
LZ_Decoder * const decoder = LZ_decompress_open();
|
LZ_Decoder * const decoder = LZ_decompress_open();
|
||||||
if( !new_data || !ibuffer || !decoder ||
|
if( !new_data || !ibuffer || !decoder ||
|
||||||
LZ_decompress_errno( decoder ) != LZ_ok )
|
LZ_decompress_errno( decoder ) != LZ_ok )
|
||||||
{ pp( "Not enough memory" ); fatal(); }
|
{ pp( "Not enough memory" ); cleanup_and_fail(); }
|
||||||
int new_pos = 0;
|
int new_pos = 0;
|
||||||
|
|
||||||
for( int i = worker_id; i < file_index.members(); i += num_workers )
|
for( int i = worker_id; i < file_index.members(); i += num_workers )
|
||||||
|
@ -188,7 +188,7 @@ extern "C" void * dworker_o( void * arg )
|
||||||
if( size > 0 )
|
if( size > 0 )
|
||||||
{
|
{
|
||||||
if( preadblock( infd, ibuffer, size, member_pos ) != size )
|
if( preadblock( infd, ibuffer, size, member_pos ) != size )
|
||||||
{ pp(); show_error( "Read error", errno ); fatal(); }
|
{ pp(); show_error( "Read error", errno ); cleanup_and_fail(); }
|
||||||
member_pos += size;
|
member_pos += size;
|
||||||
member_rest -= size;
|
member_rest -= size;
|
||||||
if( LZ_decompress_write( decoder, ibuffer, size ) != size )
|
if( LZ_decompress_write( decoder, ibuffer, size ) != size )
|
||||||
|
@ -201,7 +201,7 @@ extern "C" void * dworker_o( void * arg )
|
||||||
const int rd = LZ_decompress_read( decoder, new_data + new_pos,
|
const int rd = LZ_decompress_read( decoder, new_data + new_pos,
|
||||||
max_packet_size - new_pos );
|
max_packet_size - new_pos );
|
||||||
if( rd < 0 )
|
if( rd < 0 )
|
||||||
fatal( decompress_read_error( decoder, pp, worker_id ) );
|
cleanup_and_fail( decompress_read_error( decoder, pp, worker_id ) );
|
||||||
new_pos += rd;
|
new_pos += rd;
|
||||||
if( new_pos > max_packet_size )
|
if( new_pos > max_packet_size )
|
||||||
internal_error( "opacket size exceeded in worker" );
|
internal_error( "opacket size exceeded in worker" );
|
||||||
|
@ -216,7 +216,7 @@ extern "C" void * dworker_o( void * arg )
|
||||||
courier.collect_packet( opacket, worker_id );
|
courier.collect_packet( opacket, worker_id );
|
||||||
new_pos = 0;
|
new_pos = 0;
|
||||||
new_data = new( std::nothrow ) uint8_t[max_packet_size];
|
new_data = new( std::nothrow ) uint8_t[max_packet_size];
|
||||||
if( !new_data ) { pp( "Not enough memory" ); fatal(); }
|
if( !new_data ) { pp( "Not enough memory" ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
if( LZ_decompress_finished( decoder ) == 1 )
|
if( LZ_decompress_finished( decoder ) == 1 )
|
||||||
{
|
{
|
||||||
|
@ -235,9 +235,9 @@ extern "C" void * dworker_o( void * arg )
|
||||||
|
|
||||||
delete[] ibuffer; delete[] new_data;
|
delete[] ibuffer; delete[] new_data;
|
||||||
if( LZ_decompress_member_position( decoder ) != 0 )
|
if( LZ_decompress_member_position( decoder ) != 0 )
|
||||||
{ pp( "Error, some data remains in decoder" ); fatal(); }
|
{ pp( "Error, some data remains in decoder" ); cleanup_and_fail(); }
|
||||||
if( LZ_decompress_close( decoder ) < 0 )
|
if( LZ_decompress_close( decoder ) < 0 )
|
||||||
{ pp( "LZ_decompress_close failed" ); fatal(); }
|
{ pp( "LZ_decompress_close failed" ); cleanup_and_fail(); }
|
||||||
courier.worker_finished();
|
courier.worker_finished();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -256,7 +256,7 @@ void muxer( Packet_courier & courier, const Pretty_print & pp, const int outfd )
|
||||||
{
|
{
|
||||||
const int wr = writeblock( outfd, opacket->data, opacket->size );
|
const int wr = writeblock( outfd, opacket->data, opacket->size );
|
||||||
if( wr != opacket->size )
|
if( wr != opacket->size )
|
||||||
{ pp(); show_error( "Write error", errno ); fatal(); }
|
{ pp(); show_error( "Write error", errno ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
delete[] opacket->data;
|
delete[] opacket->data;
|
||||||
delete opacket;
|
delete opacket;
|
||||||
|
@ -280,7 +280,7 @@ int dec_stdout( const int num_workers, const int infd, const int outfd,
|
||||||
Worker_arg * worker_args = new( std::nothrow ) Worker_arg[num_workers];
|
Worker_arg * worker_args = new( std::nothrow ) Worker_arg[num_workers];
|
||||||
pthread_t * worker_threads = new( std::nothrow ) pthread_t[num_workers];
|
pthread_t * worker_threads = new( std::nothrow ) pthread_t[num_workers];
|
||||||
if( !worker_args || !worker_threads )
|
if( !worker_args || !worker_threads )
|
||||||
{ pp( "Not enough memory" ); fatal(); }
|
{ pp( "Not enough memory" ); cleanup_and_fail(); }
|
||||||
for( int i = 0; i < num_workers; ++i )
|
for( int i = 0; i < num_workers; ++i )
|
||||||
{
|
{
|
||||||
worker_args[i].file_index = &file_index;
|
worker_args[i].file_index = &file_index;
|
||||||
|
@ -292,7 +292,7 @@ int dec_stdout( const int num_workers, const int infd, const int outfd,
|
||||||
const int errcode =
|
const int errcode =
|
||||||
pthread_create( &worker_threads[i], 0, dworker_o, &worker_args[i] );
|
pthread_create( &worker_threads[i], 0, dworker_o, &worker_args[i] );
|
||||||
if( errcode )
|
if( errcode )
|
||||||
{ show_error( "Can't create worker threads", errcode ); fatal(); }
|
{ show_error( "Can't create worker threads", errcode ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
muxer( courier, pp, outfd );
|
muxer( courier, pp, outfd );
|
||||||
|
@ -301,7 +301,7 @@ int dec_stdout( const int num_workers, const int infd, const int outfd,
|
||||||
{
|
{
|
||||||
const int errcode = pthread_join( worker_threads[i], 0 );
|
const int errcode = pthread_join( worker_threads[i], 0 );
|
||||||
if( errcode )
|
if( errcode )
|
||||||
{ show_error( "Can't join worker threads", errcode ); fatal(); }
|
{ show_error( "Can't join worker threads", errcode ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
delete[] worker_threads;
|
delete[] worker_threads;
|
||||||
delete[] worker_args;
|
delete[] worker_args;
|
||||||
|
|
|
@ -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 Laszlo Ersek.
|
||||||
Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
|
|
||||||
|
@ -248,22 +248,31 @@ extern "C" void * dsplitter_s( void * arg )
|
||||||
Packet_courier & courier = *tmp.courier;
|
Packet_courier & courier = *tmp.courier;
|
||||||
const Pretty_print & pp = *tmp.pp;
|
const Pretty_print & pp = *tmp.pp;
|
||||||
const int infd = tmp.infd;
|
const int infd = tmp.infd;
|
||||||
const int hsize = 6; // header size
|
const int hsize = File_header::size;
|
||||||
const int tsize = 20; // trailer size
|
const int tsize = File_trailer::size;
|
||||||
const int buffer_size = max_packet_size;
|
const int buffer_size = max_packet_size;
|
||||||
const int base_buffer_size = tsize + buffer_size + hsize;
|
const int base_buffer_size = tsize + buffer_size + hsize;
|
||||||
uint8_t * const base_buffer = new( std::nothrow ) uint8_t[base_buffer_size];
|
uint8_t * const base_buffer = new( std::nothrow ) uint8_t[base_buffer_size];
|
||||||
if( !base_buffer ) { pp( "Not enough memory" ); fatal(); }
|
if( !base_buffer ) { pp( "Not enough memory" ); cleanup_and_fail(); }
|
||||||
uint8_t * const buffer = base_buffer + tsize;
|
uint8_t * const buffer = base_buffer + tsize;
|
||||||
|
|
||||||
int size = readblock( infd, buffer, buffer_size + hsize ) - hsize;
|
int size = readblock( infd, buffer, buffer_size + hsize ) - hsize;
|
||||||
bool at_stream_end = ( size < buffer_size );
|
bool at_stream_end = ( size < buffer_size );
|
||||||
if( size != buffer_size && errno )
|
if( size != buffer_size && errno )
|
||||||
{ pp(); show_error( "Read error", errno ); fatal(); }
|
{ pp(); show_error( "Read error", errno ); cleanup_and_fail(); }
|
||||||
if( size <= tsize )
|
if( size + hsize < min_member_size )
|
||||||
{ pp( "Error reading member header" ); fatal(); }
|
{ pp( "Input file is too short" ); cleanup_and_fail( 2 ); }
|
||||||
if( find_magic( buffer, 0, 4 ) != 0 )
|
const File_header & header = *(File_header *)buffer;
|
||||||
{ pp( "Bad magic number (file not in lzip format)" ); fatal(); }
|
if( !header.verify_magic() )
|
||||||
|
{ pp( "Bad magic number (file not in lzip format)" ); cleanup_and_fail( 2 ); }
|
||||||
|
if( !header.verify_version() )
|
||||||
|
{
|
||||||
|
if( verbosity >= 0 )
|
||||||
|
{ pp();
|
||||||
|
std::fprintf( stderr, "Version %d member format not supported.\n",
|
||||||
|
header.version() ); }
|
||||||
|
cleanup_and_fail( 2 );
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long long partial_member_size = 0;
|
unsigned long long partial_member_size = 0;
|
||||||
while( true )
|
while( true )
|
||||||
|
@ -274,13 +283,21 @@ extern "C" void * dsplitter_s( void * arg )
|
||||||
newpos = find_magic( buffer, newpos, size + 4 - newpos );
|
newpos = find_magic( buffer, newpos, size + 4 - newpos );
|
||||||
if( newpos <= size )
|
if( newpos <= size )
|
||||||
{
|
{
|
||||||
unsigned long long member_size = 0;
|
const File_trailer & trailer = *(File_trailer *)(buffer + newpos - tsize);
|
||||||
for( int i = 1; i <= 8; ++i )
|
const unsigned long long member_size = trailer.member_size();
|
||||||
{ member_size <<= 8; member_size += base_buffer[tsize+newpos-i]; }
|
|
||||||
if( partial_member_size + newpos - pos == member_size )
|
if( partial_member_size + newpos - pos == member_size )
|
||||||
{ // header found
|
{ // header found
|
||||||
|
const File_header & header = *(File_header *)(buffer + newpos);
|
||||||
|
if( !header.verify_version() )
|
||||||
|
{
|
||||||
|
if( verbosity >= 0 )
|
||||||
|
{ pp();
|
||||||
|
std::fprintf( stderr, "Version %d member format not supported.\n",
|
||||||
|
header.version() ); }
|
||||||
|
cleanup_and_fail( 2 );
|
||||||
|
}
|
||||||
uint8_t * const data = new( std::nothrow ) uint8_t[newpos - pos];
|
uint8_t * const data = new( std::nothrow ) uint8_t[newpos - pos];
|
||||||
if( !data ) { pp( "Not enough memory" ); fatal(); }
|
if( !data ) { pp( "Not enough memory" ); cleanup_and_fail(); }
|
||||||
std::memcpy( data, buffer + pos, newpos - pos );
|
std::memcpy( data, buffer + pos, newpos - pos );
|
||||||
courier.receive_packet( data, newpos - pos );
|
courier.receive_packet( data, newpos - pos );
|
||||||
courier.receive_packet( 0, 0 ); // end of member token
|
courier.receive_packet( 0, 0 ); // end of member token
|
||||||
|
@ -293,7 +310,7 @@ extern "C" void * dsplitter_s( void * arg )
|
||||||
if( at_stream_end )
|
if( at_stream_end )
|
||||||
{
|
{
|
||||||
uint8_t * data = new( std::nothrow ) uint8_t[size + hsize - pos];
|
uint8_t * data = new( std::nothrow ) uint8_t[size + hsize - pos];
|
||||||
if( !data ) { pp( "Not enough memory" ); fatal(); }
|
if( !data ) { pp( "Not enough memory" ); cleanup_and_fail(); }
|
||||||
std::memcpy( data, buffer + pos, size + hsize - pos );
|
std::memcpy( data, buffer + pos, size + hsize - pos );
|
||||||
courier.receive_packet( data, size + hsize - pos );
|
courier.receive_packet( data, size + hsize - pos );
|
||||||
courier.receive_packet( 0, 0 ); // end of member token
|
courier.receive_packet( 0, 0 ); // end of member token
|
||||||
|
@ -303,7 +320,7 @@ extern "C" void * dsplitter_s( void * arg )
|
||||||
{
|
{
|
||||||
partial_member_size += buffer_size - pos;
|
partial_member_size += buffer_size - pos;
|
||||||
uint8_t * data = new( std::nothrow ) uint8_t[buffer_size - pos];
|
uint8_t * data = new( std::nothrow ) uint8_t[buffer_size - pos];
|
||||||
if( !data ) { pp( "Not enough memory" ); fatal(); }
|
if( !data ) { pp( "Not enough memory" ); cleanup_and_fail(); }
|
||||||
std::memcpy( data, buffer + pos, buffer_size - pos );
|
std::memcpy( data, buffer + pos, buffer_size - pos );
|
||||||
courier.receive_packet( data, buffer_size - pos );
|
courier.receive_packet( data, buffer_size - pos );
|
||||||
}
|
}
|
||||||
|
@ -311,7 +328,7 @@ extern "C" void * dsplitter_s( void * arg )
|
||||||
size = readblock( infd, buffer + hsize, buffer_size );
|
size = readblock( infd, buffer + hsize, buffer_size );
|
||||||
at_stream_end = ( size < buffer_size );
|
at_stream_end = ( size < buffer_size );
|
||||||
if( size != buffer_size && errno )
|
if( size != buffer_size && errno )
|
||||||
{ pp(); show_error( "Read error", errno ); fatal(); }
|
{ pp(); show_error( "Read error", errno ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
delete[] base_buffer;
|
delete[] base_buffer;
|
||||||
courier.finish(); // no more packets to send
|
courier.finish(); // no more packets to send
|
||||||
|
@ -339,7 +356,7 @@ extern "C" void * dworker_s( void * arg )
|
||||||
uint8_t * new_data = new( std::nothrow ) uint8_t[max_packet_size];
|
uint8_t * new_data = new( std::nothrow ) uint8_t[max_packet_size];
|
||||||
LZ_Decoder * const decoder = LZ_decompress_open();
|
LZ_Decoder * const decoder = LZ_decompress_open();
|
||||||
if( !new_data || !decoder || LZ_decompress_errno( decoder ) != LZ_ok )
|
if( !new_data || !decoder || LZ_decompress_errno( decoder ) != LZ_ok )
|
||||||
{ pp( "Not enough memory" ); fatal(); }
|
{ pp( "Not enough memory" ); cleanup_and_fail(); }
|
||||||
int new_pos = 0;
|
int new_pos = 0;
|
||||||
bool trailing_garbage_found = false;
|
bool trailing_garbage_found = false;
|
||||||
|
|
||||||
|
@ -370,7 +387,7 @@ extern "C" void * dworker_s( void * arg )
|
||||||
if( LZ_decompress_errno( decoder ) == LZ_header_error )
|
if( LZ_decompress_errno( decoder ) == LZ_header_error )
|
||||||
trailing_garbage_found = true;
|
trailing_garbage_found = true;
|
||||||
else
|
else
|
||||||
fatal( decompress_read_error( decoder, pp, worker_id ) );
|
cleanup_and_fail( decompress_read_error( decoder, pp, worker_id ) );
|
||||||
}
|
}
|
||||||
else new_pos += rd;
|
else new_pos += rd;
|
||||||
if( new_pos > max_packet_size )
|
if( new_pos > max_packet_size )
|
||||||
|
@ -386,7 +403,7 @@ extern "C" void * dworker_s( void * arg )
|
||||||
courier.collect_packet( opacket, worker_id );
|
courier.collect_packet( opacket, worker_id );
|
||||||
new_pos = 0;
|
new_pos = 0;
|
||||||
new_data = new( std::nothrow ) uint8_t[max_packet_size];
|
new_data = new( std::nothrow ) uint8_t[max_packet_size];
|
||||||
if( !new_data ) { pp( "Not enough memory" ); fatal(); }
|
if( !new_data ) { pp( "Not enough memory" ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
if( trailing_garbage_found ||
|
if( trailing_garbage_found ||
|
||||||
LZ_decompress_finished( decoder ) == 1 )
|
LZ_decompress_finished( decoder ) == 1 )
|
||||||
|
@ -409,9 +426,9 @@ extern "C" void * dworker_s( void * arg )
|
||||||
|
|
||||||
delete[] new_data;
|
delete[] new_data;
|
||||||
if( LZ_decompress_member_position( decoder ) != 0 )
|
if( LZ_decompress_member_position( decoder ) != 0 )
|
||||||
{ pp( "Error, some data remains in decoder" ); fatal(); }
|
{ pp( "Error, some data remains in decoder" ); cleanup_and_fail(); }
|
||||||
if( LZ_decompress_close( decoder ) < 0 )
|
if( LZ_decompress_close( decoder ) < 0 )
|
||||||
{ pp( "LZ_decompress_close failed" ); fatal(); }
|
{ pp( "LZ_decompress_close failed" ); cleanup_and_fail(); }
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,7 +448,7 @@ void muxer( Packet_courier & courier, const Pretty_print & pp, const int outfd )
|
||||||
{
|
{
|
||||||
const int wr = writeblock( outfd, opacket->data, opacket->size );
|
const int wr = writeblock( outfd, opacket->data, opacket->size );
|
||||||
if( wr != opacket->size )
|
if( wr != opacket->size )
|
||||||
{ pp(); show_error( "Write error", errno ); fatal(); }
|
{ pp(); show_error( "Write error", errno ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
delete[] opacket->data;
|
delete[] opacket->data;
|
||||||
delete opacket;
|
delete opacket;
|
||||||
|
@ -462,12 +479,12 @@ int dec_stream( const int num_workers, const int infd, const int outfd,
|
||||||
pthread_t splitter_thread;
|
pthread_t splitter_thread;
|
||||||
int errcode = pthread_create( &splitter_thread, 0, dsplitter_s, &splitter_arg );
|
int errcode = pthread_create( &splitter_thread, 0, dsplitter_s, &splitter_arg );
|
||||||
if( errcode )
|
if( errcode )
|
||||||
{ show_error( "Can't create splitter thread", errcode ); fatal(); }
|
{ show_error( "Can't create splitter thread", errcode ); cleanup_and_fail(); }
|
||||||
|
|
||||||
Worker_arg * worker_args = new( std::nothrow ) Worker_arg[num_workers];
|
Worker_arg * worker_args = new( std::nothrow ) Worker_arg[num_workers];
|
||||||
pthread_t * worker_threads = new( std::nothrow ) pthread_t[num_workers];
|
pthread_t * worker_threads = new( std::nothrow ) pthread_t[num_workers];
|
||||||
if( !worker_args || !worker_threads )
|
if( !worker_args || !worker_threads )
|
||||||
{ pp( "Not enough memory" ); fatal(); }
|
{ pp( "Not enough memory" ); cleanup_and_fail(); }
|
||||||
for( int i = 0; i < num_workers; ++i )
|
for( int i = 0; i < num_workers; ++i )
|
||||||
{
|
{
|
||||||
worker_args[i].courier = &courier;
|
worker_args[i].courier = &courier;
|
||||||
|
@ -475,7 +492,7 @@ int dec_stream( const int num_workers, const int infd, const int outfd,
|
||||||
worker_args[i].worker_id = i;
|
worker_args[i].worker_id = i;
|
||||||
errcode = pthread_create( &worker_threads[i], 0, dworker_s, &worker_args[i] );
|
errcode = pthread_create( &worker_threads[i], 0, dworker_s, &worker_args[i] );
|
||||||
if( errcode )
|
if( errcode )
|
||||||
{ show_error( "Can't create worker threads", errcode ); fatal(); }
|
{ show_error( "Can't create worker threads", errcode ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
muxer( courier, pp, outfd );
|
muxer( courier, pp, outfd );
|
||||||
|
@ -484,14 +501,14 @@ int dec_stream( const int num_workers, const int infd, const int outfd,
|
||||||
{
|
{
|
||||||
errcode = pthread_join( worker_threads[i], 0 );
|
errcode = pthread_join( worker_threads[i], 0 );
|
||||||
if( errcode )
|
if( errcode )
|
||||||
{ show_error( "Can't join worker threads", errcode ); fatal(); }
|
{ show_error( "Can't join worker threads", errcode ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
delete[] worker_threads;
|
delete[] worker_threads;
|
||||||
delete[] worker_args;
|
delete[] worker_args;
|
||||||
|
|
||||||
errcode = pthread_join( splitter_thread, 0 );
|
errcode = pthread_join( splitter_thread, 0 );
|
||||||
if( errcode )
|
if( errcode )
|
||||||
{ show_error( "Can't join splitter thread", errcode ); fatal(); }
|
{ show_error( "Can't join splitter thread", errcode ); cleanup_and_fail(); }
|
||||||
|
|
||||||
if( verbosity >= 2 && out_size > 0 && in_size > 0 )
|
if( verbosity >= 2 && out_size > 0 && in_size > 0 )
|
||||||
std::fprintf( stderr, "%6.3f:1, %6.3f bits/byte, %5.2f%% saved. ",
|
std::fprintf( stderr, "%6.3f:1, %6.3f bits/byte, %5.2f%% saved. ",
|
||||||
|
|
|
@ -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 Laszlo Ersek.
|
||||||
Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ extern "C" void * dworker( void * arg )
|
||||||
LZ_Decoder * const decoder = LZ_decompress_open();
|
LZ_Decoder * const decoder = LZ_decompress_open();
|
||||||
if( !ibuffer || !obuffer || !decoder ||
|
if( !ibuffer || !obuffer || !decoder ||
|
||||||
LZ_decompress_errno( decoder ) != LZ_ok )
|
LZ_decompress_errno( decoder ) != LZ_ok )
|
||||||
{ pp( "Not enough memory" ); fatal(); }
|
{ pp( "Not enough memory" ); cleanup_and_fail(); }
|
||||||
|
|
||||||
for( int i = worker_id; i < file_index.members(); i += num_workers )
|
for( int i = worker_id; i < file_index.members(); i += num_workers )
|
||||||
{
|
{
|
||||||
|
@ -140,7 +140,7 @@ extern "C" void * dworker( void * arg )
|
||||||
if( size > 0 )
|
if( size > 0 )
|
||||||
{
|
{
|
||||||
if( preadblock( infd, ibuffer, size, member_pos ) != size )
|
if( preadblock( infd, ibuffer, size, member_pos ) != size )
|
||||||
{ pp(); show_error( "Read error", errno ); fatal(); }
|
{ pp(); show_error( "Read error", errno ); cleanup_and_fail(); }
|
||||||
member_pos += size;
|
member_pos += size;
|
||||||
member_rest -= size;
|
member_rest -= size;
|
||||||
if( LZ_decompress_write( decoder, ibuffer, size ) != size )
|
if( LZ_decompress_write( decoder, ibuffer, size ) != size )
|
||||||
|
@ -152,7 +152,7 @@ extern "C" void * dworker( void * arg )
|
||||||
{
|
{
|
||||||
const int rd = LZ_decompress_read( decoder, obuffer, buffer_size );
|
const int rd = LZ_decompress_read( decoder, obuffer, buffer_size );
|
||||||
if( rd < 0 )
|
if( rd < 0 )
|
||||||
fatal( decompress_read_error( decoder, pp, worker_id ) );
|
cleanup_and_fail( decompress_read_error( decoder, pp, worker_id ) );
|
||||||
if( rd > 0 && outfd >= 0 )
|
if( rd > 0 && outfd >= 0 )
|
||||||
{
|
{
|
||||||
const int wr = pwriteblock( outfd, obuffer, rd, data_pos );
|
const int wr = pwriteblock( outfd, obuffer, rd, data_pos );
|
||||||
|
@ -162,7 +162,7 @@ extern "C" void * dworker( void * arg )
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "Write error in worker %d: %s\n",
|
std::fprintf( stderr, "Write error in worker %d: %s\n",
|
||||||
worker_id, std::strerror( errno ) );
|
worker_id, std::strerror( errno ) );
|
||||||
fatal();
|
cleanup_and_fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( rd > 0 )
|
if( rd > 0 )
|
||||||
|
@ -184,9 +184,9 @@ extern "C" void * dworker( void * arg )
|
||||||
|
|
||||||
delete[] obuffer; delete[] ibuffer;
|
delete[] obuffer; delete[] ibuffer;
|
||||||
if( LZ_decompress_member_position( decoder ) != 0 )
|
if( LZ_decompress_member_position( decoder ) != 0 )
|
||||||
{ pp( "Error, some data remains in decoder" ); fatal(); }
|
{ pp( "Error, some data remains in decoder" ); cleanup_and_fail(); }
|
||||||
if( LZ_decompress_close( decoder ) < 0 )
|
if( LZ_decompress_close( decoder ) < 0 )
|
||||||
{ pp( "LZ_decompress_close failed" ); fatal(); }
|
{ pp( "LZ_decompress_close failed" ); cleanup_and_fail(); }
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +208,7 @@ int decompress( int num_workers, const int infd, const int outfd,
|
||||||
return dec_stream( num_workers, infd, outfd, pp, debug_level, testing );
|
return dec_stream( num_workers, infd, outfd, pp, debug_level, testing );
|
||||||
}
|
}
|
||||||
if( file_index.retval() != 0 )
|
if( file_index.retval() != 0 )
|
||||||
{ show_error( file_index.error().c_str() ); return file_index.retval(); }
|
{ pp( file_index.error().c_str() ); return file_index.retval(); }
|
||||||
|
|
||||||
if( num_workers > file_index.members() )
|
if( num_workers > file_index.members() )
|
||||||
num_workers = file_index.members();
|
num_workers = file_index.members();
|
||||||
|
@ -224,7 +224,7 @@ int decompress( int num_workers, const int infd, const int outfd,
|
||||||
Worker_arg * worker_args = new( std::nothrow ) Worker_arg[num_workers];
|
Worker_arg * worker_args = new( std::nothrow ) Worker_arg[num_workers];
|
||||||
pthread_t * worker_threads = new( std::nothrow ) pthread_t[num_workers];
|
pthread_t * worker_threads = new( std::nothrow ) pthread_t[num_workers];
|
||||||
if( !worker_args || !worker_threads )
|
if( !worker_args || !worker_threads )
|
||||||
{ pp( "Not enough memory" ); fatal(); }
|
{ pp( "Not enough memory" ); cleanup_and_fail(); }
|
||||||
for( int i = 0; i < num_workers; ++i )
|
for( int i = 0; i < num_workers; ++i )
|
||||||
{
|
{
|
||||||
worker_args[i].file_index = &file_index;
|
worker_args[i].file_index = &file_index;
|
||||||
|
@ -236,14 +236,14 @@ int decompress( int num_workers, const int infd, const int outfd,
|
||||||
const int errcode =
|
const int errcode =
|
||||||
pthread_create( &worker_threads[i], 0, dworker, &worker_args[i] );
|
pthread_create( &worker_threads[i], 0, dworker, &worker_args[i] );
|
||||||
if( errcode )
|
if( errcode )
|
||||||
{ show_error( "Can't create worker threads", errcode ); fatal(); }
|
{ show_error( "Can't create worker threads", errcode ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
for( int i = num_workers - 1; i >= 0; --i )
|
for( int i = num_workers - 1; i >= 0; --i )
|
||||||
{
|
{
|
||||||
const int errcode = pthread_join( worker_threads[i], 0 );
|
const int errcode = pthread_join( worker_threads[i], 0 );
|
||||||
if( errcode )
|
if( errcode )
|
||||||
{ show_error( "Can't join worker threads", errcode ); fatal(); }
|
{ show_error( "Can't join worker threads", errcode ); cleanup_and_fail(); }
|
||||||
}
|
}
|
||||||
delete[] worker_threads;
|
delete[] worker_threads;
|
||||||
delete[] worker_args;
|
delete[] worker_args;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1.
|
||||||
.TH PLZIP "1" "May 2013" "Plzip 1.0" "User Commands"
|
.TH PLZIP "1" "July 2013" "Plzip 1.1-pre1" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
Plzip \- reduces the size of files
|
Plzip \- reduces the size of files
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B plzip
|
.B plzip
|
||||||
[\fIoptions\fR] [\fIfiles\fR]
|
[\fIoptions\fR] [\fIfiles\fR]
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
Plzip \- A parallel compressor compatible with lzip.
|
Plzip \- Parallel compressor compatible with lzip.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
\fB\-h\fR, \fB\-\-help\fR
|
\fB\-h\fR, \fB\-\-help\fR
|
||||||
|
|
105
doc/plzip.info
105
doc/plzip.info
|
@ -12,16 +12,16 @@ File: plzip.info, Node: Top, Next: Introduction, Up: (dir)
|
||||||
Plzip Manual
|
Plzip Manual
|
||||||
************
|
************
|
||||||
|
|
||||||
This manual is for Plzip (version 1.0, 29 May 2013).
|
This manual is for Plzip (version 1.1-pre1, 20 July 2013).
|
||||||
|
|
||||||
* Menu:
|
* Menu:
|
||||||
|
|
||||||
* Introduction:: Purpose and features of plzip
|
* Introduction:: Purpose and features of plzip
|
||||||
* Program Design:: Internal structure of plzip
|
* Program design:: Internal structure of plzip
|
||||||
* Invoking Plzip:: Command line interface
|
* Invoking plzip:: Command line interface
|
||||||
* File Format:: Detailed format of the compressed file
|
* File format:: Detailed format of the compressed file
|
||||||
* Problems:: Reporting bugs
|
* Problems:: Reporting bugs
|
||||||
* Concept Index:: Index of concepts
|
* Concept index:: Index of concepts
|
||||||
|
|
||||||
|
|
||||||
Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||||
|
@ -30,27 +30,46 @@ This manual is for Plzip (version 1.0, 29 May 2013).
|
||||||
copy, distribute and modify it.
|
copy, distribute and modify it.
|
||||||
|
|
||||||
|
|
||||||
File: plzip.info, Node: Introduction, Next: Program Design, Prev: Top, Up: Top
|
File: plzip.info, Node: Introduction, Next: Program design, Prev: Top, Up: Top
|
||||||
|
|
||||||
1 Introduction
|
1 Introduction
|
||||||
**************
|
**************
|
||||||
|
|
||||||
Plzip is a massively parallel (multi-threaded), lossless data compressor
|
Plzip is a massively parallel (multi-threaded), lossless data compressor
|
||||||
based on the lzlib compression library, with very safe integrity
|
based on the lzlib compression library, with a user interface similar to
|
||||||
checking and a user interface similar to the one of bzip2, gzip or lzip.
|
the one of lzip, bzip2 or gzip.
|
||||||
|
|
||||||
Plzip is intended for faster compression/decompression of big files
|
Plzip can compress/decompress large files on multiprocessor machines
|
||||||
on multiprocessor machines, which makes it specially well suited for
|
much faster than lzip, at the cost of a slightly reduced compression
|
||||||
distribution of big software files and large scale data archiving. On
|
ratio. On files large enough (several GB), plzip can use hundreds of
|
||||||
files big enough (several GB), plzip can use hundreds of processors.
|
processors. On files of only a few MB it is better to use lzip.
|
||||||
|
|
||||||
|
Plzip uses the same well-defined exit status values used by lzip and
|
||||||
|
bzip2, which makes it safer when used in pipes or scripts than
|
||||||
|
compressors returning ambiguous warning values, like gzip.
|
||||||
|
|
||||||
Plzip uses the lzip file format; the files produced by plzip are
|
Plzip uses the lzip file format; the files produced by plzip are
|
||||||
fully compatible with lzip-1.4 or newer, and can be rescued with
|
fully compatible with lzip-1.4 or newer, and can be rescued with
|
||||||
lziprecover.
|
lziprecover.
|
||||||
|
|
||||||
Plzip uses the same well-defined exit status values used by lzip and
|
The lzip file format is designed for long-term data archiving and
|
||||||
bzip2, which makes it safer when used in pipes or scripts than
|
provides very safe integrity checking. The member trailer stores the
|
||||||
compressors returning ambiguous warning values, like gzip.
|
32-bit CRC of the original data, the size of the original data and the
|
||||||
|
size of the member. These values, together with the value remaining in
|
||||||
|
the range decoder and the end-of-stream marker, provide a 4 factor
|
||||||
|
integrity checking which guarantees that the decompressed version of the
|
||||||
|
data is identical to the original. This guards against corruption of the
|
||||||
|
compressed data, and against undetected bugs in plzip (hopefully very
|
||||||
|
unlikely). The chances of data corruption going undetected are
|
||||||
|
microscopic. Be aware, though, that the check occurs upon decompression,
|
||||||
|
so it can only tell you that something is wrong. It can't help you
|
||||||
|
recover the original uncompressed data.
|
||||||
|
|
||||||
|
If you ever need to recover data from a damaged lzip file, try the
|
||||||
|
lziprecover program. Lziprecover makes lzip files resistant to bit-flip
|
||||||
|
(one of the most common forms of data corruption), and provides data
|
||||||
|
recovery capabilities, including error-checked merging of damaged copies
|
||||||
|
of a file.
|
||||||
|
|
||||||
Plzip replaces every file given in the command line with a compressed
|
Plzip replaces every file given in the command line with a compressed
|
||||||
version of itself, with the name "original_name.lz". Each compressed
|
version of itself, with the name "original_name.lz". Each compressed
|
||||||
|
@ -76,18 +95,6 @@ filename.lz becomes filename
|
||||||
filename.tlz becomes filename.tar
|
filename.tlz becomes filename.tar
|
||||||
anyothername becomes anyothername.out
|
anyothername becomes anyothername.out
|
||||||
|
|
||||||
As a self-check for your protection, plzip stores in the member
|
|
||||||
trailer the 32-bit CRC of the original data, the size of the original
|
|
||||||
data and the size of the member. These values, together with the value
|
|
||||||
remaining in the range decoder and the end-of-stream marker, provide a
|
|
||||||
very safe 4 factor integrity checking which guarantees that the
|
|
||||||
decompressed version of the data is identical to the original. This
|
|
||||||
guards against corruption of the compressed data, and against
|
|
||||||
undetected bugs in plzip (hopefully very unlikely). The chances of data
|
|
||||||
corruption going undetected are microscopic. Be aware, though, that the
|
|
||||||
check occurs upon decompression, so it can only tell you that something
|
|
||||||
is wrong. It can't help you recover the original uncompressed data.
|
|
||||||
|
|
||||||
WARNING! Even if plzip is bug-free, other causes may result in a
|
WARNING! Even if plzip is bug-free, other causes may result in a
|
||||||
corrupt compressed file (bugs in the system libraries, memory errors,
|
corrupt compressed file (bugs in the system libraries, memory errors,
|
||||||
etc). Therefore, if the data you are going to compress is important,
|
etc). Therefore, if the data you are going to compress is important,
|
||||||
|
@ -96,9 +103,9 @@ until you verify the compressed file with a command like
|
||||||
`plzip -cd file.lz | cmp file -'.
|
`plzip -cd file.lz | cmp file -'.
|
||||||
|
|
||||||
|
|
||||||
File: plzip.info, Node: Program Design, Next: Invoking Plzip, Prev: Introduction, Up: Top
|
File: plzip.info, Node: Program design, Next: Invoking plzip, Prev: Introduction, Up: Top
|
||||||
|
|
||||||
2 Program Design
|
2 Program design
|
||||||
****************
|
****************
|
||||||
|
|
||||||
For each input file, a splitter thread and several worker threads are
|
For each input file, a splitter thread and several worker threads are
|
||||||
|
@ -119,9 +126,9 @@ speed of large files with many members is only limited by the number of
|
||||||
processors available and by I/O speed.
|
processors available and by I/O speed.
|
||||||
|
|
||||||
|
|
||||||
File: plzip.info, Node: Invoking Plzip, Next: File Format, Prev: Program Design, Up: Top
|
File: plzip.info, Node: Invoking plzip, Next: File format, Prev: Program design, Up: Top
|
||||||
|
|
||||||
3 Invoking Plzip
|
3 Invoking plzip
|
||||||
****************
|
****************
|
||||||
|
|
||||||
The format for running plzip is:
|
The format for running plzip is:
|
||||||
|
@ -220,7 +227,7 @@ The format for running plzip is:
|
||||||
`--verbose'
|
`--verbose'
|
||||||
Verbose mode.
|
Verbose mode.
|
||||||
When compressing, show the compression ratio for each file
|
When compressing, show the compression ratio for each file
|
||||||
processed.
|
processed. A second -v shows the progress of compression.
|
||||||
When decompressing or testing, further -v's (up to 4) increase the
|
When decompressing or testing, further -v's (up to 4) increase the
|
||||||
verbosity level, showing status, compression ratio, decompressed
|
verbosity level, showing status, compression ratio, decompressed
|
||||||
size, and compressed size.
|
size, and compressed size.
|
||||||
|
@ -275,9 +282,9 @@ invalid input file, 3 for an internal consistency error (eg, bug) which
|
||||||
caused plzip to panic.
|
caused plzip to panic.
|
||||||
|
|
||||||
|
|
||||||
File: plzip.info, Node: File Format, Next: Problems, Prev: Invoking Plzip, Up: Top
|
File: plzip.info, Node: File format, Next: Problems, Prev: Invoking plzip, Up: Top
|
||||||
|
|
||||||
4 File Format
|
4 File format
|
||||||
*************
|
*************
|
||||||
|
|
||||||
Perfection is reached, not when there is no longer anything to add, but
|
Perfection is reached, not when there is no longer anything to add, but
|
||||||
|
@ -348,7 +355,7 @@ additional information before, between, or after them.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
File: plzip.info, Node: Problems, Next: Concept Index, Prev: File Format, Up: Top
|
File: plzip.info, Node: Problems, Next: Concept index, Prev: File format, Up: Top
|
||||||
|
|
||||||
5 Reporting Bugs
|
5 Reporting Bugs
|
||||||
****************
|
****************
|
||||||
|
@ -363,34 +370,34 @@ for all eternity, if not longer.
|
||||||
by running `plzip --version'.
|
by running `plzip --version'.
|
||||||
|
|
||||||
|
|
||||||
File: plzip.info, Node: Concept Index, Prev: Problems, Up: Top
|
File: plzip.info, Node: Concept index, Prev: Problems, Up: Top
|
||||||
|
|
||||||
Concept Index
|
Concept index
|
||||||
*************
|
*************
|
||||||
|
|
||||||
|