| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "blob-compressor.h" |
| |
| #include <zircon/status.h> |
| #include <zircon/types.h> |
| |
| #include <memory> |
| |
| #include <fbl/algorithm.h> |
| #include <fbl/auto_call.h> |
| #include <fbl/macros.h> |
| #include <fs/trace.h> |
| |
| #include "chunked.h" |
| #include "lz4.h" |
| #include "zstd-plain.h" |
| #include "zstd-seekable.h" |
| |
| namespace blobfs { |
| |
| std::optional<BlobCompressor> BlobCompressor::Create(CompressionAlgorithm algorithm, |
| size_t blob_size) { |
| switch (algorithm) { |
| case CompressionAlgorithm::LZ4: { |
| fzl::OwnedVmoMapper compressed_blob; |
| size_t max = LZ4Compressor::BufferMax(blob_size); |
| zx_status_t status = compressed_blob.CreateAndMap(max, "lz4-blob"); |
| if (status != ZX_OK) { |
| return std::nullopt; |
| } |
| std::unique_ptr<LZ4Compressor> compressor; |
| status = LZ4Compressor::Create(blob_size, compressed_blob.start(), compressed_blob.size(), |
| &compressor); |
| if (status != ZX_OK) { |
| return std::nullopt; |
| } |
| auto result = BlobCompressor(std::move(compressor), std::move(compressed_blob)); |
| return std::make_optional(std::move(result)); |
| } |
| case CompressionAlgorithm::ZSTD: { |
| fzl::OwnedVmoMapper compressed_blob; |
| size_t max = ZSTDCompressor::BufferMax(blob_size); |
| zx_status_t status = compressed_blob.CreateAndMap(max, "zstd-blob"); |
| if (status != ZX_OK) { |
| return std::nullopt; |
| } |
| std::unique_ptr<ZSTDCompressor> compressor; |
| status = ZSTDCompressor::Create(blob_size, compressed_blob.start(), compressed_blob.size(), |
| &compressor); |
| if (status != ZX_OK) { |
| return std::nullopt; |
| } |
| auto result = BlobCompressor(std::move(compressor), std::move(compressed_blob)); |
| return std::make_optional(std::move(result)); |
| } |
| case CompressionAlgorithm::ZSTD_SEEKABLE: { |
| fzl::OwnedVmoMapper compressed_blob; |
| size_t max = ZSTDSeekableCompressor::BufferMax(blob_size); |
| zx_status_t status = compressed_blob.CreateAndMap(max, "zstd-seekable-blob"); |
| if (status != ZX_OK) { |
| return std::nullopt; |
| } |
| std::unique_ptr<ZSTDSeekableCompressor> compressor; |
| status = ZSTDSeekableCompressor::Create(blob_size, compressed_blob.start(), |
| compressed_blob.size(), &compressor); |
| if (status != ZX_OK) { |
| return std::nullopt; |
| } |
| auto result = BlobCompressor(std::move(compressor), std::move(compressed_blob)); |
| return std::make_optional(std::move(result)); |
| } |
| case CompressionAlgorithm::CHUNKED: { |
| std::unique_ptr<ChunkedCompressor> compressor; |
| size_t max; |
| zx_status_t status = ChunkedCompressor::Create(blob_size, &max, &compressor); |
| if (status != ZX_OK) { |
| FS_TRACE_ERROR("[blobfs] Failed to create compressor: %s\n", zx_status_get_string(status)); |
| return std::nullopt; |
| } |
| fzl::OwnedVmoMapper compressed_blob; |
| status = compressed_blob.CreateAndMap(max, "chunk-compressed-blob"); |
| if (status != ZX_OK) { |
| FS_TRACE_ERROR("[blobfs] Failed to create mapping for compressed data: %s\n", |
| zx_status_get_string(status)); |
| return std::nullopt; |
| } |
| status = compressor->SetOutput(compressed_blob.start(), compressed_blob.size()); |
| if (status != ZX_OK) { |
| FS_TRACE_ERROR("[blobfs] Failed to initialize compressor: %s\n", |
| zx_status_get_string(status)); |
| return std::nullopt; |
| } |
| return BlobCompressor(std::move(compressor), std::move(compressed_blob)); |
| } |
| default: |
| return std::nullopt; |
| } |
| } |
| |
| BlobCompressor::BlobCompressor(std::unique_ptr<Compressor> compressor, |
| fzl::OwnedVmoMapper compressed_blob) |
| : compressor_(std::move(compressor)), compressed_blob_(std::move(compressed_blob)) {} |
| |
| BlobCompressor::~BlobCompressor() = default; |
| |
| } // namespace blobfs |