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