The branch, master has been updated via f3262027a3314edda8c0659f7d7b27dbdbea0203 (commit) via 946573aaed89c7f2900e2d5b49ccc6b9389a5e89 (commit) via 113651c517209c5424303331238a2f6913094775 (commit) via f337974ed55ff0217dfb59243574fcdd01e87ffc (commit) via fa2461ae73e5add4b51b9eb6a44a7b7a4cb26a78 (commit) via 1d949fe742f3470010ee032b6b465857cc41d582 (commit) via f131718c607eba5e94e32ae6c4ce81d65ec98718 (commit) via f3c5bd9b776def71517a6395c595f3bd941434eb (commit) via 3c9ad421fb03c70f49ec60666fce592e122d5616 (commit) via 66b2604ef185228bb2ec5b5b0983ea39b55cd17c (commit) from abb96e202b93f044d39b4ed17422248e8c721811 (commit)
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit f3262027a3314edda8c0659f7d7b27dbdbea0203 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Feb 13 18:52:40 2009 +0100 s4:configure: require the same version for external and internal libtevent Until we reach 1.0.0, we better require the exact same version. metze commit 946573aaed89c7f2900e2d5b49ccc6b9389a5e89 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Feb 13 18:51:28 2009 +0100 tevent: raise version to 0.9.3 - aio events are removed - tevent_req infrastructure was added metze commit 113651c517209c5424303331238a2f6913094775 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Feb 13 15:37:35 2009 +0100 lib/tevent: add tevent_req infrastructure This is almost a copy of the async_req code, which will be removed later. metze commit f337974ed55ff0217dfb59243574fcdd01e87ffc Author: Stefan Metzmacher <me...@samba.org> Date: Fri Feb 13 15:43:04 2009 +0100 lib/tevent: add tevent_req.c as copy of lib/async_req/async_req.c metze commit fa2461ae73e5add4b51b9eb6a44a7b7a4cb26a78 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Feb 13 15:36:16 2009 +0100 lib/tevent: expose ev_timeval_zero() for internal usage metze commit 1d949fe742f3470010ee032b6b465857cc41d582 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Feb 13 14:05:41 2009 +0100 lib/tevent: remove broken tevent_aio support It makes no sense to support aio events because, the current implementation was based on IOCB_CMD_EPOLL_WAIT which never made it into the main kernel tree. The native linux aio can be used with select/epoll using eventfd(), which means we can implement aio with fd events and implement aio outside of tevent. metze commit f131718c607eba5e94e32ae6c4ce81d65ec98718 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Feb 13 13:07:58 2009 +0100 s4:lib/socket: add socket_address_copy() metze commit f3c5bd9b776def71517a6395c595f3bd941434eb Author: Stefan Metzmacher <me...@samba.org> Date: Fri Feb 13 11:38:21 2009 +0100 s4:ldb_ildap: remove compiler warnings metze commit 3c9ad421fb03c70f49ec60666fce592e122d5616 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Feb 13 11:37:15 2009 +0100 s4:libcli/ldap: use const char * const *attributes as in all other places metze commit 66b2604ef185228bb2ec5b5b0983ea39b55cd17c Author: Stefan Metzmacher <me...@samba.org> Date: Fri Feb 13 11:35:17 2009 +0100 s4:ntvfs_generic: use talloc_get_type() to remote compiler warnings metze ----------------------------------------------------------------------- Summary of changes: lib/tevent/configure.ac | 2 +- lib/tevent/libtevent.m4 | 12 +- lib/tevent/tevent.c | 19 -- lib/tevent/tevent.h | 185 ++++++++++-- lib/tevent/tevent_aio.c | 545 --------------------------------- lib/tevent/tevent_internal.h | 15 +- lib/tevent/tevent_req.c | 276 +++++++++++++++++ lib/tevent/tevent_timed.c | 2 +- source3/samba4.m4 | 2 +- source4/configure.ac | 2 +- source4/lib/ldb/ldb_ildap/ldb_ildap.c | 13 +- source4/lib/socket/socket.c | 33 ++ source4/lib/socket/socket.h | 2 + source4/libcli/ldap/ldap.h | 2 +- source4/libcli/ldap/ldap_ildap.c | 2 +- source4/ntvfs/ntvfs_generic.c | 8 +- 16 files changed, 496 insertions(+), 624 deletions(-) delete mode 100644 lib/tevent/tevent_aio.c create mode 100644 lib/tevent/tevent_req.c Changeset truncated at 500 lines: diff --git a/lib/tevent/configure.ac b/lib/tevent/configure.ac index 3cc06a1..4333461 100644 --- a/lib/tevent/configure.ac +++ b/lib/tevent/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.50) -AC_INIT(tevent, 0.9.2) +AC_INIT(tevent, 0.9.3) AC_CONFIG_SRCDIR([tevent.c]) AC_CONFIG_HEADER(config.h) diff --git a/lib/tevent/libtevent.m4 b/lib/tevent/libtevent.m4 index ec2ed9c..cbfb981 100644 --- a/lib/tevent/libtevent.m4 +++ b/lib/tevent/libtevent.m4 @@ -26,23 +26,13 @@ AC_SUBST(TEVENT_LIBS) TEVENT_CFLAGS="-I$teventdir" -TEVENT_OBJ="tevent.o tevent_fd.o tevent_timed.o tevent_signal.o tevent_debug.o tevent_util.o" +TEVENT_OBJ="tevent.o tevent_fd.o tevent_timed.o tevent_signal.o tevent_req.o tevent_debug.o tevent_util.o" TEVENT_OBJ="$TEVENT_OBJ tevent_standard.o tevent_select.o" -tevent_cv_aio_support=no AC_CHECK_HEADERS(sys/epoll.h) AC_CHECK_FUNCS(epoll_create) if test x"$ac_cv_header_sys_epoll_h" = x"yes" -a x"$ac_cv_func_epoll_create" = x"yes"; then TEVENT_OBJ="$TEVENT_OBJ tevent_epoll.o" AC_DEFINE(HAVE_EPOLL, 1, [Whether epoll available]) - - # check for native Linux AIO interface - AC_CHECK_HEADERS(libaio.h) - AC_CHECK_LIB_EXT(aio, TEVENT_LIBS, io_getevents) - if test x"$ac_cv_header_libaio_h" = x"yes" -a x"$ac_cv_lib_ext_aio_io_getevents" = x"yes";then - TEVENT_OBJ="$TEVENT_OBJ tevent_aio.o" - tevent_cv_aio_support=yes - AC_DEFINE(HAVE_LINUX_AIO, 1, [Whether Linux AIO is available]) - fi fi diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c index ea16fa1..4b22e33 100644 --- a/lib/tevent/tevent.c +++ b/lib/tevent/tevent.c @@ -112,9 +112,6 @@ static void tevent_backend_init(void) #ifdef HAVE_EPOLL tevent_epoll_init(); #endif -#ifdef HAVE_LINUX_AIO - tevent_aio_init(); -#endif } /* @@ -260,22 +257,6 @@ struct tevent_fd *_tevent_add_fd(struct tevent_context *ev, } /* - add a disk aio event -*/ -struct tevent_aio *_tevent_add_aio(struct tevent_context *ev, - TALLOC_CTX *mem_ctx, - struct iocb *iocb, - tevent_aio_handler_t handler, - void *private_data, - const char *handler_name, - const char *location) -{ - if (ev->ops->add_aio == NULL) return NULL; - return ev->ops->add_aio(ev, mem_ctx, iocb, handler, private_data, - handler_name, location); -} - -/* set a close function on the fd event */ void tevent_fd_set_close_fn(struct tevent_fd *fde, diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index de02c00..2ab1864 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -4,6 +4,8 @@ generalised event loop handling Copyright (C) Andrew Tridgell 2005 + Copyright (C) Stefan Metzmacher 2005-2009 + Copyright (C) Volker Lendecke 2008 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,7 +32,6 @@ struct tevent_context; struct tevent_ops; struct tevent_fd; struct tevent_timer; -struct tevent_aio; struct tevent_signal; /* event handler types */ @@ -52,10 +53,6 @@ typedef void (*tevent_signal_handler_t)(struct tevent_context *ev, int count, void *siginfo, void *private_data); -typedef void (*tevent_aio_handler_t)(struct tevent_context *ev, - struct tevent_aio *ae, - int ret, - void *private_data); struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx); struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx, const char *name); @@ -97,18 +94,6 @@ struct tevent_signal *_tevent_add_signal(struct tevent_context *ev, _tevent_add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data, \ #handler, __location__) -struct iocb; -struct tevent_aio *_tevent_add_aio(struct tevent_context *ev, - TALLOC_CTX *mem_ctx, - struct iocb *iocb, - tevent_aio_handler_t handler, - void *private_data, - const char *handler_name, - const char *location); -#define tevent_add_aio(ev, mem_ctx, iocb, handler, private_data) \ - _tevent_add_aio(ev, mem_ctx, iocb, handler, private_data, \ - #handler, __location__) - int tevent_loop_once(struct tevent_context *ev); int tevent_loop_wait(struct tevent_context *ev); @@ -148,18 +133,177 @@ int tevent_set_debug(struct tevent_context *ev, void *context); int tevent_set_debug_stderr(struct tevent_context *ev); +/** + * An async request moves between the following 4 states: + */ +enum tevent_req_state { + /** + * we are creating the request + */ + TEVENT_REQ_INIT, + /** + * we are waiting the request to complete + */ + TEVENT_REQ_IN_PROGRESS, + /** + * the request is finished + */ + TEVENT_REQ_DONE, + /** + * A user error has occured + */ + TEVENT_REQ_USER_ERROR, + /** + * Request timed out + */ + TEVENT_REQ_TIMED_OUT, + /** + * No memory in between + */ + TEVENT_REQ_NO_MEMORY +}; + +/** + * @brief An async request + * + * This represents an async request being processed by callbacks via an event + * context. A user can issue for example a write request to a socket, giving + * an implementation function the fd, the buffer and the number of bytes to + * transfer. The function issuing the request will immediately return without + * blocking most likely without having sent anything. The API user then fills + * in req->async.fn and req->async.private_data, functions that are called + * when the request is finished. + * + * It is up to the user of the async request to talloc_free it after it has + * finished. This can happen while the completion function is called. + */ + +struct tevent_req { + /** + * @brief What to do on completion + * + * This is used for the user of an async request, fn is called when + * the request completes, either successfully or with an error. + */ + struct { + /** + * @brief Completion function + * Completion function, to be filled by the API user + */ + void (*fn)(struct tevent_req *); + /** + * @brief Private data for the completion function + */ + void *private_data; + } async; + + /** + * @brief Private state pointer for the actual implementation + * + * The implementation doing the work for the async request needs a + * current state like for example a fd event. The user of an async + * request should not touch this. + */ + void *private_state; + + /** + * @brief Internal state of the request + * + * Callers should only access this via functions and never directly. + */ + struct { + /** + * @brief The talloc type of the private_state pointer + * + * This is filled by the tevent_req_create() macro. + * + * This for debugging only. + */ + const char *private_type; + + /** + * @brief The location where the request was created + * + * This uses the __location__ macro via the tevent_req_create() + * macro. + * + * This for debugging only. + */ + const char *location; + + /** + * @brief The external state - will be queried by the caller + * + * While the async request is being processed, state will remain in + * TEVENT_REQ_IN_PROGRESS. A request is finished if + * req->state>=TEVENT_REQ_DONE. + */ + enum tevent_req_state state; + + /** + * @brief status code when finished + * + * This status can be queried in the async completion function. It + * will be set to 0 when everything went fine. + */ + uint64_t error; + + /** + * @brief the timer event if tevent_req_post was used + * + */ + struct tevent_timer *trigger; + + /** + * @brief the timer event if tevent_req_set_timeout was used + * + */ + struct tevent_timer *timer; + } internal; +}; + +struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, + void *pstate, + size_t state_size, + const char *type, + const char *location); + +#define tevent_req_create(_mem_ctx, _pstate, _type) \ + _tevent_req_create((_mem_ctx), (_pstate), sizeof(_type), \ + #_type, __location__) + +bool tevent_req_set_timeout(struct tevent_req *req, + struct tevent_context *ev, + struct timeval endtime); + +void tevent_req_done(struct tevent_req *req); + +bool tevent_req_error(struct tevent_req *req, + uint64_t error); + +bool tevent_req_nomem(const void *p, + struct tevent_req *req); + +struct tevent_req *tevent_req_post(struct tevent_req *req, + struct tevent_context *ev); + +bool tevent_req_is_in_progress(struct tevent_req *req); + +bool tevent_req_is_error(struct tevent_req *req, + enum tevent_req_state *state, + uint64_t *error); + + #ifdef TEVENT_COMPAT_DEFINES #define event_context tevent_context #define event_ops tevent_ops #define fd_event tevent_fd #define timed_event tevent_timer -#define aio_event tevent_aio #define signal_event tevent_signal #define event_fd_handler_t tevent_fd_handler_t #define event_timed_handler_t tevent_timer_handler_t -#define event_aio_handler_t tevent_aio_handler_t #define event_signal_handler_t tevent_signal_handler_t #define event_context_init(mem_ctx) \ @@ -183,9 +327,6 @@ int tevent_set_debug_stderr(struct tevent_context *ev); #define event_add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data) \ tevent_add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data) -#define event_add_aio(ev, mem_ctx, iocb, handler, private_data) \ - tevent_add_aio(ev, mem_ctx, iocb, handler, private_data) - #define event_loop_once(ev) \ tevent_loop_once(ev) diff --git a/lib/tevent/tevent_aio.c b/lib/tevent/tevent_aio.c deleted file mode 100644 index 330794f..0000000 --- a/lib/tevent/tevent_aio.c +++ /dev/null @@ -1,545 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - main select loop and event handling - aio/epoll hybrid implementation - - Copyright (C) Andrew Tridgell 2006 - - based on events_standard.c - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ -/* - this is a very strange beast. The Linux AIO implementation doesn't - yet integrate properly with epoll, but there is a kernel patch that - allows the aio wait primitives to be used to wait for epoll events, - and this can be used to give us a unified event system incorporating - both aio events and epoll events - - this is _very_ experimental code -*/ - -#include "replace.h" -#include "system/filesys.h" -#include "system/select.h" -#include "tevent.h" -#include "tevent_internal.h" -#include "tevent_util.h" -#include <libaio.h> - -#define MAX_AIO_QUEUE_DEPTH 100 -#ifndef IOCB_CMD_EPOLL_WAIT -#define IOCB_CMD_EPOLL_WAIT 9 -#endif - -struct aio_event_context { - /* a pointer back to the generic event_context */ - struct tevent_context *ev; - - uint32_t destruction_count; - - io_context_t ioctx; - - struct epoll_event epevent[MAX_AIO_QUEUE_DEPTH]; - - struct iocb *epoll_iocb; - - int epoll_fd; - int is_epoll_set; - pid_t pid; -}; - -struct tevent_aio { - struct tevent_context *event_ctx; - struct iocb iocb; - void *private_data; - tevent_aio_handler_t handler; -}; - -/* - map from EVENT_FD_* to EPOLLIN/EPOLLOUT -*/ -static uint32_t epoll_map_flags(uint16_t flags) -{ - uint32_t ret = 0; - if (flags & TEVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP); - if (flags & TEVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP); - return ret; -} - -/* - free the epoll fd -*/ -static int aio_ctx_destructor(struct aio_event_context *aio_ev) -{ - io_queue_release(aio_ev->ioctx); - close(aio_ev->epoll_fd); - aio_ev->epoll_fd = -1; - return 0; -} - -static void epoll_add_event(struct aio_event_context *aio_ev, struct tevent_fd *fde); - -/* - reopen the epoll handle when our pid changes - see http://junkcode.samba.org/ftp/unpacked/junkcode/epoll_fork.c for an - demonstration of why this is needed - */ -static void epoll_check_reopen(struct aio_event_context *aio_ev) -{ - struct tevent_fd *fde; - - if (aio_ev->pid == getpid()) { - return; - } - - close(aio_ev->epoll_fd); - aio_ev->epoll_fd = epoll_create(MAX_AIO_QUEUE_DEPTH); - if (aio_ev->epoll_fd == -1) { - tevent_debug(aio_ev->ev, TEVENT_DEBUG_FATAL, - "Failed to recreate epoll handle after fork\n"); - return; - } - aio_ev->pid = getpid(); - for (fde=aio_ev->ev->fd_events;fde;fde=fde->next) { - epoll_add_event(aio_ev, fde); - } -} - -#define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT (1<<0) -#define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1) -#define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2) - -/* - add the epoll event to the given fd_event -*/ -static void epoll_add_event(struct aio_event_context *aio_ev, struct tevent_fd *fde) -{ - struct epoll_event event; - if (aio_ev->epoll_fd == -1) return; - - fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; - - /* if we don't want events yet, don't add an aio_event */ - if (fde->flags == 0) return; - - memset(&event, 0, sizeof(event)); - event.events = epoll_map_flags(fde->flags); - event.data.ptr = fde; - epoll_ctl(aio_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event); - fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; - - /* only if we want to read we want to tell the event handler about errors */ - if (fde->flags & TEVENT_FD_READ) { - fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; - } -} - -/* - delete the epoll event for given fd_event -*/ -static void epoll_del_event(struct aio_event_context *aio_ev, struct tevent_fd *fde) -{ - struct epoll_event event; - - if (aio_ev->epoll_fd == -1) return; - - fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; - - /* if there's no aio_event, we don't need to delete it */ - if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT)) return; - - ZERO_STRUCT(event); - event.events = epoll_map_flags(fde->flags); - event.data.ptr = fde; - epoll_ctl(aio_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event); - - fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; -} - -/* - change the epoll event to the given fd_event -*/ -static void epoll_mod_event(struct aio_event_context *aio_ev, struct tevent_fd *fde) -{ - struct epoll_event event; -- Samba Shared Repository