Package Kit & packagefs: Allocate scratch buffers for decompression further up.

Zstd wants a ~90 KB scratch buffer to decompress our 64 KB chunks.
Rather than let it allocate that itself every time, pass in a 2*64KB
"scratch" buffer and statically allocate the working memory from it.
Pass it down using iovecs, and pass down the other buffers in the same
way, to reduce parameters.

Further, rework the object_cache used for heap decompression buffers
to contain objects sized as 4x64KB, so we only need to do one allocation
and deallocation for the compression/decompression and scratch buffers.
Set the minimum reserve to 1 so that the low-memory manager doesn't
reclaim this, as we'll need it when reading back data.

Improves packagefs I/O performance (and thus boot speeds at least a bit,
it appears.)

Change-Id: Id51f6f598b33b9d757a283184c533bb97049529f
Reviewed-on: https://review.haiku-os.org/c/haiku/+/8717
Reviewed-by: waddlesplash <[email protected]>
Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
Augustin Cavalier
2024-12-30 19:04:10 +00:00
committed by waddlesplash
parent 7651b97c0a
commit f44cb411cc
15 changed files with 128 additions and 127 deletions
@@ -99,23 +99,23 @@ public:
public: public:
static const size_t kChunkSize = 64 * 1024; static const size_t kChunkSize = 64 * 1024;
#if defined(_KERNEL_MODE) #if defined(_KERNEL_MODE)
static void* sChunkCache; static void* sQuadChunkCache;
#endif #endif
protected: protected:
virtual status_t ReadAndDecompressChunk(size_t chunkIndex, virtual status_t ReadAndDecompressChunk(size_t chunkIndex,
void* compressedDataBuffer, void* compressedDataBuffer,
void* uncompressedDataBuffer) = 0; void* uncompressedDataBuffer,
iovec* scratchBuffer = NULL) = 0;
status_t ReadAndDecompressChunkData(uint64 offset, status_t ReadAndDecompressChunkData(uint64 offset,
size_t compressedSize, size_t compressedSize,
size_t uncompressedSize, size_t uncompressedSize,
void* compressedDataBuffer, void* compressedDataBuffer,
void* uncompressedDataBuffer);
status_t DecompressChunkData(
void* compressedDataBuffer,
size_t compressedSize,
void* uncompressedDataBuffer, void* uncompressedDataBuffer,
size_t uncompressedSize); iovec* scratchBuffer = NULL);
status_t DecompressChunkData(const iovec& compressedBuffer,
iovec& uncompressedBuffer,
iovec* scratchBuffer = NULL);
status_t ReadFileData(uint64 offset, void* buffer, status_t ReadFileData(uint64 offset, void* buffer,
size_t size); size_t size);
@@ -42,7 +42,8 @@ public:
protected: protected:
virtual status_t ReadAndDecompressChunk(size_t chunkIndex, virtual status_t ReadAndDecompressChunk(size_t chunkIndex,
void* compressedDataBuffer, void* compressedDataBuffer,
void* uncompressedDataBuffer); void* uncompressedDataBuffer,
iovec* scratchBuffer = NULL);
private: private:
OffsetArray fOffsets; OffsetArray fOffsets;
@@ -57,7 +57,8 @@ public:
protected: protected:
virtual status_t ReadAndDecompressChunk(size_t chunkIndex, virtual status_t ReadAndDecompressChunk(size_t chunkIndex,
void* compressedDataBuffer, void* compressedDataBuffer,
void* uncompressedDataBuffer); void* uncompressedDataBuffer,
iovec* scratchBuffer = NULL);
private: private:
struct Chunk; struct Chunk;
+7 -11
View File
@@ -7,6 +7,7 @@
#include <DataIO.h> #include <DataIO.h>
#include <sys/uio.h>
class BCompressionParameters { class BCompressionParameters {
@@ -41,17 +42,12 @@ public:
const BDecompressionParameters* parameters, const BDecompressionParameters* parameters,
BDataIO*& _stream); BDataIO*& _stream);
virtual status_t CompressBuffer(const void* input, virtual status_t CompressBuffer(const iovec& input, iovec& output,
size_t inputSize, void* output, const BCompressionParameters* parameters = NULL,
size_t outputSize, size_t& _compressedSize, iovec* scratch = NULL);
const BCompressionParameters* parameters virtual status_t DecompressBuffer(const iovec& input, iovec& output,
= NULL); const BDecompressionParameters* parameters = NULL,
virtual status_t DecompressBuffer(const void* input, iovec* scratch = NULL);
size_t inputSize, void* output,
size_t outputSize,
size_t& _uncompressedSize,
const BDecompressionParameters* parameters
= NULL);
protected: protected:
class BAbstractStream; class BAbstractStream;
@@ -73,17 +73,12 @@ public:
const BDecompressionParameters* parameters, const BDecompressionParameters* parameters,
BDataIO*& _stream); BDataIO*& _stream);
virtual status_t CompressBuffer(const void* input, virtual status_t CompressBuffer(const iovec& input, iovec& output,
size_t inputSize, void* output, const BCompressionParameters* parameters = NULL,
size_t outputSize, size_t& _compressedSize, iovec* scratch = NULL);
const BCompressionParameters* parameters virtual status_t DecompressBuffer(const iovec& input, iovec& output,
= NULL); const BDecompressionParameters* parameters = NULL,
virtual status_t DecompressBuffer(const void* input, iovec* scratch = NULL);
size_t inputSize, void* output,
size_t outputSize,
size_t& _uncompressedSize,
const BDecompressionParameters* parameters
= NULL);
private: private:
struct CompressionStrategy; struct CompressionStrategy;
@@ -69,17 +69,12 @@ public:
const BDecompressionParameters* parameters, const BDecompressionParameters* parameters,
BDataIO*& _stream); BDataIO*& _stream);
virtual status_t CompressBuffer(const void* input, virtual status_t CompressBuffer(const iovec& input, iovec& output,
size_t inputSize, void* output, const BCompressionParameters* parameters = NULL,
size_t outputSize, size_t& _compressedSize, iovec* scratch = NULL);
const BCompressionParameters* parameters virtual status_t DecompressBuffer(const iovec& input, iovec& output,
= NULL); const BDecompressionParameters* parameters = NULL,
virtual status_t DecompressBuffer(const void* input, iovec* scratch = NULL);
size_t inputSize, void* output,
size_t outputSize,
size_t& _uncompressedSize,
const BDecompressionParameters* parameters
= NULL);
private: private:
struct CompressionStrategy; struct CompressionStrategy;
@@ -12,7 +12,7 @@ if [ FIsBuildFeatureEnabled zstd ] {
UseBuildFeatureHeaders zstd ; UseBuildFeatureHeaders zstd ;
Includes [ FGristFiles $(zstdSources) ] Includes [ FGristFiles $(zstdSources) ]
: [ BuildFeatureAttribute zstd : headers ] ; : [ BuildFeatureAttribute zstd : headers ] ;
SubDirC++Flags -DZSTD_ENABLED ; SubDirC++Flags -DZSTD_ENABLED -DZSTD_STATIC_LINKING_ONLY ;
} }
local subDirs = local subDirs =
@@ -1144,11 +1144,13 @@ packagefs_std_ops(int32 op, ...)
return error; return error;
} }
PackageFileHeapAccessorBase::sChunkCache = object_cache* quadChunkCache;
create_object_cache_etc("pkgfs heap buffers", PackageFileHeapAccessorBase::sQuadChunkCache = quadChunkCache =
PackageFileHeapAccessorBase::kChunkSize, sizeof(void*), create_object_cache("pkgfs heap buffers",
0, /* magazine capacity, count */ 2, 1, PackageFileHeapAccessorBase::kChunkSize * 4,
0, NULL, NULL, NULL, NULL); 0, NULL, NULL, NULL);
object_cache_set_minimum_reserve(quadChunkCache, 1);
TwoKeyAVLTreeNode<void*>::sNodeCache = TwoKeyAVLTreeNode<void*>::sNodeCache =
create_object_cache_etc("pkgfs TKAVLTreeNodes", create_object_cache_etc("pkgfs TKAVLTreeNodes",
sizeof(TwoKeyAVLTreeNode<void*>), 8, sizeof(TwoKeyAVLTreeNode<void*>), 8,
@@ -1172,7 +1174,7 @@ packagefs_std_ops(int32 op, ...)
PackageFSRoot::GlobalUninit(); PackageFSRoot::GlobalUninit();
delete_object_cache(TwoKeyAVLTreeNode<void*>::sNodeCache); delete_object_cache(TwoKeyAVLTreeNode<void*>::sNodeCache);
delete_object_cache((object_cache*) delete_object_cache((object_cache*)
PackageFileHeapAccessorBase::sChunkCache); PackageFileHeapAccessorBase::sQuadChunkCache);
StringConstants::Cleanup(); StringConstants::Cleanup();
StringPool::Cleanup(); StringPool::Cleanup();
exit_debugging(); exit_debugging();
@@ -31,7 +31,7 @@ namespace BPrivate {
#if defined(_KERNEL_MODE) #if defined(_KERNEL_MODE)
void* PackageFileHeapAccessorBase::sChunkCache = NULL; void* PackageFileHeapAccessorBase::sQuadChunkCache = NULL;
#endif #endif
@@ -218,7 +218,7 @@ PackageFileHeapAccessorBase::ReadDataToOutput(off_t offset, size_t size,
// allocate buffers for compressed and uncompressed data // allocate buffers for compressed and uncompressed data
uint16* compressedDataBuffer, *uncompressedDataBuffer; uint16* compressedDataBuffer, *uncompressedDataBuffer;
MemoryDeleter compressedMemoryDeleter, uncompressedMemoryDeleter; iovec* scratch = NULL;
#if defined(_KERNEL_MODE) && !defined(_BOOT_MODE) #if defined(_KERNEL_MODE) && !defined(_BOOT_MODE)
struct ObjectCacheDeleter { struct ObjectCacheDeleter {
@@ -238,21 +238,24 @@ PackageFileHeapAccessorBase::ReadDataToOutput(off_t offset, size_t size,
} }
}; };
ObjectCacheDeleter compressedCacheDeleter((object_cache*)sChunkCache), ObjectCacheDeleter chunkBufferDeleter((object_cache*)sQuadChunkCache);
uncompressedCacheDeleter((object_cache*)sChunkCache); uint8* quadChunkBuffer = (uint8*)object_cache_alloc((object_cache*)sQuadChunkCache, 0);
if (sChunkCache != NULL) { chunkBufferDeleter.object = quadChunkBuffer;
compressedDataBuffer = (uint16*)object_cache_alloc((object_cache*)sChunkCache, 0);
uncompressedDataBuffer = (uint16*)object_cache_alloc((object_cache*)sChunkCache, 0); // segment data buffer
compressedCacheDeleter.object = compressedDataBuffer; iovec localScratch;
uncompressedCacheDeleter.object = uncompressedDataBuffer; compressedDataBuffer = (uint16*)(quadChunkBuffer + 0);
} else uncompressedDataBuffer = (uint16*)(quadChunkBuffer + kChunkSize);
localScratch.iov_base = (quadChunkBuffer + (kChunkSize * 2));
localScratch.iov_len = kChunkSize * 2;
scratch = &localScratch;
#else
MemoryDeleter compressedMemoryDeleter, uncompressedMemoryDeleter;
compressedDataBuffer = (uint16*)malloc(kChunkSize);
uncompressedDataBuffer = (uint16*)malloc(kChunkSize);
compressedMemoryDeleter.SetTo(compressedDataBuffer);
uncompressedMemoryDeleter.SetTo(uncompressedDataBuffer);
#endif #endif
{
compressedDataBuffer = (uint16*)malloc(kChunkSize);
uncompressedDataBuffer = (uint16*)malloc(kChunkSize);
compressedMemoryDeleter.SetTo(compressedDataBuffer);
uncompressedMemoryDeleter.SetTo(uncompressedDataBuffer);
}
if (compressedDataBuffer == NULL || uncompressedDataBuffer == NULL) if (compressedDataBuffer == NULL || uncompressedDataBuffer == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -264,7 +267,7 @@ PackageFileHeapAccessorBase::ReadDataToOutput(off_t offset, size_t size,
while (remainingBytes > 0) { while (remainingBytes > 0) {
status_t error = ReadAndDecompressChunk(chunkIndex, status_t error = ReadAndDecompressChunk(chunkIndex,
compressedDataBuffer, uncompressedDataBuffer); compressedDataBuffer, uncompressedDataBuffer, scratch);
if (error != B_OK) if (error != B_OK)
return error; return error;
@@ -289,8 +292,9 @@ PackageFileHeapAccessorBase::ReadDataToOutput(off_t offset, size_t size,
status_t status_t
PackageFileHeapAccessorBase::ReadAndDecompressChunkData(uint64 offset, PackageFileHeapAccessorBase::ReadAndDecompressChunkData(uint64 offset,
size_t compressedSize, size_t uncompressedSize, void* compressedDataBuffer, size_t compressedSize, size_t uncompressedSize,
void* uncompressedDataBuffer) void* compressedDataBuffer, void* uncompressedDataBuffer,
iovec* scratchBuffer)
{ {
// if uncompressed, read directly into the uncompressed data buffer // if uncompressed, read directly into the uncompressed data buffer
if (compressedSize == uncompressedSize) if (compressedSize == uncompressedSize)
@@ -301,27 +305,26 @@ PackageFileHeapAccessorBase::ReadAndDecompressChunkData(uint64 offset,
if (error != B_OK) if (error != B_OK)
return error; return error;
return DecompressChunkData(compressedDataBuffer, compressedSize, iovec compressed = { compressedDataBuffer, compressedSize },
uncompressedDataBuffer, uncompressedSize); uncompressed = { uncompressedDataBuffer, uncompressedSize };
return DecompressChunkData(compressed, uncompressed, scratchBuffer);
} }
status_t status_t
PackageFileHeapAccessorBase::DecompressChunkData(void* compressedDataBuffer, PackageFileHeapAccessorBase::DecompressChunkData(const iovec& compressed,
size_t compressedSize, void* uncompressedDataBuffer, iovec& uncompressed, iovec* scratchBuffer)
size_t uncompressedSize)
{ {
size_t actualSize; const size_t uncompressedSize = uncompressed.iov_len;
status_t error = fDecompressionAlgorithm->algorithm->DecompressBuffer( status_t error = fDecompressionAlgorithm->algorithm->DecompressBuffer(
compressedDataBuffer, compressedSize, uncompressedDataBuffer, compressed, uncompressed, fDecompressionAlgorithm->parameters, scratchBuffer);
uncompressedSize, actualSize, fDecompressionAlgorithm->parameters);
if (error != B_OK) { if (error != B_OK) {
fErrorOutput->PrintError("Failed to decompress chunk data: %s\n", fErrorOutput->PrintError("Failed to decompress chunk data: %s\n",
strerror(error)); strerror(error));
return error; return error;
} }
if (actualSize != uncompressedSize) { if (uncompressed.iov_len != uncompressedSize) {
fErrorOutput->PrintError("Failed to decompress chunk data: size " fErrorOutput->PrintError("Failed to decompress chunk data: size "
"mismatch\n"); "mismatch\n");
return B_ERROR; return B_ERROR;
@@ -153,7 +153,8 @@ PackageFileHeapReader::Clone() const
status_t status_t
PackageFileHeapReader::ReadAndDecompressChunk(size_t chunkIndex, PackageFileHeapReader::ReadAndDecompressChunk(size_t chunkIndex,
void* compressedDataBuffer, void* uncompressedDataBuffer) void* compressedDataBuffer, void* uncompressedDataBuffer,
iovec* scratchBuffer)
{ {
uint64 offset = fOffsets[chunkIndex]; uint64 offset = fOffsets[chunkIndex];
bool isLastChunk bool isLastChunk
@@ -166,7 +167,7 @@ PackageFileHeapReader::ReadAndDecompressChunk(size_t chunkIndex,
: kChunkSize; : kChunkSize;
return ReadAndDecompressChunkData(offset, compressedSize, uncompressedSize, return ReadAndDecompressChunkData(offset, compressedSize, uncompressedSize,
compressedDataBuffer, uncompressedDataBuffer); compressedDataBuffer, uncompressedDataBuffer, scratchBuffer);
} }
+12 -10
View File
@@ -409,9 +409,9 @@ PackageFileHeapWriter::RemoveDataRanges(
} else if (decompressedChunk == &chunk) { } else if (decompressedChunk == &chunk) {
uncompressedData = decompressionBuffer; uncompressedData = decompressionBuffer;
} else { } else {
status_t error = DecompressChunkData(chunk.buffer, iovec compressed = { chunk.buffer, chunk.compressedSize },
chunk.compressedSize, decompressionBuffer, uncompressed = { decompressionBuffer, chunk.uncompressedSize };
chunk.uncompressedSize); status_t error = DecompressChunkData(compressed, uncompressed);
if (error != B_OK) if (error != B_OK)
throw error; throw error;
@@ -479,7 +479,8 @@ PackageFileHeapWriter::Finish()
status_t status_t
PackageFileHeapWriter::ReadAndDecompressChunk(size_t chunkIndex, PackageFileHeapWriter::ReadAndDecompressChunk(size_t chunkIndex,
void* compressedDataBuffer, void* uncompressedDataBuffer) void* compressedDataBuffer, void* uncompressedDataBuffer,
iovec* scratchBuffer)
{ {
if (uint64(chunkIndex + 1) * kChunkSize > fUncompressedHeapSize) { if (uint64(chunkIndex + 1) * kChunkSize > fUncompressedHeapSize) {
// The chunk has not been written to disk yet. Its data are still in the // The chunk has not been written to disk yet. Its data are still in the
@@ -496,7 +497,7 @@ PackageFileHeapWriter::ReadAndDecompressChunk(size_t chunkIndex,
: fOffsets[chunkIndex + 1] - offset; : fOffsets[chunkIndex + 1] - offset;
return ReadAndDecompressChunkData(offset, compressedSize, kChunkSize, return ReadAndDecompressChunkData(offset, compressedSize, kChunkSize,
compressedDataBuffer, uncompressedDataBuffer); compressedDataBuffer, uncompressedDataBuffer, scratchBuffer);
} }
@@ -562,9 +563,10 @@ PackageFileHeapWriter::_WriteDataCompressed(const void* data, size_t size)
if (fCompressionAlgorithm == NULL) if (fCompressionAlgorithm == NULL)
return B_BUFFER_OVERFLOW; return B_BUFFER_OVERFLOW;
size_t compressedSize; const iovec uncompressed = { (void*)data, size };
status_t error = fCompressionAlgorithm->algorithm->CompressBuffer(data, iovec compressed = { fCompressedDataBuffer, size };
size, fCompressedDataBuffer, size, compressedSize, status_t error = fCompressionAlgorithm->algorithm->CompressBuffer(
uncompressed, compressed,
fCompressionAlgorithm->parameters); fCompressionAlgorithm->parameters);
if (error != B_OK) { if (error != B_OK) {
if (error != B_BUFFER_OVERFLOW) { if (error != B_BUFFER_OVERFLOW) {
@@ -575,10 +577,10 @@ PackageFileHeapWriter::_WriteDataCompressed(const void* data, size_t size)
} }
// only use compressed data when we've actually saved space // only use compressed data when we've actually saved space
if (compressedSize == size) if (compressed.iov_len == size)
return B_BUFFER_OVERFLOW; return B_BUFFER_OVERFLOW;
return _WriteDataUncompressed(fCompressedDataBuffer, compressedSize); return _WriteDataUncompressed(fCompressedDataBuffer, compressed.iov_len);
} }
@@ -293,12 +293,11 @@ private:
if (error != B_OK) if (error != B_OK)
return error; return error;
size_t actuallyUncompressedSize; iovec compressed = { readBuffer->Buffer(), compressedSize },
BZlibCompressionAlgorithm().DecompressBuffer( uncompressed = { fUncompressBuffer->Buffer(), uncompressedSize };
readBuffer->Buffer(), compressedSize, error = BZlibCompressionAlgorithm().DecompressBuffer(
fUncompressBuffer->Buffer(), uncompressedSize, compressed, uncompressed);
actuallyUncompressedSize); if (error == B_OK && uncompressed.iov_len != uncompressedSize)
if (error == B_OK && actuallyUncompressedSize != uncompressedSize)
error = B_BAD_DATA; error = B_BAD_DATA;
} }
+4 -6
View File
@@ -84,18 +84,16 @@ BCompressionAlgorithm::CreateDecompressingOutputStream(BDataIO* output,
status_t status_t
BCompressionAlgorithm::CompressBuffer(const void* input, size_t inputSize, BCompressionAlgorithm::CompressBuffer(const iovec& input, iovec& output,
void* output, size_t outputSize, size_t& _compressedSize, const BCompressionParameters* parameters, iovec* scratch)
const BCompressionParameters* parameters)
{ {
return B_NOT_SUPPORTED; return B_NOT_SUPPORTED;
} }
status_t status_t
BCompressionAlgorithm::DecompressBuffer(const void* input, BCompressionAlgorithm::DecompressBuffer(const iovec& input, iovec& output,
size_t inputSize, void* output, size_t outputSize, const BDecompressionParameters* parameters, iovec* scratch)
size_t& _uncompressedSize, const BDecompressionParameters* parameters)
{ {
return B_NOT_SUPPORTED; return B_NOT_SUPPORTED;
} }
+12 -14
View File
@@ -366,9 +366,8 @@ BZlibCompressionAlgorithm::CreateDecompressingOutputStream(BDataIO* output,
status_t status_t
BZlibCompressionAlgorithm::CompressBuffer(const void* input, BZlibCompressionAlgorithm::CompressBuffer(const iovec& input, iovec& output,
size_t inputSize, void* output, size_t outputSize, size_t& _compressedSize, const BCompressionParameters* parameters, iovec* scratch)
const BCompressionParameters* parameters)
{ {
#ifdef B_ZLIB_COMPRESSION_SUPPORT #ifdef B_ZLIB_COMPRESSION_SUPPORT
const BZlibCompressionParameters* zlibParameters const BZlibCompressionParameters* zlibParameters
@@ -377,13 +376,13 @@ BZlibCompressionAlgorithm::CompressBuffer(const void* input,
? zlibParameters->CompressionLevel() ? zlibParameters->CompressionLevel()
: B_ZLIB_COMPRESSION_DEFAULT; : B_ZLIB_COMPRESSION_DEFAULT;
uLongf bytesUsed = outputSize; uLongf bytesUsed = output.iov_len;
int zlibError = compress2((Bytef*)output, &bytesUsed, (const Bytef*)input, int zlibError = compress2((Bytef*)output.iov_base, &bytesUsed,
(uLong)inputSize, compressionLevel); (const Bytef*)input.iov_base, (uLong)input.iov_len, compressionLevel);
if (zlibError != Z_OK) if (zlibError != Z_OK)
return _TranslateZlibError(zlibError); return _TranslateZlibError(zlibError);
_compressedSize = (size_t)bytesUsed; output.iov_len = (size_t)bytesUsed;
return B_OK; return B_OK;
#else #else
return B_NOT_SUPPORTED; return B_NOT_SUPPORTED;
@@ -392,17 +391,16 @@ BZlibCompressionAlgorithm::CompressBuffer(const void* input,
status_t status_t
BZlibCompressionAlgorithm::DecompressBuffer(const void* input, BZlibCompressionAlgorithm::DecompressBuffer(const iovec& input, iovec& output,
size_t inputSize, void* output, size_t outputSize, const BDecompressionParameters* parameters, iovec* scratch)
size_t& _uncompressedSize, const BDecompressionParameters* parameters)
{ {
uLongf bytesUsed = outputSize; uLongf bytesUsed = output.iov_len;
int zlibError = uncompress((Bytef*)output, &bytesUsed, (const Bytef*)input, int zlibError = uncompress((Bytef*)output.iov_base, &bytesUsed,
(uLong)inputSize); (const Bytef*)input.iov_base, (uLong)input.iov_len);
if (zlibError != Z_OK) if (zlibError != Z_OK)
return _TranslateZlibError(zlibError); return _TranslateZlibError(zlibError);
_uncompressedSize = (size_t)bytesUsed; output.iov_len = (size_t)bytesUsed;
return B_OK; return B_OK;
} }
+22 -12
View File
@@ -18,6 +18,7 @@
#include <zstd_errors.h> #include <zstd_errors.h>
#endif #endif
#include <AutoDeleter.h>
#include <DataIO.h> #include <DataIO.h>
@@ -367,23 +368,23 @@ BZstdCompressionAlgorithm::CreateDecompressingOutputStream(BDataIO* output,
status_t status_t
BZstdCompressionAlgorithm::CompressBuffer(const void* input, BZstdCompressionAlgorithm::CompressBuffer(const iovec& input, iovec& output,
size_t inputSize, void* output, size_t outputSize, size_t& _compressedSize, const BCompressionParameters* parameters, iovec* scratch)
const BCompressionParameters* parameters)
{ {
#ifdef B_ZSTD_COMPRESSION_SUPPORT #ifdef B_ZSTD_COMPRESSION_SUPPORT
// TODO: Make use of scratch buffer (if available.)
const BZstdCompressionParameters* zstdParameters const BZstdCompressionParameters* zstdParameters
= dynamic_cast<const BZstdCompressionParameters*>(parameters); = dynamic_cast<const BZstdCompressionParameters*>(parameters);
int compressionLevel = zstdParameters != NULL int compressionLevel = zstdParameters != NULL
? zstdParameters->CompressionLevel() ? zstdParameters->CompressionLevel()
: B_ZSTD_COMPRESSION_DEFAULT; : B_ZSTD_COMPRESSION_DEFAULT;
size_t zstdError = ZSTD_compress(output, outputSize, input, size_t zstdError = ZSTD_compress(output.iov_base, output.iov_len,
inputSize, compressionLevel); input.iov_base, input.iov_len, compressionLevel);
if (ZSTD_isError(zstdError)) if (ZSTD_isError(zstdError))
return _TranslateZstdError(zstdError); return _TranslateZstdError(zstdError);
_compressedSize = zstdError; output.iov_len = zstdError;
return B_OK; return B_OK;
#else #else
return B_NOT_SUPPORTED; return B_NOT_SUPPORTED;
@@ -392,17 +393,26 @@ BZstdCompressionAlgorithm::CompressBuffer(const void* input,
status_t status_t
BZstdCompressionAlgorithm::DecompressBuffer(const void* input, BZstdCompressionAlgorithm::DecompressBuffer(const iovec& input, iovec& output,
size_t inputSize, void* output, size_t outputSize, const BDecompressionParameters* parameters, iovec* scratch)
size_t& _uncompressedSize, const BDecompressionParameters* parameters)
{ {
#ifdef ZSTD_ENABLED #ifdef ZSTD_ENABLED
size_t zstdError = ZSTD_decompress(output, outputSize, input, ZSTD_DCtx* dctx;
inputSize); CObjectDeleter<ZSTD_DCtx, size_t, ZSTD_freeDCtx> dctxDeleter;
#if defined(ZSTD_STATIC_LINKING_ONLY)
if (scratch != NULL)
dctx = ZSTD_initStaticDCtx(scratch->iov_base, scratch->iov_len);
else
#endif
dctxDeleter.SetTo(dctx = ZSTD_createDCtx());
size_t zstdError = ZSTD_decompressDCtx(dctx,
output.iov_base, output.iov_len,
input.iov_base, input.iov_len);
if (ZSTD_isError(zstdError)) if (ZSTD_isError(zstdError))
return _TranslateZstdError(zstdError); return _TranslateZstdError(zstdError);
_uncompressedSize = zstdError; output.iov_len = zstdError;
return B_OK; return B_OK;
#else #else
return B_NOT_SUPPORTED; return B_NOT_SUPPORTED;