diff --git a/openVulkanoCpp/IO/Archive/ArchiveWriter.cpp b/openVulkanoCpp/IO/Archive/ArchiveWriter.cpp index 81635ea..ca34774 100644 --- a/openVulkanoCpp/IO/Archive/ArchiveWriter.cpp +++ b/openVulkanoCpp/IO/Archive/ArchiveWriter.cpp @@ -43,8 +43,8 @@ namespace openVulkanoCpp { archive_entry_clear(m_archiveEntry); std::unique_ptr 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)); diff --git a/openVulkanoCpp/IO/Archive/MultiPartArchiveWriter.cpp b/openVulkanoCpp/IO/Archive/MultiPartArchiveWriter.cpp new file mode 100644 index 0000000..dd3e7a0 --- /dev/null +++ b/openVulkanoCpp/IO/Archive/MultiPartArchiveWriter.cpp @@ -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 //TODO replace with external fmt +#include +#include + +namespace openVulkanoCpp +{ + MultiPartArchiveWriter::MultiPartArchiveWriter(const std::string& dir, const std::string& fileNamePattern, + const ArchiveConfiguration& archiveConfiguration, + size_t sizeLimit, const std::shared_ptr& 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(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>& buffers) + { + CheckSize(description.size); + return m_writer->AddFile(description, buffers); + } + + bool MultiPartArchiveWriter::AddFile(const char* fileName, const char* inArchiveName) + { + std::unique_ptr archiveEntry(archive_entry_new(), archive_entry_free); + std::unique_ptr 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 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(); + } +} diff --git a/openVulkanoCpp/IO/Archive/MultiPartArchiveWriter.hpp b/openVulkanoCpp/IO/Archive/MultiPartArchiveWriter.hpp new file mode 100644 index 0000000..87291d7 --- /dev/null +++ b/openVulkanoCpp/IO/Archive/MultiPartArchiveWriter.hpp @@ -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 + +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 m_writer; + std::shared_ptr m_logger; + std::vector 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& logger = nullptr); + + ~MultiPartArchiveWriter() override; + + bool AddFile(const FileDescription& description, const void* buffer) override; + bool AddFile(const FileDescription& description, const std::vector>& buffers) override; + bool AddFile(const char* fileName, const char* inArchiveName) override; + using IArchiveWriter::AddFile; + + void SetLogger(const std::shared_ptr& logger) { m_logger = logger; } + [[nodiscard]] std::shared_ptr 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); + }; +}