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