window_size: explicit adjustments only
Removed the automatic window_size adjustments from _libssh2_channel_read() and instead all channel readers must now make sure to enlarge the window sizes properly themselves. libssh2_channel_read_ex() - the public function, now grows the window size according to the requested buffer size. Applications can still opt to grow the window more on demand. Larger windows tend to give higher performance. sftp_read() now uses the read-ahead logic to figure out a window_size.
This commit is contained in:
parent
7d58994571
commit
03ca902075
@ -1734,6 +1734,9 @@ libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel,
|
||||
* It is important to not return 0 until the currently read channel is
|
||||
* complete. If we read stuff from the wire but it was no payload data to fill
|
||||
* in the buffer with, we MUST make sure to return LIBSSH2_ERROR_EAGAIN.
|
||||
*
|
||||
* The receive window must be maintained (enlarged) by the user of this
|
||||
* function.
|
||||
*/
|
||||
ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
|
||||
char *buf, size_t buflen)
|
||||
@ -1755,15 +1758,6 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
|
||||
channel->read_state = libssh2_NB_state_created;
|
||||
}
|
||||
|
||||
/*
|
||||
* =============================== NOTE ===============================
|
||||
* I know this is very ugly and not a really good use of "goto", but
|
||||
* this case statement would be even uglier to do it any other way
|
||||
*/
|
||||
if (channel->read_state == libssh2_NB_state_jump1) {
|
||||
goto channel_read_window_adjust;
|
||||
}
|
||||
|
||||
rc = 1; /* set to >0 to let the while loop start */
|
||||
|
||||
/* Process all pending incoming packets in all states in order to "even
|
||||
@ -1872,26 +1866,6 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
|
||||
more off the network again */
|
||||
channel->read_state = libssh2_NB_state_created;
|
||||
|
||||
if(channel->remote.window_size < (LIBSSH2_CHANNEL_WINDOW_DEFAULT*30)) {
|
||||
/* the window is getting too narrow, expand it! */
|
||||
|
||||
channel_read_window_adjust:
|
||||
channel->read_state = libssh2_NB_state_jump1;
|
||||
/* the actual window adjusting may not finish so we need to deal with
|
||||
this special state here */
|
||||
rc = _libssh2_channel_receive_window_adjust(channel,
|
||||
(LIBSSH2_CHANNEL_WINDOW_DEFAULT*60), 0, NULL);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||
"channel_read() filled %d adjusted %d",
|
||||
bytes_read, buflen);
|
||||
/* continue in 'created' state to drain the already read packages
|
||||
first before starting to empty the socket further */
|
||||
channel->read_state = libssh2_NB_state_created;
|
||||
}
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
@ -1904,16 +1878,29 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
|
||||
* currently read channel is complete. If we read stuff from the wire but it
|
||||
* was no payload data to fill in the buffer with, we MUST make sure to return
|
||||
* LIBSSH2_ERROR_EAGAIN.
|
||||
*
|
||||
* This function will first make sure there's a receive window enough to
|
||||
* receive a full buffer's wort of contents. An application may choose to
|
||||
* adjust the receive window more to increase transfer performance.
|
||||
*/
|
||||
LIBSSH2_API ssize_t
|
||||
libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id, char *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
int rc;
|
||||
unsigned long recv_window;
|
||||
|
||||
if(!channel)
|
||||
return LIBSSH2_ERROR_BAD_USE;
|
||||
|
||||
recv_window = libssh2_channel_window_read_ex(channel, NULL, NULL);
|
||||
|
||||
if(buflen > recv_window) {
|
||||
BLOCK_ADJUST(rc, channel->session,
|
||||
_libssh2_channel_receive_window_adjust(channel, buflen,
|
||||
0, NULL));
|
||||
}
|
||||
|
||||
BLOCK_ADJUST(rc, channel->session,
|
||||
_libssh2_channel_read(channel, stream_id, buf, buflen));
|
||||
return rc;
|
||||
|
26
src/sftp.c
26
src/sftp.c
@ -1111,8 +1111,10 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
||||
having been acked - until we reach EOF. */
|
||||
if(!filep->eof) {
|
||||
size_t max_read_ahead = buffer_size*4;
|
||||
if(max_read_ahead > LIBSSH2_CHANNEL_WINDOW_DEFAULT*30)
|
||||
max_read_ahead = LIBSSH2_CHANNEL_WINDOW_DEFAULT*30;
|
||||
unsigned long recv_window;
|
||||
|
||||
if(max_read_ahead > LIBSSH2_CHANNEL_WINDOW_DEFAULT*4)
|
||||
max_read_ahead = LIBSSH2_CHANNEL_WINDOW_DEFAULT*4;
|
||||
|
||||
/* if the buffer_size passed in now is smaller than what has already
|
||||
been sent, we risk getting count become a very large number */
|
||||
@ -1137,6 +1139,26 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
||||
buffer_size*4 amount of data so that we can return them very fast
|
||||
in subsequent calls.
|
||||
*/
|
||||
|
||||
recv_window = libssh2_channel_window_read_ex(sftp->channel,
|
||||
NULL, NULL);
|
||||
if(max_read_ahead > recv_window) {
|
||||
/* more data will be asked for than what the window currently
|
||||
allows, expand it! */
|
||||
|
||||
if(total_read)
|
||||
/* since we risk getting EAGAIN below, we return here if
|
||||
there is data available */
|
||||
return total_read;
|
||||
|
||||
rc = _libssh2_channel_receive_window_adjust(sftp->channel,
|
||||
max_read_ahead*8,
|
||||
0, NULL);
|
||||
/* if this returns EAGAIN, we will get back to this function
|
||||
at next call */
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
while(count > 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user