lttng-live: check graph cancel state, check ctf trace pointer
[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);
a256a42d 1181 enum bt_graph_status status = BT_GRAPH_STATUS_ERROR;
9009cc24 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,
71c7c95f 1193 GUINT_TO_POINTER(downstreamp_comp_name_quark));
9009cc24 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! */
a256a42d
PP
1246 status = bt_graph_connect_ports(ctx->graph,
1247 upstream_port, downstream_port, NULL);
9009cc24 1248 bt_put(downstream_port);
a256a42d
PP
1249 switch (status) {
1250 case BT_GRAPH_STATUS_OK:
1251 break;
1252 case BT_GRAPH_STATUS_CANCELED:
1253 BT_LOGI_STR("Graph was canceled by user.");
1254 status = BT_GRAPH_STATUS_OK;
1255 break;
1256 case BT_GRAPH_STATUS_COMPONENT_REFUSES_PORT_CONNECTION:
1257 BT_LOGE("A component refused a connection to one of its ports: "
1258 "upstream-comp-addr=%p, upstream-comp-name=\"%s\", "
1259 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
1260 "downstream-comp-addr=%p, downstream-comp-name=\"%s\", "
1261 "downstream-port-addr=%p, downstream-port-name=\"%s\", "
1262 "conn-arg=\"%s\"",
1263 upstream_comp, bt_component_get_name(upstream_comp),
1264 upstream_port, bt_port_get_name(upstream_port),
1265 downstream_comp, cfg_conn->downstream_comp_name->str,
1266 downstream_port, downstream_port_name,
1267 cfg_conn->arg->str);
1268 fprintf(stderr,
1269 "A component refused a connection to one of its ports (`%s` to `%s`): %s\n",
1270 bt_port_get_name(upstream_port),
1271 downstream_port_name,
1272 cfg_conn->arg->str);
1273 break;
1274 default:
7213a328
PP
1275 BT_LOGE("Cannot create connection: graph refuses to connect ports: "
1276 "upstream-comp-addr=%p, upstream-comp-name=\"%s\", "
1277 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
1278 "downstream-comp-addr=%p, downstream-comp-name=\"%s\", "
1279 "downstream-port-addr=%p, downstream-port-name=\"%s\", "
1280 "conn-arg=\"%s\"",
1281 upstream_comp, bt_component_get_name(upstream_comp),
1282 upstream_port, bt_port_get_name(upstream_port),
1283 downstream_comp, cfg_conn->downstream_comp_name->str,
1284 downstream_port, downstream_port_name,
1285 cfg_conn->arg->str);
9009cc24
PP
1286 fprintf(stderr,
1287 "Cannot create connection: graph refuses to connect ports (`%s` to `%s`): %s\n",
1288 bt_port_get_name(upstream_port),
1289 downstream_port_name,
1290 cfg_conn->arg->str);
1291 goto error;
1292 }
1293
7213a328
PP
1294 BT_LOGI("Connected component ports: "
1295 "upstream-comp-addr=%p, upstream-comp-name=\"%s\", "
1296 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
1297 "downstream-comp-addr=%p, downstream-comp-name=\"%s\", "
1298 "downstream-port-addr=%p, downstream-port-name=\"%s\", "
1299 "conn-arg=\"%s\"",
1300 upstream_comp, bt_component_get_name(upstream_comp),
1301 upstream_port, bt_port_get_name(upstream_port),
1302 downstream_comp, cfg_conn->downstream_comp_name->str,
1303 downstream_port, downstream_port_name,
1304 cfg_conn->arg->str);
1305
9009cc24
PP
1306 goto end;
1307 }
1308
1309 bt_put(downstream_port);
1310 }
1311
a256a42d 1312 if (status != BT_GRAPH_STATUS_OK) {
7213a328
PP
1313 BT_LOGE("Cannot create connection: cannot find a matching downstream port for upstream port: "
1314 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
1315 "downstream-comp-name=\"%s\", conn-arg=\"%s\"",
1316 upstream_port, bt_port_get_name(upstream_port),
1317 cfg_conn->downstream_comp_name->str,
1318 cfg_conn->arg->str);
9009cc24
PP
1319 fprintf(stderr,
1320 "Cannot create connection: cannot find a matching downstream port for upstream port `%s`: %s\n",
1321 bt_port_get_name(upstream_port), cfg_conn->arg->str);
1322 goto error;
05a67631
PP
1323 }
1324
9009cc24
PP
1325 goto end;
1326
1327error:
1328 ret = -1;
1329
1330end:
9009cc24
PP
1331 return ret;
1332}
1333
1334static
1335int cmd_run_ctx_connect_upstream_port(struct cmd_run_ctx *ctx,
1336 struct bt_port *upstream_port)
1337{
1338 int ret = 0;
1339 const char *upstream_port_name;
1340 const char *upstream_comp_name;
1341 struct bt_component *upstream_comp = NULL;
1342 size_t i;
1343
1344 assert(ctx);
1345 assert(upstream_port);
1346 upstream_port_name = bt_port_get_name(upstream_port);
1347 assert(upstream_port_name);
1348 upstream_comp = bt_port_get_component(upstream_port);
1349 if (!upstream_comp) {
7213a328
PP
1350 BT_LOGW("Upstream port to connect is not part of a component: "
1351 "port-addr=%p, port-name=\"%s\"",
1352 upstream_port, upstream_port_name);
98ecef32
MD
1353 ret = -1;
1354 goto end;
33bceaf8
JG
1355 }
1356
9009cc24
PP
1357 upstream_comp_name = bt_component_get_name(upstream_comp);
1358 assert(upstream_comp_name);
7213a328
PP
1359 BT_LOGI("Connecting upstream port: comp-addr=%p, comp-name=\"%s\", "
1360 "port-addr=%p, port-name=\"%s\"",
1361 upstream_comp, upstream_comp_name,
1362 upstream_port, upstream_port_name);
9009cc24
PP
1363
1364 for (i = 0; i < ctx->cfg->cmd_data.run.connections->len; i++) {
1365 struct bt_config_connection *cfg_conn =
1366 g_ptr_array_index(
1367 ctx->cfg->cmd_data.run.connections, i);
1368
1369 if (strcmp(cfg_conn->upstream_comp_name->str,
1370 upstream_comp_name) == 0) {
1371 if (bt_common_star_glob_match(
1372 cfg_conn->upstream_port_glob->str,
1373 -1ULL, upstream_port_name, -1ULL)) {
1374 ret = cmd_run_ctx_connect_upstream_port_to_downstream_component(
1375 ctx, upstream_comp, upstream_port,
1376 cfg_conn);
1377 if (ret) {
7213a328
PP
1378 BT_LOGE("Cannot connect upstream port: "
1379 "port-addr=%p, port-name=\"%s\"",
1380 upstream_port,
1381 upstream_port_name);
9009cc24
PP
1382 fprintf(stderr,
1383 "Cannot connect port `%s` of component `%s` to a downstream port: %s\n",
1384 upstream_port_name,
1385 upstream_comp_name,
1386 cfg_conn->arg->str);
1387 goto error;
1388 }
1389
1390 goto end;
1391 }
1392 }
1393 }
1394
7213a328
PP
1395 BT_LOGE("Cannot connect upstream port: port does not match any connection argument: "
1396 "port-addr=%p, port-name=\"%s\"", upstream_port,
1397 upstream_port_name);
9009cc24
PP
1398 fprintf(stderr,
1399 "Cannot create connection: upstream port `%s` does not match any connection\n",
7213a328 1400 upstream_port_name);
9009cc24
PP
1401
1402error:
1403 ret = -1;
1404
1405end:
1406 bt_put(upstream_comp);
1407 return ret;
1408}
1409
1410static
1411void graph_port_added_listener(struct bt_port *port, void *data)
1412{
1413 struct bt_component *comp = NULL;
1414 struct cmd_run_ctx *ctx = data;
1415
e12720c0
PP
1416 comp = bt_port_get_component(port);
1417 BT_LOGI("Port added to a graph's component: comp-addr=%p, "
1418 "comp-name=\"%s\", port-addr=%p, port-name=\"%s\"",
1419 comp, comp ? bt_component_get_name(comp) : "",
7213a328 1420 port, bt_port_get_name(port));
36712f1d
PP
1421
1422 if (!ctx->connect_ports) {
1423 goto end;
1424 }
1425
e12720c0
PP
1426 if (!comp) {
1427 BT_LOGW_STR("Port has no component.");
56a1cced
JG
1428 goto end;
1429 }
7c7c0433 1430
e12720c0
PP
1431 if (bt_port_is_connected(port)) {
1432 BT_LOGW_STR("Port is already connected.");
7c7c0433
JG
1433 goto end;
1434 }
1435
9009cc24 1436 if (!bt_port_is_output(port)) {
7213a328 1437 BT_LOGI_STR("Skipping input port.");
61ddbc8a
JG
1438 goto end;
1439 }
1440
9009cc24 1441 if (cmd_run_ctx_connect_upstream_port(ctx, port)) {
7213a328 1442 BT_LOGF_STR("Cannot connect upstream port.");
9009cc24
PP
1443 fprintf(stderr, "Added port could not be connected: aborting\n");
1444 abort();
1445 }
1446
1447end:
1448 bt_put(comp);
1449 return;
1450}
1451
1452static
1453void graph_port_removed_listener(struct bt_component *component,
1454 struct bt_port *port, void *data)
1455{
7213a328
PP
1456 BT_LOGI("Port removed from a graph's component: comp-addr=%p, "
1457 "comp-name=\"%s\", port-addr=%p, port-name=\"%s\"",
1458 component, bt_component_get_name(component),
1459 port, bt_port_get_name(port));
9009cc24
PP
1460}
1461
1462static
1463void graph_ports_connected_listener(struct bt_port *upstream_port,
1464 struct bt_port *downstream_port, void *data)
1465{
e12720c0
PP
1466 struct bt_component *upstream_comp = bt_port_get_component(upstream_port);
1467 struct bt_component *downstream_comp = bt_port_get_component(downstream_port);
1468
1469 assert(upstream_comp);
1470 assert(downstream_comp);
7213a328 1471 BT_LOGI("Graph's component ports connected: "
e12720c0 1472 "upstream-comp-addr=%p, upstream-comp-name=\"%s\", "
7213a328 1473 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
e12720c0 1474 "downstream-comp-addr=%p, downstream-comp-name=\"%s\", "
7213a328 1475 "downstream-port-addr=%p, downstream-port-name=\"%s\"",
e12720c0 1476 upstream_comp, bt_component_get_name(upstream_comp),
7213a328 1477 upstream_port, bt_port_get_name(upstream_port),
e12720c0 1478 downstream_comp, bt_component_get_name(downstream_comp),
7213a328 1479 downstream_port, bt_port_get_name(downstream_port));
e12720c0
PP
1480 bt_put(upstream_comp);
1481 bt_put(downstream_comp);
9009cc24
PP
1482}
1483
1484static
1485void graph_ports_disconnected_listener(
1486 struct bt_component *upstream_component,
1487 struct bt_component *downstream_component,
1488 struct bt_port *upstream_port, struct bt_port *downstream_port,
1489 void *data)
1490{
7213a328
PP
1491 BT_LOGI("Graph's component ports disconnected: "
1492 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
1493 "downstream-port-addr=%p, downstream-port-name=\"%s\"",
1494 upstream_port, bt_port_get_name(upstream_port),
1495 downstream_port, bt_port_get_name(downstream_port));
9009cc24
PP
1496}
1497
1498static
1499void cmd_run_ctx_destroy(struct cmd_run_ctx *ctx)
1500{
1501 if (!ctx) {
1502 return;
1503 }
1504
1505 if (ctx->components) {
1506 g_hash_table_destroy(ctx->components);
1507 ctx->components = NULL;
1508 }
1509
1510 BT_PUT(ctx->graph);
5401f780 1511 the_graph = NULL;
9009cc24
PP
1512 ctx->cfg = NULL;
1513}
1514
1515static
1516int cmd_run_ctx_init(struct cmd_run_ctx *ctx, struct bt_config *cfg)
1517{
1518 int ret = 0;
1519
1520 ctx->cfg = cfg;
1521 ctx->connect_ports = false;
1522 ctx->components = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1523 NULL, bt_put);
1524 if (!ctx->components) {
1525 goto error;
1526 }
1527
1528 ctx->graph = bt_graph_create();
1529 if (!ctx->graph) {
1530 goto error;
1531 }
1532
5401f780 1533 the_graph = ctx->graph;
9009cc24
PP
1534 ret = bt_graph_add_port_added_listener(ctx->graph,
1535 graph_port_added_listener, ctx);
0d107cdd
PP
1536 if (ret < 0) {
1537 BT_LOGE_STR("Cannot add \"port added\" listener to graph.");
9009cc24
PP
1538 goto error;
1539 }
1540
1541 ret = bt_graph_add_port_removed_listener(ctx->graph,
1542 graph_port_removed_listener, ctx);
0d107cdd
PP
1543 if (ret < 0) {
1544 BT_LOGE_STR("Cannot add \"port removed\" listener to graph.");
9009cc24
PP
1545 goto error;
1546 }
1547
1548 ret = bt_graph_add_ports_connected_listener(ctx->graph,
1549 graph_ports_connected_listener, ctx);
0d107cdd
PP
1550 if (ret < 0) {
1551 BT_LOGE_STR("Cannot add \"ports connected\" listener to graph.");
9009cc24
PP
1552 goto error;
1553 }
1554
1555 ret = bt_graph_add_ports_disconnected_listener(ctx->graph,
1556 graph_ports_disconnected_listener, ctx);
0d107cdd
PP
1557 if (ret < 0) {
1558 BT_LOGE_STR("Cannot add \"ports disconnected\" listener to graph.");
9009cc24
PP
1559 goto error;
1560 }
1561
1562 goto end;
1563
1564error:
1565 cmd_run_ctx_destroy(ctx);
1566 ret = -1;
1567
1568end:
1569 return ret;
1570}
1571
1572static
1573int cmd_run_ctx_create_components_from_config_components(
1574 struct cmd_run_ctx *ctx, GPtrArray *cfg_components)
1575{
1576 size_t i;
1577 struct bt_component_class *comp_cls = NULL;
1578 struct bt_component *comp = NULL;
1579 int ret = 0;
1580
1581 for (i = 0; i < cfg_components->len; i++) {
1582 struct bt_config_component *cfg_comp =
1583 g_ptr_array_index(cfg_components, i);
1584 GQuark quark;
1585
1586 comp_cls = find_component_class(cfg_comp->plugin_name->str,
1587 cfg_comp->comp_cls_name->str, cfg_comp->type);
1588 if (!comp_cls) {
7213a328
PP
1589 BT_LOGE("Cannot find component class: plugin-name=\"%s\", "
1590 "comp-cls-name=\"%s\", comp-cls-type=%d",
1591 cfg_comp->plugin_name->str,
1592 cfg_comp->comp_cls_name->str,
1593 cfg_comp->type);
9009cc24
PP
1594 fprintf(stderr, "%s%sCannot find component class %s",
1595 bt_common_color_bold(),
1596 bt_common_color_fg_red(),
1597 bt_common_color_reset());
1598 print_plugin_comp_cls_opt(stderr,
1599 cfg_comp->plugin_name->str,
1600 cfg_comp->comp_cls_name->str,
1601 cfg_comp->type);
1602 fprintf(stderr, "\n");
1603 goto error;
1604 }
1605
36712f1d
PP
1606 ret = bt_graph_add_component(ctx->graph, comp_cls,
1607 cfg_comp->instance_name->str, cfg_comp->params, &comp);
1608 if (ret) {
7213a328 1609 BT_LOGE("Cannot create component: plugin-name=\"%s\", "
32e87ceb 1610 "comp-cls-name=\"%s\", comp-cls-type=%d, "
7213a328
PP
1611 "comp-name=\"%s\"",
1612 cfg_comp->plugin_name->str,
1613 cfg_comp->comp_cls_name->str,
1614 cfg_comp->type, cfg_comp->instance_name->str);
9009cc24
PP
1615 fprintf(stderr, "%s%sCannot create component `%s`%s\n",
1616 bt_common_color_bold(),
1617 bt_common_color_fg_red(),
1618 cfg_comp->instance_name->str,
1619 bt_common_color_reset());
1620 goto error;
1621 }
1622
7213a328
PP
1623 BT_LOGI("Created and inserted component: comp-addr=%p, comp-name=\"%s\"",
1624 comp, cfg_comp->instance_name->str);
9009cc24
PP
1625 quark = g_quark_from_string(cfg_comp->instance_name->str);
1626 assert(quark > 0);
1627 g_hash_table_insert(ctx->components,
71c7c95f 1628 GUINT_TO_POINTER(quark), comp);
9009cc24
PP
1629 comp = NULL;
1630 BT_PUT(comp_cls);
1631 }
1632
1633 goto end;
1634
1635error:
1636 ret = -1;
1637
1638end:
1639 bt_put(comp);
1640 bt_put(comp_cls);
1641 return ret;
1642}
56a1cced 1643
9009cc24
PP
1644static
1645int cmd_run_ctx_create_components(struct cmd_run_ctx *ctx)
1646{
1647 int ret = 0;
1648
1649 /*
1650 * Make sure that, during this phase, our graph's "port added"
1651 * listener does not connect ports while we are creating the
1652 * components because we have a special, initial phase for
1653 * this.
1654 */
1655 ctx->connect_ports = false;
1656
1657 ret = cmd_run_ctx_create_components_from_config_components(
1658 ctx, ctx->cfg->cmd_data.run.sources);
1659 if (ret) {
7c7c0433 1660 ret = -1;
2e339de1
JG
1661 goto end;
1662 }
1663
9009cc24
PP
1664 ret = cmd_run_ctx_create_components_from_config_components(
1665 ctx, ctx->cfg->cmd_data.run.filters);
6c2f3ee5 1666 if (ret) {
290725f7 1667 ret = -1;
fec2a9f2
JG
1668 goto end;
1669 }
78586d8a 1670
9009cc24
PP
1671 ret = cmd_run_ctx_create_components_from_config_components(
1672 ctx, ctx->cfg->cmd_data.run.sinks);
1673 if (ret) {
1674 ret = -1;
1675 goto end;
1676 }
1677
1678end:
1679 return ret;
1680}
1681
1682static
1683int cmd_run_ctx_connect_comp_ports(struct cmd_run_ctx *ctx,
1684 struct bt_component *comp,
1685 int64_t (*port_count_fn)(struct bt_component *),
1686 struct bt_port *(*port_by_index_fn)(struct bt_component *, uint64_t))
1687{
1688 int ret = 0;
1689 int64_t count;
1690 uint64_t i;
1691
1692 count = port_count_fn(comp);
1693 assert(count >= 0);
1694
1695 for (i = 0; i < count; i++) {
1696 struct bt_port *upstream_port = port_by_index_fn(comp, i);
1697
1698 assert(upstream_port);
1699 ret = cmd_run_ctx_connect_upstream_port(ctx, upstream_port);
1700 bt_put(upstream_port);
1701 if (ret) {
1702 goto end;
1703 }
1704 }
1705
1706end:
1707 return ret;
1708}
1709
1710static
1711int cmd_run_ctx_connect_ports(struct cmd_run_ctx *ctx)
1712{
1713 int ret = 0;
1714 GHashTableIter iter;
1715 gpointer g_name_quark, g_comp;
1716
1717 ctx->connect_ports = true;
1718 g_hash_table_iter_init(&iter, ctx->components);
1719
1720 while (g_hash_table_iter_next(&iter, &g_name_quark, &g_comp)) {
1721 if (bt_component_is_source(g_comp)) {
1722 ret = cmd_run_ctx_connect_comp_ports(ctx,
1723 g_comp, bt_component_source_get_output_port_count,
1724 bt_component_source_get_output_port_by_index);
1725 } else if (bt_component_is_filter(g_comp)) {
1726 ret = cmd_run_ctx_connect_comp_ports(ctx,
1727 g_comp, bt_component_filter_get_output_port_count,
1728 bt_component_filter_get_output_port_by_index);
1729 }
1730
1731 if (ret) {
1732 goto end;
1733 }
1734 }
1735
1736end:
1737 return ret;
1738}
1739
fd948396
PP
1740static inline
1741const char *bt_graph_status_str(enum bt_graph_status status)
1742{
1743 switch (status) {
1744 case BT_GRAPH_STATUS_CANCELED:
1745 return "BT_GRAPH_STATUS_CANCELED";
1746 case BT_GRAPH_STATUS_AGAIN:
1747 return "BT_GRAPH_STATUS_AGAIN";
1748 case BT_GRAPH_STATUS_END:
1749 return "BT_GRAPH_STATUS_END";
1750 case BT_GRAPH_STATUS_OK:
1751 return "BT_GRAPH_STATUS_OK";
fd948396
PP
1752 case BT_GRAPH_STATUS_INVALID:
1753 return "BT_GRAPH_STATUS_INVALID";
1754 case BT_GRAPH_STATUS_NO_SINK:
1755 return "BT_GRAPH_STATUS_NO_SINK";
1756 case BT_GRAPH_STATUS_ERROR:
1757 return "BT_GRAPH_STATUS_ERROR";
1758 default:
1759 return "(unknown)";
1760 }
1761}
1762
9009cc24
PP
1763static
1764int cmd_run(struct bt_config *cfg)
1765{
1766 int ret = 0;
1767 struct cmd_run_ctx ctx = { 0 };
1768
9009cc24
PP
1769 /* Initialize the command's context and the graph object */
1770 if (cmd_run_ctx_init(&ctx, cfg)) {
7213a328 1771 BT_LOGE_STR("Cannot initialize the command's context.");
9009cc24
PP
1772 fprintf(stderr, "Cannot initialize the command's context\n");
1773 goto error;
1774 }
1775
cc308374
PP
1776 if (canceled) {
1777 BT_LOGI_STR("Canceled by user before creating components.");
1778 goto error;
1779 }
1780
1781 BT_LOGI_STR("Creating components.");
1782
9009cc24
PP
1783 /* Create the requested component instances */
1784 if (cmd_run_ctx_create_components(&ctx)) {
7213a328 1785 BT_LOGE_STR("Cannot create components.");
9009cc24
PP
1786 fprintf(stderr, "Cannot create components\n");
1787 goto error;
1788 }
1789
cc308374
PP
1790 if (canceled) {
1791 BT_LOGI_STR("Canceled by user before connecting components.");
1792 goto error;
1793 }
1794
1795 BT_LOGI_STR("Connecting components.");
1796
9009cc24
PP
1797 /* Connect the initially visible component ports */
1798 if (cmd_run_ctx_connect_ports(&ctx)) {
7213a328 1799 BT_LOGE_STR("Cannot connect initial component ports.");
9009cc24
PP
1800 fprintf(stderr, "Cannot connect initial component ports\n");
1801 goto error;
1802 }
1803
5401f780 1804 if (canceled) {
cc308374
PP
1805 BT_LOGI_STR("Canceled by user before running the graph.");
1806 goto error;
5401f780
PP
1807 }
1808
7213a328
PP
1809 BT_LOGI_STR("Running the graph.");
1810
9009cc24 1811 /* Run the graph */
fec2a9f2 1812 while (true) {
9009cc24 1813 enum bt_graph_status graph_status = bt_graph_run(ctx.graph);
61ddbc8a 1814
5669a3e7
PP
1815 /*
1816 * Reset console in case something messed with console
1817 * codes during the graph's execution.
1818 */
1819 printf("%s", bt_common_color_reset());
1820 fflush(stdout);
1821 fprintf(stderr, "%s", bt_common_color_reset());
fd948396
PP
1822 BT_LOGV("bt_graph_run() returned: status=%s",
1823 bt_graph_status_str(graph_status));
1824
61ddbc8a 1825 switch (graph_status) {
9009cc24
PP
1826 case BT_GRAPH_STATUS_OK:
1827 break;
5401f780 1828 case BT_GRAPH_STATUS_CANCELED:
fd948396 1829 BT_LOGI_STR("Graph was canceled by user.");
5401f780 1830 goto error;
61ddbc8a 1831 case BT_GRAPH_STATUS_AGAIN:
5401f780 1832 if (bt_graph_is_canceled(ctx.graph)) {
fd948396 1833 BT_LOGI_STR("Graph was canceled by user.");
5401f780
PP
1834 goto error;
1835 }
1836
9009cc24 1837 if (cfg->cmd_data.run.retry_duration_us > 0) {
7213a328
PP
1838 BT_LOGV("Got BT_GRAPH_STATUS_AGAIN: sleeping: "
1839 "time-us=%" PRIu64,
1840 cfg->cmd_data.run.retry_duration_us);
1841
9009cc24 1842 if (usleep(cfg->cmd_data.run.retry_duration_us)) {
cfa4637b
PP
1843 if (bt_graph_is_canceled(ctx.graph)) {
1844 BT_LOGI_STR("Graph was canceled by user.");
1845 goto error;
1846 }
9009cc24
PP
1847 }
1848 }
78586d8a 1849 break;
fec2a9f2
JG
1850 case BT_COMPONENT_STATUS_END:
1851 goto end;
1852 default:
7213a328
PP
1853 BT_LOGE_STR("Graph failed to complete successfully");
1854 fprintf(stderr, "Graph failed to complete successfully\n");
9009cc24 1855 goto error;
78586d8a 1856 }
fec2a9f2 1857 }
290725f7 1858
9009cc24
PP
1859 goto end;
1860
1861error:
1862 if (ret == 0) {
1863 ret = -1;
1864 }
1865
11e1d048 1866end:
9009cc24 1867 cmd_run_ctx_destroy(&ctx);
290725f7
PP
1868 return ret;
1869}
1870
9009cc24
PP
1871static
1872void warn_command_name_and_directory_clash(struct bt_config *cfg)
290725f7 1873{
9009cc24
PP
1874 const char *env_clash;
1875
290725f7
PP
1876 if (!cfg->command_name) {
1877 return;
1878 }
1879
9009cc24
PP
1880 env_clash = getenv(ENV_BABELTRACE_WARN_COMMAND_NAME_DIRECTORY_CLASH);
1881 if (env_clash && strcmp(env_clash, "0") == 0) {
1882 return;
1883 }
1884
290725f7
PP
1885 if (g_file_test(cfg->command_name,
1886 G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
1887 fprintf(stderr, "\nNOTE: The `%s` command was executed. If you meant to convert a\n",
1888 cfg->command_name);
1889 fprintf(stderr, "trace located in the local `%s` directory, please use:\n",
1890 cfg->command_name);
1891 fprintf(stderr, "\n");
1892 fprintf(stderr, " babeltrace convert %s [OPTIONS]\n",
1893 cfg->command_name);
1894 }
1895}
1896
7213a328
PP
1897static
1898void init_log_level(void)
1899{
373c938b 1900 bt_cli_log_level = bt_log_get_level_from_env("BABELTRACE_CLI_LOG_LEVEL");
7213a328
PP
1901}
1902
5401f780
PP
1903void set_sigint_handler(void)
1904{
1905 struct sigaction new_action, old_action;
1906
1907 new_action.sa_handler = sigint_handler;
1908 sigemptyset(&new_action.sa_mask);
1909 new_action.sa_flags = 0;
1910 sigaction(SIGINT, NULL, &old_action);
1911
1912 if (old_action.sa_handler != SIG_IGN) {
1913 sigaction(SIGINT, &new_action, NULL);
1914 }
1915}
1916
290725f7
PP
1917int main(int argc, const char **argv)
1918{
1919 int ret;
1920 int retcode;
1921 struct bt_config *cfg;
1922
7213a328 1923 init_log_level();
5401f780 1924 set_sigint_handler();
9009cc24
PP
1925 init_static_data();
1926 cfg = bt_config_cli_args_create_with_default(argc, argv, &retcode);
290725f7
PP
1927
1928 if (retcode < 0) {
1929 /* Quit without errors; typically usage/version */
1930 retcode = 0;
7213a328 1931 BT_LOGI_STR("Quitting without errors.");
290725f7
PP
1932 goto end;
1933 }
1934
1935 if (retcode > 0) {
7213a328 1936 BT_LOGE("Command-line error: retcode=%d", retcode);
290725f7
PP
1937 goto end;
1938 }
1939
1940 if (!cfg) {
7213a328 1941 BT_LOGE_STR("Failed to create a valid Babeltrace configuration.");
290725f7 1942 fprintf(stderr, "Failed to create Babeltrace configuration\n");
db0f160a 1943 retcode = 1;
290725f7
PP
1944 goto end;
1945 }
1946
7213a328
PP
1947 if (cfg->verbose) {
1948 bt_cli_log_level = BT_LOGGING_LEVEL_VERBOSE;
1949 bt_logging_set_global_level(BT_LOGGING_LEVEL_VERBOSE);
1950 // TODO: for backward compat., set the log level
1951 // environment variables of the known plugins
1952 // to VERBOSE
1953 } else if (cfg->debug) {
1954 bt_cli_log_level = BT_LOGGING_LEVEL_DEBUG;
1955 bt_logging_set_global_level(BT_LOGGING_LEVEL_DEBUG);
1956 // TODO: for backward compat., set the log level
1957 // environment variables of the known plugins
1958 // to DEBUG
1959 }
1960
290725f7
PP
1961 babeltrace_debug = cfg->debug;
1962 babeltrace_verbose = cfg->verbose;
1963 print_cfg(cfg);
1964
db0f160a
PP
1965 if (cfg->command_needs_plugins) {
1966 ret = load_all_plugins(cfg->plugin_paths);
1967 if (ret) {
7213a328 1968 BT_LOGE("Failed to load plugins: ret=%d", ret);
db0f160a
PP
1969 retcode = 1;
1970 goto end;
1971 }
1972 }
1973
7213a328
PP
1974 BT_LOGI("Executing command: cmd=%d, command-name=\"%s\"",
1975 cfg->command, cfg->command_name);
1976
290725f7 1977 switch (cfg->command) {
db0f160a
PP
1978 case BT_CONFIG_COMMAND_RUN:
1979 ret = cmd_run(cfg);
290725f7
PP
1980 break;
1981 case BT_CONFIG_COMMAND_LIST_PLUGINS:
1982 ret = cmd_list_plugins(cfg);
1983 break;
22e22462
PP
1984 case BT_CONFIG_COMMAND_HELP:
1985 ret = cmd_help(cfg);
1986 break;
a67681c1
PP
1987 case BT_CONFIG_COMMAND_QUERY:
1988 ret = cmd_query(cfg);
63ce0e1d 1989 break;
db0f160a
PP
1990 case BT_CONFIG_COMMAND_PRINT_CTF_METADATA:
1991 ret = cmd_print_ctf_metadata(cfg);
1992 break;
1993 case BT_CONFIG_COMMAND_PRINT_LTTNG_LIVE_SESSIONS:
1994 ret = cmd_print_lttng_live_sessions(cfg);
1995 break;
290725f7 1996 default:
0fbb9a9f
PP
1997 BT_LOGF("Invalid/unknown command: cmd=%d", cfg->command);
1998 abort();
290725f7
PP
1999 }
2000
d26ef3e3
PP
2001 BT_LOGI("Command completed: cmd=%d, command-name=\"%s\", ret=%d",
2002 cfg->command, cfg->command_name, ret);
290725f7
PP
2003 warn_command_name_and_directory_clash(cfg);
2004 retcode = ret ? 1 : 0;
2005
2006end:
2007 BT_PUT(cfg);
9009cc24 2008 fini_static_data();
290725f7 2009 return retcode;
4c8bfb7e 2010}
This page took 0.145119 seconds and 4 git commands to generate.