debug-info: handle the static notifications
[babeltrace.git] / plugins / lttng-utils / plugin.c
CommitLineData
4f45f9bb
JD
1/*
2 * plugin.c
3 *
4 * Babeltrace Debug Info Plug-in
5 *
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 *
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
7b077a9d
JD
29#include <babeltrace/graph/notification-iterator.h>
30#include <babeltrace/graph/private-notification-iterator.h>
73d5c1ad 31#include <babeltrace/graph/connection.h>
7b077a9d
JD
32#include <babeltrace/graph/notification.h>
33#include <babeltrace/graph/notification-event.h>
34#include <babeltrace/graph/notification-stream.h>
35#include <babeltrace/graph/notification-packet.h>
36#include <babeltrace/graph/component-filter.h>
37#include <babeltrace/graph/private-component-filter.h>
38#include <babeltrace/graph/private-port.h>
39#include <babeltrace/graph/private-connection.h>
40#include <babeltrace/graph/private-component.h>
4f45f9bb 41#include <babeltrace/plugin/plugin-dev.h>
4f45f9bb
JD
42#include <plugins-common.h>
43#include <assert.h>
44#include "debug-info.h"
45#include "copy.h"
46
1c78e839
JD
47static
48gboolean empty_trace_map(gpointer key, gpointer value, gpointer user_data)
49{
50 struct debug_info_trace *di_trace = value;
51
52 di_trace->trace_static = 1;
53 debug_info_close_trace(di_trace->debug_it, di_trace);
54
55 return TRUE;
56}
57
4f45f9bb
JD
58static
59void destroy_debug_info_data(struct debug_info_component *debug_info)
60{
61 free(debug_info->arg_debug_info_field_name);
62 g_free(debug_info);
63}
64
65static
7b077a9d 66void destroy_debug_info_component(struct bt_private_component *component)
4f45f9bb 67{
7b077a9d 68 void *data = bt_private_component_get_user_data(component);
4f45f9bb
JD
69 destroy_debug_info_data(data);
70}
71
72static
73struct debug_info_component *create_debug_info_component_data(void)
74{
75 struct debug_info_component *debug_info;
76
77 debug_info = g_new0(struct debug_info_component, 1);
78 if (!debug_info) {
79 goto end;
80 }
81 debug_info->err = stderr;
82
83end:
84 return debug_info;
85}
86
87static
504db471 88void unref_trace(struct debug_info_trace *di_trace)
4f45f9bb 89{
1c78e839
JD
90 bt_put(di_trace->writer_trace);
91 g_free(di_trace);
4f45f9bb
JD
92}
93
94static
7b077a9d 95void debug_info_iterator_destroy(struct bt_private_notification_iterator *it)
4f45f9bb
JD
96{
97 struct debug_info_iterator *it_data;
98
7b077a9d 99 it_data = bt_private_notification_iterator_get_user_data(it);
4f45f9bb
JD
100 assert(it_data);
101
102 if (it_data->input_iterator_group) {
103 g_ptr_array_free(it_data->input_iterator_group, TRUE);
104 }
1c78e839
JD
105
106 g_hash_table_foreach_remove(it_data->trace_map,
107 empty_trace_map, it_data);
108 g_hash_table_destroy(it_data->trace_map);
109
4f45f9bb
JD
110 bt_put(it_data->current_notification);
111 bt_put(it_data->input_iterator);
1c78e839 112
4f45f9bb
JD
113 g_free(it_data);
114}
115
116static
117struct bt_notification *handle_notification(FILE *err,
118 struct debug_info_iterator *debug_it,
119 struct bt_notification *notification)
120{
121 struct bt_notification *new_notification = NULL;
122
123 switch (bt_notification_get_type(notification)) {
124 case BT_NOTIFICATION_TYPE_PACKET_BEGIN:
125 {
126 struct bt_ctf_packet *packet =
127 bt_notification_packet_begin_get_packet(notification);
128 struct bt_ctf_packet *writer_packet;
129
130 if (!packet) {
131 goto end;
132 }
133
134 writer_packet = debug_info_new_packet(debug_it, packet);
135 assert(writer_packet);
136 new_notification = bt_notification_packet_begin_create(
137 writer_packet);
138 assert(new_notification);
139 bt_put(packet);
1c78e839 140 bt_put(writer_packet);
4f45f9bb
JD
141 break;
142 }
143 case BT_NOTIFICATION_TYPE_PACKET_END:
144 {
145 struct bt_ctf_packet *packet =
146 bt_notification_packet_end_get_packet(notification);
147 struct bt_ctf_packet *writer_packet;
148
149 if (!packet) {
150 goto end;
151 }
152
153 writer_packet = debug_info_close_packet(debug_it, packet);
154 assert(writer_packet);
155 new_notification = bt_notification_packet_end_create(
156 writer_packet);
157 assert(new_notification);
158 bt_put(packet);
1c78e839 159 bt_put(writer_packet);
4f45f9bb
JD
160 break;
161 }
162 case BT_NOTIFICATION_TYPE_EVENT:
163 {
164 struct bt_ctf_event *event = bt_notification_event_get_event(
165 notification);
166 struct bt_ctf_event *writer_event;
167 struct bt_clock_class_priority_map *cc_prio_map =
168 bt_notification_event_get_clock_class_priority_map(
169 notification);
170
171 if (!event) {
172 goto end;
173 }
174 writer_event = debug_info_output_event(debug_it, event);
175 assert(writer_event);
176 new_notification = bt_notification_event_create(writer_event,
177 cc_prio_map);
178 bt_put(cc_prio_map);
179 assert(new_notification);
180 bt_put(event);
181 bt_put(writer_event);
182 break;
183 }
504db471
JD
184 case BT_NOTIFICATION_TYPE_STREAM_BEGIN:
185 {
186 struct bt_ctf_stream *stream =
187 bt_notification_stream_begin_get_stream(notification);
188 struct bt_ctf_stream *writer_stream;
189
190 if (!stream) {
191 goto end;
192 }
193
194 writer_stream = debug_info_stream_begin(debug_it, stream);
195 assert(writer_stream);
196 new_notification = bt_notification_stream_begin_create(
197 writer_stream);
198 assert(new_notification);
199 bt_put(stream);
200 bt_put(writer_stream);
201 break;
202 }
4f45f9bb
JD
203 case BT_NOTIFICATION_TYPE_STREAM_END:
204 {
205 struct bt_ctf_stream *stream =
206 bt_notification_stream_end_get_stream(notification);
207 struct bt_ctf_stream *writer_stream;
208
209 if (!stream) {
210 goto end;
211 }
212
213 writer_stream = debug_info_stream_end(debug_it, stream);
214 assert(writer_stream);
215 new_notification = bt_notification_stream_end_create(
216 writer_stream);
217 assert(new_notification);
218 bt_put(stream);
219 bt_put(writer_stream);
220 break;
221 }
779fc95d
JD
222 case BT_NOTIFICATION_TYPE_INACTIVITY:
223 {
224 new_notification = bt_get(notification);
225 break;
226 }
4f45f9bb
JD
227 default:
228 puts("Unhandled notification type");
229 }
230
231end:
232 return new_notification;
233}
234
235static
7b077a9d
JD
236struct bt_notification_iterator_next_return debug_info_iterator_next(
237 struct bt_private_notification_iterator *iterator)
4f45f9bb
JD
238{
239 struct debug_info_iterator *debug_it = NULL;
7b077a9d 240 struct bt_private_component *component = NULL;
4f45f9bb
JD
241 struct debug_info_component *debug_info = NULL;
242 struct bt_notification_iterator *source_it = NULL;
7b077a9d
JD
243 struct bt_notification *notification;
244 struct bt_notification_iterator_next_return ret = {
245 .status = BT_NOTIFICATION_ITERATOR_STATUS_OK,
246 .notification = NULL,
247 };
4f45f9bb 248
7b077a9d 249 debug_it = bt_private_notification_iterator_get_user_data(iterator);
4f45f9bb
JD
250 assert(debug_it);
251
7b077a9d 252 component = bt_private_notification_iterator_get_private_component(iterator);
4f45f9bb 253 assert(component);
7b077a9d 254 debug_info = bt_private_component_get_user_data(component);
4f45f9bb
JD
255 assert(debug_info);
256
257 source_it = debug_it->input_iterator;
258
7b077a9d
JD
259 ret.status = bt_notification_iterator_next(source_it);
260 if (ret.status != BT_NOTIFICATION_ITERATOR_STATUS_OK) {
4f45f9bb
JD
261 goto end;
262 }
263
264 notification = bt_notification_iterator_get_notification(
265 source_it);
266 if (!notification) {
7b077a9d 267 ret.status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
4f45f9bb
JD
268 goto end;
269 }
270
7b077a9d 271 ret.notification = handle_notification(debug_info->err, debug_it,
4f45f9bb 272 notification);
7b077a9d 273 assert(ret.notification);
4f45f9bb
JD
274 bt_put(notification);
275
4f45f9bb
JD
276end:
277 bt_put(component);
278 return ret;
279}
280
4f45f9bb 281static
7b077a9d
JD
282enum bt_notification_iterator_status debug_info_iterator_init(
283 struct bt_private_notification_iterator *iterator,
284 struct bt_private_port *port)
4f45f9bb
JD
285{
286 enum bt_notification_iterator_status ret =
287 BT_NOTIFICATION_ITERATOR_STATUS_OK;
288 enum bt_notification_iterator_status it_ret;
73d5c1ad 289 enum bt_connection_status conn_status;
7b077a9d
JD
290 struct bt_private_connection *connection = NULL;
291 struct bt_private_component *component =
292 bt_private_notification_iterator_get_private_component(iterator);
4f45f9bb 293 struct debug_info_iterator *it_data = g_new0(struct debug_info_iterator, 1);
779fc95d
JD
294 struct bt_private_port *input_port;
295 static const enum bt_notification_type notif_types[] = {
296 BT_NOTIFICATION_TYPE_EVENT,
504db471 297 BT_NOTIFICATION_TYPE_STREAM_BEGIN,
779fc95d
JD
298 BT_NOTIFICATION_TYPE_STREAM_END,
299 BT_NOTIFICATION_TYPE_PACKET_BEGIN,
300 BT_NOTIFICATION_TYPE_PACKET_END,
301 BT_NOTIFICATION_TYPE_SENTINEL,
302 };
4f45f9bb
JD
303
304 if (!it_data) {
305 ret = BT_NOTIFICATION_ITERATOR_STATUS_NOMEM;
306 goto end;
307 }
308
b9d103be 309 input_port = bt_private_component_filter_get_input_private_port_by_name(
779fc95d
JD
310 component, "in");
311 if (!input_port) {
312 ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
313 goto end;
314 }
315
7b077a9d 316 connection = bt_private_port_get_private_connection(input_port);
779fc95d
JD
317 bt_put(input_port);
318 if (!connection) {
319 ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
320 goto end;
321 }
4f45f9bb 322
73d5c1ad
PP
323 conn_status = bt_private_connection_create_notification_iterator(
324 connection, notif_types, &it_data->input_iterator);
325 if (conn_status != BT_CONNECTION_STATUS_OK) {
326 ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
4f45f9bb
JD
327 goto end;
328 }
779fc95d 329
4f45f9bb 330 it_data->debug_info_component = (struct debug_info_component *)
7b077a9d 331 bt_private_component_get_user_data(component);
4f45f9bb
JD
332 it_data->err = it_data->debug_info_component->err;
333 it_data->trace_map = g_hash_table_new_full(g_direct_hash,
334 g_direct_equal, NULL, (GDestroyNotify) unref_trace);
4f45f9bb 335
7b077a9d 336 it_ret = bt_private_notification_iterator_set_user_data(iterator, it_data);
4f45f9bb
JD
337 if (it_ret) {
338 goto end;
339 }
340
341end:
342 bt_put(connection);
779fc95d 343 bt_put(component);
4f45f9bb
JD
344 return ret;
345}
346
347static
348enum bt_component_status init_from_params(
349 struct debug_info_component *debug_info_component,
350 struct bt_value *params)
351{
352 struct bt_value *value = NULL;
353 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
354
355 assert(params);
356
357 value = bt_value_map_get(params, "debug-info-field-name");
358 if (value) {
359 enum bt_value_status value_ret;
360 const char *tmp;
361
362 value_ret = bt_value_string_get(value, &tmp);
363 if (value_ret) {
364 ret = BT_COMPONENT_STATUS_INVALID;
365 printf_error("Failed to retrieve debug-info-field-name value. "
366 "Expecting a string");
367 }
368 strcpy(debug_info_component->arg_debug_info_field_name, tmp);
369 bt_put(value);
370 } else {
371 debug_info_component->arg_debug_info_field_name =
372 malloc(strlen("debug_info") + 1);
373 if (!debug_info_component->arg_debug_info_field_name) {
374 ret = BT_COMPONENT_STATUS_NOMEM;
375 printf_error();
376 }
377 sprintf(debug_info_component->arg_debug_info_field_name,
378 "debug_info");
379 }
380 if (ret != BT_COMPONENT_STATUS_OK) {
381 goto end;
382 }
383
384 value = bt_value_map_get(params, "debug-dir");
385 if (value) {
386 enum bt_value_status value_ret;
387
388 value_ret = bt_value_string_get(value,
389 &debug_info_component->arg_debug_dir);
390 if (value_ret) {
391 ret = BT_COMPONENT_STATUS_INVALID;
392 printf_error("Failed to retrieve debug-dir value. "
393 "Expecting a string");
394 }
395 }
396 bt_put(value);
397 if (ret != BT_COMPONENT_STATUS_OK) {
398 goto end;
399 }
400
401 value = bt_value_map_get(params, "target-prefix");
402 if (value) {
403 enum bt_value_status value_ret;
404
405 value_ret = bt_value_string_get(value,
406 &debug_info_component->arg_target_prefix);
407 if (value_ret) {
408 ret = BT_COMPONENT_STATUS_INVALID;
409 printf_error("Failed to retrieve target-prefix value. "
410 "Expecting a string");
411 }
412 }
413 bt_put(value);
414 if (ret != BT_COMPONENT_STATUS_OK) {
415 goto end;
416 }
417
418 value = bt_value_map_get(params, "full-path");
419 if (value) {
420 enum bt_value_status value_ret;
c55a9f58 421 bt_bool bool_val;
4f45f9bb
JD
422
423 value_ret = bt_value_bool_get(value,
c55a9f58 424 &bool_val);
4f45f9bb
JD
425 if (value_ret) {
426 ret = BT_COMPONENT_STATUS_INVALID;
427 printf_error("Failed to retrieve full-path value. "
428 "Expecting a boolean");
429 }
c55a9f58
PP
430
431 debug_info_component->arg_full_path = bool_val;
4f45f9bb
JD
432 }
433 bt_put(value);
434 if (ret != BT_COMPONENT_STATUS_OK) {
435 goto end;
436 }
437
438end:
439 return ret;
440}
441
442enum bt_component_status debug_info_component_init(
7b077a9d 443 struct bt_private_component *component, struct bt_value *params,
4f45f9bb
JD
444 UNUSED_VAR void *init_method_data)
445{
446 enum bt_component_status ret;
447 struct debug_info_component *debug_info = create_debug_info_component_data();
448
449 if (!debug_info) {
450 ret = BT_COMPONENT_STATUS_NOMEM;
451 goto end;
452 }
453
7b077a9d 454 ret = bt_private_component_set_user_data(component, debug_info);
4f45f9bb
JD
455 if (ret != BT_COMPONENT_STATUS_OK) {
456 goto error;
457 }
458
147337a3
PP
459 ret = bt_private_component_filter_add_input_private_port(
460 component, "in", NULL, NULL);
461 if (ret != BT_COMPONENT_STATUS_OK) {
779fc95d
JD
462 goto end;
463 }
779fc95d 464
147337a3
PP
465 ret = bt_private_component_filter_add_output_private_port(
466 component, "out", NULL, NULL);
467 if (ret != BT_COMPONENT_STATUS_OK) {
779fc95d
JD
468 goto end;
469 }
779fc95d 470
4f45f9bb
JD
471 ret = init_from_params(debug_info, params);
472end:
473 return ret;
474error:
475 destroy_debug_info_data(debug_info);
476 return ret;
477}
478
479/* Initialize plug-in entry points. */
456a4476
PP
480BT_PLUGIN_WITH_ID(lttng_utils, "lttng-utils");
481BT_PLUGIN_DESCRIPTION_WITH_ID(lttng_utils, "LTTng utilities");
482BT_PLUGIN_AUTHOR_WITH_ID(lttng_utils, "Julien Desfossez");
483BT_PLUGIN_LICENSE_WITH_ID(lttng_utils, "MIT");
484
485BT_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID(lttng_utils, debug_info, "debug-info",
486 debug_info_iterator_next);
487BT_PLUGIN_FILTER_COMPONENT_CLASS_DESCRIPTION_WITH_ID(lttng_utils, debug_info,
488 "Augment compatible events with debugging information.");
489BT_PLUGIN_FILTER_COMPONENT_CLASS_INIT_METHOD_WITH_ID(lttng_utils,
490 debug_info, debug_info_component_init);
491BT_PLUGIN_FILTER_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID(lttng_utils,
492 debug_info, destroy_debug_info_component);
493BT_PLUGIN_FILTER_COMPONENT_CLASS_NOTIFICATION_ITERATOR_INIT_METHOD_WITH_ID(
494 lttng_utils, debug_info, debug_info_iterator_init);
495BT_PLUGIN_FILTER_COMPONENT_CLASS_NOTIFICATION_ITERATOR_FINALIZE_METHOD_WITH_ID(
496 lttng_utils, debug_info, debug_info_iterator_destroy);
This page took 0.046811 seconds and 4 git commands to generate.