#pragma once #include "util/serialization.hpp" #include "util/shared_ptr.hpp" #include "util/Thread.h" #include namespace fs { class file; } // Uncompressed file serialization handler struct uncompressed_serialization_file_handler : utils::serialization_file_handler { const std::unique_ptr m_file_storage; const std::add_pointer_t m_file; explicit uncompressed_serialization_file_handler(fs::file&& file) noexcept : utils::serialization_file_handler(), m_file_storage(std::make_unique(std::move(file))), m_file(m_file_storage.get()) { } explicit uncompressed_serialization_file_handler(const fs::file& file) noexcept : utils::serialization_file_handler(), m_file_storage(nullptr), m_file(std::addressof(file)) { } uncompressed_serialization_file_handler(const uncompressed_serialization_file_handler&) = delete; uncompressed_serialization_file_handler& operator=(const uncompressed_serialization_file_handler&) = delete; // Handle file read and write requests bool handle_file_op(utils::serial& ar, usz pos, usz size, const void* data) override; // Get available memory or file size // Preferably memory size if is already greater/equal to recommended to avoid additional file ops usz get_size(const utils::serial& ar, usz recommended) const override; void finalize(utils::serial& ar) override; }; template requires(std::is_same_v, fs::file>) inline std::unique_ptr make_uncompressed_serialization_file_handler(File&& file) { ensure(file); return std::make_unique(std::forward(file)); } struct compressed_stream_data; // Compressed file serialization handler struct compressed_serialization_file_handler : utils::serialization_file_handler { explicit compressed_serialization_file_handler(fs::file&& file) noexcept : utils::serialization_file_handler(), m_file_storage(std::make_unique(std::move(file))), m_file(m_file_storage.get()) { } explicit compressed_serialization_file_handler(const fs::file& file) noexcept : utils::serialization_file_handler(), m_file_storage(nullptr), m_file(std::addressof(file)) { } compressed_serialization_file_handler(const compressed_serialization_file_handler&) = delete; compressed_serialization_file_handler& operator=(const compressed_serialization_file_handler&) = delete; // Handle file read and write requests bool handle_file_op(utils::serial& ar, usz pos, usz size, const void* data) override; // Get available memory or file size // Preferably memory size if is already greater/equal to recommended to avoid additional file ops usz get_size(const utils::serial& ar, usz recommended) const override; void skip_until(utils::serial& ar) override; bool is_valid() const override { return !m_errored; } void finalize(utils::serial& ar) override; private: const std::unique_ptr m_file_storage; const std::add_pointer_t m_file; std::vector m_stream_data; usz m_stream_data_index = 0; usz m_file_read_index = 0; atomic_t m_pending_bytes = 0; atomic_t m_pending_signal = false; bool m_write_inited = false; bool m_read_inited = false; bool m_errored = false; std::shared_ptr m_stream; std::unique_ptr>> m_stream_data_prepare_thread; std::unique_ptr>> m_file_writer_thread; usz read_at(utils::serial& ar, usz read_pos, void* data, usz size); void initialize(utils::serial& ar); void stream_data_prepare_thread_op(); void file_writer_thread_op(); void blocked_compressed_write(const std::vector& data); }; template requires(std::is_same_v, fs::file>) inline std::unique_ptr make_compressed_serialization_file_handler(File&& file) { ensure(file); return std::make_unique(std::forward(file)); } struct compressed_zstd_stream_data; // Compressed file serialization handler struct compressed_zstd_serialization_file_handler : utils::serialization_file_handler { explicit compressed_zstd_serialization_file_handler(fs::file&& file) noexcept : utils::serialization_file_handler(), m_file_storage(std::make_unique(std::move(file))), m_file(m_file_storage.get()) { } explicit compressed_zstd_serialization_file_handler(const fs::file& file) noexcept : utils::serialization_file_handler(), m_file_storage(nullptr), m_file(std::addressof(file)) { } compressed_zstd_serialization_file_handler(const compressed_zstd_serialization_file_handler&) = delete; compressed_zstd_serialization_file_handler& operator=(const compressed_zstd_serialization_file_handler&) = delete; // Handle file read and write requests bool handle_file_op(utils::serial& ar, usz pos, usz size, const void* data) override; // Get available memory or file size // Preferably memory size if is already greater/equal to recommended to avoid additional file ops usz get_size(const utils::serial& ar, usz recommended) const override; void skip_until(utils::serial& ar) override; bool is_valid() const override { return !m_errored; } void finalize(utils::serial& ar) override; private: const std::unique_ptr m_file_storage; const std::add_pointer_t m_file; std::vector m_stream_data; usz m_stream_data_index = 0; usz m_file_read_index = 0; atomic_t m_pending_bytes = 0; atomic_t m_pending_signal = false; bool m_write_inited = false; bool m_read_inited = false; atomic_t m_errored = false; usz m_input_buffer_index = 0; atomic_t m_output_buffer_index = 0; atomic_t m_thread_buffer_index = 0; struct compression_thread_context_t { atomic_ptr> m_input; atomic_ptr> m_output; bool notified = false; std::unique_ptr>> m_thread; }; std::deque m_compression_threads; std::shared_ptr m_stream; std::unique_ptr>> m_file_writer_thread; usz read_at(utils::serial& ar, usz read_pos, void* data, usz size); void initialize(utils::serial& ar); void stream_data_prepare_thread_op(); void file_writer_thread_op(); }; template requires(std::is_same_v, fs::file>) inline std::unique_ptr make_compressed_zstd_serialization_file_handler(File&& file) { ensure(file); return std::make_unique(std::forward(file)); } // Null file serialization handler struct null_serialization_file_handler : utils::serialization_file_handler { explicit null_serialization_file_handler() noexcept { } // Handle file read and write requests bool handle_file_op(utils::serial& ar, usz pos, usz size, const void* data) override; void finalize(utils::serial& ar) override; bool is_null() const override { return true; } }; inline std::unique_ptr make_null_serialization_file_handler() { return std::make_unique(); }