diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2009-02-25 15:22:31 +0100 |
---|---|---|
committer | Jelmer Vernooij <jelmer@samba.org> | 2009-02-25 15:22:31 +0100 |
commit | 59cc0c09d5413d1264758bef505856f5f56131e4 (patch) | |
tree | 2a40aaa183203b59162cbb8c4dfbfd50ed0a0e34 /lib | |
parent | 838b950138255beb7135a32d4429a74fec2bfe42 (diff) | |
parent | b6457c78d61992f12903ed0966d9d1608de68da8 (diff) | |
download | samba-59cc0c09d5413d1264758bef505856f5f56131e4.tar.gz samba-59cc0c09d5413d1264758bef505856f5f56131e4.tar.bz2 samba-59cc0c09d5413d1264758bef505856f5f56131e4.zip |
Merge branch 'master' of ssh://git.samba.org/data/git/samba
Diffstat (limited to 'lib')
-rw-r--r-- | lib/async_req/async_sock.c | 300 | ||||
-rw-r--r-- | lib/async_req/async_sock.h | 11 | ||||
-rw-r--r-- | lib/tevent/tevent.h | 14 | ||||
-rw-r--r-- | lib/tevent/tevent_req.c | 42 |
4 files changed, 53 insertions, 314 deletions
diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c index 3563421e0e..40e7bca4c8 100644 --- a/lib/async_req/async_sock.c +++ b/lib/async_req/async_sock.c @@ -30,45 +30,6 @@ #endif /** - * Discriminator for async_syscall_state - */ -enum async_syscall_type { - ASYNC_SYSCALL_SEND, - ASYNC_SYSCALL_RECV, -}; - -/** - * Holder for syscall arguments and the result - */ - -struct async_syscall_state { - enum async_syscall_type syscall_type; - struct tevent_fd *fde; - - union { - struct param_send { - int fd; - const void *buffer; - size_t length; - int flags; - } param_send; - struct param_recv { - int fd; - void *buffer; - size_t length; - int flags; - } param_recv; - } param; - - union { - ssize_t result_ssize_t; - size_t result_size_t; - int result_int; - } result; - int sys_errno; -}; - -/** * @brief Map async_req states to unix-style errnos * @param[in] req The async req to get the state from * @param[out] err Pointer to take the unix-style errno @@ -117,267 +78,6 @@ int async_req_simple_recv_errno(struct async_req *req) return 0; } -/** - * @brief Create a new async syscall req - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] type Which syscall will this be - * @param[in] pstate Where to put the newly created private_data state - * @retval The new request - * - * This is a helper function to prepare a new struct async_req with an - * associated struct async_syscall_state. The async_syscall_state will be put - * into the async_req as private_data. - */ - -static struct async_req *async_syscall_new(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - enum async_syscall_type type, - struct async_syscall_state **pstate) -{ - struct async_req *result; - struct async_syscall_state *state; - - if (!async_req_setup(mem_ctx, &result, &state, - struct async_syscall_state)) { - return NULL; - } - state->syscall_type = type; - - result->private_data = state; - - *pstate = state; - - return result; -} - -/** - * @brief Create a new async syscall req based on a fd - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] type Which syscall will this be - * @param[in] fd The file descriptor we work on - * @param[in] fde_flags TEVENT_FD_READ/WRITE -- what are we interested in? - * @param[in] fde_cb The callback function for the file descriptor event - * @param[in] pstate Where to put the newly created private_data state - * @retval The new request - * - * This is a helper function to prepare a new struct async_req with an - * associated struct async_syscall_state and an associated file descriptor - * event. - */ - -static struct async_req *async_fde_syscall_new( - TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - enum async_syscall_type type, - int fd, - uint16_t fde_flags, - void (*fde_cb)(struct tevent_context *ev, - struct tevent_fd *fde, uint16_t flags, - void *priv), - struct async_syscall_state **pstate) -{ - struct async_req *result; - struct async_syscall_state *state; - - result = async_syscall_new(mem_ctx, ev, type, &state); - if (result == NULL) { - return NULL; - } - - state->fde = tevent_add_fd(ev, state, fd, fde_flags, fde_cb, result); - if (state->fde == NULL) { - TALLOC_FREE(result); - return NULL; - } - *pstate = state; - return result; -} - -/** - * Retrieve a ssize_t typed result from an async syscall - * @param[in] req The syscall that has just finished - * @param[out] perrno Where to put the syscall's errno - * @retval The return value from the asynchronously called syscall - */ - -ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno) -{ - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - - *perrno = state->sys_errno; - return state->result.result_ssize_t; -} - -/** - * Retrieve a size_t typed result from an async syscall - * @param[in] req The syscall that has just finished - * @param[out] perrno Where to put the syscall's errno - * @retval The return value from the asynchronously called syscall - */ - -size_t async_syscall_result_size_t(struct async_req *req, int *perrno) -{ - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - - *perrno = state->sys_errno; - return state->result.result_size_t; -} - -/** - * Retrieve a int typed result from an async syscall - * @param[in] req The syscall that has just finished - * @param[out] perrno Where to put the syscall's errno - * @retval The return value from the asynchronously called syscall - */ - -int async_syscall_result_int(struct async_req *req, int *perrno) -{ - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - - *perrno = state->sys_errno; - return state->result.result_int; -} - -/** - * fde event handler for the "send" syscall - * @param[in] ev The event context that sent us here - * @param[in] fde The file descriptor event associated with the send - * @param[in] flags Can only be TEVENT_FD_WRITE here - * @param[in] priv private data, "struct async_req *" in this case - */ - -static void async_send_callback(struct tevent_context *ev, - struct tevent_fd *fde, uint16_t flags, - void *priv) -{ - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - struct param_send *p = &state->param.param_send; - - if (state->syscall_type != ASYNC_SYSCALL_SEND) { - async_req_error(req, EIO); - return; - } - - state->result.result_ssize_t = send(p->fd, p->buffer, p->length, - p->flags); - state->sys_errno = errno; - - TALLOC_FREE(state->fde); - - async_req_done(req); -} - -/** - * Async version of send(2) - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] fd The socket to send to - * @param[in] buffer The buffer to send - * @param[in] length How many bytes to send - * @param[in] flags flags passed to send(2) - * - * This function is a direct counterpart of send(2) - */ - -struct async_req *async_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - int fd, const void *buffer, size_t length, - int flags) -{ - struct async_req *result; - struct async_syscall_state *state; - - result = async_fde_syscall_new( - mem_ctx, ev, ASYNC_SYSCALL_SEND, - fd, TEVENT_FD_WRITE, async_send_callback, - &state); - if (result == NULL) { - return NULL; - } - - state->param.param_send.fd = fd; - state->param.param_send.buffer = buffer; - state->param.param_send.length = length; - state->param.param_send.flags = flags; - - return result; -} - -/** - * fde event handler for the "recv" syscall - * @param[in] ev The event context that sent us here - * @param[in] fde The file descriptor event associated with the recv - * @param[in] flags Can only be TEVENT_FD_READ here - * @param[in] priv private data, "struct async_req *" in this case - */ - -static void async_recv_callback(struct tevent_context *ev, - struct tevent_fd *fde, uint16_t flags, - void *priv) -{ - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - struct param_recv *p = &state->param.param_recv; - - if (state->syscall_type != ASYNC_SYSCALL_RECV) { - async_req_error(req, EIO); - return; - } - - state->result.result_ssize_t = recv(p->fd, p->buffer, p->length, - p->flags); - state->sys_errno = errno; - - TALLOC_FREE(state->fde); - - async_req_done(req); -} - -/** - * Async version of recv(2) - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] fd The socket to recv from - * @param[in] buffer The buffer to recv into - * @param[in] length How many bytes to recv - * @param[in] flags flags passed to recv(2) - * - * This function is a direct counterpart of recv(2) - */ - -struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - int fd, void *buffer, size_t length, - int flags) -{ - struct async_req *result; - struct async_syscall_state *state; - - result = async_fde_syscall_new( - mem_ctx, ev, ASYNC_SYSCALL_RECV, - fd, TEVENT_FD_READ, async_recv_callback, - &state); - - if (result == NULL) { - return NULL; - } - - state->param.param_recv.fd = fd; - state->param.param_recv.buffer = buffer; - state->param.param_recv.length = length; - state->param.param_recv.flags = flags; - - return result; -} - struct async_send_state { int fd; const void *buf; diff --git a/lib/async_req/async_sock.h b/lib/async_req/async_sock.h index bfc4346d39..e001709d27 100644 --- a/lib/async_req/async_sock.h +++ b/lib/async_req/async_sock.h @@ -25,17 +25,6 @@ bool async_req_is_errno(struct async_req *req, int *err); int async_req_simple_recv_errno(struct async_req *req); -ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno); -size_t async_syscall_result_size_t(struct async_req *req, int *perrno); -int async_syscall_result_int(struct async_req *req, int *perrno); - -struct async_req *async_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - int fd, const void *buffer, size_t length, - int flags); -struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - int fd, void *buffer, size_t length, - int flags); - struct tevent_req *async_send_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, int fd, const void *buf, size_t len, diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index b3d1c6d59a..185a8fa193 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -212,6 +212,15 @@ struct tevent_req { void *private_state; /** + * @brief A function to overwrite the default print function + * + * The implementation doing the work may want to imeplement a + * custom function to print the text representation of the async + * request. + */ + char *(*private_print)(struct tevent_req *req, TALLOC_CTX *mem_ctx); + + /** * @brief Internal state of the request * * Callers should only access this via functions and never directly. @@ -267,6 +276,8 @@ struct tevent_req { } internal; }; +char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx); + char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req); struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, @@ -296,6 +307,9 @@ struct tevent_req *tevent_req_post(struct tevent_req *req, bool tevent_req_is_in_progress(struct tevent_req *req); +bool tevent_req_poll(struct tevent_req *req, + struct tevent_context *ev); + bool tevent_req_is_error(struct tevent_req *req, enum tevent_req_state *state, uint64_t *error); diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c index 800e3855d1..e243c7de5d 100644 --- a/lib/tevent/tevent_req.c +++ b/lib/tevent/tevent_req.c @@ -28,14 +28,17 @@ #include "tevent_util.h" /** - * @brief Print an tevent_req structure in debug messages - * @param[in] mem_ctx The memory context for the result + * @brief The default print function for creating debug messages * @param[in] req The request to be printed + * @param[in] mem_ctx The memory context for the result * @retval Text representation of req * + * The function should not be used by users of the asynx API, + * but custom print function can use it and append custom text + * to the string. */ -char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req) +char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx) { return talloc_asprintf(mem_ctx, "tevent_req[%p/%s]: state[%d] error[%lld (0x%llX)] " @@ -51,6 +54,24 @@ char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req) } /** + * @brief Print an tevent_req structure in debug messages + * @param[in] mem_ctx The memory context for the result + * @param[in] req The request to be printed + * @retval Text representation of req + * + * This function should be used by callers of the async API + */ + +char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req) +{ + if (!req->private_print) { + return tevent_req_default_print(req, mem_ctx); + } + + return req->private_print(req, mem_ctx); +} + +/** * @brief Create an async request * @param[in] mem_ctx The memory context for the result * @param[in] ev The event context this async request will be driven by @@ -235,6 +256,21 @@ bool tevent_req_is_in_progress(struct tevent_req *req) return false; } +bool tevent_req_poll(struct tevent_req *req, + struct tevent_context *ev) +{ + while (tevent_req_is_in_progress(req)) { + int ret; + + ret = tevent_loop_once(ev); + if (ret != 0) { + return false; + } + } + + return true; +} + bool tevent_req_is_error(struct tevent_req *req, enum tevent_req_state *state, uint64_t *error) { |