Standardize *get_*_count() functions
[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 struct bt_connection *connection = NULL;
558 struct bt_component *trimmer = NULL;
559 struct bt_port *source_port =
560 bt_component_source_get_default_output_port(source);
561 struct bt_port *sink_port =
562 bt_component_sink_get_default_input_port(sink);
563 struct bt_port *to_sink_port = NULL;
564 struct bt_port *trimmer_input_port = NULL;
565
566 if (!source_port) {
567 fprintf(stderr, "Failed to find default source output port. Aborting...\n");
568 ret = -1;
569 goto end;
570 }
571 if (!sink_port) {
572 fprintf(stderr, "Failed to find default sink input port. Aborting...\n");
573 ret = -1;
574 goto end;
575 }
576
577 if (bt_value_map_has_key(source_cfg->params, "begin")
578 || bt_value_map_has_key(source_cfg->params, "end")) {
579 /* A trimmer must be inserted in the graph. */
580 trimmer = create_trimmer(source_cfg);
581 if (!trimmer) {
582 fprintf(stderr, "Failed to create trimmer component. Aborting...\n");
583 ret = -1;
584 goto end;
585 }
586
587 trimmer_input_port = bt_component_filter_get_default_input_port(
588 trimmer);
589 if (!trimmer_input_port) {
590 fprintf(stderr, "Failed to find trimmer input port. Aborting...\n");
591 ret = -1;
592 goto end;
593 }
594 to_sink_port = bt_component_filter_get_default_output_port(
595 trimmer);
596 if (!to_sink_port) {
597 fprintf(stderr, "Failed to find trimmer output port. Aborting...\n");
598 ret = -1;
599 goto end;
600 }
601
602 connection = bt_graph_connect_ports(graph, source_port,
603 trimmer_input_port);
604 if (!connection) {
605 fprintf(stderr, "Failed to connect source to trimmer. Aborting...\n");
606 ret = -1;
607 goto end;
608 }
609 BT_PUT(connection);
610 } else {
611 BT_MOVE(to_sink_port, source_port);
612 }
613
614 connection = bt_graph_connect_ports(graph, to_sink_port, sink_port);
615 if (!connection) {
616 fprintf(stderr, "Failed to connect to sink. Aborting...\n");
617 ret = -1;
618 goto end;
619 }
620 end:
621 bt_put(trimmer);
622 bt_put(source_port);
623 bt_put(sink_port);
624 bt_put(to_sink_port);
625 bt_put(connection);
626 return ret;
627 }
628
629 static
630 void add_to_loaded_plugins(struct bt_plugin_set *plugin_set)
631 {
632 int64_t i;
633 int64_t count;
634
635 count = bt_plugin_set_get_plugin_count(plugin_set);
636 assert(count >= 0);
637
638 for (i = 0; i < count; i++) {
639 struct bt_plugin *plugin =
640 bt_plugin_set_get_plugin(plugin_set, i);
641 struct bt_plugin *loaded_plugin =
642 find_plugin(bt_plugin_get_name(plugin));
643
644 assert(plugin);
645
646 if (loaded_plugin) {
647 printf_verbose("Not loading plugin `%s`: already loaded from `%s`\n",
648 bt_plugin_get_path(plugin),
649 bt_plugin_get_path(loaded_plugin));
650 bt_put(loaded_plugin);
651 } else {
652 /* Add to global array. */
653 g_ptr_array_add(loaded_plugins, bt_get(plugin));
654 }
655
656 bt_put(plugin);
657 }
658 }
659
660 static
661 int load_dynamic_plugins(struct bt_value *plugin_paths)
662 {
663 int nr_paths, i, ret = 0;
664
665 nr_paths = bt_value_array_size(plugin_paths);
666 if (nr_paths < 0) {
667 ret = -1;
668 goto end;
669 }
670
671 for (i = 0; i < nr_paths; i++) {
672 struct bt_value *plugin_path_value = NULL;
673 const char *plugin_path;
674 struct bt_plugin_set *plugin_set;
675
676 plugin_path_value = bt_value_array_get(plugin_paths, i);
677 if (bt_value_string_get(plugin_path_value,
678 &plugin_path)) {
679 BT_PUT(plugin_path_value);
680 continue;
681 }
682
683 plugin_set = bt_plugin_create_all_from_dir(plugin_path, false);
684 if (!plugin_set) {
685 printf_debug("Unable to dynamically load plugins from path %s.\n",
686 plugin_path);
687 BT_PUT(plugin_path_value);
688 continue;
689 }
690
691 add_to_loaded_plugins(plugin_set);
692 bt_put(plugin_set);
693 BT_PUT(plugin_path_value);
694 }
695 end:
696 return ret;
697 }
698
699 static
700 int load_static_plugins(void)
701 {
702 int ret = 0;
703 struct bt_plugin_set *plugin_set;
704
705 plugin_set = bt_plugin_create_all_from_static();
706 if (!plugin_set) {
707 printf_debug("Unable to load static plugins.\n");
708 ret = -1;
709 goto end;
710 }
711
712 add_to_loaded_plugins(plugin_set);
713 bt_put(plugin_set);
714 end:
715 return ret;
716 }
717
718 static int load_all_plugins(struct bt_value *plugin_paths)
719 {
720 int ret = 0;
721
722 if (load_dynamic_plugins(plugin_paths)) {
723 fprintf(stderr, "Failed to load dynamic plugins.\n");
724 ret = -1;
725 goto end;
726 }
727
728 if (load_static_plugins()) {
729 fprintf(stderr, "Failed to load static plugins.\n");
730 ret = -1;
731 goto end;
732 }
733
734 end:
735 return ret;
736 }
737
738 static void print_plugin_info(struct bt_plugin *plugin)
739 {
740 unsigned int major, minor, patch;
741 const char *extra;
742 enum bt_plugin_status version_status;
743 const char *plugin_name;
744 const char *path;
745 const char *author;
746 const char *license;
747 const char *plugin_description;
748
749 plugin_name = bt_plugin_get_name(plugin);
750 path = bt_plugin_get_path(plugin);
751 author = bt_plugin_get_author(plugin);
752 license = bt_plugin_get_license(plugin);
753 plugin_description = bt_plugin_get_description(plugin);
754 version_status = bt_plugin_get_version(plugin, &major, &minor,
755 &patch, &extra);
756 printf("%s%s%s%s:\n", bt_common_color_bold(),
757 bt_common_color_fg_blue(), plugin_name,
758 bt_common_color_reset());
759 printf(" %sPath%s: %s\n", bt_common_color_bold(),
760 bt_common_color_reset(), path ? path : "(None)");
761
762 if (version_status == BT_PLUGIN_STATUS_OK) {
763 printf(" %sVersion%s: %u.%u.%u",
764 bt_common_color_bold(), bt_common_color_reset(),
765 major, minor, patch);
766
767 if (extra) {
768 printf("%s", extra);
769 }
770
771 printf("\n");
772 }
773
774 printf(" %sDescription%s: %s\n", bt_common_color_bold(),
775 bt_common_color_reset(),
776 plugin_description ? plugin_description : "(None)");
777 printf(" %sAuthor%s: %s\n", bt_common_color_bold(),
778 bt_common_color_reset(), author ? author : "(Unknown)");
779 printf(" %sLicense%s: %s\n", bt_common_color_bold(),
780 bt_common_color_reset(),
781 license ? license : "(Unknown)");
782 }
783
784 static int cmd_query(struct bt_config *cfg)
785 {
786 int ret;
787 struct bt_component_class *comp_cls = NULL;
788 struct bt_value *results = NULL;
789
790 ret = load_all_plugins(cfg->plugin_paths);
791 if (ret) {
792 goto end;
793 }
794
795 comp_cls = find_component_class(cfg->cmd_data.query.cfg_component->plugin_name->str,
796 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
797 cfg->cmd_data.query.cfg_component->type);
798 if (!comp_cls) {
799 fprintf(stderr, "%s%sCannot find component class %s",
800 bt_common_color_bold(),
801 bt_common_color_fg_red(),
802 bt_common_color_reset());
803 print_plugin_comp_cls_opt(stderr,
804 cfg->cmd_data.query.cfg_component->plugin_name->str,
805 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
806 cfg->cmd_data.query.cfg_component->type);
807 fprintf(stderr, "\n");
808 ret = -1;
809 goto end;
810 }
811
812 results = bt_component_class_query(comp_cls,
813 cfg->cmd_data.query.object->str,
814 cfg->cmd_data.query.cfg_component->params);
815 if (!results) {
816 fprintf(stderr, "%s%sFailed to query info to %s",
817 bt_common_color_bold(),
818 bt_common_color_fg_red(),
819 bt_common_color_reset());
820 print_plugin_comp_cls_opt(stderr,
821 cfg->cmd_data.query.cfg_component->plugin_name->str,
822 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
823 cfg->cmd_data.query.cfg_component->type);
824 fprintf(stderr, "%s%s with object `%s`%s\n",
825 bt_common_color_bold(),
826 bt_common_color_fg_red(),
827 cfg->cmd_data.query.object->str,
828 bt_common_color_reset());
829 ret = -1;
830 goto end;
831 }
832
833 print_value(results, 0);
834
835 end:
836 bt_put(comp_cls);
837 bt_put(results);
838 return ret;
839 }
840
841 static int cmd_help(struct bt_config *cfg)
842 {
843 int ret;
844 struct bt_plugin *plugin = NULL;
845 size_t i;
846
847 ret = load_all_plugins(cfg->plugin_paths);
848 if (ret) {
849 goto end;
850 }
851
852 plugin = find_plugin(cfg->cmd_data.help.cfg_component->plugin_name->str);
853 if (!plugin) {
854 fprintf(stderr, "%s%sCannot find plugin %s%s%s\n",
855 bt_common_color_bold(), bt_common_color_fg_red(),
856 bt_common_color_fg_blue(),
857 cfg->cmd_data.help.cfg_component->plugin_name->str,
858 bt_common_color_reset());
859 ret = -1;
860 goto end;
861 }
862
863 print_plugin_info(plugin);
864 printf(" %sComponent classes%s: %d\n",
865 bt_common_color_bold(),
866 bt_common_color_reset(),
867 (int) bt_plugin_get_component_class_count(plugin));
868
869
870 if (cfg->cmd_data.help.cfg_component->type !=
871 BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
872 struct bt_component_class *needed_comp_cls =
873 find_component_class(
874 cfg->cmd_data.help.cfg_component->plugin_name->str,
875 cfg->cmd_data.help.cfg_component->comp_cls_name->str,
876 cfg->cmd_data.help.cfg_component->type);
877
878 if (!needed_comp_cls) {
879 fprintf(stderr, "\n%s%sCannot find component class %s",
880 bt_common_color_bold(),
881 bt_common_color_fg_red(),
882 bt_common_color_reset());
883 print_plugin_comp_cls_opt(stderr,
884 cfg->cmd_data.help.cfg_component->plugin_name->str,
885 cfg->cmd_data.help.cfg_component->comp_cls_name->str,
886 cfg->cmd_data.help.cfg_component->type);
887 fprintf(stderr, "\n");
888 ret = -1;
889 goto end;
890 }
891
892 bt_put(needed_comp_cls);
893 }
894
895 for (i = 0; i < bt_plugin_get_component_class_count(plugin); i++) {
896 struct bt_component_class *comp_cls =
897 bt_plugin_get_component_class(plugin, i);
898 const char *comp_class_name =
899 bt_component_class_get_name(comp_cls);
900 const char *comp_class_description =
901 bt_component_class_get_description(comp_cls);
902 const char *comp_class_help =
903 bt_component_class_get_help(comp_cls);
904 enum bt_component_class_type type =
905 bt_component_class_get_type(comp_cls);
906
907 assert(comp_cls);
908
909 if (cfg->cmd_data.help.cfg_component->type !=
910 BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
911 if (strcmp(cfg->cmd_data.help.cfg_component->comp_cls_name->str,
912 comp_class_name) != 0 &&
913 type ==
914 cfg->cmd_data.help.cfg_component->type) {
915 bt_put(comp_cls);
916 continue;
917 }
918 }
919
920 printf("\n");
921 print_plugin_comp_cls_opt(stdout,
922 cfg->cmd_data.help.cfg_component->plugin_name->str,
923 comp_class_name,
924 type);
925 printf("\n");
926 printf(" %sDescription%s: %s\n", bt_common_color_bold(),
927 bt_common_color_reset(),
928 comp_class_description ? comp_class_description : "(None)");
929
930 if (comp_class_help) {
931 printf("\n%s\n", comp_class_help);
932 }
933
934 bt_put(comp_cls);
935 }
936
937 end:
938 bt_put(plugin);
939 return ret;
940 }
941
942 static int cmd_list_plugins(struct bt_config *cfg)
943 {
944 int ret;
945 int plugins_count, component_classes_count = 0, i;
946
947 ret = load_all_plugins(cfg->plugin_paths);
948 if (ret) {
949 goto end;
950 }
951
952 printf("From the following plugin paths:\n\n");
953 print_value(cfg->plugin_paths, 2);
954 printf("\n");
955 plugins_count = loaded_plugins->len;
956 if (plugins_count == 0) {
957 fprintf(stderr, "%s%sNo plugins found.%s\n",
958 bt_common_color_bold(), bt_common_color_fg_red(),
959 bt_common_color_reset());
960 fprintf(stderr, "\n");
961 fprintf(stderr, "Please make sure your plugin search path is set correctly. You can use\n");
962 fprintf(stderr, "the --plugin-path command-line option or the BABELTRACE_PLUGIN_PATH\n");
963 fprintf(stderr, "environment variable.\n");
964 ret = -1;
965 goto end;
966 }
967
968 for (i = 0; i < plugins_count; i++) {
969 struct bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i);
970
971 component_classes_count += bt_plugin_get_component_class_count(plugin);
972 }
973
974 printf("Found %s%d%s component classes in %s%d%s plugins.\n",
975 bt_common_color_bold(),
976 component_classes_count,
977 bt_common_color_reset(),
978 bt_common_color_bold(),
979 plugins_count,
980 bt_common_color_reset());
981
982 for (i = 0; i < plugins_count; i++) {
983 int j;
984 struct bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i);
985
986 component_classes_count =
987 bt_plugin_get_component_class_count(plugin);
988 printf("\n");
989 print_plugin_info(plugin);
990
991 if (component_classes_count == 0) {
992 printf(" %sComponent classes%s: (None)\n",
993 bt_common_color_bold(),
994 bt_common_color_reset());
995 } else {
996 printf(" %sComponent classes%s:\n",
997 bt_common_color_bold(),
998 bt_common_color_reset());
999 }
1000
1001 for (j = 0; j < component_classes_count; j++) {
1002 struct bt_component_class *comp_class =
1003 bt_plugin_get_component_class(plugin, j);
1004 const char *comp_class_name =
1005 bt_component_class_get_name(comp_class);
1006 const char *comp_class_description =
1007 bt_component_class_get_description(comp_class);
1008 enum bt_component_class_type type =
1009 bt_component_class_get_type(comp_class);
1010
1011 printf(" ");
1012 print_plugin_comp_cls_opt(stdout,
1013 bt_plugin_get_name(plugin), comp_class_name,
1014 type);
1015
1016 if (comp_class_description) {
1017 printf(": %s", comp_class_description);
1018 }
1019
1020 printf("\n");
1021 bt_put(comp_class);
1022 }
1023 }
1024
1025 end:
1026 return ret;
1027 }
1028
1029 static int cmd_print_lttng_live_sessions(struct bt_config *cfg)
1030 {
1031 printf("TODO\n");
1032 return -1;
1033 }
1034
1035 static int cmd_print_ctf_metadata(struct bt_config *cfg)
1036 {
1037 int ret = 0;
1038 struct bt_component_class *comp_cls = NULL;
1039 struct bt_value *results = NULL;
1040 struct bt_value *params = NULL;
1041 struct bt_value *metadata_text_value = NULL;
1042 const char *metadata_text = NULL;
1043 static const char * const plugin_name = "ctf";
1044 static const char * const comp_cls_name = "fs";
1045 static const enum bt_component_class_type comp_cls_type =
1046 BT_COMPONENT_CLASS_TYPE_SOURCE;
1047
1048 assert(cfg->cmd_data.print_ctf_metadata.path);
1049 comp_cls = find_component_class(plugin_name, comp_cls_name,
1050 comp_cls_type);
1051 if (!comp_cls) {
1052 fprintf(stderr, "%s%sCannot find component class %s",
1053 bt_common_color_bold(),
1054 bt_common_color_fg_red(),
1055 bt_common_color_reset());
1056 print_plugin_comp_cls_opt(stderr, plugin_name,
1057 comp_cls_name, comp_cls_type);
1058 fprintf(stderr, "\n");
1059 ret = -1;
1060 goto end;
1061 }
1062
1063 params = bt_value_map_create();
1064 if (!params) {
1065 ret = -1;
1066 goto end;
1067 }
1068
1069 ret = bt_value_map_insert_string(params, "path",
1070 cfg->cmd_data.print_ctf_metadata.path->str);
1071 if (ret) {
1072 ret = -1;
1073 goto end;
1074 }
1075
1076 results = bt_component_class_query(comp_cls, "metadata-info",
1077 params);
1078 if (!results) {
1079 ret = -1;
1080 fprintf(stderr, "%s%sFailed to request metadata info%s\n",
1081 bt_common_color_bold(),
1082 bt_common_color_fg_red(),
1083 bt_common_color_reset());
1084 goto end;
1085 }
1086
1087 metadata_text_value = bt_value_map_get(results, "text");
1088 if (!metadata_text_value) {
1089 ret = -1;
1090 goto end;
1091 }
1092
1093 ret = bt_value_string_get(metadata_text_value, &metadata_text);
1094 assert(ret == 0);
1095 printf("%s\n", metadata_text);
1096
1097 end:
1098 bt_put(results);
1099 bt_put(params);
1100 bt_put(metadata_text_value);
1101 bt_put(comp_cls);
1102 return 0;
1103 }
1104
1105 static int cmd_run(struct bt_config *cfg)
1106 {
1107 int ret = 0;
1108 struct bt_component_class *source_class = NULL;
1109 struct bt_component_class *sink_class = NULL;
1110 struct bt_component *source = NULL, *sink = NULL;
1111 struct bt_value *source_params = NULL, *sink_params = NULL;
1112 struct bt_config_component *source_cfg = NULL, *sink_cfg = NULL;
1113 struct bt_graph *graph = NULL;
1114
1115 ret = load_all_plugins(cfg->plugin_paths);
1116 if (ret) {
1117 goto end;
1118 }
1119
1120 /* TODO handle more than 1 source and 1 sink. */
1121 if (cfg->cmd_data.run.sources->len != 1 ||
1122 cfg->cmd_data.run.sinks->len != 1) {
1123 fprintf(stderr, "Only one source and one sink component class are supported. Aborting...\n");
1124 ret = -1;
1125 goto end;
1126 }
1127
1128 source_cfg = bt_config_get_component(cfg->cmd_data.run.sources, 0);
1129 source_params = bt_get(source_cfg->params);
1130 source_class = find_component_class(source_cfg->plugin_name->str,
1131 source_cfg->comp_cls_name->str,
1132 BT_COMPONENT_CLASS_TYPE_SOURCE);
1133 if (!source_class) {
1134 fprintf(stderr, "Could not find ");
1135 print_plugin_comp_cls_opt(stderr, source_cfg->plugin_name->str,
1136 source_cfg->comp_cls_name->str, BT_COMPONENT_CLASS_TYPE_SOURCE);
1137 fprintf(stderr, ". Aborting...\n");
1138 ret = -1;
1139 goto end;
1140 }
1141
1142 sink_cfg = bt_config_get_component(cfg->cmd_data.run.sinks, 0);
1143 sink_params = bt_get(sink_cfg->params);
1144 sink_class = find_component_class(sink_cfg->plugin_name->str,
1145 sink_cfg->comp_cls_name->str,
1146 BT_COMPONENT_CLASS_TYPE_SINK);
1147 if (!sink_class) {
1148 fprintf(stderr, "Could not find ");
1149 print_plugin_comp_cls_opt(stderr, sink_cfg->plugin_name->str,
1150 sink_cfg->comp_cls_name->str, BT_COMPONENT_CLASS_TYPE_SINK);
1151 fprintf(stderr, ". Aborting...\n");
1152 ret = -1;
1153 goto end;
1154 }
1155
1156 graph = bt_graph_create();
1157 if (!graph) {
1158 ret = -1;
1159 goto end;
1160 }
1161
1162 source = bt_component_create(source_class, "source", source_params);
1163 if (!source) {
1164 fprintf(stderr, "Failed to instantiate selected source component. Aborting...\n");
1165 ret = -1;
1166 goto end;
1167 }
1168
1169 sink = bt_component_create(sink_class, "sink", sink_params);
1170 if (!sink) {
1171 fprintf(stderr, "Failed to instantiate selected output component. Aborting...\n");
1172 ret = -1;
1173 goto end;
1174 }
1175
1176 ret = connect_source_sink(graph, source, source_cfg, sink);
1177 if (ret) {
1178 ret = -1;
1179 goto end;
1180 }
1181
1182 while (true) {
1183 enum bt_graph_status graph_status;
1184
1185 graph_status = bt_graph_run(graph);
1186 switch (graph_status) {
1187 case BT_GRAPH_STATUS_AGAIN:
1188 /* Wait for an arbitraty 500 ms. */
1189 usleep(500000);
1190 break;
1191 case BT_COMPONENT_STATUS_END:
1192 goto end;
1193 default:
1194 fprintf(stderr, "Sink component returned an error, aborting...\n");
1195 ret = -1;
1196 goto end;
1197 }
1198 }
1199
1200 end:
1201 bt_put(sink_class);
1202 bt_put(source_class);
1203 bt_put(source);
1204 bt_put(sink);
1205 bt_put(source_params);
1206 bt_put(sink_params);
1207 bt_put(sink_cfg);
1208 bt_put(source_cfg);
1209 bt_put(graph);
1210 return ret;
1211 }
1212
1213 static void warn_command_name_and_directory_clash(struct bt_config *cfg)
1214 {
1215 if (!cfg->command_name) {
1216 return;
1217 }
1218
1219 if (g_file_test(cfg->command_name,
1220 G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
1221 fprintf(stderr, "\nNOTE: The `%s` command was executed. If you meant to convert a\n",
1222 cfg->command_name);
1223 fprintf(stderr, "trace located in the local `%s` directory, please use:\n",
1224 cfg->command_name);
1225 fprintf(stderr, "\n");
1226 fprintf(stderr, " babeltrace convert %s [OPTIONS]\n",
1227 cfg->command_name);
1228 }
1229 }
1230
1231 int main(int argc, const char **argv)
1232 {
1233 int ret;
1234 int retcode;
1235 struct bt_config *cfg;
1236
1237 init_loaded_plugins_array();
1238 cfg = bt_config_from_args_with_defaults(argc, argv, &retcode);
1239
1240 if (retcode < 0) {
1241 /* Quit without errors; typically usage/version */
1242 retcode = 0;
1243 goto end;
1244 }
1245
1246 if (retcode > 0) {
1247 goto end;
1248 }
1249
1250 if (!cfg) {
1251 fprintf(stderr, "Failed to create Babeltrace configuration\n");
1252 retcode = 1;
1253 goto end;
1254 }
1255
1256 babeltrace_debug = cfg->debug;
1257 babeltrace_verbose = cfg->verbose;
1258 print_cfg(cfg);
1259
1260 if (cfg->command_needs_plugins) {
1261 ret = load_all_plugins(cfg->plugin_paths);
1262 if (ret) {
1263 retcode = 1;
1264 goto end;
1265 }
1266 }
1267
1268 switch (cfg->command) {
1269 case BT_CONFIG_COMMAND_RUN:
1270 ret = cmd_run(cfg);
1271 break;
1272 case BT_CONFIG_COMMAND_LIST_PLUGINS:
1273 ret = cmd_list_plugins(cfg);
1274 break;
1275 case BT_CONFIG_COMMAND_HELP:
1276 ret = cmd_help(cfg);
1277 break;
1278 case BT_CONFIG_COMMAND_QUERY:
1279 ret = cmd_query(cfg);
1280 break;
1281 case BT_CONFIG_COMMAND_PRINT_CTF_METADATA:
1282 ret = cmd_print_ctf_metadata(cfg);
1283 break;
1284 case BT_CONFIG_COMMAND_PRINT_LTTNG_LIVE_SESSIONS:
1285 ret = cmd_print_lttng_live_sessions(cfg);
1286 break;
1287 default:
1288 assert(false);
1289 }
1290
1291 warn_command_name_and_directory_clash(cfg);
1292 retcode = ret ? 1 : 0;
1293
1294 end:
1295 BT_PUT(cfg);
1296 fini_loaded_plugins_array();
1297 return retcode;
1298 }
This page took 0.07278 seconds and 5 git commands to generate.