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