Add logging API (internal to log, public to set the current log level)
[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>
a8ff38ef 43#include <unistd.h>
34ac0e6c 44#include <stdlib.h>
7f26a816
PP
45#include <popt.h>
46#include <string.h>
47#include <stdio.h>
33b34c43 48#include <glib.h>
dc3fffef 49#include <inttypes.h>
c42c79ea 50#include "babeltrace-cfg.h"
ebba3338 51#include "babeltrace-cfg-connect.h"
c1870f57 52#include "default-cfg.h"
34ac0e6c 53
33b34c43
PP
54GPtrArray *loaded_plugins;
55
56static
57void init_loaded_plugins_array(void)
58{
59 loaded_plugins = g_ptr_array_new_full(8, bt_put);
60}
61
62static
63void fini_loaded_plugins_array(void)
64{
65 g_ptr_array_free(loaded_plugins, TRUE);
66}
67
68static
69struct bt_plugin *find_plugin(const char *name)
70{
71 int i;
72 struct bt_plugin *plugin = NULL;
73
74 for (i = 0; i < loaded_plugins->len; i++) {
75 plugin = g_ptr_array_index(loaded_plugins, i);
76
77 if (strcmp(name, bt_plugin_get_name(plugin)) == 0) {
78 break;
79 }
80
81 plugin = NULL;
82 }
83
84 return bt_get(plugin);
85}
86
87static
88struct bt_component_class *find_component_class(const char *plugin_name,
89 const char *comp_class_name,
d3e4dcd8 90 enum bt_component_class_type comp_class_type)
33b34c43
PP
91{
92 struct bt_component_class *comp_class = NULL;
93 struct bt_plugin *plugin = find_plugin(plugin_name);
94
95 if (!plugin) {
96 goto end;
97 }
98
99 comp_class = bt_plugin_get_component_class_by_name_and_type(plugin,
100 comp_class_name, comp_class_type);
101 BT_PUT(plugin);
102end:
103 return comp_class;
104}
6c2f3ee5 105
c42c79ea
PP
106static
107void print_indent(size_t indent)
108{
109 size_t i;
110
111 for (i = 0; i < indent; i++) {
00447e45 112 printf(" ");
c42c79ea
PP
113 }
114}
115
87796884
PP
116static char *escape_name_for_shell(const char *input)
117{
118 char *output = g_malloc0(strlen(input) * 5 + 1);
119 const char *in;
120 char *out = output;
121
122 if (!output) {
123 goto end;
124 }
125
126 for (in = input; *in != '\0'; in++) {
127 switch (*in) {
128 case '\\':
129 *out++ = '\\';
130 *out++ = '\\';
131 break;
132 case '\'':
133 *out++ = '\'';
134 *out++ = '"';
135 *out++ = '\'';
136 *out++ = '"';
137 *out++ = '\'';
138 break;
139 case '.':
140 *out++ = '\\';
141 *out++ = '.';
142 break;
143 default:
144 *out++ = *in;
145 break;
146 }
147 }
148
149end:
150 return output;
151}
152
153static
154const char *component_type_str(enum bt_component_class_type type)
155{
156 switch (type) {
157 case BT_COMPONENT_CLASS_TYPE_SOURCE:
158 return "source";
159 case BT_COMPONENT_CLASS_TYPE_SINK:
160 return "sink";
161 case BT_COMPONENT_CLASS_TYPE_FILTER:
162 return "filter";
163 case BT_COMPONENT_CLASS_TYPE_UNKNOWN:
164 default:
165 return "unknown";
166 }
167}
168
169static void print_plugin_comp_cls_opt(FILE *fh, const char *plugin_name,
170 const char *comp_cls_name, enum bt_component_class_type type)
171{
172 char *shell_plugin_name = NULL;
173 char *shell_comp_cls_name = NULL;
174
175 shell_plugin_name = escape_name_for_shell(plugin_name);
176 if (!shell_plugin_name) {
177 goto end;
178 }
179
180 shell_comp_cls_name = escape_name_for_shell(comp_cls_name);
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(),
193 shell_plugin_name,
194 bt_common_color_fg_default(),
195 bt_common_color_fg_yellow(),
196 shell_comp_cls_name,
197 bt_common_color_reset());
198
199end:
200 g_free(shell_plugin_name);
201 g_free(shell_comp_cls_name);
202}
203
c42c79ea 204static
290725f7 205void print_value(struct bt_value *, size_t);
c42c79ea 206
c1081aa6
PP
207static
208void print_value_rec(struct bt_value *, size_t);
209
c42c79ea
PP
210static
211bool print_map_value(const char *key, struct bt_value *object, void *data)
212{
290725f7
PP
213 size_t *indent = data;
214
215 print_indent(*indent);
216 printf("%s: ", key);
217
218 if (bt_value_is_array(object) &&
219 bt_value_array_is_empty(object)) {
220 printf("[ ]\n");
221 return true;
222 }
223
224 if (bt_value_is_map(object) &&
225 bt_value_map_is_empty(object)) {
226 printf("{ }\n");
227 return true;
228 }
c42c79ea 229
290725f7
PP
230 if (bt_value_is_array(object) ||
231 bt_value_is_map(object)) {
232 printf("\n");
233 }
c42c79ea 234
c1081aa6 235 print_value_rec(object, *indent + 2);
c42c79ea
PP
236 return true;
237}
238
239static
c1081aa6 240void print_value_rec(struct bt_value *value, size_t indent)
c42c79ea
PP
241{
242 bool bool_val;
243 int64_t int_val;
244 double dbl_val;
245 const char *str_val;
246 int size;
247 int i;
248
249 if (!value) {
250 return;
251 }
252
c42c79ea
PP
253 switch (bt_value_get_type(value)) {
254 case BT_VALUE_TYPE_NULL:
c1081aa6
PP
255 printf("%snull%s\n", bt_common_color_bold(),
256 bt_common_color_reset());
c42c79ea
PP
257 break;
258 case BT_VALUE_TYPE_BOOL:
259 bt_value_bool_get(value, &bool_val);
c1081aa6
PP
260 printf("%s%s%s%s\n", bt_common_color_bold(),
261 bt_common_color_fg_cyan(), bool_val ? "yes" : "no",
262 bt_common_color_reset());
c42c79ea
PP
263 break;
264 case BT_VALUE_TYPE_INTEGER:
265 bt_value_integer_get(value, &int_val);
c1081aa6
PP
266 printf("%s%s%" PRId64 "%s\n", bt_common_color_bold(),
267 bt_common_color_fg_red(), int_val,
268 bt_common_color_reset());
c42c79ea
PP
269 break;
270 case BT_VALUE_TYPE_FLOAT:
271 bt_value_float_get(value, &dbl_val);
c1081aa6
PP
272 printf("%s%s%lf%s\n", bt_common_color_bold(),
273 bt_common_color_fg_red(), dbl_val,
274 bt_common_color_reset());
c42c79ea
PP
275 break;
276 case BT_VALUE_TYPE_STRING:
277 bt_value_string_get(value, &str_val);
c1081aa6
PP
278 printf("%s%s%s%s\n", bt_common_color_bold(),
279 bt_common_color_fg_green(), str_val,
280 bt_common_color_reset());
c42c79ea
PP
281 break;
282 case BT_VALUE_TYPE_ARRAY:
283 size = bt_value_array_size(value);
290725f7
PP
284 assert(size >= 0);
285
286 if (size == 0) {
287 print_indent(indent);
288 printf("[ ]\n");
289 break;
290 }
c42c79ea
PP
291
292 for (i = 0; i < size; i++) {
293 struct bt_value *element =
294 bt_value_array_get(value, i);
295
290725f7
PP
296 assert(element);
297 print_indent(indent);
298 printf("- ");
299
300 if (bt_value_is_array(element) &&
301 bt_value_array_is_empty(element)) {
302 printf("[ ]\n");
303 continue;
304 }
305
306 if (bt_value_is_map(element) &&
307 bt_value_map_is_empty(element)) {
308 printf("{ }\n");
309 continue;
310 }
311
312 if (bt_value_is_array(element) ||
313 bt_value_is_map(element)) {
314 printf("\n");
315 }
316
c1081aa6 317 print_value_rec(element, indent + 2);
c42c79ea
PP
318 BT_PUT(element);
319 }
c42c79ea
PP
320 break;
321 case BT_VALUE_TYPE_MAP:
322 if (bt_value_map_is_empty(value)) {
290725f7
PP
323 print_indent(indent);
324 printf("{ }\n");
325 break;
c42c79ea
PP
326 }
327
290725f7 328 bt_value_map_foreach(value, print_map_value, &indent);
c42c79ea
PP
329 break;
330 default:
331 assert(false);
332 }
333}
334
c1081aa6
PP
335static
336void print_value(struct bt_value *value, size_t indent)
337{
338 if (!bt_value_is_array(value) && !bt_value_is_map(value)) {
339 print_indent(indent);
340 }
341
342 print_value_rec(value, indent);
343}
344
c42c79ea
PP
345static
346void print_bt_config_component(struct bt_config_component *bt_config_component)
347{
87796884
PP
348 printf(" ");
349 print_plugin_comp_cls_opt(stdout, bt_config_component->plugin_name->str,
db0f160a 350 bt_config_component->comp_cls_name->str,
87796884
PP
351 bt_config_component->type);
352 printf(":\n");
3b6cfcc5
PP
353
354 if (bt_config_component->instance_name->len > 0) {
355 printf(" Name: %s\n",
356 bt_config_component->instance_name->str);
357 }
358
290725f7
PP
359 printf(" Parameters:\n");
360 print_value(bt_config_component->params, 8);
c42c79ea
PP
361}
362
363static
364void print_bt_config_components(GPtrArray *array)
365{
366 size_t i;
367
368 for (i = 0; i < array->len; i++) {
369 struct bt_config_component *cfg_component =
e5bc7f81 370 bt_config_get_component(array, i);
c42c79ea
PP
371 print_bt_config_component(cfg_component);
372 BT_PUT(cfg_component);
373 }
374}
375
290725f7
PP
376static
377void print_plugin_paths(struct bt_value *plugin_paths)
378{
379 printf(" Plugin paths:\n");
380 print_value(plugin_paths, 4);
381}
382
383static
db0f160a 384void print_cfg_run(struct bt_config *cfg)
290725f7 385{
ebba3338
PP
386 size_t i;
387
db0f160a 388 print_plugin_paths(cfg->plugin_paths);
290725f7 389 printf(" Source component instances:\n");
db0f160a 390 print_bt_config_components(cfg->cmd_data.run.sources);
ebba3338 391
db0f160a 392 if (cfg->cmd_data.run.filters->len > 0) {
ebba3338 393 printf(" Filter component instances:\n");
db0f160a 394 print_bt_config_components(cfg->cmd_data.run.filters);
ebba3338
PP
395 }
396
290725f7 397 printf(" Sink component instances:\n");
db0f160a 398 print_bt_config_components(cfg->cmd_data.run.sinks);
ebba3338
PP
399 printf(" Connections:\n");
400
db0f160a 401 for (i = 0; i < cfg->cmd_data.run.connections->len; i++) {
ebba3338 402 struct bt_config_connection *cfg_connection =
db0f160a 403 g_ptr_array_index(cfg->cmd_data.run.connections,
ebba3338
PP
404 i);
405
406 printf(" %s%s%s -> %s%s%s\n",
407 cfg_connection->src_instance_name->str,
408 cfg_connection->src_port_name->len > 0 ? "." : "",
409 cfg_connection->src_port_name->str,
410 cfg_connection->dst_instance_name->str,
411 cfg_connection->dst_port_name->len > 0 ? "." : "",
412 cfg_connection->dst_port_name->str);
413 }
290725f7
PP
414}
415
416static
417void print_cfg_list_plugins(struct bt_config *cfg)
418{
db0f160a 419 print_plugin_paths(cfg->plugin_paths);
290725f7
PP
420}
421
c1081aa6
PP
422static
423void print_cfg_help(struct bt_config *cfg)
424{
db0f160a
PP
425 print_plugin_paths(cfg->plugin_paths);
426}
427
428static
429void print_cfg_print_ctf_metadata(struct bt_config *cfg)
430{
431 print_plugin_paths(cfg->plugin_paths);
432 printf(" Path: %s\n", cfg->cmd_data.print_ctf_metadata.path->str);
433}
434
435static
436void print_cfg_print_lttng_live_sessions(struct bt_config *cfg)
437{
438 print_plugin_paths(cfg->plugin_paths);
439 printf(" URL: %s\n", cfg->cmd_data.print_lttng_live_sessions.url->str);
c1081aa6
PP
440}
441
442static
a67681c1 443void print_cfg_query(struct bt_config *cfg)
c1081aa6 444{
db0f160a 445 print_plugin_paths(cfg->plugin_paths);
a67681c1 446 printf(" Object: `%s`\n", cfg->cmd_data.query.object->str);
c1081aa6 447 printf(" Component class:\n");
a67681c1 448 print_bt_config_component(cfg->cmd_data.query.cfg_component);
c1081aa6
PP
449}
450
c42c79ea
PP
451static
452void print_cfg(struct bt_config *cfg)
453{
00447e45
PP
454 if (!babeltrace_verbose) {
455 return;
456 }
457
290725f7
PP
458 printf("Configuration:\n");
459 printf(" Debug mode: %s\n", cfg->debug ? "yes" : "no");
460 printf(" Verbose mode: %s\n", cfg->verbose ? "yes" : "no");
461
462 switch (cfg->command) {
db0f160a
PP
463 case BT_CONFIG_COMMAND_RUN:
464 print_cfg_run(cfg);
290725f7
PP
465 break;
466 case BT_CONFIG_COMMAND_LIST_PLUGINS:
467 print_cfg_list_plugins(cfg);
c1081aa6
PP
468 break;
469 case BT_CONFIG_COMMAND_HELP:
470 print_cfg_help(cfg);
471 break;
a67681c1
PP
472 case BT_CONFIG_COMMAND_QUERY:
473 print_cfg_query(cfg);
290725f7 474 break;
db0f160a
PP
475 case BT_CONFIG_COMMAND_PRINT_CTF_METADATA:
476 print_cfg_print_ctf_metadata(cfg);
477 break;
478 case BT_CONFIG_COMMAND_PRINT_LTTNG_LIVE_SESSIONS:
479 print_cfg_print_lttng_live_sessions(cfg);
480 break;
290725f7
PP
481 default:
482 assert(false);
483 }
c42c79ea
PP
484}
485
6c2f3ee5
JG
486static
487struct bt_component *create_trimmer(struct bt_config_component *source_cfg)
488{
489 struct bt_component *trimmer = NULL;
490 struct bt_component_class *trimmer_class = NULL;
491 struct bt_value *trimmer_params = NULL;
528debdf 492 struct bt_value *value;
6c2f3ee5 493
6c2f3ee5
JG
494 trimmer_params = bt_value_map_create();
495 if (!trimmer_params) {
496 goto end;
497 }
498
528debdf
MD
499 value = bt_value_map_get(source_cfg->params, "begin");
500 if (value) {
6c2f3ee5 501 enum bt_value_status ret;
6c2f3ee5 502
528debdf 503 ret = bt_value_map_insert(trimmer_params, "begin",
6c2f3ee5
JG
504 value);
505 BT_PUT(value);
506 if (ret) {
507 goto end;
508 }
509 }
528debdf
MD
510 value = bt_value_map_get(source_cfg->params, "end");
511 if (value) {
6c2f3ee5 512 enum bt_value_status ret;
6c2f3ee5 513
528debdf
MD
514 ret = bt_value_map_insert(trimmer_params, "end",
515 value);
516 BT_PUT(value);
517 if (ret) {
6c2f3ee5
JG
518 goto end;
519 }
528debdf
MD
520 }
521 value = bt_value_map_get(source_cfg->params, "clock-gmt");
522 if (value) {
523 enum bt_value_status ret;
6c2f3ee5 524
528debdf 525 ret = bt_value_map_insert(trimmer_params, "clock-gmt",
6c2f3ee5
JG
526 value);
527 BT_PUT(value);
528 if (ret) {
529 goto end;
530 }
531 }
532
33b34c43 533 trimmer_class = find_component_class("utils", "trimmer",
d3e4dcd8 534 BT_COMPONENT_CLASS_TYPE_FILTER);
6c2f3ee5
JG
535 if (!trimmer_class) {
536 fprintf(stderr, "Could not find trimmer component class. Aborting...\n");
537 goto end;
538 }
539 trimmer = bt_component_create(trimmer_class, "source_trimmer",
540 trimmer_params);
541 if (!trimmer) {
542 goto end;
543 }
544end:
545 bt_put(trimmer_params);
546 bt_put(trimmer_class);
547 return trimmer;
548}
549
550static
61ddbc8a
JG
551int connect_source_sink(struct bt_graph *graph,
552 struct bt_component *source,
6c2f3ee5
JG
553 struct bt_config_component *source_cfg,
554 struct bt_component *sink)
555{
556 int ret = 0;
b9d103be
PP
557
558#if 0
61ddbc8a 559 struct bt_connection *connection = NULL;
6c2f3ee5 560 struct bt_component *trimmer = NULL;
61ddbc8a
JG
561 struct bt_port *source_port =
562 bt_component_source_get_default_output_port(source);
563 struct bt_port *sink_port =
564 bt_component_sink_get_default_input_port(sink);
565 struct bt_port *to_sink_port = NULL;
566 struct bt_port *trimmer_input_port = NULL;
567
568 if (!source_port) {
569 fprintf(stderr, "Failed to find default source output port. Aborting...\n");
570 ret = -1;
571 goto end;
572 }
573 if (!sink_port) {
574 fprintf(stderr, "Failed to find default sink input port. Aborting...\n");
575 ret = -1;
576 goto end;
577 }
6c2f3ee5 578
528debdf
MD
579 if (bt_value_map_has_key(source_cfg->params, "begin")
580 || bt_value_map_has_key(source_cfg->params, "end")) {
6c2f3ee5 581 /* A trimmer must be inserted in the graph. */
6c2f3ee5
JG
582 trimmer = create_trimmer(source_cfg);
583 if (!trimmer) {
584 fprintf(stderr, "Failed to create trimmer component. Aborting...\n");
585 ret = -1;
586 goto end;
587 }
588
61ddbc8a
JG
589 trimmer_input_port = bt_component_filter_get_default_input_port(
590 trimmer);
591 if (!trimmer_input_port) {
592 fprintf(stderr, "Failed to find trimmer input port. Aborting...\n");
593 ret = -1;
594 goto end;
595 }
596 to_sink_port = bt_component_filter_get_default_output_port(
597 trimmer);
598 if (!to_sink_port) {
599 fprintf(stderr, "Failed to find trimmer output port. Aborting...\n");
6c2f3ee5
JG
600 ret = -1;
601 goto end;
602 }
603
77a54f99 604 connection = bt_graph_connect_ports(graph, source_port,
61ddbc8a
JG
605 trimmer_input_port);
606 if (!connection) {
607 fprintf(stderr, "Failed to connect source to trimmer. Aborting...\n");
6c2f3ee5
JG
608 ret = -1;
609 goto end;
610 }
61ddbc8a 611 BT_PUT(connection);
6c2f3ee5 612 } else {
61ddbc8a 613 BT_MOVE(to_sink_port, source_port);
6c2f3ee5
JG
614 }
615
77a54f99 616 connection = bt_graph_connect_ports(graph, to_sink_port, sink_port);
61ddbc8a
JG
617 if (!connection) {
618 fprintf(stderr, "Failed to connect to sink. Aborting...\n");
6c2f3ee5
JG
619 ret = -1;
620 goto end;
621 }
622end:
623 bt_put(trimmer);
61ddbc8a
JG
624 bt_put(source_port);
625 bt_put(sink_port);
626 bt_put(to_sink_port);
627 bt_put(connection);
b9d103be
PP
628
629#endif
6c2f3ee5
JG
630 return ret;
631}
632
33b34c43 633static
a8ff38ef 634void add_to_loaded_plugins(struct bt_plugin_set *plugin_set)
98ecef32 635{
544d0515
PP
636 int64_t i;
637 int64_t count;
a8ff38ef
PP
638
639 count = bt_plugin_set_get_plugin_count(plugin_set);
640 assert(count >= 0);
641
642 for (i = 0; i < count; i++) {
643 struct bt_plugin *plugin =
644 bt_plugin_set_get_plugin(plugin_set, i);
33b34c43
PP
645 struct bt_plugin *loaded_plugin =
646 find_plugin(bt_plugin_get_name(plugin));
647
a8ff38ef
PP
648 assert(plugin);
649
33b34c43
PP
650 if (loaded_plugin) {
651 printf_verbose("Not loading plugin `%s`: already loaded from `%s`\n",
652 bt_plugin_get_path(plugin),
653 bt_plugin_get_path(loaded_plugin));
a8ff38ef 654 bt_put(loaded_plugin);
33b34c43 655 } else {
a8ff38ef
PP
656 /* Add to global array. */
657 g_ptr_array_add(loaded_plugins, bt_get(plugin));
33b34c43 658 }
a8ff38ef
PP
659
660 bt_put(plugin);
33b34c43
PP
661 }
662}
663
664static
290725f7 665int load_dynamic_plugins(struct bt_value *plugin_paths)
33b34c43
PP
666{
667 int nr_paths, i, ret = 0;
98ecef32 668
290725f7 669 nr_paths = bt_value_array_size(plugin_paths);
98ecef32 670 if (nr_paths < 0) {
33b34c43
PP
671 ret = -1;
672 goto end;
98ecef32 673 }
33b34c43 674
98ecef32
MD
675 for (i = 0; i < nr_paths; i++) {
676 struct bt_value *plugin_path_value = NULL;
677 const char *plugin_path;
a8ff38ef 678 struct bt_plugin_set *plugin_set;
98ecef32 679
290725f7 680 plugin_path_value = bt_value_array_get(plugin_paths, i);
98ecef32
MD
681 if (bt_value_string_get(plugin_path_value,
682 &plugin_path)) {
683 BT_PUT(plugin_path_value);
684 continue;
685 }
33b34c43 686
a8ff38ef
PP
687 plugin_set = bt_plugin_create_all_from_dir(plugin_path, false);
688 if (!plugin_set) {
98ecef32
MD
689 printf_debug("Unable to dynamically load plugins from path %s.\n",
690 plugin_path);
33b34c43
PP
691 BT_PUT(plugin_path_value);
692 continue;
98ecef32 693 }
33b34c43 694
a8ff38ef
PP
695 add_to_loaded_plugins(plugin_set);
696 bt_put(plugin_set);
98ecef32
MD
697 BT_PUT(plugin_path_value);
698 }
33b34c43
PP
699end:
700 return ret;
701}
702
703static
704int load_static_plugins(void)
705{
706 int ret = 0;
a8ff38ef 707 struct bt_plugin_set *plugin_set;
33b34c43 708
a8ff38ef
PP
709 plugin_set = bt_plugin_create_all_from_static();
710 if (!plugin_set) {
33b34c43
PP
711 printf_debug("Unable to load static plugins.\n");
712 ret = -1;
713 goto end;
714 }
715
a8ff38ef
PP
716 add_to_loaded_plugins(plugin_set);
717 bt_put(plugin_set);
33b34c43
PP
718end:
719 return ret;
98ecef32
MD
720}
721
290725f7
PP
722static int load_all_plugins(struct bt_value *plugin_paths)
723{
724 int ret = 0;
33b34c43 725
290725f7
PP
726 if (load_dynamic_plugins(plugin_paths)) {
727 fprintf(stderr, "Failed to load dynamic plugins.\n");
728 ret = -1;
c1870f57
JG
729 goto end;
730 }
731
290725f7
PP
732 if (load_static_plugins()) {
733 fprintf(stderr, "Failed to load static plugins.\n");
734 ret = -1;
c1870f57
JG
735 goto end;
736 }
737
290725f7
PP
738end:
739 return ret;
740}
741
22e22462
PP
742static void print_plugin_info(struct bt_plugin *plugin)
743{
744 unsigned int major, minor, patch;
745 const char *extra;
746 enum bt_plugin_status version_status;
747 const char *plugin_name;
748 const char *path;
749 const char *author;
750 const char *license;
751 const char *plugin_description;
752
753 plugin_name = bt_plugin_get_name(plugin);
754 path = bt_plugin_get_path(plugin);
755 author = bt_plugin_get_author(plugin);
756 license = bt_plugin_get_license(plugin);
757 plugin_description = bt_plugin_get_description(plugin);
758 version_status = bt_plugin_get_version(plugin, &major, &minor,
759 &patch, &extra);
760 printf("%s%s%s%s:\n", bt_common_color_bold(),
761 bt_common_color_fg_blue(), plugin_name,
762 bt_common_color_reset());
763 printf(" %sPath%s: %s\n", bt_common_color_bold(),
764 bt_common_color_reset(), path ? path : "(None)");
765
766 if (version_status == BT_PLUGIN_STATUS_OK) {
767 printf(" %sVersion%s: %u.%u.%u",
768 bt_common_color_bold(), bt_common_color_reset(),
769 major, minor, patch);
770
771 if (extra) {
772 printf("%s", extra);
773 }
774
775 printf("\n");
776 }
777
778 printf(" %sDescription%s: %s\n", bt_common_color_bold(),
779 bt_common_color_reset(),
780 plugin_description ? plugin_description : "(None)");
781 printf(" %sAuthor%s: %s\n", bt_common_color_bold(),
782 bt_common_color_reset(), author ? author : "(Unknown)");
783 printf(" %sLicense%s: %s\n", bt_common_color_bold(),
784 bt_common_color_reset(),
785 license ? license : "(Unknown)");
786}
787
a67681c1 788static int cmd_query(struct bt_config *cfg)
63ce0e1d
PP
789{
790 int ret;
791 struct bt_component_class *comp_cls = NULL;
792 struct bt_value *results = NULL;
793
db0f160a 794 ret = load_all_plugins(cfg->plugin_paths);
63ce0e1d
PP
795 if (ret) {
796 goto end;
797 }
798
a67681c1 799 comp_cls = find_component_class(cfg->cmd_data.query.cfg_component->plugin_name->str,
db0f160a 800 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
a67681c1 801 cfg->cmd_data.query.cfg_component->type);
63ce0e1d
PP
802 if (!comp_cls) {
803 fprintf(stderr, "%s%sCannot find component class %s",
804 bt_common_color_bold(),
805 bt_common_color_fg_red(),
806 bt_common_color_reset());
807 print_plugin_comp_cls_opt(stderr,
a67681c1 808 cfg->cmd_data.query.cfg_component->plugin_name->str,
db0f160a 809 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
a67681c1 810 cfg->cmd_data.query.cfg_component->type);
63ce0e1d
PP
811 fprintf(stderr, "\n");
812 ret = -1;
813 goto end;
814 }
815
a67681c1
PP
816 results = bt_component_class_query(comp_cls,
817 cfg->cmd_data.query.object->str,
818 cfg->cmd_data.query.cfg_component->params);
63ce0e1d
PP
819 if (!results) {
820 fprintf(stderr, "%s%sFailed to query info to %s",
821 bt_common_color_bold(),
822 bt_common_color_fg_red(),
823 bt_common_color_reset());
824 print_plugin_comp_cls_opt(stderr,
a67681c1 825 cfg->cmd_data.query.cfg_component->plugin_name->str,
db0f160a 826 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
a67681c1
PP
827 cfg->cmd_data.query.cfg_component->type);
828 fprintf(stderr, "%s%s with object `%s`%s\n",
63ce0e1d
PP
829 bt_common_color_bold(),
830 bt_common_color_fg_red(),
a67681c1 831 cfg->cmd_data.query.object->str,
63ce0e1d
PP
832 bt_common_color_reset());
833 ret = -1;
834 goto end;
835 }
836
837 print_value(results, 0);
838
839end:
840 bt_put(comp_cls);
841 bt_put(results);
842 return ret;
843}
844
22e22462
PP
845static int cmd_help(struct bt_config *cfg)
846{
847 int ret;
848 struct bt_plugin *plugin = NULL;
849 size_t i;
850
db0f160a 851 ret = load_all_plugins(cfg->plugin_paths);
22e22462
PP
852 if (ret) {
853 goto end;
854 }
855
90de159b 856 plugin = find_plugin(cfg->cmd_data.help.cfg_component->plugin_name->str);
22e22462
PP
857 if (!plugin) {
858 fprintf(stderr, "%s%sCannot find plugin %s%s%s\n",
859 bt_common_color_bold(), bt_common_color_fg_red(),
860 bt_common_color_fg_blue(),
90de159b 861 cfg->cmd_data.help.cfg_component->plugin_name->str,
22e22462
PP
862 bt_common_color_reset());
863 ret = -1;
864 goto end;
865 }
866
867 print_plugin_info(plugin);
868 printf(" %sComponent classes%s: %d\n",
869 bt_common_color_bold(),
870 bt_common_color_reset(),
544d0515 871 (int) bt_plugin_get_component_class_count(plugin));
22e22462
PP
872
873
90de159b 874 if (cfg->cmd_data.help.cfg_component->type !=
22e22462
PP
875 BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
876 struct bt_component_class *needed_comp_cls =
877 find_component_class(
90de159b 878 cfg->cmd_data.help.cfg_component->plugin_name->str,
db0f160a 879 cfg->cmd_data.help.cfg_component->comp_cls_name->str,
90de159b 880 cfg->cmd_data.help.cfg_component->type);
22e22462
PP
881
882 if (!needed_comp_cls) {
883 fprintf(stderr, "\n%s%sCannot find component class %s",
884 bt_common_color_bold(),
885 bt_common_color_fg_red(),
886 bt_common_color_reset());
887 print_plugin_comp_cls_opt(stderr,
90de159b 888 cfg->cmd_data.help.cfg_component->plugin_name->str,
db0f160a 889 cfg->cmd_data.help.cfg_component->comp_cls_name->str,
90de159b 890 cfg->cmd_data.help.cfg_component->type);
22e22462
PP
891 fprintf(stderr, "\n");
892 ret = -1;
893 goto end;
894 }
895
896 bt_put(needed_comp_cls);
897 }
898
899 for (i = 0; i < bt_plugin_get_component_class_count(plugin); i++) {
900 struct bt_component_class *comp_cls =
9ac68eb1 901 bt_plugin_get_component_class_by_index(plugin, i);
22e22462
PP
902 const char *comp_class_name =
903 bt_component_class_get_name(comp_cls);
904 const char *comp_class_description =
905 bt_component_class_get_description(comp_cls);
906 const char *comp_class_help =
907 bt_component_class_get_help(comp_cls);
908 enum bt_component_class_type type =
909 bt_component_class_get_type(comp_cls);
910
911 assert(comp_cls);
912
90de159b 913 if (cfg->cmd_data.help.cfg_component->type !=
22e22462 914 BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
db0f160a 915 if (strcmp(cfg->cmd_data.help.cfg_component->comp_cls_name->str,
22e22462
PP
916 comp_class_name) != 0 &&
917 type ==
90de159b 918 cfg->cmd_data.help.cfg_component->type) {
22e22462
PP
919 bt_put(comp_cls);
920 continue;
921 }
922 }
923
924 printf("\n");
925 print_plugin_comp_cls_opt(stdout,
90de159b 926 cfg->cmd_data.help.cfg_component->plugin_name->str,
22e22462
PP
927 comp_class_name,
928 type);
929 printf("\n");
930 printf(" %sDescription%s: %s\n", bt_common_color_bold(),
931 bt_common_color_reset(),
932 comp_class_description ? comp_class_description : "(None)");
933
934 if (comp_class_help) {
935 printf("\n%s\n", comp_class_help);
936 }
937
938 bt_put(comp_cls);
939 }
940
941end:
942 bt_put(plugin);
943 return ret;
944}
945
290725f7
PP
946static int cmd_list_plugins(struct bt_config *cfg)
947{
948 int ret;
949 int plugins_count, component_classes_count = 0, i;
950
db0f160a 951 ret = load_all_plugins(cfg->plugin_paths);
290725f7 952 if (ret) {
56a1cced
JG
953 goto end;
954 }
955
22e22462 956 printf("From the following plugin paths:\n\n");
db0f160a 957 print_value(cfg->plugin_paths, 2);
22e22462 958 printf("\n");
290725f7
PP
959 plugins_count = loaded_plugins->len;
960 if (plugins_count == 0) {
961 fprintf(stderr, "%s%sNo plugins found.%s\n",
962 bt_common_color_bold(), bt_common_color_fg_red(),
963 bt_common_color_reset());
964 fprintf(stderr, "\n");
965 fprintf(stderr, "Please make sure your plugin search path is set correctly. You can use\n");
966 fprintf(stderr, "the --plugin-path command-line option or the BABELTRACE_PLUGIN_PATH\n");
967 fprintf(stderr, "environment variable.\n");
56a1cced
JG
968 ret = -1;
969 goto end;
970 }
971
290725f7
PP
972 for (i = 0; i < plugins_count; i++) {
973 struct bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i);
974
975 component_classes_count += bt_plugin_get_component_class_count(plugin);
976 }
33bceaf8 977
290725f7
PP
978 printf("Found %s%d%s component classes in %s%d%s plugins.\n",
979 bt_common_color_bold(),
980 component_classes_count,
981 bt_common_color_reset(),
982 bt_common_color_bold(),
983 plugins_count,
984 bt_common_color_reset());
985
986 for (i = 0; i < plugins_count; i++) {
987 int j;
988 struct bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i);
290725f7
PP
989
990 component_classes_count =
991 bt_plugin_get_component_class_count(plugin);
22e22462
PP
992 printf("\n");
993 print_plugin_info(plugin);
290725f7
PP
994
995 if (component_classes_count == 0) {
996 printf(" %sComponent classes%s: (None)\n",
997 bt_common_color_bold(),
998 bt_common_color_reset());
999 } else {
1000 printf(" %sComponent classes%s:\n",
1001 bt_common_color_bold(),
1002 bt_common_color_reset());
1003 }
1004
1005 for (j = 0; j < component_classes_count; j++) {
1006 struct bt_component_class *comp_class =
9ac68eb1
PP
1007 bt_plugin_get_component_class_by_index(
1008 plugin, j);
290725f7
PP
1009 const char *comp_class_name =
1010 bt_component_class_get_name(comp_class);
1011 const char *comp_class_description =
1012 bt_component_class_get_description(comp_class);
1013 enum bt_component_class_type type =
1014 bt_component_class_get_type(comp_class);
1015
22e22462
PP
1016 printf(" ");
1017 print_plugin_comp_cls_opt(stdout,
1018 bt_plugin_get_name(plugin), comp_class_name,
1019 type);
290725f7
PP
1020
1021 if (comp_class_description) {
1022 printf(": %s", comp_class_description);
1023 }
1024
1025 printf("\n");
1026 bt_put(comp_class);
1027 }
1028 }
1029
1030end:
1031 return ret;
1032}
1033
db0f160a
PP
1034static int cmd_print_lttng_live_sessions(struct bt_config *cfg)
1035{
1036 printf("TODO\n");
1037 return -1;
1038}
1039
1040static int cmd_print_ctf_metadata(struct bt_config *cfg)
05a67631
PP
1041{
1042 int ret = 0;
1043 struct bt_component_class *comp_cls = NULL;
05a67631 1044 struct bt_value *results = NULL;
05a67631
PP
1045 struct bt_value *params = NULL;
1046 struct bt_value *metadata_text_value = NULL;
1047 const char *metadata_text = NULL;
db0f160a
PP
1048 static const char * const plugin_name = "ctf";
1049 static const char * const comp_cls_name = "fs";
1050 static const enum bt_component_class_type comp_cls_type =
1051 BT_COMPONENT_CLASS_TYPE_SOURCE;
1052
1053 assert(cfg->cmd_data.print_ctf_metadata.path);
1054 comp_cls = find_component_class(plugin_name, comp_cls_name,
1055 comp_cls_type);
05a67631
PP
1056 if (!comp_cls) {
1057 fprintf(stderr, "%s%sCannot find component class %s",
1058 bt_common_color_bold(),
1059 bt_common_color_fg_red(),
1060 bt_common_color_reset());
db0f160a
PP
1061 print_plugin_comp_cls_opt(stderr, plugin_name,
1062 comp_cls_name, comp_cls_type);
05a67631
PP
1063 fprintf(stderr, "\n");
1064 ret = -1;
1065 goto end;
1066 }
1067
05a67631
PP
1068 params = bt_value_map_create();
1069 if (!params) {
1070 ret = -1;
1071 goto end;
1072 }
1073
db0f160a
PP
1074 ret = bt_value_map_insert_string(params, "path",
1075 cfg->cmd_data.print_ctf_metadata.path->str);
05a67631
PP
1076 if (ret) {
1077 ret = -1;
1078 goto end;
1079 }
1080
a67681c1 1081 results = bt_component_class_query(comp_cls, "metadata-info",
05a67631
PP
1082 params);
1083 if (!results) {
1084 ret = -1;
a67681c1 1085 fprintf(stderr, "%s%sFailed to request metadata info%s\n",
05a67631
PP
1086 bt_common_color_bold(),
1087 bt_common_color_fg_red(),
1088 bt_common_color_reset());
1089 goto end;
1090 }
1091
1092 metadata_text_value = bt_value_map_get(results, "text");
1093 if (!metadata_text_value) {
1094 ret = -1;
1095 goto end;
1096 }
1097
1098 ret = bt_value_string_get(metadata_text_value, &metadata_text);
1099 assert(ret == 0);
1100 printf("%s\n", metadata_text);
1101
1102end:
1103 bt_put(results);
05a67631
PP
1104 bt_put(params);
1105 bt_put(metadata_text_value);
1106 bt_put(comp_cls);
05a67631
PP
1107 return 0;
1108}
1109
db0f160a 1110static int cmd_run(struct bt_config *cfg)
290725f7
PP
1111{
1112 int ret = 0;
1113 struct bt_component_class *source_class = NULL;
1114 struct bt_component_class *sink_class = NULL;
1115 struct bt_component *source = NULL, *sink = NULL;
1116 struct bt_value *source_params = NULL, *sink_params = NULL;
290725f7 1117 struct bt_config_component *source_cfg = NULL, *sink_cfg = NULL;
61ddbc8a 1118 struct bt_graph *graph = NULL;
290725f7 1119
db0f160a 1120 ret = load_all_plugins(cfg->plugin_paths);
05a67631 1121 if (ret) {
05a67631
PP
1122 goto end;
1123 }
1124
290725f7 1125 /* TODO handle more than 1 source and 1 sink. */
db0f160a
PP
1126 if (cfg->cmd_data.run.sources->len != 1 ||
1127 cfg->cmd_data.run.sinks->len != 1) {
ebba3338 1128 fprintf(stderr, "Only one source and one sink component class are supported. Aborting...\n");
98ecef32
MD
1129 ret = -1;
1130 goto end;
33bceaf8
JG
1131 }
1132
db0f160a 1133 source_cfg = bt_config_get_component(cfg->cmd_data.run.sources, 0);
e5bc7f81 1134 source_params = bt_get(source_cfg->params);
33b34c43 1135 source_class = find_component_class(source_cfg->plugin_name->str,
db0f160a 1136 source_cfg->comp_cls_name->str,
d3e4dcd8 1137 BT_COMPONENT_CLASS_TYPE_SOURCE);
56a1cced 1138 if (!source_class) {
87796884
PP
1139 fprintf(stderr, "Could not find ");
1140 print_plugin_comp_cls_opt(stderr, source_cfg->plugin_name->str,
db0f160a 1141 source_cfg->comp_cls_name->str, BT_COMPONENT_CLASS_TYPE_SOURCE);
87796884 1142 fprintf(stderr, ". Aborting...\n");
56a1cced
JG
1143 ret = -1;
1144 goto end;
1145 }
7c7c0433 1146
db0f160a 1147 sink_cfg = bt_config_get_component(cfg->cmd_data.run.sinks, 0);
e5bc7f81 1148 sink_params = bt_get(sink_cfg->params);
33b34c43 1149 sink_class = find_component_class(sink_cfg->plugin_name->str,
db0f160a 1150 sink_cfg->comp_cls_name->str,
d3e4dcd8 1151 BT_COMPONENT_CLASS_TYPE_SINK);
7c7c0433 1152 if (!sink_class) {
87796884
PP
1153 fprintf(stderr, "Could not find ");
1154 print_plugin_comp_cls_opt(stderr, sink_cfg->plugin_name->str,
db0f160a 1155 sink_cfg->comp_cls_name->str, BT_COMPONENT_CLASS_TYPE_SINK);
87796884 1156 fprintf(stderr, ". Aborting...\n");
7c7c0433
JG
1157 ret = -1;
1158 goto end;
1159 }
1160
61ddbc8a
JG
1161 graph = bt_graph_create();
1162 if (!graph) {
1163 ret = -1;
1164 goto end;
1165 }
1166
e5bc7f81 1167 source = bt_component_create(source_class, "source", source_params);
56a1cced 1168 if (!source) {
e5bc7f81 1169 fprintf(stderr, "Failed to instantiate selected source component. Aborting...\n");
c42c79ea
PP
1170 ret = -1;
1171 goto end;
1172 }
56a1cced 1173
e5bc7f81 1174 sink = bt_component_create(sink_class, "sink", sink_params);
7c7c0433 1175 if (!sink) {
e5bc7f81 1176 fprintf(stderr, "Failed to instantiate selected output component. Aborting...\n");
7c7c0433 1177 ret = -1;
2e339de1
JG
1178 goto end;
1179 }
1180
61ddbc8a 1181 ret = connect_source_sink(graph, source, source_cfg, sink);
6c2f3ee5 1182 if (ret) {
290725f7 1183 ret = -1;
fec2a9f2
JG
1184 goto end;
1185 }
78586d8a 1186
fec2a9f2 1187 while (true) {
61ddbc8a
JG
1188 enum bt_graph_status graph_status;
1189
72b913fb 1190 graph_status = bt_graph_run(graph);
61ddbc8a
JG
1191 switch (graph_status) {
1192 case BT_GRAPH_STATUS_AGAIN:
fec2a9f2
JG
1193 /* Wait for an arbitraty 500 ms. */
1194 usleep(500000);
78586d8a 1195 break;
fec2a9f2
JG
1196 case BT_COMPONENT_STATUS_END:
1197 goto end;
1198 default:
1199 fprintf(stderr, "Sink component returned an error, aborting...\n");
1200 ret = -1;
1201 goto end;
78586d8a 1202 }
fec2a9f2 1203 }
290725f7 1204
11e1d048 1205end:
61ddbc8a
JG
1206 bt_put(sink_class);
1207 bt_put(source_class);
1208 bt_put(source);
1209 bt_put(sink);
1210 bt_put(source_params);
1211 bt_put(sink_params);
1212 bt_put(sink_cfg);
1213 bt_put(source_cfg);
1214 bt_put(graph);
290725f7
PP
1215 return ret;
1216}
1217
1218static void warn_command_name_and_directory_clash(struct bt_config *cfg)
1219{
1220 if (!cfg->command_name) {
1221 return;
1222 }
1223
1224 if (g_file_test(cfg->command_name,
1225 G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
1226 fprintf(stderr, "\nNOTE: The `%s` command was executed. If you meant to convert a\n",
1227 cfg->command_name);
1228 fprintf(stderr, "trace located in the local `%s` directory, please use:\n",
1229 cfg->command_name);
1230 fprintf(stderr, "\n");
1231 fprintf(stderr, " babeltrace convert %s [OPTIONS]\n",
1232 cfg->command_name);
1233 }
1234}
1235
1236int main(int argc, const char **argv)
1237{
1238 int ret;
1239 int retcode;
1240 struct bt_config *cfg;
1241
1242 init_loaded_plugins_array();
1243 cfg = bt_config_from_args_with_defaults(argc, argv, &retcode);
1244
1245 if (retcode < 0) {
1246 /* Quit without errors; typically usage/version */
1247 retcode = 0;
1248 goto end;
1249 }
1250
1251 if (retcode > 0) {
1252 goto end;
1253 }
1254
1255 if (!cfg) {
1256 fprintf(stderr, "Failed to create Babeltrace configuration\n");
db0f160a 1257 retcode = 1;
290725f7
PP
1258 goto end;
1259 }
1260
1261 babeltrace_debug = cfg->debug;
1262 babeltrace_verbose = cfg->verbose;
1263 print_cfg(cfg);
1264
db0f160a
PP
1265 if (cfg->command_needs_plugins) {
1266 ret = load_all_plugins(cfg->plugin_paths);
1267 if (ret) {
1268 retcode = 1;
1269 goto end;
1270 }
1271 }
1272
290725f7 1273 switch (cfg->command) {
db0f160a
PP
1274 case BT_CONFIG_COMMAND_RUN:
1275 ret = cmd_run(cfg);
290725f7
PP
1276 break;
1277 case BT_CONFIG_COMMAND_LIST_PLUGINS:
1278 ret = cmd_list_plugins(cfg);
1279 break;
22e22462
PP
1280 case BT_CONFIG_COMMAND_HELP:
1281 ret = cmd_help(cfg);
1282 break;
a67681c1
PP
1283 case BT_CONFIG_COMMAND_QUERY:
1284 ret = cmd_query(cfg);
63ce0e1d 1285 break;
db0f160a
PP
1286 case BT_CONFIG_COMMAND_PRINT_CTF_METADATA:
1287 ret = cmd_print_ctf_metadata(cfg);
1288 break;
1289 case BT_CONFIG_COMMAND_PRINT_LTTNG_LIVE_SESSIONS:
1290 ret = cmd_print_lttng_live_sessions(cfg);
1291 break;
290725f7
PP
1292 default:
1293 assert(false);
1294 }
1295
1296 warn_command_name_and_directory_clash(cfg);
1297 retcode = ret ? 1 : 0;
1298
1299end:
1300 BT_PUT(cfg);
33b34c43 1301 fini_loaded_plugins_array();
290725f7 1302 return retcode;
4c8bfb7e 1303}
This page took 0.107167 seconds and 4 git commands to generate.