|
@@ -39,13 +39,12 @@
|
|
|
|
|
|
#include "faux/faux.h"
|
|
|
#include "faux/str.h"
|
|
|
+#include "faux/buf.h"
|
|
|
#include "faux/net.h"
|
|
|
#include "faux/async.h"
|
|
|
|
|
|
#include "private.h"
|
|
|
|
|
|
-#define DATA_CHUNK 4096
|
|
|
-
|
|
|
/** @brief Create new async I/O object.
|
|
|
*
|
|
|
* Constructor gets associated file descriptor to operate on it. File
|
|
@@ -81,22 +80,14 @@ faux_async_t *faux_async_new(int fd)
|
|
|
async->read_udata = NULL;
|
|
|
async->min = 1;
|
|
|
async->max = FAUX_ASYNC_UNLIMITED;
|
|
|
- async->i_list = faux_list_new(FAUX_LIST_UNSORTED, FAUX_LIST_NONUNIQUE,
|
|
|
- NULL, NULL, faux_free);
|
|
|
- async->i_rpos = 0;
|
|
|
- async->i_wpos = 0;
|
|
|
- async->i_size = 0;
|
|
|
- async->i_overflow = 10000000l; // ~ 10M
|
|
|
+ async->ibuf = faux_buf_new(DATA_CHUNK);
|
|
|
+ faux_buf_set_limit(async->ibuf, FAUX_ASYNC_IN_OVERFLOW);
|
|
|
|
|
|
// Write (Output)
|
|
|
async->stall_cb = NULL;
|
|
|
async->stall_udata = NULL;
|
|
|
- async->o_overflow = 10000000l; // ~ 10M
|
|
|
- async->o_list = faux_list_new(FAUX_LIST_UNSORTED, FAUX_LIST_NONUNIQUE,
|
|
|
- NULL, NULL, faux_free);
|
|
|
- async->o_rpos = 0;
|
|
|
- async->o_wpos = 0;
|
|
|
- async->o_size = 0;
|
|
|
+ async->obuf = faux_buf_new(DATA_CHUNK);
|
|
|
+ faux_buf_set_limit(async->obuf, FAUX_ASYNC_OUT_OVERFLOW);
|
|
|
|
|
|
return async;
|
|
|
}
|
|
@@ -111,8 +102,8 @@ void faux_async_free(faux_async_t *async)
|
|
|
if (!async)
|
|
|
return;
|
|
|
|
|
|
- faux_list_free(async->i_list);
|
|
|
- faux_list_free(async->o_list);
|
|
|
+ faux_buf_free(async->ibuf);
|
|
|
+ faux_buf_free(async->obuf);
|
|
|
|
|
|
faux_free(async);
|
|
|
}
|
|
@@ -216,7 +207,7 @@ void faux_async_set_write_overflow(faux_async_t *async, size_t overflow)
|
|
|
if (!async)
|
|
|
return;
|
|
|
|
|
|
- async->o_overflow = overflow;
|
|
|
+ faux_buf_set_limit(async->obuf, overflow);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -235,27 +226,7 @@ void faux_async_set_read_overflow(faux_async_t *async, size_t overflow)
|
|
|
if (!async)
|
|
|
return;
|
|
|
|
|
|
- async->i_overflow = overflow;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/** @brief Get amount of unused space within current data chunk.
|
|
|
- *
|
|
|
- * Inernal static function.
|
|
|
- *
|
|
|
- * @param [in] list Internal buffer (list of chunks) to inspect.
|
|
|
- * @param [in] pos Current write position within last chunk
|
|
|
- * @return Size of unused space or < 0 on error.
|
|
|
- */
|
|
|
-static ssize_t free_space(faux_list_t *list, size_t pos)
|
|
|
-{
|
|
|
- if (!list)
|
|
|
- return -1;
|
|
|
-
|
|
|
- if (faux_list_len(list) == 0)
|
|
|
- return 0;
|
|
|
-
|
|
|
- return (DATA_CHUNK - pos);
|
|
|
+ faux_buf_set_limit(async->ibuf, overflow);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -275,8 +246,7 @@ static ssize_t free_space(faux_list_t *list, size_t pos)
|
|
|
*/
|
|
|
ssize_t faux_async_write(faux_async_t *async, void *data, size_t len)
|
|
|
{
|
|
|
- void *new_chunk = NULL;
|
|
|
- size_t data_left = len;
|
|
|
+ ssize_t data_written = len;
|
|
|
|
|
|
assert(async);
|
|
|
if (!async)
|
|
@@ -285,34 +255,9 @@ ssize_t faux_async_write(faux_async_t *async, void *data, size_t len)
|
|
|
if (!data)
|
|
|
return -1;
|
|
|
|
|
|
- while (data_left != 0) {
|
|
|
- ssize_t bytes_free = 0;
|
|
|
- size_t copy_len = 0;
|
|
|
- char *chunk_ptr = NULL;
|
|
|
-
|
|
|
- // Allocate new chunk if necessary
|
|
|
- bytes_free = free_space(async->o_list, async->o_wpos);
|
|
|
- if (bytes_free < 0)
|
|
|
- return -1;
|
|
|
- if (0 == bytes_free) {
|
|
|
- new_chunk = faux_malloc(DATA_CHUNK);
|
|
|
- assert(new_chunk);
|
|
|
- faux_list_add(async->o_list, new_chunk);
|
|
|
- async->o_wpos = 0;
|
|
|
- bytes_free = free_space(async->o_list, async->o_wpos);
|
|
|
- }
|
|
|
-
|
|
|
- // Copy data
|
|
|
- chunk_ptr = faux_list_data(faux_list_tail(async->o_list));
|
|
|
- copy_len = (data_left < (size_t)bytes_free) ? data_left : (size_t)bytes_free;
|
|
|
- memcpy(chunk_ptr + async->o_wpos, data + len - data_left,
|
|
|
- copy_len);
|
|
|
- async->o_wpos += copy_len;
|
|
|
- data_left -= copy_len;
|
|
|
- async->o_size += copy_len;
|
|
|
- if (async->o_size >= async->o_overflow)
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ data_written = faux_buf_write(async->obuf, data, len);
|
|
|
+ if (data_written < 0)
|
|
|
+ return -1;
|
|
|
|
|
|
// Try to real write data to fd in nonblocked mode
|
|
|
faux_async_out(async);
|
|
@@ -442,33 +387,23 @@ ssize_t faux_async_out(faux_async_t *async)
|
|
|
*/
|
|
|
ssize_t faux_async_in(faux_async_t *async)
|
|
|
{
|
|
|
- void *new_chunk = NULL;
|
|
|
ssize_t total_readed = 0;
|
|
|
ssize_t bytes_readed = 0;
|
|
|
- ssize_t bytes_free = 0; // Free space within current (last) chunk
|
|
|
+ ssize_t locked_len = 0;
|
|
|
|
|
|
assert(async);
|
|
|
if (!async)
|
|
|
return -1;
|
|
|
|
|
|
do {
|
|
|
- char *chunk_ptr = NULL;
|
|
|
+ void *data = NULL;
|
|
|
+ size_t bytes_stored = 0;
|
|
|
|
|
|
- // Allocate new chunk if necessary
|
|
|
- bytes_free = free_space(async->i_list, async->i_wpos);
|
|
|
- if (bytes_free < 0)
|
|
|
+ locked_len = faux_buf_dwrite_lock_easy(async->ibuf, &data);
|
|
|
+ if (locked_len <= 0)
|
|
|
return -1;
|
|
|
- if (0 == bytes_free) { // We need to allocate additional chunk
|
|
|
- new_chunk = faux_malloc(DATA_CHUNK);
|
|
|
- assert(new_chunk);
|
|
|
- faux_list_add(async->i_list, new_chunk);
|
|
|
- async->i_wpos = 0;
|
|
|
- bytes_free = free_space(async->i_list, async->i_wpos);
|
|
|
- }
|
|
|
-
|
|
|
- // Read data to last chunk
|
|
|
- chunk_ptr = faux_list_data(faux_list_tail(async->i_list));
|
|
|
- bytes_readed = read(async->fd, chunk_ptr + async->i_wpos, bytes_free);
|
|
|
+ // Read data
|
|
|
+ bytes_readed = read(async->fd, data, locked_len);
|
|
|
if (bytes_readed < 0) {
|
|
|
if ( // Something went wrong
|
|
|
(errno != EINTR) &&
|
|
@@ -477,64 +412,30 @@ ssize_t faux_async_in(faux_async_t *async)
|
|
|
)
|
|
|
return -1;
|
|
|
}
|
|
|
- if (bytes_readed > 0) {
|
|
|
- async->i_wpos += bytes_readed;
|
|
|
- async->i_size += bytes_readed;
|
|
|
- total_readed += bytes_readed;
|
|
|
- }
|
|
|
- if (async->i_size >= async->i_overflow)
|
|
|
- return -1;
|
|
|
+ faux_buf_dwrite_unlock_easy(async->ibuf, bytes_readed);
|
|
|
+ total_readed += bytes_readed;
|
|
|
|
|
|
// Check for amount of stored data
|
|
|
- while (async->i_size >= async->min) {
|
|
|
-
|
|
|
+ while ((bytes_stored = faux_buf_len(async->ibuf)) >= async->min) {
|
|
|
size_t copy_len = 0;
|
|
|
- size_t full_size = 0;
|
|
|
char *buf = NULL;
|
|
|
- char *buf_ptr = NULL;
|
|
|
|
|
|
if (FAUX_ASYNC_UNLIMITED == async->max) { // Indefinite
|
|
|
- copy_len = async->i_size; // Take all data
|
|
|
+ copy_len = bytes_stored; // Take all data
|
|
|
} else {
|
|
|
- copy_len = (async->i_size < async->max) ?
|
|
|
- async->i_size : async->max;
|
|
|
+ copy_len = (bytes_stored < async->max) ?
|
|
|
+ bytes_stored : async->max;
|
|
|
}
|
|
|
+ buf = faux_malloc(copy_len);
|
|
|
+ assert(buf);
|
|
|
+ faux_buf_read(async->ibuf, buf, copy_len);
|
|
|
|
|
|
- full_size = copy_len; // Save full length value
|
|
|
- buf = faux_malloc(full_size);
|
|
|
- buf_ptr = buf;
|
|
|
- while (copy_len > 0) {
|
|
|
- size_t data_to_write = 0;
|
|
|
- faux_list_node_t *node = faux_list_head(async->i_list);
|
|
|
- char *chunk_ptr = NULL;
|
|
|
-
|
|
|
- if (!node) // Something went wrong
|
|
|
- return -1;
|
|
|
- chunk_ptr = faux_list_data(node);
|
|
|
- data_to_write = data_avail(async->i_list,
|
|
|
- async->i_rpos, async->i_wpos);
|
|
|
- if (copy_len < data_to_write)
|
|
|
- data_to_write = copy_len;
|
|
|
- memcpy(buf_ptr, chunk_ptr + async->i_rpos,
|
|
|
- data_to_write);
|
|
|
- copy_len -= data_to_write;
|
|
|
- async->i_size -= data_to_write;
|
|
|
- async->i_rpos += data_to_write;
|
|
|
- buf_ptr += data_to_write;
|
|
|
- if (data_avail(async->i_list,
|
|
|
- async->i_rpos, async->i_wpos) <= 0) {
|
|
|
- async->i_rpos = 0;
|
|
|
- faux_list_del(async->i_list, node);
|
|
|
- }
|
|
|
- }
|
|
|
// Execute callback
|
|
|
if (async->read_cb)
|
|
|
async->read_cb(async, buf,
|
|
|
- full_size, async->read_udata);
|
|
|
-
|
|
|
+ copy_len, async->read_udata);
|
|
|
}
|
|
|
-
|
|
|
- } while (bytes_readed == bytes_free);
|
|
|
+ } while (bytes_readed == locked_len);
|
|
|
|
|
|
return total_readed;
|
|
|
}
|