execve_hook/src/compression.c

210 lines
5.8 KiB
C

/*
* compression.c - LZ4 压缩支持
*
* 使用 LZ4 库实现高性能数据压缩,适用于终端数据流。
* LZ4 特点:
* - 压缩速度:~500 MB/s
* - 解压速度:~1500 MB/s
* - 压缩比:约 2:1 到 3:1
*/
#include "compression.h"
#include "debug.h"
#include <string.h>
#include <stdlib.h>
// 检查是否有 LZ4 库
#ifdef HAVE_LZ4
#include <lz4.h>
#include <lz4hc.h>
#define LZ4_AVAILABLE 1
#else
// 如果没有 LZ4 库,提供一个简单的回退实现
#define LZ4_AVAILABLE 0
#endif
void compression_init(CompressionContext* ctx, CompressionType type, int level) {
if (ctx == NULL) return;
memset(ctx, 0, sizeof(CompressionContext));
ctx->type = type;
ctx->level = level > 0 ? level : 9; // 默认级别
ctx->enabled = (type != COMPRESS_NONE);
#if !LZ4_AVAILABLE
if (ctx->enabled) {
DEBUG_LOG("警告: LZ4 库未编译,压缩功能已禁用");
ctx->enabled = 0;
ctx->type = COMPRESS_NONE;
}
#endif
DEBUG_LOG("压缩初始化: type=%d, level=%d, enabled=%d",
ctx->type, ctx->level, ctx->enabled);
}
size_t get_compress_bound(size_t src_size) {
#if LZ4_AVAILABLE
return LZ4_compressBound(src_size);
#else
// 无压缩时,输出大小等于输入大小
return src_size;
#endif
}
int compress_data(CompressionContext* ctx,
const void* src, size_t src_size,
void* dst, size_t dst_capacity,
uint32_t* flags) {
if (ctx == NULL || src == NULL || dst == NULL || flags == NULL) {
return -1;
}
*flags = 0;
// 如果压缩未启用或数据太小,直接复制
if (!ctx->enabled || src_size < COMPRESSION_THRESHOLD || src_size > MAX_COMPRESS_INPUT_SIZE) {
if (dst_capacity < src_size) {
DEBUG_LOG("compress_data: 缓冲区不足 %zu < %zu", dst_capacity, src_size);
return -1;
}
memcpy(dst, src, src_size);
ctx->skip_count++;
return (int)src_size;
}
#if LZ4_AVAILABLE
int compressed_size = 0;
switch (ctx->type) {
case COMPRESS_LZ4:
compressed_size = LZ4_compress_default(
(const char*)src, (char*)dst,
(int)src_size, (int)dst_capacity);
break;
case COMPRESS_LZ4_HC:
compressed_size = LZ4_compress_HC(
(const char*)src, (char*)dst,
(int)src_size, (int)dst_capacity, ctx->level);
break;
default:
// 不应该到达这里
memcpy(dst, src, src_size);
return (int)src_size;
}
if (compressed_size <= 0) {
// 压缩失败,复制原始数据
DEBUG_LOG("压缩失败,使用原始数据");
if (dst_capacity < src_size) {
return -1;
}
memcpy(dst, src, src_size);
ctx->skip_count++;
return (int)src_size;
}
// 如果压缩后更大,使用原始数据
if ((size_t)compressed_size >= src_size) {
DEBUG_LOG("压缩后更大 (%d >= %zu),使用原始数据", compressed_size, src_size);
memcpy(dst, src, src_size);
ctx->skip_count++;
return (int)src_size;
}
// 压缩成功
*flags = MSG_FLAG_COMPRESSED | MSG_FLAG_COMPRESS_LZ4;
if (ctx->type == COMPRESS_LZ4_HC) {
*flags |= MSG_FLAG_COMPRESS_HC;
}
ctx->bytes_in += src_size;
ctx->bytes_out += compressed_size;
ctx->compress_count++;
DEBUG_LOG("压缩成功: %zu -> %d (%.1f%%)",
src_size, compressed_size,
(float)compressed_size / src_size * 100);
return compressed_size;
#else
// 无 LZ4 库,直接复制
if (dst_capacity < src_size) {
return -1;
}
memcpy(dst, src, src_size);
ctx->skip_count++;
return (int)src_size;
#endif
}
int decompress_data(uint32_t flags,
const void* src, size_t src_size,
void* dst, size_t dst_capacity) {
if (src == NULL || dst == NULL) {
return -1;
}
// 如果数据未压缩,直接复制
if (!(flags & MSG_FLAG_COMPRESSED)) {
if (dst_capacity < src_size) {
DEBUG_LOG("decompress_data: 缓冲区不足 %zu < %zu", dst_capacity, src_size);
return -1;
}
memcpy(dst, src, src_size);
return (int)src_size;
}
#if LZ4_AVAILABLE
// 使用 LZ4 解压
if (flags & MSG_FLAG_COMPRESS_LZ4) {
int decompressed_size = LZ4_decompress_safe(
(const char*)src, (char*)dst,
(int)src_size, (int)dst_capacity);
if (decompressed_size < 0) {
DEBUG_LOG("LZ4 解压失败");
return -1;
}
DEBUG_LOG("解压成功: %zu -> %d", src_size, decompressed_size);
return decompressed_size;
}
#endif
// 不支持的压缩格式或无 LZ4 库
DEBUG_LOG("不支持的压缩格式: flags=0x%x", flags);
return -1;
}
void compression_get_stats(const CompressionContext* ctx,
uint64_t* bytes_in, uint64_t* bytes_out,
uint64_t* compress_count, uint64_t* skip_count) {
if (ctx == NULL) return;
if (bytes_in) *bytes_in = ctx->bytes_in;
if (bytes_out) *bytes_out = ctx->bytes_out;
if (compress_count) *compress_count = ctx->compress_count;
if (skip_count) *skip_count = ctx->skip_count;
}
void compression_reset_stats(CompressionContext* ctx) {
if (ctx == NULL) return;
ctx->bytes_in = 0;
ctx->bytes_out = 0;
ctx->compress_count = 0;
ctx->skip_count = 0;
}
int compression_get_ratio(const CompressionContext* ctx) {
if (ctx == NULL || ctx->bytes_in == 0) {
return 100; // 无压缩
}
return (int)(ctx->bytes_out * 100 / ctx->bytes_in);
}