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