Refactor the plugin registration and loading machinery
[babeltrace.git] / plugins / text / text.c
CommitLineData
7a278c8e 1/*
5dac767a 2 * text.c
7a278c8e 3 *
5dac767a 4 * Babeltrace CTF Text Output Plugin
7a278c8e 5 *
2e339de1 6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
f504043c 7 * Copyright 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7a278c8e
JG
8 *
9 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * SOFTWARE.
28 */
29
33b34c43
PP
30#include <babeltrace/plugin/plugin-dev.h>
31#include <babeltrace/component/component.h>
32#include <babeltrace/component/sink.h>
33#include <babeltrace/component/notification/notification.h>
34#include <babeltrace/component/notification/iterator.h>
35#include <babeltrace/component/notification/event.h>
6e1bc0df
MD
36#include <babeltrace/values.h>
37#include <babeltrace/compiler.h>
bfd20a42 38#include <stdio.h>
39cfa40f 39#include <stdbool.h>
bac67f0f 40#include <glib.h>
541b0a11 41#include "text.h"
6405967d 42
6e1bc0df
MD
43static
44const char *plugin_options[] = {
45 "output-path",
46 "debug-info-dir",
47 "debug-info-target-prefix",
48 "debug-info-full-path",
49 "no-delta",
50 "clock-cycles",
51 "clock-seconds",
52 "clock-date",
53 "clock-gmt",
54 "name-default", /* show/hide */
55 "name-payload",
56 "name-context",
57 "name-scope",
58 "name-header",
59 "field-default", /* show/hide */
60 "field-trace",
61 "field-trace:hostname",
62 "field-trace:domain",
63 "field-trace:procname",
64 "field-trace:vpid",
65 "field-loglevel",
66 "field-emf",
6e1bc0df
MD
67};
68
bfd20a42 69static
541b0a11 70void destroy_text_data(struct text_component *text)
bac67f0f 71{
6a18b281 72 (void) g_string_free(text->string, TRUE);
6e1bc0df
MD
73 g_free(text->options.output_path);
74 g_free(text->options.debug_info_dir);
75 g_free(text->options.debug_info_target_prefix);
541b0a11 76 g_free(text);
bac67f0f
JG
77}
78
b25bd455 79static
541b0a11 80struct text_component *create_text(void)
bac67f0f 81{
541b0a11
JG
82 struct text_component *text;
83
84 text = g_new0(struct text_component, 1);
85 if (!text) {
86 goto end;
87 }
6a18b281
MD
88 text->string = g_string_new("");
89 if (!text->string) {
90 goto error;
91 }
541b0a11
JG
92end:
93 return text;
6a18b281
MD
94
95error:
96 g_free(text);
97 return NULL;
bac67f0f
JG
98}
99
fec2a9f2
JG
100static
101void destroy_text(struct bt_component *component)
b25bd455
JG
102{
103 void *data = bt_component_get_private_data(component);
104
105 destroy_text_data(data);
106}
107
bac67f0f 108static
fec2a9f2 109enum bt_component_status handle_notification(struct text_component *text,
6e1bc0df 110 struct bt_notification *notification)
4c1456f0 111{
541b0a11 112 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
541b0a11
JG
113
114 if (!text) {
115 ret = BT_COMPONENT_STATUS_ERROR;
116 goto end;
117 }
118
78586d8a 119 switch (bt_notification_get_type(notification)) {
ea0e619e 120 case BT_NOTIFICATION_TYPE_PACKET_BEGIN:
78586d8a
JG
121 puts("<packet>");
122 break;
123 case BT_NOTIFICATION_TYPE_PACKET_END:
124 puts("</packet>");
125 break;
126 case BT_NOTIFICATION_TYPE_EVENT:
541b0a11
JG
127 {
128 struct bt_ctf_event *event = bt_notification_event_get_event(
129 notification);
130
541b0a11
JG
131 if (!event) {
132 ret = BT_COMPONENT_STATUS_ERROR;
133 goto end;
134 }
135 ret = text_print_event(text, event);
fec2a9f2 136 bt_put(event);
541b0a11
JG
137 if (ret != BT_COMPONENT_STATUS_OK) {
138 goto end;
139 }
043e2020 140 break;
541b0a11 141 }
043e2020
JG
142 case BT_NOTIFICATION_TYPE_STREAM_END:
143 puts("</stream>");
78586d8a
JG
144 break;
145 default:
146 puts("Unhandled notification type");
147 }
541b0a11
JG
148end:
149 return ret;
4c1456f0 150}
bac67f0f 151
fec2a9f2
JG
152static
153enum bt_component_status run(struct bt_component *component)
154{
155 enum bt_component_status ret;
156 struct bt_notification *notification = NULL;
157 struct bt_notification_iterator *it;
158 struct text_component *text = bt_component_get_private_data(component);
159
160 ret = bt_component_sink_get_input_iterator(component, 0, &it);
161 if (ret != BT_COMPONENT_STATUS_OK) {
162 goto end;
163 }
164
f48bc732
JG
165 if (likely(text->processed_first_event)) {
166 enum bt_notification_iterator_status it_ret;
167
168 it_ret = bt_notification_iterator_next(it);
169 switch (it_ret) {
170 case BT_NOTIFICATION_ITERATOR_STATUS_ERROR:
171 ret = BT_COMPONENT_STATUS_ERROR;
fec2a9f2 172 goto end;
f48bc732
JG
173 case BT_NOTIFICATION_ITERATOR_STATUS_END:
174 ret = BT_COMPONENT_STATUS_END;
175 goto end;
176 default:
177 break;
fec2a9f2 178 }
fec2a9f2 179 }
fec2a9f2
JG
180 notification = bt_notification_iterator_get_notification(it);
181 if (!notification) {
182 ret = BT_COMPONENT_STATUS_ERROR;
183 goto end;
184 }
185
186 ret = handle_notification(text, notification);
f48bc732 187 text->processed_first_event = true;
fec2a9f2
JG
188end:
189 bt_put(it);
190 bt_put(notification);
191 return ret;
192}
193
6e1bc0df
MD
194static
195enum bt_component_status add_params_to_map(struct bt_value *plugin_opt_map)
196{
197 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
198 unsigned int i;
199
200 for (i = 0; i < BT_ARRAY_SIZE(plugin_options); i++) {
201 const char *key = plugin_options[i];
202 enum bt_value_status status;
203
204 status = bt_value_map_insert(plugin_opt_map, key, bt_value_null);
205 switch (status) {
206 case BT_VALUE_STATUS_OK:
207 break;
208 default:
209 ret = BT_COMPONENT_STATUS_ERROR;
210 goto end;
211 }
212 }
213end:
214 return ret;
215}
216
217static
218bool check_param_exists(const char *key, struct bt_value *object, void *data)
219{
220 struct text_component *text = data;
221 struct bt_value *plugin_opt_map = text->plugin_opt_map;
222
223 if (!bt_value_map_get(plugin_opt_map, key)) {
224 fprintf(text->err,
6ba0b073 225 "[warning] Parameter \"%s\" unknown to \"text\" plugin\n", key);
6e1bc0df
MD
226 }
227 return true;
228}
229
230static
231enum bt_component_status apply_one_string(const char *key,
232 struct bt_value *params,
233 char **option)
234{
235 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
236 struct bt_value *value = NULL;
237 enum bt_value_status status;
238 const char *str;
239
240 value = bt_value_map_get(params, key);
241 if (!value) {
242 goto end;
243 }
244 if (bt_value_is_null(value)) {
245 goto end;
246 }
247 status = bt_value_string_get(value, &str);
248 switch (status) {
249 case BT_VALUE_STATUS_OK:
250 break;
251 default:
252 ret = BT_COMPONENT_STATUS_ERROR;
253 goto end;
254 }
255 *option = g_strdup(str);
256end:
257 bt_put(value);
258 return ret;
259}
260
261static
262enum bt_component_status apply_one_bool(const char *key,
263 struct bt_value *params,
264 bool *option,
265 bool *found)
266{
267 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
268 struct bt_value *value = NULL;
269 enum bt_value_status status;
270
271 value = bt_value_map_get(params, key);
272 if (!value) {
273 goto end;
274 }
275 status = bt_value_bool_get(value, option);
276 switch (status) {
277 case BT_VALUE_STATUS_OK:
278 break;
279 default:
280 ret = BT_COMPONENT_STATUS_ERROR;
281 goto end;
282 }
283 if (found) {
284 *found = true;
285 }
286end:
287 bt_put(value);
288 return ret;
289}
290
291static
292enum bt_component_status apply_params(struct text_component *text,
293 struct bt_value *params)
294{
295 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
296 enum bt_value_status status;
297 bool value, found;
298 char *str = NULL;
299
300 text->plugin_opt_map = bt_value_map_create();
301 if (!text->plugin_opt_map) {
302 ret = BT_COMPONENT_STATUS_ERROR;
303 goto end;
304 }
305 ret = add_params_to_map(text->plugin_opt_map);
306 if (ret != BT_COMPONENT_STATUS_OK) {
307 goto end;
308 }
309 /* Report unknown parameters. */
310 status = bt_value_map_foreach(params, check_param_exists, text);
311 switch (status) {
312 case BT_VALUE_STATUS_OK:
313 break;
314 default:
315 ret = BT_COMPONENT_STATUS_ERROR;
316 goto end;
317 }
318 /* Known parameters. */
319 ret = apply_one_string("output-path",
320 params,
321 &text->options.output_path);
322 if (ret != BT_COMPONENT_STATUS_OK) {
323 goto end;
324 }
325
326 ret = apply_one_string("debug-info-dir",
327 params,
328 &text->options.debug_info_dir);
329 if (ret != BT_COMPONENT_STATUS_OK) {
330 goto end;
331 }
332
333 ret = apply_one_string("debug-info-target-prefix",
334 params,
335 &text->options.debug_info_target_prefix);
336 if (ret != BT_COMPONENT_STATUS_OK) {
337 goto end;
338 }
339
340 value = false; /* Default. */
341 ret = apply_one_bool("debug-info-full-path", params, &value, NULL);
342 if (ret != BT_COMPONENT_STATUS_OK) {
343 goto end;
344 }
345 text->options.debug_info_full_path = value;
346
347 value = false; /* Default. */
348 ret = apply_one_bool("no-delta", params, &value, NULL);
349 if (ret != BT_COMPONENT_STATUS_OK) {
350 goto end;
351 }
352 text->options.print_delta_field = !value; /* Reverse logic. */
353
354 value = false; /* Default. */
355 ret = apply_one_bool("clock-cycles", params, &value, NULL);
356 if (ret != BT_COMPONENT_STATUS_OK) {
357 goto end;
358 }
359 text->options.print_timestamp_cycles = value;
360
361 value = false; /* Default. */
362 ret = apply_one_bool("clock-seconds", params, &value, NULL);
363 if (ret != BT_COMPONENT_STATUS_OK) {
364 goto end;
365 }
366 text->options.clock_seconds = value;
367
368 value = false; /* Default. */
369 ret = apply_one_bool("clock-date", params, &value, NULL);
370 if (ret != BT_COMPONENT_STATUS_OK) {
371 goto end;
372 }
373 text->options.clock_date = value;
374
375 value = false; /* Default. */
376 ret = apply_one_bool("clock-gmt", params, &value, NULL);
377 if (ret != BT_COMPONENT_STATUS_OK) {
378 goto end;
379 }
380 text->options.clock_gmt = value;
381
382 /* Names. */
383 ret = apply_one_string("name-default", params, &str);
384 if (ret != BT_COMPONENT_STATUS_OK) {
385 goto end;
386 }
387 if (!str) {
388 text->options.name_default = TEXT_DEFAULT_UNSET;
389 } else if (!strcmp(str, "show")) {
390 text->options.name_default = TEXT_DEFAULT_SHOW;
391 } else if (!strcmp(str, "hide")) {
392 text->options.name_default = TEXT_DEFAULT_HIDE;
393 } else {
394 ret = BT_COMPONENT_STATUS_ERROR;
395 goto end;
396 }
397 g_free(str);
398 str = NULL;
399
400 switch (text->options.name_default) {
401 case TEXT_DEFAULT_UNSET:
402 text->options.print_payload_field_names = true;
403 text->options.print_context_field_names = true;
404 text->options.print_header_field_names = false;
405 text->options.print_scope_field_names = false;
406 break;
407 case TEXT_DEFAULT_SHOW:
408 text->options.print_payload_field_names = true;
409 text->options.print_context_field_names = true;
410 text->options.print_header_field_names = true;
411 text->options.print_scope_field_names = true;
412 break;
413 case TEXT_DEFAULT_HIDE:
414 text->options.print_payload_field_names = false;
415 text->options.print_context_field_names = false;
416 text->options.print_header_field_names = false;
417 text->options.print_scope_field_names = false;
418 break;
419 default:
420 ret = BT_COMPONENT_STATUS_ERROR;
421 goto end;
422 }
423
424 value = false;
425 found = false;
426 ret = apply_one_bool("name-payload", params, &value, &found);
427 if (ret != BT_COMPONENT_STATUS_OK) {
428 goto end;
429 }
430 if (found) {
431 text->options.print_payload_field_names = value;
432 }
433
434 value = false;
435 found = false;
436 ret = apply_one_bool("name-context", params, &value, &found);
437 if (ret != BT_COMPONENT_STATUS_OK) {
438 goto end;
439 }
440 if (found) {
441 text->options.print_context_field_names = value;
442 }
443
444 value = false;
445 found = false;
446 ret = apply_one_bool("name-header", params, &value, &found);
447 if (ret != BT_COMPONENT_STATUS_OK) {
448 goto end;
449 }
450 if (found) {
451 text->options.print_header_field_names = value;
452 }
453
454 value = false;
455 found = false;
456 ret = apply_one_bool("name-scope", params, &value, &found);
457 if (ret != BT_COMPONENT_STATUS_OK) {
458 goto end;
459 }
460 if (found) {
461 text->options.print_scope_field_names = value;
462 }
463
464 /* Fields. */
465 ret = apply_one_string("field-default", params, &str);
466 if (ret != BT_COMPONENT_STATUS_OK) {
467 goto end;
468 }
469 if (!str) {
470 text->options.field_default = TEXT_DEFAULT_UNSET;
471 } else if (!strcmp(str, "show")) {
472 text->options.field_default = TEXT_DEFAULT_SHOW;
473 } else if (!strcmp(str, "hide")) {
474 text->options.field_default = TEXT_DEFAULT_HIDE;
475 } else {
476 ret = BT_COMPONENT_STATUS_ERROR;
477 goto end;
478 }
479 g_free(str);
480 str = NULL;
481
482 switch (text->options.field_default) {
483 case TEXT_DEFAULT_UNSET:
484 text->options.print_trace_field = false;
485 text->options.print_trace_hostname_field = true;
486 text->options.print_trace_domain_field = false;
487 text->options.print_trace_procname_field = true;
488 text->options.print_trace_vpid_field = true;
489 text->options.print_loglevel_field = false;
490 text->options.print_emf_field = false;
491 text->options.print_emf_field = false;
6e1bc0df
MD
492 break;
493 case TEXT_DEFAULT_SHOW:
494 text->options.print_trace_field = true;
495 text->options.print_trace_hostname_field = true;
496 text->options.print_trace_domain_field = true;
497 text->options.print_trace_procname_field = true;
498 text->options.print_trace_vpid_field = true;
499 text->options.print_loglevel_field = true;
500 text->options.print_emf_field = true;
501 text->options.print_emf_field = true;
6e1bc0df
MD
502 break;
503 case TEXT_DEFAULT_HIDE:
504 text->options.print_trace_field = false;
505 text->options.print_trace_hostname_field = false;
506 text->options.print_trace_domain_field = false;
507 text->options.print_trace_procname_field = false;
508 text->options.print_trace_vpid_field = false;
509 text->options.print_loglevel_field = false;
510 text->options.print_emf_field = false;
511 text->options.print_emf_field = false;
6e1bc0df
MD
512 break;
513 default:
514 ret = BT_COMPONENT_STATUS_ERROR;
515 goto end;
516 }
517
518 value = false;
519 found = false;
520 ret = apply_one_bool("field-trace", params, &value, &found);
521 if (ret != BT_COMPONENT_STATUS_OK) {
522 goto end;
523 }
524 if (found) {
525 text->options.print_trace_field = value;
526 }
527
528 value = false;
529 found = false;
530 ret = apply_one_bool("field-trace:hostname", params, &value, &found);
531 if (ret != BT_COMPONENT_STATUS_OK) {
532 goto end;
533 }
534 if (found) {
535 text->options.print_trace_hostname_field = value;
536 }
537
538 value = false;
539 found = false;
540 ret = apply_one_bool("field-trace:domain", params, &value, &found);
541 if (ret != BT_COMPONENT_STATUS_OK) {
542 goto end;
543 }
544 if (found) {
545 text->options.print_trace_domain_field = value;
546 }
547
548 value = false;
549 found = false;
550 ret = apply_one_bool("field-trace:procname", params, &value, &found);
551 if (ret != BT_COMPONENT_STATUS_OK) {
552 goto end;
553 }
554 if (found) {
555 text->options.print_trace_procname_field = value;
556 }
557
558 value = false;
559 found = false;
560 ret = apply_one_bool("field-trace:vpid", params, &value, &found);
561 if (ret != BT_COMPONENT_STATUS_OK) {
562 goto end;
563 }
564 if (found) {
565 text->options.print_trace_vpid_field = value;
566 }
567
568 value = false;
569 found = false;
570 ret = apply_one_bool("field-loglevel", params, &value, &found);
571 if (ret != BT_COMPONENT_STATUS_OK) {
572 goto end;
573 }
574 if (found) {
575 text->options.print_loglevel_field = value;
576 }
577
578 value = false;
579 found = false;
580 ret = apply_one_bool("field-emf", params, &value, &found);
581 if (ret != BT_COMPONENT_STATUS_OK) {
582 goto end;
583 }
584 if (found) {
585 text->options.print_emf_field = value;
586 }
587
588 value = false;
589 found = false;
590 ret = apply_one_bool("field-emf", params, &value, &found);
591 if (ret != BT_COMPONENT_STATUS_OK) {
592 goto end;
593 }
594 if (found) {
595 text->options.print_emf_field = value;
596 }
597
6e1bc0df
MD
598end:
599 bt_put(text->plugin_opt_map);
600 text->plugin_opt_map = NULL;
601 g_free(str);
602 return ret;
603}
604
bac67f0f
JG
605static
606enum bt_component_status text_component_init(
6e1bc0df 607 struct bt_component *component, struct bt_value *params)
bac67f0f
JG
608{
609 enum bt_component_status ret;
610 struct text_component *text = create_text();
611
612 if (!text) {
613 ret = BT_COMPONENT_STATUS_NOMEM;
614 goto end;
615 }
616
6e1bc0df
MD
617 text->out = stdout;
618 text->err = stderr;
619
3af83b5a
MD
620 text->delta_cycles = -1ULL;
621 text->last_cycles_timestamp = -1ULL;
622
623 text->delta_real_timestamp = -1ULL;
624 text->last_real_timestamp = -1ULL;
625
6e1bc0df
MD
626 ret = apply_params(text, params);
627 if (ret != BT_COMPONENT_STATUS_OK) {
628 goto error;
629 }
630
a97c4b1a 631 ret = bt_component_set_destroy_cb(component,
e78cdc59 632 destroy_text);
bac67f0f
JG
633 if (ret != BT_COMPONENT_STATUS_OK) {
634 goto error;
635 }
636
637 ret = bt_component_set_private_data(component, text);
638 if (ret != BT_COMPONENT_STATUS_OK) {
639 goto error;
640 }
641
fec2a9f2
JG
642 ret = bt_component_sink_set_consume_cb(component,
643 run);
bac67f0f
JG
644 if (ret != BT_COMPONENT_STATUS_OK) {
645 goto error;
646 }
647end:
648 return ret;
649error:
b25bd455 650 destroy_text_data(text);
bac67f0f
JG
651 return ret;
652}
653
bac67f0f 654/* Initialize plug-in entry points. */
6ba0b073 655BT_PLUGIN(text);
bac67f0f
JG
656BT_PLUGIN_DESCRIPTION("Babeltrace text output plug-in.");
657BT_PLUGIN_AUTHOR("Jérémie Galarneau");
658BT_PLUGIN_LICENSE("MIT");
6ba0b073
PP
659BT_PLUGIN_COMPONENT_CLASS(BT_COMPONENT_TYPE_SINK, text,
660 text_component_init);
661BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION(BT_COMPONENT_TYPE_SINK, text,
662 "Formats CTF-IR to text. Formerly known as ctf-text.");
This page took 0.055639 seconds and 4 git commands to generate.