Skip to content

GUACAMOLE-2180: Improve SFTP upload performance#629

Open
alailsonko wants to merge 2 commits intoapache:mainfrom
alailsonko:GUACAMOLE-2180-improve_sftp_upload_performance
Open

GUACAMOLE-2180: Improve SFTP upload performance#629
alailsonko wants to merge 2 commits intoapache:mainfrom
alailsonko:GUACAMOLE-2180-improve_sftp_upload_performance

Conversation

@alailsonko
Copy link

This pull request significantly improves the efficiency and reliability of SFTP file uploads by introducing buffered uploads and robust error handling. Instead of writing each incoming data blob directly to the remote file, uploads are now buffered in memory and flushed in larger chunks, reducing the number of SFTP write operations and handling partial writes more gracefully. The code also introduces a per-upload state structure to track progress and errors, and ensures proper cleanup at the end of each upload.

Buffered SFTP uploads

  • Introduced a new upload state struct (guac_common_ssh_sftp_upload_state) to manage buffered data, the SFTP file handle, and error status for each upload stream.
  • Implemented a buffered upload mechanism: incoming data is accumulated in a 256KB buffer and only flushed to the remote file when full or at the end of the upload, reducing the number of SFTP write calls and handling partial writes robustly. [1] [2]
  • Enhanced error handling: errors during write or flush are tracked in the upload state, and subsequent blobs or end-of-stream events respond with appropriate error messages. [1] [2]
  • Modified the SFTP blob and end handlers to use the new buffered upload logic and state, including proper acknowledgment and freeing of resources at the end of uploads. [1] [2]
  • Updated stream initialization in both file and put handlers to allocate and initialize the new upload state, replacing direct storage of the SFTP file handle. [1] [2]

Related Jira Item

@alailsonko alailsonko changed the title GUACAMOLE-2188: Improve SFTP upload performance GUACAMOLE-2180: Improve SFTP upload performance Dec 15, 2025
Copy link
Contributor

@necouchman necouchman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall I think it looks okay - just needs some updated documentation.

*/
#define GUAC_COMMON_SSH_SFTP_UPLOAD_BUFFER_SIZE (256 * 1024)

typedef struct guac_common_ssh_sftp_upload_state {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please provide overall documentation for the data structure.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

documentation added on commit 40a3726

Comment on lines +72 to +97
static void guac_common_ssh_sftp_upload_flush(guac_user* user,
guac_common_ssh_sftp_upload_state* state) {

if (state->error || state->buffered_length <= 0 || state->file == NULL)
return;

int offset = 0;
while (offset < state->buffered_length) {
ssize_t written = libssh2_sftp_write(state->file,
state->buffer + offset, state->buffered_length - offset);
if (written <= 0) {
guac_user_log(user, GUAC_LOG_INFO,
"Buffered SFTP write failed after %d bytes (attempt returned %zd)",
offset, written);
state->error = 1;
break;
}
offset += (int)written;
}

if (!state->error)
guac_user_log(user, GUAC_LOG_DEBUG,
"Flushed %d buffered bytes to remote file", state->buffered_length);

state->buffered_length = 0;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some documentation throughout this function would be nice.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

documentation added on commit 40a3726

@alailsonko alailsonko requested a review from necouchman January 26, 2026 08:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants