sink.utils.counter: honor component's initial log level
[babeltrace.git] / src / cli / babeltrace2.c
CommitLineData
34ac0e6c 1/*
64fa3fec
MD
2 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
3 *
4 * Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
34ac0e6c
MD
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
c462e188
MD
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
34ac0e6c 23 */
4c8bfb7e 24
ea9f8b29
PP
25#define BT_LOG_TAG "CLI"
26#include "logging.h"
27
3fadfbc0 28#include <babeltrace2/babeltrace.h>
578e048b 29#include "common/common.h"
a8ff38ef 30#include <unistd.h>
34ac0e6c 31#include <stdlib.h>
7f26a816
PP
32#include <popt.h>
33#include <string.h>
34#include <stdio.h>
33b34c43 35#include <glib.h>
dc3fffef 36#include <inttypes.h>
7cdc2bab 37#include <unistd.h>
5401f780 38#include <signal.h>
ec2c5e50
MJ
39#include "babeltrace2-cfg.h"
40#include "babeltrace2-cfg-cli-args.h"
41#include "babeltrace2-cfg-cli-args-default.h"
9009cc24
PP
42
43#define ENV_BABELTRACE_WARN_COMMAND_NAME_DIRECTORY_CLASH "BABELTRACE_CLI_WARN_COMMAND_NAME_DIRECTORY_CLASH"
c6d4d1ae 44#define ENV_BABELTRACE_CLI_LOG_LEVEL "BABELTRACE_CLI_LOG_LEVEL"
75a2cb9b 45#define NSEC_PER_SEC 1000000000LL
34ac0e6c 46
fc11b6a6
PP
47/*
48 * Known environment variable names for the log levels of the project's
49 * modules.
50 */
51static const char* log_level_env_var_names[] = {
2fad3ae7 52 "BABELTRACE_FLT_LTTNG_UTILS_DEBUG_INFO_LOG_LEVEL",
2fad3ae7
PP
53 "BABELTRACE_FLT_UTILS_MUXER_LOG_LEVEL",
54 "BABELTRACE_FLT_UTILS_TRIMMER_LOG_LEVEL",
918fe780
PP
55 "BABELTRACE_PLUGIN_CTF_BFCR_LOG_LEVEL",
56 "BABELTRACE_PLUGIN_CTF_METADATA_LOG_LEVEL",
57 "BABELTRACE_PLUGIN_CTF_MSG_ITER_LOG_LEVEL",
58 "BABELTRACE_PLUGIN_CTF_UTILS_LOG_LEVEL",
fdad611f 59 "BABELTRACE_PYTHON_BT2_LOG_LEVEL",
918fe780 60 "BABELTRACE_SINK_CTF_FS_LOG_LEVEL",
55478183 61 "BABELTRACE_SINK_TEXT_DETAILS_LOG_LEVEL",
918fe780
PP
62 "BABELTRACE_SRC_CTF_FS_LOG_LEVEL",
63 "BABELTRACE_SRC_CTF_LTTNG_LIVE_LOG_LEVEL",
fc11b6a6
PP
64 NULL,
65};
66
5401f780 67/* Application's processing graph (weak) */
b19ff26f
PP
68static bt_graph *the_graph;
69static bt_query_executor *the_query_executor;
5401f780
PP
70static bool canceled = false;
71
33b34c43
PP
72GPtrArray *loaded_plugins;
73
65d3198f 74#ifdef __MINGW32__
a2d06fd5 75
65d3198f
MJ
76#include <windows.h>
77
78static
79BOOL WINAPI signal_handler(DWORD signal) {
80 if (the_graph) {
0d72b8c3 81 bt_graph_cancel(the_graph);
65d3198f
MJ
82 }
83
84 canceled = true;
85
86 return TRUE;
87}
88
5401f780 89static
65d3198f
MJ
90void set_signal_handler(void)
91{
92 if (!SetConsoleCtrlHandler(signal_handler, TRUE)) {
3f7d4d90 93 BT_LOGE("Failed to set the Ctrl+C handler.");
65d3198f
MJ
94 }
95}
a2d06fd5 96
65d3198f 97#else /* __MINGW32__ */
a2d06fd5 98
65d3198f
MJ
99static
100void signal_handler(int signum)
5401f780
PP
101{
102 if (signum != SIGINT) {
103 return;
104 }
105
106 if (the_graph) {
0d72b8c3 107 bt_graph_cancel(the_graph);
5401f780
PP
108 }
109
c7eee084 110 if (the_query_executor) {
0d72b8c3 111 bt_query_executor_cancel(the_query_executor);
c7eee084
PP
112 }
113
5401f780
PP
114 canceled = true;
115}
116
65d3198f
MJ
117static
118void set_signal_handler(void)
119{
120 struct sigaction new_action, old_action;
121
122 new_action.sa_handler = signal_handler;
123 sigemptyset(&new_action.sa_mask);
124 new_action.sa_flags = 0;
125 sigaction(SIGINT, NULL, &old_action);
126
127 if (old_action.sa_handler != SIG_IGN) {
128 sigaction(SIGINT, &new_action, NULL);
129 }
130}
a2d06fd5 131
65d3198f
MJ
132#endif /* __MINGW32__ */
133
33b34c43 134static
9009cc24 135void init_static_data(void)
33b34c43 136{
398454ed
PP
137 loaded_plugins = g_ptr_array_new_with_free_func(
138 (GDestroyNotify) bt_object_put_ref);
33b34c43
PP
139}
140
141static
9009cc24 142void fini_static_data(void)
33b34c43
PP
143{
144 g_ptr_array_free(loaded_plugins, TRUE);
145}
146
c7eee084
PP
147static
148int create_the_query_executor(void)
149{
150 int ret = 0;
151
0d72b8c3 152 the_query_executor = bt_query_executor_create();
c7eee084
PP
153 if (!the_query_executor) {
154 BT_LOGE_STR("Cannot create a query executor.");
155 ret = -1;
156 }
157
158 return ret;
159}
160
161static
162void destroy_the_query_executor(void)
163{
c5b9b441 164 BT_QUERY_EXECUTOR_PUT_REF_AND_RESET(the_query_executor);
c7eee084
PP
165}
166
167static
f4e38e70
PP
168int query(struct bt_config *cfg, const bt_component_class *comp_cls,
169 const char *obj, const bt_value *params,
170 const bt_value **user_result, const char **fail_reason)
c7eee084 171{
b19ff26f 172 const bt_value *result = NULL;
4cdfc5e8 173 bt_query_executor_status status;
c7eee084
PP
174 *fail_reason = "unknown error";
175 int ret = 0;
176
f6ccaed9
PP
177 BT_ASSERT(fail_reason);
178 BT_ASSERT(user_result);
c7eee084
PP
179 ret = create_the_query_executor();
180 if (ret) {
181 /* create_the_query_executor() logs errors */
182 goto end;
183 }
184
185 if (canceled) {
186 BT_LOGI("Canceled by user before executing the query: "
187 "comp-cls-addr=%p, comp-cls-name=\"%s\", "
188 "query-obj=\"%s\"", comp_cls,
189 bt_component_class_get_name(comp_cls), obj);
190 *fail_reason = "canceled by user";
191 goto error;
192 }
193
194 while (true) {
0d72b8c3 195 status = bt_query_executor_query(the_query_executor,
f4e38e70 196 comp_cls, obj, params, cfg->log_level, &result);
c7eee084 197 switch (status) {
d72535e6 198 case BT_QUERY_EXECUTOR_STATUS_OK:
c7eee084 199 goto ok;
d72535e6 200 case BT_QUERY_EXECUTOR_STATUS_AGAIN:
c7eee084
PP
201 {
202 const uint64_t sleep_time_us = 100000;
203
204 /* Wait 100 ms and retry */
3f7d4d90 205 BT_LOGD("Got BT_QUERY_EXECUTOR_STATUS_AGAIN: sleeping: "
c7eee084
PP
206 "time-us=%" PRIu64, sleep_time_us);
207
208 if (usleep(sleep_time_us)) {
0d72b8c3 209 if (bt_query_executor_is_canceled(the_query_executor)) {
c7eee084
PP
210 BT_LOGI("Query was canceled by user: "
211 "comp-cls-addr=%p, comp-cls-name=\"%s\", "
212 "query-obj=\"%s\"", comp_cls,
213 bt_component_class_get_name(comp_cls),
214 obj);
215 *fail_reason = "canceled by user";
216 goto error;
217 }
218 }
219
220 continue;
221 }
d72535e6 222 case BT_QUERY_EXECUTOR_STATUS_CANCELED:
c7eee084
PP
223 *fail_reason = "canceled by user";
224 goto error;
d72535e6 225 case BT_QUERY_EXECUTOR_STATUS_ERROR:
c7eee084 226 goto error;
d72535e6 227 case BT_QUERY_EXECUTOR_STATUS_INVALID_OBJECT:
c7eee084
PP
228 *fail_reason = "invalid or unknown query object";
229 goto error;
d72535e6 230 case BT_QUERY_EXECUTOR_STATUS_INVALID_PARAMS:
c7eee084
PP
231 *fail_reason = "invalid query parameters";
232 goto error;
d72535e6
PP
233 case BT_QUERY_EXECUTOR_STATUS_UNSUPPORTED:
234 *fail_reason = "unsupported action";
235 goto error;
236 case BT_QUERY_EXECUTOR_STATUS_NOMEM:
c7eee084
PP
237 *fail_reason = "not enough memory";
238 goto error;
239 default:
240 BT_LOGF("Unknown query status: status=%d", status);
241 abort();
242 }
243 }
244
245ok:
246 *user_result = result;
247 result = NULL;
248 goto end;
249
250error:
251 ret = -1;
252
253end:
254 destroy_the_query_executor();
c5b9b441 255 bt_value_put_ref(result);
c7eee084
PP
256 return ret;
257}
258
33b34c43 259static
b19ff26f 260const bt_plugin *find_plugin(const char *name)
33b34c43
PP
261{
262 int i;
b19ff26f 263 const bt_plugin *plugin = NULL;
33b34c43 264
f6ccaed9 265 BT_ASSERT(name);
3f7d4d90 266 BT_LOGI("Finding plugin: name=\"%s\"", name);
7213a328 267
33b34c43
PP
268 for (i = 0; i < loaded_plugins->len; i++) {
269 plugin = g_ptr_array_index(loaded_plugins, i);
270
271 if (strcmp(name, bt_plugin_get_name(plugin)) == 0) {
272 break;
273 }
274
275 plugin = NULL;
276 }
277
3f7d4d90
PP
278 if (plugin) {
279 BT_LOGI("Found plugin: name=\"%s\", plugin-addr=%p",
280 name, plugin);
281 } else {
282 BT_LOGI("Cannot find plugin: name=\"%s\"", name);
7213a328
PP
283 }
284
c5b9b441 285 bt_plugin_get_ref(plugin);
398454ed 286 return plugin;
33b34c43
PP
287}
288
0d72b8c3 289typedef const void *(*plugin_borrow_comp_cls_func_t)(
b19ff26f 290 const bt_plugin *, const char *);
d94d92ac 291
33b34c43 292static
0d72b8c3 293const void *find_component_class_from_plugin(const char *plugin_name,
33b34c43 294 const char *comp_class_name,
d94d92ac 295 plugin_borrow_comp_cls_func_t plugin_borrow_comp_cls_func)
33b34c43 296{
0d72b8c3 297 const void *comp_class = NULL;
b19ff26f 298 const bt_plugin *plugin;
7213a328 299
3f7d4d90 300 BT_LOGI("Finding component class: plugin-name=\"%s\", "
d94d92ac 301 "comp-cls-name=\"%s\"", plugin_name, comp_class_name);
7213a328
PP
302
303 plugin = find_plugin(plugin_name);
33b34c43
PP
304 if (!plugin) {
305 goto end;
306 }
307
398454ed
PP
308 comp_class = plugin_borrow_comp_cls_func(plugin, comp_class_name);
309 bt_object_get_ref(comp_class);
c5b9b441 310 BT_PLUGIN_PUT_REF_AND_RESET(plugin);
7213a328 311
33b34c43 312end:
3f7d4d90
PP
313 if (comp_class) {
314 BT_LOGI("Found component class: plugin-name=\"%s\", "
315 "comp-cls-name=\"%s\"", plugin_name, comp_class_name);
316 } else {
317 BT_LOGI("Cannot find source component class: "
318 "plugin-name=\"%s\", comp-cls-name=\"%s\"",
319 plugin_name, comp_class_name);
7213a328
PP
320 }
321
33b34c43
PP
322 return comp_class;
323}
6c2f3ee5 324
d94d92ac 325static
b19ff26f 326const bt_component_class_source *find_source_component_class(
d94d92ac
PP
327 const char *plugin_name, const char *comp_class_name)
328{
0d72b8c3
PP
329 return (const void *) find_component_class_from_plugin(
330 plugin_name, comp_class_name,
d94d92ac 331 (plugin_borrow_comp_cls_func_t)
92fed4e1 332 bt_plugin_borrow_source_component_class_by_name_const);
d94d92ac
PP
333}
334
335static
b19ff26f 336const bt_component_class_filter *find_filter_component_class(
d94d92ac
PP
337 const char *plugin_name, const char *comp_class_name)
338{
0d72b8c3
PP
339 return (const void *) find_component_class_from_plugin(
340 plugin_name, comp_class_name,
d94d92ac 341 (plugin_borrow_comp_cls_func_t)
92fed4e1 342 bt_plugin_borrow_filter_component_class_by_name_const);
d94d92ac
PP
343}
344
345static
b19ff26f 346const bt_component_class_sink *find_sink_component_class(
d94d92ac
PP
347 const char *plugin_name, const char *comp_class_name)
348{
0d72b8c3 349 return (const void *) find_component_class_from_plugin(plugin_name,
d94d92ac
PP
350 comp_class_name,
351 (plugin_borrow_comp_cls_func_t)
92fed4e1 352 bt_plugin_borrow_sink_component_class_by_name_const);
d94d92ac
PP
353}
354
355static
b19ff26f 356const bt_component_class *find_component_class(const char *plugin_name,
d94d92ac 357 const char *comp_class_name,
4cdfc5e8 358 bt_component_class_type comp_class_type)
d94d92ac 359{
b19ff26f 360 const bt_component_class *comp_cls = NULL;
d94d92ac
PP
361
362 switch (comp_class_type) {
363 case BT_COMPONENT_CLASS_TYPE_SOURCE:
0d72b8c3 364 comp_cls = bt_component_class_source_as_component_class_const(find_source_component_class(plugin_name, comp_class_name));
d94d92ac
PP
365 break;
366 case BT_COMPONENT_CLASS_TYPE_FILTER:
0d72b8c3 367 comp_cls = bt_component_class_filter_as_component_class_const(find_filter_component_class(plugin_name, comp_class_name));
d94d92ac
PP
368 break;
369 case BT_COMPONENT_CLASS_TYPE_SINK:
0d72b8c3 370 comp_cls = bt_component_class_sink_as_component_class_const(find_sink_component_class(plugin_name, comp_class_name));
d94d92ac
PP
371 break;
372 default:
373 abort();
374 }
375
376 return comp_cls;
377}
378
c42c79ea 379static
7213a328 380void print_indent(FILE *fp, size_t indent)
c42c79ea
PP
381{
382 size_t i;
383
384 for (i = 0; i < indent; i++) {
7213a328 385 fprintf(fp, " ");
c42c79ea
PP
386 }
387}
388
87796884 389static
4cdfc5e8 390const char *component_type_str(bt_component_class_type type)
87796884
PP
391{
392 switch (type) {
393 case BT_COMPONENT_CLASS_TYPE_SOURCE:
394 return "source";
395 case BT_COMPONENT_CLASS_TYPE_SINK:
396 return "sink";
397 case BT_COMPONENT_CLASS_TYPE_FILTER:
398 return "filter";
87796884 399 default:
fd5f8053 400 return "(unknown)";
87796884
PP
401 }
402}
403
9009cc24
PP
404static
405void print_plugin_comp_cls_opt(FILE *fh, const char *plugin_name,
4cdfc5e8 406 const char *comp_cls_name, bt_component_class_type type)
87796884 407{
9009cc24
PP
408 GString *shell_plugin_name = NULL;
409 GString *shell_comp_cls_name = NULL;
87796884 410
9009cc24 411 shell_plugin_name = bt_common_shell_quote(plugin_name, false);
87796884
PP
412 if (!shell_plugin_name) {
413 goto end;
414 }
415
9009cc24 416 shell_comp_cls_name = bt_common_shell_quote(comp_cls_name, false);
87796884
PP
417 if (!shell_comp_cls_name) {
418 goto end;
419 }
420
fd5f8053 421 fprintf(fh, "'%s%s%s%s.%s%s%s.%s%s%s'",
87796884
PP
422 bt_common_color_bold(),
423 bt_common_color_fg_cyan(),
424 component_type_str(type),
87796884 425 bt_common_color_fg_default(),
87796884 426 bt_common_color_fg_blue(),
9009cc24 427 shell_plugin_name->str,
87796884
PP
428 bt_common_color_fg_default(),
429 bt_common_color_fg_yellow(),
9009cc24 430 shell_comp_cls_name->str,
87796884
PP
431 bt_common_color_reset());
432
433end:
9009cc24
PP
434 if (shell_plugin_name) {
435 g_string_free(shell_plugin_name, TRUE);
436 }
437
438 if (shell_comp_cls_name) {
439 g_string_free(shell_comp_cls_name, TRUE);
440 }
87796884
PP
441}
442
c42c79ea 443static
b19ff26f 444void print_value(FILE *, const bt_value *, size_t);
c42c79ea 445
c1081aa6 446static
b19ff26f 447void print_value_rec(FILE *, const bt_value *, size_t);
7213a328
PP
448
449struct print_map_value_data {
450 size_t indent;
451 FILE *fp;
452};
c1081aa6 453
c42c79ea 454static
b19ff26f 455bt_bool print_map_value(const char *key, const bt_value *object,
05e21286 456 void *data)
c42c79ea 457{
7213a328 458 struct print_map_value_data *print_map_value_data = data;
290725f7 459
7213a328
PP
460 print_indent(print_map_value_data->fp, print_map_value_data->indent);
461 fprintf(print_map_value_data->fp, "%s: ", key);
f6ccaed9 462 BT_ASSERT(object);
290725f7
PP
463
464 if (bt_value_is_array(object) &&
465 bt_value_array_is_empty(object)) {
7213a328 466 fprintf(print_map_value_data->fp, "[ ]\n");
290725f7
PP
467 return true;
468 }
469
470 if (bt_value_is_map(object) &&
471 bt_value_map_is_empty(object)) {
7213a328 472 fprintf(print_map_value_data->fp, "{ }\n");
290725f7
PP
473 return true;
474 }
c42c79ea 475
290725f7
PP
476 if (bt_value_is_array(object) ||
477 bt_value_is_map(object)) {
7213a328 478 fprintf(print_map_value_data->fp, "\n");
290725f7 479 }
c42c79ea 480
7213a328
PP
481 print_value_rec(print_map_value_data->fp, object,
482 print_map_value_data->indent + 2);
c55a9f58 483 return BT_TRUE;
c42c79ea
PP
484}
485
486static
b19ff26f 487void print_value_rec(FILE *fp, const bt_value *value, size_t indent)
c42c79ea 488{
c55a9f58 489 bt_bool bool_val;
c42c79ea 490 int64_t int_val;
fdd3a2da 491 uint64_t uint_val;
c42c79ea
PP
492 double dbl_val;
493 const char *str_val;
494 int size;
495 int i;
496
497 if (!value) {
498 return;
499 }
500
c42c79ea
PP
501 switch (bt_value_get_type(value)) {
502 case BT_VALUE_TYPE_NULL:
7213a328 503 fprintf(fp, "%snull%s\n", bt_common_color_bold(),
c1081aa6 504 bt_common_color_reset());
c42c79ea
PP
505 break;
506 case BT_VALUE_TYPE_BOOL:
601b0d3c 507 bool_val = bt_value_bool_get(value);
7213a328 508 fprintf(fp, "%s%s%s%s\n", bt_common_color_bold(),
c1081aa6
PP
509 bt_common_color_fg_cyan(), bool_val ? "yes" : "no",
510 bt_common_color_reset());
c42c79ea 511 break;
fdd3a2da
PP
512 case BT_VALUE_TYPE_UNSIGNED_INTEGER:
513 uint_val = bt_value_unsigned_integer_get(value);
514 fprintf(fp, "%s%s%" PRIu64 "%s\n", bt_common_color_bold(),
515 bt_common_color_fg_red(), uint_val,
516 bt_common_color_reset());
517 break;
518 case BT_VALUE_TYPE_SIGNED_INTEGER:
519 int_val = bt_value_signed_integer_get(value);
7213a328 520 fprintf(fp, "%s%s%" PRId64 "%s\n", bt_common_color_bold(),
c1081aa6
PP
521 bt_common_color_fg_red(), int_val,
522 bt_common_color_reset());
c42c79ea 523 break;
a373bf69 524 case BT_VALUE_TYPE_REAL:
601b0d3c 525 dbl_val = bt_value_real_get(value);
7213a328 526 fprintf(fp, "%s%s%lf%s\n", bt_common_color_bold(),
c1081aa6
PP
527 bt_common_color_fg_red(), dbl_val,
528 bt_common_color_reset());
c42c79ea
PP
529 break;
530 case BT_VALUE_TYPE_STRING:
601b0d3c 531 str_val = bt_value_string_get(value);
7213a328 532 fprintf(fp, "%s%s%s%s\n", bt_common_color_bold(),
c1081aa6
PP
533 bt_common_color_fg_green(), str_val,
534 bt_common_color_reset());
c42c79ea
PP
535 break;
536 case BT_VALUE_TYPE_ARRAY:
07208d85 537 size = bt_value_array_get_size(value);
60a97734
MD
538 if (size < 0) {
539 goto error;
540 }
290725f7
PP
541
542 if (size == 0) {
7213a328
PP
543 print_indent(fp, indent);
544 fprintf(fp, "[ ]\n");
290725f7
PP
545 break;
546 }
c42c79ea
PP
547
548 for (i = 0; i < size; i++) {
b19ff26f 549 const bt_value *element =
05e21286 550 bt_value_array_borrow_element_by_index_const(
07208d85 551 value, i);
c42c79ea 552
60a97734
MD
553 if (!element) {
554 goto error;
555 }
7213a328
PP
556 print_indent(fp, indent);
557 fprintf(fp, "- ");
290725f7
PP
558
559 if (bt_value_is_array(element) &&
560 bt_value_array_is_empty(element)) {
7213a328 561 fprintf(fp, "[ ]\n");
290725f7
PP
562 continue;
563 }
564
565 if (bt_value_is_map(element) &&
566 bt_value_map_is_empty(element)) {
7213a328 567 fprintf(fp, "{ }\n");
290725f7
PP
568 continue;
569 }
570
571 if (bt_value_is_array(element) ||
572 bt_value_is_map(element)) {
7213a328 573 fprintf(fp, "\n");
290725f7
PP
574 }
575
7213a328 576 print_value_rec(fp, element, indent + 2);
c42c79ea 577 }
c42c79ea
PP
578 break;
579 case BT_VALUE_TYPE_MAP:
7213a328
PP
580 {
581 struct print_map_value_data data = {
582 .indent = indent,
583 .fp = fp,
584 };
585
c42c79ea 586 if (bt_value_map_is_empty(value)) {
7213a328
PP
587 print_indent(fp, indent);
588 fprintf(fp, "{ }\n");
290725f7 589 break;
c42c79ea
PP
590 }
591
05e21286 592 bt_value_map_foreach_entry_const(value, print_map_value, &data);
c42c79ea 593 break;
7213a328 594 }
c42c79ea 595 default:
0fbb9a9f 596 abort();
c42c79ea 597 }
60a97734
MD
598 return;
599
600error:
601 BT_LOGE("Error printing value of type %s.",
da91b29a 602 bt_common_value_type_string(bt_value_get_type(value)));
c42c79ea
PP
603}
604
c1081aa6 605static
b19ff26f 606void print_value(FILE *fp, const bt_value *value, size_t indent)
c1081aa6
PP
607{
608 if (!bt_value_is_array(value) && !bt_value_is_map(value)) {
7213a328 609 print_indent(fp, indent);
c1081aa6
PP
610 }
611
7213a328 612 print_value_rec(fp, value, indent);
c1081aa6
PP
613}
614
c42c79ea
PP
615static
616void print_bt_config_component(struct bt_config_component *bt_config_component)
617{
7213a328
PP
618 fprintf(stderr, " ");
619 print_plugin_comp_cls_opt(stderr, bt_config_component->plugin_name->str,
db0f160a 620 bt_config_component->comp_cls_name->str,
87796884 621 bt_config_component->type);
7213a328 622 fprintf(stderr, ":\n");
3b6cfcc5
PP
623
624 if (bt_config_component->instance_name->len > 0) {
7213a328 625 fprintf(stderr, " Name: %s\n",
3b6cfcc5
PP
626 bt_config_component->instance_name->str);
627 }
628
7213a328 629 fprintf(stderr, " Parameters:\n");
05e21286 630 print_value(stderr, bt_config_component->params, 8);
c42c79ea
PP
631}
632
633static
634void print_bt_config_components(GPtrArray *array)
635{
636 size_t i;
637
638 for (i = 0; i < array->len; i++) {
639 struct bt_config_component *cfg_component =
e5bc7f81 640 bt_config_get_component(array, i);
c42c79ea 641 print_bt_config_component(cfg_component);
65300d60 642 BT_OBJECT_PUT_REF_AND_RESET(cfg_component);
c42c79ea
PP
643 }
644}
645
290725f7 646static
b19ff26f 647void print_plugin_paths(const bt_value *plugin_paths)
290725f7 648{
7213a328
PP
649 fprintf(stderr, " Plugin paths:\n");
650 print_value(stderr, plugin_paths, 4);
290725f7
PP
651}
652
653static
db0f160a 654void print_cfg_run(struct bt_config *cfg)
290725f7 655{
ebba3338
PP
656 size_t i;
657
05e21286 658 print_plugin_paths(cfg->plugin_paths);
7213a328 659 fprintf(stderr, " Source component instances:\n");
db0f160a 660 print_bt_config_components(cfg->cmd_data.run.sources);
ebba3338 661
db0f160a 662 if (cfg->cmd_data.run.filters->len > 0) {
7213a328 663 fprintf(stderr, " Filter component instances:\n");
db0f160a 664 print_bt_config_components(cfg->cmd_data.run.filters);
ebba3338
PP
665 }
666
7213a328 667 fprintf(stderr, " Sink component instances:\n");
db0f160a 668 print_bt_config_components(cfg->cmd_data.run.sinks);
7213a328 669 fprintf(stderr, " Connections:\n");
ebba3338 670
db0f160a 671 for (i = 0; i < cfg->cmd_data.run.connections->len; i++) {
ebba3338 672 struct bt_config_connection *cfg_connection =
db0f160a 673 g_ptr_array_index(cfg->cmd_data.run.connections,
ebba3338
PP
674 i);
675
7213a328 676 fprintf(stderr, " %s%s%s -> %s%s%s\n",
9009cc24
PP
677 cfg_connection->upstream_comp_name->str,
678 cfg_connection->upstream_port_glob->len > 0 ? "." : "",
679 cfg_connection->upstream_port_glob->str,
680 cfg_connection->downstream_comp_name->str,
681 cfg_connection->downstream_port_glob->len > 0 ? "." : "",
682 cfg_connection->downstream_port_glob->str);
ebba3338 683 }
290725f7
PP
684}
685
686static
687void print_cfg_list_plugins(struct bt_config *cfg)
688{
05e21286 689 print_plugin_paths(cfg->plugin_paths);
290725f7
PP
690}
691
c1081aa6
PP
692static
693void print_cfg_help(struct bt_config *cfg)
694{
05e21286 695 print_plugin_paths(cfg->plugin_paths);
db0f160a
PP
696}
697
698static
699void print_cfg_print_ctf_metadata(struct bt_config *cfg)
700{
05e21286 701 print_plugin_paths(cfg->plugin_paths);
7213a328
PP
702 fprintf(stderr, " Path: %s\n",
703 cfg->cmd_data.print_ctf_metadata.path->str);
db0f160a
PP
704}
705
706static
707void print_cfg_print_lttng_live_sessions(struct bt_config *cfg)
708{
05e21286 709 print_plugin_paths(cfg->plugin_paths);
7213a328
PP
710 fprintf(stderr, " URL: %s\n",
711 cfg->cmd_data.print_lttng_live_sessions.url->str);
c1081aa6
PP
712}
713
714static
a67681c1 715void print_cfg_query(struct bt_config *cfg)
c1081aa6 716{
05e21286 717 print_plugin_paths(cfg->plugin_paths);
7213a328
PP
718 fprintf(stderr, " Object: `%s`\n", cfg->cmd_data.query.object->str);
719 fprintf(stderr, " Component class:\n");
a67681c1 720 print_bt_config_component(cfg->cmd_data.query.cfg_component);
c1081aa6
PP
721}
722
c42c79ea
PP
723static
724void print_cfg(struct bt_config *cfg)
725{
7213a328 726 if (!BT_LOG_ON_INFO) {
00447e45
PP
727 return;
728 }
729
3f7d4d90
PP
730 BT_LOGI_STR("CLI configuration:");
731 BT_LOGI(" Debug mode: %s\n", cfg->debug ? "yes" : "no");
732 BT_LOGI(" Verbose mode: %s\n", cfg->verbose ? "yes" : "no");
290725f7
PP
733
734 switch (cfg->command) {
db0f160a
PP
735 case BT_CONFIG_COMMAND_RUN:
736 print_cfg_run(cfg);
290725f7
PP
737 break;
738 case BT_CONFIG_COMMAND_LIST_PLUGINS:
739 print_cfg_list_plugins(cfg);
c1081aa6
PP
740 break;
741 case BT_CONFIG_COMMAND_HELP:
742 print_cfg_help(cfg);
743 break;
a67681c1
PP
744 case BT_CONFIG_COMMAND_QUERY:
745 print_cfg_query(cfg);
290725f7 746 break;
db0f160a
PP
747 case BT_CONFIG_COMMAND_PRINT_CTF_METADATA:
748 print_cfg_print_ctf_metadata(cfg);
749 break;
750 case BT_CONFIG_COMMAND_PRINT_LTTNG_LIVE_SESSIONS:
751 print_cfg_print_lttng_live_sessions(cfg);
752 break;
290725f7 753 default:
0fbb9a9f 754 abort();
290725f7 755 }
c42c79ea
PP
756}
757
33b34c43 758static
b19ff26f 759void add_to_loaded_plugins(const bt_plugin_set *plugin_set)
98ecef32 760{
544d0515
PP
761 int64_t i;
762 int64_t count;
a8ff38ef
PP
763
764 count = bt_plugin_set_get_plugin_count(plugin_set);
f6ccaed9 765 BT_ASSERT(count >= 0);
a8ff38ef
PP
766
767 for (i = 0; i < count; i++) {
b19ff26f 768 const bt_plugin *plugin =
92fed4e1 769 bt_plugin_set_borrow_plugin_by_index_const(plugin_set, i);
b19ff26f 770 const bt_plugin *loaded_plugin =
d94d92ac 771 find_plugin(bt_plugin_get_name(plugin));
33b34c43 772
f6ccaed9 773 BT_ASSERT(plugin);
a8ff38ef 774
33b34c43 775 if (loaded_plugin) {
7213a328
PP
776 BT_LOGI("Not using plugin: another one already exists with the same name: "
777 "plugin-name=\"%s\", plugin-path=\"%s\", "
778 "existing-plugin-path=\"%s\"",
779 bt_plugin_get_name(plugin),
780 bt_plugin_get_path(plugin),
781 bt_plugin_get_path(loaded_plugin));
c5b9b441 782 bt_plugin_put_ref(loaded_plugin);
33b34c43 783 } else {
a8ff38ef 784 /* Add to global array. */
7213a328
PP
785 BT_LOGD("Adding plugin to loaded plugins: plugin-path=\"%s\"",
786 bt_plugin_get_name(plugin));
c5b9b441 787 bt_plugin_get_ref(plugin);
92fed4e1 788 g_ptr_array_add(loaded_plugins, (void *) plugin);
33b34c43 789 }
33b34c43
PP
790 }
791}
792
793static
b19ff26f 794int load_dynamic_plugins(const bt_value *plugin_paths)
33b34c43
PP
795{
796 int nr_paths, i, ret = 0;
98ecef32 797
07208d85 798 nr_paths = bt_value_array_get_size(plugin_paths);
98ecef32 799 if (nr_paths < 0) {
7213a328 800 BT_LOGE_STR("Cannot load dynamic plugins: no plugin path.");
33b34c43
PP
801 ret = -1;
802 goto end;
98ecef32 803 }
33b34c43 804
3f7d4d90 805 BT_LOGI_STR("Loading dynamic plugins.");
7213a328 806
98ecef32 807 for (i = 0; i < nr_paths; i++) {
b19ff26f 808 const bt_value *plugin_path_value = NULL;
98ecef32 809 const char *plugin_path;
b19ff26f 810 const bt_plugin_set *plugin_set;
98ecef32 811
05e21286
PP
812 plugin_path_value =
813 bt_value_array_borrow_element_by_index_const(
814 plugin_paths, i);
601b0d3c 815 plugin_path = bt_value_string_get(plugin_path_value);
50ad9320
PP
816
817 /*
818 * Skip this if the directory does not exist because
c8db3219 819 * bt_plugin_find_all_from_dir() expects an existing
50ad9320
PP
820 * directory.
821 */
822 if (!g_file_test(plugin_path, G_FILE_TEST_IS_DIR)) {
3f7d4d90 823 BT_LOGI("Skipping nonexistent directory path: "
50ad9320 824 "path=\"%s\"", plugin_path);
50ad9320
PP
825 continue;
826 }
827
c8db3219 828 plugin_set = bt_plugin_find_all_from_dir(plugin_path, false);
a8ff38ef 829 if (!plugin_set) {
3f7d4d90
PP
830 BT_LOGI("Unable to load dynamic plugins from directory: "
831 "path=\"%s\"", plugin_path);
33b34c43 832 continue;
98ecef32 833 }
33b34c43 834
a8ff38ef 835 add_to_loaded_plugins(plugin_set);
c5b9b441 836 bt_plugin_set_put_ref(plugin_set);
98ecef32 837 }
33b34c43
PP
838end:
839 return ret;
840}
841
842static
843int load_static_plugins(void)
844{
845 int ret = 0;
b19ff26f 846 const bt_plugin_set *plugin_set;
33b34c43 847
7213a328 848 BT_LOGI("Loading static plugins.");
c8db3219 849 plugin_set = bt_plugin_find_all_from_static();
a8ff38ef 850 if (!plugin_set) {
7213a328 851 BT_LOGE("Unable to load static plugins.");
33b34c43
PP
852 ret = -1;
853 goto end;
854 }
855
a8ff38ef 856 add_to_loaded_plugins(plugin_set);
c5b9b441 857 bt_plugin_set_put_ref(plugin_set);
33b34c43
PP
858end:
859 return ret;
98ecef32
MD
860}
861
9009cc24 862static
b19ff26f 863int load_all_plugins(const bt_value *plugin_paths)
290725f7
PP
864{
865 int ret = 0;
33b34c43 866
290725f7 867 if (load_dynamic_plugins(plugin_paths)) {
290725f7 868 ret = -1;
c1870f57
JG
869 goto end;
870 }
871
290725f7 872 if (load_static_plugins()) {
290725f7 873 ret = -1;
c1870f57
JG
874 goto end;
875 }
876
7213a328
PP
877 BT_LOGI("Loaded all plugins: count=%u", loaded_plugins->len);
878
290725f7
PP
879end:
880 return ret;
881}
882
9009cc24 883static
b19ff26f 884void print_plugin_info(const bt_plugin *plugin)
22e22462
PP
885{
886 unsigned int major, minor, patch;
887 const char *extra;
4cdfc5e8 888 bt_property_availability version_avail;
22e22462
PP
889 const char *plugin_name;
890 const char *path;
891 const char *author;
892 const char *license;
893 const char *plugin_description;
894
895 plugin_name = bt_plugin_get_name(plugin);
896 path = bt_plugin_get_path(plugin);
897 author = bt_plugin_get_author(plugin);
898 license = bt_plugin_get_license(plugin);
899 plugin_description = bt_plugin_get_description(plugin);
9724cce9 900 version_avail = bt_plugin_get_version(plugin, &major, &minor,
22e22462
PP
901 &patch, &extra);
902 printf("%s%s%s%s:\n", bt_common_color_bold(),
903 bt_common_color_fg_blue(), plugin_name,
904 bt_common_color_reset());
a157fea9
MJ
905 if (path) {
906 printf(" %sPath%s: %s\n", bt_common_color_bold(),
907 bt_common_color_reset(), path);
908 } else {
909 puts(" Built-in");
910 }
22e22462 911
9724cce9 912 if (version_avail == BT_PROPERTY_AVAILABILITY_AVAILABLE) {
22e22462
PP
913 printf(" %sVersion%s: %u.%u.%u",
914 bt_common_color_bold(), bt_common_color_reset(),
915 major, minor, patch);
916
917 if (extra) {
918 printf("%s", extra);
919 }
920
921 printf("\n");
922 }
923
924 printf(" %sDescription%s: %s\n", bt_common_color_bold(),
925 bt_common_color_reset(),
926 plugin_description ? plugin_description : "(None)");
927 printf(" %sAuthor%s: %s\n", bt_common_color_bold(),
928 bt_common_color_reset(), author ? author : "(Unknown)");
929 printf(" %sLicense%s: %s\n", bt_common_color_bold(),
930 bt_common_color_reset(),
931 license ? license : "(Unknown)");
932}
933
9009cc24
PP
934static
935int cmd_query(struct bt_config *cfg)
63ce0e1d 936{
db95fa29 937 int ret = 0;
b19ff26f
PP
938 const bt_component_class *comp_cls = NULL;
939 const bt_value *results = NULL;
c7eee084 940 const char *fail_reason = NULL;
63ce0e1d 941
d94d92ac
PP
942 comp_cls = find_component_class(
943 cfg->cmd_data.query.cfg_component->plugin_name->str,
db0f160a 944 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
a67681c1 945 cfg->cmd_data.query.cfg_component->type);
63ce0e1d 946 if (!comp_cls) {
7213a328
PP
947 BT_LOGE("Cannot find component class: plugin-name=\"%s\", "
948 "comp-cls-name=\"%s\", comp-cls-type=%d",
949 cfg->cmd_data.query.cfg_component->plugin_name->str,
950 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
951 cfg->cmd_data.query.cfg_component->type);
63ce0e1d
PP
952 fprintf(stderr, "%s%sCannot find component class %s",
953 bt_common_color_bold(),
954 bt_common_color_fg_red(),
955 bt_common_color_reset());
956 print_plugin_comp_cls_opt(stderr,
a67681c1 957 cfg->cmd_data.query.cfg_component->plugin_name->str,
db0f160a 958 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
a67681c1 959 cfg->cmd_data.query.cfg_component->type);
63ce0e1d
PP
960 fprintf(stderr, "\n");
961 ret = -1;
962 goto end;
963 }
964
f4e38e70 965 ret = query(cfg, comp_cls, cfg->cmd_data.query.object->str,
05e21286 966 cfg->cmd_data.query.cfg_component->params,
da91b29a 967 &results, &fail_reason);
c7eee084
PP
968 if (ret) {
969 goto failed;
63ce0e1d
PP
970 }
971
7213a328 972 print_value(stdout, results, 0);
c7eee084
PP
973 goto end;
974
975failed:
976 BT_LOGE("Failed to query component class: %s: plugin-name=\"%s\", "
977 "comp-cls-name=\"%s\", comp-cls-type=%d "
978 "object=\"%s\"", fail_reason,
979 cfg->cmd_data.query.cfg_component->plugin_name->str,
980 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
981 cfg->cmd_data.query.cfg_component->type,
982 cfg->cmd_data.query.object->str);
983 fprintf(stderr, "%s%sFailed to query info to %s",
984 bt_common_color_bold(),
985 bt_common_color_fg_red(),
986 bt_common_color_reset());
987 print_plugin_comp_cls_opt(stderr,
988 cfg->cmd_data.query.cfg_component->plugin_name->str,
989 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
990 cfg->cmd_data.query.cfg_component->type);
991 fprintf(stderr, "%s%s with object `%s`: %s%s\n",
992 bt_common_color_bold(),
993 bt_common_color_fg_red(),
994 cfg->cmd_data.query.object->str,
995 fail_reason,
996 bt_common_color_reset());
997 ret = -1;
63ce0e1d
PP
998
999end:
c5b9b441
PP
1000 bt_component_class_put_ref(comp_cls);
1001 bt_value_put_ref(results);
63ce0e1d
PP
1002 return ret;
1003}
1004
d94d92ac
PP
1005static
1006void print_component_class_help(const char *plugin_name,
b19ff26f 1007 const bt_component_class *comp_cls)
d94d92ac
PP
1008{
1009 const char *comp_class_name =
1010 bt_component_class_get_name(comp_cls);
1011 const char *comp_class_description =
1012 bt_component_class_get_description(comp_cls);
1013 const char *comp_class_help =
1014 bt_component_class_get_help(comp_cls);
4cdfc5e8 1015 bt_component_class_type type =
d94d92ac
PP
1016 bt_component_class_get_type(comp_cls);
1017
1018 print_plugin_comp_cls_opt(stdout, plugin_name, comp_class_name, type);
1019 printf("\n");
1020 printf(" %sDescription%s: %s\n", bt_common_color_bold(),
1021 bt_common_color_reset(),
1022 comp_class_description ? comp_class_description : "(None)");
1023
1024 if (comp_class_help) {
1025 printf("\n%s\n", comp_class_help);
1026 }
1027}
1028
9009cc24
PP
1029static
1030int cmd_help(struct bt_config *cfg)
22e22462 1031{
db95fa29 1032 int ret = 0;
b19ff26f
PP
1033 const bt_plugin *plugin = NULL;
1034 const bt_component_class *needed_comp_cls = NULL;
22e22462 1035
90de159b 1036 plugin = find_plugin(cfg->cmd_data.help.cfg_component->plugin_name->str);
22e22462 1037 if (!plugin) {
7213a328
PP
1038 BT_LOGE("Cannot find plugin: plugin-name=\"%s\"",
1039 cfg->cmd_data.help.cfg_component->plugin_name->str);
22e22462
PP
1040 fprintf(stderr, "%s%sCannot find plugin %s%s%s\n",
1041 bt_common_color_bold(), bt_common_color_fg_red(),
1042 bt_common_color_fg_blue(),
90de159b 1043 cfg->cmd_data.help.cfg_component->plugin_name->str,
22e22462
PP
1044 bt_common_color_reset());
1045 ret = -1;
1046 goto end;
1047 }
1048
1049 print_plugin_info(plugin);
d94d92ac
PP
1050 printf(" %sSource component classes%s: %d\n",
1051 bt_common_color_bold(),
1052 bt_common_color_reset(),
1053 (int) bt_plugin_get_source_component_class_count(plugin));
1054 printf(" %sFilter component classes%s: %d\n",
22e22462
PP
1055 bt_common_color_bold(),
1056 bt_common_color_reset(),
d94d92ac
PP
1057 (int) bt_plugin_get_filter_component_class_count(plugin));
1058 printf(" %sSink component classes%s: %d\n",
1059 bt_common_color_bold(),
1060 bt_common_color_reset(),
1061 (int) bt_plugin_get_sink_component_class_count(plugin));
22e22462 1062
d94d92ac
PP
1063 if (strlen(cfg->cmd_data.help.cfg_component->comp_cls_name->str) == 0) {
1064 /* Plugin help only */
1065 goto end;
1066 }
22e22462 1067
d94d92ac
PP
1068 needed_comp_cls = find_component_class(
1069 cfg->cmd_data.help.cfg_component->plugin_name->str,
1070 cfg->cmd_data.help.cfg_component->comp_cls_name->str,
1071 cfg->cmd_data.help.cfg_component->type);
1072 if (!needed_comp_cls) {
1073 BT_LOGE("Cannot find component class: plugin-name=\"%s\", "
1074 "comp-cls-name=\"%s\", comp-cls-type=%d",
1075 cfg->cmd_data.help.cfg_component->plugin_name->str,
1076 cfg->cmd_data.help.cfg_component->comp_cls_name->str,
1077 cfg->cmd_data.help.cfg_component->type);
1078 fprintf(stderr, "\n%s%sCannot find component class %s",
1079 bt_common_color_bold(),
1080 bt_common_color_fg_red(),
1081 bt_common_color_reset());
1082 print_plugin_comp_cls_opt(stderr,
1083 cfg->cmd_data.help.cfg_component->plugin_name->str,
1084 cfg->cmd_data.help.cfg_component->comp_cls_name->str,
1085 cfg->cmd_data.help.cfg_component->type);
1086 fprintf(stderr, "\n");
1087 ret = -1;
1088 goto end;
1089 }
22e22462 1090
d94d92ac
PP
1091 printf("\n");
1092 print_component_class_help(
1093 cfg->cmd_data.help.cfg_component->plugin_name->str,
1094 needed_comp_cls);
1095
1096end:
c5b9b441
PP
1097 bt_component_class_put_ref(needed_comp_cls);
1098 bt_plugin_put_ref(plugin);
d94d92ac
PP
1099 return ret;
1100}
1101
b19ff26f 1102typedef void *(* plugin_borrow_comp_cls_by_index_func_t)(const bt_plugin *,
d94d92ac 1103 uint64_t);
b19ff26f 1104typedef const bt_component_class *(* spec_comp_cls_borrow_comp_cls_func_t)(
d94d92ac
PP
1105 void *);
1106
b19ff26f 1107void cmd_list_plugins_print_component_classes(const bt_plugin *plugin,
d94d92ac
PP
1108 const char *cc_type_name, uint64_t count,
1109 plugin_borrow_comp_cls_by_index_func_t borrow_comp_cls_by_index_func,
1110 spec_comp_cls_borrow_comp_cls_func_t spec_comp_cls_borrow_comp_cls_func)
1111{
1112 uint64_t i;
22e22462 1113
d94d92ac 1114 if (count == 0) {
8a7c9d06 1115 printf(" %s%s component classes%s: (none)\n",
d94d92ac 1116 bt_common_color_bold(),
8a7c9d06 1117 cc_type_name,
d94d92ac
PP
1118 bt_common_color_reset());
1119 goto end;
1120 } else {
8a7c9d06 1121 printf(" %s%s component classes%s:\n",
d94d92ac 1122 bt_common_color_bold(),
8a7c9d06 1123 cc_type_name,
d94d92ac 1124 bt_common_color_reset());
22e22462
PP
1125 }
1126
d94d92ac 1127 for (i = 0; i < count; i++) {
b19ff26f 1128 const bt_component_class *comp_class =
d94d92ac
PP
1129 spec_comp_cls_borrow_comp_cls_func(
1130 borrow_comp_cls_by_index_func(plugin, i));
22e22462 1131 const char *comp_class_name =
d94d92ac 1132 bt_component_class_get_name(comp_class);
22e22462 1133 const char *comp_class_description =
d94d92ac 1134 bt_component_class_get_description(comp_class);
4cdfc5e8 1135 bt_component_class_type type =
d94d92ac 1136 bt_component_class_get_type(comp_class);
22e22462 1137
d94d92ac 1138 printf(" ");
22e22462 1139 print_plugin_comp_cls_opt(stdout,
d94d92ac 1140 bt_plugin_get_name(plugin), comp_class_name,
22e22462 1141 type);
22e22462 1142
d94d92ac
PP
1143 if (comp_class_description) {
1144 printf(": %s", comp_class_description);
22e22462
PP
1145 }
1146
d94d92ac 1147 printf("\n");
22e22462
PP
1148 }
1149
1150end:
d94d92ac 1151 return;
22e22462
PP
1152}
1153
9009cc24
PP
1154static
1155int cmd_list_plugins(struct bt_config *cfg)
290725f7 1156{
7213a328 1157 int ret = 0;
290725f7
PP
1158 int plugins_count, component_classes_count = 0, i;
1159
22e22462 1160 printf("From the following plugin paths:\n\n");
05e21286 1161 print_value(stdout, cfg->plugin_paths, 2);
22e22462 1162 printf("\n");
290725f7
PP
1163 plugins_count = loaded_plugins->len;
1164 if (plugins_count == 0) {
7213a328 1165 printf("No plugins found.\n");
56a1cced
JG
1166 goto end;
1167 }
1168
290725f7 1169 for (i = 0; i < plugins_count; i++) {
b19ff26f 1170 const bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i);
290725f7 1171
d94d92ac
PP
1172 component_classes_count +=
1173 bt_plugin_get_source_component_class_count(plugin) +
1174 bt_plugin_get_filter_component_class_count(plugin) +
1175 bt_plugin_get_sink_component_class_count(plugin);
290725f7 1176 }
33bceaf8 1177
290725f7
PP
1178 printf("Found %s%d%s component classes in %s%d%s plugins.\n",
1179 bt_common_color_bold(),
1180 component_classes_count,
1181 bt_common_color_reset(),
1182 bt_common_color_bold(),
1183 plugins_count,
1184 bt_common_color_reset());
1185
1186 for (i = 0; i < plugins_count; i++) {
b19ff26f 1187 const bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i);
290725f7 1188
22e22462
PP
1189 printf("\n");
1190 print_plugin_info(plugin);
d94d92ac
PP
1191 cmd_list_plugins_print_component_classes(plugin, "Source",
1192 bt_plugin_get_source_component_class_count(plugin),
1193 (plugin_borrow_comp_cls_by_index_func_t)
c3dd43ec 1194 bt_plugin_borrow_source_component_class_by_index_const,
d94d92ac 1195 (spec_comp_cls_borrow_comp_cls_func_t)
707b7d35 1196 bt_component_class_source_as_component_class);
d94d92ac
PP
1197 cmd_list_plugins_print_component_classes(plugin, "Filter",
1198 bt_plugin_get_filter_component_class_count(plugin),
1199 (plugin_borrow_comp_cls_by_index_func_t)
c3dd43ec 1200 bt_plugin_borrow_filter_component_class_by_index_const,
d94d92ac 1201 (spec_comp_cls_borrow_comp_cls_func_t)
707b7d35 1202 bt_component_class_filter_as_component_class);
d94d92ac
PP
1203 cmd_list_plugins_print_component_classes(plugin, "Sink",
1204 bt_plugin_get_sink_component_class_count(plugin),
1205 (plugin_borrow_comp_cls_by_index_func_t)
c3dd43ec 1206 bt_plugin_borrow_sink_component_class_by_index_const,
d94d92ac 1207 (spec_comp_cls_borrow_comp_cls_func_t)
707b7d35 1208 bt_component_class_sink_as_component_class);
290725f7
PP
1209 }
1210
1211end:
1212 return ret;
1213}
1214
9009cc24
PP
1215static
1216int cmd_print_lttng_live_sessions(struct bt_config *cfg)
db0f160a 1217{
96e8c7e1 1218 int ret = 0;
b19ff26f
PP
1219 const bt_component_class *comp_cls = NULL;
1220 const bt_value *results = NULL;
1221 bt_value *params = NULL;
1222 const bt_value *map = NULL;
1223 const bt_value *v = NULL;
96e8c7e1
MD
1224 static const char * const plugin_name = "ctf";
1225 static const char * const comp_cls_name = "lttng-live";
4cdfc5e8 1226 static const bt_component_class_type comp_cls_type =
96e8c7e1
MD
1227 BT_COMPONENT_CLASS_TYPE_SOURCE;
1228 int64_t array_size, i;
c7eee084 1229 const char *fail_reason = NULL;
c327e427 1230 FILE *out_stream = stdout;
96e8c7e1 1231
f6ccaed9 1232 BT_ASSERT(cfg->cmd_data.print_lttng_live_sessions.url);
96e8c7e1
MD
1233 comp_cls = find_component_class(plugin_name, comp_cls_name,
1234 comp_cls_type);
1235 if (!comp_cls) {
1236 BT_LOGE("Cannot find component class: plugin-name=\"%s\", "
1237 "comp-cls-name=\"%s\", comp-cls-type=%d",
1238 plugin_name, comp_cls_name,
1239 BT_COMPONENT_CLASS_TYPE_SOURCE);
1240 fprintf(stderr, "%s%sCannot find component class %s",
1241 bt_common_color_bold(),
1242 bt_common_color_fg_red(),
1243 bt_common_color_reset());
1244 print_plugin_comp_cls_opt(stderr, plugin_name,
1245 comp_cls_name, comp_cls_type);
1246 fprintf(stderr, "\n");
1247 goto error;
1248 }
1249
05e21286 1250 params = bt_value_map_create();
96e8c7e1
MD
1251 if (!params) {
1252 goto error;
1253 }
1254
05e21286 1255 ret = bt_value_map_insert_string_entry(params, "url",
96e8c7e1
MD
1256 cfg->cmd_data.print_lttng_live_sessions.url->str);
1257 if (ret) {
1258 goto error;
1259 }
1260
f4e38e70 1261 ret = query(cfg, comp_cls, "sessions", params,
05e21286 1262 &results, &fail_reason);
c7eee084
PP
1263 if (ret) {
1264 goto failed;
96e8c7e1
MD
1265 }
1266
f6ccaed9
PP
1267 BT_ASSERT(results);
1268
96e8c7e1
MD
1269 if (!bt_value_is_array(results)) {
1270 BT_LOGE_STR("Expecting an array for sessions query.");
1271 fprintf(stderr, "%s%sUnexpected type returned by session query%s\n",
1272 bt_common_color_bold(),
1273 bt_common_color_fg_red(),
1274 bt_common_color_reset());
1275 goto error;
1276 }
1277
c327e427
PP
1278 if (cfg->cmd_data.print_lttng_live_sessions.output_path->len > 0) {
1279 out_stream =
1280 fopen(cfg->cmd_data.print_lttng_live_sessions.output_path->str,
1281 "w");
1282 if (!out_stream) {
1283 ret = -1;
1284 BT_LOGE_ERRNO("Cannot open file for writing",
1285 ": path=\"%s\"",
1286 cfg->cmd_data.print_lttng_live_sessions.output_path->str);
1287 goto end;
1288 }
1289 }
1290
07208d85 1291 array_size = bt_value_array_get_size(results);
96e8c7e1
MD
1292 for (i = 0; i < array_size; i++) {
1293 const char *url_text;
1294 int64_t timer_us, streams, clients;
1295
05e21286 1296 map = bt_value_array_borrow_element_by_index_const(results, i);
96e8c7e1
MD
1297 if (!map) {
1298 BT_LOGE_STR("Unexpected empty array entry.");
1299 goto error;
1300 }
1301 if (!bt_value_is_map(map)) {
1302 BT_LOGE_STR("Unexpected entry type.");
1303 goto error;
1304 }
1305
05e21286 1306 v = bt_value_map_borrow_entry_value_const(map, "url");
96e8c7e1
MD
1307 if (!v) {
1308 BT_LOGE_STR("Unexpected empty array \"url\" entry.");
1309 goto error;
1310 }
601b0d3c 1311 url_text = bt_value_string_get(v);
c327e427 1312 fprintf(out_stream, "%s", url_text);
05e21286 1313 v = bt_value_map_borrow_entry_value_const(map, "timer-us");
96e8c7e1
MD
1314 if (!v) {
1315 BT_LOGE_STR("Unexpected empty array \"timer-us\" entry.");
1316 goto error;
1317 }
fdd3a2da 1318 timer_us = bt_value_signed_integer_get(v);
c327e427 1319 fprintf(out_stream, " (timer = %" PRIu64 ", ", timer_us);
05e21286 1320 v = bt_value_map_borrow_entry_value_const(map, "stream-count");
96e8c7e1
MD
1321 if (!v) {
1322 BT_LOGE_STR("Unexpected empty array \"stream-count\" entry.");
1323 goto error;
1324 }
fdd3a2da 1325 streams = bt_value_signed_integer_get(v);
c327e427 1326 fprintf(out_stream, "%" PRIu64 " stream(s), ", streams);
05e21286 1327 v = bt_value_map_borrow_entry_value_const(map, "client-count");
96e8c7e1
MD
1328 if (!v) {
1329 BT_LOGE_STR("Unexpected empty array \"client-count\" entry.");
1330 goto error;
1331 }
fdd3a2da 1332 clients = bt_value_signed_integer_get(v);
c327e427 1333 fprintf(out_stream, "%" PRIu64 " client(s) connected)\n", clients);
96e8c7e1 1334 }
c7eee084
PP
1335
1336 goto end;
1337
1338failed:
1339 BT_LOGE("Failed to query for sessions: %s", fail_reason);
1340 fprintf(stderr, "%s%sFailed to request sessions: %s%s\n",
1341 bt_common_color_bold(),
1342 bt_common_color_fg_red(),
1343 fail_reason,
1344 bt_common_color_reset());
1345
1346error:
1347 ret = -1;
1348
96e8c7e1 1349end:
c5b9b441
PP
1350 bt_value_put_ref(results);
1351 bt_value_put_ref(params);
1352 bt_component_class_put_ref(comp_cls);
c327e427
PP
1353
1354 if (out_stream && out_stream != stdout) {
1355 int fclose_ret = fclose(out_stream);
1356
1357 if (fclose_ret) {
1358 BT_LOGE_ERRNO("Cannot close file stream",
1359 ": path=\"%s\"",
1360 cfg->cmd_data.print_lttng_live_sessions.output_path->str);
1361 }
1362 }
1363
bb345f58 1364 return ret;
db0f160a
PP
1365}
1366
9009cc24
PP
1367static
1368int cmd_print_ctf_metadata(struct bt_config *cfg)
05a67631
PP
1369{
1370 int ret = 0;
b19ff26f
PP
1371 const bt_component_class *comp_cls = NULL;
1372 const bt_value *results = NULL;
1373 bt_value *params = NULL;
1374 const bt_value *metadata_text_value = NULL;
05a67631 1375 const char *metadata_text = NULL;
db0f160a
PP
1376 static const char * const plugin_name = "ctf";
1377 static const char * const comp_cls_name = "fs";
4cdfc5e8 1378 static const bt_component_class_type comp_cls_type =
db0f160a 1379 BT_COMPONENT_CLASS_TYPE_SOURCE;
c7eee084 1380 const char *fail_reason = NULL;
c327e427 1381 FILE *out_stream = stdout;
db0f160a 1382
f6ccaed9 1383 BT_ASSERT(cfg->cmd_data.print_ctf_metadata.path);
db0f160a
PP
1384 comp_cls = find_component_class(plugin_name, comp_cls_name,
1385 comp_cls_type);
05a67631 1386 if (!comp_cls) {
7213a328
PP
1387 BT_LOGE("Cannot find component class: plugin-name=\"%s\", "
1388 "comp-cls-name=\"%s\", comp-cls-type=%d",
1389 plugin_name, comp_cls_name,
1390 BT_COMPONENT_CLASS_TYPE_SOURCE);
05a67631
PP
1391 fprintf(stderr, "%s%sCannot find component class %s",
1392 bt_common_color_bold(),
1393 bt_common_color_fg_red(),
1394 bt_common_color_reset());
db0f160a
PP
1395 print_plugin_comp_cls_opt(stderr, plugin_name,
1396 comp_cls_name, comp_cls_type);
05a67631
PP
1397 fprintf(stderr, "\n");
1398 ret = -1;
1399 goto end;
1400 }
1401
05e21286 1402 params = bt_value_map_create();
05a67631
PP
1403 if (!params) {
1404 ret = -1;
1405 goto end;
1406 }
1407
05e21286 1408 ret = bt_value_map_insert_string_entry(params, "path",
db0f160a 1409 cfg->cmd_data.print_ctf_metadata.path->str);
05a67631
PP
1410 if (ret) {
1411 ret = -1;
1412 goto end;
1413 }
1414
f4e38e70 1415 ret = query(cfg, comp_cls, "metadata-info",
05e21286 1416 params, &results, &fail_reason);
c7eee084
PP
1417 if (ret) {
1418 goto failed;
05a67631
PP
1419 }
1420
05e21286
PP
1421 metadata_text_value = bt_value_map_borrow_entry_value_const(results,
1422 "text");
05a67631 1423 if (!metadata_text_value) {
7213a328 1424 BT_LOGE_STR("Cannot find `text` string value in the resulting metadata info object.");
05a67631
PP
1425 ret = -1;
1426 goto end;
1427 }
1428
601b0d3c 1429 metadata_text = bt_value_string_get(metadata_text_value);
c327e427
PP
1430
1431 if (cfg->cmd_data.print_ctf_metadata.output_path->len > 0) {
1432 out_stream =
1433 fopen(cfg->cmd_data.print_ctf_metadata.output_path->str,
1434 "w");
1435 if (!out_stream) {
1436 ret = -1;
1437 BT_LOGE_ERRNO("Cannot open file for writing",
1438 ": path=\"%s\"",
1439 cfg->cmd_data.print_ctf_metadata.output_path->str);
1440 goto end;
1441 }
1442 }
1443
1444 ret = fprintf(out_stream, "%s\n", metadata_text);
1445 if (ret < 0) {
1446 BT_LOGE("Cannot write whole metadata text to output stream: "
1447 "ret=%d", ret);
b4c499ed 1448 goto end;
c327e427
PP
1449 }
1450
b4c499ed
SM
1451 ret = 0;
1452
c7eee084
PP
1453 goto end;
1454
1455failed:
1456 ret = -1;
1457 BT_LOGE("Failed to query for metadata info: %s", fail_reason);
1458 fprintf(stderr, "%s%sFailed to request metadata info: %s%s\n",
1459 bt_common_color_bold(),
1460 bt_common_color_fg_red(),
1461 fail_reason,
1462 bt_common_color_reset());
05a67631
PP
1463
1464end:
c5b9b441
PP
1465 bt_value_put_ref(results);
1466 bt_value_put_ref(params);
1467 bt_component_class_put_ref(comp_cls);
c327e427
PP
1468
1469 if (out_stream && out_stream != stdout) {
1470 int fclose_ret = fclose(out_stream);
1471
1472 if (fclose_ret) {
1473 BT_LOGE_ERRNO("Cannot close file stream",
1474 ": path=\"%s\"",
1475 cfg->cmd_data.print_ctf_metadata.output_path->str);
1476 }
1477 }
1478
bb345f58 1479 return ret;
05a67631
PP
1480}
1481
75a2cb9b
JG
1482struct port_id {
1483 char *instance_name;
1484 char *port_name;
1485};
1486
1487struct trace_range {
1488 uint64_t intersection_range_begin_ns;
1489 uint64_t intersection_range_end_ns;
1490};
1491
1492static
1493guint port_id_hash(gconstpointer v)
1494{
1495 const struct port_id *id = v;
1496
f6ccaed9
PP
1497 BT_ASSERT(id->instance_name);
1498 BT_ASSERT(id->port_name);
75a2cb9b
JG
1499
1500 return g_str_hash(id->instance_name) ^ g_str_hash(id->port_name);
1501}
1502
1503static
1504gboolean port_id_equal(gconstpointer v1, gconstpointer v2)
1505{
1506 const struct port_id *id1 = v1;
1507 const struct port_id *id2 = v2;
1508
1509 return !strcmp(id1->instance_name, id2->instance_name) &&
1510 !strcmp(id1->port_name, id2->port_name);
1511}
1512
1513static
1514void port_id_destroy(gpointer data)
1515{
1516 struct port_id *id = data;
1517
1518 free(id->instance_name);
1519 free(id->port_name);
1520 free(id);
1521}
1522
1523static
1524void trace_range_destroy(gpointer data)
1525{
1526 free(data);
1527}
1528
9009cc24
PP
1529struct cmd_run_ctx {
1530 /* Owned by this */
d94d92ac
PP
1531 GHashTable *src_components;
1532
1533 /* Owned by this */
1534 GHashTable *flt_components;
1535
1536 /* Owned by this */
1537 GHashTable *sink_components;
9009cc24
PP
1538
1539 /* Owned by this */
b19ff26f 1540 bt_graph *graph;
9009cc24
PP
1541
1542 /* Weak */
1543 struct bt_config *cfg;
1544
1545 bool connect_ports;
75a2cb9b
JG
1546
1547 bool stream_intersection_mode;
1548
1549 /*
1550 * Association of struct port_id -> struct trace_range.
1551 */
1552 GHashTable *intersections;
9009cc24
PP
1553};
1554
75a2cb9b
JG
1555/* Returns a timestamp of the form "(-)s.ns" */
1556static
1557char *s_from_ns(int64_t ns)
1558{
1559 int ret;
1560 char *s_ret = NULL;
1561 bool is_negative;
1562 int64_t ts_sec_abs, ts_nsec_abs;
1563 int64_t ts_sec = ns / NSEC_PER_SEC;
1564 int64_t ts_nsec = ns % NSEC_PER_SEC;
1565
1566 if (ts_sec >= 0 && ts_nsec >= 0) {
1567 is_negative = false;
1568 ts_sec_abs = ts_sec;
1569 ts_nsec_abs = ts_nsec;
1570 } else if (ts_sec > 0 && ts_nsec < 0) {
1571 is_negative = false;
1572 ts_sec_abs = ts_sec - 1;
1573 ts_nsec_abs = NSEC_PER_SEC + ts_nsec;
1574 } else if (ts_sec == 0 && ts_nsec < 0) {
1575 is_negative = true;
1576 ts_sec_abs = ts_sec;
1577 ts_nsec_abs = -ts_nsec;
1578 } else if (ts_sec < 0 && ts_nsec > 0) {
1579 is_negative = true;
1580 ts_sec_abs = -(ts_sec + 1);
1581 ts_nsec_abs = NSEC_PER_SEC - ts_nsec;
1582 } else if (ts_sec < 0 && ts_nsec == 0) {
1583 is_negative = true;
1584 ts_sec_abs = -ts_sec;
1585 ts_nsec_abs = ts_nsec;
1586 } else { /* (ts_sec < 0 && ts_nsec < 0) */
1587 is_negative = true;
1588 ts_sec_abs = -ts_sec;
1589 ts_nsec_abs = -ts_nsec;
1590 }
1591
1592 ret = asprintf(&s_ret, "%s%" PRId64 ".%09" PRId64,
1593 is_negative ? "-" : "", ts_sec_abs, ts_nsec_abs);
1594 if (ret < 0) {
1595 s_ret = NULL;
1596 }
1597 return s_ret;
1598}
1599
9009cc24
PP
1600static
1601int cmd_run_ctx_connect_upstream_port_to_downstream_component(
d94d92ac 1602 struct cmd_run_ctx *ctx,
b19ff26f
PP
1603 const bt_component *upstream_comp,
1604 const bt_port_output *out_upstream_port,
9009cc24 1605 struct bt_config_connection *cfg_conn)
290725f7 1606{
d94d92ac 1607 typedef uint64_t (*input_port_count_func_t)(void *);
b19ff26f 1608 typedef const bt_port_input *(*borrow_input_port_by_index_func_t)(
0d72b8c3 1609 const void *, uint64_t);
b19ff26f 1610 const bt_port *upstream_port =
0d72b8c3 1611 bt_port_output_as_port_const(out_upstream_port);
d94d92ac 1612
290725f7 1613 int ret = 0;
9009cc24 1614 GQuark downstreamp_comp_name_quark;
d94d92ac
PP
1615 void *downstream_comp;
1616 uint64_t downstream_port_count;
9009cc24 1617 uint64_t i;
d94d92ac
PP
1618 input_port_count_func_t port_count_fn;
1619 borrow_input_port_by_index_func_t port_by_index_fn;
4cdfc5e8 1620 bt_graph_status status = BT_GRAPH_STATUS_ERROR;
75a2cb9b 1621 bool insert_trimmer = false;
b19ff26f 1622 bt_value *trimmer_params = NULL;
75a2cb9b
JG
1623 char *intersection_begin = NULL;
1624 char *intersection_end = NULL;
b19ff26f
PP
1625 const bt_component_filter *trimmer = NULL;
1626 const bt_component_class_filter *trimmer_class = NULL;
1627 const bt_port_input *trimmer_input = NULL;
1628 const bt_port_output *trimmer_output = NULL;
75a2cb9b
JG
1629
1630 if (ctx->intersections &&
1631 bt_component_get_class_type(upstream_comp) ==
1632 BT_COMPONENT_CLASS_TYPE_SOURCE) {
1633 struct trace_range *range;
1634 struct port_id port_id = {
1635 .instance_name = (char *) bt_component_get_name(upstream_comp),
1636 .port_name = (char *) bt_port_get_name(upstream_port)
1637 };
1638
1639 if (!port_id.instance_name || !port_id.port_name) {
1640 goto error;
1641 }
1642
1643 range = (struct trace_range *) g_hash_table_lookup(
1644 ctx->intersections, &port_id);
1645 if (range) {
4cdfc5e8 1646 bt_value_status status;
75a2cb9b
JG
1647
1648 intersection_begin = s_from_ns(
1649 range->intersection_range_begin_ns);
1650 intersection_end = s_from_ns(
1651 range->intersection_range_end_ns);
1652 if (!intersection_begin || !intersection_end) {
1653 BT_LOGE_STR("Cannot create trimmer argument timestamp string.");
1654 goto error;
1655 }
1656
1657 insert_trimmer = true;
05e21286 1658 trimmer_params = bt_value_map_create();
75a2cb9b
JG
1659 if (!trimmer_params) {
1660 goto error;
1661 }
1662
05e21286 1663 status = bt_value_map_insert_string_entry(
07208d85 1664 trimmer_params, "begin", intersection_begin);
75a2cb9b
JG
1665 if (status != BT_VALUE_STATUS_OK) {
1666 goto error;
1667 }
05e21286 1668 status = bt_value_map_insert_string_entry(
07208d85 1669 trimmer_params,
75a2cb9b
JG
1670 "end", intersection_end);
1671 if (status != BT_VALUE_STATUS_OK) {
1672 goto error;
1673 }
1674 }
1675
d94d92ac 1676 trimmer_class = find_filter_component_class("utils", "trimmer");
75a2cb9b
JG
1677 if (!trimmer_class) {
1678 goto error;
1679 }
1680 }
9009cc24 1681
7213a328
PP
1682 BT_LOGI("Connecting upstream port to the next available downstream port: "
1683 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
1684 "downstream-comp-name=\"%s\", conn-arg=\"%s\"",
1685 upstream_port, bt_port_get_name(upstream_port),
1686 cfg_conn->downstream_comp_name->str,
1687 cfg_conn->arg->str);
9009cc24
PP
1688 downstreamp_comp_name_quark = g_quark_from_string(
1689 cfg_conn->downstream_comp_name->str);
f6ccaed9 1690 BT_ASSERT(downstreamp_comp_name_quark > 0);
d94d92ac 1691 downstream_comp = g_hash_table_lookup(ctx->flt_components,
71c7c95f 1692 GUINT_TO_POINTER(downstreamp_comp_name_quark));
d94d92ac
PP
1693 port_count_fn = (input_port_count_func_t)
1694 bt_component_filter_get_input_port_count;
1695 port_by_index_fn = (borrow_input_port_by_index_func_t)
0d72b8c3 1696 bt_component_filter_borrow_input_port_by_index_const;
d94d92ac
PP
1697
1698 if (!downstream_comp) {
1699 downstream_comp = g_hash_table_lookup(ctx->sink_components,
1700 GUINT_TO_POINTER(downstreamp_comp_name_quark));
1701 port_count_fn = (input_port_count_func_t)
1702 bt_component_sink_get_input_port_count;
1703 port_by_index_fn = (borrow_input_port_by_index_func_t)
0d72b8c3 1704 bt_component_sink_borrow_input_port_by_index_const;
d94d92ac
PP
1705 }
1706
9009cc24 1707 if (!downstream_comp) {
7213a328
PP
1708 BT_LOGE("Cannot find downstream component: comp-name=\"%s\", "
1709 "conn-arg=\"%s\"", cfg_conn->downstream_comp_name->str,
1710 cfg_conn->arg->str);
9009cc24
PP
1711 fprintf(stderr, "Cannot create connection: cannot find downstream component: %s\n",
1712 cfg_conn->arg->str);
1713 goto error;
1714 }
1715
9009cc24 1716 downstream_port_count = port_count_fn(downstream_comp);
9009cc24
PP
1717
1718 for (i = 0; i < downstream_port_count; i++) {
b19ff26f 1719 const bt_port_input *in_downstream_port =
9009cc24 1720 port_by_index_fn(downstream_comp, i);
b19ff26f 1721 const bt_port *downstream_port =
0d72b8c3 1722 bt_port_input_as_port_const(in_downstream_port);
75a2cb9b 1723 const char *upstream_port_name;
9009cc24
PP
1724 const char *downstream_port_name;
1725
f6ccaed9 1726 BT_ASSERT(downstream_port);
9009cc24 1727
75a2cb9b 1728 /* Skip port if it's already connected. */
9009cc24 1729 if (bt_port_is_connected(downstream_port)) {
3f7d4d90 1730 BT_LOGI("Skipping downstream port: already connected: "
7213a328
PP
1731 "port-addr=%p, port-name=\"%s\"",
1732 downstream_port,
1733 bt_port_get_name(downstream_port));
9009cc24
PP
1734 continue;
1735 }
1736
1737 downstream_port_name = bt_port_get_name(downstream_port);
f6ccaed9 1738 BT_ASSERT(downstream_port_name);
75a2cb9b 1739 upstream_port_name = bt_port_get_name(upstream_port);
f6ccaed9 1740 BT_ASSERT(upstream_port_name);
9009cc24 1741
75a2cb9b 1742 if (!bt_common_star_glob_match(
1974687e
MJ
1743 cfg_conn->downstream_port_glob->str, SIZE_MAX,
1744 downstream_port_name, SIZE_MAX)) {
75a2cb9b
JG
1745 continue;
1746 }
1747
1748 if (insert_trimmer) {
1749 /*
d94d92ac
PP
1750 * In order to insert the trimmer between the
1751 * two components that were being connected, we
1752 * create a connection configuration entry which
1753 * describes a connection from the trimmer's
1754 * output to the original input that was being
1755 * connected.
75a2cb9b 1756 *
d94d92ac
PP
1757 * Hence, the creation of the trimmer will cause
1758 * the graph "new port" listener to establish
1759 * all downstream connections as its output port
1760 * is connected. We will then establish the
1761 * connection between the original upstream
1762 * source and the trimmer.
75a2cb9b
JG
1763 */
1764 char *trimmer_name = NULL;
4cdfc5e8 1765 bt_graph_status graph_status;
75a2cb9b 1766
d94d92ac
PP
1767 ret = asprintf(&trimmer_name,
1768 "stream-intersection-trimmer-%s",
75a2cb9b
JG
1769 upstream_port_name);
1770 if (ret < 0) {
1771 goto error;
1772 }
1773 ret = 0;
1774
1775 ctx->connect_ports = false;
0d72b8c3 1776 graph_status = bt_graph_add_filter_component(
d94d92ac 1777 ctx->graph, trimmer_class, trimmer_name,
e874da19
PP
1778 trimmer_params, ctx->cfg->log_level,
1779 &trimmer);
75a2cb9b
JG
1780 free(trimmer_name);
1781 if (graph_status != BT_GRAPH_STATUS_OK) {
1782 goto error;
1783 }
f6ccaed9 1784 BT_ASSERT(trimmer);
75a2cb9b
JG
1785
1786 trimmer_input =
0d72b8c3 1787 bt_component_filter_borrow_input_port_by_index_const(
75a2cb9b
JG
1788 trimmer, 0);
1789 if (!trimmer_input) {
1790 goto error;
1791 }
1792 trimmer_output =
0d72b8c3 1793 bt_component_filter_borrow_output_port_by_index_const(
75a2cb9b
JG
1794 trimmer, 0);
1795 if (!trimmer_output) {
9009cc24
PP
1796 goto error;
1797 }
1798
75a2cb9b
JG
1799 /*
1800 * Replace the current downstream port by the trimmer's
1801 * upstream port.
1802 */
d94d92ac
PP
1803 in_downstream_port = trimmer_input;
1804 downstream_port =
0d72b8c3 1805 bt_port_input_as_port_const(in_downstream_port);
75a2cb9b
JG
1806 downstream_port_name = bt_port_get_name(
1807 downstream_port);
d94d92ac 1808 BT_ASSERT(downstream_port_name);
75a2cb9b
JG
1809 }
1810
1811 /* We have a winner! */
0d72b8c3 1812 status = bt_graph_connect_ports(ctx->graph,
d94d92ac
PP
1813 out_upstream_port, in_downstream_port, NULL);
1814 downstream_port = NULL;
75a2cb9b
JG
1815 switch (status) {
1816 case BT_GRAPH_STATUS_OK:
1817 break;
1818 case BT_GRAPH_STATUS_CANCELED:
1819 BT_LOGI_STR("Graph was canceled by user.");
1820 status = BT_GRAPH_STATUS_OK;
1821 break;
1822 case BT_GRAPH_STATUS_COMPONENT_REFUSES_PORT_CONNECTION:
1823 BT_LOGE("A component refused a connection to one of its ports: "
7213a328
PP
1824 "upstream-comp-addr=%p, upstream-comp-name=\"%s\", "
1825 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
1826 "downstream-comp-addr=%p, downstream-comp-name=\"%s\", "
1827 "downstream-port-addr=%p, downstream-port-name=\"%s\", "
1828 "conn-arg=\"%s\"",
1829 upstream_comp, bt_component_get_name(upstream_comp),
1830 upstream_port, bt_port_get_name(upstream_port),
1831 downstream_comp, cfg_conn->downstream_comp_name->str,
1832 downstream_port, downstream_port_name,
1833 cfg_conn->arg->str);
75a2cb9b
JG
1834 fprintf(stderr,
1835 "A component refused a connection to one of its ports (`%s` to `%s`): %s\n",
1836 bt_port_get_name(upstream_port),
1837 downstream_port_name,
1838 cfg_conn->arg->str);
1839 break;
1840 default:
1841 BT_LOGE("Cannot create connection: graph refuses to connect ports: "
1842 "upstream-comp-addr=%p, upstream-comp-name=\"%s\", "
1843 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
1844 "downstream-comp-addr=%p, downstream-comp-name=\"%s\", "
1845 "downstream-port-addr=%p, downstream-port-name=\"%s\", "
1846 "conn-arg=\"%s\"",
1847 upstream_comp, bt_component_get_name(upstream_comp),
1848 upstream_port, bt_port_get_name(upstream_port),
1849 downstream_comp, cfg_conn->downstream_comp_name->str,
1850 downstream_port, downstream_port_name,
1851 cfg_conn->arg->str);
1852 fprintf(stderr,
1853 "Cannot create connection: graph refuses to connect ports (`%s` to `%s`): %s\n",
1854 bt_port_get_name(upstream_port),
1855 downstream_port_name,
1856 cfg_conn->arg->str);
1857 goto error;
9009cc24
PP
1858 }
1859
75a2cb9b
JG
1860 BT_LOGI("Connected component ports: "
1861 "upstream-comp-addr=%p, upstream-comp-name=\"%s\", "
1862 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
1863 "downstream-comp-addr=%p, downstream-comp-name=\"%s\", "
1864 "downstream-port-addr=%p, downstream-port-name=\"%s\", "
1865 "conn-arg=\"%s\"",
1866 upstream_comp, bt_component_get_name(upstream_comp),
1867 upstream_port, bt_port_get_name(upstream_port),
1868 downstream_comp, cfg_conn->downstream_comp_name->str,
1869 downstream_port, downstream_port_name,
1870 cfg_conn->arg->str);
1871
1872 if (insert_trimmer) {
1873 /*
1874 * The first connection, from the source to the trimmer,
1875 * has been done. We now connect the trimmer to the
1876 * original downstream port.
1877 */
1878 ret = cmd_run_ctx_connect_upstream_port_to_downstream_component(
d94d92ac 1879 ctx,
0d72b8c3 1880 bt_component_filter_as_component_const(trimmer),
d94d92ac 1881 trimmer_output, cfg_conn);
75a2cb9b
JG
1882 if (ret) {
1883 goto error;
1884 }
1885 ctx->connect_ports = true;
1886 }
9009cc24 1887
53bc54cd
PP
1888 /*
1889 * We found a matching downstream port: the search is
1890 * over.
1891 */
1892 goto end;
05a67631
PP
1893 }
1894
53bc54cd
PP
1895 /* No downstream port found */
1896 BT_LOGE("Cannot create connection: cannot find a matching downstream port for upstream port: "
1897 "upstream-port-addr=%p, upstream-port-name=\"%s\", "
1898 "downstream-comp-name=\"%s\", conn-arg=\"%s\"",
1899 upstream_port, bt_port_get_name(upstream_port),
1900 cfg_conn->downstream_comp_name->str,
1901 cfg_conn->arg->str);
1902 fprintf(stderr,
1903 "Cannot create connection: cannot find a matching downstream port for upstream port `%s`: %s\n",
1904 bt_port_get_name(upstream_port), cfg_conn->arg->str);
9009cc24
PP
1905
1906error:
1907 ret = -1;
1908
1909end:
75a2cb9b
JG
1910 free(intersection_begin);
1911 free(intersection_end);
c5b9b441
PP
1912 BT_VALUE_PUT_REF_AND_RESET(trimmer_params);
1913 BT_COMPONENT_CLASS_FILTER_PUT_REF_AND_RESET(trimmer_class);
1914 BT_COMPONENT_FILTER_PUT_REF_AND_RESET(trimmer);
9009cc24
PP
1915 return ret;
1916}
1917
1918static
1919int cmd_run_ctx_connect_upstream_port(struct cmd_run_ctx *ctx,
b19ff26f 1920 const bt_port_output *upstream_port)
9009cc24
PP
1921{
1922 int ret = 0;
1923 const char *upstream_port_name;
1924 const char *upstream_comp_name;
b19ff26f 1925 const bt_component *upstream_comp = NULL;
9009cc24
PP
1926 size_t i;
1927
f6ccaed9
PP
1928 BT_ASSERT(ctx);
1929 BT_ASSERT(upstream_port);
d94d92ac 1930 upstream_port_name = bt_port_get_name(
0d72b8c3 1931 bt_port_output_as_port_const(upstream_port));
f6ccaed9 1932 BT_ASSERT(upstream_port_name);
0d72b8c3
PP
1933 upstream_comp = bt_port_borrow_component_const(
1934 bt_port_output_as_port_const(upstream_port));
9009cc24 1935 if (!upstream_comp) {
7213a328
PP
1936 BT_LOGW("Upstream port to connect is not part of a component: "
1937 "port-addr=%p, port-name=\"%s\"",
1938 upstream_port, upstream_port_name);
98ecef32
MD
1939 ret = -1;
1940 goto end;
33bceaf8
JG
1941 }
1942
9009cc24 1943 upstream_comp_name = bt_component_get_name(upstream_comp);
f6ccaed9 1944 BT_ASSERT(upstream_comp_name);
7213a328
PP
1945 BT_LOGI("Connecting upstream port: comp-addr=%p, comp-name=\"%s\", "
1946 "port-addr=%p, port-name=\"%s\"",
1947 upstream_comp, upstream_comp_name,
1948 upstream_port, upstream_port_name);
9009cc24
PP
1949
1950 for (i = 0; i < ctx->cfg->cmd_data.run.connections->len; i++) {
1951 struct bt_config_connection *cfg_conn =
1952 g_ptr_array_index(
1953 ctx->cfg->cmd_data.run.connections, i);
1954
1955 if (strcmp(cfg_conn->upstream_comp_name->str,
75a2cb9b
JG
1956 upstream_comp_name)) {
1957 continue;
1958 }
1959
1960 if (!bt_common_star_glob_match(
1961 cfg_conn->upstream_port_glob->str,
1974687e 1962 SIZE_MAX, upstream_port_name, SIZE_MAX)) {
75a2cb9b
JG
1963 continue;
1964 }
1965
1966 ret = cmd_run_ctx_connect_upstream_port_to_downstream_component(
1967 ctx, upstream_comp, upstream_port, cfg_conn);
1968 if (ret) {
1969 BT_LOGE("Cannot connect upstream port: "
1970 "port-addr=%p, port-name=\"%s\"",
1971 upstream_port,
1972 upstream_port_name);
1973 fprintf(stderr,
1974 "Cannot connect port `%s` of component `%s` to a downstream port: %s\n",
1975 upstream_port_name,
1976 upstream_comp_name,
1977 cfg_conn->arg->str);
1978 goto error;
9009cc24 1979 }
75a2cb9b 1980 goto end;
9009cc24
PP
1981 }
1982
7213a328
PP
1983 BT_LOGE("Cannot connect upstream port: port does not match any connection argument: "
1984 "port-addr=%p, port-name=\"%s\"", upstream_port,
1985 upstream_port_name);
9009cc24
PP
1986 fprintf(stderr,
1987 "Cannot create connection: upstream port `%s` does not match any connection\n",
7213a328 1988 upstream_port_name);
9009cc24
PP
1989
1990error:
1991 ret = -1;
1992
1993end:
9009cc24
PP
1994 return ret;
1995}
1996
1997static
8cc56726
SM
1998bt_graph_listener_status
1999graph_output_port_added_listener(struct cmd_run_ctx *ctx,
b19ff26f 2000 const bt_port_output *out_port)
9009cc24 2001{
b19ff26f
PP
2002 const bt_component *comp;
2003 const bt_port *port = bt_port_output_as_port_const(out_port);
8cc56726 2004 bt_graph_listener_status ret = BT_GRAPH_LISTENER_STATUS_OK;
9009cc24 2005
0d72b8c3 2006 comp = bt_port_borrow_component_const(port);
e12720c0
PP
2007 BT_LOGI("Port added to a graph's component: comp-addr=%p, "
2008 "comp-name=\"%s\", port-addr=%p, port-name=\"%s\"",
2009 comp, comp ? bt_component_get_name(comp) : "",
7213a328 2010 port, bt_port_get_name(port));
36712f1d
PP
2011
2012 if (!ctx->connect_ports) {
2013 goto end;
2014 }
2015
e12720c0
PP
2016 if (!comp) {
2017 BT_LOGW_STR("Port has no component.");
56a1cced
JG
2018 goto end;
2019 }
7c7c0433 2020
e12720c0
PP
2021 if (bt_port_is_connected(port)) {
2022 BT_LOGW_STR("Port is already connected.");
7c7c0433
JG
2023 goto end;
2024 }
2025
d94d92ac 2026 if (cmd_run_ctx_connect_upstream_port(ctx, out_port)) {
7213a328 2027 BT_LOGF_STR("Cannot connect upstream port.");
9009cc24 2028 fprintf(stderr, "Added port could not be connected: aborting\n");
8cc56726
SM
2029 ret = BT_GRAPH_LISTENER_STATUS_ERROR;
2030 goto end;
9009cc24
PP
2031 }
2032
2033end:
8cc56726 2034 return ret;
9009cc24
PP
2035}
2036
2037static
8cc56726 2038bt_graph_listener_status graph_source_output_port_added_listener(
b19ff26f
PP
2039 const bt_component_source *component,
2040 const bt_port_output *port, void *data)
9009cc24 2041{
8cc56726 2042 return graph_output_port_added_listener(data, port);
9009cc24
PP
2043}
2044
2045static
8cc56726 2046bt_graph_listener_status graph_filter_output_port_added_listener(
b19ff26f
PP
2047 const bt_component_filter *component,
2048 const bt_port_output *port, void *data)
9009cc24 2049{
8cc56726 2050 return graph_output_port_added_listener(data, port);
9009cc24
PP
2051}
2052
2053static
2054void cmd_run_ctx_destroy(struct cmd_run_ctx *ctx)
2055{
2056 if (!ctx) {
2057 return;
2058 }
2059
d94d92ac
PP
2060 if (ctx->src_components) {
2061 g_hash_table_destroy(ctx->src_components);
2062 ctx->src_components = NULL;
2063 }
2064
2065 if (ctx->flt_components) {
2066 g_hash_table_destroy(ctx->flt_components);
2067 ctx->flt_components = NULL;
2068 }
2069
2070 if (ctx->sink_components) {
2071 g_hash_table_destroy(ctx->sink_components);
2072 ctx->sink_components = NULL;
9009cc24
PP
2073 }
2074
75a2cb9b
JG
2075 if (ctx->intersections) {
2076 g_hash_table_destroy(ctx->intersections);
a5302548 2077 ctx->intersections = NULL;
75a2cb9b
JG
2078 }
2079
c5b9b441 2080 BT_GRAPH_PUT_REF_AND_RESET(ctx->graph);
5401f780 2081 the_graph = NULL;
9009cc24
PP
2082 ctx->cfg = NULL;
2083}
2084
2085static
2086int cmd_run_ctx_init(struct cmd_run_ctx *ctx, struct bt_config *cfg)
2087{
2088 int ret = 0;
4cdfc5e8 2089 bt_graph_status status;
9009cc24
PP
2090
2091 ctx->cfg = cfg;
2092 ctx->connect_ports = false;
d94d92ac 2093 ctx->src_components = g_hash_table_new_full(g_direct_hash,
398454ed 2094 g_direct_equal, NULL, (GDestroyNotify) bt_object_put_ref);
d94d92ac
PP
2095 if (!ctx->src_components) {
2096 goto error;
2097 }
2098
2099 ctx->flt_components = g_hash_table_new_full(g_direct_hash,
398454ed 2100 g_direct_equal, NULL, (GDestroyNotify) bt_object_put_ref);
d94d92ac
PP
2101 if (!ctx->flt_components) {
2102 goto error;
2103 }
2104
2105 ctx->sink_components = g_hash_table_new_full(g_direct_hash,
398454ed 2106 g_direct_equal, NULL, (GDestroyNotify) bt_object_put_ref);
d94d92ac 2107 if (!ctx->sink_components) {
9009cc24
PP
2108 goto error;
2109 }
2110
75a2cb9b
JG
2111 if (cfg->cmd_data.run.stream_intersection_mode) {
2112 ctx->stream_intersection_mode = true;
2113 ctx->intersections = g_hash_table_new_full(port_id_hash,
2114 port_id_equal, port_id_destroy, trace_range_destroy);
2115 if (!ctx->intersections) {
2116 goto error;
2117 }
2118 }
2119
0d72b8c3 2120 ctx->graph = bt_graph_create();
9009cc24
PP
2121 if (!ctx->graph) {
2122 goto error;
2123 }
2124
5401f780 2125 the_graph = ctx->graph;
0d72b8c3 2126 status = bt_graph_add_source_component_output_port_added_listener(
d94d92ac
PP
2127 ctx->graph, graph_source_output_port_added_listener, NULL, ctx,
2128 NULL);
2129 if (status != BT_GRAPH_STATUS_OK) {
0d107cdd 2130 BT_LOGE_STR("Cannot add \"port added\" listener to graph.");
9009cc24
PP
2131 goto error;
2132 }
2133
0d72b8c3 2134 status = bt_graph_add_filter_component_output_port_added_listener(
d94d92ac
PP
2135 ctx->graph, graph_filter_output_port_added_listener, NULL, ctx,
2136 NULL);
2137 if (status != BT_GRAPH_STATUS_OK) {
2138 BT_LOGE_STR("Cannot add \"port added\" listener to graph.");
9009cc24
PP
2139 goto error;
2140 }
2141
2142 goto end;
2143
2144error:
2145 cmd_run_ctx_destroy(ctx);
2146 ret = -1;
2147
2148end:
2149 return ret;
2150}
2151
75a2cb9b
JG
2152static
2153int set_stream_intersections(struct cmd_run_ctx *ctx,
2154 struct bt_config_component *cfg_comp,
b19ff26f 2155 const bt_component_class_source *src_comp_cls)
75a2cb9b
JG
2156{
2157 int ret = 0;
2158 uint64_t trace_idx;
2159 int64_t trace_count;
75a2cb9b 2160 const char *path = NULL;
b19ff26f
PP
2161 const bt_value *query_result = NULL;
2162 const bt_value *trace_info = NULL;
2163 const bt_value *intersection_range = NULL;
2164 const bt_value *intersection_begin = NULL;
2165 const bt_value *intersection_end = NULL;
b19ff26f
PP
2166 const bt_value *stream_infos = NULL;
2167 const bt_value *stream_info = NULL;
75a2cb9b
JG
2168 struct port_id *port_id = NULL;
2169 struct trace_range *trace_range = NULL;
c7eee084 2170 const char *fail_reason = NULL;
b19ff26f 2171 const bt_component_class *comp_cls =
0d72b8c3 2172 bt_component_class_source_as_component_class_const(src_comp_cls);
75a2cb9b 2173
f4e38e70 2174 ret = query(ctx->cfg, comp_cls, "trace-info",
f280892e 2175 cfg_comp->params, &query_result,
c7eee084
PP
2176 &fail_reason);
2177 if (ret) {
2178 BT_LOGD("Component class does not support the `trace-info` query: %s: "
2179 "comp-class-name=\"%s\"", fail_reason,
75a2cb9b
JG
2180 bt_component_class_get_name(comp_cls));
2181 ret = -1;
2182 goto error;
2183 }
2184
f6ccaed9
PP
2185 BT_ASSERT(query_result);
2186
75a2cb9b
JG
2187 if (!bt_value_is_array(query_result)) {
2188 BT_LOGD("Unexpected format of \'trace-info\' query result: "
2189 "component-class-name=%s",
2190 bt_component_class_get_name(comp_cls));
2191 ret = -1;
2192 goto error;
2193 }
2194
07208d85 2195 trace_count = bt_value_array_get_size(query_result);
75a2cb9b
JG
2196 if (trace_count < 0) {
2197 ret = -1;
2198 goto error;
2199 }
2200
2201 for (trace_idx = 0; trace_idx < trace_count; trace_idx++) {
2202 int64_t begin, end;
2203 uint64_t stream_idx;
2204 int64_t stream_count;
2205
05e21286 2206 trace_info = bt_value_array_borrow_element_by_index_const(
07208d85 2207 query_result, trace_idx);
75a2cb9b
JG
2208 if (!trace_info || !bt_value_is_map(trace_info)) {
2209 ret = -1;
2210 BT_LOGD_STR("Cannot retrieve trace from query result.");
2211 goto error;
2212 }
2213
05e21286
PP
2214 intersection_range = bt_value_map_borrow_entry_value_const(
2215 trace_info, "intersection-range-ns");
75a2cb9b
JG
2216 if (!intersection_range) {
2217 ret = -1;
2218 BT_LOGD_STR("Cannot retrieve \'intersetion-range-ns\' field from query result.");
2219 goto error;
2220 }
2221
05e21286
PP
2222 intersection_begin = bt_value_map_borrow_entry_value_const(intersection_range,
2223 "begin");
75a2cb9b
JG
2224 if (!intersection_begin) {
2225 ret = -1;
2226 BT_LOGD_STR("Cannot retrieve intersection-range-ns \'begin\' field from query result.");
2227 goto error;
2228 }
2229
05e21286
PP
2230 intersection_end = bt_value_map_borrow_entry_value_const(intersection_range,
2231 "end");
75a2cb9b
JG
2232 if (!intersection_end) {
2233 ret = -1;
2234 BT_LOGD_STR("Cannot retrieve intersection-range-ns \'end\' field from query result.");
2235 goto error;
2236 }
2237
fdd3a2da
PP
2238 begin = bt_value_signed_integer_get(intersection_begin);
2239 end = bt_value_signed_integer_get(intersection_end);
75a2cb9b
JG
2240
2241 if (begin < 0 || end < 0 || end < begin) {
2242 BT_LOGW("Invalid trace stream intersection values: "
2243 "intersection-range-ns:begin=%" PRId64
2244 ", intersection-range-ns:end=%" PRId64,
2245 begin, end);
2246 ret = -1;
2247 goto error;
2248 }
2249
05e21286
PP
2250 stream_infos = bt_value_map_borrow_entry_value_const(trace_info,
2251 "streams");
75a2cb9b
JG
2252 if (!stream_infos || !bt_value_is_array(stream_infos)) {
2253 ret = -1;
e07ab7c8 2254 BT_LOGD_STR("Cannot retrieve stream information from trace in query result.");
75a2cb9b
JG
2255 goto error;
2256 }
2257
07208d85 2258 stream_count = bt_value_array_get_size(stream_infos);
75a2cb9b
JG
2259 if (stream_count < 0) {
2260 ret = -1;
2261 goto error;
2262 }
2263
75a2cb9b 2264 for (stream_idx = 0; stream_idx < stream_count; stream_idx++) {
a38d7650 2265 const bt_value *port_name;
75a2cb9b
JG
2266
2267 port_id = g_new0(struct port_id, 1);
2268 if (!port_id) {
2269 ret = -1;
2270 BT_LOGE_STR("Cannot allocate memory for port_id structure.");
2271 goto error;
2272 }
2273 port_id->instance_name = strdup(cfg_comp->instance_name->str);
2274 if (!port_id->instance_name) {
2275 ret = -1;
2276 BT_LOGE_STR("Cannot allocate memory for port_id component instance name.");
2277 goto error;
2278 }
2279
2280 trace_range = g_new0(struct trace_range, 1);
2281 if (!trace_range) {
2282 ret = -1;
2283 BT_LOGE_STR("Cannot allocate memory for trace_range structure.");
2284 goto error;
2285 }
2286 trace_range->intersection_range_begin_ns = begin;
2287 trace_range->intersection_range_end_ns = end;
2288
05e21286 2289 stream_info = bt_value_array_borrow_element_by_index_const(
07208d85 2290 stream_infos, stream_idx);
75a2cb9b
JG
2291 if (!stream_info || !bt_value_is_map(stream_info)) {
2292 ret = -1;
3f7d4d90 2293 BT_LOGE_STR("Cannot retrieve stream informations from trace in query result.");
75a2cb9b
JG
2294 goto error;
2295 }
2296
a38d7650
SM
2297 port_name = bt_value_map_borrow_entry_value_const(stream_info, "port-name");
2298 if (!port_name || !bt_value_is_string(port_name)) {
75a2cb9b 2299 ret = -1;
3f7d4d90 2300 BT_LOGE_STR("Cannot retrieve port name in query result.");
75a2cb9b
JG
2301 goto error;
2302 }
2303
a38d7650 2304 port_id->port_name = g_strdup(bt_value_string_get(port_name));
75a2cb9b
JG
2305 if (!port_id->port_name) {
2306 ret = -1;
2307 BT_LOGE_STR("Cannot allocate memory for port_id port_name.");
2308 goto error;
2309 }
2310
2311 BT_LOGD("Inserting stream intersection ");
2312
1ddeea34 2313 g_hash_table_insert(ctx->intersections, port_id, trace_range);
75a2cb9b
JG
2314
2315 port_id = NULL;
2316 trace_range = NULL;
75a2cb9b 2317 }
75a2cb9b
JG
2318 }
2319
2320 goto end;
2321
2322error:
2323 fprintf(stderr, "%s%sCannot determine stream intersection of trace at path \'%s\'.%s\n",
2324 bt_common_color_bold(),
2325 bt_common_color_fg_yellow(),
2326 path ? path : "(unknown)",
2327 bt_common_color_reset());
2328end:
c5b9b441 2329 bt_value_put_ref(query_result);
75a2cb9b
JG
2330 g_free(port_id);
2331 g_free(trace_range);
2332 return ret;
2333}
2334
9009cc24
PP
2335static
2336int cmd_run_ctx_create_components_from_config_components(
2337 struct cmd_run_ctx *ctx, GPtrArray *cfg_components)
2338{
2339 size_t i;
0d72b8c3
PP
2340 const void *comp_cls = NULL;
2341 const void *comp = NULL;
9009cc24
PP
2342 int ret = 0;
2343
2344 for (i = 0; i < cfg_components->len; i++) {
2345 struct bt_config_component *cfg_comp =
2346 g_ptr_array_index(cfg_components, i);
2347 GQuark quark;
2348
d94d92ac
PP
2349 switch (cfg_comp->type) {
2350 case BT_COMPONENT_CLASS_TYPE_SOURCE:
2351 comp_cls = find_source_component_class(
2352 cfg_comp->plugin_name->str,
2353 cfg_comp->comp_cls_name->str);
2354 break;
2355 case BT_COMPONENT_CLASS_TYPE_FILTER:
2356 comp_cls = find_filter_component_class(
2357 cfg_comp->plugin_name->str,
2358 cfg_comp->comp_cls_name->str);
2359 break;
2360 case BT_COMPONENT_CLASS_TYPE_SINK:
2361 comp_cls = find_sink_component_class(
2362 cfg_comp->plugin_name->str,
2363 cfg_comp->comp_cls_name->str);
2364 break;
2365 default:
2366 abort();
2367 }
2368
9009cc24 2369 if (!comp_cls) {
7213a328
PP
2370 BT_LOGE("Cannot find component class: plugin-name=\"%s\", "
2371 "comp-cls-name=\"%s\", comp-cls-type=%d",
2372 cfg_comp->plugin_name->str,
2373 cfg_comp->comp_cls_name->str,
2374 cfg_comp->type);
9009cc24
PP
2375 fprintf(stderr, "%s%sCannot find component class %s",
2376 bt_common_color_bold(),
2377 bt_common_color_fg_red(),
2378 bt_common_color_reset());
2379 print_plugin_comp_cls_opt(stderr,
2380 cfg_comp->plugin_name->str,
2381 cfg_comp->comp_cls_name->str,
2382 cfg_comp->type);
2383 fprintf(stderr, "\n");
2384 goto error;
2385 }
2386
29da2ffc
PP
2387 BT_ASSERT(cfg_comp->log_level >= BT_LOG_VERBOSE);
2388
d94d92ac
PP
2389 switch (cfg_comp->type) {
2390 case BT_COMPONENT_CLASS_TYPE_SOURCE:
0d72b8c3 2391 ret = bt_graph_add_source_component(ctx->graph,
d94d92ac 2392 comp_cls, cfg_comp->instance_name->str,
29da2ffc 2393 cfg_comp->params, cfg_comp->log_level,
d94d92ac
PP
2394 (void *) &comp);
2395 break;
2396 case BT_COMPONENT_CLASS_TYPE_FILTER:
0d72b8c3 2397 ret = bt_graph_add_filter_component(ctx->graph,
d94d92ac 2398 comp_cls, cfg_comp->instance_name->str,
29da2ffc 2399 cfg_comp->params, cfg_comp->log_level,
d94d92ac
PP
2400 (void *) &comp);
2401 break;
2402 case BT_COMPONENT_CLASS_TYPE_SINK:
0d72b8c3 2403 ret = bt_graph_add_sink_component(ctx->graph,
d94d92ac 2404 comp_cls, cfg_comp->instance_name->str,
29da2ffc 2405 cfg_comp->params, cfg_comp->log_level,
d94d92ac
PP
2406 (void *) &comp);
2407 break;
2408 default:
2409 abort();
2410 }
2411
36712f1d 2412 if (ret) {
7213a328 2413 BT_LOGE("Cannot create component: plugin-name=\"%s\", "
32e87ceb 2414 "comp-cls-name=\"%s\", comp-cls-type=%d, "
7213a328
PP
2415 "comp-name=\"%s\"",
2416 cfg_comp->plugin_name->str,
2417 cfg_comp->comp_cls_name->str,
2418 cfg_comp->type, cfg_comp->instance_name->str);
9009cc24
PP
2419 fprintf(stderr, "%s%sCannot create component `%s`%s\n",
2420 bt_common_color_bold(),
2421 bt_common_color_fg_red(),
2422 cfg_comp->instance_name->str,
2423 bt_common_color_reset());
2424 goto error;
2425 }
2426
75a2cb9b
JG
2427 if (ctx->stream_intersection_mode &&
2428 cfg_comp->type == BT_COMPONENT_CLASS_TYPE_SOURCE) {
2429 ret = set_stream_intersections(ctx, cfg_comp, comp_cls);
2430 if (ret) {
2431 goto error;
2432 }
2433 }
2434
7213a328
PP
2435 BT_LOGI("Created and inserted component: comp-addr=%p, comp-name=\"%s\"",
2436 comp, cfg_comp->instance_name->str);
9009cc24 2437 quark = g_quark_from_string(cfg_comp->instance_name->str);
f6ccaed9 2438 BT_ASSERT(quark > 0);
d94d92ac
PP
2439
2440 switch (cfg_comp->type) {
2441 case BT_COMPONENT_CLASS_TYPE_SOURCE:
2442 g_hash_table_insert(ctx->src_components,
0d72b8c3 2443 GUINT_TO_POINTER(quark), (void *) comp);
d94d92ac
PP
2444 break;
2445 case BT_COMPONENT_CLASS_TYPE_FILTER:
2446 g_hash_table_insert(ctx->flt_components,
0d72b8c3 2447 GUINT_TO_POINTER(quark), (void *) comp);
d94d92ac
PP
2448 break;
2449 case BT_COMPONENT_CLASS_TYPE_SINK:
2450 g_hash_table_insert(ctx->sink_components,
0d72b8c3 2451 GUINT_TO_POINTER(quark), (void *) comp);
d94d92ac
PP
2452 break;
2453 default:
2454 abort();
2455 }
2456
9009cc24 2457 comp = NULL;
65300d60 2458 BT_OBJECT_PUT_REF_AND_RESET(comp_cls);
9009cc24
PP
2459 }
2460
2461 goto end;
2462
2463error:
2464 ret = -1;
2465
2466end:
65300d60
PP
2467 bt_object_put_ref(comp);
2468 bt_object_put_ref(comp_cls);
9009cc24
PP
2469 return ret;
2470}
56a1cced 2471
9009cc24
PP
2472static
2473int cmd_run_ctx_create_components(struct cmd_run_ctx *ctx)
2474{
2475 int ret = 0;
2476
2477 /*
2478 * Make sure that, during this phase, our graph's "port added"
2479 * listener does not connect ports while we are creating the
2480 * components because we have a special, initial phase for
2481 * this.
2482 */
2483 ctx->connect_ports = false;
2484
2485 ret = cmd_run_ctx_create_components_from_config_components(
2486 ctx, ctx->cfg->cmd_data.run.sources);
2487 if (ret) {
7c7c0433 2488 ret = -1;
2e339de1
JG
2489 goto end;
2490 }
2491
9009cc24
PP
2492 ret = cmd_run_ctx_create_components_from_config_components(
2493 ctx, ctx->cfg->cmd_data.run.filters);
6c2f3ee5 2494 if (ret) {
290725f7 2495 ret = -1;
fec2a9f2
JG
2496 goto end;
2497 }
78586d8a 2498
9009cc24
PP
2499 ret = cmd_run_ctx_create_components_from_config_components(
2500 ctx, ctx->cfg->cmd_data.run.sinks);
2501 if (ret) {
2502 ret = -1;
2503 goto end;
2504 }
2505
2506end:
2507 return ret;
2508}
2509
0d72b8c3 2510typedef uint64_t (*output_port_count_func_t)(const void *);
b19ff26f 2511typedef const bt_port_output *(*borrow_output_port_by_index_func_t)(
0d72b8c3 2512 const void *, uint64_t);
d94d92ac 2513
9009cc24
PP
2514static
2515int cmd_run_ctx_connect_comp_ports(struct cmd_run_ctx *ctx,
d94d92ac
PP
2516 void *comp, output_port_count_func_t port_count_fn,
2517 borrow_output_port_by_index_func_t port_by_index_fn)
9009cc24
PP
2518{
2519 int ret = 0;
d94d92ac 2520 uint64_t count;
9009cc24
PP
2521 uint64_t i;
2522
2523 count = port_count_fn(comp);
9009cc24
PP
2524
2525 for (i = 0; i < count; i++) {
b19ff26f 2526 const bt_port_output *upstream_port = port_by_index_fn(comp, i);
9009cc24 2527
f6ccaed9 2528 BT_ASSERT(upstream_port);
9009cc24 2529 ret = cmd_run_ctx_connect_upstream_port(ctx, upstream_port);
9009cc24
PP
2530 if (ret) {
2531 goto end;
2532 }
2533 }
2534
2535end:
2536 return ret;
2537}
2538
2539static
2540int cmd_run_ctx_connect_ports(struct cmd_run_ctx *ctx)
2541{
2542 int ret = 0;
2543 GHashTableIter iter;
2544 gpointer g_name_quark, g_comp;
2545
2546 ctx->connect_ports = true;
d94d92ac 2547 g_hash_table_iter_init(&iter, ctx->src_components);
9009cc24
PP
2548
2549 while (g_hash_table_iter_next(&iter, &g_name_quark, &g_comp)) {
d94d92ac
PP
2550 ret = cmd_run_ctx_connect_comp_ports(ctx, g_comp,
2551 (output_port_count_func_t)
2552 bt_component_source_get_output_port_count,
2553 (borrow_output_port_by_index_func_t)
0d72b8c3 2554 bt_component_source_borrow_output_port_by_index_const);
d94d92ac
PP
2555 if (ret) {
2556 goto end;
9009cc24 2557 }
d94d92ac
PP
2558 }
2559
2560 g_hash_table_iter_init(&iter, ctx->flt_components);
9009cc24 2561
d94d92ac
PP
2562 while (g_hash_table_iter_next(&iter, &g_name_quark, &g_comp)) {
2563 ret = cmd_run_ctx_connect_comp_ports(ctx, g_comp,
2564 (output_port_count_func_t)
2565 bt_component_filter_get_output_port_count,
2566 (borrow_output_port_by_index_func_t)
0d72b8c3 2567 bt_component_filter_borrow_output_port_by_index_const);
9009cc24
PP
2568 if (ret) {
2569 goto end;
2570 }
2571 }
2572
2573end:
2574 return ret;
2575}
2576
fd948396 2577static inline
4cdfc5e8 2578const char *bt_graph_status_str(bt_graph_status status)
fd948396
PP
2579{
2580 switch (status) {
fd948396
PP
2581 case BT_GRAPH_STATUS_OK:
2582 return "BT_GRAPH_STATUS_OK";
d94d92ac
PP
2583 case BT_GRAPH_STATUS_END:
2584 return "BT_GRAPH_STATUS_END";
2585 case BT_GRAPH_STATUS_AGAIN:
2586 return "BT_GRAPH_STATUS_AGAIN";
2587 case BT_GRAPH_STATUS_COMPONENT_REFUSES_PORT_CONNECTION:
2588 return "BT_GRAPH_STATUS_COMPONENT_REFUSES_PORT_CONNECTION";
2589 case BT_GRAPH_STATUS_CANCELED:
2590 return "BT_GRAPH_STATUS_CANCELED";
fd948396
PP
2591 case BT_GRAPH_STATUS_ERROR:
2592 return "BT_GRAPH_STATUS_ERROR";
d94d92ac
PP
2593 case BT_GRAPH_STATUS_NOMEM:
2594 return "BT_GRAPH_STATUS_NOMEM";
fd948396
PP
2595 default:
2596 return "(unknown)";
2597 }
2598}
2599
9009cc24
PP
2600static
2601int cmd_run(struct bt_config *cfg)
2602{
2603 int ret = 0;
2604 struct cmd_run_ctx ctx = { 0 };
2605
9009cc24
PP
2606 /* Initialize the command's context and the graph object */
2607 if (cmd_run_ctx_init(&ctx, cfg)) {
7213a328 2608 BT_LOGE_STR("Cannot initialize the command's context.");
9009cc24
PP
2609 fprintf(stderr, "Cannot initialize the command's context\n");
2610 goto error;
2611 }
2612
cc308374
PP
2613 if (canceled) {
2614 BT_LOGI_STR("Canceled by user before creating components.");
2615 goto error;
2616 }
2617
2618 BT_LOGI_STR("Creating components.");
2619
9009cc24
PP
2620 /* Create the requested component instances */
2621 if (cmd_run_ctx_create_components(&ctx)) {
7213a328 2622 BT_LOGE_STR("Cannot create components.");
9009cc24
PP
2623 fprintf(stderr, "Cannot create components\n");
2624 goto error;
2625 }
2626
cc308374
PP
2627 if (canceled) {
2628 BT_LOGI_STR("Canceled by user before connecting components.");
2629 goto error;
2630 }
2631
2632 BT_LOGI_STR("Connecting components.");
2633
9009cc24
PP
2634 /* Connect the initially visible component ports */
2635 if (cmd_run_ctx_connect_ports(&ctx)) {
7213a328 2636 BT_LOGE_STR("Cannot connect initial component ports.");
9009cc24
PP
2637 fprintf(stderr, "Cannot connect initial component ports\n");
2638 goto error;
2639 }
2640
5401f780 2641 if (canceled) {
cc308374
PP
2642 BT_LOGI_STR("Canceled by user before running the graph.");
2643 goto error;
5401f780
PP
2644 }
2645
7213a328
PP
2646 BT_LOGI_STR("Running the graph.");
2647
9009cc24 2648 /* Run the graph */
fec2a9f2 2649 while (true) {
4cdfc5e8 2650 bt_graph_status graph_status = bt_graph_run(ctx.graph);
61ddbc8a 2651
5669a3e7
PP
2652 /*
2653 * Reset console in case something messed with console
2654 * codes during the graph's execution.
2655 */
2656 printf("%s", bt_common_color_reset());
2657 fflush(stdout);
2658 fprintf(stderr, "%s", bt_common_color_reset());
0d72b8c3 2659 BT_LOGV("bt_graph_run() returned: status=%s",
fd948396
PP
2660 bt_graph_status_str(graph_status));
2661
61ddbc8a 2662 switch (graph_status) {
9009cc24
PP
2663 case BT_GRAPH_STATUS_OK:
2664 break;
5401f780 2665 case BT_GRAPH_STATUS_CANCELED:
fd948396 2666 BT_LOGI_STR("Graph was canceled by user.");
5401f780 2667 goto error;
61ddbc8a 2668 case BT_GRAPH_STATUS_AGAIN:
0d72b8c3 2669 if (bt_graph_is_canceled(ctx.graph)) {
fd948396 2670 BT_LOGI_STR("Graph was canceled by user.");
5401f780
PP
2671 goto error;
2672 }
2673
9009cc24 2674 if (cfg->cmd_data.run.retry_duration_us > 0) {
7213a328
PP
2675 BT_LOGV("Got BT_GRAPH_STATUS_AGAIN: sleeping: "
2676 "time-us=%" PRIu64,
2677 cfg->cmd_data.run.retry_duration_us);
2678
9009cc24 2679 if (usleep(cfg->cmd_data.run.retry_duration_us)) {
0d72b8c3 2680 if (bt_graph_is_canceled(ctx.graph)) {
cfa4637b
PP
2681 BT_LOGI_STR("Graph was canceled by user.");
2682 goto error;
2683 }
9009cc24
PP
2684 }
2685 }
78586d8a 2686 break;
d94d92ac 2687 case BT_GRAPH_STATUS_END:
fec2a9f2
JG
2688 goto end;
2689 default:
7213a328
PP
2690 BT_LOGE_STR("Graph failed to complete successfully");
2691 fprintf(stderr, "Graph failed to complete successfully\n");
9009cc24 2692 goto error;
78586d8a 2693 }
fec2a9f2 2694 }
290725f7 2695
9009cc24
PP
2696 goto end;
2697
2698error:
2699 if (ret == 0) {
2700 ret = -1;
2701 }
2702
11e1d048 2703end:
9009cc24 2704 cmd_run_ctx_destroy(&ctx);
290725f7
PP
2705 return ret;
2706}
2707
9009cc24
PP
2708static
2709void warn_command_name_and_directory_clash(struct bt_config *cfg)
290725f7 2710{
9009cc24
PP
2711 const char *env_clash;
2712
290725f7
PP
2713 if (!cfg->command_name) {
2714 return;
2715 }
2716
9009cc24
PP
2717 env_clash = getenv(ENV_BABELTRACE_WARN_COMMAND_NAME_DIRECTORY_CLASH);
2718 if (env_clash && strcmp(env_clash, "0") == 0) {
2719 return;
2720 }
2721
290725f7
PP
2722 if (g_file_test(cfg->command_name,
2723 G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
2724 fprintf(stderr, "\nNOTE: The `%s` command was executed. If you meant to convert a\n",
2725 cfg->command_name);
2726 fprintf(stderr, "trace located in the local `%s` directory, please use:\n",
2727 cfg->command_name);
2728 fprintf(stderr, "\n");
ec2c5e50 2729 fprintf(stderr, " babeltrace2 convert %s [OPTIONS]\n",
290725f7
PP
2730 cfg->command_name);
2731 }
2732}
2733
7213a328
PP
2734static
2735void init_log_level(void)
2736{
c6d4d1ae 2737 bt_cli_log_level = bt_log_get_level_from_env(ENV_BABELTRACE_CLI_LOG_LEVEL);
7213a328
PP
2738}
2739
c6d4d1ae
PP
2740static
2741void set_auto_log_levels(struct bt_config *cfg)
2742{
2743 const char **env_var_name;
2744
b4565e8b
PP
2745 /*
2746 * Override the configuration's default log level if
2747 * BABELTRACE_VERBOSE or BABELTRACE_DEBUG environment variables
2748 * are found for backward compatibility with legacy Babetrace 1.
2749 */
2750 if (getenv("BABELTRACE_DEBUG") &&
2751 strcmp(getenv("BABELTRACE_DEBUG"), "1") == 0) {
83094759 2752 cfg->log_level = BT_LOG_VERBOSE;
b4565e8b
PP
2753 } else if (getenv("BABELTRACE_VERBOSE") &&
2754 strcmp(getenv("BABELTRACE_VERBOSE"), "1") == 0) {
83094759 2755 cfg->log_level = BT_LOG_INFO;
b4565e8b
PP
2756 }
2757
c6d4d1ae
PP
2758 /*
2759 * Set log levels according to --debug or --verbose. For
2760 * backward compatibility, --debug is more verbose than
2761 * --verbose. So:
2762 *
2763 * --verbose: INFO log level
2764 * --debug: VERBOSE log level (includes DEBUG, which is
2765 * is less verbose than VERBOSE in the internal
2766 * logging framework)
2767 */
2768 if (!getenv("BABELTRACE_LOGGING_GLOBAL_LEVEL")) {
2769 if (cfg->verbose) {
83094759 2770 bt_logging_set_global_level(BT_LOG_INFO);
c6d4d1ae 2771 } else if (cfg->debug) {
83094759 2772 bt_logging_set_global_level(BT_LOG_VERBOSE);
c6d4d1ae
PP
2773 } else {
2774 /*
2775 * Set library's default log level if not
2776 * explicitly specified.
2777 */
83094759 2778 bt_logging_set_global_level(cfg->log_level);
c6d4d1ae
PP
2779 }
2780 }
2781
2782 if (!getenv(ENV_BABELTRACE_CLI_LOG_LEVEL)) {
2783 if (cfg->verbose) {
2784 bt_cli_log_level = BT_LOG_INFO;
2785 } else if (cfg->debug) {
2786 bt_cli_log_level = BT_LOG_VERBOSE;
2787 } else {
2788 /*
2789 * Set CLI's default log level if not explicitly
2790 * specified.
2791 */
83094759 2792 bt_cli_log_level = cfg->log_level;
c6d4d1ae
PP
2793 }
2794 }
2795
2796 env_var_name = log_level_env_var_names;
2797
2798 while (*env_var_name) {
2799 if (!getenv(*env_var_name)) {
2800 if (cfg->verbose) {
fbb2f0da 2801 g_setenv(*env_var_name, "I", 1);
c6d4d1ae 2802 } else if (cfg->debug) {
fbb2f0da 2803 g_setenv(*env_var_name, "V", 1);
c6d4d1ae 2804 } else {
3efa3052
PP
2805 char val[2] = { 0 };
2806
c6d4d1ae
PP
2807 /*
2808 * Set module's default log level if not
2809 * explicitly specified.
2810 */
83094759
PP
2811 val[0] = bt_log_get_letter_from_level(
2812 cfg->log_level);
fbb2f0da 2813 g_setenv(*env_var_name, val, 1);
c6d4d1ae
PP
2814 }
2815 }
2816
2817 env_var_name++;
2818 }
c6d4d1ae
PP
2819}
2820
290725f7
PP
2821int main(int argc, const char **argv)
2822{
2823 int ret;
2824 int retcode;
2825 struct bt_config *cfg;
2826
7213a328 2827 init_log_level();
65d3198f 2828 set_signal_handler();
9009cc24
PP
2829 init_static_data();
2830 cfg = bt_config_cli_args_create_with_default(argc, argv, &retcode);
290725f7
PP
2831
2832 if (retcode < 0) {
2833 /* Quit without errors; typically usage/version */
2834 retcode = 0;
7213a328 2835 BT_LOGI_STR("Quitting without errors.");
290725f7
PP
2836 goto end;
2837 }
2838
2839 if (retcode > 0) {
7213a328 2840 BT_LOGE("Command-line error: retcode=%d", retcode);
290725f7
PP
2841 goto end;
2842 }
2843
2844 if (!cfg) {
7213a328 2845 BT_LOGE_STR("Failed to create a valid Babeltrace configuration.");
290725f7 2846 fprintf(stderr, "Failed to create Babeltrace configuration\n");
db0f160a 2847 retcode = 1;
290725f7
PP
2848 goto end;
2849 }
2850
c6d4d1ae 2851 set_auto_log_levels(cfg);
290725f7
PP
2852 print_cfg(cfg);
2853
db0f160a 2854 if (cfg->command_needs_plugins) {
05e21286 2855 ret = load_all_plugins(cfg->plugin_paths);
db0f160a 2856 if (ret) {
7213a328 2857 BT_LOGE("Failed to load plugins: ret=%d", ret);
db0f160a
PP
2858 retcode = 1;
2859 goto end;
2860 }
2861 }
2862
7213a328
PP
2863 BT_LOGI("Executing command: cmd=%d, command-name=\"%s\"",
2864 cfg->command, cfg->command_name);
2865
290725f7 2866 switch (cfg->command) {
db0f160a
PP
2867 case BT_CONFIG_COMMAND_RUN:
2868 ret = cmd_run(cfg);
290725f7
PP
2869 break;
2870 case BT_CONFIG_COMMAND_LIST_PLUGINS:
2871 ret = cmd_list_plugins(cfg);
2872 break;
22e22462
PP
2873 case BT_CONFIG_COMMAND_HELP:
2874 ret = cmd_help(cfg);
2875 break;
a67681c1
PP
2876 case BT_CONFIG_COMMAND_QUERY:
2877 ret = cmd_query(cfg);
63ce0e1d 2878 break;
db0f160a
PP
2879 case BT_CONFIG_COMMAND_PRINT_CTF_METADATA:
2880 ret = cmd_print_ctf_metadata(cfg);
2881 break;
2882 case BT_CONFIG_COMMAND_PRINT_LTTNG_LIVE_SESSIONS:
2883 ret = cmd_print_lttng_live_sessions(cfg);
2884 break;
290725f7 2885 default:
0fbb9a9f
PP
2886 BT_LOGF("Invalid/unknown command: cmd=%d", cfg->command);
2887 abort();
290725f7
PP
2888 }
2889
d26ef3e3
PP
2890 BT_LOGI("Command completed: cmd=%d, command-name=\"%s\", ret=%d",
2891 cfg->command, cfg->command_name, ret);
290725f7
PP
2892 warn_command_name_and_directory_clash(cfg);
2893 retcode = ret ? 1 : 0;
2894
2895end:
65300d60 2896 BT_OBJECT_PUT_REF_AND_RESET(cfg);
9009cc24 2897 fini_static_data();
290725f7 2898 return retcode;
4c8bfb7e 2899}
This page took 0.229805 seconds and 4 git commands to generate.