Add MultiPartArchiveWriter

This commit is contained in:
2021-03-03 20:48:08 +01:00
parent 468ca9487b
commit 3787249d34
3 changed files with 136 additions and 2 deletions

View File

@@ -43,8 +43,8 @@ namespace openVulkanoCpp
{
archive_entry_clear(m_archiveEntry);
std::unique_ptr<archive, decltype(archive_free)*> archiveDisk(archive_read_disk_new(), archive_free);
ChkErr(archive_read_disk_open(archiveDisk.get(), fileName));
ChkErr(archive_read_next_header2(archiveDisk.get(), m_archiveEntry));
LibArchiveHelper::CheckError(archive_read_disk_open(archiveDisk.get(), fileName), archiveDisk.get(), m_logger);
LibArchiveHelper::CheckError(archive_read_next_header2(archiveDisk.get(), m_archiveEntry), archiveDisk.get(), m_logger);
//archive_read_disk_entry_from_file(archiveDisk, m_archiveEntry, -1, nullptr);
archive_entry_set_pathname(m_archiveEntry, inArchiveName);
ChkErr(archive_write_header(m_archive, m_archiveEntry));

View File

@@ -0,0 +1,87 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include "MultiPartArchiveWriter.hpp"
#include "LibArchiveHelper.hpp"
#include <spdlog/fmt/fmt.h> //TODO replace with external fmt
#include <archive.h>
#include <archive_entry.h>
namespace openVulkanoCpp
{
MultiPartArchiveWriter::MultiPartArchiveWriter(const std::string& dir, const std::string& fileNamePattern,
const ArchiveConfiguration& archiveConfiguration,
size_t sizeLimit, const std::shared_ptr<spdlog::logger>& logger)
: m_fileSizeLimit(sizeLimit), m_archiveId(0), m_archiveConfig(archiveConfiguration)
, m_dir(dir), m_fileNamePattern(fileNamePattern), m_logger(logger)
{
StartNewFile();
}
MultiPartArchiveWriter::~MultiPartArchiveWriter() = default;
void MultiPartArchiveWriter::StartNewFile()
{
m_archives.push_back(m_dir / fmt::format(m_fileNamePattern, m_archiveId++));
m_writer = std::make_unique<ArchiveWriter>(m_archives.back().c_str(), m_archiveConfig, m_logger);
}
void MultiPartArchiveWriter::CheckSize(size_t size)
{
if (m_fileSizeLimit < m_writer->GetTotalWrittenBytes() + size)
{
StartNewFile();
}
}
bool MultiPartArchiveWriter::AddFile(const FileDescription& description, const void* buffer)
{
CheckSize(description.size);
return m_writer->AddFile(description, buffer);
}
bool MultiPartArchiveWriter::AddFile(const FileDescription& description, const std::vector<std::pair<const void*, size_t>>& buffers)
{
CheckSize(description.size);
return m_writer->AddFile(description, buffers);
}
bool MultiPartArchiveWriter::AddFile(const char* fileName, const char* inArchiveName)
{
std::unique_ptr<archive_entry, decltype(archive_entry_free)*> archiveEntry(archive_entry_new(), archive_entry_free);
std::unique_ptr<archive, decltype(archive_free)*> archiveDisk(archive_read_disk_new(), archive_free);
LibArchiveHelper::CheckError(archive_read_disk_open(archiveDisk.get(), fileName), archiveDisk.get(), m_logger);
LibArchiveHelper::CheckError(archive_read_next_header2(archiveDisk.get(), archiveEntry.get()), archiveDisk.get(), m_logger);
CheckSize(archive_entry_size(archiveEntry.get()));
return m_writer->AddFile(fileName, inArchiveName);
}
void MultiPartArchiveWriter::Move(const std::filesystem::path& newDir)
{
bool hasToMove = m_archives.size() > 1 || m_writer->GetTotalWrittenBytes() > 0;
m_writer = nullptr; // Close current archive
if (hasToMove)
{ // Move all existing archives
std::vector<std::filesystem::path> newArchivePaths;
newArchivePaths.reserve(m_archives.size() + 1);
for (const auto& file : m_archives)
{
newArchivePaths.push_back(newDir / file.filename());
std::filesystem::rename(file, newArchivePaths.back());
}
m_archives = std::move(newArchivePaths);
}
else
{
m_archiveId = 0;
std::filesystem::remove(m_archives.back());
m_archives.clear();
}
m_dir = newDir;
StartNewFile();
}
}

View File

@@ -0,0 +1,47 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "ArchiveWriter.hpp"
#include <memory>
namespace openVulkanoCpp
{
class MultiPartArchiveWriter final : public IArchiveWriter
{
size_t m_fileSizeLimit;
uint32_t m_archiveId;
ArchiveConfiguration m_archiveConfig;
std::filesystem::path m_dir;
std::string m_fileNamePattern;
std::unique_ptr<ArchiveWriter> m_writer;
std::shared_ptr<spdlog::logger> m_logger;
std::vector<std::filesystem::path> m_archives;
void StartNewFile();
void CheckSize(size_t size);
public:
MultiPartArchiveWriter(const std::string& dir, const std::string& fileNamePattern, const ArchiveConfiguration& archiveConfiguration, size_t sizeLimit = 2ull << 30, const std::shared_ptr<spdlog::logger>& logger = nullptr);
~MultiPartArchiveWriter() override;
bool AddFile(const FileDescription& description, const void* buffer) override;
bool AddFile(const FileDescription& description, const std::vector<std::pair<const void*, size_t>>& buffers) override;
bool AddFile(const char* fileName, const char* inArchiveName) override;
using IArchiveWriter::AddFile;
void SetLogger(const std::shared_ptr<spdlog::logger>& logger) { m_logger = logger; }
[[nodiscard]] std::shared_ptr<spdlog::logger> GetLogger() const { return m_logger; }
void SetMaxArchiveFileSize(size_t sizeLimit) { m_fileSizeLimit = sizeLimit; }
[[nodiscard]] size_t GetMaxArchiveFileSize() const { return m_fileSizeLimit; }
void Move(const std::filesystem::path& newDir);
};
}