Commit | Line | Data |
---|---|---|
7704a0af PP |
1 | #include <stdlib.h> |
2 | #include <stdio.h> | |
3 | #include <stdint.h> | |
4 | #include <inttypes.h> | |
5 | #include <string.h> | |
6 | #include <babeltrace2/babeltrace.h> | |
7 | ||
8 | /* Sink component's private data */ | |
9 | struct epitome_out { | |
10 | /* Upstream message iterator (owned by this) */ | |
11 | bt_message_iterator *message_iterator; | |
12 | ||
13 | /* Current event message index */ | |
14 | uint64_t index; | |
15 | }; | |
16 | ||
17 | /* | |
18 | * Initializes the sink component. | |
19 | */ | |
20 | static | |
21 | bt_component_class_initialize_method_status epitome_out_initialize( | |
22 | bt_self_component_sink *self_component_sink, | |
23 | bt_self_component_sink_configuration *configuration, | |
24 | const bt_value *params, void *initialize_method_data) | |
25 | { | |
26 | /* Allocate a private data structure */ | |
27 | struct epitome_out *epitome_out = malloc(sizeof(*epitome_out)); | |
28 | ||
29 | /* Initialize the first event message's index */ | |
30 | epitome_out->index = 1; | |
31 | ||
32 | /* Set the component's user data to our private data structure */ | |
33 | bt_self_component_set_data( | |
34 | bt_self_component_sink_as_self_component(self_component_sink), | |
35 | epitome_out); | |
36 | ||
37 | /* | |
38 | * Add an input port named `in` to the sink component. | |
39 | * | |
40 | * This is needed so that this sink component can be connected to a | |
41 | * filter or a source component. With a connected upstream | |
42 | * component, this sink component can create a message iterator | |
43 | * to consume messages. | |
44 | */ | |
45 | bt_self_component_sink_add_input_port(self_component_sink, | |
46 | "in", NULL, NULL); | |
47 | ||
48 | return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK; | |
49 | } | |
50 | ||
51 | /* | |
52 | * Finalizes the sink component. | |
53 | */ | |
54 | static | |
55 | void epitome_out_finalize(bt_self_component_sink *self_component_sink) | |
56 | { | |
57 | /* Retrieve our private data from the component's user data */ | |
58 | struct epitome_out *epitome_out = bt_self_component_get_data( | |
59 | bt_self_component_sink_as_self_component(self_component_sink)); | |
60 | ||
61 | /* Free the allocated structure */ | |
62 | free(epitome_out); | |
63 | } | |
64 | ||
65 | /* | |
66 | * Called when the trace processing graph containing the sink component | |
67 | * is configured. | |
68 | * | |
69 | * This is where we can create our upstream message iterator. | |
70 | */ | |
71 | static | |
72 | bt_component_class_sink_graph_is_configured_method_status | |
73 | epitome_out_graph_is_configured(bt_self_component_sink *self_component_sink) | |
74 | { | |
75 | /* Retrieve our private data from the component's user data */ | |
76 | struct epitome_out *epitome_out = bt_self_component_get_data( | |
77 | bt_self_component_sink_as_self_component(self_component_sink)); | |
78 | ||
79 | /* Borrow our unique port */ | |
80 | bt_self_component_port_input *in_port = | |
81 | bt_self_component_sink_borrow_input_port_by_index( | |
82 | self_component_sink, 0); | |
83 | ||
84 | /* Create the uptream message iterator */ | |
85 | bt_message_iterator_create_from_sink_component(self_component_sink, | |
86 | in_port, &epitome_out->message_iterator); | |
87 | ||
88 | return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_OK; | |
89 | } | |
90 | ||
91 | /* | |
92 | * Prints a line for `message`, if it's an event message, to the | |
93 | * standard output. | |
94 | */ | |
95 | static | |
96 | void print_message(struct epitome_out *epitome_out, const bt_message *message) | |
97 | { | |
98 | /* Discard if it's not an event message */ | |
99 | if (bt_message_get_type(message) != BT_MESSAGE_TYPE_EVENT) { | |
100 | goto end; | |
101 | } | |
102 | ||
103 | /* Borrow the event message's event and its class */ | |
104 | const bt_event *event = | |
105 | bt_message_event_borrow_event_const(message); | |
106 | const bt_event_class *event_class = bt_event_borrow_class_const(event); | |
107 | ||
108 | /* Get the number of payload field members */ | |
109 | const bt_field *payload_field = | |
110 | bt_event_borrow_payload_field_const(event); | |
111 | uint64_t member_count = bt_field_class_structure_get_member_count( | |
112 | bt_field_borrow_class_const(payload_field)); | |
113 | ||
114 | /* Write a corresponding line to the standard output */ | |
115 | printf("#%" PRIu64 ": %s (%" PRIu64 " payload member%s)\n", | |
116 | epitome_out->index, bt_event_class_get_name(event_class), | |
117 | member_count, member_count == 1 ? "" : "s"); | |
118 | ||
119 | /* Increment the current event message's index */ | |
120 | epitome_out->index++; | |
121 | ||
122 | end: | |
123 | return; | |
124 | } | |
125 | ||
126 | /* | |
127 | * Consumes a batch of messages and writes the corresponding lines to | |
128 | * the standard output. | |
129 | */ | |
130 | bt_component_class_sink_consume_method_status epitome_out_consume( | |
131 | bt_self_component_sink *self_component_sink) | |
132 | { | |
133 | bt_component_class_sink_consume_method_status status = | |
134 | BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK; | |
135 | ||
136 | /* Retrieve our private data from the component's user data */ | |
137 | struct epitome_out *epitome_out = bt_self_component_get_data( | |
138 | bt_self_component_sink_as_self_component(self_component_sink)); | |
139 | ||
140 | /* Consume a batch of messages from the upstream message iterator */ | |
141 | bt_message_array_const messages; | |
142 | uint64_t message_count; | |
143 | bt_message_iterator_next_status next_status = | |
144 | bt_message_iterator_next(epitome_out->message_iterator, &messages, | |
145 | &message_count); | |
146 | ||
147 | switch (next_status) { | |
148 | case BT_MESSAGE_ITERATOR_NEXT_STATUS_END: | |
149 | /* End of iteration: put the message iterator's reference */ | |
150 | bt_message_iterator_put_ref(epitome_out->message_iterator); | |
151 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_END; | |
152 | goto end; | |
153 | case BT_MESSAGE_ITERATOR_NEXT_STATUS_AGAIN: | |
154 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_AGAIN; | |
155 | goto end; | |
156 | case BT_MESSAGE_ITERATOR_NEXT_STATUS_MEMORY_ERROR: | |
157 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_MEMORY_ERROR; | |
158 | goto end; | |
159 | case BT_MESSAGE_ITERATOR_NEXT_STATUS_ERROR: | |
160 | status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; | |
161 | goto end; | |
162 | default: | |
163 | break; | |
164 | } | |
165 | ||
166 | /* For each consumed message */ | |
167 | for (uint64_t i = 0; i < message_count; i++) { | |
168 | /* Current message */ | |
169 | const bt_message *message = messages[i]; | |
170 | ||
171 | /* Print line for current message if it's an event message */ | |
172 | print_message(epitome_out, message); | |
173 | ||
174 | /* Put this message's reference */ | |
175 | bt_message_put_ref(message); | |
176 | } | |
177 | ||
178 | end: | |
179 | return status; | |
180 | } | |
181 | ||
182 | /* Mandatory */ | |
183 | BT_PLUGIN_MODULE(); | |
184 | ||
185 | /* Define the `epitome` plugin */ | |
186 | BT_PLUGIN(epitome); | |
187 | ||
188 | /* Define the `output` sink component class */ | |
189 | BT_PLUGIN_SINK_COMPONENT_CLASS(output, epitome_out_consume); | |
190 | ||
191 | /* Set some of the `output` sink component class's optional methods */ | |
192 | BT_PLUGIN_SINK_COMPONENT_CLASS_INITIALIZE_METHOD(output, | |
193 | epitome_out_initialize); | |
194 | BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD(output, epitome_out_finalize); | |
195 | BT_PLUGIN_SINK_COMPONENT_CLASS_GRAPH_IS_CONFIGURED_METHOD(output, | |
196 | epitome_out_graph_is_configured); |