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