c94bf9675a59a49bc49cf86ea20e9593eca7cdea
[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(" Print CTF metadata: %s\n",
297 cfg->cmd_data.convert.print_ctf_metadata ? "yes" : "no");
298 printf(" Source component instances:\n");
299 print_bt_config_components(cfg->cmd_data.convert.sources);
300
301 if (cfg->cmd_data.convert.filters->len > 0) {
302 printf(" Filter component instances:\n");
303 print_bt_config_components(cfg->cmd_data.convert.filters);
304 }
305
306 printf(" Sink component instances:\n");
307 print_bt_config_components(cfg->cmd_data.convert.sinks);
308 printf(" Connections:\n");
309
310 for (i = 0; i < cfg->cmd_data.convert.connections->len; i++) {
311 struct bt_config_connection *cfg_connection =
312 g_ptr_array_index(cfg->cmd_data.convert.connections,
313 i);
314
315 printf(" %s%s%s -> %s%s%s\n",
316 cfg_connection->src_instance_name->str,
317 cfg_connection->src_port_name->len > 0 ? "." : "",
318 cfg_connection->src_port_name->str,
319 cfg_connection->dst_instance_name->str,
320 cfg_connection->dst_port_name->len > 0 ? "." : "",
321 cfg_connection->dst_port_name->str);
322 }
323 }
324
325 static
326 void print_cfg_list_plugins(struct bt_config *cfg)
327 {
328 print_plugin_paths(cfg->cmd_data.list_plugins.plugin_paths);
329 }
330
331 static
332 void print_cfg_help(struct bt_config *cfg)
333 {
334 print_plugin_paths(cfg->cmd_data.help.plugin_paths);
335 }
336
337 static
338 void print_cfg_query_info(struct bt_config *cfg)
339 {
340 print_plugin_paths(cfg->cmd_data.query_info.plugin_paths);
341 printf(" Action: `%s`\n", cfg->cmd_data.query_info.action->str);
342 printf(" Component class:\n");
343 print_bt_config_component(cfg->cmd_data.query_info.cfg_component);
344 }
345
346 static
347 void print_cfg(struct bt_config *cfg)
348 {
349 if (!babeltrace_verbose) {
350 return;
351 }
352
353 printf("Configuration:\n");
354 printf(" Debug mode: %s\n", cfg->debug ? "yes" : "no");
355 printf(" Verbose mode: %s\n", cfg->verbose ? "yes" : "no");
356
357 switch (cfg->command) {
358 case BT_CONFIG_COMMAND_CONVERT:
359 print_cfg_convert(cfg);
360 break;
361 case BT_CONFIG_COMMAND_LIST_PLUGINS:
362 print_cfg_list_plugins(cfg);
363 break;
364 case BT_CONFIG_COMMAND_HELP:
365 print_cfg_help(cfg);
366 break;
367 case BT_CONFIG_COMMAND_QUERY_INFO:
368 print_cfg_query_info(cfg);
369 break;
370 default:
371 assert(false);
372 }
373 }
374
375 static
376 struct bt_component *create_trimmer(struct bt_config_component *source_cfg)
377 {
378 struct bt_component *trimmer = NULL;
379 struct bt_component_class *trimmer_class = NULL;
380 struct bt_value *trimmer_params = NULL;
381 struct bt_value *value;
382
383 trimmer_params = bt_value_map_create();
384 if (!trimmer_params) {
385 goto end;
386 }
387
388 value = bt_value_map_get(source_cfg->params, "begin");
389 if (value) {
390 enum bt_value_status ret;
391
392 ret = bt_value_map_insert(trimmer_params, "begin",
393 value);
394 BT_PUT(value);
395 if (ret) {
396 goto end;
397 }
398 }
399 value = bt_value_map_get(source_cfg->params, "end");
400 if (value) {
401 enum bt_value_status ret;
402
403 ret = bt_value_map_insert(trimmer_params, "end",
404 value);
405 BT_PUT(value);
406 if (ret) {
407 goto end;
408 }
409 }
410 value = bt_value_map_get(source_cfg->params, "clock-gmt");
411 if (value) {
412 enum bt_value_status ret;
413
414 ret = bt_value_map_insert(trimmer_params, "clock-gmt",
415 value);
416 BT_PUT(value);
417 if (ret) {
418 goto end;
419 }
420 }
421
422 trimmer_class = find_component_class("utils", "trimmer",
423 BT_COMPONENT_CLASS_TYPE_FILTER);
424 if (!trimmer_class) {
425 fprintf(stderr, "Could not find trimmer component class. Aborting...\n");
426 goto end;
427 }
428 trimmer = bt_component_create(trimmer_class, "source_trimmer",
429 trimmer_params);
430 if (!trimmer) {
431 goto end;
432 }
433 end:
434 bt_put(trimmer_params);
435 bt_put(trimmer_class);
436 return trimmer;
437 }
438
439 static
440 int connect_source_sink(struct bt_component *source,
441 struct bt_config_component *source_cfg,
442 struct bt_component *sink)
443 {
444 int ret = 0;
445 enum bt_component_status sink_status;
446 struct bt_component *trimmer = NULL;
447 struct bt_notification_iterator *source_it = NULL;
448 struct bt_notification_iterator *to_sink_it = NULL;
449
450 source_it = bt_component_source_create_notification_iterator(source);
451 if (!source_it) {
452 fprintf(stderr, "Failed to instantiate source iterator. Aborting...\n");
453 ret = -1;
454 goto end;
455 }
456
457 if (bt_value_map_has_key(source_cfg->params, "begin")
458 || bt_value_map_has_key(source_cfg->params, "end")) {
459 /* A trimmer must be inserted in the graph. */
460 enum bt_component_status trimmer_status;
461
462 trimmer = create_trimmer(source_cfg);
463 if (!trimmer) {
464 fprintf(stderr, "Failed to create trimmer component. Aborting...\n");
465 ret = -1;
466 goto end;
467 }
468
469 trimmer_status = bt_component_filter_add_iterator(trimmer,
470 source_it);
471 BT_PUT(source_it);
472 if (trimmer_status != BT_COMPONENT_STATUS_OK) {
473 fprintf(stderr, "Failed to connect source to trimmer. Aborting...\n");
474 ret = -1;
475 goto end;
476 }
477
478 to_sink_it = bt_component_filter_create_notification_iterator(trimmer);
479 if (!to_sink_it) {
480 fprintf(stderr, "Failed to instantiate trimmer iterator. Aborting...\n");
481 ret = -1;
482 goto end;
483 }
484 } else {
485 BT_MOVE(to_sink_it, source_it);
486 }
487
488 sink_status = bt_component_sink_add_iterator(sink, to_sink_it);
489 if (sink_status != BT_COMPONENT_STATUS_OK) {
490 fprintf(stderr, "Failed to connect to sink component. Aborting...\n");
491 ret = -1;
492 goto end;
493 }
494 end:
495 bt_put(trimmer);
496 bt_put(source_it);
497 bt_put(to_sink_it);
498 return ret;
499 }
500
501 static
502 void add_to_loaded_plugins(struct bt_plugin **plugins)
503 {
504 while (*plugins) {
505 struct bt_plugin *plugin = *plugins;
506 /* Check if it's already loaded (from another path). */
507 struct bt_plugin *loaded_plugin =
508 find_plugin(bt_plugin_get_name(plugin));
509
510 if (loaded_plugin) {
511 printf_verbose("Not loading plugin `%s`: already loaded from `%s`\n",
512 bt_plugin_get_path(plugin),
513 bt_plugin_get_path(loaded_plugin));
514 BT_PUT(loaded_plugin);
515 BT_PUT(plugin);
516 } else {
517 /* Transfer ownership to global array. */
518 g_ptr_array_add(loaded_plugins, plugin);
519 }
520 *(plugins++) = NULL;
521 }
522 }
523
524 static
525 int load_dynamic_plugins(struct bt_value *plugin_paths)
526 {
527 int nr_paths, i, ret = 0;
528
529 nr_paths = bt_value_array_size(plugin_paths);
530 if (nr_paths < 0) {
531 ret = -1;
532 goto end;
533 }
534
535 for (i = 0; i < nr_paths; i++) {
536 struct bt_value *plugin_path_value = NULL;
537 const char *plugin_path;
538 struct bt_plugin **plugins;
539
540 plugin_path_value = bt_value_array_get(plugin_paths, i);
541 if (bt_value_string_get(plugin_path_value,
542 &plugin_path)) {
543 BT_PUT(plugin_path_value);
544 continue;
545 }
546
547 plugins = bt_plugin_create_all_from_dir(plugin_path, false);
548 if (!plugins) {
549 printf_debug("Unable to dynamically load plugins from path %s.\n",
550 plugin_path);
551 BT_PUT(plugin_path_value);
552 continue;
553 }
554
555 add_to_loaded_plugins(plugins);
556 free(plugins);
557
558 BT_PUT(plugin_path_value);
559 }
560 end:
561 return ret;
562 }
563
564 static
565 int load_static_plugins(void)
566 {
567 int ret = 0;
568 struct bt_plugin **plugins;
569
570 plugins = bt_plugin_create_all_from_static();
571 if (!plugins) {
572 printf_debug("Unable to load static plugins.\n");
573 ret = -1;
574 goto end;
575 }
576
577 add_to_loaded_plugins(plugins);
578 free(plugins);
579 end:
580 return ret;
581 }
582
583 static
584 const char *component_type_str(enum bt_component_class_type type)
585 {
586 switch (type) {
587 case BT_COMPONENT_CLASS_TYPE_SOURCE:
588 return "source";
589 case BT_COMPONENT_CLASS_TYPE_SINK:
590 return "sink";
591 case BT_COMPONENT_CLASS_TYPE_FILTER:
592 return "filter";
593 case BT_COMPONENT_CLASS_TYPE_UNKNOWN:
594 default:
595 return "unknown";
596 }
597 }
598
599 static int load_all_plugins(struct bt_value *plugin_paths)
600 {
601 int ret = 0;
602
603 if (load_dynamic_plugins(plugin_paths)) {
604 fprintf(stderr, "Failed to load dynamic plugins.\n");
605 ret = -1;
606 goto end;
607 }
608
609 if (load_static_plugins()) {
610 fprintf(stderr, "Failed to load static plugins.\n");
611 ret = -1;
612 goto end;
613 }
614
615 end:
616 return ret;
617 }
618
619 static void print_plugin_info(struct bt_plugin *plugin)
620 {
621 unsigned int major, minor, patch;
622 const char *extra;
623 enum bt_plugin_status version_status;
624 const char *plugin_name;
625 const char *path;
626 const char *author;
627 const char *license;
628 const char *plugin_description;
629
630 plugin_name = bt_plugin_get_name(plugin);
631 path = bt_plugin_get_path(plugin);
632 author = bt_plugin_get_author(plugin);
633 license = bt_plugin_get_license(plugin);
634 plugin_description = bt_plugin_get_description(plugin);
635 version_status = bt_plugin_get_version(plugin, &major, &minor,
636 &patch, &extra);
637 printf("%s%s%s%s:\n", bt_common_color_bold(),
638 bt_common_color_fg_blue(), plugin_name,
639 bt_common_color_reset());
640 printf(" %sPath%s: %s\n", bt_common_color_bold(),
641 bt_common_color_reset(), path ? path : "(None)");
642
643 if (version_status == BT_PLUGIN_STATUS_OK) {
644 printf(" %sVersion%s: %u.%u.%u",
645 bt_common_color_bold(), bt_common_color_reset(),
646 major, minor, patch);
647
648 if (extra) {
649 printf("%s", extra);
650 }
651
652 printf("\n");
653 }
654
655 printf(" %sDescription%s: %s\n", bt_common_color_bold(),
656 bt_common_color_reset(),
657 plugin_description ? plugin_description : "(None)");
658 printf(" %sAuthor%s: %s\n", bt_common_color_bold(),
659 bt_common_color_reset(), author ? author : "(Unknown)");
660 printf(" %sLicense%s: %s\n", bt_common_color_bold(),
661 bt_common_color_reset(),
662 license ? license : "(Unknown)");
663 }
664
665 static void print_plugin_comp_cls_opt(FILE *fh, const char *plugin_name,
666 const char *comp_cls_name, enum bt_component_class_type type)
667 {
668 fprintf(fh, "%s%s--%s%s %s%s%s.%s%s%s",
669 bt_common_color_bold(),
670 bt_common_color_fg_cyan(),
671 component_type_str(type),
672 bt_common_color_fg_default(),
673 bt_common_color_fg_blue(),
674 plugin_name,
675 bt_common_color_fg_default(),
676 bt_common_color_fg_yellow(),
677 comp_cls_name,
678 bt_common_color_reset());
679 }
680
681 static int cmd_query_info(struct bt_config *cfg)
682 {
683 int ret;
684 struct bt_component_class *comp_cls = NULL;
685 struct bt_value *results = NULL;
686
687 ret = load_all_plugins(cfg->cmd_data.list_plugins.plugin_paths);
688 if (ret) {
689 goto end;
690 }
691
692 comp_cls = find_component_class(cfg->cmd_data.query_info.cfg_component->plugin_name->str,
693 cfg->cmd_data.query_info.cfg_component->component_name->str,
694 cfg->cmd_data.query_info.cfg_component->type);
695 if (!comp_cls) {
696 fprintf(stderr, "%s%sCannot find component class %s",
697 bt_common_color_bold(),
698 bt_common_color_fg_red(),
699 bt_common_color_reset());
700 print_plugin_comp_cls_opt(stderr,
701 cfg->cmd_data.query_info.cfg_component->plugin_name->str,
702 cfg->cmd_data.query_info.cfg_component->component_name->str,
703 cfg->cmd_data.query_info.cfg_component->type);
704 fprintf(stderr, "\n");
705 ret = -1;
706 goto end;
707 }
708
709 results = bt_component_class_query_info(comp_cls,
710 cfg->cmd_data.query_info.action->str,
711 cfg->cmd_data.query_info.cfg_component->params);
712 if (!results) {
713 fprintf(stderr, "%s%sFailed to query info to %s",
714 bt_common_color_bold(),
715 bt_common_color_fg_red(),
716 bt_common_color_reset());
717 print_plugin_comp_cls_opt(stderr,
718 cfg->cmd_data.query_info.cfg_component->plugin_name->str,
719 cfg->cmd_data.query_info.cfg_component->component_name->str,
720 cfg->cmd_data.query_info.cfg_component->type);
721 fprintf(stderr, "%s%s with action `%s`%s\n",
722 bt_common_color_bold(),
723 bt_common_color_fg_red(),
724 cfg->cmd_data.query_info.action->str,
725 bt_common_color_reset());
726 ret = -1;
727 goto end;
728 }
729
730 print_value(results, 0);
731
732 end:
733 bt_put(comp_cls);
734 bt_put(results);
735 return ret;
736 }
737
738 static int cmd_help(struct bt_config *cfg)
739 {
740 int ret;
741 struct bt_plugin *plugin = NULL;
742 size_t i;
743
744 ret = load_all_plugins(cfg->cmd_data.list_plugins.plugin_paths);
745 if (ret) {
746 goto end;
747 }
748
749 plugin = find_plugin(cfg->cmd_data.help.cfg_component->plugin_name->str);
750 if (!plugin) {
751 fprintf(stderr, "%s%sCannot find plugin %s%s%s\n",
752 bt_common_color_bold(), bt_common_color_fg_red(),
753 bt_common_color_fg_blue(),
754 cfg->cmd_data.help.cfg_component->plugin_name->str,
755 bt_common_color_reset());
756 ret = -1;
757 goto end;
758 }
759
760 print_plugin_info(plugin);
761 printf(" %sComponent classes%s: %d\n",
762 bt_common_color_bold(),
763 bt_common_color_reset(),
764 bt_plugin_get_component_class_count(plugin));
765
766
767 if (cfg->cmd_data.help.cfg_component->type !=
768 BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
769 struct bt_component_class *needed_comp_cls =
770 find_component_class(
771 cfg->cmd_data.help.cfg_component->plugin_name->str,
772 cfg->cmd_data.help.cfg_component->component_name->str,
773 cfg->cmd_data.help.cfg_component->type);
774
775 if (!needed_comp_cls) {
776 fprintf(stderr, "\n%s%sCannot find component class %s",
777 bt_common_color_bold(),
778 bt_common_color_fg_red(),
779 bt_common_color_reset());
780 print_plugin_comp_cls_opt(stderr,
781 cfg->cmd_data.help.cfg_component->plugin_name->str,
782 cfg->cmd_data.help.cfg_component->component_name->str,
783 cfg->cmd_data.help.cfg_component->type);
784 fprintf(stderr, "\n");
785 ret = -1;
786 goto end;
787 }
788
789 bt_put(needed_comp_cls);
790 }
791
792 for (i = 0; i < bt_plugin_get_component_class_count(plugin); i++) {
793 struct bt_component_class *comp_cls =
794 bt_plugin_get_component_class(plugin, i);
795 const char *comp_class_name =
796 bt_component_class_get_name(comp_cls);
797 const char *comp_class_description =
798 bt_component_class_get_description(comp_cls);
799 const char *comp_class_help =
800 bt_component_class_get_help(comp_cls);
801 enum bt_component_class_type type =
802 bt_component_class_get_type(comp_cls);
803
804 assert(comp_cls);
805
806 if (cfg->cmd_data.help.cfg_component->type !=
807 BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
808 if (strcmp(cfg->cmd_data.help.cfg_component->component_name->str,
809 comp_class_name) != 0 &&
810 type ==
811 cfg->cmd_data.help.cfg_component->type) {
812 bt_put(comp_cls);
813 continue;
814 }
815 }
816
817 printf("\n");
818 print_plugin_comp_cls_opt(stdout,
819 cfg->cmd_data.help.cfg_component->plugin_name->str,
820 comp_class_name,
821 type);
822 printf("\n");
823 printf(" %sDescription%s: %s\n", bt_common_color_bold(),
824 bt_common_color_reset(),
825 comp_class_description ? comp_class_description : "(None)");
826
827 if (comp_class_help) {
828 printf("\n%s\n", comp_class_help);
829 }
830
831 bt_put(comp_cls);
832 }
833
834 end:
835 bt_put(plugin);
836 return ret;
837 }
838
839 static int cmd_list_plugins(struct bt_config *cfg)
840 {
841 int ret;
842 int plugins_count, component_classes_count = 0, i;
843
844 ret = load_all_plugins(cfg->cmd_data.list_plugins.plugin_paths);
845 if (ret) {
846 goto end;
847 }
848
849 printf("From the following plugin paths:\n\n");
850 print_value(cfg->cmd_data.list_plugins.plugin_paths, 2);
851 printf("\n");
852 plugins_count = loaded_plugins->len;
853 if (plugins_count == 0) {
854 fprintf(stderr, "%s%sNo plugins found.%s\n",
855 bt_common_color_bold(), bt_common_color_fg_red(),
856 bt_common_color_reset());
857 fprintf(stderr, "\n");
858 fprintf(stderr, "Please make sure your plugin search path is set correctly. You can use\n");
859 fprintf(stderr, "the --plugin-path command-line option or the BABELTRACE_PLUGIN_PATH\n");
860 fprintf(stderr, "environment variable.\n");
861 ret = -1;
862 goto end;
863 }
864
865 for (i = 0; i < plugins_count; i++) {
866 struct bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i);
867
868 component_classes_count += bt_plugin_get_component_class_count(plugin);
869 }
870
871 printf("Found %s%d%s component classes in %s%d%s plugins.\n",
872 bt_common_color_bold(),
873 component_classes_count,
874 bt_common_color_reset(),
875 bt_common_color_bold(),
876 plugins_count,
877 bt_common_color_reset());
878
879 for (i = 0; i < plugins_count; i++) {
880 int j;
881 struct bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i);
882
883 component_classes_count =
884 bt_plugin_get_component_class_count(plugin);
885 printf("\n");
886 print_plugin_info(plugin);
887
888 if (component_classes_count == 0) {
889 printf(" %sComponent classes%s: (None)\n",
890 bt_common_color_bold(),
891 bt_common_color_reset());
892 } else {
893 printf(" %sComponent classes%s:\n",
894 bt_common_color_bold(),
895 bt_common_color_reset());
896 }
897
898 for (j = 0; j < component_classes_count; j++) {
899 struct bt_component_class *comp_class =
900 bt_plugin_get_component_class(plugin, j);
901 const char *comp_class_name =
902 bt_component_class_get_name(comp_class);
903 const char *comp_class_description =
904 bt_component_class_get_description(comp_class);
905 enum bt_component_class_type type =
906 bt_component_class_get_type(comp_class);
907
908 printf(" ");
909 print_plugin_comp_cls_opt(stdout,
910 bt_plugin_get_name(plugin), comp_class_name,
911 type);
912
913 if (comp_class_description) {
914 printf(": %s", comp_class_description);
915 }
916
917 printf("\n");
918 bt_put(comp_class);
919 }
920 }
921
922 end:
923 return ret;
924 }
925
926 static int print_ctf_metadata(struct bt_config *cfg)
927 {
928 int ret = 0;
929 struct bt_component_class *comp_cls = NULL;
930 struct bt_config_component *source_cfg = NULL;
931 struct bt_value *results = NULL;
932 struct bt_value *path = NULL;
933 struct bt_value *params = NULL;
934 struct bt_value *metadata_text_value = NULL;
935 const char *metadata_text = NULL;
936
937 assert(cfg->cmd_data.convert.sources->len == 1);
938 source_cfg = bt_config_get_component(cfg->cmd_data.convert.sources, 0);
939 assert(source_cfg);
940 comp_cls = find_component_class(source_cfg->plugin_name->str,
941 source_cfg->component_name->str,
942 source_cfg->type);
943 if (!comp_cls) {
944 fprintf(stderr, "%s%sCannot find component class %s",
945 bt_common_color_bold(),
946 bt_common_color_fg_red(),
947 bt_common_color_reset());
948 print_plugin_comp_cls_opt(stderr,
949 source_cfg->plugin_name->str,
950 source_cfg->component_name->str,
951 source_cfg->type);
952 fprintf(stderr, "\n");
953 ret = -1;
954 goto end;
955 }
956
957 path = bt_value_map_get(source_cfg->params, "path");
958 if (!path) {
959 ret = -1;
960 goto end;
961 }
962
963 params = bt_value_map_create();
964 if (!params) {
965 ret = -1;
966 goto end;
967 }
968
969 ret = bt_value_map_insert(params, "path", path);
970 if (ret) {
971 ret = -1;
972 goto end;
973 }
974
975 results = bt_component_class_query_info(comp_cls, "get-metadata-info",
976 params);
977 if (!results) {
978 ret = -1;
979 fprintf(stderr, "%s%sFailed to get metadata info%s\n",
980 bt_common_color_bold(),
981 bt_common_color_fg_red(),
982 bt_common_color_reset());
983 goto end;
984 }
985
986 metadata_text_value = bt_value_map_get(results, "text");
987 if (!metadata_text_value) {
988 ret = -1;
989 goto end;
990 }
991
992 ret = bt_value_string_get(metadata_text_value, &metadata_text);
993 assert(ret == 0);
994 printf("%s\n", metadata_text);
995
996 end:
997 bt_put(results);
998 bt_put(path);
999 bt_put(params);
1000 bt_put(metadata_text_value);
1001 bt_put(comp_cls);
1002 bt_put(source_cfg);
1003 return 0;
1004 }
1005
1006 static int cmd_convert(struct bt_config *cfg)
1007 {
1008 int ret = 0;
1009 struct bt_component_class *source_class = NULL;
1010 struct bt_component_class *sink_class = NULL;
1011 struct bt_component *source = NULL, *sink = NULL;
1012 struct bt_value *source_params = NULL, *sink_params = NULL;
1013 enum bt_component_status sink_status;
1014 struct bt_config_component *source_cfg = NULL, *sink_cfg = NULL;
1015
1016 ret = load_all_plugins(cfg->cmd_data.convert.plugin_paths);
1017 if (ret) {
1018 fprintf(stderr, "Could not load plugins from configured plugin paths. Aborting...\n");
1019 goto end;
1020 }
1021
1022 if (cfg->cmd_data.convert.print_ctf_metadata) {
1023 ret = print_ctf_metadata(cfg);
1024 goto end;
1025 }
1026
1027 /* TODO handle more than 1 source and 1 sink. */
1028 if (cfg->cmd_data.convert.sources->len != 1 ||
1029 cfg->cmd_data.convert.sinks->len != 1) {
1030 fprintf(stderr, "Only one source and one sink component class are supported. Aborting...\n");
1031 ret = -1;
1032 goto end;
1033 }
1034
1035 source_cfg = bt_config_get_component(cfg->cmd_data.convert.sources, 0);
1036 source_params = bt_get(source_cfg->params);
1037 source_class = find_component_class(source_cfg->plugin_name->str,
1038 source_cfg->component_name->str,
1039 BT_COMPONENT_CLASS_TYPE_SOURCE);
1040 if (!source_class) {
1041 fprintf(stderr, "Could not find %s.%s source component class. Aborting...\n",
1042 source_cfg->plugin_name->str,
1043 source_cfg->component_name->str);
1044 ret = -1;
1045 goto end;
1046 }
1047
1048 sink_cfg = bt_config_get_component(cfg->cmd_data.convert.sinks, 0);
1049 sink_params = bt_get(sink_cfg->params);
1050 sink_class = find_component_class(sink_cfg->plugin_name->str,
1051 sink_cfg->component_name->str,
1052 BT_COMPONENT_CLASS_TYPE_SINK);
1053 if (!sink_class) {
1054 fprintf(stderr, "Could not find %s.%s output component class. Aborting...\n",
1055 sink_cfg->plugin_name->str,
1056 sink_cfg->component_name->str);
1057 ret = -1;
1058 goto end;
1059 }
1060
1061 source = bt_component_create(source_class, "source", source_params);
1062 if (!source) {
1063 fprintf(stderr, "Failed to instantiate selected source component. Aborting...\n");
1064 ret = -1;
1065 goto end;
1066 }
1067
1068 sink = bt_component_create(sink_class, "sink", sink_params);
1069 if (!sink) {
1070 fprintf(stderr, "Failed to instantiate selected output component. Aborting...\n");
1071 ret = -1;
1072 goto end;
1073 }
1074
1075 ret = connect_source_sink(source, source_cfg, sink);
1076 if (ret) {
1077 ret = -1;
1078 goto end;
1079 }
1080
1081 while (true) {
1082 sink_status = bt_component_sink_consume(sink);
1083 switch (sink_status) {
1084 case BT_COMPONENT_STATUS_AGAIN:
1085 /* Wait for an arbitraty 500 ms. */
1086 usleep(500000);
1087 break;
1088 case BT_COMPONENT_STATUS_OK:
1089 break;
1090 case BT_COMPONENT_STATUS_END:
1091 goto end;
1092 default:
1093 fprintf(stderr, "Sink component returned an error, aborting...\n");
1094 ret = -1;
1095 goto end;
1096 }
1097 }
1098
1099 end:
1100 BT_PUT(sink_class);
1101 BT_PUT(source_class);
1102 BT_PUT(source);
1103 BT_PUT(sink);
1104 BT_PUT(source_params);
1105 BT_PUT(sink_params);
1106 BT_PUT(sink_cfg);
1107 BT_PUT(source_cfg);
1108 return ret;
1109 }
1110
1111 static void warn_command_name_and_directory_clash(struct bt_config *cfg)
1112 {
1113 if (!cfg->command_name) {
1114 return;
1115 }
1116
1117 if (g_file_test(cfg->command_name,
1118 G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
1119 fprintf(stderr, "\nNOTE: The `%s` command was executed. If you meant to convert a\n",
1120 cfg->command_name);
1121 fprintf(stderr, "trace located in the local `%s` directory, please use:\n",
1122 cfg->command_name);
1123 fprintf(stderr, "\n");
1124 fprintf(stderr, " babeltrace convert %s [OPTIONS]\n",
1125 cfg->command_name);
1126 }
1127 }
1128
1129 int main(int argc, const char **argv)
1130 {
1131 int ret;
1132 int retcode;
1133 struct bt_config *cfg;
1134
1135 init_loaded_plugins_array();
1136 cfg = bt_config_from_args_with_defaults(argc, argv, &retcode);
1137
1138 if (retcode < 0) {
1139 /* Quit without errors; typically usage/version */
1140 retcode = 0;
1141 goto end;
1142 }
1143
1144 if (retcode > 0) {
1145 goto end;
1146 }
1147
1148 if (!cfg) {
1149 fprintf(stderr, "Failed to create Babeltrace configuration\n");
1150 goto end;
1151 }
1152
1153 babeltrace_debug = cfg->debug;
1154 babeltrace_verbose = cfg->verbose;
1155 print_cfg(cfg);
1156
1157 switch (cfg->command) {
1158 case BT_CONFIG_COMMAND_CONVERT:
1159 ret = cmd_convert(cfg);
1160 break;
1161 case BT_CONFIG_COMMAND_LIST_PLUGINS:
1162 ret = cmd_list_plugins(cfg);
1163 break;
1164 case BT_CONFIG_COMMAND_HELP:
1165 ret = cmd_help(cfg);
1166 break;
1167 case BT_CONFIG_COMMAND_QUERY_INFO:
1168 ret = cmd_query_info(cfg);
1169 break;
1170 default:
1171 assert(false);
1172 }
1173
1174 warn_command_name_and_directory_clash(cfg);
1175 retcode = ret ? 1 : 0;
1176
1177 end:
1178 BT_PUT(cfg);
1179 fini_loaded_plugins_array();
1180 return retcode;
1181 }
This page took 0.05958 seconds and 4 git commands to generate.