2012-08-27 16:21:55 +00:00
|
|
|
/*
|
|
|
|
* This file is a part of Pcompress, a chunked parallel multi-
|
|
|
|
* algorithm lossless compression and decompression program.
|
|
|
|
*
|
2013-03-07 14:56:48 +00:00
|
|
|
* Copyright (C) 2012-2013 Moinak Ghosh. All rights reserved.
|
2012-08-27 16:21:55 +00:00
|
|
|
* Use is subject to license terms.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 3 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
2013-03-07 14:56:48 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this program.
|
|
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
2012-08-27 16:21:55 +00:00
|
|
|
* moinakg@belenix.org, http://moinakg.wordpress.com/
|
2014-07-24 16:50:30 +00:00
|
|
|
*
|
2012-08-27 16:21:55 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <strings.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <utils.h>
|
|
|
|
#include <pcompress.h>
|
|
|
|
#include <allocator.h>
|
|
|
|
#include <libbsc.h>
|
|
|
|
|
|
|
|
// 1G
|
|
|
|
#define BSC_MAX_CHUNK 1073741824L
|
|
|
|
|
|
|
|
struct libbsc_params {
|
|
|
|
int lzpHashSize;
|
|
|
|
int lzpMinLen;
|
|
|
|
int bscCoder;
|
|
|
|
int features;
|
2013-11-30 16:43:33 +00:00
|
|
|
int oldversion;
|
2012-08-27 16:21:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
libbsc_err(int err) {
|
|
|
|
switch (err) {
|
|
|
|
case LIBBSC_BAD_PARAMETER:
|
2013-10-02 15:15:33 +00:00
|
|
|
log_msg(LOG_ERR, 0, "LIBBSC: Bad Parameter.\n");
|
2012-08-27 16:21:55 +00:00
|
|
|
break;
|
|
|
|
case LIBBSC_NOT_ENOUGH_MEMORY:
|
2013-10-02 15:15:33 +00:00
|
|
|
log_msg(LOG_ERR, 0, "LIBBSC: Out of memory.\n");
|
2012-08-27 16:21:55 +00:00
|
|
|
break;
|
|
|
|
case LIBBSC_NOT_SUPPORTED:
|
2013-10-02 15:15:33 +00:00
|
|
|
log_msg(LOG_ERR, 0, "LIBBSC: Using unsupported feature.\n");
|
2012-08-27 16:21:55 +00:00
|
|
|
break;
|
|
|
|
case LIBBSC_UNEXPECTED_EOB:
|
2013-10-02 15:15:33 +00:00
|
|
|
log_msg(LOG_ERR, 0, "LIBBSC: Unexpected end of block.\n");
|
2012-08-27 16:21:55 +00:00
|
|
|
break;
|
|
|
|
case LIBBSC_DATA_CORRUPT:
|
2013-10-02 15:15:33 +00:00
|
|
|
log_msg(LOG_ERR, 0, "LIBBSC: Corrupt data.\n");
|
2012-08-27 16:21:55 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
libbsc_stats(int show)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-11-30 16:43:33 +00:00
|
|
|
int
|
|
|
|
libbsc_buf_extra(uint64_t buflen)
|
|
|
|
{
|
|
|
|
return (4096);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-27 16:21:55 +00:00
|
|
|
/*
|
2013-01-26 12:58:13 +00:00
|
|
|
* BSC uses OpenMP where it does not control thread count
|
2012-08-27 16:21:55 +00:00
|
|
|
* deterministically. We only use multithread capability in BSC
|
|
|
|
* when compressing entire file in a single chunk.
|
|
|
|
*/
|
|
|
|
void
|
2012-12-27 17:36:48 +00:00
|
|
|
libbsc_props(algo_props_t *data, int level, uint64_t chunksize) {
|
2012-08-27 16:21:55 +00:00
|
|
|
data->compress_mt_capable = 0;
|
|
|
|
data->decompress_mt_capable = 0;
|
|
|
|
data->single_chunk_mt_capable = 1;
|
|
|
|
data->buf_extra = 0;
|
|
|
|
data->c_max_threads = 8;
|
|
|
|
data->d_max_threads = 8;
|
2012-12-13 15:48:16 +00:00
|
|
|
data->delta2_span = 150;
|
2013-01-14 07:50:07 +00:00
|
|
|
if (chunksize > (EIGHTM * 2))
|
|
|
|
data->deltac_min_distance = FOURM;
|
|
|
|
else
|
|
|
|
data->deltac_min_distance = EIGHTM;
|
2012-08-27 16:21:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-12-27 17:36:48 +00:00
|
|
|
libbsc_init(void **data, int *level, int nthreads, uint64_t chunksize,
|
2012-11-22 15:32:50 +00:00
|
|
|
int file_version, compress_op_t op)
|
2012-08-27 16:21:55 +00:00
|
|
|
{
|
|
|
|
struct libbsc_params *bscdat;
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
if (chunksize > BSC_MAX_CHUNK) {
|
2013-10-02 15:15:33 +00:00
|
|
|
log_msg(LOG_ERR, 0, "Max allowed chunk size for LIBBSC is: %s \n",
|
2013-05-12 06:24:40 +00:00
|
|
|
bytes_to_size(BSC_MAX_CHUNK));
|
2012-08-27 16:21:55 +00:00
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
bscdat = slab_alloc(NULL, sizeof (struct libbsc_params));
|
|
|
|
|
|
|
|
bscdat->features = LIBBSC_FEATURE_FASTMODE;
|
|
|
|
if (nthreads > 1)
|
|
|
|
bscdat->features |= LIBBSC_FEATURE_MULTITHREADING;
|
|
|
|
|
|
|
|
if (*level > 9) *level = 9;
|
|
|
|
|
|
|
|
bscdat->lzpHashSize = LIBBSC_DEFAULT_LZPHASHSIZE + (*level - 1);
|
|
|
|
bscdat->bscCoder = LIBBSC_CODER_QLFC_STATIC;
|
|
|
|
if (*level == 0) {
|
|
|
|
bscdat->lzpMinLen = 32;
|
|
|
|
|
|
|
|
} else if (*level < 3) {
|
|
|
|
bscdat->lzpMinLen = 64;
|
|
|
|
|
|
|
|
} else if (*level < 5) {
|
|
|
|
bscdat->lzpMinLen = 128;
|
|
|
|
bscdat->bscCoder = LIBBSC_CODER_QLFC_ADAPTIVE;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
bscdat->lzpMinLen = 200;
|
|
|
|
bscdat->bscCoder = LIBBSC_CODER_QLFC_ADAPTIVE;
|
|
|
|
}
|
2013-11-30 16:43:33 +00:00
|
|
|
|
|
|
|
if (file_version < 9) {
|
|
|
|
bscdat->oldversion = 1;
|
|
|
|
}
|
2012-08-27 16:21:55 +00:00
|
|
|
*data = bscdat;
|
|
|
|
rv = bsc_init(bscdat->features);
|
|
|
|
if (rv != LIBBSC_NO_ERROR) {
|
|
|
|
libbsc_err(rv);
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
libbsc_deinit(void **data)
|
|
|
|
{
|
|
|
|
struct libbsc_params *bscdat = (struct libbsc_params *)(*data);
|
2014-07-24 16:50:30 +00:00
|
|
|
|
2012-08-27 16:21:55 +00:00
|
|
|
if (bscdat) {
|
|
|
|
slab_free(NULL, bscdat);
|
|
|
|
}
|
|
|
|
*data = NULL;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-12-09 04:45:06 +00:00
|
|
|
libbsc_compress(void *src, uint64_t srclen, void *dst, uint64_t *dstlen,
|
2013-11-08 18:20:28 +00:00
|
|
|
int level, uchar_t chdr, int btype, void *data)
|
2012-08-27 16:21:55 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
struct libbsc_params *bscdat = (struct libbsc_params *)data;
|
|
|
|
|
2013-11-09 11:16:19 +00:00
|
|
|
if (PC_TYPE(btype) == TYPE_COMPRESSED) {
|
|
|
|
int subtype = PC_SUBTYPE(btype);
|
|
|
|
if (subtype == TYPE_COMPRESSED_BZ2 || subtype == TYPE_COMPRESSED_LZMA)
|
|
|
|
return (-1);
|
|
|
|
}
|
2013-11-08 18:20:28 +00:00
|
|
|
|
2012-08-27 16:21:55 +00:00
|
|
|
rv = bsc_compress(src, dst, srclen, bscdat->lzpHashSize, bscdat->lzpMinLen,
|
|
|
|
LIBBSC_BLOCKSORTER_BWT, bscdat->bscCoder, bscdat->features);
|
|
|
|
if (rv < 0) {
|
|
|
|
libbsc_err(rv);
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
*dstlen = rv;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-12-09 04:45:06 +00:00
|
|
|
libbsc_decompress(void *src, uint64_t srclen, void *dst, uint64_t *dstlen,
|
2013-11-08 18:20:28 +00:00
|
|
|
int level, uchar_t chdr, int btype, void *data)
|
2012-08-27 16:21:55 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
struct libbsc_params *bscdat = (struct libbsc_params *)data;
|
|
|
|
|
2013-11-30 16:43:33 +00:00
|
|
|
if (bscdat->oldversion)
|
|
|
|
rv = bsc_decompress_old(src, srclen, dst, *dstlen, bscdat->features);
|
|
|
|
else
|
|
|
|
rv = bsc_decompress(src, srclen, dst, *dstlen, bscdat->features);
|
2012-08-27 16:21:55 +00:00
|
|
|
if (rv != LIBBSC_NO_ERROR) {
|
|
|
|
libbsc_err(rv);
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|