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