ddb3b0ee5d15a8bd72fdd9939a9423fe7a9e57e9
[babeltrace.git] / converter / babeltrace.c
1 /*
2 * babeltrace.c
3 *
4 * Babeltrace Trace Converter
5 *
6 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
7 *
8 * Author: Mathieu Desnoyers <mathieu.desnoyers@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
29 #include <babeltrace/babeltrace.h>
30 #include <babeltrace/plugin/plugin.h>
31 #include <babeltrace/common-internal.h>
32 #include <babeltrace/component/component.h>
33 #include <babeltrace/component/component-source.h>
34 #include <babeltrace/component/component-sink.h>
35 #include <babeltrace/component/component-filter.h>
36 #include <babeltrace/component/component-class.h>
37 #include <babeltrace/component/notification/iterator.h>
38 #include <babeltrace/ref.h>
39 #include <babeltrace/values.h>
40 #include <stdlib.h>
41 #include <babeltrace/ctf-ir/metadata.h> /* for clocks */
42 #include <popt.h>
43 #include <string.h>
44 #include <stdio.h>
45 #include <glib.h>
46 #include "babeltrace-cfg.h"
47 #include "default-cfg.h"
48
49 GPtrArray *loaded_plugins;
50
51 static
52 void init_loaded_plugins_array(void)
53 {
54 loaded_plugins = g_ptr_array_new_full(8, bt_put);
55 }
56
57 static
58 void fini_loaded_plugins_array(void)
59 {
60 g_ptr_array_free(loaded_plugins, TRUE);
61 }
62
63 static
64 struct bt_plugin *find_plugin(const char *name)
65 {
66 int i;
67 struct bt_plugin *plugin = NULL;
68
69 for (i = 0; i < loaded_plugins->len; i++) {
70 plugin = g_ptr_array_index(loaded_plugins, i);
71
72 if (strcmp(name, bt_plugin_get_name(plugin)) == 0) {
73 break;
74 }
75
76 plugin = NULL;
77 }
78
79 return bt_get(plugin);
80 }
81
82 static
83 struct bt_component_class *find_component_class(const char *plugin_name,
84 const char *comp_class_name,
85 enum bt_component_class_type comp_class_type)
86 {
87 struct bt_component_class *comp_class = NULL;
88 struct bt_plugin *plugin = find_plugin(plugin_name);
89
90 if (!plugin) {
91 goto end;
92 }
93
94 comp_class = bt_plugin_get_component_class_by_name_and_type(plugin,
95 comp_class_name, comp_class_type);
96 BT_PUT(plugin);
97 end:
98 return comp_class;
99 }
100
101 static
102 void print_indent(size_t indent)
103 {
104 size_t i;
105
106 for (i = 0; i < indent; i++) {
107 printf(" ");
108 }
109 }
110
111 static
112 void print_value(struct bt_value *, size_t);
113
114 static
115 bool print_map_value(const char *key, struct bt_value *object, void *data)
116 {
117 size_t *indent = data;
118
119 print_indent(*indent);
120 printf("%s: ", key);
121
122 if (bt_value_is_array(object) &&
123 bt_value_array_is_empty(object)) {
124 printf("[ ]\n");
125 return true;
126 }
127
128 if (bt_value_is_map(object) &&
129 bt_value_map_is_empty(object)) {
130 printf("{ }\n");
131 return true;
132 }
133
134 if (bt_value_is_array(object) ||
135 bt_value_is_map(object)) {
136 printf("\n");
137 }
138
139 print_value(object, *indent + 2);
140 return true;
141 }
142
143 static
144 void print_value(struct bt_value *value, size_t indent)
145 {
146 bool bool_val;
147 int64_t int_val;
148 double dbl_val;
149 const char *str_val;
150 int size;
151 int i;
152
153 if (!value) {
154 return;
155 }
156
157 switch (bt_value_get_type(value)) {
158 case BT_VALUE_TYPE_NULL:
159 printf("null\n");
160 break;
161 case BT_VALUE_TYPE_BOOL:
162 bt_value_bool_get(value, &bool_val);
163 printf("%s\n", bool_val ? "yes" : "no");
164 break;
165 case BT_VALUE_TYPE_INTEGER:
166 bt_value_integer_get(value, &int_val);
167 printf("%" PRId64 "\n", int_val);
168 break;
169 case BT_VALUE_TYPE_FLOAT:
170 bt_value_float_get(value, &dbl_val);
171 printf("%lf\n", dbl_val);
172 break;
173 case BT_VALUE_TYPE_STRING:
174 bt_value_string_get(value, &str_val);
175 printf("%s\n", str_val);
176 break;
177 case BT_VALUE_TYPE_ARRAY:
178 size = bt_value_array_size(value);
179 assert(size >= 0);
180
181 if (size == 0) {
182 print_indent(indent);
183 printf("[ ]\n");
184 break;
185 }
186
187 for (i = 0; i < size; i++) {
188 struct bt_value *element =
189 bt_value_array_get(value, i);
190
191 assert(element);
192 print_indent(indent);
193 printf("- ");
194
195 if (bt_value_is_array(element) &&
196 bt_value_array_is_empty(element)) {
197 printf("[ ]\n");
198 continue;
199 }
200
201 if (bt_value_is_map(element) &&
202 bt_value_map_is_empty(element)) {
203 printf("{ }\n");
204 continue;
205 }
206
207 if (bt_value_is_array(element) ||
208 bt_value_is_map(element)) {
209 printf("\n");
210 }
211
212 print_value(element, indent + 2);
213 BT_PUT(element);
214 }
215 break;
216 case BT_VALUE_TYPE_MAP:
217 if (bt_value_map_is_empty(value)) {
218 print_indent(indent);
219 printf("{ }\n");
220 break;
221 }
222
223 bt_value_map_foreach(value, print_map_value, &indent);
224 break;
225 default:
226 assert(false);
227 }
228 }
229
230 static
231 void print_bt_config_component(struct bt_config_component *bt_config_component)
232 {
233 printf(" %s.%s:\n", bt_config_component->plugin_name->str,
234 bt_config_component->component_name->str);
235 printf(" Parameters:\n");
236 print_value(bt_config_component->params, 8);
237 }
238
239 static
240 void print_bt_config_components(GPtrArray *array)
241 {
242 size_t i;
243
244 for (i = 0; i < array->len; i++) {
245 struct bt_config_component *cfg_component =
246 bt_config_get_component(array, i);
247 print_bt_config_component(cfg_component);
248 BT_PUT(cfg_component);
249 }
250 }
251
252 static
253 void print_plugin_paths(struct bt_value *plugin_paths)
254 {
255 printf(" Plugin paths:\n");
256 print_value(plugin_paths, 4);
257 }
258
259 static
260 void print_cfg_convert(struct bt_config *cfg)
261 {
262 printf(" Force correlate: %s\n",
263 cfg->cmd_data.convert.force_correlate ? "yes" : "no");
264 print_plugin_paths(cfg->cmd_data.convert.plugin_paths);
265 printf(" Source component instances:\n");
266 print_bt_config_components(cfg->cmd_data.convert.sources);
267 printf(" Sink component instances:\n");
268 print_bt_config_components(cfg->cmd_data.convert.sinks);
269 }
270
271 static
272 void print_cfg_list_plugins(struct bt_config *cfg)
273 {
274 print_plugin_paths(cfg->cmd_data.list_plugins.plugin_paths);
275 }
276
277 static
278 void print_cfg(struct bt_config *cfg)
279 {
280 if (!babeltrace_verbose) {
281 return;
282 }
283
284 printf("Configuration:\n");
285 printf(" Debug mode: %s\n", cfg->debug ? "yes" : "no");
286 printf(" Verbose mode: %s\n", cfg->verbose ? "yes" : "no");
287
288 switch (cfg->command) {
289 case BT_CONFIG_COMMAND_CONVERT:
290 print_cfg_convert(cfg);
291 break;
292 case BT_CONFIG_COMMAND_LIST_PLUGINS:
293 print_cfg_list_plugins(cfg);
294 break;
295 default:
296 assert(false);
297 }
298 }
299
300 static
301 struct bt_component *create_trimmer(struct bt_config_component *source_cfg)
302 {
303 struct bt_component *trimmer = NULL;
304 struct bt_component_class *trimmer_class = NULL;
305 struct bt_value *trimmer_params = NULL;
306 struct bt_value *value;
307
308 trimmer_params = bt_value_map_create();
309 if (!trimmer_params) {
310 goto end;
311 }
312
313 value = bt_value_map_get(source_cfg->params, "begin");
314 if (value) {
315 enum bt_value_status ret;
316
317 ret = bt_value_map_insert(trimmer_params, "begin",
318 value);
319 BT_PUT(value);
320 if (ret) {
321 goto end;
322 }
323 }
324 value = bt_value_map_get(source_cfg->params, "end");
325 if (value) {
326 enum bt_value_status ret;
327
328 ret = bt_value_map_insert(trimmer_params, "end",
329 value);
330 BT_PUT(value);
331 if (ret) {
332 goto end;
333 }
334 }
335 value = bt_value_map_get(source_cfg->params, "clock-gmt");
336 if (value) {
337 enum bt_value_status ret;
338
339 ret = bt_value_map_insert(trimmer_params, "clock-gmt",
340 value);
341 BT_PUT(value);
342 if (ret) {
343 goto end;
344 }
345 }
346
347 trimmer_class = find_component_class("utils", "trimmer",
348 BT_COMPONENT_CLASS_TYPE_FILTER);
349 if (!trimmer_class) {
350 fprintf(stderr, "Could not find trimmer component class. Aborting...\n");
351 goto end;
352 }
353 trimmer = bt_component_create(trimmer_class, "source_trimmer",
354 trimmer_params);
355 if (!trimmer) {
356 goto end;
357 }
358 end:
359 bt_put(trimmer_params);
360 bt_put(trimmer_class);
361 return trimmer;
362 }
363
364 static
365 int connect_source_sink(struct bt_component *source,
366 struct bt_config_component *source_cfg,
367 struct bt_component *sink)
368 {
369 int ret = 0;
370 enum bt_component_status sink_status;
371 struct bt_component *trimmer = NULL;
372 struct bt_notification_iterator *source_it = NULL;
373 struct bt_notification_iterator *to_sink_it = NULL;
374
375 source_it = bt_component_source_create_notification_iterator(source);
376 if (!source_it) {
377 fprintf(stderr, "Failed to instantiate source iterator. Aborting...\n");
378 ret = -1;
379 goto end;
380 }
381
382 if (bt_value_map_has_key(source_cfg->params, "begin")
383 || bt_value_map_has_key(source_cfg->params, "end")) {
384 /* A trimmer must be inserted in the graph. */
385 enum bt_component_status trimmer_status;
386
387 trimmer = create_trimmer(source_cfg);
388 if (!trimmer) {
389 fprintf(stderr, "Failed to create trimmer component. Aborting...\n");
390 ret = -1;
391 goto end;
392 }
393
394 trimmer_status = bt_component_filter_add_iterator(trimmer,
395 source_it);
396 BT_PUT(source_it);
397 if (trimmer_status != BT_COMPONENT_STATUS_OK) {
398 fprintf(stderr, "Failed to connect source to trimmer. Aborting...\n");
399 ret = -1;
400 goto end;
401 }
402
403 to_sink_it = bt_component_filter_create_notification_iterator(trimmer);
404 if (!to_sink_it) {
405 fprintf(stderr, "Failed to instantiate trimmer iterator. Aborting...\n");
406 ret = -1;
407 goto end;
408 }
409 } else {
410 BT_MOVE(to_sink_it, source_it);
411 }
412
413 sink_status = bt_component_sink_add_iterator(sink, to_sink_it);
414 if (sink_status != BT_COMPONENT_STATUS_OK) {
415 fprintf(stderr, "Failed to connect to sink component. Aborting...\n");
416 ret = -1;
417 goto end;
418 }
419 end:
420 bt_put(trimmer);
421 bt_put(source_it);
422 bt_put(to_sink_it);
423 return ret;
424 }
425
426 static
427 void add_to_loaded_plugins(struct bt_plugin **plugins)
428 {
429 while (*plugins) {
430 struct bt_plugin *plugin = *plugins;
431 /* Check if it's already loaded (from another path). */
432 struct bt_plugin *loaded_plugin =
433 find_plugin(bt_plugin_get_name(plugin));
434
435 if (loaded_plugin) {
436 printf_verbose("Not loading plugin `%s`: already loaded from `%s`\n",
437 bt_plugin_get_path(plugin),
438 bt_plugin_get_path(loaded_plugin));
439 BT_PUT(loaded_plugin);
440 BT_PUT(plugin);
441 } else {
442 /* Transfer ownership to global array. */
443 g_ptr_array_add(loaded_plugins, plugin);
444 }
445 *(plugins++) = NULL;
446 }
447 }
448
449 static
450 int load_dynamic_plugins(struct bt_value *plugin_paths)
451 {
452 int nr_paths, i, ret = 0;
453
454 nr_paths = bt_value_array_size(plugin_paths);
455 if (nr_paths < 0) {
456 ret = -1;
457 goto end;
458 }
459
460 for (i = 0; i < nr_paths; i++) {
461 struct bt_value *plugin_path_value = NULL;
462 const char *plugin_path;
463 struct bt_plugin **plugins;
464
465 plugin_path_value = bt_value_array_get(plugin_paths, i);
466 if (bt_value_string_get(plugin_path_value,
467 &plugin_path)) {
468 BT_PUT(plugin_path_value);
469 continue;
470 }
471
472 plugins = bt_plugin_create_all_from_dir(plugin_path, false);
473 if (!plugins) {
474 printf_debug("Unable to dynamically load plugins from path %s.\n",
475 plugin_path);
476 BT_PUT(plugin_path_value);
477 continue;
478 }
479
480 add_to_loaded_plugins(plugins);
481 free(plugins);
482
483 BT_PUT(plugin_path_value);
484 }
485 end:
486 return ret;
487 }
488
489 static
490 int load_static_plugins(void)
491 {
492 int ret = 0;
493 struct bt_plugin **plugins;
494
495 plugins = bt_plugin_create_all_from_static();
496 if (!plugins) {
497 printf_debug("Unable to load static plugins.\n");
498 ret = -1;
499 goto end;
500 }
501
502 add_to_loaded_plugins(plugins);
503 free(plugins);
504 end:
505 return ret;
506 }
507
508 static
509 const char *component_type_str(enum bt_component_class_type type)
510 {
511 switch (type) {
512 case BT_COMPONENT_CLASS_TYPE_SOURCE:
513 return "source";
514 case BT_COMPONENT_CLASS_TYPE_SINK:
515 return "sink";
516 case BT_COMPONENT_CLASS_TYPE_FILTER:
517 return "filter";
518 case BT_COMPONENT_CLASS_TYPE_UNKNOWN:
519 default:
520 return "unknown";
521 }
522 }
523
524 static int load_all_plugins(struct bt_value *plugin_paths)
525 {
526 int ret = 0;
527
528 if (load_dynamic_plugins(plugin_paths)) {
529 fprintf(stderr, "Failed to load dynamic plugins.\n");
530 ret = -1;
531 goto end;
532 }
533
534 if (load_static_plugins()) {
535 fprintf(stderr, "Failed to load static plugins.\n");
536 ret = -1;
537 goto end;
538 }
539
540 end:
541 return ret;
542 }
543
544 static void print_plugin_info(struct bt_plugin *plugin)
545 {
546 unsigned int major, minor, patch;
547 const char *extra;
548 enum bt_plugin_status version_status;
549 const char *plugin_name;
550 const char *path;
551 const char *author;
552 const char *license;
553 const char *plugin_description;
554
555 plugin_name = bt_plugin_get_name(plugin);
556 path = bt_plugin_get_path(plugin);
557 author = bt_plugin_get_author(plugin);
558 license = bt_plugin_get_license(plugin);
559 plugin_description = bt_plugin_get_description(plugin);
560 version_status = bt_plugin_get_version(plugin, &major, &minor,
561 &patch, &extra);
562 printf("%s%s%s%s:\n", bt_common_color_bold(),
563 bt_common_color_fg_blue(), plugin_name,
564 bt_common_color_reset());
565 printf(" %sPath%s: %s\n", bt_common_color_bold(),
566 bt_common_color_reset(), path ? path : "(None)");
567
568 if (version_status == BT_PLUGIN_STATUS_OK) {
569 printf(" %sVersion%s: %u.%u.%u",
570 bt_common_color_bold(), bt_common_color_reset(),
571 major, minor, patch);
572
573 if (extra) {
574 printf("%s", extra);
575 }
576
577 printf("\n");
578 }
579
580 printf(" %sDescription%s: %s\n", bt_common_color_bold(),
581 bt_common_color_reset(),
582 plugin_description ? plugin_description : "(None)");
583 printf(" %sAuthor%s: %s\n", bt_common_color_bold(),
584 bt_common_color_reset(), author ? author : "(Unknown)");
585 printf(" %sLicense%s: %s\n", bt_common_color_bold(),
586 bt_common_color_reset(),
587 license ? license : "(Unknown)");
588 }
589
590 static void print_plugin_comp_cls_opt(FILE *fh, const char *plugin_name,
591 const char *comp_cls_name, enum bt_component_class_type type)
592 {
593 fprintf(fh, "%s%s--%s%s %s%s%s.%s%s%s",
594 bt_common_color_bold(),
595 bt_common_color_fg_cyan(),
596 component_type_str(type),
597 bt_common_color_fg_default(),
598 bt_common_color_fg_blue(),
599 plugin_name,
600 bt_common_color_fg_default(),
601 bt_common_color_fg_yellow(),
602 comp_cls_name,
603 bt_common_color_reset());
604 }
605
606 static int cmd_help(struct bt_config *cfg)
607 {
608 int ret;
609 struct bt_plugin *plugin = NULL;
610 size_t i;
611
612 ret = load_all_plugins(cfg->cmd_data.list_plugins.plugin_paths);
613 if (ret) {
614 goto end;
615 }
616
617 plugin = find_plugin(cfg->cmd_data.help.plugin_name->str);
618 if (!plugin) {
619 fprintf(stderr, "%s%sCannot find plugin %s%s%s\n",
620 bt_common_color_bold(), bt_common_color_fg_red(),
621 bt_common_color_fg_blue(),
622 cfg->cmd_data.help.plugin_name->str,
623 bt_common_color_reset());
624 ret = -1;
625 goto end;
626 }
627
628 print_plugin_info(plugin);
629 printf(" %sComponent classes%s: %d\n",
630 bt_common_color_bold(),
631 bt_common_color_reset(),
632 bt_plugin_get_component_class_count(plugin));
633
634
635 if (cfg->cmd_data.help.comp_cls_type !=
636 BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
637 struct bt_component_class *needed_comp_cls =
638 find_component_class(
639 cfg->cmd_data.help.plugin_name->str,
640 cfg->cmd_data.help.component_name->str,
641 cfg->cmd_data.help.comp_cls_type);
642
643 if (!needed_comp_cls) {
644 fprintf(stderr, "\n%s%sCannot find component class %s",
645 bt_common_color_bold(),
646 bt_common_color_fg_red(),
647 bt_common_color_reset());
648 print_plugin_comp_cls_opt(stderr,
649 cfg->cmd_data.help.plugin_name->str,
650 cfg->cmd_data.help.component_name->str,
651 cfg->cmd_data.help.comp_cls_type);
652 fprintf(stderr, "\n");
653 ret = -1;
654 goto end;
655 }
656
657 bt_put(needed_comp_cls);
658 }
659
660 for (i = 0; i < bt_plugin_get_component_class_count(plugin); i++) {
661 struct bt_component_class *comp_cls =
662 bt_plugin_get_component_class(plugin, i);
663 const char *comp_class_name =
664 bt_component_class_get_name(comp_cls);
665 const char *comp_class_description =
666 bt_component_class_get_description(comp_cls);
667 const char *comp_class_help =
668 bt_component_class_get_help(comp_cls);
669 enum bt_component_class_type type =
670 bt_component_class_get_type(comp_cls);
671
672 assert(comp_cls);
673
674 if (cfg->cmd_data.help.comp_cls_type !=
675 BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
676 if (strcmp(cfg->cmd_data.help.component_name->str,
677 comp_class_name) != 0 &&
678 type ==
679 cfg->cmd_data.help.comp_cls_type) {
680 bt_put(comp_cls);
681 continue;
682 }
683 }
684
685 printf("\n");
686 print_plugin_comp_cls_opt(stdout,
687 cfg->cmd_data.help.plugin_name->str,
688 comp_class_name,
689 type);
690 printf("\n");
691 printf(" %sDescription%s: %s\n", bt_common_color_bold(),
692 bt_common_color_reset(),
693 comp_class_description ? comp_class_description : "(None)");
694
695 if (comp_class_help) {
696 printf("\n%s\n", comp_class_help);
697 }
698
699 bt_put(comp_cls);
700 }
701
702 end:
703 bt_put(plugin);
704 return ret;
705 }
706
707 static int cmd_list_plugins(struct bt_config *cfg)
708 {
709 int ret;
710 int plugins_count, component_classes_count = 0, i;
711
712 ret = load_all_plugins(cfg->cmd_data.list_plugins.plugin_paths);
713 if (ret) {
714 goto end;
715 }
716
717 printf("From the following plugin paths:\n\n");
718 print_value(cfg->cmd_data.list_plugins.plugin_paths, 2);
719 printf("\n");
720 plugins_count = loaded_plugins->len;
721 if (plugins_count == 0) {
722 fprintf(stderr, "%s%sNo plugins found.%s\n",
723 bt_common_color_bold(), bt_common_color_fg_red(),
724 bt_common_color_reset());
725 fprintf(stderr, "\n");
726 fprintf(stderr, "Please make sure your plugin search path is set correctly. You can use\n");
727 fprintf(stderr, "the --plugin-path command-line option or the BABELTRACE_PLUGIN_PATH\n");
728 fprintf(stderr, "environment variable.\n");
729 ret = -1;
730 goto end;
731 }
732
733 for (i = 0; i < plugins_count; i++) {
734 struct bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i);
735
736 component_classes_count += bt_plugin_get_component_class_count(plugin);
737 }
738
739 printf("Found %s%d%s component classes in %s%d%s plugins.\n",
740 bt_common_color_bold(),
741 component_classes_count,
742 bt_common_color_reset(),
743 bt_common_color_bold(),
744 plugins_count,
745 bt_common_color_reset());
746
747 for (i = 0; i < plugins_count; i++) {
748 int j;
749 struct bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i);
750
751 component_classes_count =
752 bt_plugin_get_component_class_count(plugin);
753 printf("\n");
754 print_plugin_info(plugin);
755
756 if (component_classes_count == 0) {
757 printf(" %sComponent classes%s: (None)\n",
758 bt_common_color_bold(),
759 bt_common_color_reset());
760 } else {
761 printf(" %sComponent classes%s:\n",
762 bt_common_color_bold(),
763 bt_common_color_reset());
764 }
765
766 for (j = 0; j < component_classes_count; j++) {
767 struct bt_component_class *comp_class =
768 bt_plugin_get_component_class(plugin, j);
769 const char *comp_class_name =
770 bt_component_class_get_name(comp_class);
771 const char *comp_class_description =
772 bt_component_class_get_description(comp_class);
773 enum bt_component_class_type type =
774 bt_component_class_get_type(comp_class);
775
776 printf(" ");
777 print_plugin_comp_cls_opt(stdout,
778 bt_plugin_get_name(plugin), comp_class_name,
779 type);
780
781 if (comp_class_description) {
782 printf(": %s", comp_class_description);
783 }
784
785 printf("\n");
786 bt_put(comp_class);
787 }
788 }
789
790 end:
791 return ret;
792 }
793
794 static int cmd_convert(struct bt_config *cfg)
795 {
796 int ret = 0;
797 struct bt_component_class *source_class = NULL;
798 struct bt_component_class *sink_class = NULL;
799 struct bt_component *source = NULL, *sink = NULL;
800 struct bt_value *source_params = NULL, *sink_params = NULL;
801 enum bt_component_status sink_status;
802 struct bt_config_component *source_cfg = NULL, *sink_cfg = NULL;
803
804 /* TODO handle more than 1 source and 1 sink. */
805 if (cfg->cmd_data.convert.sources->len != 1 ||
806 cfg->cmd_data.convert.sinks->len != 1) {
807 ret = -1;
808 goto end;
809 }
810
811 ret = load_all_plugins(cfg->cmd_data.convert.plugin_paths);
812 if (ret) {
813 goto end;
814 }
815
816 source_cfg = bt_config_get_component(cfg->cmd_data.convert.sources, 0);
817 source_params = bt_get(source_cfg->params);
818 source_class = find_component_class(source_cfg->plugin_name->str,
819 source_cfg->component_name->str,
820 BT_COMPONENT_CLASS_TYPE_SOURCE);
821 if (!source_class) {
822 fprintf(stderr, "Could not find %s.%s source component class. Aborting...\n",
823 source_cfg->plugin_name->str,
824 source_cfg->component_name->str);
825 ret = -1;
826 goto end;
827 }
828
829 sink_cfg = bt_config_get_component(cfg->cmd_data.convert.sinks, 0);
830 sink_params = bt_get(sink_cfg->params);
831 sink_class = find_component_class(sink_cfg->plugin_name->str,
832 sink_cfg->component_name->str,
833 BT_COMPONENT_CLASS_TYPE_SINK);
834 if (!sink_class) {
835 fprintf(stderr, "Could not find %s.%s output component class. Aborting...\n",
836 sink_cfg->plugin_name->str,
837 sink_cfg->component_name->str);
838 ret = -1;
839 goto end;
840 }
841
842 source = bt_component_create(source_class, "source", source_params);
843 if (!source) {
844 fprintf(stderr, "Failed to instantiate selected source component. Aborting...\n");
845 ret = -1;
846 goto end;
847 }
848
849 sink = bt_component_create(sink_class, "sink", sink_params);
850 if (!sink) {
851 fprintf(stderr, "Failed to instantiate selected output component. Aborting...\n");
852 ret = -1;
853 goto end;
854 }
855
856 ret = connect_source_sink(source, source_cfg, sink);
857 if (ret) {
858 ret = -1;
859 goto end;
860 }
861
862 while (true) {
863 sink_status = bt_component_sink_consume(sink);
864 switch (sink_status) {
865 case BT_COMPONENT_STATUS_AGAIN:
866 /* Wait for an arbitraty 500 ms. */
867 usleep(500000);
868 break;
869 case BT_COMPONENT_STATUS_OK:
870 break;
871 case BT_COMPONENT_STATUS_END:
872 goto end;
873 default:
874 fprintf(stderr, "Sink component returned an error, aborting...\n");
875 ret = -1;
876 goto end;
877 }
878 }
879
880 end:
881 BT_PUT(sink_class);
882 BT_PUT(source_class);
883 BT_PUT(source);
884 BT_PUT(sink);
885 BT_PUT(source_params);
886 BT_PUT(sink_params);
887 BT_PUT(sink_cfg);
888 BT_PUT(source_cfg);
889 return ret;
890 }
891
892 static void warn_command_name_and_directory_clash(struct bt_config *cfg)
893 {
894 if (!cfg->command_name) {
895 return;
896 }
897
898 if (g_file_test(cfg->command_name,
899 G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
900 fprintf(stderr, "\nNOTE: The `%s` command was executed. If you meant to convert a\n",
901 cfg->command_name);
902 fprintf(stderr, "trace located in the local `%s` directory, please use:\n",
903 cfg->command_name);
904 fprintf(stderr, "\n");
905 fprintf(stderr, " babeltrace convert %s [OPTIONS]\n",
906 cfg->command_name);
907 }
908 }
909
910 int main(int argc, const char **argv)
911 {
912 int ret;
913 int retcode;
914 struct bt_config *cfg;
915
916 init_loaded_plugins_array();
917 cfg = bt_config_from_args_with_defaults(argc, argv, &retcode);
918
919 if (retcode < 0) {
920 /* Quit without errors; typically usage/version */
921 retcode = 0;
922 goto end;
923 }
924
925 if (retcode > 0) {
926 goto end;
927 }
928
929 if (!cfg) {
930 fprintf(stderr, "Failed to create Babeltrace configuration\n");
931 goto end;
932 }
933
934 babeltrace_debug = cfg->debug;
935 babeltrace_verbose = cfg->verbose;
936 print_cfg(cfg);
937
938 switch (cfg->command) {
939 case BT_CONFIG_COMMAND_CONVERT:
940 ret = cmd_convert(cfg);
941 break;
942 case BT_CONFIG_COMMAND_LIST_PLUGINS:
943 ret = cmd_list_plugins(cfg);
944 break;
945 case BT_CONFIG_COMMAND_HELP:
946 ret = cmd_help(cfg);
947 break;
948 default:
949 assert(false);
950 }
951
952 warn_command_name_and_directory_clash(cfg);
953 retcode = ret ? 1 : 0;
954
955 end:
956 BT_PUT(cfg);
957 fini_loaded_plugins_array();
958 return retcode;
959 }
This page took 0.047695 seconds and 4 git commands to generate.