diff --git a/common/jobs/jobs_output_archive.cpp b/common/jobs/jobs_output_archive.cpp index 20d1a03d6f..b190235302 100644 --- a/common/jobs/jobs_output_archive.cpp +++ b/common/jobs/jobs_output_archive.cpp @@ -25,6 +25,7 @@ #include #include #include +#include JOBS_OUTPUT_ARCHIVE::JOBS_OUTPUT_ARCHIVE() : JOBS_OUTPUT_HANDLER(), @@ -61,14 +62,17 @@ bool JOBS_OUTPUT_ARCHIVE::HandleOutputs( const wxString& baseTemp wxFFileOutputStream ostream( outputPath ); - if( !ostream.IsOk() ) // issue to create the file. Perhaps not writable dir + if( !ostream.IsOk() ) { - //msg.Printf( _( "Failed to create file '%s'." ), aDestFile ); - //aReporter.Report( msg, RPT_SEVERITY_ERROR ); aResolvedOutputPath.reset(); return false; } + // Use a large I/O buffer to improve compatibility with cloud-synced folders. + // See KIPLATFORM::IO::CLOUD_SYNC_BUFFER_SIZE comment for details. + if( FILE* fp = ostream.GetFile()->fp() ) + setvbuf( fp, nullptr, _IOFBF, KIPLATFORM::IO::CLOUD_SYNC_BUFFER_SIZE ); + wxZipOutputStream zipstream( ostream, -1, wxConvUTF8 ); wxString errors; diff --git a/common/project/project_archiver.cpp b/common/project/project_archiver.cpp index 60ec69134c..bf3fb44284 100644 --- a/common/project/project_archiver.cpp +++ b/common/project/project_archiver.cpp @@ -252,6 +252,10 @@ bool PROJECT_ARCHIVER::Archive( const wxString& aSrcDir, const wxString& aDestFi return false; } + // Use a large I/O buffer to improve compatibility with cloud-synced folders. + if( FILE* fp = ostream.GetFile()->fp() ) + setvbuf( fp, nullptr, _IOFBF, KIPLATFORM::IO::CLOUD_SYNC_BUFFER_SIZE ); + wxZipOutputStream zipstream( ostream, -1, wxConvUTF8 ); wxDir projectDir( aSrcDir ); diff --git a/libs/kiplatform/include/kiplatform/io.h b/libs/kiplatform/include/kiplatform/io.h index cfd17194a2..357ff6d839 100644 --- a/libs/kiplatform/include/kiplatform/io.h +++ b/libs/kiplatform/include/kiplatform/io.h @@ -21,6 +21,7 @@ #define KIPLATFORM_IO_H_ #include +#include class wxString; class wxFileName; @@ -29,6 +30,15 @@ namespace KIPLATFORM { namespace IO { + /** + * Buffer size for file I/O operations on cloud-synced folders. + * + * Cloud sync services like Google Drive, OneDrive, and Dropbox can report stale file sizes + * during seek operations immediately after writing. Using a 512KB buffer reduces the number + * of I/O operations and allows the cloud sync driver to flush data more reliably before + * subsequent reads. This value was determined empirically to eliminate sync issues. + */ + static constexpr size_t CLOUD_SYNC_BUFFER_SIZE = 512 * 1024; /** * Opens the file like fopen but sets flags (if available) for sequential read hinting. * Only use this variant of fopen if the file is truely going to be read sequentially only diff --git a/pcbnew/dialogs/dialog_export_odbpp.cpp b/pcbnew/dialogs/dialog_export_odbpp.cpp index 558bc33733..87114ee03e 100644 --- a/pcbnew/dialogs/dialog_export_odbpp.cpp +++ b/pcbnew/dialogs/dialog_export_odbpp.cpp @@ -49,6 +49,7 @@ #include #include #include +#include @@ -462,6 +463,12 @@ void DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( const JOB_EXPORT_PCB_ODB& aJob, BO aProgressReporter->AdvancePhase( _( "Compressing output" ) ); wxFFileOutputStream fnout( outputFn.GetFullPath() ); + + // Use a large I/O buffer to improve compatibility with cloud-synced folders. + // See KIPLATFORM::IO::CLOUD_SYNC_BUFFER_SIZE comment for details. + if( FILE* fp = fnout.GetFile()->fp() ) + setvbuf( fp, nullptr, _IOFBF, KIPLATFORM::IO::CLOUD_SYNC_BUFFER_SIZE ); + wxZipOutputStream zipStream( fnout ); std::function addDirToZip = @@ -505,6 +512,12 @@ void DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( const JOB_EXPORT_PCB_ODB& aJob, BO else if( aJob.m_compressionMode == JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::TGZ ) { wxFFileOutputStream fnout( outputFn.GetFullPath() ); + + // Use a large I/O buffer to improve compatibility with cloud-synced folders. + // See KIPLATFORM::IO::CLOUD_SYNC_BUFFER_SIZE comment for details. + if( FILE* fp = fnout.GetFile()->fp() ) + setvbuf( fp, nullptr, _IOFBF, KIPLATFORM::IO::CLOUD_SYNC_BUFFER_SIZE ); + wxZlibOutputStream zlibStream( fnout, -1, wxZLIB_GZIP ); wxTarOutputStream tarStream( zlibStream ); diff --git a/pcbnew/pcbnew_jobs_handler.cpp b/pcbnew/pcbnew_jobs_handler.cpp index 800374d32b..19e8f79d84 100644 --- a/pcbnew/pcbnew_jobs_handler.cpp +++ b/pcbnew/pcbnew_jobs_handler.cpp @@ -89,6 +89,7 @@ #include #include #include +#include #include #include #include @@ -2509,6 +2510,12 @@ int PCBNEW_JOBS_HANDLER::JobExportIpc2581( JOB* aJob ) { wxFFileOutputStream fnout( zipfn.GetFullPath() ); + + // Use a large I/O buffer to improve compatibility with cloud-synced folders. + // See KIPLATFORM::IO::CLOUD_SYNC_BUFFER_SIZE comment for details. + if( FILE* fp = fnout.GetFile()->fp() ) + setvbuf( fp, nullptr, _IOFBF, KIPLATFORM::IO::CLOUD_SYNC_BUFFER_SIZE ); + wxZipOutputStream zip( fnout ); wxFFileInputStream fnin( tempFile );