The branch, master has been updated via a20d41accdc tevent:tests: Test queue entry tags via f681ef2ff48 tevent: Add tevent queue tracing support via dfbb381839e tevent: Use internally an empty trigger function for blocker requests via ddc8f4f4d84 tevent: Move the code below the trigger check via 3198b94a2d0 tevent: Fix trailing whitespaces from be23ffbc5d6 examples: Update winbindd.stp and generate script
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit a20d41accdc999262da94531627c7e1e8ec7677f Author: Pavel Filipenský <pfili...@redhat.com> Date: Wed Mar 16 09:11:25 2022 +0100 tevent:tests: Test queue entry tags Signed-off-by: Pavel Filipenský <pfili...@redhat.com> Reviewed-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> Autobuild-User(master): Andreas Schneider <a...@cryptomilk.org> Autobuild-Date(master): Mon Apr 11 17:51:08 UTC 2022 on sn-devel-184 commit f681ef2ff48b5b48fd1f0a2075184689059cb9a1 Author: Pavel Filipenský <pfili...@redhat.com> Date: Mon Mar 14 11:22:15 2022 +0100 tevent: Add tevent queue tracing support Signed-off-by: Pavel Filipenský <pfili...@redhat.com> Reviewed-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit dfbb381839e9ea179cb53791606d6be08ebac806 Author: Pavel Filipenský <pfili...@redhat.com> Date: Wed Mar 23 14:50:57 2022 +0100 tevent: Use internally an empty trigger function for blocker requests This avoids special magic, but keeps the same external behavior. It makes the following changes easier to understand. Signed-off-by: Pavel Filipenský <pfili...@redhat.com> Reviewed-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit ddc8f4f4d84ca40274463a40e5c16f0542337499 Author: Pavel Filipenský <pfili...@redhat.com> Date: Wed Mar 30 15:59:51 2022 +0200 tevent: Move the code below the trigger check This makes the next commit smaller. Signed-off-by: Pavel Filipenský <pfili...@redhat.com> Reviewed-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 3198b94a2d0b62251fc2d497201a88ac3dbfb31f Author: Pavel Filipenský <pfili...@redhat.com> Date: Mon Mar 14 11:16:58 2022 +0100 tevent: Fix trailing whitespaces Signed-off-by: Pavel Filipenský <pfili...@redhat.com> Reviewed-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> ----------------------------------------------------------------------- Summary of changes: .../ABI/{tevent-0.11.0.sigs => tevent-0.12.0.sigs} | 5 + lib/tevent/tests/test_tevent_tag.c | 41 ++++ lib/tevent/tests/test_tevent_trace.c | 259 +++++++++++++++++++++ lib/tevent/tevent.h | 51 +++- lib/tevent/tevent_debug.c | 32 +++ lib/tevent/tevent_internal.h | 13 +- lib/tevent/tevent_queue.c | 46 +++- lib/tevent/wscript | 2 +- 8 files changed, 438 insertions(+), 11 deletions(-) copy lib/tevent/ABI/{tevent-0.11.0.sigs => tevent-0.12.0.sigs} (96%) Changeset truncated at 500 lines: diff --git a/lib/tevent/ABI/tevent-0.11.0.sigs b/lib/tevent/ABI/tevent-0.12.0.sigs similarity index 96% copy from lib/tevent/ABI/tevent-0.11.0.sigs copy to lib/tevent/ABI/tevent-0.12.0.sigs index e64007e0516..22a8ce33413 100644 --- a/lib/tevent/ABI/tevent-0.11.0.sigs +++ b/lib/tevent/ABI/tevent-0.12.0.sigs @@ -62,10 +62,13 @@ tevent_fd_set_tag: void (struct tevent_fd *, uint64_t) tevent_get_trace_callback: void (struct tevent_context *, tevent_trace_callback_t *, void *) tevent_get_trace_fd_callback: void (struct tevent_context *, tevent_trace_fd_callback_t *, void *) tevent_get_trace_immediate_callback: void (struct tevent_context *, tevent_trace_immediate_callback_t *, void *) +tevent_get_trace_queue_callback: void (struct tevent_context *, tevent_trace_queue_callback_t *, void *) tevent_get_trace_signal_callback: void (struct tevent_context *, tevent_trace_signal_callback_t *, void *) tevent_get_trace_timer_callback: void (struct tevent_context *, tevent_trace_timer_callback_t *, void *) tevent_immediate_get_tag: uint64_t (const struct tevent_immediate *) tevent_immediate_set_tag: void (struct tevent_immediate *, uint64_t) +tevent_queue_entry_get_tag: uint64_t (const struct tevent_queue_entry *) +tevent_queue_entry_set_tag: void (struct tevent_queue_entry *, uint64_t) tevent_loop_allow_nesting: void (struct tevent_context *) tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *) tevent_num_signals: size_t (void) @@ -118,6 +121,7 @@ tevent_set_default_backend: void (const char *) tevent_set_trace_callback: void (struct tevent_context *, tevent_trace_callback_t, void *) tevent_set_trace_fd_callback: void (struct tevent_context *, tevent_trace_fd_callback_t, void *) tevent_set_trace_immediate_callback: void (struct tevent_context *, tevent_trace_immediate_callback_t, void *) +tevent_set_trace_queue_callback: void (struct tevent_context *, tevent_trace_queue_callback_t, void *) tevent_set_trace_signal_callback: void (struct tevent_context *, tevent_trace_signal_callback_t, void *) tevent_set_trace_timer_callback: void (struct tevent_context *, tevent_trace_timer_callback_t, void *) tevent_signal_get_tag: uint64_t (const struct tevent_signal *) @@ -138,6 +142,7 @@ tevent_timeval_until: struct timeval (const struct timeval *, const struct timev tevent_timeval_zero: struct timeval (void) tevent_trace_fd_callback: void (struct tevent_context *, struct tevent_fd *, enum tevent_event_trace_point) tevent_trace_immediate_callback: void (struct tevent_context *, struct tevent_immediate *, enum tevent_event_trace_point) +tevent_trace_queue_callback: void (struct tevent_context *, struct tevent_queue_entry *, enum tevent_event_trace_point) tevent_trace_point_callback: void (struct tevent_context *, enum tevent_trace_point) tevent_trace_signal_callback: void (struct tevent_context *, struct tevent_signal *, enum tevent_event_trace_point) tevent_trace_timer_callback: void (struct tevent_context *, struct tevent_timer *, enum tevent_event_trace_point) diff --git a/lib/tevent/tests/test_tevent_tag.c b/lib/tevent/tests/test_tevent_tag.c index ce64d3c396e..2ae0e386d40 100644 --- a/lib/tevent/tests/test_tevent_tag.c +++ b/lib/tevent/tests/test_tevent_tag.c @@ -33,6 +33,12 @@ #include <tevent.h> #include <cmocka.h> +static void queue_trigger(struct tevent_req *req, void *private_data) +{ + /* Dummy handler. Just return. */ + return; +} + static void fd_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, @@ -197,6 +203,40 @@ static void test_immediate_tag(void **state) TALLOC_FREE(im); } +static void test_queue_entry_tag(void **state) +{ + struct tevent_context *ev = (struct tevent_context *)(*state); + struct tevent_queue *q; + struct tevent_queue_entry *e1, *e2; + struct tevent_req *r1, *r2; + int *s1, *s2; + uint64_t tag; + + q = tevent_queue_create(ev, "test_queue"); + assert_non_null(q); + + r1 = tevent_req_create(ev, &s1, int); + r2 = tevent_req_create(ev, &s2, int); + e1 = tevent_queue_add_entry(q, ev, r1, queue_trigger, NULL); + e2 = tevent_queue_add_entry(q, ev, r2, queue_trigger, NULL); + + tag = tevent_queue_entry_get_tag(e1); + assert_int_equal(0, tag); + tag = tevent_queue_entry_get_tag(e2); + assert_int_equal(0, tag); + + tevent_queue_entry_set_tag(e1, 1); + tevent_queue_entry_set_tag(e2, 2); + + tag = tevent_queue_entry_get_tag(e1); + assert_int_equal(1, tag); + + tag = tevent_queue_entry_get_tag(e2); + assert_int_equal(2, tag); + + TALLOC_FREE(q); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { @@ -204,6 +244,7 @@ int main(int argc, char **argv) cmocka_unit_test_setup_teardown(test_timer_tag, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_signal_tag, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_immediate_tag, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_queue_entry_tag, test_setup, test_teardown), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); diff --git a/lib/tevent/tests/test_tevent_trace.c b/lib/tevent/tests/test_tevent_trace.c index e9d26f9ceba..10e1ee00693 100644 --- a/lib/tevent/tests/test_tevent_trace.c +++ b/lib/tevent/tests/test_tevent_trace.c @@ -280,6 +280,28 @@ static void trace_event_cb(void *event, } } +static void trace_event_cb1(void *event, + enum tevent_event_trace_point point, + void *private_data) +{ + struct test_ctx *tctx = (struct test_ctx *)private_data; + uint64_t tag; + + switch (point) { + case TEVENT_EVENT_TRACE_ATTACH: + tctx->attach = true; + tag = ++tctx->current_tag; + tctx->set_tag(event, tag); + break; + case TEVENT_EVENT_TRACE_BEFORE_HANDLER: + tctx->before_handler = true; + break; + case TEVENT_EVENT_TRACE_DETACH: + tctx->detach = true; + break; + } +} + static int test_setup(void **state) { struct test_ctx *tctx; @@ -371,6 +393,22 @@ static void immediate_set_tag(void *_event, uint64_t tag) tevent_immediate_set_tag(event, tag); } +static uint64_t queue_entry_get_tag(const void *_event) +{ + const struct tevent_queue_entry *event = + (const struct tevent_queue_entry *)_event; + + return tevent_queue_entry_get_tag(event); +} + +static void queue_entry_set_tag(void *_event, uint64_t tag) +{ + struct tevent_queue_entry *event = + (struct tevent_queue_entry *)_event; + + tevent_queue_entry_set_tag(event, tag); +} + static void test_trace_event_fd__loop(void **state) { struct test_ctx *tctx = (struct test_ctx *)(*state); @@ -949,6 +987,203 @@ static void test_trace_event_immediate__reschedule(void **state) assert_true(tctx->detach); } +struct dummy_request_state +{ + int i; + struct tevent_queue_entry *e; +}; + +static void queue_trigger(struct tevent_req *req, void *private_data) +{ + struct test_ctx *tctx = (struct test_ctx *)private_data; + struct dummy_request_state *state = tevent_req_data( + req, struct dummy_request_state); + + tctx->handler_called = true; + assert_int_equal(tevent_queue_entry_get_tag(state->e), state->i); + TALLOC_FREE(req); + + return; +} + +static void test_trace_queue__loop(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_queue *qa, *qb; + struct tevent_req *r1, *r2, *r3, *r4, *r5; + struct dummy_request_state *ds1, *ds2, *ds3, *ds4, *ds5; + + tevent_set_trace_queue_callback( + tctx->ev, + (tevent_trace_queue_callback_t)trace_event_cb1, + tctx); + tctx->get_tag = queue_entry_get_tag; + tctx->set_tag = queue_entry_set_tag; + + qa = tevent_queue_create(tctx->ev, "test_queue A"); + assert_non_null(qa); + qb = tevent_queue_create(tctx->ev, "test_queue B"); + assert_non_null(qb); + + r1 = tevent_req_create(tctx->ev, &ds1, struct dummy_request_state); + ds1->e = tevent_queue_add_entry(qa, + tctx->ev, + r1, + queue_trigger, + *state); + ds1->i = tctx->current_tag; + assert_int_equal(ds1->i, 1); + + r2 = tevent_req_create(tctx->ev, &ds2, struct dummy_request_state); + ds2->e = tevent_queue_add_entry(qa, + tctx->ev, + r2, + queue_trigger, + *state); + ds2->i = tctx->current_tag; + assert_int_equal(ds2->i, 2); + + r3 = tevent_req_create(tctx->ev, &ds3, struct dummy_request_state); + ds3->e = tevent_queue_add_entry(qb, + tctx->ev, + r3, + queue_trigger, + *state); + ds3->i = tctx->current_tag; + assert_int_equal(ds3->i, 3); + + r4 = tevent_req_create(tctx->ev, &ds4, struct dummy_request_state); + ds4->e = tevent_queue_add_entry(qb, + tctx->ev, + r4, + queue_trigger, + *state); + ds4->i = tctx->current_tag; + assert_int_equal(ds4->i, 4); + + r5 = tevent_req_create(tctx->ev, &ds5, struct dummy_request_state); + ds5->e = tevent_queue_add_entry(qa, + tctx->ev, + r5, + queue_trigger, + *state); + ds5->i = tctx->current_tag; + assert_int_equal(ds5->i, 5); + + tevent_loop_once(tctx->ev); + tevent_loop_once(tctx->ev); + tevent_loop_once(tctx->ev); + tevent_loop_once(tctx->ev); + tevent_loop_once(tctx->ev); +} + +static void reset_tctx(struct test_ctx *tctx) +{ + tctx->attach = false; + tctx->before_handler = false; + tctx->handler_called = false; + tctx->detach = false; +} + +static void test_trace_queue__extra(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_queue *qa; + struct tevent_req *r1, *r2, *r3; + struct dummy_request_state *ds1, *ds2, *ds3; + + tevent_set_trace_queue_callback( + tctx->ev, + (tevent_trace_queue_callback_t)trace_event_cb1, + tctx); + tctx->get_tag = queue_entry_get_tag; + tctx->set_tag = queue_entry_set_tag; + + qa = tevent_queue_create(tctx->ev, "test_queue A"); + assert_non_null(qa); + + /* + * r1 - this tests optimize_empty - request is triggered immediately, + * (and not even scheduled to tevent_context). The TALLOC_FREE() called + * from queue_trigger removes the request/queue_entry from the queue qa. + * So qa is empty + */ + r1 = tevent_req_create(tctx->ev, &ds1, struct dummy_request_state); + ds1->e = tevent_queue_add_optimize_empty(qa, + tctx->ev, + r1, + queue_trigger, + *state); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_true(tctx->handler_called); + assert_true(tctx->detach); + assert_int_equal(tevent_queue_length(qa), 0); + + reset_tctx(tctx); + + /* + * Test a blocker request r2 - the trigger function is NULL. + */ + r2 = tevent_req_create(tctx->ev, &ds2, struct dummy_request_state); + ds2->e = tevent_queue_add_entry(qa, tctx->ev, r2, NULL, *state); + ds2->i = tctx->current_tag; + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + assert_int_equal(tevent_queue_length(qa), 1); + + /* + * This runs the tevent_queue_noop_trigger(). + * A blocker r2 is still on the queue head, with triggered==true + */ + tevent_loop_once(tctx->ev); + + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_false(tctx->handler_called); + /* tevent_queue_noop_trigger() is a noop. Does not set handler_called */ + assert_false(tctx->detach); + assert_int_equal(tevent_queue_length(qa), 1); + + /* + * Add a normal request r3. It will be blocked by r2. + */ + r3 = tevent_req_create(tctx->ev, &ds3, struct dummy_request_state); + ds3->e = tevent_queue_add_entry(qa, + tctx->ev, + r3, + queue_trigger, + *state); + ds3->i = tctx->current_tag; + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + assert_int_equal(tevent_queue_length(qa), 2); + + /* + * Remove the blocker r2. + */ + TALLOC_FREE(r2); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_false(tctx->handler_called); + assert_true(tctx->detach); + assert_int_equal(tevent_queue_length(qa), 1); + + reset_tctx(tctx); + + /* Process r3 */ + tevent_loop_once(tctx->ev); + + assert_false(tctx->attach); + assert_true(tctx->before_handler); + assert_true(tctx->handler_called); + assert_true(tctx->detach); +} + static void test_get_set_trace_fd_callback(void **state) { struct test_ctx *tctx = (struct test_ctx *)(*state); @@ -1033,6 +1268,27 @@ static void test_get_set_trace_immediate_callback(void **state) assert_null(pvt); } +static void test_get_set_trace_queue_callback(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + tevent_trace_queue_callback_t cb; + void *pvt; + + tevent_get_trace_queue_callback(tctx->ev, &cb, &pvt); + assert_null(cb); + assert_null(pvt); + + tevent_set_trace_queue_callback(tctx->ev, (tevent_trace_queue_callback_t)trace_event_cb, tctx); + tevent_get_trace_queue_callback(tctx->ev, &cb, &pvt); + assert_ptr_equal(cb, trace_event_cb); + assert_ptr_equal(pvt, tctx); + + tevent_set_trace_queue_callback(tctx->ev, NULL, NULL); + tevent_get_trace_queue_callback(tctx->ev, &cb, &pvt); + assert_null(cb); + assert_null(pvt); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { @@ -1053,10 +1309,13 @@ int main(int argc, char **argv) cmocka_unit_test_setup_teardown(test_trace_event_immediate__free, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_trace_event_immediate__free_in_handler, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_trace_event_immediate__reschedule, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_queue__loop, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_queue__extra, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_get_set_trace_fd_callback, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_get_set_trace_timer_callback, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_get_set_trace_signal_callback, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_get_set_trace_immediate_callback, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_get_set_trace_queue_callback, test_setup, test_teardown), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index 2d1863d7c6e..1c337adbf74 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -1,4 +1,4 @@ -/* +/* Unix SMB/CIFS implementation. generalised event loop handling @@ -1931,6 +1931,55 @@ struct timeval tevent_timeval_current_ofs(uint32_t secs, uint32_t usecs); struct tevent_queue; struct tevent_queue_entry; +/** + * @brief Associate a custom tag with the queue entry. + * + * This tag can be then retrieved with tevent_queue_entry_get_tag() + * + * @param[in] qe The queue entry. + * + * @param[in] tag Custom tag. + */ +void tevent_queue_entry_set_tag(struct tevent_queue_entry *qe, uint64_t tag); + +/** + * @brief Get custom queue entry tag. + */ +uint64_t tevent_queue_entry_get_tag(const struct tevent_queue_entry *qe); + +typedef void (*tevent_trace_queue_callback_t)(struct tevent_queue_entry *qe, + enum tevent_event_trace_point, + void *private_data); + +/** + * Register a callback to be called at certain trace points of queue. + * + * @param[in] ev Event context + * @param[in] cb Trace callback + * @param[in] private_data Data to be passed to callback + * + * @note The callback will be called at trace points defined by + * tevent_event_trace_point. Call with NULL to reset. + */ +void tevent_set_trace_queue_callback(struct tevent_context *ev, + tevent_trace_queue_callback_t cb, + void *private_data); + +/** + * Retrieve the current trace callback of queue. + * + * @param[in] ev Event context + * @param[out] cb Registered trace callback + * @param[out] p_private_data Registered data to be passed to callback + * + * @note This can be used to allow one component that wants to + * register a callback to respect the callback that another component + * has already registered. + */ +void tevent_get_trace_queue_callback(struct tevent_context *ev, + tevent_trace_queue_callback_t *cb, + void *p_private_data); + #ifdef DOXYGEN /** * @brief Create and start a tevent queue. diff --git a/lib/tevent/tevent_debug.c b/lib/tevent/tevent_debug.c index 44f76f789ca..6b8f2d5100b 100644 --- a/lib/tevent/tevent_debug.c +++ b/lib/tevent/tevent_debug.c @@ -260,3 +260,35 @@ void tevent_trace_immediate_callback(struct tevent_context *ev, ev->tracing.im.callback(im, tp, ev->tracing.im.private_data); } } + +void tevent_set_trace_queue_callback(struct tevent_context *ev, + tevent_trace_queue_callback_t cb, + void *private_data) +{ + if (ev->wrapper.glue != NULL) { + ev = tevent_wrapper_main_ev(ev); + tevent_abort(ev, "tevent_set_trace_queue_callback() " + "on wrapper"); + return; + } + + ev->tracing.qe.callback = cb; + ev->tracing.qe.private_data = private_data; +} + +void tevent_get_trace_queue_callback(struct tevent_context *ev, + tevent_trace_queue_callback_t *cb, + void *p_private_data) +{ + *cb = ev->tracing.qe.callback; -- Samba Shared Repository