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