From 9e3178e8387cd85858a145bb4918073f91127d20 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 25 Feb 2009 10:54:19 +0100 Subject: Attempt to fix the OpenChange build -- sorry for the break --- lib/tevent/tevent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/tevent') diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index 33747f0986..b3d1c6d59a 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -31,7 +31,7 @@ #include #include #include -#include <../lib/replace/replace.h> +#include struct tevent_context; struct tevent_ops; -- cgit From 13ac0dc4565b1cbdb977b6959562f3f8f9ac5ff8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 25 Feb 2009 13:53:19 +0100 Subject: tevent: add tevent_req_poll() function metze --- lib/tevent/tevent.h | 3 +++ lib/tevent/tevent_req.c | 15 +++++++++++++++ 2 files changed, 18 insertions(+) (limited to 'lib/tevent') diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index b3d1c6d59a..b3611228aa 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -296,6 +296,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..c17587b16c 100644 --- a/lib/tevent/tevent_req.c +++ b/lib/tevent/tevent_req.c @@ -235,6 +235,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) { -- cgit From e2f37ec106fb51ec894e0d6160949545e80dfe69 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 25 Feb 2009 14:29:31 +0100 Subject: tevent: add private_print function feature to tevent_req metze --- lib/tevent/tevent.h | 11 +++++++++++ lib/tevent/tevent_req.c | 27 ++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 3 deletions(-) (limited to 'lib/tevent') diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index b3611228aa..185a8fa193 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -211,6 +211,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 * @@ -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, diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c index c17587b16c..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)] " @@ -50,6 +53,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 -- cgit From 3a1f24f286d4dba836b750122f571f831a794e4a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 17 Feb 2009 11:42:01 +0100 Subject: tevent: add tevent_queue infrastructure metze --- lib/tevent/libtevent.m4 | 2 +- lib/tevent/tevent.h | 22 ++++++ lib/tevent/tevent_queue.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 lib/tevent/tevent_queue.c (limited to 'lib/tevent') 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 185a8fa193..8c119ffb8e 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -338,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 . +*/ + +#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; +} -- cgit From 235244f4cc707130dd130afce88bde49606bd501 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 1 Mar 2009 16:38:07 +0100 Subject: Avoid using tevent_util.h, which won't be available if we use the system tevent. --- lib/tevent/pytevent.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/tevent') diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index 4c0cbfd3cd..fe7e7e3e38 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -29,7 +29,6 @@ #include #include -#include typedef struct { PyObject_HEAD @@ -54,7 +53,8 @@ static PyObject *py_backend_list(PyObject *self) PyObject *ret; int i, len; - len = ev_str_list_length(backends); + for (len = 0; backends[len]; len++); + ret = PyList_New(len); for (i = 0; i < len; i++) PyList_SetItem(ret, i, PyString_FromString(backends[i])); -- cgit From 67d41d0fc7567cf141b12e866dd227d393e33551 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 28 Feb 2009 15:44:30 -0500 Subject: Make struct tevent_req opaque Move struct tevent_req in tevent_internal, and ad getters and setters for private data and the callback function. This patch also renames 'private_state' into 'data'. What is held in this pointer is in fact data and not a state like enum tevent_req_state. Calling it 'state' is confusing. The functions addedd are: tevent_req_set_callback() - sets req->async.fn and req->async.private_data tevent_req_set_print_fn() - sets req->private_print tevent_req_callback_data() - gets req->async.private_data tevent_req_data() - gets rea->data This way it is much simpler to keep API/ABI compatibility in the future. --- lib/tevent/tevent.h | 102 ++++++------------------------------------- lib/tevent/tevent_internal.h | 93 +++++++++++++++++++++++++++++++++++++++ lib/tevent/tevent_req.c | 42 +++++++++++++----- 3 files changed, 137 insertions(+), 100 deletions(-) (limited to 'lib/tevent') diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index 8c119ffb8e..5089d18ec2 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -183,98 +183,22 @@ enum tevent_req_state { * 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; +struct tevent_req; - /** - * @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; +typedef void (*tevent_req_fn)(struct tevent_req *); - /** - * @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); +void tevent_req_set_callback(struct tevent_req *req, tevent_req_fn fn, void *pvt); +void *_tevent_req_callback_data(struct tevent_req *req); +void *_tevent_req_data(struct tevent_req *req); - /** - * @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; -}; +#define tevent_req_callback_data(_req, _type) \ + talloc_get_type_abort(_tevent_req_callback_data(_req), _type) +#define tevent_req_data(_req, _type) \ + talloc_get_type_abort(_tevent_req_data(_req), _type) + +typedef char *(*tevent_req_print_fn)(struct tevent_req *, TALLOC_CTX *); + +void tevent_req_set_print_fn(struct tevent_req *req, tevent_req_print_fn fn); char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx); diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h index 758bdb4628..fa73b22a48 100644 --- a/lib/tevent/tevent_internal.h +++ b/lib/tevent/tevent_internal.h @@ -25,6 +25,99 @@ License along with this library; if not, see . */ +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 + */ + tevent_req_fn fn; + /** + * @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 to + * keep around current data like for example a fd event. The user of + * an async request should not touch this. + */ + void *data; + + /** + * @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. + */ + tevent_req_print_fn private_print; + + /** + * @brief Internal state of the request + * + * Callers should only access this via functions and never directly. + */ + struct { + /** + * @brief The talloc type of the data 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_ops { /* conntext init */ int (*context_init)(struct tevent_context *ev); diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c index e243c7de5d..9b3e00ec8f 100644 --- a/lib/tevent/tevent_req.c +++ b/lib/tevent/tevent_req.c @@ -47,8 +47,8 @@ char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx) req->internal.state, (unsigned long long)req->internal.error, (unsigned long long)req->internal.error, - talloc_get_name(req->private_state), - req->private_state, + talloc_get_name(req->data), + req->data, req->internal.timer ); } @@ -81,14 +81,14 @@ char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req) */ struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, - void *pstate, - size_t state_size, + void *pdata, + size_t data_size, const char *type, const char *location) { struct tevent_req *req; - void **ppstate = (void **)pstate; - void *state; + void **ppdata = (void **)pdata; + void *data; req = talloc_zero(mem_ctx, struct tevent_req); if (req == NULL) { @@ -98,16 +98,16 @@ struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, req->internal.location = location; req->internal.state = TEVENT_REQ_IN_PROGRESS; - state = talloc_size(req, state_size); - if (state == NULL) { + data = talloc_size(req, data_size); + if (data == NULL) { talloc_free(req); return NULL; } - talloc_set_name_const(state, type); + talloc_set_name_const(data, type); - req->private_state = state; + req->data = data; - *ppstate = state; + *ppdata = data; return req; } @@ -314,3 +314,23 @@ bool tevent_req_set_endtime(struct tevent_req *req, return true; } +void tevent_req_set_callback(struct tevent_req *req, tevent_req_fn fn, void *pvt) +{ + req->async.fn = fn; + req->async.private_data = pvt; +} + +void *_tevent_req_callback_data(struct tevent_req *req) +{ + return req->async.private_data; +} + +void *_tevent_req_data(struct tevent_req *req) +{ + return req->data; +} + +void tevent_req_set_print_fn(struct tevent_req *req, tevent_req_print_fn fn) +{ + req->private_print = fn; +} -- cgit