lib/tevent: Add trace point callback
authorMartin Schwenke <martin@meltin.net>
Tue, 5 Jun 2012 06:00:07 +0000 (16:00 +1000)
committerStefan Metzmacher <metze@samba.org>
Fri, 8 Jun 2012 17:00:05 +0000 (19:00 +0200)
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 <amitay@gmail.com>
Signed-off-by: Martin Schwenke <martin@meltin.net>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
lib/tevent/tevent.h
lib/tevent/tevent_debug.c
lib/tevent/tevent_epoll.c
lib/tevent/tevent_internal.h
lib/tevent/tevent_poll.c
lib/tevent/tevent_select.c
lib/tevent/tevent_standard.c
lib/tevent/wscript [changed mode: 0644->0755]

index c38f7c36e17c2d91c51c208ece0191428b299cf0..c8719fa4f194cdaeca7a448ce84fa5bf8f80ceb0 100644 (file)
@@ -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);
+
 /**
  * @}
  */
index 3f4112831a6ff32f6b2c7c42ac5225459cc934c3..31da7b968366cad509e33bcb8e40caf4455d70ca 100644 (file)
@@ -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);
+       }
+}
index 33e1d3f20fffe6b6c0a970c9516591dfb78375c0..5f93de2c578af7c5d8f1dad9f38da393909110a7 100644 (file)
@@ -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)) {
index 472beb5c94ab08a6a3608549ad2f5e35c4011d71..877510f9f43b67b11d925b9efb25991b3fbad6d2 100644 (file)
@@ -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);
index 2e202aa7ec266fe9bc645a15dd603c9f57676992..7ae3c42188de1aec1b8e70d26cb9c8bbf9683f42 100644 (file)
@@ -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);
index 94faa8659340a7d5ab1bb4d0833520a8b56ebe09..c11f0e8324c9042bfb1b3c9b8f0f0e66564410c5 100644 (file)
@@ -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) {
index e2ca44f9c2950a5da998d6aa5d40720d1fd7a9d9..1e33720f7037d21617222bf531394f38fc648cc0 100644 (file)
@@ -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)) {
old mode 100644 (file)
new mode 100755 (executable)