92 lines
3.1 KiB
C++
92 lines
3.1 KiB
C++
/*
|
|
* 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++));
|
|
#ifdef WIN32
|
|
m_writer = std::make_unique<ArchiveWriter>(m_archives.back().string().c_str(), m_archiveConfig, m_logger);
|
|
#else
|
|
m_writer = std::make_unique<ArchiveWriter>(m_archives.back().c_str(), m_archiveConfig, m_logger);
|
|
#endif
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|