visitor-generate-ir.c: automatically map specific fields to trace's clock class
[babeltrace.git] / cli / babeltrace.c
CommitLineData
34ac0e6c
MD
1/*
2 * babeltrace.c
3 *
4 * Babeltrace Trace Converter
5 *
64fa3fec
MD
6 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
7 *
8 * Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
34ac0e6c
MD
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.
c462e188
MD
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.
34ac0e6c 27 */
4c8bfb7e 28
ea9f8b29
PP
29#define BT_LOG_TAG "CLI"
30#include "logging.h"
31
95d36295 32#include <babeltrace/babeltrace.h>
7c7c0433 33#include <babeltrace/plugin/plugin.h>
290725f7 34#include <babeltrace/common-internal.h>
b2e0c907
PP
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>
2e339de1
JG
44#include <babeltrace/ref.h>
45#include <babeltrace/values.h>
7213a328 46#include <babeltrace/logging.h>
a8ff38ef 47#include <unistd.h>
34ac0e6c 48#include <stdlib.h>
7f26a816
PP
49#include <popt.h>
50#include <string.h>
51#include <stdio.h>
33b34c43 52#include <glib.h>
dc3fffef 53#include <inttypes.h>
7cdc2bab 54#include <unistd.h>
5401f780 55#include <signal.h>
c42c79ea 56#include "babeltrace-cfg.h"
9009cc24
PP
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"
c6d4d1ae 61#define ENV_BABELTRACE_CLI_LOG_LEVEL "BABELTRACE_CLI_LOG_LEVEL"
34ac0e6c 62
fc11b6a6
PP
63/*
64 * Known environment variable names for the log levels of the project's
65 * modules.
66 */
67static 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
5401f780
PP
77/* Application's processing graph (weak) */
78static struct bt_graph *the_graph;
79static bool canceled = false;
80
33b34c43
PP
81GPtrArray *loaded_plugins;
82
5401f780
PP
83static
84void 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
33b34c43 97static
9009cc24 98void init_static_data(void)
33b34c43 99{
9009cc24 100 loaded_plugins = g_ptr_array_new_with_free_func(bt_put);
33b34c43
PP
101}
102
103static
9009cc24 104void fini_static_data(void)
33b34c43
PP
105{
106 g_ptr_array_free(loaded_plugins, TRUE);
107}
108
109static
110struct bt_plugin *find_plugin(const char *name)
111{
112 int i;
113 struct bt_plugin *plugin = NULL;
114
7213a328
PP
115 assert(name);
116 BT_LOGD("Finding plugin: name=\"%s\"", name);
117
33b34c43
PP
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
7213a328
PP
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
33b34c43
PP
136 return bt_get(plugin);
137}
138
139static
140struct bt_component_class *find_component_class(const char *plugin_name,
141 const char *comp_class_name,
d3e4dcd8 142 enum bt_component_class_type comp_class_type)
33b34c43
PP
143{
144 struct bt_component_class *comp_class = NULL;
7213a328
PP
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);
33b34c43
PP
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);
7213a328 160
33b34c43 161end:
7213a328
PP
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
33b34c43
PP
171 return comp_class;
172}
6c2f3ee5 173
c42c79ea 174static
7213a328 175void print_indent(FILE *fp, size_t indent)
c42c79ea
PP
176{
177 size_t i;
178
179 for (i = 0; i < indent; i++) {
7213a328 180 fprintf(fp, " ");
c42c79ea
PP
181 }
182}
183
87796884
PP
184static
185const 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:
fd5f8053 196 return "(unknown)";
87796884
PP
197 }
198}
199
9009cc24
PP
200static
201void print_plugin_comp_cls_opt(FILE *fh, const char *plugin_name,
87796884
PP
202 const char *comp_cls_name, enum bt_component_class_type type)
203{
9009cc24
PP
204 GString *shell_plugin_name = NULL;
205 GString *shell_comp_cls_name = NULL;
87796884 206
9009cc24 207 shell_plugin_name = bt_common_shell_quote(plugin_name, false);
87796884
PP
208 if (!shell_plugin_name) {
209 goto end;
210 }
211
9009cc24 212 shell_comp_cls_name = bt_common_shell_quote(comp_cls_name, false);
87796884
PP
213 if (!shell_comp_cls_name) {
214 goto end;
215 }
216
fd5f8053 217 fprintf(fh, "'%s%s%s%s.%s%s%s.%s%s%s'",
87796884
PP
218 bt_common_color_bold(),
219 bt_common_color_fg_cyan(),
220 component_type_str(type),
87796884 221 bt_common_color_fg_default(),
87796884 222 bt_common_color_fg_blue(),
9009cc24 223 shell_plugin_name->str,
87796884
PP
224 bt_common_color_fg_default(),
225 bt_common_color_fg_yellow(),
9009cc24 226 shell_comp_cls_name->str,
87796884
PP
227 bt_common_color_reset());
228
229end:
9009cc24
PP
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 }
87796884
PP
237}
238
c42c79ea 239static
7213a328 240void print_value(FILE *, struct bt_value *, size_t);
c42c79ea 241
c1081aa6 242static
7213a328
PP
243void print_value_rec(FILE *, struct bt_value *, size_t);
244
245struct print_map_value_data {
246 size_t indent;
247 FILE *fp;
248};
c1081aa6 249
c42c79ea 250static
c55a9f58 251bt_bool print_map_value(const char *key, struct bt_value *object, void *data)
c42c79ea 252{
7213a328 253 struct print_map_value_data *print_map_value_data = data;
290725f7 254
7213a328
PP
255 print_indent(print_map_value_data->fp, print_map_value_data->indent);
256 fprintf(print_map_value_data->fp, "%s: ", key);
290725f7
PP
257
258 if (bt_value_is_array(object) &&
259 bt_value_array_is_empty(object)) {
7213a328 260 fprintf(print_map_value_data->fp, "[ ]\n");
290725f7
PP
261 return true;
262 }
263
264 if (bt_value_is_map(object) &&
265 bt_value_map_is_empty(object)) {
7213a328 266 fprintf(print_map_value_data->fp, "{ }\n");
290725f7
PP
267 return true;
268 }
c42c79ea 269
290725f7
PP
270 if (bt_value_is_array(object) ||
271 bt_value_is_map(object)) {
7213a328 272 fprintf(print_map_value_data->fp, "\n");
290725f7 273 }
c42c79ea 274
7213a328
PP
275 print_value_rec(print_map_value_data->fp, object,
276 print_map_value_data->indent + 2);
c55a9f58 277 return BT_TRUE;
c42c79ea
PP
278}
279
280static
7213a328 281void print_value_rec(FILE *fp, struct bt_value *value, size_t indent)
c42c79ea 282{
c55a9f58 283 bt_bool bool_val;
c42c79ea
PP
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
c42c79ea
PP
294 switch (bt_value_get_type(value)) {
295 case BT_VALUE_TYPE_NULL:
7213a328 296 fprintf(fp, "%snull%s\n", bt_common_color_bold(),
c1081aa6 297 bt_common_color_reset());
c42c79ea
PP
298 break;
299 case BT_VALUE_TYPE_BOOL:
300 bt_value_bool_get(value, &bool_val);
7213a328 301 fprintf(fp, "%s%s%s%s\n", bt_common_color_bold(),
c1081aa6
PP
302 bt_common_color_fg_cyan(), bool_val ? "yes" : "no",
303 bt_common_color_reset());
c42c79ea
PP
304 break;
305 case BT_VALUE_TYPE_INTEGER:
306 bt_value_integer_get(value, &int_val);
7213a328 307 fprintf(fp, "%s%s%" PRId64 "%s\n", bt_common_color_bold(),
c1081aa6
PP
308 bt_common_color_fg_red(), int_val,
309 bt_common_color_reset());
c42c79ea
PP
310 break;
311 case BT_VALUE_TYPE_FLOAT:
312 bt_value_float_get(value, &dbl_val);
7213a328 313 fprintf(fp, "%s%s%lf%s\n", bt_common_color_bold(),
c1081aa6
PP
314 bt_common_color_fg_red(), dbl_val,
315 bt_common_color_reset());
c42c79ea
PP
316 break;
317 case BT_VALUE_TYPE_STRING:
318 bt_value_string_get(value, &str_val);
7213a328 319 fprintf(fp, "%s%s%s%s\n", bt_common_color_bold(),
c1081aa6
PP
320 bt_common_color_fg_green(), str_val,
321 bt_common_color_reset());
c42c79ea
PP
322 break;
323 case BT_VALUE_TYPE_ARRAY:
324 size = bt_value_array_size(value);
290725f7
PP
325 assert(size >= 0);
326
327 if (size == 0) {
7213a328
PP
328 print_indent(fp, indent);
329 fprintf(fp, "[ ]\n");
290725f7
PP
330 break;
331 }
c42c79ea
PP
332
333 for (i = 0; i < size; i++) {
334 struct bt_value *element =
335 bt_value_array_get(value, i);
336
290725f7 337 assert(element);
7213a328
PP
338 print_indent(fp, indent);
339 fprintf(fp, "- ");
290725f7
PP
340
341 if (bt_value_is_array(element) &&
342 bt_value_array_is_empty(element)) {
7213a328 343 fprintf(fp, "[ ]\n");
290725f7
PP
344 continue;
345 }
346
347 if (bt_value_is_map(element) &&
348 bt_value_map_is_empty(element)) {
7213a328 349 fprintf(fp, "{ }\n");
290725f7
PP
350 continue;
351 }
352
353 if (bt_value_is_array(element) ||
354 bt_value_is_map(element)) {
7213a328 355 fprintf(fp, "\n");
290725f7
PP
356 }
357
7213a328 358 print_value_rec(fp, element, indent + 2);
c42c79ea
PP
359 BT_PUT(element);
360 }
c42c79ea
PP
361 break;
362 case BT_VALUE_TYPE_MAP:
7213a328
PP
363 {
364 struct print_map_value_data data = {
365 .indent = indent,
366 .fp = fp,
367 };
368
c42c79ea 369 if (bt_value_map_is_empty(value)) {
7213a328
PP
370 print_indent(fp, indent);
371 fprintf(fp, "{ }\n");
290725f7 372 break;
c42c79ea
PP
373 }
374
7213a328 375 bt_value_map_foreach(value, print_map_value, &data);
c42c79ea 376 break;
7213a328 377 }
c42c79ea 378 default:
0fbb9a9f 379 abort();
c42c79ea
PP
380 }
381}
382
c1081aa6 383static
7213a328 384void print_value(FILE *fp, struct bt_value *value, size_t indent)
c1081aa6
PP
385{
386 if (!bt_value_is_array(value) && !bt_value_is_map(value)) {
7213a328 387 print_indent(fp, indent);
c1081aa6
PP
388 }
389
7213a328 390 print_value_rec(fp, value, indent);
c1081aa6
PP
391}
392
c42c79ea
PP
393static
394void print_bt_config_component(struct bt_config_component *bt_config_component)
395{
7213a328
PP
396 fprintf(stderr, " ");
397 print_plugin_comp_cls_opt(stderr, bt_config_component->plugin_name->str,
db0f160a 398 bt_config_component->comp_cls_name->str,
87796884 399 bt_config_component->type);
7213a328 400 fprintf(stderr, ":\n");
3b6cfcc5
PP
401
402 if (bt_config_component->instance_name->len > 0) {
7213a328 403 fprintf(stderr, " Name: %s\n",
3b6cfcc5
PP
404 bt_config_component->instance_name->str);
405 }
406
7213a328
PP
407 fprintf(stderr, " Parameters:\n");
408 print_value(stderr, bt_config_component->params, 8);
c42c79ea
PP
409}
410
411static
412void 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 =
e5bc7f81 418 bt_config_get_component(array, i);
c42c79ea
PP
419 print_bt_config_component(cfg_component);
420 BT_PUT(cfg_component);
421 }
422}
423
290725f7
PP
424static
425void print_plugin_paths(struct bt_value *plugin_paths)
426{
7213a328
PP
427 fprintf(stderr, " Plugin paths:\n");
428 print_value(stderr, plugin_paths, 4);
290725f7
PP
429}
430
431static
db0f160a 432void print_cfg_run(struct bt_config *cfg)
290725f7 433{
ebba3338
PP
434 size_t i;
435
db0f160a 436 print_plugin_paths(cfg->plugin_paths);
7213a328 437 fprintf(stderr, " Source component instances:\n");
db0f160a 438 print_bt_config_components(cfg->cmd_data.run.sources);
ebba3338 439
db0f160a 440 if (cfg->cmd_data.run.filters->len > 0) {
7213a328 441 fprintf(stderr, " Filter component instances:\n");
db0f160a 442 print_bt_config_components(cfg->cmd_data.run.filters);
ebba3338
PP
443 }
444
7213a328 445 fprintf(stderr, " Sink component instances:\n");
db0f160a 446 print_bt_config_components(cfg->cmd_data.run.sinks);
7213a328 447 fprintf(stderr, " Connections:\n");
ebba3338 448
db0f160a 449 for (i = 0; i < cfg->cmd_data.run.connections->len; i++) {
ebba3338 450 struct bt_config_connection *cfg_connection =
db0f160a 451 g_ptr_array_index(cfg->cmd_data.run.connections,
ebba3338
PP
452 i);
453
7213a328 454 fprintf(stderr, " %s%s%s -> %s%s%s\n",
9009cc24
PP
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);
ebba3338 461 }
290725f7
PP
462}
463
464static
465void print_cfg_list_plugins(struct bt_config *cfg)
466{
db0f160a 467 print_plugin_paths(cfg->plugin_paths);
290725f7
PP
468}
469
c1081aa6
PP
470static
471void print_cfg_help(struct bt_config *cfg)
472{
db0f160a
PP
473 print_plugin_paths(cfg->plugin_paths);
474}
475
476static
477void print_cfg_print_ctf_metadata(struct bt_config *cfg)
478{
479 print_plugin_paths(cfg->plugin_paths);
7213a328
PP
480 fprintf(stderr, " Path: %s\n",
481 cfg->cmd_data.print_ctf_metadata.path->str);
db0f160a
PP
482}
483
484static
485void print_cfg_print_lttng_live_sessions(struct bt_config *cfg)
486{
487 print_plugin_paths(cfg->plugin_paths);
7213a328
PP
488 fprintf(stderr, " URL: %s\n",
489 cfg->cmd_data.print_lttng_live_sessions.url->str);
c1081aa6
PP
490}
491
492static
a67681c1 493void print_cfg_query(struct bt_config *cfg)
c1081aa6 494{
db0f160a 495 print_plugin_paths(cfg->plugin_paths);
7213a328
PP
496 fprintf(stderr, " Object: `%s`\n", cfg->cmd_data.query.object->str);
497 fprintf(stderr, " Component class:\n");
a67681c1 498 print_bt_config_component(cfg->cmd_data.query.cfg_component);
c1081aa6
PP
499}
500
c42c79ea
PP
501static
502void print_cfg(struct bt_config *cfg)
503{
7213a328 504 if (!BT_LOG_ON_INFO) {
00447e45
PP
505 return;
506 }
507
7213a328
PP
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");
290725f7
PP
511
512 switch (cfg->command) {
db0f160a
PP
513 case BT_CONFIG_COMMAND_RUN:
514 print_cfg_run(cfg);
290725f7
PP
515 break;
516 case BT_CONFIG_COMMAND_LIST_PLUGINS:
517 print_cfg_list_plugins(cfg);
c1081aa6
PP
518 break;
519 case BT_CONFIG_COMMAND_HELP:
520 print_cfg_help(cfg);
521 break;
a67681c1
PP
522 case BT_CONFIG_COMMAND_QUERY:
523 print_cfg_query(cfg);
290725f7 524 break;
db0f160a
PP
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;
290725f7 531 default:
0fbb9a9f 532 abort();
290725f7 533 }
c42c79ea
PP
534}
535
33b34c43 536static
a8ff38ef 537void add_to_loaded_plugins(struct bt_plugin_set *plugin_set)
98ecef32 538{
544d0515
PP
539 int64_t i;
540 int64_t count;
a8ff38ef
PP
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);
33b34c43
PP
548 struct bt_plugin *loaded_plugin =
549 find_plugin(bt_plugin_get_name(plugin));
550
a8ff38ef
PP
551 assert(plugin);
552
33b34c43 553 if (loaded_plugin) {
7213a328
PP
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));
a8ff38ef 560 bt_put(loaded_plugin);
33b34c43 561 } else {
a8ff38ef 562 /* Add to global array. */
7213a328
PP
563 BT_LOGD("Adding plugin to loaded plugins: plugin-path=\"%s\"",
564 bt_plugin_get_name(plugin));
a8ff38ef 565 g_ptr_array_add(loaded_plugins, bt_get(plugin));
33b34c43 566 }
a8ff38ef
PP
567
568 bt_put(plugin);
33b34c43
PP
569 }
570}
571
572static
290725f7 573int load_dynamic_plugins(struct bt_value *plugin_paths)
33b34c43
PP
574{
575 int nr_paths, i, ret = 0;
98ecef32 576
290725f7 577 nr_paths = bt_value_array_size(plugin_paths);
98ecef32 578 if (nr_paths < 0) {
7213a328 579 BT_LOGE_STR("Cannot load dynamic plugins: no plugin path.");
33b34c43
PP
580 ret = -1;
581 goto end;
98ecef32 582 }
33b34c43 583
7213a328
PP
584 BT_LOGI("Loading dynamic plugins.");
585
98ecef32
MD
586 for (i = 0; i < nr_paths; i++) {
587 struct bt_value *plugin_path_value = NULL;
588 const char *plugin_path;
a8ff38ef 589 struct bt_plugin_set *plugin_set;
98ecef32 590
290725f7 591 plugin_path_value = bt_value_array_get(plugin_paths, i);
7213a328
PP
592 bt_value_string_get(plugin_path_value, &plugin_path);
593 assert(plugin_path);
50ad9320
PP
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
a8ff38ef
PP
607 plugin_set = bt_plugin_create_all_from_dir(plugin_path, false);
608 if (!plugin_set) {
7213a328 609 BT_LOGD("Unable to load dynamic plugins: path=\"%s\"",
98ecef32 610 plugin_path);
33b34c43
PP
611 BT_PUT(plugin_path_value);
612 continue;
98ecef32 613 }
33b34c43 614
a8ff38ef
PP
615 add_to_loaded_plugins(plugin_set);
616 bt_put(plugin_set);
98ecef32
MD
617 BT_PUT(plugin_path_value);
618 }
33b34c43
PP
619end:
620 return ret;
621}
622
623static
624int load_static_plugins(void)
625{
626 int ret = 0;
a8ff38ef 627 struct bt_plugin_set *plugin_set;
33b34c43 628
7213a328 629 BT_LOGI("Loading static plugins.");
a8ff38ef
PP
630 plugin_set = bt_plugin_create_all_from_static();
631 if (!plugin_set) {
7213a328 632 BT_LOGE("Unable to load static plugins.");
33b34c43
PP
633 ret = -1;
634 goto end;
635 }
636
a8ff38ef
PP
637 add_to_loaded_plugins(plugin_set);
638 bt_put(plugin_set);
33b34c43
PP
639end:
640 return ret;
98ecef32
MD
641}
642
9009cc24
PP
643static
644int load_all_plugins(struct bt_value *plugin_paths)
290725f7
PP
645{
646 int ret = 0;
33b34c43 647
290725f7 648 if (load_dynamic_plugins(plugin_paths)) {
290725f7 649 ret = -1;
c1870f57
JG
650 goto end;
651 }
652
290725f7 653 if (load_static_plugins()) {
290725f7 654 ret = -1;
c1870f57
JG
655 goto end;
656 }
657
7213a328
PP
658 BT_LOGI("Loaded all plugins: count=%u", loaded_plugins->len);
659
290725f7
PP
660end:
661 return ret;
662}
663
9009cc24
PP
664static
665void print_plugin_info(struct bt_plugin *plugin)
22e22462
PP
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
9009cc24
PP
711static
712int cmd_query(struct bt_config *cfg)
63ce0e1d 713{
db95fa29 714 int ret = 0;
63ce0e1d
PP
715 struct bt_component_class *comp_cls = NULL;
716 struct bt_value *results = NULL;
717
a67681c1 718 comp_cls = find_component_class(cfg->cmd_data.query.cfg_component->plugin_name->str,
db0f160a 719 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
a67681c1 720 cfg->cmd_data.query.cfg_component->type);
63ce0e1d 721 if (!comp_cls) {
7213a328
PP
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);
63ce0e1d
PP
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,
a67681c1 732 cfg->cmd_data.query.cfg_component->plugin_name->str,
db0f160a 733 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
a67681c1 734 cfg->cmd_data.query.cfg_component->type);
63ce0e1d
PP
735 fprintf(stderr, "\n");
736 ret = -1;
737 goto end;
738 }
739
a67681c1
PP
740 results = bt_component_class_query(comp_cls,
741 cfg->cmd_data.query.object->str,
742 cfg->cmd_data.query.cfg_component->params);
63ce0e1d 743 if (!results) {
7213a328
PP
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);
63ce0e1d
PP
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,
a67681c1 756 cfg->cmd_data.query.cfg_component->plugin_name->str,
db0f160a 757 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
a67681c1
PP
758 cfg->cmd_data.query.cfg_component->type);
759 fprintf(stderr, "%s%s with object `%s`%s\n",
63ce0e1d
PP
760 bt_common_color_bold(),
761 bt_common_color_fg_red(),
a67681c1 762 cfg->cmd_data.query.object->str,
63ce0e1d
PP
763 bt_common_color_reset());
764 ret = -1;
765 goto end;
766 }
767
7213a328 768 print_value(stdout, results, 0);
63ce0e1d
PP
769
770end:
771 bt_put(comp_cls);
772 bt_put(results);
773 return ret;
774}
775
9009cc24
PP
776static
777int cmd_help(struct bt_config *cfg)
22e22462 778{
db95fa29 779 int ret = 0;
22e22462
PP
780 struct bt_plugin *plugin = NULL;
781 size_t i;
782
90de159b 783 plugin = find_plugin(cfg->cmd_data.help.cfg_component->plugin_name->str);
22e22462 784 if (!plugin) {
7213a328
PP
785 BT_LOGE("Cannot find plugin: plugin-name=\"%s\"",
786 cfg->cmd_data.help.cfg_component->plugin_name->str);
22e22462
PP
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(),
90de159b 790 cfg->cmd_data.help.cfg_component->plugin_name->str,
22e22462
PP
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(),
544d0515 800 (int) bt_plugin_get_component_class_count(plugin));
22e22462
PP
801
802
90de159b 803 if (cfg->cmd_data.help.cfg_component->type !=
22e22462
PP
804 BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
805 struct bt_component_class *needed_comp_cls =
806 find_component_class(
90de159b 807 cfg->cmd_data.help.cfg_component->plugin_name->str,
db0f160a 808 cfg->cmd_data.help.cfg_component->comp_cls_name->str,
90de159b 809 cfg->cmd_data.help.cfg_component->type);
22e22462
PP
810
811 if (!needed_comp_cls) {
7213a328
PP
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);
22e22462
PP
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,
90de159b 822 cfg->cmd_data.help.cfg_component->plugin_name->str,
db0f160a 823 cfg->cmd_data.help.cfg_component->comp_cls_name->str,
90de159b 824 cfg->cmd_data.help.cfg_component->type);
22e22462
PP
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 =
9ac68eb1 835 bt_plugin_get_component_class_by_index(plugin, i);
22e22462
PP
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
90de159b 847 if (cfg->cmd_data.help.cfg_component->type !=
22e22462 848 BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
db0f160a 849 if (strcmp(cfg->cmd_data.help.cfg_component->comp_cls_name->str,
22e22462
PP
850 comp_class_name) != 0 &&
851 type ==
90de159b 852 cfg->cmd_data.help.cfg_component->type) {
22e22462
PP
853 bt_put(comp_cls);
854 continue;
855 }
856 }
857
858 printf("\n");
859 print_plugin_comp_cls_opt(stdout,
90de159b 860 cfg->cmd_data.help.cfg_component->plugin_name->str,
22e22462
PP
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
875end:
876 bt_put(plugin);
877 return ret;
878}
879
9009cc24
PP
880static
881int cmd_list_plugins(struct bt_config *cfg)
290725f7 882{
7213a328 883 int ret = 0;
290725f7
PP
884 int plugins_count, component_classes_count = 0, i;
885
22e22462 886 printf("From the following plugin paths:\n\n");
7213a328 887 print_value(stdout, cfg->plugin_paths, 2);
22e22462 888 printf("\n");
290725f7
PP
889 plugins_count = loaded_plugins->len;
890 if (plugins_count == 0) {
7213a328 891 printf("No plugins found.\n");
56a1cced
JG
892 goto end;
893 }
894
290725f7
PP
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 }
33bceaf8 900
290725f7
PP
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);
290725f7
PP
912
913 component_classes_count =
914 bt_plugin_get_component_class_count(plugin);
22e22462
PP
915 printf("\n");
916 print_plugin_info(plugin);
290725f7
PP
917
918 if (component_classes_count == 0) {
9009cc24 919 printf(" %sComponent classes%s: (none)\n",
290725f7
PP
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 =
9ac68eb1
PP
930 bt_plugin_get_component_class_by_index(
931 plugin, j);
290725f7
PP
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
22e22462
PP
939 printf(" ");
940 print_plugin_comp_cls_opt(stdout,
941 bt_plugin_get_name(plugin), comp_class_name,
942 type);
290725f7
PP
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
953end:
954 return ret;
955}
956
9009cc24
PP
957static
958int cmd_print_lttng_live_sessions(struct bt_config *cfg)
db0f160a 959{
96e8c7e1
MD
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 }
1078end:
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
1086error:
1087 ret = -1;
1088 goto end;
db0f160a
PP
1089}
1090
9009cc24
PP
1091static
1092int cmd_print_ctf_metadata(struct bt_config *cfg)
05a67631
PP
1093{
1094 int ret = 0;
1095 struct bt_component_class *comp_cls = NULL;
05a67631 1096 struct bt_value *results = NULL;
05a67631
PP
1097 struct bt_value *params = NULL;
1098 struct bt_value *metadata_text_value = NULL;
1099 const char *metadata_text = NULL;
db0f160a
PP
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);
05a67631 1108 if (!comp_cls) {
7213a328
PP
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);
05a67631
PP
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());
db0f160a
PP
1117 print_plugin_comp_cls_opt(stderr, plugin_name,
1118 comp_cls_name, comp_cls_type);
05a67631
PP
1119 fprintf(stderr, "\n");
1120 ret = -1;
1121 goto end;
1122 }
1123
05a67631
PP
1124 params = bt_value_map_create();
1125 if (!params) {
1126 ret = -1;
1127 goto end;
1128 }
1129
db0f160a
PP
1130 ret = bt_value_map_insert_string(params, "path",
1131 cfg->cmd_data.print_ctf_metadata.path->str);
05a67631
PP
1132 if (ret) {
1133 ret = -1;
1134 goto end;
1135 }
1136
a67681c1 1137 results = bt_component_class_query(comp_cls, "metadata-info",
05a67631
PP
1138 params);
1139 if (!results) {
1140 ret = -1;
7213a328 1141 BT_LOGE_STR("Failed to query for metadata info.");
a67681c1 1142 fprintf(stderr, "%s%sFailed to request metadata info%s\n",
05a67631
PP
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) {
7213a328 1151 BT_LOGE_STR("Cannot find `text` string value in the resulting metadata info object.");
05a67631
PP
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
1160end:
1161 bt_put(results);
05a67631
PP
1162 bt_put(params);
1163 bt_put(metadata_text_value);
1164 bt_put(comp_cls);
05a67631
PP
1165 return 0;
1166}
1167
9009cc24
PP
1168struct 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
1181static
1182int 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)
290725f7
PP
1186{
1187 int ret = 0;
9009cc24
PP
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);
a256a42d 1194 enum bt_graph_status status = BT_GRAPH_STATUS_ERROR;
9009cc24 1195
7213a328
PP
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);
9009cc24
PP
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,
71c7c95f 1206 GUINT_TO_POINTER(downstreamp_comp_name_quark));
9009cc24 1207 if (!downstream_comp) {
7213a328
PP
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);
9009cc24
PP
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 */
7213a328
PP
1227 BT_LOGF("Invalid connection: downstream component is a source: "
1228 "conn-arg=\"%s\"", cfg_conn->arg->str);
0fbb9a9f 1229 abort();
9009cc24 1230 }
290725f7 1231
9009cc24
PP
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);
7213a328
PP
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));
9009cc24
PP
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! */
a256a42d
PP
1259 status = bt_graph_connect_ports(ctx->graph,
1260 upstream_port, downstream_port, NULL);
9009cc24 1261 bt_put(downstream_port);
a256a42d
PP
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:
7213a328
PP
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);
9009cc24
PP
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
7213a328
PP
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
9009cc24
PP
1319 goto end;
1320 }
1321
1322 bt_put(downstream_port);
1323 }
1324
a256a42d 1325 if (status != BT_GRAPH_STATUS_OK) {
7213a328
PP
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);
9009cc24
PP
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;
05a67631
PP
1336 }
1337
9009cc24
PP
1338 goto end;
1339
1340error:
1341 ret = -1;
1342
1343end:
9009cc24
PP
1344 return ret;
1345}
1346
1347static
1348int 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) {
7213a328
PP
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);
98ecef32
MD
1366 ret = -1;
1367 goto end;
33bceaf8
JG
1368 }
1369
9009cc24
PP
1370 upstream_comp_name = bt_component_get_name(upstream_comp);
1371 assert(upstream_comp_name);
7213a328
PP
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);
9009cc24
PP
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) {
7213a328
PP
1391 BT_LOGE("Cannot connect upstream port: "
1392 "port-addr=%p, port-name=\"%s\"",
1393 upstream_port,
1394 upstream_port_name);
9009cc24
PP
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
7213a328
PP
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);
9009cc24
PP
1411 fprintf(stderr,
1412 "Cannot create connection: upstream port `%s` does not match any connection\n",
7213a328 1413 upstream_port_name);
9009cc24
PP
1414
1415error:
1416 ret = -1;
1417
1418end:
1419 bt_put(upstream_comp);
1420 return ret;
1421}
1422
1423static
1424void 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
e12720c0
PP
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) : "",
7213a328 1433 port, bt_port_get_name(port));
36712f1d
PP
1434
1435 if (!ctx->connect_ports) {
1436 goto end;
1437 }
1438
e12720c0
PP
1439 if (!comp) {
1440 BT_LOGW_STR("Port has no component.");
56a1cced
JG
1441 goto end;
1442 }
7c7c0433 1443
e12720c0
PP
1444 if (bt_port_is_connected(port)) {
1445 BT_LOGW_STR("Port is already connected.");
7c7c0433
JG
1446 goto end;
1447 }
1448
9009cc24 1449 if (!bt_port_is_output(port)) {
7213a328 1450 BT_LOGI_STR("Skipping input port.");
61ddbc8a
JG
1451 goto end;
1452 }
1453
9009cc24 1454 if (cmd_run_ctx_connect_upstream_port(ctx, port)) {
7213a328 1455 BT_LOGF_STR("Cannot connect upstream port.");
9009cc24
PP
1456 fprintf(stderr, "Added port could not be connected: aborting\n");
1457 abort();
1458 }
1459
1460end:
1461 bt_put(comp);
1462 return;
1463}
1464
1465static
1466void graph_port_removed_listener(struct bt_component *component,
1467 struct bt_port *port, void *data)
1468{
7213a328
PP
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));
9009cc24
PP
1473}
1474
1475static
1476void graph_ports_connected_listener(struct bt_port *upstream_port,
1477 struct bt_port *downstream_port, void *data)
1478{
e12720c0
PP
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);
7213a328 1484 BT_LOGI("Graph's component ports connected: "
e12720c0 1485 "upstream-comp-addr=%p, upstream-comp-name=\"%s\", "
7213a328 1486 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
e12720c0 1487 "downstream-comp-addr=%p, downstream-comp-name=\"%s\", "
7213a328 1488 "downstream-port-addr=%p, downstream-port-name=\"%s\"",
e12720c0 1489 upstream_comp, bt_component_get_name(upstream_comp),
7213a328 1490 upstream_port, bt_port_get_name(upstream_port),
e12720c0 1491 downstream_comp, bt_component_get_name(downstream_comp),
7213a328 1492 downstream_port, bt_port_get_name(downstream_port));
e12720c0
PP
1493 bt_put(upstream_comp);
1494 bt_put(downstream_comp);
9009cc24
PP
1495}
1496
1497static
1498void 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{
7213a328
PP
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));
9009cc24
PP
1509}
1510
1511static
1512void 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);
5401f780 1524 the_graph = NULL;
9009cc24
PP
1525 ctx->cfg = NULL;
1526}
1527
1528static
1529int 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
5401f780 1546 the_graph = ctx->graph;
9009cc24
PP
1547 ret = bt_graph_add_port_added_listener(ctx->graph,
1548 graph_port_added_listener, ctx);
0d107cdd
PP
1549 if (ret < 0) {
1550 BT_LOGE_STR("Cannot add \"port added\" listener to graph.");
9009cc24
PP
1551 goto error;
1552 }
1553
1554 ret = bt_graph_add_port_removed_listener(ctx->graph,
1555 graph_port_removed_listener, ctx);
0d107cdd
PP
1556 if (ret < 0) {
1557 BT_LOGE_STR("Cannot add \"port removed\" listener to graph.");
9009cc24
PP
1558 goto error;
1559 }
1560
1561 ret = bt_graph_add_ports_connected_listener(ctx->graph,
1562 graph_ports_connected_listener, ctx);
0d107cdd
PP
1563 if (ret < 0) {
1564 BT_LOGE_STR("Cannot add \"ports connected\" listener to graph.");
9009cc24
PP
1565 goto error;
1566 }
1567
1568 ret = bt_graph_add_ports_disconnected_listener(ctx->graph,
1569 graph_ports_disconnected_listener, ctx);
0d107cdd
PP
1570 if (ret < 0) {
1571 BT_LOGE_STR("Cannot add \"ports disconnected\" listener to graph.");
9009cc24
PP
1572 goto error;
1573 }
1574
1575 goto end;
1576
1577error:
1578 cmd_run_ctx_destroy(ctx);
1579 ret = -1;
1580
1581end:
1582 return ret;
1583}
1584
1585static
1586int 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) {
7213a328
PP
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);
9009cc24
PP
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
36712f1d
PP
1619 ret = bt_graph_add_component(ctx->graph, comp_cls,
1620 cfg_comp->instance_name->str, cfg_comp->params, &comp);
1621 if (ret) {
7213a328 1622 BT_LOGE("Cannot create component: plugin-name=\"%s\", "
32e87ceb 1623 "comp-cls-name=\"%s\", comp-cls-type=%d, "
7213a328
PP
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);
9009cc24
PP
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
7213a328
PP
1636 BT_LOGI("Created and inserted component: comp-addr=%p, comp-name=\"%s\"",
1637 comp, cfg_comp->instance_name->str);
9009cc24
PP
1638 quark = g_quark_from_string(cfg_comp->instance_name->str);
1639 assert(quark > 0);
1640 g_hash_table_insert(ctx->components,
71c7c95f 1641 GUINT_TO_POINTER(quark), comp);
9009cc24
PP
1642 comp = NULL;
1643 BT_PUT(comp_cls);
1644 }
1645
1646 goto end;
1647
1648error:
1649 ret = -1;
1650
1651end:
1652 bt_put(comp);
1653 bt_put(comp_cls);
1654 return ret;
1655}
56a1cced 1656
9009cc24
PP
1657static
1658int 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) {
7c7c0433 1673 ret = -1;
2e339de1
JG
1674 goto end;
1675 }
1676
9009cc24
PP
1677 ret = cmd_run_ctx_create_components_from_config_components(
1678 ctx, ctx->cfg->cmd_data.run.filters);
6c2f3ee5 1679 if (ret) {
290725f7 1680 ret = -1;
fec2a9f2
JG
1681 goto end;
1682 }
78586d8a 1683
9009cc24
PP
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
1691end:
1692 return ret;
1693}
1694
1695static
1696int 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
1719end:
1720 return ret;
1721}
1722
1723static
1724int 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
1749end:
1750 return ret;
1751}
1752
fd948396
PP
1753static inline
1754const 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";
fd948396
PP
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
9009cc24
PP
1776static
1777int cmd_run(struct bt_config *cfg)
1778{
1779 int ret = 0;
1780 struct cmd_run_ctx ctx = { 0 };
1781
9009cc24
PP
1782 /* Initialize the command's context and the graph object */
1783 if (cmd_run_ctx_init(&ctx, cfg)) {
7213a328 1784 BT_LOGE_STR("Cannot initialize the command's context.");
9009cc24
PP
1785 fprintf(stderr, "Cannot initialize the command's context\n");
1786 goto error;
1787 }
1788
cc308374
PP
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
9009cc24
PP
1796 /* Create the requested component instances */
1797 if (cmd_run_ctx_create_components(&ctx)) {
7213a328 1798 BT_LOGE_STR("Cannot create components.");
9009cc24
PP
1799 fprintf(stderr, "Cannot create components\n");
1800 goto error;
1801 }
1802
cc308374
PP
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
9009cc24
PP
1810 /* Connect the initially visible component ports */
1811 if (cmd_run_ctx_connect_ports(&ctx)) {
7213a328 1812 BT_LOGE_STR("Cannot connect initial component ports.");
9009cc24
PP
1813 fprintf(stderr, "Cannot connect initial component ports\n");
1814 goto error;
1815 }
1816
5401f780 1817 if (canceled) {
cc308374
PP
1818 BT_LOGI_STR("Canceled by user before running the graph.");
1819 goto error;
5401f780
PP
1820 }
1821
7213a328
PP
1822 BT_LOGI_STR("Running the graph.");
1823
9009cc24 1824 /* Run the graph */
fec2a9f2 1825 while (true) {
9009cc24 1826 enum bt_graph_status graph_status = bt_graph_run(ctx.graph);
61ddbc8a 1827
5669a3e7
PP
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());
fd948396
PP
1835 BT_LOGV("bt_graph_run() returned: status=%s",
1836 bt_graph_status_str(graph_status));
1837
61ddbc8a 1838 switch (graph_status) {
9009cc24
PP
1839 case BT_GRAPH_STATUS_OK:
1840 break;
5401f780 1841 case BT_GRAPH_STATUS_CANCELED:
fd948396 1842 BT_LOGI_STR("Graph was canceled by user.");
5401f780 1843 goto error;
61ddbc8a 1844 case BT_GRAPH_STATUS_AGAIN:
5401f780 1845 if (bt_graph_is_canceled(ctx.graph)) {
fd948396 1846 BT_LOGI_STR("Graph was canceled by user.");
5401f780
PP
1847 goto error;
1848 }
1849
9009cc24 1850 if (cfg->cmd_data.run.retry_duration_us > 0) {
7213a328
PP
1851 BT_LOGV("Got BT_GRAPH_STATUS_AGAIN: sleeping: "
1852 "time-us=%" PRIu64,
1853 cfg->cmd_data.run.retry_duration_us);
1854
9009cc24 1855 if (usleep(cfg->cmd_data.run.retry_duration_us)) {
cfa4637b
PP
1856 if (bt_graph_is_canceled(ctx.graph)) {
1857 BT_LOGI_STR("Graph was canceled by user.");
1858 goto error;
1859 }
9009cc24
PP
1860 }
1861 }
78586d8a 1862 break;
fec2a9f2
JG
1863 case BT_COMPONENT_STATUS_END:
1864 goto end;
1865 default:
7213a328
PP
1866 BT_LOGE_STR("Graph failed to complete successfully");
1867 fprintf(stderr, "Graph failed to complete successfully\n");
9009cc24 1868 goto error;
78586d8a 1869 }
fec2a9f2 1870 }
290725f7 1871
9009cc24
PP
1872 goto end;
1873
1874error:
1875 if (ret == 0) {
1876 ret = -1;
1877 }
1878
11e1d048 1879end:
9009cc24 1880 cmd_run_ctx_destroy(&ctx);
290725f7
PP
1881 return ret;
1882}
1883
9009cc24
PP
1884static
1885void warn_command_name_and_directory_clash(struct bt_config *cfg)
290725f7 1886{
9009cc24
PP
1887 const char *env_clash;
1888
290725f7
PP
1889 if (!cfg->command_name) {
1890 return;
1891 }
1892
9009cc24
PP
1893 env_clash = getenv(ENV_BABELTRACE_WARN_COMMAND_NAME_DIRECTORY_CLASH);
1894 if (env_clash && strcmp(env_clash, "0") == 0) {
1895 return;
1896 }
1897
290725f7
PP
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
7213a328
PP
1910static
1911void init_log_level(void)
1912{
c6d4d1ae 1913 bt_cli_log_level = bt_log_get_level_from_env(ENV_BABELTRACE_CLI_LOG_LEVEL);
7213a328
PP
1914}
1915
c6d4d1ae
PP
1916static
1917void 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 */
3efa3052
PP
1941 switch (cfg->log_level) {
1942 case 'N':
1943 bt_logging_set_global_level(BT_LOGGING_LEVEL_NONE);
1944 break;
1945 case 'V':
1946 bt_logging_set_global_level(BT_LOGGING_LEVEL_VERBOSE);
1947 break;
1948 case 'D':
1949 bt_logging_set_global_level(BT_LOGGING_LEVEL_DEBUG);
1950 break;
1951 case 'I':
1952 bt_logging_set_global_level(BT_LOGGING_LEVEL_INFO);
1953 break;
1954 case 'W':
1955 bt_logging_set_global_level(BT_LOGGING_LEVEL_WARN);
1956 break;
1957 case 'E':
1958 bt_logging_set_global_level(BT_LOGGING_LEVEL_ERROR);
1959 break;
1960 case 'F':
1961 bt_logging_set_global_level(BT_LOGGING_LEVEL_FATAL);
1962 break;
1963 default:
1964 abort();
1965 }
c6d4d1ae
PP
1966 }
1967 }
1968
1969 if (!getenv(ENV_BABELTRACE_CLI_LOG_LEVEL)) {
1970 if (cfg->verbose) {
1971 bt_cli_log_level = BT_LOG_INFO;
1972 } else if (cfg->debug) {
1973 bt_cli_log_level = BT_LOG_VERBOSE;
1974 } else {
1975 /*
1976 * Set CLI's default log level if not explicitly
1977 * specified.
1978 */
3efa3052
PP
1979 switch (cfg->log_level) {
1980 case 'N':
1981 bt_cli_log_level = BT_LOG_NONE;
1982 break;
1983 case 'V':
1984 bt_cli_log_level = BT_LOG_VERBOSE;
1985 break;
1986 case 'D':
1987 bt_cli_log_level = BT_LOG_DEBUG;
1988 break;
1989 case 'I':
1990 bt_cli_log_level = BT_LOG_INFO;
1991 break;
1992 case 'W':
1993 bt_cli_log_level = BT_LOG_WARN;
1994 break;
1995 case 'E':
1996 bt_cli_log_level = BT_LOG_ERROR;
1997 break;
1998 case 'F':
1999 bt_cli_log_level = BT_LOG_FATAL;
2000 break;
2001 default:
2002 abort();
2003 }
c6d4d1ae
PP
2004 }
2005 }
2006
2007 env_var_name = log_level_env_var_names;
2008
2009 while (*env_var_name) {
2010 if (!getenv(*env_var_name)) {
2011 if (cfg->verbose) {
2012 setenv(*env_var_name, "I", 1);
2013 } else if (cfg->debug) {
2014 setenv(*env_var_name, "V", 1);
2015 } else {
3efa3052
PP
2016 char val[2] = { 0 };
2017
c6d4d1ae
PP
2018 /*
2019 * Set module's default log level if not
2020 * explicitly specified.
2021 */
3efa3052
PP
2022 val[0] = cfg->log_level;
2023 setenv(*env_var_name, val, 1);
c6d4d1ae
PP
2024 }
2025 }
2026
2027 env_var_name++;
2028 }
2029
2030 babeltrace_debug = cfg->debug;
2031 babeltrace_verbose = cfg->verbose;
2032}
2033
2034static
5401f780
PP
2035void set_sigint_handler(void)
2036{
2037 struct sigaction new_action, old_action;
2038
2039 new_action.sa_handler = sigint_handler;
2040 sigemptyset(&new_action.sa_mask);
2041 new_action.sa_flags = 0;
2042 sigaction(SIGINT, NULL, &old_action);
2043
2044 if (old_action.sa_handler != SIG_IGN) {
2045 sigaction(SIGINT, &new_action, NULL);
2046 }
2047}
2048
290725f7
PP
2049int main(int argc, const char **argv)
2050{
2051 int ret;
2052 int retcode;
2053 struct bt_config *cfg;
2054
7213a328 2055 init_log_level();
5401f780 2056 set_sigint_handler();
9009cc24
PP
2057 init_static_data();
2058 cfg = bt_config_cli_args_create_with_default(argc, argv, &retcode);
290725f7
PP
2059
2060 if (retcode < 0) {
2061 /* Quit without errors; typically usage/version */
2062 retcode = 0;
7213a328 2063 BT_LOGI_STR("Quitting without errors.");
290725f7
PP
2064 goto end;
2065 }
2066
2067 if (retcode > 0) {
7213a328 2068 BT_LOGE("Command-line error: retcode=%d", retcode);
290725f7
PP
2069 goto end;
2070 }
2071
2072 if (!cfg) {
7213a328 2073 BT_LOGE_STR("Failed to create a valid Babeltrace configuration.");
290725f7 2074 fprintf(stderr, "Failed to create Babeltrace configuration\n");
db0f160a 2075 retcode = 1;
290725f7
PP
2076 goto end;
2077 }
2078
c6d4d1ae 2079 set_auto_log_levels(cfg);
290725f7
PP
2080 print_cfg(cfg);
2081
db0f160a
PP
2082 if (cfg->command_needs_plugins) {
2083 ret = load_all_plugins(cfg->plugin_paths);
2084 if (ret) {
7213a328 2085 BT_LOGE("Failed to load plugins: ret=%d", ret);
db0f160a
PP
2086 retcode = 1;
2087 goto end;
2088 }
2089 }
2090
7213a328
PP
2091 BT_LOGI("Executing command: cmd=%d, command-name=\"%s\"",
2092 cfg->command, cfg->command_name);
2093
290725f7 2094 switch (cfg->command) {
db0f160a
PP
2095 case BT_CONFIG_COMMAND_RUN:
2096 ret = cmd_run(cfg);
290725f7
PP
2097 break;
2098 case BT_CONFIG_COMMAND_LIST_PLUGINS:
2099 ret = cmd_list_plugins(cfg);
2100 break;
22e22462
PP
2101 case BT_CONFIG_COMMAND_HELP:
2102 ret = cmd_help(cfg);
2103 break;
a67681c1
PP
2104 case BT_CONFIG_COMMAND_QUERY:
2105 ret = cmd_query(cfg);
63ce0e1d 2106 break;
db0f160a
PP
2107 case BT_CONFIG_COMMAND_PRINT_CTF_METADATA:
2108 ret = cmd_print_ctf_metadata(cfg);
2109 break;
2110 case BT_CONFIG_COMMAND_PRINT_LTTNG_LIVE_SESSIONS:
2111 ret = cmd_print_lttng_live_sessions(cfg);
2112 break;
290725f7 2113 default:
0fbb9a9f
PP
2114 BT_LOGF("Invalid/unknown command: cmd=%d", cfg->command);
2115 abort();
290725f7
PP
2116 }
2117
d26ef3e3
PP
2118 BT_LOGI("Command completed: cmd=%d, command-name=\"%s\", ret=%d",
2119 cfg->command, cfg->command_name, ret);
290725f7
PP
2120 warn_command_name_and_directory_clash(cfg);
2121 retcode = ret ? 1 : 0;
2122
2123end:
2124 BT_PUT(cfg);
9009cc24 2125 fini_static_data();
290725f7 2126 return retcode;
4c8bfb7e 2127}
This page took 0.162341 seconds and 4 git commands to generate.