From 796acbd9ffd20f13f320641b8a27f86624f3d701 Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Tue, 5 Jun 2012 16:00:07 +1000 Subject: lib/tevent: Add trace point callback Set/get a single callback function to be invoked at various trace points. Define "before wait" and "after wait" trace points - more trace points can be added later if required. CTDB wants this to log long waits and events. Pair-programmed-with: Amitay Isaacs Signed-off-by: Martin Schwenke Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent.h | 43 +++++++++++++++++++++++++++++++++++++++++++ lib/tevent/tevent_debug.c | 23 +++++++++++++++++++++++ lib/tevent/tevent_epoll.c | 2 ++ lib/tevent/tevent_internal.h | 8 ++++++++ lib/tevent/tevent_poll.c | 2 ++ lib/tevent/tevent_select.c | 2 ++ lib/tevent/tevent_standard.c | 2 ++ lib/tevent/wscript | 0 8 files changed, 82 insertions(+) mode change 100644 => 100755 lib/tevent/wscript (limited to 'lib') diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index c38f7c36e1..c8719fa4f1 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -501,6 +501,49 @@ int tevent_set_debug(struct tevent_context *ev, */ int tevent_set_debug_stderr(struct tevent_context *ev); +enum tevent_trace_point { + /** + * Corresponds to a trace point just before waiting + */ + TEVENT_TRACE_BEFORE_WAIT, + /** + * Corresponds to a trace point just after waiting + */ + TEVENT_TRACE_AFTER_WAIT, +}; + +typedef void (*tevent_trace_callback_t)(enum tevent_trace_point, + void *private_data); + +/** + * Register a callback to be called at certain trace points + * + * @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_trace_point. Call with NULL to reset. + */ +void tevent_set_trace_callback(struct tevent_context *ev, + tevent_trace_callback_t cb, + void *private_data); + +/** + * Retrieve the current trace callback + * + * @param[in] ev Event context + * @param[out] cb Registered trace callback + * @param[out] 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_callback(struct tevent_context *ev, + tevent_trace_callback_t *cb, + void *private_data); + /** * @} */ diff --git a/lib/tevent/tevent_debug.c b/lib/tevent/tevent_debug.c index 3f4112831a..31da7b9683 100644 --- a/lib/tevent/tevent_debug.c +++ b/lib/tevent/tevent_debug.c @@ -94,3 +94,26 @@ void tevent_debug(struct tevent_context *ev, enum tevent_debug_level level, va_end(ap); } +void tevent_set_trace_callback(struct tevent_context *ev, + tevent_trace_callback_t cb, + void *private_data) +{ + ev->tracing.callback = cb; + ev->tracing.private_data = private_data; +} + +void tevent_get_trace_callback(struct tevent_context *ev, + tevent_trace_callback_t *cb, + void *private_data) +{ + *cb = ev->tracing.callback; + *(void**)private_data = ev->tracing.private_data; +} + +void tevent_trace_point_callback(struct tevent_context *ev, + enum tevent_trace_point tp) +{ + if (ev->tracing.callback != NULL) { + ev->tracing.callback(tp, ev->tracing.private_data); + } +} diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 33e1d3f20f..5f93de2c57 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -264,7 +264,9 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval return 0; } + tevent_trace_point_callback(epoll_ev->ev, TEVENT_TRACE_BEFORE_WAIT); ret = epoll_wait(epoll_ev->epoll_fd, events, MAXEVENTS, timeout); + tevent_trace_point_callback(epoll_ev->ev, TEVENT_TRACE_AFTER_WAIT); if (ret == -1 && errno == EINTR && epoll_ev->ev->signal_events) { if (tevent_common_check_signal(epoll_ev->ev)) { diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h index 472beb5c94..877510f9f4 100644 --- a/lib/tevent/tevent_internal.h +++ b/lib/tevent/tevent_internal.h @@ -258,6 +258,11 @@ struct tevent_context { tevent_nesting_hook hook_fn; void *hook_private; } nesting; + + struct { + tevent_trace_callback_t callback; + void *private_data; + } tracing; }; @@ -313,3 +318,6 @@ bool tevent_poll_init(void); #ifdef HAVE_EPOLL bool tevent_epoll_init(void); #endif + +void tevent_trace_point_callback(struct tevent_context *ev, + enum tevent_trace_point); diff --git a/lib/tevent/tevent_poll.c b/lib/tevent/tevent_poll.c index 2e202aa7ec..7ae3c42188 100644 --- a/lib/tevent/tevent_poll.c +++ b/lib/tevent/tevent_poll.c @@ -201,7 +201,9 @@ static int poll_event_loop_poll(struct tevent_context *ev, timeout += (tvalp->tv_usec + 999) / 1000; } + tevent_trace_point_callback(poll_ev->ev, TEVENT_TRACE_BEFORE_WAIT); pollrtn = poll(poll_ev->fds, poll_ev->num_fds, timeout); + tevent_trace_point_callback(poll_ev->ev, TEVENT_TRACE_AFTER_WAIT); if (pollrtn == -1 && errno == EINTR && ev->signal_events) { tevent_common_check_signal(ev); diff --git a/lib/tevent/tevent_select.c b/lib/tevent/tevent_select.c index 94faa86593..c11f0e8324 100644 --- a/lib/tevent/tevent_select.c +++ b/lib/tevent/tevent_select.c @@ -167,7 +167,9 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru return 0; } + tevent_trace_point_callback(select_ev->ev, TEVENT_TRACE_BEFORE_WAIT); selrtn = select(select_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp); + tevent_trace_point_callback(select_ev->ev, TEVENT_TRACE_AFTER_WAIT); if (selrtn == -1 && errno == EINTR && select_ev->ev->signal_events) { diff --git a/lib/tevent/tevent_standard.c b/lib/tevent/tevent_standard.c index e2ca44f9c2..1e33720f70 100644 --- a/lib/tevent/tevent_standard.c +++ b/lib/tevent/tevent_standard.c @@ -278,7 +278,9 @@ static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tv return 0; } + tevent_trace_point_callback(std_ev->ev, TEVENT_TRACE_BEFORE_WAIT); ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout); + tevent_trace_point_callback(std_ev->ev, TEVENT_TRACE_AFTER_WAIT); if (ret == -1 && errno == EINTR && std_ev->ev->signal_events) { if (tevent_common_check_signal(std_ev->ev)) { diff --git a/lib/tevent/wscript b/lib/tevent/wscript old mode 100644 new mode 100755 -- cgit