diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2009-03-01 16:39:35 +0100 |
---|---|---|
committer | Jelmer Vernooij <jelmer@samba.org> | 2009-03-01 16:39:35 +0100 |
commit | 09ac816b36e45fd537af2f7fe7c57a11f5c744f5 (patch) | |
tree | 4d5d44c27a2395a39efc62359f6e4b6976f2ba2e /lib/tevent | |
parent | 235244f4cc707130dd130afce88bde49606bd501 (diff) | |
parent | 54bc27e9374742d37b1ed9012d1cfe8f5ace6d40 (diff) | |
download | samba-09ac816b36e45fd537af2f7fe7c57a11f5c744f5.tar.gz samba-09ac816b36e45fd537af2f7fe7c57a11f5c744f5.tar.bz2 samba-09ac816b36e45fd537af2f7fe7c57a11f5c744f5.zip |
Merge branch 'master' of git://git.samba.org/samba into teventfix
Conflicts:
lib/tevent/pytevent.c
Diffstat (limited to 'lib/tevent')
-rw-r--r-- | lib/tevent/libtevent.m4 | 2 | ||||
-rw-r--r-- | lib/tevent/tevent.h | 37 | ||||
-rw-r--r-- | lib/tevent/tevent_queue.c | 198 | ||||
-rw-r--r-- | lib/tevent/tevent_req.c | 42 |
4 files changed, 275 insertions, 4 deletions
diff --git a/lib/tevent/libtevent.m4 b/lib/tevent/libtevent.m4 index 29a64ae3b3..c316823a71 100644 --- a/lib/tevent/libtevent.m4 +++ b/lib/tevent/libtevent.m4 @@ -27,7 +27,7 @@ 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_OBJ tevent_req.o tevent_wakeup.o" +TEVENT_OBJ="$TEVENT_OBJ tevent_req.o tevent_wakeup.o tevent_queue.o" TEVENT_OBJ="$TEVENT_OBJ tevent_standard.o tevent_select.o" AC_CHECK_HEADERS(sys/epoll.h) diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index 16fac7327f..8c119ffb8e 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -31,6 +31,7 @@ #include <stdint.h> #include <talloc.h> #include <sys/time.h> +#include <stdbool.h> struct tevent_context; struct tevent_ops; @@ -211,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. @@ -266,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, @@ -295,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); @@ -323,6 +338,28 @@ struct timeval tevent_timeval_add(const struct timeval *tv, uint32_t secs, struct timeval tevent_timeval_current_ofs(uint32_t secs, uint32_t usecs); +struct tevent_queue; + +struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx, + const char *name, + const char *location); + +#define tevent_queue_create(_mem_ctx, _name) \ + _tevent_queue_create((_mem_ctx), (_name), __location__) + +typedef void (*tevent_queue_trigger_fn_t)(struct tevent_req *req, + void *private_data); +bool tevent_queue_add(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data); +bool tevent_queue_start(struct tevent_queue *queue, + struct tevent_context *ev); +void tevent_queue_stop(struct tevent_queue *queue); + +size_t tevent_queue_length(struct tevent_queue *queue); + #ifdef TEVENT_COMPAT_DEFINES #define event_context tevent_context diff --git a/lib/tevent/tevent_queue.c b/lib/tevent/tevent_queue.c new file mode 100644 index 0000000000..6c8fbe4f95 --- /dev/null +++ b/lib/tevent/tevent_queue.c @@ -0,0 +1,198 @@ +/* + Unix SMB/CIFS implementation. + Infrastructure for async requests + Copyright (C) Volker Lendecke 2008 + Copyright (C) Stefan Metzmacher 2009 + + ** NOTE! The following LGPL license applies to the tevent + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +struct tevent_queue_entry { + struct tevent_queue_entry *prev, *next; + struct tevent_queue *queue; + + bool triggered; + + struct tevent_req *req; + + tevent_queue_trigger_fn_t trigger; + void *private_data; +}; + +struct tevent_queue { + const char *name; + const char *location; + + bool running; + struct tevent_timer *timer; + + size_t length; + struct tevent_queue_entry *list; +}; + +static int tevent_queue_entry_destructor(struct tevent_queue_entry *e) +{ + struct tevent_queue *q = e->queue; + + if (!q) { + return 0; + } + + DLIST_REMOVE(q->list, e); + q->length--; + + if (e->triggered && + q->running && + q->list) { + q->list->triggered = true; + q->list->trigger(q->list->req, + q->list->private_data); + } + + return 0; +} + +static int tevent_queue_destructor(struct tevent_queue *q) +{ + q->running = false; + + while (q->list) { + struct tevent_queue_entry *e = q->list; + talloc_free(e); + } + + return 0; +} + +struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx, + const char *name, + const char *location) +{ + struct tevent_queue *queue; + + queue = talloc_zero(mem_ctx, struct tevent_queue); + if (!queue) { + return NULL; + } + + queue->name = talloc_strdup(queue, name); + if (!queue->name) { + talloc_free(queue); + return NULL; + } + + queue->location = location; + + /* queue is running by default */ + queue->running = true; + + talloc_set_destructor(queue, tevent_queue_destructor); + return queue; +} + +static void tevent_queue_timer_start(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval now, + void *private_data) +{ + struct tevent_queue *q = talloc_get_type(private_data, + struct tevent_queue); + + talloc_free(te); + q->timer = NULL; + + q->list->triggered = true; + q->list->trigger(q->list->req, q->list->private_data); +} + +bool tevent_queue_add(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data) +{ + struct tevent_queue_entry *e; + + e = talloc_zero(req, struct tevent_queue_entry); + if (e == NULL) { + return false; + } + + e->queue = queue; + e->req = req; + e->trigger = trigger; + e->private_data = private_data; + + if (queue->running && + !queue->timer && + !queue->list) { + queue->timer = tevent_add_timer(ev, queue, tevent_timeval_zero(), + tevent_queue_timer_start, + queue); + if (!queue->timer) { + talloc_free(e); + return false; + } + } + + DLIST_ADD_END(queue->list, e, struct tevent_queue_entry *); + queue->length++; + talloc_set_destructor(e, tevent_queue_entry_destructor); + + return true; +} + +bool tevent_queue_start(struct tevent_queue *queue, + struct tevent_context *ev) +{ + if (queue->running) { + /* already started */ + return true; + } + + if (!queue->timer && + queue->list) { + queue->timer = tevent_add_timer(ev, queue, tevent_timeval_zero(), + tevent_queue_timer_start, + queue); + if (!queue->timer) { + return false; + } + } + + queue->running = true; + + return true; +} + +void tevent_queue_stop(struct tevent_queue *queue) +{ + queue->running = false; + talloc_free(queue->timer); + queue->timer = NULL; +} + +size_t tevent_queue_length(struct tevent_queue *queue) +{ + return queue->length; +} 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) { |