src/native/io/compressed/bspatch_decompression_reader.cpp (68 lines of code) (raw):
/**
* @file bspatch_decompression_reader.cpp
*
* @copyright Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*/
#include <bsdiff.h>
#include "bspatch_decompression_reader.h"
#include "bsdiff_stream_wrappers.h"
#include "adu_log.h"
namespace archive_diff::io::compressed
{
bspatch_decompression_reader::bspatch_decompression_reader(
io::reader &diff_reader, uint64_t uncompressed_size, io::reader &dictionary_reader) :
m_diff_reader(diff_reader), m_dictionary_reader(dictionary_reader),
m_channel(std::make_shared<writer_to_reader_channel>(uncompressed_size)), m_channel_as_writer(m_channel)
{
m_channel_thread =
std::thread(apply_patch_worker, &m_dictionary_reader, &m_channel_as_writer, &m_diff_reader, this);
}
bspatch_decompression_reader::~bspatch_decompression_reader()
{
m_channel->cancel();
m_channel_thread.join();
}
void bspatch_decompression_reader::apply_patch_worker(
io::reader *old_reader,
std::shared_ptr<io::sequential::writer> *new_writer,
io::reader *diff_reader,
[[maybe_unused]] bspatch_decompression_reader *self)
{
try
{
apply_patch(old_reader, new_writer, diff_reader);
}
catch (const std::exception &e)
{
auto msg = e.what();
if (msg == nullptr)
{
msg = "Unknown error";
}
ADU_LOG("bspatch_decompression_reader::apply_patch_worker(): std::exception: {}", msg);
}
catch (const errors::user_exception &e)
{
ADU_LOG(
"bspatch_decompression_reader::apply_patch_worker(): user_exception ({}): {}",
static_cast<uint32_t>(e.get_error()),
e.get_message());
}
}
void bspatch_decompression_reader::apply_patch(
io::reader *old_reader, std::shared_ptr<io::sequential::writer> *new_writer, io::reader *diff_reader)
{
bsdiff_ctx ctx{0};
auto_bsdiff_stream old_stream(create_reader_based_bsdiff_stream(*old_reader));
auto_bsdiff_stream new_stream = create_sequential_writer_based_bsdiff_stream(*new_writer);
auto_bsdiff_stream diff_stream = create_reader_based_bsdiff_stream(*diff_reader);
bsdiff_patch_packer diff_packer;
int ret = bsdiff_open_bz2_patch_packer(BSDIFF_MODE_READ, &diff_stream, &diff_packer);
if (ret != BSDIFF_SUCCESS)
{
std::string msg = "bsdiff_open_bz2_patch_packer failed. ret: " + std::to_string(ret);
throw errors::user_exception(errors::error_code::diff_bspatch_failure, msg);
}
ret = bspatch(&ctx, &old_stream, &new_stream, &diff_packer);
if (ret != BSDIFF_SUCCESS)
{
std::string msg = "bspatch failed. ret: " + std::to_string(ret);
throw errors::user_exception(errors::error_code::diff_bspatch_failure, msg);
}
}
} // namespace archive_diff::io::compressed