From e848076dfa6a98e135dba5fbdf12ec2e96fb7d88 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Wed, 2 Sep 2026 02:05:21 +0200 Subject: [PATCH] Add a file writer that replaces its target only on completion. The data is written to .tmp in the same directory as the target and moved to on Commit(); a failed or interrupted write leaves the previous file untouched, with an orphaned .tmp. --- server/TracySafeFileWrite.hpp | 53 +++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 server/TracySafeFileWrite.hpp diff --git a/server/TracySafeFileWrite.hpp b/server/TracySafeFileWrite.hpp new file mode 100644 index 00000000..aee205a2 --- /dev/null +++ b/server/TracySafeFileWrite.hpp @@ -0,0 +1,53 @@ +#ifndef __TRACYSAFEFILEWRITE_HPP__ +#define __TRACYSAFEFILEWRITE_HPP__ + +#include +#include +#include +#include +#include + +#include "TracyFileWrite.hpp" + +namespace tracy +{ + +class SafeFileWrite +{ +public: + static SafeFileWrite* Open( const char* fn, FileCompression comp = FileCompression::Fast, int level = 1, int streams = -1 ) + { + std::string final( fn ); + std::string tmp = final + ".tmp"; + auto f = FileWrite::Open( tmp.c_str(), comp, level, streams ); + if( !f ) return nullptr; + return new SafeFileWrite( std::unique_ptr( f ), std::move( final ), std::move( tmp ) ); + } + + SafeFileWrite( const SafeFileWrite& ) = delete; + SafeFileWrite& operator=( const SafeFileWrite& ) = delete; + + FileWrite& File() { return *m_file; } + std::pair GetCompressionStatistics() const { return m_file->GetCompressionStatistics(); } + + bool Commit() + { + std::error_code ec; + std::filesystem::rename( m_tmp, m_final, ec ); + return !ec; + } + +private: + SafeFileWrite( std::unique_ptr f, std::string final, std::string tmp ) + : m_file( std::move( f ) ) + , m_final( std::move( final ) ) + , m_tmp( std::move( tmp ) ) + {} + + std::unique_ptr m_file; + std::string m_final, m_tmp; +}; + +} + +#endif