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