From 8bf65fbd5d6164488f1912f88ef632a58598ed2f Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Sat, 4 Jun 2016 12:20:07 -0400 Subject: [PATCH] Add CTF-IR visitor interface MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérémie Galarneau --- formats/ctf/ir/Makefile.am | 3 +- formats/ctf/ir/stream-class.c | 45 +++++++ formats/ctf/ir/trace.c | 74 +++++++++++ formats/ctf/ir/visitor.c | 96 +++++++++++++++ include/Makefile.am | 7 +- include/babeltrace/ctf-ir/stream-class.h | 15 +++ include/babeltrace/ctf-ir/trace.h | 17 +++ include/babeltrace/ctf-ir/visitor-internal.h | 51 ++++++++ include/babeltrace/ctf-ir/visitor.h | 80 ++++++++++++ .../plugin/notification/notification.h | 11 +- .../babeltrace/plugin/notification/schema.h | 115 ++++++++++++++++++ 11 files changed, 510 insertions(+), 4 deletions(-) create mode 100644 formats/ctf/ir/visitor.c create mode 100644 include/babeltrace/ctf-ir/visitor-internal.h create mode 100644 include/babeltrace/ctf-ir/visitor.h create mode 100644 include/babeltrace/plugin/notification/schema.h diff --git a/formats/ctf/ir/Makefile.am b/formats/ctf/ir/Makefile.am index b9048bc5..4a8c5344 100644 --- a/formats/ctf/ir/Makefile.am +++ b/formats/ctf/ir/Makefile.am @@ -16,7 +16,8 @@ libctf_ir_la_SOURCES = \ trace.c \ utils.c \ resolve.c \ - validation.c + validation.c \ + visitor.c libctf_ir_la_LIBADD = \ $(top_builddir)/lib/libbabeltrace.la diff --git a/formats/ctf/ir/stream-class.c b/formats/ctf/ir/stream-class.c index 326e759e..cddbb979 100644 --- a/formats/ctf/ir/stream-class.c +++ b/formats/ctf/ir/stream-class.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -697,6 +698,50 @@ void bt_ctf_stream_class_put(struct bt_ctf_stream_class *stream_class) bt_put(stream_class); } +static +int get_event_class_count(void *element) +{ + return bt_ctf_stream_class_get_event_class_count( + (struct bt_ctf_stream_class *) element); +} + +static +void *get_event_class(void *element, int i) +{ + return bt_ctf_stream_class_get_event_class( + (struct bt_ctf_stream_class *) element, i); +} + +static +int visit_event_class(void *element, bt_ctf_ir_visitor visitor,void *data) +{ + struct bt_ctf_ir_element ir_element = + { .element = element, + .type = BT_CTF_IR_TYPE_EVENT_CLASS }; + + return visitor(&ir_element, data); +} + +int bt_ctf_stream_class_visit(struct bt_ctf_stream_class *stream_class, + bt_ctf_ir_visitor visitor, void *data) +{ + int ret; + struct bt_ctf_ir_element element = + { .element = stream_class, + .type = BT_CTF_IR_TYPE_STREAM_CLASS }; + + if (!stream_class || !visitor) { + ret = -1; + goto end; + } + + ret = visitor_helper(&element, get_event_class_count, + get_event_class, + visit_event_class, visitor, data); +end: + return ret; +} + BT_HIDDEN void bt_ctf_stream_class_freeze(struct bt_ctf_stream_class *stream_class) { diff --git a/formats/ctf/ir/trace.c b/formats/ctf/ir/trace.c index c4889b79..2cbfdb4e 100644 --- a/formats/ctf/ir/trace.c +++ b/formats/ctf/ir/trace.c @@ -37,7 +37,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -1032,6 +1034,71 @@ end: return ret; } +static +int get_stream_class_count(void *element) +{ + return bt_ctf_trace_get_stream_class_count( + (struct bt_ctf_trace *) element); +} + +static +void *get_stream_class(void *element, int i) +{ + return bt_ctf_trace_get_stream_class( + (struct bt_ctf_trace *) element, i); +} + +static +int visit_stream_class(void *element, bt_ctf_ir_visitor visitor,void *data) +{ + return bt_ctf_stream_class_visit(element, visitor, data); +} + +int bt_ctf_trace_visit(struct bt_ctf_trace *trace, + bt_ctf_ir_visitor visitor, void *data) +{ + int ret; + struct bt_ctf_ir_element element = + { .element = trace, .type = BT_CTF_IR_TYPE_TRACE }; + + if (!trace || !visitor) { + ret = -1; + goto end; + } + + ret = visitor_helper(&element, get_stream_class_count, + get_stream_class, visit_stream_class, visitor, data); +end: + return ret; +} + +static +int ir_visitor(struct bt_ctf_ir_element *element, void *data) +{ + int ret = 0; + + switch (element->type) { + case BT_CTF_IR_TYPE_TRACE: + { + break; + } + case BT_CTF_IR_TYPE_STREAM_CLASS: + { + break; + } + case BT_CTF_IR_TYPE_EVENT_CLASS: + { + break; + } + default: + assert(0); + ret = -1; + goto end; + } +end: + return ret; +} + int bt_ctf_trace_add_notification_handler_cb(struct bt_ctf_trace *trace, bt_ctf_notification_cb handler, void *handler_data) { @@ -1046,6 +1113,13 @@ int bt_ctf_trace_add_notification_handler_cb(struct bt_ctf_trace *trace, handler_wrapper->func = handler; handler_wrapper->data = handler_data; + + /* Emit notifications describing the current schema. */ + ret = bt_ctf_trace_visit(trace, ir_visitor, handler_wrapper); + if (ret) { + goto error; + } + g_ptr_array_add(trace->notification_handlers, handler_wrapper); return ret; error: diff --git a/formats/ctf/ir/visitor.c b/formats/ctf/ir/visitor.c new file mode 100644 index 00000000..762dce22 --- /dev/null +++ b/formats/ctf/ir/visitor.c @@ -0,0 +1,96 @@ +/* + * visitor.c + * + * Babeltrace CTF IR - Visitor + * + * Copyright 2016 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + +BT_HIDDEN +int visitor_helper(struct bt_ctf_ir_element *root, + bt_child_count_accessor child_counter, + bt_child_accessor child_accessor, + bt_child_visitor child_visitor, + bt_ctf_ir_visitor visitor, + void *data) +{ + int ret, child_count, i; + + ret = visitor(root, data); + if (ret) { + goto end; + } + + child_count = child_counter(root->element); + if (child_count < 0) { + ret = child_count; + goto end; + } + + for (i = 0; i < child_count; i++) { + void *child; + + child = child_accessor(root->element, i); + if (!child) { + ret = -1; + goto end; + } + ret = child_visitor(child, visitor, data); + BT_PUT(child); + if (ret) { + goto end; + } + } +end: + return ret; +} + +enum bt_ctf_ir_type bt_ctf_ir_element_get_type( + struct bt_ctf_ir_element *element) +{ + enum bt_ctf_ir_type ret = BT_CTF_IR_TYPE_UNKNOWN; + + if (!element) { + goto end; + } + + ret = element->type; +end: + return ret; +} + +void *bt_ctf_ir_element_get_element(struct bt_ctf_ir_element *element) +{ + void *ret = NULL; + + if (!element) { + goto end; + } + + ret = element->element; +end: + return ret; +} diff --git a/include/Makefile.am b/include/Makefile.am index 816b3b50..76e07722 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -34,7 +34,8 @@ babeltracectfirinclude_HEADERS = \ babeltrace/ctf-ir/packet.h \ babeltrace/ctf-ir/stream-class.h \ babeltrace/ctf-ir/trace.h \ - babeltrace/ctf-ir/utils.h + babeltrace/ctf-ir/utils.h \ + babeltrace/ctf-ir/visitor.h babeltraceplugininclude_HEADERS = \ babeltrace/plugin/plugin.h \ @@ -49,7 +50,8 @@ babeltraceplugininclude_HEADERS = \ babeltrace/plugin/notification/notification.h \ babeltrace/plugin/notification/event.h \ babeltrace/plugin/notification/iterator.h \ - babeltrace/plugin/notification/packet.h + babeltrace/plugin/notification/packet.h \ + babeltrace/plugin/notification/schema.h noinst_HEADERS = \ babeltrace/align.h \ @@ -92,6 +94,7 @@ noinst_HEADERS = \ babeltrace/ctf-ir/packet-internal.h \ babeltrace/ctf-ir/trace-internal.h \ babeltrace/ctf-ir/validation-internal.h \ + babeltrace/ctf-ir/visitor-internal.h \ babeltrace/ctf-writer/functor-internal.h \ babeltrace/trace-handle-internal.h \ babeltrace/compat/uuid.h \ diff --git a/include/babeltrace/ctf-ir/stream-class.h b/include/babeltrace/ctf-ir/stream-class.h index 433fc563..bc1ece1d 100644 --- a/include/babeltrace/ctf-ir/stream-class.h +++ b/include/babeltrace/ctf-ir/stream-class.h @@ -31,6 +31,7 @@ */ #include +#include #ifdef __cplusplus extern "C" { @@ -271,6 +272,20 @@ extern int bt_ctf_stream_class_set_event_context_type( struct bt_ctf_stream_class *stream_class, struct bt_ctf_field_type *event_context_type); +/* + * bt_ctf_stream_class_visit: visit a stream class' event classes. + * + * Call visitor on each of a stream class' event classes. + * + * @param stream_class Stream class instance. + * @param visitor visitor function to invoke for each stream class. + * @param data user data passed to the visitor. + * + * Returns 0 on success, a negative value on error. + */ +extern int bt_ctf_stream_class_visit(struct bt_ctf_stream_class *stream_class, + bt_ctf_ir_visitor visitor, void *data); + #ifdef __cplusplus } #endif diff --git a/include/babeltrace/ctf-ir/trace.h b/include/babeltrace/ctf-ir/trace.h index ccbfe9ef..39574f3a 100644 --- a/include/babeltrace/ctf-ir/trace.h +++ b/include/babeltrace/ctf-ir/trace.h @@ -31,7 +31,9 @@ */ #include +#include #include +#include #include #ifdef __cplusplus @@ -350,6 +352,21 @@ extern struct bt_ctf_field_type *bt_ctf_trace_get_packet_header_type( extern int bt_ctf_trace_set_packet_header_type(struct bt_ctf_trace *trace, struct bt_ctf_field_type *packet_header_type); +/* + * bt_ctf_trace_visit: visit a trace's hierarchy. + * + * Recursively walk a trace's hierarchy and call visitor on each of its + * elements. + * + * @param trace Trace instance. + * @param visitor visitor function to invoke for each element. + * @param data user data passed to the visitor. + * + * Returns 0 on success, a negative value on error. + */ +extern int bt_ctf_trace_visit(struct bt_ctf_trace *trace, + bt_ctf_ir_visitor visitor, void *data); + /* * bt_ctf_trace_add_notification_handler_cb: set a notification callback * which will be invoked whenever a trace's schema is modified. diff --git a/include/babeltrace/ctf-ir/visitor-internal.h b/include/babeltrace/ctf-ir/visitor-internal.h new file mode 100644 index 00000000..a8fd1ae9 --- /dev/null +++ b/include/babeltrace/ctf-ir/visitor-internal.h @@ -0,0 +1,51 @@ +#ifndef BABELTRACE_CTF_IR_VISITOR_INTERNAL_H +#define BABELTRACE_CTF_IR_VISITOR_INTERNAL_H + +/* + * BabelTrace - CTF IR: Visitor internal + * + * Copyright 2016 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + +typedef void *(*bt_child_accessor)(void *element, int index); +typedef int (*bt_child_count_accessor)(void *element); +typedef int (*bt_child_visitor)(void *element, bt_ctf_ir_visitor visitor, + void *data); + +struct bt_ctf_ir_element { + enum bt_ctf_ir_type type; + void *element; +}; + +BT_HIDDEN +int visitor_helper(struct bt_ctf_ir_element *root, + bt_child_count_accessor child_counter, + bt_child_accessor child_accessor, + bt_child_visitor child_visitor, + bt_ctf_ir_visitor visitor, + void *data); + +#endif /* BABELTRACE_CTF_IR_VISITOR_INTERNAL_H */ diff --git a/include/babeltrace/ctf-ir/visitor.h b/include/babeltrace/ctf-ir/visitor.h new file mode 100644 index 00000000..1a187ccb --- /dev/null +++ b/include/babeltrace/ctf-ir/visitor.h @@ -0,0 +1,80 @@ +#ifndef BABELTRACE_CTF_IR_VISITOR_H +#define BABELTRACE_CTF_IR_VISITOR_H + +/* + * BabelTrace - CTF IR: Visitor + * + * Copyright 2016 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The Common Trace Format (CTF) Specification is available at + * http://www.efficios.com/ctf + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct bt_ctf_ir_element; + +enum bt_ctf_ir_type { + BT_CTF_IR_TYPE_UNKNOWN = -1, + BT_CTF_IR_TYPE_TRACE = 0, + BT_CTF_IR_TYPE_STREAM_CLASS = 1, + BT_CTF_IR_TYPE_STREAM = 2, + BT_CTF_IR_TYPE_EVENT_CLASS = 3, + BT_CTF_IR_TYPE_EVENT = 4, + BT_CTF_IR_TYPE_NR, +}; + +typedef int (*bt_ctf_ir_visitor)(struct bt_ctf_ir_element *element, + void *data); + +/* + * bt_ctf_ir_element_get_type: get an IR element's type. + * + * Get an IR element's type. + * + * @param element Element instance. + * + * Returns one of #bt_ctf_ir_type. + */ +enum bt_ctf_ir_type bt_ctf_ir_element_get_type( + struct bt_ctf_ir_element *element); + +/* + * bt_ctf_ir_element_get_element: get an IR element's value. + * + * Get an IR element's value. + * + * @param element Element instance. + * + * Returns a CTF-IR type. Use #bt_ctf_ir_type to determine the + * concrete type of the value returned. + */ +void *bt_ctf_ir_element_get_element(struct bt_ctf_ir_element *element); + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE_CTF_IR_VISITOR_H */ diff --git a/include/babeltrace/plugin/notification/notification.h b/include/babeltrace/plugin/notification/notification.h index 21a7328d..b8b87a44 100644 --- a/include/babeltrace/plugin/notification/notification.h +++ b/include/babeltrace/plugin/notification/notification.h @@ -54,8 +54,17 @@ enum bt_notification_type { /** End of stream packet notification, see packet.h */ BT_NOTIFICATION_TYPE_END_PACKET = 3, + /** New trace notification, see model.h */ + BT_NOTIFICATION_TYPE_NEW_TRACE = 4, + + /** New stream class notification, see model.h */ + BT_NOTIFICATION_TYPE_NEW_STREAM_CLASS = 5, + + /** New event class notification, see model.h */ + BT_NOTIFICATION_TYPE_NEW_EVENT_CLASS = 6, + /** End of trace notification, see eot.h */ - BT_NOTIFICATION_TYPE_END_OF_TRACE = 4, + BT_NOTIFICATION_TYPE_END_OF_TRACE = 7, BT_NOTIFICATION_TYPE_NR, }; diff --git a/include/babeltrace/plugin/notification/schema.h b/include/babeltrace/plugin/notification/schema.h new file mode 100644 index 00000000..96b161a0 --- /dev/null +++ b/include/babeltrace/plugin/notification/schema.h @@ -0,0 +1,115 @@ +#ifndef BABELTRACE_PLUGIN_NOTIFICATION_SCHEMA_H +#define BABELTRACE_PLUGIN_NOTIFICATION_SCHEMA_H + +/* + * BabelTrace - Plug-in Schema Change Notification + * + * Copyright 2016 Jérémie Galarneau + * + * Author: Jérémie Galarneau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct bt_notification; +struct bt_ctf_trace; +struct bt_ctf_stream_class; +struct bt_ctf_event_class; + + +/* BT_NOTIFICATION_TYPE_NEW_TRACE */ +/** + * Create a new trace notification. + * + * @param trace The new trace + * @returns A new trace notification instance + * + * @see #bt_notification_type + */ +extern struct bt_notification *bt_notification_new_trace_create( + struct bt_ctf_trace *trace); + +/** + * Get a new trace notification's associated trace. + * + * @param notification New trace notification instance + * @returns A trace instance + * + * @see #bt_ctf_trace + */ +extern struct bt_ctf_trace *bt_notification_new_trace_get_trace( + struct bt_notification *notification); + + +/* BT_NOTIFICATION_TYPE_NEW_STREAM_CLASS */ +/** + * Create a new stream class notification. + * + * @param trace The event's trace + * @returns A new stream class notification instance + * + * @see #bt_notification_type + */ +extern struct bt_notification *bt_notification_new_stream_class_create( + struct bt_ctf_stream_class *stream_class); + +/** + * Get a new stream class notification's associated stream class. + * + * @param notification New stream class notification instance + * @returns A stream class instance + * + * @see #bt_ctf_stream_class + */ +extern struct bt_ctf_trace *bt_notification_new_stream_class_get_stream_class( + struct bt_notification *notification); + + +/* BT_NOTIFICATION_TYPE_EVENT_CLASS */ +/** + * Create a new trace notification. + * + * @param trace The event's trace + * @returns An event notification instance + * + * @see #bt_notification_type + */ +extern struct bt_notification *bt_notification_new_trace_create( + struct bt_ctf_trace *trace); + +/** + * Get a new trace notification's associated trace. + * + * @param notification New trace notification instance + * @returns A trace instance + * + * @see #bt_ctf_trace + */ +extern struct bt_ctf_trace *bt_notification_new_trace_get_trace( + struct bt_notification *notification); + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE_PLUGIN_NOTIFICATION_SCHEMA_H */ -- 2.34.1