From: Philippe Proulx Date: Sat, 27 May 2017 00:50:07 +0000 (-0400) Subject: Add bt_ctf_trace_add_is_static_listener() and ..._remove_is_static_listener() X-Git-Tag: v2.0.0-pre1~136 X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=3602afb05ca664461109fa2d29d4e53db1c13fe2 Add bt_ctf_trace_add_is_static_listener() and ..._remove_is_static_listener() See the functions's documentation for more details. Signed-off-by: Philippe Proulx Signed-off-by: Jérémie Galarneau --- diff --git a/include/babeltrace/ctf-ir/trace-internal.h b/include/babeltrace/ctf-ir/trace-internal.h index b468379a..3f583065 100644 --- a/include/babeltrace/ctf-ir/trace-internal.h +++ b/include/babeltrace/ctf-ir/trace-internal.h @@ -69,6 +69,7 @@ struct bt_ctf_trace { */ int valid; GPtrArray *listeners; /* Array of struct listener_wrapper */ + GArray *is_static_listeners; bt_bool is_static; }; diff --git a/include/babeltrace/ctf-ir/trace.h b/include/babeltrace/ctf-ir/trace.h index e6a3bc47..83e888b4 100644 --- a/include/babeltrace/ctf-ir/trace.h +++ b/include/babeltrace/ctf-ir/trace.h @@ -147,6 +147,20 @@ struct bt_ctf_stream; struct bt_ctf_stream_class; struct bt_ctf_clock_class; +/** +@brief User function type to use with + bt_ctf_trace_add_is_static_listener(). + +@param[in] trace_class Trace class which is now static. +@param[in] data User data as passed to + bt_ctf_trace_add_is_static_listener() when + you added the listener. + +@prenotnull{trace_class} +*/ +typedef void (* bt_ctf_trace_is_static_listener)( + struct bt_ctf_trace *trace_class, void *data); + /** @name Creation function @{ @@ -830,6 +844,10 @@ function on it: - bt_ctf_trace_add_stream_class() - bt_ctf_trace_add_clock_class() +- bt_ctf_trace_set_environment_field() +- bt_ctf_trace_set_environment_field_integer() +- bt_ctf_trace_set_environment_field_string() +- bt_ctf_trace_add_is_static_listener() You cannot create a stream with bt_ctf_stream_create() with any of the stream classes of a static trace class. @@ -843,9 +861,72 @@ stream classes of a static trace class. @sa bt_ctf_trace_is_static(): Checks whether or not a given trace class is static. +@sa bt_ctf_trace_add_is_static_listener(): Adds a listener to a trace + class which is called when the trace class is made static. */ extern int bt_ctf_trace_set_is_static(struct bt_ctf_trace *trace_class); +/** +@brief Adds the listener \p listener to the CTF IR trace class + \p trace_class which is called when the trace is made static. + +\p listener is called with \p data, the user data, the first time +bt_ctf_trace_set_is_static() is called on \p trace_class. + +This function fails if \p trace_class is already static: you need to +check the condition first with bt_ctf_trace_is_static(). + +On success, this function returns a unique numeric identifier for this +listener within \p trace. You can use this identifier to remove the +specific listener you added with +bt_ctf_trace_remove_is_static_listener(). + +@param[in] trace_class Trace class to which to add the listener. +@param[in] listener Listener to add to \p trace_class. +@param[in] data User data passed when \p listener is called. +@returns A unique numeric identifier for this listener + on success (0 or greater), or a negative value + on error. + +@prenotnull{trace_class} +@prenotnull{listener} +@pre \p trace_class is not static. +@postrefcountsame{trace_class} + +@sa bt_ctf_trace_remove_is_static_listener(): Removes a "trace is + static" listener from a trace class previously added with this + function. +@sa bt_ctf_trace_is_static(): Checks whether or not a given trace class + is static. +@sa bt_ctf_trace_set_is_static(): Makes a trace class static. +*/ +extern int bt_ctf_trace_add_is_static_listener( + struct bt_ctf_trace *trace_class, + bt_ctf_trace_is_static_listener listener, void *data); + +/** +@brief Removes the "trace is static" listener identified by + \p listener_id from the trace class \p trace_class. + +@param[in] trace_class Trace class from which to remove the listener + identified by \p listener_id. +@param[in] listener_id Identifier of the listener to remove from + \p trace_class. +@returns 0 if this function removed the listener, or + a negative value on error. + +@prenotnull{trace_class} +@pre \p listener_id is the identifier of a listener that you previously + added with bt_ctf_trace_add_is_static_listener() and did not + already remove with this function. +@postrefcountsame{trace_class} + +@sa bt_ctf_trace_add_is_static_listener(): Adds a listener to a trace + class which is called when the trace class is made static. +*/ +extern int bt_ctf_trace_remove_is_static_listener( + struct bt_ctf_trace *trace_class, int listener_id); + /** @brief Accepts the visitor \p visitor to visit the hierarchy of the CTF IR trace class \p trace_class. diff --git a/lib/ctf-ir/trace.c b/lib/ctf-ir/trace.c index bcba9b1d..fe0d362e 100644 --- a/lib/ctf-ir/trace.c +++ b/lib/ctf-ir/trace.c @@ -62,6 +62,11 @@ struct listener_wrapper { void *data; }; +struct bt_ctf_trace_is_static_listener_elem { + bt_ctf_trace_is_static_listener func; + void *data; +}; + static void bt_ctf_trace_destroy(struct bt_object *obj); static @@ -141,6 +146,13 @@ struct bt_ctf_trace *bt_ctf_trace_create(void) goto error; } + trace->is_static_listeners = g_array_new(FALSE, TRUE, + sizeof(struct bt_ctf_trace_is_static_listener_elem)); + if (!trace->is_static_listeners) { + BT_LOGE_STR("Failed to allocate one GArray."); + goto error; + } + BT_LOGD("Created trace object: addr=%p", trace); return trace; @@ -298,6 +310,10 @@ void bt_ctf_trace_destroy(struct bt_object *obj) g_ptr_array_free(trace->listeners, TRUE); } + if (trace->is_static_listeners) { + g_array_free(trace->is_static_listeners, TRUE); + } + BT_LOGD_STR("Putting packet header field type."); bt_put(trace->packet_header_type); g_free(trace); @@ -2107,6 +2123,7 @@ end: int bt_ctf_trace_set_is_static(struct bt_ctf_trace *trace) { int ret = 0; + size_t i; if (!trace) { BT_LOGW_STR("Invalid parameter: trace is NULL."); @@ -2119,6 +2136,123 @@ int bt_ctf_trace_set_is_static(struct bt_ctf_trace *trace) BT_LOGV("Set trace static: addr=%p, name=\"%s\"", trace, bt_ctf_trace_get_name(trace)); + /* Call all the "trace is static" listeners */ + for (i = 0; i < trace->is_static_listeners->len; i++) { + struct bt_ctf_trace_is_static_listener_elem elem = + g_array_index(trace->is_static_listeners, + struct bt_ctf_trace_is_static_listener_elem, i); + + if (elem.func) { + elem.func(trace, elem.data); + } + } + +end: + return ret; +} + +int bt_ctf_trace_add_is_static_listener(struct bt_ctf_trace *trace, + bt_ctf_trace_is_static_listener listener, void *data) +{ + int i; + struct bt_ctf_trace_is_static_listener_elem new_elem = { + .func = listener, + .data = data, + }; + + if (!trace) { + BT_LOGW_STR("Invalid parameter: trace is NULL."); + i = -1; + goto end; + } + + if (!listener) { + BT_LOGW_STR("Invalid parameter: listener is NULL."); + i = -1; + goto end; + } + + if (trace->is_static) { + BT_LOGW("Invalid parameter: trace is already static: " + "addr=%p, name=\"%s\"", + trace, bt_ctf_trace_get_name(trace)); + i = -1; + goto end; + } + + /* Find the next available spot */ + for (i = 0; i < trace->is_static_listeners->len; i++) { + struct bt_ctf_trace_is_static_listener_elem elem = + g_array_index(trace->is_static_listeners, + struct bt_ctf_trace_is_static_listener_elem, i); + + if (!elem.func) { + break; + } + } + + if (i == trace->is_static_listeners->len) { + g_array_append_val(trace->is_static_listeners, new_elem); + } else { + g_array_insert_val(trace->is_static_listeners, i, new_elem); + } + + BT_LOGV("Added \"trace is static\" listener: " + "trace-addr=%p, trace-name=\"%s\", func-addr=%p, " + "data-addr=%p, listener-id=%d", + trace, bt_ctf_trace_get_name(trace), listener, data, i); + +end: + return i; +} + +int bt_ctf_trace_remove_is_static_listener( + struct bt_ctf_trace *trace, int listener_id) +{ + int ret = 0; + struct bt_ctf_trace_is_static_listener_elem *elem; + + if (!trace) { + BT_LOGW_STR("Invalid parameter: trace is NULL."); + ret = -1; + goto end; + } + + if (listener_id < 0) { + BT_LOGW("Invalid listener ID: must be zero or positive: " + "listener-id=%d", listener_id); + ret = -1; + goto end; + } + + if (listener_id >= trace->is_static_listeners->len) { + BT_LOGW("Invalid parameter: no listener with this listener ID: " + "addr=%p, name=\"%s\", listener-id=%d", + trace, bt_ctf_trace_get_name(trace), + listener_id); + ret = -1; + goto end; + } + + elem = &g_array_index(trace->is_static_listeners, + struct bt_ctf_trace_is_static_listener_elem, + listener_id); + if (!elem->func) { + BT_LOGW("Invalid parameter: no listener with this listener ID: " + "addr=%p, name=\"%s\", listener-id=%d", + trace, bt_ctf_trace_get_name(trace), + listener_id); + ret = -1; + goto end; + } + + elem->func = NULL; + elem->data = NULL; + BT_LOGV("Removed \"trace is static\" listener: " + "trace-addr=%p, trace-name=\"%s\", " + "listener-id=%d", trace, bt_ctf_trace_get_name(trace), + listener_id); + end: return ret; }