3c44db359025eb3e73936eb2b129ceac64d81b76
[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 #define BT_LOG_TAG "CLI"
30 #include "logging.h"
31
32 #include <babeltrace/babeltrace.h>
33 #include <babeltrace/plugin/plugin.h>
34 #include <babeltrace/common-internal.h>
35 #include <babeltrace/graph/component.h>
36 #include <babeltrace/graph/component-source.h>
37 #include <babeltrace/graph/component-sink.h>
38 #include <babeltrace/graph/component-filter.h>
39 #include <babeltrace/graph/component-class.h>
40 #include <babeltrace/graph/port.h>
41 #include <babeltrace/graph/graph.h>
42 #include <babeltrace/graph/connection.h>
43 #include <babeltrace/graph/notification-iterator.h>
44 #include <babeltrace/ref.h>
45 #include <babeltrace/values.h>
46 #include <babeltrace/logging.h>
47 #include <unistd.h>
48 #include <stdlib.h>
49 #include <popt.h>
50 #include <string.h>
51 #include <stdio.h>
52 #include <glib.h>
53 #include <inttypes.h>
54 #include <unistd.h>
55 #include <signal.h>
56 #include "babeltrace-cfg.h"
57 #include "babeltrace-cfg-cli-args.h"
58 #include "babeltrace-cfg-cli-args-default.h"
59
60 #define ENV_BABELTRACE_WARN_COMMAND_NAME_DIRECTORY_CLASH "BABELTRACE_CLI_WARN_COMMAND_NAME_DIRECTORY_CLASH"
61 #define ENV_BABELTRACE_CLI_LOG_LEVEL "BABELTRACE_CLI_LOG_LEVEL"
62
63 /*
64 * Known environment variable names for the log levels of the project's
65 * modules.
66 */
67 static const char* log_level_env_var_names[] = {
68 "BABELTRACE_COMMON_LOG_LEVEL",
69 "BABELTRACE_PLUGIN_CTF_BTR_LOG_LEVEL",
70 "BABELTRACE_PLUGIN_CTF_FS_SRC_LOG_LEVEL",
71 "BABELTRACE_PLUGIN_CTF_LTTNG_LIVE_SRC_LOG_LEVEL",
72 "BABELTRACE_PLUGIN_CTF_METADATA_LOG_LEVEL",
73 "BABELTRACE_PLUGIN_CTF_NOTIF_ITER_LOG_LEVEL",
74 "BABELTRACE_PLUGIN_LTTNG_UTILS_DEBUG_INFO_FLT_LOG_LEVEL",
75 "BABELTRACE_PLUGIN_UTILS_TRIMMER_FLT_LOG_LEVEL",
76 "BABELTRACE_PYTHON_PLUGIN_PROVIDER_LOG_LEVEL",
77 NULL,
78 };
79
80 /* Application's processing graph (weak) */
81 static struct bt_graph *the_graph;
82 static bool canceled = false;
83
84 GPtrArray *loaded_plugins;
85
86 static
87 void sigint_handler(int signum)
88 {
89 if (signum != SIGINT) {
90 return;
91 }
92
93 if (the_graph) {
94 bt_graph_cancel(the_graph);
95 }
96
97 canceled = true;
98 }
99
100 static
101 void init_static_data(void)
102 {
103 loaded_plugins = g_ptr_array_new_with_free_func(bt_put);
104 }
105
106 static
107 void fini_static_data(void)
108 {
109 g_ptr_array_free(loaded_plugins, TRUE);
110 }
111
112 static
113 struct bt_plugin *find_plugin(const char *name)
114 {
115 int i;
116 struct bt_plugin *plugin = NULL;
117
118 assert(name);
119 BT_LOGD("Finding plugin: name=\"%s\"", name);
120
121 for (i = 0; i < loaded_plugins->len; i++) {
122 plugin = g_ptr_array_index(loaded_plugins, i);
123
124 if (strcmp(name, bt_plugin_get_name(plugin)) == 0) {
125 break;
126 }
127
128 plugin = NULL;
129 }
130
131 if (BT_LOG_ON_DEBUG) {
132 if (plugin) {
133 BT_LOGD("Found plugin: plugin-addr=%p", plugin);
134 } else {
135 BT_LOGD("Cannot find plugin.");
136 }
137 }
138
139 return bt_get(plugin);
140 }
141
142 static
143 struct bt_component_class *find_component_class(const char *plugin_name,
144 const char *comp_class_name,
145 enum bt_component_class_type comp_class_type)
146 {
147 struct bt_component_class *comp_class = NULL;
148 struct bt_plugin *plugin;
149
150 BT_LOGD("Finding component class: plugin-name=\"%s\", "
151 "comp-cls-name=\"%s\", comp-cls-type=%d",
152 plugin_name, comp_class_name, comp_class_type);
153
154 plugin = find_plugin(plugin_name);
155
156 if (!plugin) {
157 goto end;
158 }
159
160 comp_class = bt_plugin_get_component_class_by_name_and_type(plugin,
161 comp_class_name, comp_class_type);
162 BT_PUT(plugin);
163
164 end:
165 if (BT_LOG_ON_DEBUG) {
166 if (comp_class) {
167 BT_LOGD("Found component class: comp-cls-addr=%p",
168 comp_class);
169 } else {
170 BT_LOGD("Cannot find component class.");
171 }
172 }
173
174 return comp_class;
175 }
176
177 static
178 void print_indent(FILE *fp, size_t indent)
179 {
180 size_t i;
181
182 for (i = 0; i < indent; i++) {
183 fprintf(fp, " ");
184 }
185 }
186
187 static
188 const char *component_type_str(enum bt_component_class_type type)
189 {
190 switch (type) {
191 case BT_COMPONENT_CLASS_TYPE_SOURCE:
192 return "source";
193 case BT_COMPONENT_CLASS_TYPE_SINK:
194 return "sink";
195 case BT_COMPONENT_CLASS_TYPE_FILTER:
196 return "filter";
197 case BT_COMPONENT_CLASS_TYPE_UNKNOWN:
198 default:
199 return "(unknown)";
200 }
201 }
202
203 static
204 void print_plugin_comp_cls_opt(FILE *fh, const char *plugin_name,
205 const char *comp_cls_name, enum bt_component_class_type type)
206 {
207 GString *shell_plugin_name = NULL;
208 GString *shell_comp_cls_name = NULL;
209
210 shell_plugin_name = bt_common_shell_quote(plugin_name, false);
211 if (!shell_plugin_name) {
212 goto end;
213 }
214
215 shell_comp_cls_name = bt_common_shell_quote(comp_cls_name, false);
216 if (!shell_comp_cls_name) {
217 goto end;
218 }
219
220 fprintf(fh, "'%s%s%s%s.%s%s%s.%s%s%s'",
221 bt_common_color_bold(),
222 bt_common_color_fg_cyan(),
223 component_type_str(type),
224 bt_common_color_fg_default(),
225 bt_common_color_fg_blue(),
226 shell_plugin_name->str,
227 bt_common_color_fg_default(),
228 bt_common_color_fg_yellow(),
229 shell_comp_cls_name->str,
230 bt_common_color_reset());
231
232 end:
233 if (shell_plugin_name) {
234 g_string_free(shell_plugin_name, TRUE);
235 }
236
237 if (shell_comp_cls_name) {
238 g_string_free(shell_comp_cls_name, TRUE);
239 }
240 }
241
242 static
243 void print_value(FILE *, struct bt_value *, size_t);
244
245 static
246 void print_value_rec(FILE *, struct bt_value *, size_t);
247
248 struct print_map_value_data {
249 size_t indent;
250 FILE *fp;
251 };
252
253 static
254 bt_bool print_map_value(const char *key, struct bt_value *object, void *data)
255 {
256 struct print_map_value_data *print_map_value_data = data;
257
258 print_indent(print_map_value_data->fp, print_map_value_data->indent);
259 fprintf(print_map_value_data->fp, "%s: ", key);
260
261 if (bt_value_is_array(object) &&
262 bt_value_array_is_empty(object)) {
263 fprintf(print_map_value_data->fp, "[ ]\n");
264 return true;
265 }
266
267 if (bt_value_is_map(object) &&
268 bt_value_map_is_empty(object)) {
269 fprintf(print_map_value_data->fp, "{ }\n");
270 return true;
271 }
272
273 if (bt_value_is_array(object) ||
274 bt_value_is_map(object)) {
275 fprintf(print_map_value_data->fp, "\n");
276 }
277
278 print_value_rec(print_map_value_data->fp, object,
279 print_map_value_data->indent + 2);
280 return BT_TRUE;
281 }
282
283 static
284 void print_value_rec(FILE *fp, struct bt_value *value, size_t indent)
285 {
286 bt_bool bool_val;
287 int64_t int_val;
288 double dbl_val;
289 const char *str_val;
290 int size;
291 int i;
292
293 if (!value) {
294 return;
295 }
296
297 switch (bt_value_get_type(value)) {
298 case BT_VALUE_TYPE_NULL:
299 fprintf(fp, "%snull%s\n", bt_common_color_bold(),
300 bt_common_color_reset());
301 break;
302 case BT_VALUE_TYPE_BOOL:
303 bt_value_bool_get(value, &bool_val);
304 fprintf(fp, "%s%s%s%s\n", bt_common_color_bold(),
305 bt_common_color_fg_cyan(), bool_val ? "yes" : "no",
306 bt_common_color_reset());
307 break;
308 case BT_VALUE_TYPE_INTEGER:
309 bt_value_integer_get(value, &int_val);
310 fprintf(fp, "%s%s%" PRId64 "%s\n", bt_common_color_bold(),
311 bt_common_color_fg_red(), int_val,
312 bt_common_color_reset());
313 break;
314 case BT_VALUE_TYPE_FLOAT:
315 bt_value_float_get(value, &dbl_val);
316 fprintf(fp, "%s%s%lf%s\n", bt_common_color_bold(),
317 bt_common_color_fg_red(), dbl_val,
318 bt_common_color_reset());
319 break;
320 case BT_VALUE_TYPE_STRING:
321 bt_value_string_get(value, &str_val);
322 fprintf(fp, "%s%s%s%s\n", bt_common_color_bold(),
323 bt_common_color_fg_green(), str_val,
324 bt_common_color_reset());
325 break;
326 case BT_VALUE_TYPE_ARRAY:
327 size = bt_value_array_size(value);
328 assert(size >= 0);
329
330 if (size == 0) {
331 print_indent(fp, indent);
332 fprintf(fp, "[ ]\n");
333 break;
334 }
335
336 for (i = 0; i < size; i++) {
337 struct bt_value *element =
338 bt_value_array_get(value, i);
339
340 assert(element);
341 print_indent(fp, indent);
342 fprintf(fp, "- ");
343
344 if (bt_value_is_array(element) &&
345 bt_value_array_is_empty(element)) {
346 fprintf(fp, "[ ]\n");
347 continue;
348 }
349
350 if (bt_value_is_map(element) &&
351 bt_value_map_is_empty(element)) {
352 fprintf(fp, "{ }\n");
353 continue;
354 }
355
356 if (bt_value_is_array(element) ||
357 bt_value_is_map(element)) {
358 fprintf(fp, "\n");
359 }
360
361 print_value_rec(fp, element, indent + 2);
362 BT_PUT(element);
363 }
364 break;
365 case BT_VALUE_TYPE_MAP:
366 {
367 struct print_map_value_data data = {
368 .indent = indent,
369 .fp = fp,
370 };
371
372 if (bt_value_map_is_empty(value)) {
373 print_indent(fp, indent);
374 fprintf(fp, "{ }\n");
375 break;
376 }
377
378 bt_value_map_foreach(value, print_map_value, &data);
379 break;
380 }
381 default:
382 abort();
383 }
384 }
385
386 static
387 void print_value(FILE *fp, struct bt_value *value, size_t indent)
388 {
389 if (!bt_value_is_array(value) && !bt_value_is_map(value)) {
390 print_indent(fp, indent);
391 }
392
393 print_value_rec(fp, value, indent);
394 }
395
396 static
397 void print_bt_config_component(struct bt_config_component *bt_config_component)
398 {
399 fprintf(stderr, " ");
400 print_plugin_comp_cls_opt(stderr, bt_config_component->plugin_name->str,
401 bt_config_component->comp_cls_name->str,
402 bt_config_component->type);
403 fprintf(stderr, ":\n");
404
405 if (bt_config_component->instance_name->len > 0) {
406 fprintf(stderr, " Name: %s\n",
407 bt_config_component->instance_name->str);
408 }
409
410 fprintf(stderr, " Parameters:\n");
411 print_value(stderr, bt_config_component->params, 8);
412 }
413
414 static
415 void print_bt_config_components(GPtrArray *array)
416 {
417 size_t i;
418
419 for (i = 0; i < array->len; i++) {
420 struct bt_config_component *cfg_component =
421 bt_config_get_component(array, i);
422 print_bt_config_component(cfg_component);
423 BT_PUT(cfg_component);
424 }
425 }
426
427 static
428 void print_plugin_paths(struct bt_value *plugin_paths)
429 {
430 fprintf(stderr, " Plugin paths:\n");
431 print_value(stderr, plugin_paths, 4);
432 }
433
434 static
435 void print_cfg_run(struct bt_config *cfg)
436 {
437 size_t i;
438
439 print_plugin_paths(cfg->plugin_paths);
440 fprintf(stderr, " Source component instances:\n");
441 print_bt_config_components(cfg->cmd_data.run.sources);
442
443 if (cfg->cmd_data.run.filters->len > 0) {
444 fprintf(stderr, " Filter component instances:\n");
445 print_bt_config_components(cfg->cmd_data.run.filters);
446 }
447
448 fprintf(stderr, " Sink component instances:\n");
449 print_bt_config_components(cfg->cmd_data.run.sinks);
450 fprintf(stderr, " Connections:\n");
451
452 for (i = 0; i < cfg->cmd_data.run.connections->len; i++) {
453 struct bt_config_connection *cfg_connection =
454 g_ptr_array_index(cfg->cmd_data.run.connections,
455 i);
456
457 fprintf(stderr, " %s%s%s -> %s%s%s\n",
458 cfg_connection->upstream_comp_name->str,
459 cfg_connection->upstream_port_glob->len > 0 ? "." : "",
460 cfg_connection->upstream_port_glob->str,
461 cfg_connection->downstream_comp_name->str,
462 cfg_connection->downstream_port_glob->len > 0 ? "." : "",
463 cfg_connection->downstream_port_glob->str);
464 }
465 }
466
467 static
468 void print_cfg_list_plugins(struct bt_config *cfg)
469 {
470 print_plugin_paths(cfg->plugin_paths);
471 }
472
473 static
474 void print_cfg_help(struct bt_config *cfg)
475 {
476 print_plugin_paths(cfg->plugin_paths);
477 }
478
479 static
480 void print_cfg_print_ctf_metadata(struct bt_config *cfg)
481 {
482 print_plugin_paths(cfg->plugin_paths);
483 fprintf(stderr, " Path: %s\n",
484 cfg->cmd_data.print_ctf_metadata.path->str);
485 }
486
487 static
488 void print_cfg_print_lttng_live_sessions(struct bt_config *cfg)
489 {
490 print_plugin_paths(cfg->plugin_paths);
491 fprintf(stderr, " URL: %s\n",
492 cfg->cmd_data.print_lttng_live_sessions.url->str);
493 }
494
495 static
496 void print_cfg_query(struct bt_config *cfg)
497 {
498 print_plugin_paths(cfg->plugin_paths);
499 fprintf(stderr, " Object: `%s`\n", cfg->cmd_data.query.object->str);
500 fprintf(stderr, " Component class:\n");
501 print_bt_config_component(cfg->cmd_data.query.cfg_component);
502 }
503
504 static
505 void print_cfg(struct bt_config *cfg)
506 {
507 if (!BT_LOG_ON_INFO) {
508 return;
509 }
510
511 BT_LOGI_STR("Configuration:");
512 fprintf(stderr, " Debug mode: %s\n", cfg->debug ? "yes" : "no");
513 fprintf(stderr, " Verbose mode: %s\n", cfg->verbose ? "yes" : "no");
514
515 switch (cfg->command) {
516 case BT_CONFIG_COMMAND_RUN:
517 print_cfg_run(cfg);
518 break;
519 case BT_CONFIG_COMMAND_LIST_PLUGINS:
520 print_cfg_list_plugins(cfg);
521 break;
522 case BT_CONFIG_COMMAND_HELP:
523 print_cfg_help(cfg);
524 break;
525 case BT_CONFIG_COMMAND_QUERY:
526 print_cfg_query(cfg);
527 break;
528 case BT_CONFIG_COMMAND_PRINT_CTF_METADATA:
529 print_cfg_print_ctf_metadata(cfg);
530 break;
531 case BT_CONFIG_COMMAND_PRINT_LTTNG_LIVE_SESSIONS:
532 print_cfg_print_lttng_live_sessions(cfg);
533 break;
534 default:
535 abort();
536 }
537 }
538
539 static
540 void add_to_loaded_plugins(struct bt_plugin_set *plugin_set)
541 {
542 int64_t i;
543 int64_t count;
544
545 count = bt_plugin_set_get_plugin_count(plugin_set);
546 assert(count >= 0);
547
548 for (i = 0; i < count; i++) {
549 struct bt_plugin *plugin =
550 bt_plugin_set_get_plugin(plugin_set, i);
551 struct bt_plugin *loaded_plugin =
552 find_plugin(bt_plugin_get_name(plugin));
553
554 assert(plugin);
555
556 if (loaded_plugin) {
557 BT_LOGI("Not using plugin: another one already exists with the same name: "
558 "plugin-name=\"%s\", plugin-path=\"%s\", "
559 "existing-plugin-path=\"%s\"",
560 bt_plugin_get_name(plugin),
561 bt_plugin_get_path(plugin),
562 bt_plugin_get_path(loaded_plugin));
563 bt_put(loaded_plugin);
564 } else {
565 /* Add to global array. */
566 BT_LOGD("Adding plugin to loaded plugins: plugin-path=\"%s\"",
567 bt_plugin_get_name(plugin));
568 g_ptr_array_add(loaded_plugins, bt_get(plugin));
569 }
570
571 bt_put(plugin);
572 }
573 }
574
575 static
576 int load_dynamic_plugins(struct bt_value *plugin_paths)
577 {
578 int nr_paths, i, ret = 0;
579
580 nr_paths = bt_value_array_size(plugin_paths);
581 if (nr_paths < 0) {
582 BT_LOGE_STR("Cannot load dynamic plugins: no plugin path.");
583 ret = -1;
584 goto end;
585 }
586
587 BT_LOGI("Loading dynamic plugins.");
588
589 for (i = 0; i < nr_paths; i++) {
590 struct bt_value *plugin_path_value = NULL;
591 const char *plugin_path;
592 struct bt_plugin_set *plugin_set;
593
594 plugin_path_value = bt_value_array_get(plugin_paths, i);
595 bt_value_string_get(plugin_path_value, &plugin_path);
596 assert(plugin_path);
597
598 /*
599 * Skip this if the directory does not exist because
600 * bt_plugin_create_all_from_dir() expects an existing
601 * directory.
602 */
603 if (!g_file_test(plugin_path, G_FILE_TEST_IS_DIR)) {
604 BT_LOGV("Skipping nonexistent directory path: "
605 "path=\"%s\"", plugin_path);
606 BT_PUT(plugin_path_value);
607 continue;
608 }
609
610 plugin_set = bt_plugin_create_all_from_dir(plugin_path, false);
611 if (!plugin_set) {
612 BT_LOGD("Unable to load dynamic plugins: path=\"%s\"",
613 plugin_path);
614 BT_PUT(plugin_path_value);
615 continue;
616 }
617
618 add_to_loaded_plugins(plugin_set);
619 bt_put(plugin_set);
620 BT_PUT(plugin_path_value);
621 }
622 end:
623 return ret;
624 }
625
626 static
627 int load_static_plugins(void)
628 {
629 int ret = 0;
630 struct bt_plugin_set *plugin_set;
631
632 BT_LOGI("Loading static plugins.");
633 plugin_set = bt_plugin_create_all_from_static();
634 if (!plugin_set) {
635 BT_LOGE("Unable to load static plugins.");
636 ret = -1;
637 goto end;
638 }
639
640 add_to_loaded_plugins(plugin_set);
641 bt_put(plugin_set);
642 end:
643 return ret;
644 }
645
646 static
647 int load_all_plugins(struct bt_value *plugin_paths)
648 {
649 int ret = 0;
650
651 if (load_dynamic_plugins(plugin_paths)) {
652 ret = -1;
653 goto end;
654 }
655
656 if (load_static_plugins()) {
657 ret = -1;
658 goto end;
659 }
660
661 BT_LOGI("Loaded all plugins: count=%u", loaded_plugins->len);
662
663 end:
664 return ret;
665 }
666
667 static
668 void print_plugin_info(struct bt_plugin *plugin)
669 {
670 unsigned int major, minor, patch;
671 const char *extra;
672 enum bt_plugin_status version_status;
673 const char *plugin_name;
674 const char *path;
675 const char *author;
676 const char *license;
677 const char *plugin_description;
678
679 plugin_name = bt_plugin_get_name(plugin);
680 path = bt_plugin_get_path(plugin);
681 author = bt_plugin_get_author(plugin);
682 license = bt_plugin_get_license(plugin);
683 plugin_description = bt_plugin_get_description(plugin);
684 version_status = bt_plugin_get_version(plugin, &major, &minor,
685 &patch, &extra);
686 printf("%s%s%s%s:\n", bt_common_color_bold(),
687 bt_common_color_fg_blue(), plugin_name,
688 bt_common_color_reset());
689 printf(" %sPath%s: %s\n", bt_common_color_bold(),
690 bt_common_color_reset(), path ? path : "(None)");
691
692 if (version_status == BT_PLUGIN_STATUS_OK) {
693 printf(" %sVersion%s: %u.%u.%u",
694 bt_common_color_bold(), bt_common_color_reset(),
695 major, minor, patch);
696
697 if (extra) {
698 printf("%s", extra);
699 }
700
701 printf("\n");
702 }
703
704 printf(" %sDescription%s: %s\n", bt_common_color_bold(),
705 bt_common_color_reset(),
706 plugin_description ? plugin_description : "(None)");
707 printf(" %sAuthor%s: %s\n", bt_common_color_bold(),
708 bt_common_color_reset(), author ? author : "(Unknown)");
709 printf(" %sLicense%s: %s\n", bt_common_color_bold(),
710 bt_common_color_reset(),
711 license ? license : "(Unknown)");
712 }
713
714 static
715 int cmd_query(struct bt_config *cfg)
716 {
717 int ret = 0;
718 struct bt_component_class *comp_cls = NULL;
719 struct bt_value *results = NULL;
720
721 comp_cls = find_component_class(cfg->cmd_data.query.cfg_component->plugin_name->str,
722 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
723 cfg->cmd_data.query.cfg_component->type);
724 if (!comp_cls) {
725 BT_LOGE("Cannot find component class: plugin-name=\"%s\", "
726 "comp-cls-name=\"%s\", comp-cls-type=%d",
727 cfg->cmd_data.query.cfg_component->plugin_name->str,
728 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
729 cfg->cmd_data.query.cfg_component->type);
730 fprintf(stderr, "%s%sCannot find component class %s",
731 bt_common_color_bold(),
732 bt_common_color_fg_red(),
733 bt_common_color_reset());
734 print_plugin_comp_cls_opt(stderr,
735 cfg->cmd_data.query.cfg_component->plugin_name->str,
736 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
737 cfg->cmd_data.query.cfg_component->type);
738 fprintf(stderr, "\n");
739 ret = -1;
740 goto end;
741 }
742
743 results = bt_component_class_query(comp_cls,
744 cfg->cmd_data.query.object->str,
745 cfg->cmd_data.query.cfg_component->params);
746 if (!results) {
747 BT_LOGE("Failed to query component class: plugin-name=\"%s\", "
748 "comp-cls-name=\"%s\", comp-cls-type=%d "
749 "object=\"%s\"",
750 cfg->cmd_data.query.cfg_component->plugin_name->str,
751 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
752 cfg->cmd_data.query.cfg_component->type,
753 cfg->cmd_data.query.object->str);
754 fprintf(stderr, "%s%sFailed to query info to %s",
755 bt_common_color_bold(),
756 bt_common_color_fg_red(),
757 bt_common_color_reset());
758 print_plugin_comp_cls_opt(stderr,
759 cfg->cmd_data.query.cfg_component->plugin_name->str,
760 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
761 cfg->cmd_data.query.cfg_component->type);
762 fprintf(stderr, "%s%s with object `%s`%s\n",
763 bt_common_color_bold(),
764 bt_common_color_fg_red(),
765 cfg->cmd_data.query.object->str,
766 bt_common_color_reset());
767 ret = -1;
768 goto end;
769 }
770
771 print_value(stdout, results, 0);
772
773 end:
774 bt_put(comp_cls);
775 bt_put(results);
776 return ret;
777 }
778
779 static
780 int cmd_help(struct bt_config *cfg)
781 {
782 int ret = 0;
783 struct bt_plugin *plugin = NULL;
784 size_t i;
785
786 plugin = find_plugin(cfg->cmd_data.help.cfg_component->plugin_name->str);
787 if (!plugin) {
788 BT_LOGE("Cannot find plugin: plugin-name=\"%s\"",
789 cfg->cmd_data.help.cfg_component->plugin_name->str);
790 fprintf(stderr, "%s%sCannot find plugin %s%s%s\n",
791 bt_common_color_bold(), bt_common_color_fg_red(),
792 bt_common_color_fg_blue(),
793 cfg->cmd_data.help.cfg_component->plugin_name->str,
794 bt_common_color_reset());
795 ret = -1;
796 goto end;
797 }
798
799 print_plugin_info(plugin);
800 printf(" %sComponent classes%s: %d\n",
801 bt_common_color_bold(),
802 bt_common_color_reset(),
803 (int) bt_plugin_get_component_class_count(plugin));
804
805
806 if (cfg->cmd_data.help.cfg_component->type !=
807 BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
808 struct bt_component_class *needed_comp_cls =
809 find_component_class(
810 cfg->cmd_data.help.cfg_component->plugin_name->str,
811 cfg->cmd_data.help.cfg_component->comp_cls_name->str,
812 cfg->cmd_data.help.cfg_component->type);
813
814 if (!needed_comp_cls) {
815 BT_LOGE("Cannot find component class: plugin-name=\"%s\", "
816 "comp-cls-name=\"%s\", comp-cls-type=%d",
817 cfg->cmd_data.help.cfg_component->plugin_name->str,
818 cfg->cmd_data.help.cfg_component->comp_cls_name->str,
819 cfg->cmd_data.help.cfg_component->type);
820 fprintf(stderr, "\n%s%sCannot find component class %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.help.cfg_component->plugin_name->str,
826 cfg->cmd_data.help.cfg_component->comp_cls_name->str,
827 cfg->cmd_data.help.cfg_component->type);
828 fprintf(stderr, "\n");
829 ret = -1;
830 goto end;
831 }
832
833 bt_put(needed_comp_cls);
834 }
835
836 for (i = 0; i < bt_plugin_get_component_class_count(plugin); i++) {
837 struct bt_component_class *comp_cls =
838 bt_plugin_get_component_class_by_index(plugin, i);
839 const char *comp_class_name =
840 bt_component_class_get_name(comp_cls);
841 const char *comp_class_description =
842 bt_component_class_get_description(comp_cls);
843 const char *comp_class_help =
844 bt_component_class_get_help(comp_cls);
845 enum bt_component_class_type type =
846 bt_component_class_get_type(comp_cls);
847
848 assert(comp_cls);
849
850 if (cfg->cmd_data.help.cfg_component->type !=
851 BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
852 if (strcmp(cfg->cmd_data.help.cfg_component->comp_cls_name->str,
853 comp_class_name) != 0 &&
854 type ==
855 cfg->cmd_data.help.cfg_component->type) {
856 bt_put(comp_cls);
857 continue;
858 }
859 }
860
861 printf("\n");
862 print_plugin_comp_cls_opt(stdout,
863 cfg->cmd_data.help.cfg_component->plugin_name->str,
864 comp_class_name,
865 type);
866 printf("\n");
867 printf(" %sDescription%s: %s\n", bt_common_color_bold(),
868 bt_common_color_reset(),
869 comp_class_description ? comp_class_description : "(None)");
870
871 if (comp_class_help) {
872 printf("\n%s\n", comp_class_help);
873 }
874
875 bt_put(comp_cls);
876 }
877
878 end:
879 bt_put(plugin);
880 return ret;
881 }
882
883 static
884 int cmd_list_plugins(struct bt_config *cfg)
885 {
886 int ret = 0;
887 int plugins_count, component_classes_count = 0, i;
888
889 printf("From the following plugin paths:\n\n");
890 print_value(stdout, cfg->plugin_paths, 2);
891 printf("\n");
892 plugins_count = loaded_plugins->len;
893 if (plugins_count == 0) {
894 printf("No plugins found.\n");
895 goto end;
896 }
897
898 for (i = 0; i < plugins_count; i++) {
899 struct bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i);
900
901 component_classes_count += bt_plugin_get_component_class_count(plugin);
902 }
903
904 printf("Found %s%d%s component classes in %s%d%s plugins.\n",
905 bt_common_color_bold(),
906 component_classes_count,
907 bt_common_color_reset(),
908 bt_common_color_bold(),
909 plugins_count,
910 bt_common_color_reset());
911
912 for (i = 0; i < plugins_count; i++) {
913 int j;
914 struct bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i);
915
916 component_classes_count =
917 bt_plugin_get_component_class_count(plugin);
918 printf("\n");
919 print_plugin_info(plugin);
920
921 if (component_classes_count == 0) {
922 printf(" %sComponent classes%s: (none)\n",
923 bt_common_color_bold(),
924 bt_common_color_reset());
925 } else {
926 printf(" %sComponent classes%s:\n",
927 bt_common_color_bold(),
928 bt_common_color_reset());
929 }
930
931 for (j = 0; j < component_classes_count; j++) {
932 struct bt_component_class *comp_class =
933 bt_plugin_get_component_class_by_index(
934 plugin, j);
935 const char *comp_class_name =
936 bt_component_class_get_name(comp_class);
937 const char *comp_class_description =
938 bt_component_class_get_description(comp_class);
939 enum bt_component_class_type type =
940 bt_component_class_get_type(comp_class);
941
942 printf(" ");
943 print_plugin_comp_cls_opt(stdout,
944 bt_plugin_get_name(plugin), comp_class_name,
945 type);
946
947 if (comp_class_description) {
948 printf(": %s", comp_class_description);
949 }
950
951 printf("\n");
952 bt_put(comp_class);
953 }
954 }
955
956 end:
957 return ret;
958 }
959
960 static
961 int cmd_print_lttng_live_sessions(struct bt_config *cfg)
962 {
963 int ret = 0;
964 struct bt_component_class *comp_cls = NULL;
965 struct bt_value *results = NULL;
966 struct bt_value *params = NULL;
967 struct bt_value *map = NULL;
968 struct bt_value *v = NULL;
969 static const char * const plugin_name = "ctf";
970 static const char * const comp_cls_name = "lttng-live";
971 static const enum bt_component_class_type comp_cls_type =
972 BT_COMPONENT_CLASS_TYPE_SOURCE;
973 int64_t array_size, i;
974
975 assert(cfg->cmd_data.print_lttng_live_sessions.url);
976 comp_cls = find_component_class(plugin_name, comp_cls_name,
977 comp_cls_type);
978 if (!comp_cls) {
979 BT_LOGE("Cannot find component class: plugin-name=\"%s\", "
980 "comp-cls-name=\"%s\", comp-cls-type=%d",
981 plugin_name, comp_cls_name,
982 BT_COMPONENT_CLASS_TYPE_SOURCE);
983 fprintf(stderr, "%s%sCannot find component class %s",
984 bt_common_color_bold(),
985 bt_common_color_fg_red(),
986 bt_common_color_reset());
987 print_plugin_comp_cls_opt(stderr, plugin_name,
988 comp_cls_name, comp_cls_type);
989 fprintf(stderr, "\n");
990 goto error;
991 }
992
993 params = bt_value_map_create();
994 if (!params) {
995 goto error;
996 }
997
998 ret = bt_value_map_insert_string(params, "url",
999 cfg->cmd_data.print_lttng_live_sessions.url->str);
1000 if (ret) {
1001 goto error;
1002 }
1003
1004 results = bt_component_class_query(comp_cls, "sessions",
1005 params);
1006 if (!results) {
1007 BT_LOGE_STR("Failed to query for sessions.");
1008 fprintf(stderr, "%s%sFailed to request sessions%s\n",
1009 bt_common_color_bold(),
1010 bt_common_color_fg_red(),
1011 bt_common_color_reset());
1012 goto error;
1013 }
1014
1015 if (!bt_value_is_array(results)) {
1016 BT_LOGE_STR("Expecting an array for sessions query.");
1017 fprintf(stderr, "%s%sUnexpected type returned by session query%s\n",
1018 bt_common_color_bold(),
1019 bt_common_color_fg_red(),
1020 bt_common_color_reset());
1021 goto error;
1022 }
1023
1024 array_size = bt_value_array_size(results);
1025 for (i = 0; i < array_size; i++) {
1026 const char *url_text;
1027 int64_t timer_us, streams, clients;
1028
1029 map = bt_value_array_get(results, i);
1030 if (!map) {
1031 BT_LOGE_STR("Unexpected empty array entry.");
1032 goto error;
1033 }
1034 if (!bt_value_is_map(map)) {
1035 BT_LOGE_STR("Unexpected entry type.");
1036 goto error;
1037 }
1038
1039 v = bt_value_map_get(map, "url");
1040 if (!v) {
1041 BT_LOGE_STR("Unexpected empty array \"url\" entry.");
1042 goto error;
1043 }
1044 ret = bt_value_string_get(v, &url_text);
1045 assert(ret == 0);
1046 printf("%s", url_text);
1047 BT_PUT(v);
1048
1049 v = bt_value_map_get(map, "timer-us");
1050 if (!v) {
1051 BT_LOGE_STR("Unexpected empty array \"timer-us\" entry.");
1052 goto error;
1053 }
1054 ret = bt_value_integer_get(v, &timer_us);
1055 assert(ret == 0);
1056 printf(" (timer = %" PRIu64 ", ", timer_us);
1057 BT_PUT(v);
1058
1059 v = bt_value_map_get(map, "stream-count");
1060 if (!v) {
1061 BT_LOGE_STR("Unexpected empty array \"stream-count\" entry.");
1062 goto error;
1063 }
1064 ret = bt_value_integer_get(v, &streams);
1065 assert(ret == 0);
1066 printf("%" PRIu64 " stream(s), ", streams);
1067 BT_PUT(v);
1068
1069 v = bt_value_map_get(map, "client-count");
1070 if (!v) {
1071 BT_LOGE_STR("Unexpected empty array \"client-count\" entry.");
1072 goto error;
1073 }
1074 ret = bt_value_integer_get(v, &clients);
1075 assert(ret == 0);
1076 printf("%" PRIu64 " client(s) connected)\n", clients);
1077 BT_PUT(v);
1078
1079 BT_PUT(map);
1080 }
1081 end:
1082 bt_put(v);
1083 bt_put(map);
1084 bt_put(results);
1085 bt_put(params);
1086 bt_put(comp_cls);
1087 return 0;
1088
1089 error:
1090 ret = -1;
1091 goto end;
1092 }
1093
1094 static
1095 int cmd_print_ctf_metadata(struct bt_config *cfg)
1096 {
1097 int ret = 0;
1098 struct bt_component_class *comp_cls = NULL;
1099 struct bt_value *results = NULL;
1100 struct bt_value *params = NULL;
1101 struct bt_value *metadata_text_value = NULL;
1102 const char *metadata_text = NULL;
1103 static const char * const plugin_name = "ctf";
1104 static const char * const comp_cls_name = "fs";
1105 static const enum bt_component_class_type comp_cls_type =
1106 BT_COMPONENT_CLASS_TYPE_SOURCE;
1107
1108 assert(cfg->cmd_data.print_ctf_metadata.path);
1109 comp_cls = find_component_class(plugin_name, comp_cls_name,
1110 comp_cls_type);
1111 if (!comp_cls) {
1112 BT_LOGE("Cannot find component class: plugin-name=\"%s\", "
1113 "comp-cls-name=\"%s\", comp-cls-type=%d",
1114 plugin_name, comp_cls_name,
1115 BT_COMPONENT_CLASS_TYPE_SOURCE);
1116 fprintf(stderr, "%s%sCannot find component class %s",
1117 bt_common_color_bold(),
1118 bt_common_color_fg_red(),
1119 bt_common_color_reset());
1120 print_plugin_comp_cls_opt(stderr, plugin_name,
1121 comp_cls_name, comp_cls_type);
1122 fprintf(stderr, "\n");
1123 ret = -1;
1124 goto end;
1125 }
1126
1127 params = bt_value_map_create();
1128 if (!params) {
1129 ret = -1;
1130 goto end;
1131 }
1132
1133 ret = bt_value_map_insert_string(params, "path",
1134 cfg->cmd_data.print_ctf_metadata.path->str);
1135 if (ret) {
1136 ret = -1;
1137 goto end;
1138 }
1139
1140 results = bt_component_class_query(comp_cls, "metadata-info",
1141 params);
1142 if (!results) {
1143 ret = -1;
1144 BT_LOGE_STR("Failed to query for metadata info.");
1145 fprintf(stderr, "%s%sFailed to request metadata info%s\n",
1146 bt_common_color_bold(),
1147 bt_common_color_fg_red(),
1148 bt_common_color_reset());
1149 goto end;
1150 }
1151
1152 metadata_text_value = bt_value_map_get(results, "text");
1153 if (!metadata_text_value) {
1154 BT_LOGE_STR("Cannot find `text` string value in the resulting metadata info object.");
1155 ret = -1;
1156 goto end;
1157 }
1158
1159 ret = bt_value_string_get(metadata_text_value, &metadata_text);
1160 assert(ret == 0);
1161 printf("%s\n", metadata_text);
1162
1163 end:
1164 bt_put(results);
1165 bt_put(params);
1166 bt_put(metadata_text_value);
1167 bt_put(comp_cls);
1168 return 0;
1169 }
1170
1171 struct cmd_run_ctx {
1172 /* Owned by this */
1173 GHashTable *components;
1174
1175 /* Owned by this */
1176 struct bt_graph *graph;
1177
1178 /* Weak */
1179 struct bt_config *cfg;
1180
1181 bool connect_ports;
1182 };
1183
1184 static
1185 int cmd_run_ctx_connect_upstream_port_to_downstream_component(
1186 struct cmd_run_ctx *ctx, struct bt_component *upstream_comp,
1187 struct bt_port *upstream_port,
1188 struct bt_config_connection *cfg_conn)
1189 {
1190 int ret = 0;
1191 GQuark downstreamp_comp_name_quark;
1192 struct bt_component *downstream_comp;
1193 int64_t downstream_port_count;
1194 uint64_t i;
1195 int64_t (*port_count_fn)(struct bt_component *);
1196 struct bt_port *(*port_by_index_fn)(struct bt_component *, uint64_t);
1197 enum bt_graph_status status = BT_GRAPH_STATUS_ERROR;
1198
1199 BT_LOGI("Connecting upstream port to the next available downstream port: "
1200 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
1201 "downstream-comp-name=\"%s\", conn-arg=\"%s\"",
1202 upstream_port, bt_port_get_name(upstream_port),
1203 cfg_conn->downstream_comp_name->str,
1204 cfg_conn->arg->str);
1205 downstreamp_comp_name_quark = g_quark_from_string(
1206 cfg_conn->downstream_comp_name->str);
1207 assert(downstreamp_comp_name_quark > 0);
1208 downstream_comp = g_hash_table_lookup(ctx->components,
1209 GUINT_TO_POINTER(downstreamp_comp_name_quark));
1210 if (!downstream_comp) {
1211 BT_LOGE("Cannot find downstream component: comp-name=\"%s\", "
1212 "conn-arg=\"%s\"", cfg_conn->downstream_comp_name->str,
1213 cfg_conn->arg->str);
1214 fprintf(stderr, "Cannot create connection: cannot find downstream component: %s\n",
1215 cfg_conn->arg->str);
1216 goto error;
1217 }
1218
1219 if (bt_component_is_filter(downstream_comp)) {
1220 port_count_fn = bt_component_filter_get_input_port_count;
1221 port_by_index_fn = bt_component_filter_get_input_port_by_index;
1222 } else if (bt_component_is_sink(downstream_comp)) {
1223 port_count_fn = bt_component_sink_get_input_port_count;
1224 port_by_index_fn = bt_component_sink_get_input_port_by_index;
1225 } else {
1226 /*
1227 * Should never happen because the connections are
1228 * validated before we get here.
1229 */
1230 BT_LOGF("Invalid connection: downstream component is a source: "
1231 "conn-arg=\"%s\"", cfg_conn->arg->str);
1232 abort();
1233 }
1234
1235 downstream_port_count = port_count_fn(downstream_comp);
1236 assert(downstream_port_count >= 0);
1237
1238 for (i = 0; i < downstream_port_count; i++) {
1239 struct bt_port *downstream_port =
1240 port_by_index_fn(downstream_comp, i);
1241 const char *downstream_port_name;
1242
1243 assert(downstream_port);
1244
1245 /* Skip port if it's already connected */
1246 if (bt_port_is_connected(downstream_port)) {
1247 bt_put(downstream_port);
1248 BT_LOGD("Skipping downstream port: already connected: "
1249 "port-addr=%p, port-name=\"%s\"",
1250 downstream_port,
1251 bt_port_get_name(downstream_port));
1252 continue;
1253 }
1254
1255 downstream_port_name = bt_port_get_name(downstream_port);
1256 assert(downstream_port_name);
1257
1258 if (bt_common_star_glob_match(
1259 cfg_conn->downstream_port_glob->str, -1ULL,
1260 downstream_port_name, -1ULL)) {
1261 /* We have a winner! */
1262 status = bt_graph_connect_ports(ctx->graph,
1263 upstream_port, downstream_port, NULL);
1264 bt_put(downstream_port);
1265 switch (status) {
1266 case BT_GRAPH_STATUS_OK:
1267 break;
1268 case BT_GRAPH_STATUS_CANCELED:
1269 BT_LOGI_STR("Graph was canceled by user.");
1270 status = BT_GRAPH_STATUS_OK;
1271 break;
1272 case BT_GRAPH_STATUS_COMPONENT_REFUSES_PORT_CONNECTION:
1273 BT_LOGE("A component refused a connection to one of its ports: "
1274 "upstream-comp-addr=%p, upstream-comp-name=\"%s\", "
1275 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
1276 "downstream-comp-addr=%p, downstream-comp-name=\"%s\", "
1277 "downstream-port-addr=%p, downstream-port-name=\"%s\", "
1278 "conn-arg=\"%s\"",
1279 upstream_comp, bt_component_get_name(upstream_comp),
1280 upstream_port, bt_port_get_name(upstream_port),
1281 downstream_comp, cfg_conn->downstream_comp_name->str,
1282 downstream_port, downstream_port_name,
1283 cfg_conn->arg->str);
1284 fprintf(stderr,
1285 "A component refused a connection to one of its ports (`%s` to `%s`): %s\n",
1286 bt_port_get_name(upstream_port),
1287 downstream_port_name,
1288 cfg_conn->arg->str);
1289 break;
1290 default:
1291 BT_LOGE("Cannot create connection: graph refuses to connect ports: "
1292 "upstream-comp-addr=%p, upstream-comp-name=\"%s\", "
1293 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
1294 "downstream-comp-addr=%p, downstream-comp-name=\"%s\", "
1295 "downstream-port-addr=%p, downstream-port-name=\"%s\", "
1296 "conn-arg=\"%s\"",
1297 upstream_comp, bt_component_get_name(upstream_comp),
1298 upstream_port, bt_port_get_name(upstream_port),
1299 downstream_comp, cfg_conn->downstream_comp_name->str,
1300 downstream_port, downstream_port_name,
1301 cfg_conn->arg->str);
1302 fprintf(stderr,
1303 "Cannot create connection: graph refuses to connect ports (`%s` to `%s`): %s\n",
1304 bt_port_get_name(upstream_port),
1305 downstream_port_name,
1306 cfg_conn->arg->str);
1307 goto error;
1308 }
1309
1310 BT_LOGI("Connected component ports: "
1311 "upstream-comp-addr=%p, upstream-comp-name=\"%s\", "
1312 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
1313 "downstream-comp-addr=%p, downstream-comp-name=\"%s\", "
1314 "downstream-port-addr=%p, downstream-port-name=\"%s\", "
1315 "conn-arg=\"%s\"",
1316 upstream_comp, bt_component_get_name(upstream_comp),
1317 upstream_port, bt_port_get_name(upstream_port),
1318 downstream_comp, cfg_conn->downstream_comp_name->str,
1319 downstream_port, downstream_port_name,
1320 cfg_conn->arg->str);
1321
1322 goto end;
1323 }
1324
1325 bt_put(downstream_port);
1326 }
1327
1328 if (status != BT_GRAPH_STATUS_OK) {
1329 BT_LOGE("Cannot create connection: cannot find a matching downstream port for upstream port: "
1330 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
1331 "downstream-comp-name=\"%s\", conn-arg=\"%s\"",
1332 upstream_port, bt_port_get_name(upstream_port),
1333 cfg_conn->downstream_comp_name->str,
1334 cfg_conn->arg->str);
1335 fprintf(stderr,
1336 "Cannot create connection: cannot find a matching downstream port for upstream port `%s`: %s\n",
1337 bt_port_get_name(upstream_port), cfg_conn->arg->str);
1338 goto error;
1339 }
1340
1341 goto end;
1342
1343 error:
1344 ret = -1;
1345
1346 end:
1347 return ret;
1348 }
1349
1350 static
1351 int cmd_run_ctx_connect_upstream_port(struct cmd_run_ctx *ctx,
1352 struct bt_port *upstream_port)
1353 {
1354 int ret = 0;
1355 const char *upstream_port_name;
1356 const char *upstream_comp_name;
1357 struct bt_component *upstream_comp = NULL;
1358 size_t i;
1359
1360 assert(ctx);
1361 assert(upstream_port);
1362 upstream_port_name = bt_port_get_name(upstream_port);
1363 assert(upstream_port_name);
1364 upstream_comp = bt_port_get_component(upstream_port);
1365 if (!upstream_comp) {
1366 BT_LOGW("Upstream port to connect is not part of a component: "
1367 "port-addr=%p, port-name=\"%s\"",
1368 upstream_port, upstream_port_name);
1369 ret = -1;
1370 goto end;
1371 }
1372
1373 upstream_comp_name = bt_component_get_name(upstream_comp);
1374 assert(upstream_comp_name);
1375 BT_LOGI("Connecting upstream port: comp-addr=%p, comp-name=\"%s\", "
1376 "port-addr=%p, port-name=\"%s\"",
1377 upstream_comp, upstream_comp_name,
1378 upstream_port, upstream_port_name);
1379
1380 for (i = 0; i < ctx->cfg->cmd_data.run.connections->len; i++) {
1381 struct bt_config_connection *cfg_conn =
1382 g_ptr_array_index(
1383 ctx->cfg->cmd_data.run.connections, i);
1384
1385 if (strcmp(cfg_conn->upstream_comp_name->str,
1386 upstream_comp_name) == 0) {
1387 if (bt_common_star_glob_match(
1388 cfg_conn->upstream_port_glob->str,
1389 -1ULL, upstream_port_name, -1ULL)) {
1390 ret = cmd_run_ctx_connect_upstream_port_to_downstream_component(
1391 ctx, upstream_comp, upstream_port,
1392 cfg_conn);
1393 if (ret) {
1394 BT_LOGE("Cannot connect upstream port: "
1395 "port-addr=%p, port-name=\"%s\"",
1396 upstream_port,
1397 upstream_port_name);
1398 fprintf(stderr,
1399 "Cannot connect port `%s` of component `%s` to a downstream port: %s\n",
1400 upstream_port_name,
1401 upstream_comp_name,
1402 cfg_conn->arg->str);
1403 goto error;
1404 }
1405
1406 goto end;
1407 }
1408 }
1409 }
1410
1411 BT_LOGE("Cannot connect upstream port: port does not match any connection argument: "
1412 "port-addr=%p, port-name=\"%s\"", upstream_port,
1413 upstream_port_name);
1414 fprintf(stderr,
1415 "Cannot create connection: upstream port `%s` does not match any connection\n",
1416 upstream_port_name);
1417
1418 error:
1419 ret = -1;
1420
1421 end:
1422 bt_put(upstream_comp);
1423 return ret;
1424 }
1425
1426 static
1427 void graph_port_added_listener(struct bt_port *port, void *data)
1428 {
1429 struct bt_component *comp = NULL;
1430 struct cmd_run_ctx *ctx = data;
1431
1432 comp = bt_port_get_component(port);
1433 BT_LOGI("Port added to a graph's component: comp-addr=%p, "
1434 "comp-name=\"%s\", port-addr=%p, port-name=\"%s\"",
1435 comp, comp ? bt_component_get_name(comp) : "",
1436 port, bt_port_get_name(port));
1437
1438 if (!ctx->connect_ports) {
1439 goto end;
1440 }
1441
1442 if (!comp) {
1443 BT_LOGW_STR("Port has no component.");
1444 goto end;
1445 }
1446
1447 if (bt_port_is_connected(port)) {
1448 BT_LOGW_STR("Port is already connected.");
1449 goto end;
1450 }
1451
1452 if (!bt_port_is_output(port)) {
1453 BT_LOGI_STR("Skipping input port.");
1454 goto end;
1455 }
1456
1457 if (cmd_run_ctx_connect_upstream_port(ctx, port)) {
1458 BT_LOGF_STR("Cannot connect upstream port.");
1459 fprintf(stderr, "Added port could not be connected: aborting\n");
1460 abort();
1461 }
1462
1463 end:
1464 bt_put(comp);
1465 return;
1466 }
1467
1468 static
1469 void graph_port_removed_listener(struct bt_component *component,
1470 struct bt_port *port, void *data)
1471 {
1472 BT_LOGI("Port removed from a graph's component: comp-addr=%p, "
1473 "comp-name=\"%s\", port-addr=%p, port-name=\"%s\"",
1474 component, bt_component_get_name(component),
1475 port, bt_port_get_name(port));
1476 }
1477
1478 static
1479 void graph_ports_connected_listener(struct bt_port *upstream_port,
1480 struct bt_port *downstream_port, void *data)
1481 {
1482 struct bt_component *upstream_comp = bt_port_get_component(upstream_port);
1483 struct bt_component *downstream_comp = bt_port_get_component(downstream_port);
1484
1485 assert(upstream_comp);
1486 assert(downstream_comp);
1487 BT_LOGI("Graph's component ports connected: "
1488 "upstream-comp-addr=%p, upstream-comp-name=\"%s\", "
1489 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
1490 "downstream-comp-addr=%p, downstream-comp-name=\"%s\", "
1491 "downstream-port-addr=%p, downstream-port-name=\"%s\"",
1492 upstream_comp, bt_component_get_name(upstream_comp),
1493 upstream_port, bt_port_get_name(upstream_port),
1494 downstream_comp, bt_component_get_name(downstream_comp),
1495 downstream_port, bt_port_get_name(downstream_port));
1496 bt_put(upstream_comp);
1497 bt_put(downstream_comp);
1498 }
1499
1500 static
1501 void graph_ports_disconnected_listener(
1502 struct bt_component *upstream_component,
1503 struct bt_component *downstream_component,
1504 struct bt_port *upstream_port, struct bt_port *downstream_port,
1505 void *data)
1506 {
1507 BT_LOGI("Graph's component ports disconnected: "
1508 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
1509 "downstream-port-addr=%p, downstream-port-name=\"%s\"",
1510 upstream_port, bt_port_get_name(upstream_port),
1511 downstream_port, bt_port_get_name(downstream_port));
1512 }
1513
1514 static
1515 void cmd_run_ctx_destroy(struct cmd_run_ctx *ctx)
1516 {
1517 if (!ctx) {
1518 return;
1519 }
1520
1521 if (ctx->components) {
1522 g_hash_table_destroy(ctx->components);
1523 ctx->components = NULL;
1524 }
1525
1526 BT_PUT(ctx->graph);
1527 the_graph = NULL;
1528 ctx->cfg = NULL;
1529 }
1530
1531 static
1532 int cmd_run_ctx_init(struct cmd_run_ctx *ctx, struct bt_config *cfg)
1533 {
1534 int ret = 0;
1535
1536 ctx->cfg = cfg;
1537 ctx->connect_ports = false;
1538 ctx->components = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1539 NULL, bt_put);
1540 if (!ctx->components) {
1541 goto error;
1542 }
1543
1544 ctx->graph = bt_graph_create();
1545 if (!ctx->graph) {
1546 goto error;
1547 }
1548
1549 the_graph = ctx->graph;
1550 ret = bt_graph_add_port_added_listener(ctx->graph,
1551 graph_port_added_listener, ctx);
1552 if (ret < 0) {
1553 BT_LOGE_STR("Cannot add \"port added\" listener to graph.");
1554 goto error;
1555 }
1556
1557 ret = bt_graph_add_port_removed_listener(ctx->graph,
1558 graph_port_removed_listener, ctx);
1559 if (ret < 0) {
1560 BT_LOGE_STR("Cannot add \"port removed\" listener to graph.");
1561 goto error;
1562 }
1563
1564 ret = bt_graph_add_ports_connected_listener(ctx->graph,
1565 graph_ports_connected_listener, ctx);
1566 if (ret < 0) {
1567 BT_LOGE_STR("Cannot add \"ports connected\" listener to graph.");
1568 goto error;
1569 }
1570
1571 ret = bt_graph_add_ports_disconnected_listener(ctx->graph,
1572 graph_ports_disconnected_listener, ctx);
1573 if (ret < 0) {
1574 BT_LOGE_STR("Cannot add \"ports disconnected\" listener to graph.");
1575 goto error;
1576 }
1577
1578 goto end;
1579
1580 error:
1581 cmd_run_ctx_destroy(ctx);
1582 ret = -1;
1583
1584 end:
1585 return ret;
1586 }
1587
1588 static
1589 int cmd_run_ctx_create_components_from_config_components(
1590 struct cmd_run_ctx *ctx, GPtrArray *cfg_components)
1591 {
1592 size_t i;
1593 struct bt_component_class *comp_cls = NULL;
1594 struct bt_component *comp = NULL;
1595 int ret = 0;
1596
1597 for (i = 0; i < cfg_components->len; i++) {
1598 struct bt_config_component *cfg_comp =
1599 g_ptr_array_index(cfg_components, i);
1600 GQuark quark;
1601
1602 comp_cls = find_component_class(cfg_comp->plugin_name->str,
1603 cfg_comp->comp_cls_name->str, cfg_comp->type);
1604 if (!comp_cls) {
1605 BT_LOGE("Cannot find component class: plugin-name=\"%s\", "
1606 "comp-cls-name=\"%s\", comp-cls-type=%d",
1607 cfg_comp->plugin_name->str,
1608 cfg_comp->comp_cls_name->str,
1609 cfg_comp->type);
1610 fprintf(stderr, "%s%sCannot find component class %s",
1611 bt_common_color_bold(),
1612 bt_common_color_fg_red(),
1613 bt_common_color_reset());
1614 print_plugin_comp_cls_opt(stderr,
1615 cfg_comp->plugin_name->str,
1616 cfg_comp->comp_cls_name->str,
1617 cfg_comp->type);
1618 fprintf(stderr, "\n");
1619 goto error;
1620 }
1621
1622 ret = bt_graph_add_component(ctx->graph, comp_cls,
1623 cfg_comp->instance_name->str, cfg_comp->params, &comp);
1624 if (ret) {
1625 BT_LOGE("Cannot create component: plugin-name=\"%s\", "
1626 "comp-cls-name=\"%s\", comp-cls-type=%d, "
1627 "comp-name=\"%s\"",
1628 cfg_comp->plugin_name->str,
1629 cfg_comp->comp_cls_name->str,
1630 cfg_comp->type, cfg_comp->instance_name->str);
1631 fprintf(stderr, "%s%sCannot create component `%s`%s\n",
1632 bt_common_color_bold(),
1633 bt_common_color_fg_red(),
1634 cfg_comp->instance_name->str,
1635 bt_common_color_reset());
1636 goto error;
1637 }
1638
1639 BT_LOGI("Created and inserted component: comp-addr=%p, comp-name=\"%s\"",
1640 comp, cfg_comp->instance_name->str);
1641 quark = g_quark_from_string(cfg_comp->instance_name->str);
1642 assert(quark > 0);
1643 g_hash_table_insert(ctx->components,
1644 GUINT_TO_POINTER(quark), comp);
1645 comp = NULL;
1646 BT_PUT(comp_cls);
1647 }
1648
1649 goto end;
1650
1651 error:
1652 ret = -1;
1653
1654 end:
1655 bt_put(comp);
1656 bt_put(comp_cls);
1657 return ret;
1658 }
1659
1660 static
1661 int cmd_run_ctx_create_components(struct cmd_run_ctx *ctx)
1662 {
1663 int ret = 0;
1664
1665 /*
1666 * Make sure that, during this phase, our graph's "port added"
1667 * listener does not connect ports while we are creating the
1668 * components because we have a special, initial phase for
1669 * this.
1670 */
1671 ctx->connect_ports = false;
1672
1673 ret = cmd_run_ctx_create_components_from_config_components(
1674 ctx, ctx->cfg->cmd_data.run.sources);
1675 if (ret) {
1676 ret = -1;
1677 goto end;
1678 }
1679
1680 ret = cmd_run_ctx_create_components_from_config_components(
1681 ctx, ctx->cfg->cmd_data.run.filters);
1682 if (ret) {
1683 ret = -1;
1684 goto end;
1685 }
1686
1687 ret = cmd_run_ctx_create_components_from_config_components(
1688 ctx, ctx->cfg->cmd_data.run.sinks);
1689 if (ret) {
1690 ret = -1;
1691 goto end;
1692 }
1693
1694 end:
1695 return ret;
1696 }
1697
1698 static
1699 int cmd_run_ctx_connect_comp_ports(struct cmd_run_ctx *ctx,
1700 struct bt_component *comp,
1701 int64_t (*port_count_fn)(struct bt_component *),
1702 struct bt_port *(*port_by_index_fn)(struct bt_component *, uint64_t))
1703 {
1704 int ret = 0;
1705 int64_t count;
1706 uint64_t i;
1707
1708 count = port_count_fn(comp);
1709 assert(count >= 0);
1710
1711 for (i = 0; i < count; i++) {
1712 struct bt_port *upstream_port = port_by_index_fn(comp, i);
1713
1714 assert(upstream_port);
1715 ret = cmd_run_ctx_connect_upstream_port(ctx, upstream_port);
1716 bt_put(upstream_port);
1717 if (ret) {
1718 goto end;
1719 }
1720 }
1721
1722 end:
1723 return ret;
1724 }
1725
1726 static
1727 int cmd_run_ctx_connect_ports(struct cmd_run_ctx *ctx)
1728 {
1729 int ret = 0;
1730 GHashTableIter iter;
1731 gpointer g_name_quark, g_comp;
1732
1733 ctx->connect_ports = true;
1734 g_hash_table_iter_init(&iter, ctx->components);
1735
1736 while (g_hash_table_iter_next(&iter, &g_name_quark, &g_comp)) {
1737 if (bt_component_is_source(g_comp)) {
1738 ret = cmd_run_ctx_connect_comp_ports(ctx,
1739 g_comp, bt_component_source_get_output_port_count,
1740 bt_component_source_get_output_port_by_index);
1741 } else if (bt_component_is_filter(g_comp)) {
1742 ret = cmd_run_ctx_connect_comp_ports(ctx,
1743 g_comp, bt_component_filter_get_output_port_count,
1744 bt_component_filter_get_output_port_by_index);
1745 }
1746
1747 if (ret) {
1748 goto end;
1749 }
1750 }
1751
1752 end:
1753 return ret;
1754 }
1755
1756 static inline
1757 const char *bt_graph_status_str(enum bt_graph_status status)
1758 {
1759 switch (status) {
1760 case BT_GRAPH_STATUS_CANCELED:
1761 return "BT_GRAPH_STATUS_CANCELED";
1762 case BT_GRAPH_STATUS_AGAIN:
1763 return "BT_GRAPH_STATUS_AGAIN";
1764 case BT_GRAPH_STATUS_END:
1765 return "BT_GRAPH_STATUS_END";
1766 case BT_GRAPH_STATUS_OK:
1767 return "BT_GRAPH_STATUS_OK";
1768 case BT_GRAPH_STATUS_INVALID:
1769 return "BT_GRAPH_STATUS_INVALID";
1770 case BT_GRAPH_STATUS_NO_SINK:
1771 return "BT_GRAPH_STATUS_NO_SINK";
1772 case BT_GRAPH_STATUS_ERROR:
1773 return "BT_GRAPH_STATUS_ERROR";
1774 default:
1775 return "(unknown)";
1776 }
1777 }
1778
1779 static
1780 int cmd_run(struct bt_config *cfg)
1781 {
1782 int ret = 0;
1783 struct cmd_run_ctx ctx = { 0 };
1784
1785 /* Initialize the command's context and the graph object */
1786 if (cmd_run_ctx_init(&ctx, cfg)) {
1787 BT_LOGE_STR("Cannot initialize the command's context.");
1788 fprintf(stderr, "Cannot initialize the command's context\n");
1789 goto error;
1790 }
1791
1792 if (canceled) {
1793 BT_LOGI_STR("Canceled by user before creating components.");
1794 goto error;
1795 }
1796
1797 BT_LOGI_STR("Creating components.");
1798
1799 /* Create the requested component instances */
1800 if (cmd_run_ctx_create_components(&ctx)) {
1801 BT_LOGE_STR("Cannot create components.");
1802 fprintf(stderr, "Cannot create components\n");
1803 goto error;
1804 }
1805
1806 if (canceled) {
1807 BT_LOGI_STR("Canceled by user before connecting components.");
1808 goto error;
1809 }
1810
1811 BT_LOGI_STR("Connecting components.");
1812
1813 /* Connect the initially visible component ports */
1814 if (cmd_run_ctx_connect_ports(&ctx)) {
1815 BT_LOGE_STR("Cannot connect initial component ports.");
1816 fprintf(stderr, "Cannot connect initial component ports\n");
1817 goto error;
1818 }
1819
1820 if (canceled) {
1821 BT_LOGI_STR("Canceled by user before running the graph.");
1822 goto error;
1823 }
1824
1825 BT_LOGI_STR("Running the graph.");
1826
1827 /* Run the graph */
1828 while (true) {
1829 enum bt_graph_status graph_status = bt_graph_run(ctx.graph);
1830
1831 /*
1832 * Reset console in case something messed with console
1833 * codes during the graph's execution.
1834 */
1835 printf("%s", bt_common_color_reset());
1836 fflush(stdout);
1837 fprintf(stderr, "%s", bt_common_color_reset());
1838 BT_LOGV("bt_graph_run() returned: status=%s",
1839 bt_graph_status_str(graph_status));
1840
1841 switch (graph_status) {
1842 case BT_GRAPH_STATUS_OK:
1843 break;
1844 case BT_GRAPH_STATUS_CANCELED:
1845 BT_LOGI_STR("Graph was canceled by user.");
1846 goto error;
1847 case BT_GRAPH_STATUS_AGAIN:
1848 if (bt_graph_is_canceled(ctx.graph)) {
1849 BT_LOGI_STR("Graph was canceled by user.");
1850 goto error;
1851 }
1852
1853 if (cfg->cmd_data.run.retry_duration_us > 0) {
1854 BT_LOGV("Got BT_GRAPH_STATUS_AGAIN: sleeping: "
1855 "time-us=%" PRIu64,
1856 cfg->cmd_data.run.retry_duration_us);
1857
1858 if (usleep(cfg->cmd_data.run.retry_duration_us)) {
1859 if (bt_graph_is_canceled(ctx.graph)) {
1860 BT_LOGI_STR("Graph was canceled by user.");
1861 goto error;
1862 }
1863 }
1864 }
1865 break;
1866 case BT_COMPONENT_STATUS_END:
1867 goto end;
1868 default:
1869 BT_LOGE_STR("Graph failed to complete successfully");
1870 fprintf(stderr, "Graph failed to complete successfully\n");
1871 goto error;
1872 }
1873 }
1874
1875 goto end;
1876
1877 error:
1878 if (ret == 0) {
1879 ret = -1;
1880 }
1881
1882 end:
1883 cmd_run_ctx_destroy(&ctx);
1884 return ret;
1885 }
1886
1887 static
1888 void warn_command_name_and_directory_clash(struct bt_config *cfg)
1889 {
1890 const char *env_clash;
1891
1892 if (!cfg->command_name) {
1893 return;
1894 }
1895
1896 env_clash = getenv(ENV_BABELTRACE_WARN_COMMAND_NAME_DIRECTORY_CLASH);
1897 if (env_clash && strcmp(env_clash, "0") == 0) {
1898 return;
1899 }
1900
1901 if (g_file_test(cfg->command_name,
1902 G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
1903 fprintf(stderr, "\nNOTE: The `%s` command was executed. If you meant to convert a\n",
1904 cfg->command_name);
1905 fprintf(stderr, "trace located in the local `%s` directory, please use:\n",
1906 cfg->command_name);
1907 fprintf(stderr, "\n");
1908 fprintf(stderr, " babeltrace convert %s [OPTIONS]\n",
1909 cfg->command_name);
1910 }
1911 }
1912
1913 static
1914 void init_log_level(void)
1915 {
1916 bt_cli_log_level = bt_log_get_level_from_env(ENV_BABELTRACE_CLI_LOG_LEVEL);
1917 }
1918
1919 static
1920 void set_auto_log_levels(struct bt_config *cfg)
1921 {
1922 const char **env_var_name;
1923
1924 /*
1925 * Override the configuration's default log level if
1926 * BABELTRACE_VERBOSE or BABELTRACE_DEBUG environment variables
1927 * are found for backward compatibility with legacy Babetrace 1.
1928 */
1929 if (getenv("BABELTRACE_DEBUG") &&
1930 strcmp(getenv("BABELTRACE_DEBUG"), "1") == 0) {
1931 cfg->log_level = 'V';
1932 } else if (getenv("BABELTRACE_VERBOSE") &&
1933 strcmp(getenv("BABELTRACE_VERBOSE"), "1") == 0) {
1934 cfg->log_level = 'I';
1935 }
1936
1937 /*
1938 * Set log levels according to --debug or --verbose. For
1939 * backward compatibility, --debug is more verbose than
1940 * --verbose. So:
1941 *
1942 * --verbose: INFO log level
1943 * --debug: VERBOSE log level (includes DEBUG, which is
1944 * is less verbose than VERBOSE in the internal
1945 * logging framework)
1946 */
1947 if (!getenv("BABELTRACE_LOGGING_GLOBAL_LEVEL")) {
1948 if (cfg->verbose) {
1949 bt_logging_set_global_level(BT_LOGGING_LEVEL_INFO);
1950 } else if (cfg->debug) {
1951 bt_logging_set_global_level(BT_LOGGING_LEVEL_VERBOSE);
1952 } else {
1953 /*
1954 * Set library's default log level if not
1955 * explicitly specified.
1956 */
1957 switch (cfg->log_level) {
1958 case 'N':
1959 bt_logging_set_global_level(BT_LOGGING_LEVEL_NONE);
1960 break;
1961 case 'V':
1962 bt_logging_set_global_level(BT_LOGGING_LEVEL_VERBOSE);
1963 break;
1964 case 'D':
1965 bt_logging_set_global_level(BT_LOGGING_LEVEL_DEBUG);
1966 break;
1967 case 'I':
1968 bt_logging_set_global_level(BT_LOGGING_LEVEL_INFO);
1969 break;
1970 case 'W':
1971 bt_logging_set_global_level(BT_LOGGING_LEVEL_WARN);
1972 break;
1973 case 'E':
1974 bt_logging_set_global_level(BT_LOGGING_LEVEL_ERROR);
1975 break;
1976 case 'F':
1977 bt_logging_set_global_level(BT_LOGGING_LEVEL_FATAL);
1978 break;
1979 default:
1980 abort();
1981 }
1982 }
1983 }
1984
1985 if (!getenv(ENV_BABELTRACE_CLI_LOG_LEVEL)) {
1986 if (cfg->verbose) {
1987 bt_cli_log_level = BT_LOG_INFO;
1988 } else if (cfg->debug) {
1989 bt_cli_log_level = BT_LOG_VERBOSE;
1990 } else {
1991 /*
1992 * Set CLI's default log level if not explicitly
1993 * specified.
1994 */
1995 switch (cfg->log_level) {
1996 case 'N':
1997 bt_cli_log_level = BT_LOG_NONE;
1998 break;
1999 case 'V':
2000 bt_cli_log_level = BT_LOG_VERBOSE;
2001 break;
2002 case 'D':
2003 bt_cli_log_level = BT_LOG_DEBUG;
2004 break;
2005 case 'I':
2006 bt_cli_log_level = BT_LOG_INFO;
2007 break;
2008 case 'W':
2009 bt_cli_log_level = BT_LOG_WARN;
2010 break;
2011 case 'E':
2012 bt_cli_log_level = BT_LOG_ERROR;
2013 break;
2014 case 'F':
2015 bt_cli_log_level = BT_LOG_FATAL;
2016 break;
2017 default:
2018 abort();
2019 }
2020 }
2021 }
2022
2023 env_var_name = log_level_env_var_names;
2024
2025 while (*env_var_name) {
2026 if (!getenv(*env_var_name)) {
2027 if (cfg->verbose) {
2028 setenv(*env_var_name, "I", 1);
2029 } else if (cfg->debug) {
2030 setenv(*env_var_name, "V", 1);
2031 } else {
2032 char val[2] = { 0 };
2033
2034 /*
2035 * Set module's default log level if not
2036 * explicitly specified.
2037 */
2038 val[0] = cfg->log_level;
2039 setenv(*env_var_name, val, 1);
2040 }
2041 }
2042
2043 env_var_name++;
2044 }
2045 }
2046
2047 static
2048 void set_sigint_handler(void)
2049 {
2050 struct sigaction new_action, old_action;
2051
2052 new_action.sa_handler = sigint_handler;
2053 sigemptyset(&new_action.sa_mask);
2054 new_action.sa_flags = 0;
2055 sigaction(SIGINT, NULL, &old_action);
2056
2057 if (old_action.sa_handler != SIG_IGN) {
2058 sigaction(SIGINT, &new_action, NULL);
2059 }
2060 }
2061
2062 int main(int argc, const char **argv)
2063 {
2064 int ret;
2065 int retcode;
2066 struct bt_config *cfg;
2067
2068 init_log_level();
2069 set_sigint_handler();
2070 init_static_data();
2071 cfg = bt_config_cli_args_create_with_default(argc, argv, &retcode);
2072
2073 if (retcode < 0) {
2074 /* Quit without errors; typically usage/version */
2075 retcode = 0;
2076 BT_LOGI_STR("Quitting without errors.");
2077 goto end;
2078 }
2079
2080 if (retcode > 0) {
2081 BT_LOGE("Command-line error: retcode=%d", retcode);
2082 goto end;
2083 }
2084
2085 if (!cfg) {
2086 BT_LOGE_STR("Failed to create a valid Babeltrace configuration.");
2087 fprintf(stderr, "Failed to create Babeltrace configuration\n");
2088 retcode = 1;
2089 goto end;
2090 }
2091
2092 set_auto_log_levels(cfg);
2093 print_cfg(cfg);
2094
2095 if (cfg->command_needs_plugins) {
2096 ret = load_all_plugins(cfg->plugin_paths);
2097 if (ret) {
2098 BT_LOGE("Failed to load plugins: ret=%d", ret);
2099 retcode = 1;
2100 goto end;
2101 }
2102 }
2103
2104 BT_LOGI("Executing command: cmd=%d, command-name=\"%s\"",
2105 cfg->command, cfg->command_name);
2106
2107 switch (cfg->command) {
2108 case BT_CONFIG_COMMAND_RUN:
2109 ret = cmd_run(cfg);
2110 break;
2111 case BT_CONFIG_COMMAND_LIST_PLUGINS:
2112 ret = cmd_list_plugins(cfg);
2113 break;
2114 case BT_CONFIG_COMMAND_HELP:
2115 ret = cmd_help(cfg);
2116 break;
2117 case BT_CONFIG_COMMAND_QUERY:
2118 ret = cmd_query(cfg);
2119 break;
2120 case BT_CONFIG_COMMAND_PRINT_CTF_METADATA:
2121 ret = cmd_print_ctf_metadata(cfg);
2122 break;
2123 case BT_CONFIG_COMMAND_PRINT_LTTNG_LIVE_SESSIONS:
2124 ret = cmd_print_lttng_live_sessions(cfg);
2125 break;
2126 default:
2127 BT_LOGF("Invalid/unknown command: cmd=%d", cfg->command);
2128 abort();
2129 }
2130
2131 BT_LOGI("Command completed: cmd=%d, command-name=\"%s\", ret=%d",
2132 cfg->command, cfg->command_name, ret);
2133 warn_command_name_and_directory_clash(cfg);
2134 retcode = ret ? 1 : 0;
2135
2136 end:
2137 BT_PUT(cfg);
2138 fini_static_data();
2139 return retcode;
2140 }
This page took 0.111927 seconds and 3 git commands to generate.