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