mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-12-11 03:42:35 +03:00
Introduce sftp async i/o (aio) api
The existing sftp async read api has two problems : 1. sftp_async_read() assumes that the value of the third parameter count is same as the number of bytes requested to read in the corresponding call to sftp_async_read_begin(). But the documentation of sftp_async_read() allows the value of count parameter to be more than that requested length. If value of count parameter is more than that requested length then sftp_async_read() updates the file->offset incorrectly which leads to further read/writes occuring from incorrect offsets. The problem here is that sftp_async_read() doesn't know about the number of bytes requested to read specified in the call to sftp_async_read_begin(), and it wrongly assumes the value of its count parameter (which is actually the size of the buffer to store the read data) to be the same as the number of bytes requested to read. 2. sftp_async_read_begin() returns an uint32_t type value type casted to int as a request identifier, whereas sftp_async_read() expects an uint32_t type value as a request identifier. Due to this the user has to typecast the identifier returned by sftp_async_read_begin() from int to uint32_t and then pass it to sftp_async_read(). This type casting is cumbersome for the user and hence the approach is not user-friendly. This commit solves the above two problems by introducing a new sftp aio api. The sftp_aio_begin_*() functions in the api send an i/o request to the sftp server and provide the caller a dynamically allocated structure storing information about the sent request. Information like number of bytes requested for i/o, id of sent request etc is stored in the structure. That structure should be provided to the sftp_aio_wait_*() functions in the api which wait for the response corresponding to the request whose info is stored in the provided structure. The libssh user is supposed to handle that structure through an opaque type sftp_aio. Since the structure stores the number of bytes requested for i/o, sftp_aio_wait_*() knows about the number of bytes requested for i/o (specified in the call to sftp_aio_begin_*()) and hence updates the file->offset correctly solving problem #1 present in the existing async api. Since the structure provided by sftp_aio_begin_*() (containing the request id) is supplied to sftp_aio_wait_*(), no casting of id's needs to be done by the user solving problem #2 of the existing async api. Signed-off-by: Eshan Kelkar <eshankelkar@galorithm.com> Reviewed-by: Sahana Prasad <sahana@redhat.com> Reviewed-by: Jakub Jelen <jjelen@redhat.com>
This commit is contained in:
committed by
Sahana Prasad
parent
7455b6ae64
commit
c1606da450
@@ -78,6 +78,7 @@ typedef struct sftp_session_struct* sftp_session;
|
||||
typedef struct sftp_status_message_struct* sftp_status_message;
|
||||
typedef struct sftp_statvfs_struct* sftp_statvfs_t;
|
||||
typedef struct sftp_limits_struct* sftp_limits_t;
|
||||
typedef struct sftp_aio_struct* sftp_aio;
|
||||
|
||||
struct sftp_session_struct {
|
||||
ssh_session session;
|
||||
@@ -580,6 +581,216 @@ LIBSSH_API int sftp_async_read(sftp_file file, void *data, uint32_t len, uint32_
|
||||
*/
|
||||
LIBSSH_API ssize_t sftp_write(sftp_file file, const void *buf, size_t count);
|
||||
|
||||
/**
|
||||
* @brief Deallocate memory corresponding to a sftp aio handle.
|
||||
*
|
||||
* This function deallocates memory corresponding to the aio handle returned
|
||||
* by the sftp_aio_begin_*() functions. Users can use this function to free
|
||||
* memory corresponding to an aio handle for an outstanding async i/o request
|
||||
* on encountering some error.
|
||||
*
|
||||
* @param aio sftp aio handle corresponding to which memory has
|
||||
* to be deallocated.
|
||||
*
|
||||
* @see sftp_aio_begin_read()
|
||||
* @see sftp_aio_wait_read()
|
||||
* @see sftp_aio_begin_write()
|
||||
* @see sftp_aio_wait_write()
|
||||
*/
|
||||
LIBSSH_API void sftp_aio_free(sftp_aio aio);
|
||||
#define SFTP_AIO_FREE(x) \
|
||||
do { if(x != NULL) {sftp_aio_free(x); x = NULL;} } while(0)
|
||||
|
||||
/**
|
||||
* @brief Start an asynchronous read from a file using an opened sftp
|
||||
* file handle.
|
||||
*
|
||||
* Its goal is to avoid the slowdowns related to the request/response pattern
|
||||
* of a synchronous read. To do so, you must call 2 functions :
|
||||
*
|
||||
* sftp_aio_begin_read() and sftp_aio_wait_read().
|
||||
*
|
||||
* - The first step is to call sftp_aio_begin_read(). This function sends a
|
||||
* read request to the sftp server, dynamically allocates memory to store
|
||||
* information about the sent request and provides the caller an sftp aio
|
||||
* handle to that memory.
|
||||
*
|
||||
* - The second step is to call sftp_aio_wait_read() and pass it the address
|
||||
* of a location storing the sftp aio handle provided by
|
||||
* sftp_aio_begin_read().
|
||||
*
|
||||
* These two functions do not close the open sftp file handle passed to
|
||||
* sftp_aio_begin_read() irrespective of whether they fail or not.
|
||||
*
|
||||
* It is the responsibility of the caller to ensure that the open sftp file
|
||||
* handle passed to sftp_aio_begin_read() must not be closed before the
|
||||
* corresponding call to sftp_aio_wait_read(). After sftp_aio_wait_read()
|
||||
* returns, it is caller's decision whether to immediately close the file by
|
||||
* calling sftp_close() or to keep it open and perform some more operations
|
||||
* on it.
|
||||
*
|
||||
* @param file The opened sftp file handle to be read from.
|
||||
*
|
||||
* @param len Number of bytes to read.
|
||||
*
|
||||
* @param aio Pointer to a location where the sftp aio handle
|
||||
* (corresponding to the sent request) should be stored.
|
||||
*
|
||||
* @returns SSH_OK on success, SSH_ERROR on error with sftp and ssh
|
||||
* errors set.
|
||||
*
|
||||
* @warning When calling this function, the internal offset is
|
||||
* updated corresponding to the len parameter.
|
||||
*
|
||||
* @warning A call to sftp_aio_begin_read() sends a request to
|
||||
* the server. When the server answers, libssh allocates
|
||||
* memory to store it until sftp_aio_wait_read() is called.
|
||||
* Not calling sftp_aio_wait_read() will lead to memory
|
||||
* leaks.
|
||||
*
|
||||
* @see sftp_aio_wait_read()
|
||||
* @see sftp_aio_free()
|
||||
* @see sftp_open()
|
||||
* @see sftp_close()
|
||||
* @see sftp_get_error()
|
||||
* @see ssh_get_error()
|
||||
*/
|
||||
LIBSSH_API int sftp_aio_begin_read(sftp_file file,
|
||||
size_t len,
|
||||
sftp_aio *aio);
|
||||
|
||||
/**
|
||||
* @brief Wait for an asynchronous read to complete and store the read data
|
||||
* in the supplied buffer.
|
||||
*
|
||||
* A pointer to an sftp aio handle should be passed while calling
|
||||
* this function. Except when the return value is SSH_AGAIN,
|
||||
* this function releases the memory corresponding to the supplied
|
||||
* aio handle and assigns NULL to that aio handle using the passed
|
||||
* pointer to that handle.
|
||||
*
|
||||
* If the file is opened in non-blocking mode and the request hasn't been
|
||||
* executed yet, this function returns SSH_AGAIN and must be called again
|
||||
* using the same sftp aio handle.
|
||||
*
|
||||
* @param aio Pointer to the sftp aio handle returned by
|
||||
* sftp_aio_begin_read().
|
||||
*
|
||||
* @param buf Pointer to the buffer in which read data will be stored.
|
||||
*
|
||||
* @param buf_size Size of the buffer in bytes. It should be bigger or
|
||||
* equal to the length parameter of the
|
||||
* sftp_aio_begin_read() call.
|
||||
*
|
||||
* @return Number of bytes read, 0 on EOF, SSH_ERROR if an error
|
||||
* occurred, SSH_AGAIN if the file is opened in nonblocking
|
||||
* mode and the request hasn't been executed yet.
|
||||
*
|
||||
* @warning A call to this function with an invalid sftp aio handle
|
||||
* may never return.
|
||||
*
|
||||
* @see sftp_aio_begin_read()
|
||||
* @see sftp_aio_free()
|
||||
*/
|
||||
LIBSSH_API ssize_t sftp_aio_wait_read(sftp_aio *aio,
|
||||
void *buf,
|
||||
size_t buf_size);
|
||||
|
||||
/**
|
||||
* @brief Start an asynchronous write to a file using an opened sftp
|
||||
* file handle.
|
||||
*
|
||||
* Its goal is to avoid the slowdowns related to the request/response pattern
|
||||
* of a synchronous write. To do so, you must call 2 functions :
|
||||
*
|
||||
* sftp_aio_begin_write() and sftp_aio_wait_write().
|
||||
*
|
||||
* - The first step is to call sftp_aio_begin_write(). This function sends a
|
||||
* write request to the sftp server, dynamically allocates memory to store
|
||||
* information about the sent request and provides the caller an sftp aio
|
||||
* handle to that memory.
|
||||
*
|
||||
* - The second step is to call sftp_aio_wait_write() and pass it the address
|
||||
* of a location storing the sftp aio handle provided by
|
||||
* sftp_aio_begin_write().
|
||||
*
|
||||
* These two functions do not close the open sftp file handle passed to
|
||||
* sftp_aio_begin_write() irrespective of whether they fail or not.
|
||||
*
|
||||
* It is the responsibility of the caller to ensure that the open sftp file
|
||||
* handle passed to sftp_aio_begin_write() must not be closed before the
|
||||
* corresponding call to sftp_aio_wait_write(). After sftp_aio_wait_write()
|
||||
* returns, it is caller's decision whether to immediately close the file by
|
||||
* calling sftp_close() or to keep it open and perform some more operations
|
||||
* on it.
|
||||
*
|
||||
* @param file The opened sftp file handle to write to.
|
||||
*
|
||||
* @param buf Pointer to the buffer containing data to write.
|
||||
*
|
||||
* @param len Number of bytes to write.
|
||||
*
|
||||
* @param aio Pointer to a location where the sftp aio handle
|
||||
* (corresponding to the sent request) should be stored.
|
||||
*
|
||||
* @returns SSH_OK on success, SSH_ERROR with sftp and ssh errors
|
||||
* set.
|
||||
*
|
||||
* @warning When calling this function, the internal offset is
|
||||
* updated corresponding to the len parameter.
|
||||
*
|
||||
* @warning A call to sftp_aio_begin_write() sends a request to
|
||||
* the server. When the server answers, libssh allocates
|
||||
* memory to store it until sftp_aio_wait_write() is
|
||||
* called. Not calling sftp_aio_wait_write() will lead to
|
||||
* memory leaks.
|
||||
*
|
||||
* @see sftp_aio_wait_write()
|
||||
* @see sftp_aio_free()
|
||||
* @see sftp_open()
|
||||
* @see sftp_close()
|
||||
* @see sftp_get_error()
|
||||
* @see ssh_get_error()
|
||||
*/
|
||||
LIBSSH_API int sftp_aio_begin_write(sftp_file file,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
sftp_aio *aio);
|
||||
|
||||
/**
|
||||
* @brief Wait for an asynchronous write to complete.
|
||||
*
|
||||
* A pointer to an sftp aio handle should be passed while calling
|
||||
* this function. Except when the return value is SSH_AGAIN,
|
||||
* this function releases the memory corresponding to the supplied
|
||||
* aio handle and assigns NULL to that aio handle using the passed
|
||||
* pointer to that handle.
|
||||
*
|
||||
* If the file is opened in non-blocking mode and the request hasn't
|
||||
* been executed yet, this function returns SSH_AGAIN and must be called
|
||||
* again using the same sftp aio handle.
|
||||
*
|
||||
* On success, this function returns the number of bytes written.
|
||||
* The SFTP protocol doesn't support partial writes to remote files,
|
||||
* hence on success this returned value will always be equal to the
|
||||
* len passed in the previous corresponding call to sftp_aio_begin_write().
|
||||
*
|
||||
* @param aio Pointer to the sftp aio handle returned by
|
||||
* sftp_aio_begin_write().
|
||||
*
|
||||
* @return Number of bytes written on success, SSH_ERROR
|
||||
* if an error occurred, SSH_AGAIN if the file is
|
||||
* opened in nonblocking mode and the request hasn't
|
||||
* been executed yet.
|
||||
*
|
||||
* @warning A call to this function with an invalid sftp aio handle
|
||||
* may never return.
|
||||
*
|
||||
* @see sftp_aio_begin_write()
|
||||
* @see sftp_aio_free()
|
||||
*/
|
||||
LIBSSH_API ssize_t sftp_aio_wait_write(sftp_aio *aio);
|
||||
|
||||
/**
|
||||
* @brief Seek to a specific location in a file.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user