ISO C: empty file needs at least one declaration
[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;
61ddbc8a 557 struct bt_connection *connection = NULL;
6c2f3ee5 558 struct bt_component *trimmer = NULL;
61ddbc8a
JG
559 struct bt_port *source_port =
560 bt_component_source_get_default_output_port(source);
561 struct bt_port *sink_port =
562 bt_component_sink_get_default_input_port(sink);
563 struct bt_port *to_sink_port = NULL;
564 struct bt_port *trimmer_input_port = NULL;
565
566 if (!source_port) {
567 fprintf(stderr, "Failed to find default source output port. Aborting...\n");
568 ret = -1;
569 goto end;
570 }
571 if (!sink_port) {
572 fprintf(stderr, "Failed to find default sink input port. Aborting...\n");
573 ret = -1;
574 goto end;
575 }
6c2f3ee5 576
528debdf
MD
577 if (bt_value_map_has_key(source_cfg->params, "begin")
578 || bt_value_map_has_key(source_cfg->params, "end")) {
6c2f3ee5 579 /* A trimmer must be inserted in the graph. */
6c2f3ee5
JG
580 trimmer = create_trimmer(source_cfg);
581 if (!trimmer) {
582 fprintf(stderr, "Failed to create trimmer component. Aborting...\n");
583 ret = -1;
584 goto end;
585 }
586
61ddbc8a
JG
587 trimmer_input_port = bt_component_filter_get_default_input_port(
588 trimmer);
589 if (!trimmer_input_port) {
590 fprintf(stderr, "Failed to find trimmer input port. Aborting...\n");
591 ret = -1;
592 goto end;
593 }
594 to_sink_port = bt_component_filter_get_default_output_port(
595 trimmer);
596 if (!to_sink_port) {
597 fprintf(stderr, "Failed to find trimmer output port. Aborting...\n");
6c2f3ee5
JG
598 ret = -1;
599 goto end;
600 }
601
77a54f99 602 connection = bt_graph_connect_ports(graph, source_port,
61ddbc8a
JG
603 trimmer_input_port);
604 if (!connection) {
605 fprintf(stderr, "Failed to connect source to trimmer. Aborting...\n");
6c2f3ee5
JG
606 ret = -1;
607 goto end;
608 }
61ddbc8a 609 BT_PUT(connection);
6c2f3ee5 610 } else {
61ddbc8a 611 BT_MOVE(to_sink_port, source_port);
6c2f3ee5
JG
612 }
613
77a54f99 614 connection = bt_graph_connect_ports(graph, to_sink_port, sink_port);
61ddbc8a
JG
615 if (!connection) {
616 fprintf(stderr, "Failed to connect to sink. Aborting...\n");
6c2f3ee5
JG
617 ret = -1;
618 goto end;
619 }
620end:
621 bt_put(trimmer);
61ddbc8a
JG
622 bt_put(source_port);
623 bt_put(sink_port);
624 bt_put(to_sink_port);
625 bt_put(connection);
6c2f3ee5
JG
626 return ret;
627}
628
33b34c43 629static
a8ff38ef 630void add_to_loaded_plugins(struct bt_plugin_set *plugin_set)
98ecef32 631{
a8ff38ef
PP
632 int i;
633 int count;
634
635 count = bt_plugin_set_get_plugin_count(plugin_set);
636 assert(count >= 0);
637
638 for (i = 0; i < count; i++) {
639 struct bt_plugin *plugin =
640 bt_plugin_set_get_plugin(plugin_set, i);
33b34c43
PP
641 struct bt_plugin *loaded_plugin =
642 find_plugin(bt_plugin_get_name(plugin));
643
a8ff38ef
PP
644 assert(plugin);
645
33b34c43
PP
646 if (loaded_plugin) {
647 printf_verbose("Not loading plugin `%s`: already loaded from `%s`\n",
648 bt_plugin_get_path(plugin),
649 bt_plugin_get_path(loaded_plugin));
a8ff38ef 650 bt_put(loaded_plugin);
33b34c43 651 } else {
a8ff38ef
PP
652 /* Add to global array. */
653 g_ptr_array_add(loaded_plugins, bt_get(plugin));
33b34c43 654 }
a8ff38ef
PP
655
656 bt_put(plugin);
33b34c43
PP
657 }
658}
659
660static
290725f7 661int load_dynamic_plugins(struct bt_value *plugin_paths)
33b34c43
PP
662{
663 int nr_paths, i, ret = 0;
98ecef32 664
290725f7 665 nr_paths = bt_value_array_size(plugin_paths);
98ecef32 666 if (nr_paths < 0) {
33b34c43
PP
667 ret = -1;
668 goto end;
98ecef32 669 }
33b34c43 670
98ecef32
MD
671 for (i = 0; i < nr_paths; i++) {
672 struct bt_value *plugin_path_value = NULL;
673 const char *plugin_path;
a8ff38ef 674 struct bt_plugin_set *plugin_set;
98ecef32 675
290725f7 676 plugin_path_value = bt_value_array_get(plugin_paths, i);
98ecef32
MD
677 if (bt_value_string_get(plugin_path_value,
678 &plugin_path)) {
679 BT_PUT(plugin_path_value);
680 continue;
681 }
33b34c43 682
a8ff38ef
PP
683 plugin_set = bt_plugin_create_all_from_dir(plugin_path, false);
684 if (!plugin_set) {
98ecef32
MD
685 printf_debug("Unable to dynamically load plugins from path %s.\n",
686 plugin_path);
33b34c43
PP
687 BT_PUT(plugin_path_value);
688 continue;
98ecef32 689 }
33b34c43 690
a8ff38ef
PP
691 add_to_loaded_plugins(plugin_set);
692 bt_put(plugin_set);
98ecef32
MD
693 BT_PUT(plugin_path_value);
694 }
33b34c43
PP
695end:
696 return ret;
697}
698
699static
700int load_static_plugins(void)
701{
702 int ret = 0;
a8ff38ef 703 struct bt_plugin_set *plugin_set;
33b34c43 704
a8ff38ef
PP
705 plugin_set = bt_plugin_create_all_from_static();
706 if (!plugin_set) {
33b34c43
PP
707 printf_debug("Unable to load static plugins.\n");
708 ret = -1;
709 goto end;
710 }
711
a8ff38ef
PP
712 add_to_loaded_plugins(plugin_set);
713 bt_put(plugin_set);
33b34c43
PP
714end:
715 return ret;
98ecef32
MD
716}
717
290725f7
PP
718static int load_all_plugins(struct bt_value *plugin_paths)
719{
720 int ret = 0;
33b34c43 721
290725f7
PP
722 if (load_dynamic_plugins(plugin_paths)) {
723 fprintf(stderr, "Failed to load dynamic plugins.\n");
724 ret = -1;
c1870f57
JG
725 goto end;
726 }
727
290725f7
PP
728 if (load_static_plugins()) {
729 fprintf(stderr, "Failed to load static plugins.\n");
730 ret = -1;
c1870f57
JG
731 goto end;
732 }
733
290725f7
PP
734end:
735 return ret;
736}
737
22e22462
PP
738static void print_plugin_info(struct bt_plugin *plugin)
739{
740 unsigned int major, minor, patch;
741 const char *extra;
742 enum bt_plugin_status version_status;
743 const char *plugin_name;
744 const char *path;
745 const char *author;
746 const char *license;
747 const char *plugin_description;
748
749 plugin_name = bt_plugin_get_name(plugin);
750 path = bt_plugin_get_path(plugin);
751 author = bt_plugin_get_author(plugin);
752 license = bt_plugin_get_license(plugin);
753 plugin_description = bt_plugin_get_description(plugin);
754 version_status = bt_plugin_get_version(plugin, &major, &minor,
755 &patch, &extra);
756 printf("%s%s%s%s:\n", bt_common_color_bold(),
757 bt_common_color_fg_blue(), plugin_name,
758 bt_common_color_reset());
759 printf(" %sPath%s: %s\n", bt_common_color_bold(),
760 bt_common_color_reset(), path ? path : "(None)");
761
762 if (version_status == BT_PLUGIN_STATUS_OK) {
763 printf(" %sVersion%s: %u.%u.%u",
764 bt_common_color_bold(), bt_common_color_reset(),
765 major, minor, patch);
766
767 if (extra) {
768 printf("%s", extra);
769 }
770
771 printf("\n");
772 }
773
774 printf(" %sDescription%s: %s\n", bt_common_color_bold(),
775 bt_common_color_reset(),
776 plugin_description ? plugin_description : "(None)");
777 printf(" %sAuthor%s: %s\n", bt_common_color_bold(),
778 bt_common_color_reset(), author ? author : "(Unknown)");
779 printf(" %sLicense%s: %s\n", bt_common_color_bold(),
780 bt_common_color_reset(),
781 license ? license : "(Unknown)");
782}
783
a67681c1 784static int cmd_query(struct bt_config *cfg)
63ce0e1d
PP
785{
786 int ret;
787 struct bt_component_class *comp_cls = NULL;
788 struct bt_value *results = NULL;
789
db0f160a 790 ret = load_all_plugins(cfg->plugin_paths);
63ce0e1d
PP
791 if (ret) {
792 goto end;
793 }
794
a67681c1 795 comp_cls = find_component_class(cfg->cmd_data.query.cfg_component->plugin_name->str,
db0f160a 796 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
a67681c1 797 cfg->cmd_data.query.cfg_component->type);
63ce0e1d
PP
798 if (!comp_cls) {
799 fprintf(stderr, "%s%sCannot find component class %s",
800 bt_common_color_bold(),
801 bt_common_color_fg_red(),
802 bt_common_color_reset());
803 print_plugin_comp_cls_opt(stderr,
a67681c1 804 cfg->cmd_data.query.cfg_component->plugin_name->str,
db0f160a 805 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
a67681c1 806 cfg->cmd_data.query.cfg_component->type);
63ce0e1d
PP
807 fprintf(stderr, "\n");
808 ret = -1;
809 goto end;
810 }
811
a67681c1
PP
812 results = bt_component_class_query(comp_cls,
813 cfg->cmd_data.query.object->str,
814 cfg->cmd_data.query.cfg_component->params);
63ce0e1d
PP
815 if (!results) {
816 fprintf(stderr, "%s%sFailed to query info to %s",
817 bt_common_color_bold(),
818 bt_common_color_fg_red(),
819 bt_common_color_reset());
820 print_plugin_comp_cls_opt(stderr,
a67681c1 821 cfg->cmd_data.query.cfg_component->plugin_name->str,
db0f160a 822 cfg->cmd_data.query.cfg_component->comp_cls_name->str,
a67681c1
PP
823 cfg->cmd_data.query.cfg_component->type);
824 fprintf(stderr, "%s%s with object `%s`%s\n",
63ce0e1d
PP
825 bt_common_color_bold(),
826 bt_common_color_fg_red(),
a67681c1 827 cfg->cmd_data.query.object->str,
63ce0e1d
PP
828 bt_common_color_reset());
829 ret = -1;
830 goto end;
831 }
832
833 print_value(results, 0);
834
835end:
836 bt_put(comp_cls);
837 bt_put(results);
838 return ret;
839}
840
22e22462
PP
841static int cmd_help(struct bt_config *cfg)
842{
843 int ret;
844 struct bt_plugin *plugin = NULL;
845 size_t i;
846
db0f160a 847 ret = load_all_plugins(cfg->plugin_paths);
22e22462
PP
848 if (ret) {
849 goto end;
850 }
851
90de159b 852 plugin = find_plugin(cfg->cmd_data.help.cfg_component->plugin_name->str);
22e22462
PP
853 if (!plugin) {
854 fprintf(stderr, "%s%sCannot find plugin %s%s%s\n",
855 bt_common_color_bold(), bt_common_color_fg_red(),
856 bt_common_color_fg_blue(),
90de159b 857 cfg->cmd_data.help.cfg_component->plugin_name->str,
22e22462
PP
858 bt_common_color_reset());
859 ret = -1;
860 goto end;
861 }
862
863 print_plugin_info(plugin);
864 printf(" %sComponent classes%s: %d\n",
865 bt_common_color_bold(),
866 bt_common_color_reset(),
867 bt_plugin_get_component_class_count(plugin));
868
869
90de159b 870 if (cfg->cmd_data.help.cfg_component->type !=
22e22462
PP
871 BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
872 struct bt_component_class *needed_comp_cls =
873 find_component_class(
90de159b 874 cfg->cmd_data.help.cfg_component->plugin_name->str,
db0f160a 875 cfg->cmd_data.help.cfg_component->comp_cls_name->str,
90de159b 876 cfg->cmd_data.help.cfg_component->type);
22e22462
PP
877
878 if (!needed_comp_cls) {
879 fprintf(stderr, "\n%s%sCannot find component class %s",
880 bt_common_color_bold(),
881 bt_common_color_fg_red(),
882 bt_common_color_reset());
883 print_plugin_comp_cls_opt(stderr,
90de159b 884 cfg->cmd_data.help.cfg_component->plugin_name->str,
db0f160a 885 cfg->cmd_data.help.cfg_component->comp_cls_name->str,
90de159b 886 cfg->cmd_data.help.cfg_component->type);
22e22462
PP
887 fprintf(stderr, "\n");
888 ret = -1;
889 goto end;
890 }
891
892 bt_put(needed_comp_cls);
893 }
894
895 for (i = 0; i < bt_plugin_get_component_class_count(plugin); i++) {
896 struct bt_component_class *comp_cls =
897 bt_plugin_get_component_class(plugin, i);
898 const char *comp_class_name =
899 bt_component_class_get_name(comp_cls);
900 const char *comp_class_description =
901 bt_component_class_get_description(comp_cls);
902 const char *comp_class_help =
903 bt_component_class_get_help(comp_cls);
904 enum bt_component_class_type type =
905 bt_component_class_get_type(comp_cls);
906
907 assert(comp_cls);
908
90de159b 909 if (cfg->cmd_data.help.cfg_component->type !=
22e22462 910 BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
db0f160a 911 if (strcmp(cfg->cmd_data.help.cfg_component->comp_cls_name->str,
22e22462
PP
912 comp_class_name) != 0 &&
913 type ==
90de159b 914 cfg->cmd_data.help.cfg_component->type) {
22e22462
PP
915 bt_put(comp_cls);
916 continue;
917 }
918 }
919
920 printf("\n");
921 print_plugin_comp_cls_opt(stdout,
90de159b 922 cfg->cmd_data.help.cfg_component->plugin_name->str,
22e22462
PP
923 comp_class_name,
924 type);
925 printf("\n");
926 printf(" %sDescription%s: %s\n", bt_common_color_bold(),
927 bt_common_color_reset(),
928 comp_class_description ? comp_class_description : "(None)");
929
930 if (comp_class_help) {
931 printf("\n%s\n", comp_class_help);
932 }
933
934 bt_put(comp_cls);
935 }
936
937end:
938 bt_put(plugin);
939 return ret;
940}
941
290725f7
PP
942static int cmd_list_plugins(struct bt_config *cfg)
943{
944 int ret;
945 int plugins_count, component_classes_count = 0, i;
946
db0f160a 947 ret = load_all_plugins(cfg->plugin_paths);
290725f7 948 if (ret) {
56a1cced
JG
949 goto end;
950 }
951
22e22462 952 printf("From the following plugin paths:\n\n");
db0f160a 953 print_value(cfg->plugin_paths, 2);
22e22462 954 printf("\n");
290725f7
PP
955 plugins_count = loaded_plugins->len;
956 if (plugins_count == 0) {
957 fprintf(stderr, "%s%sNo plugins found.%s\n",
958 bt_common_color_bold(), bt_common_color_fg_red(),
959 bt_common_color_reset());
960 fprintf(stderr, "\n");
961 fprintf(stderr, "Please make sure your plugin search path is set correctly. You can use\n");
962 fprintf(stderr, "the --plugin-path command-line option or the BABELTRACE_PLUGIN_PATH\n");
963 fprintf(stderr, "environment variable.\n");
56a1cced
JG
964 ret = -1;
965 goto end;
966 }
967
290725f7
PP
968 for (i = 0; i < plugins_count; i++) {
969 struct bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i);
970
971 component_classes_count += bt_plugin_get_component_class_count(plugin);
972 }
33bceaf8 973
290725f7
PP
974 printf("Found %s%d%s component classes in %s%d%s plugins.\n",
975 bt_common_color_bold(),
976 component_classes_count,
977 bt_common_color_reset(),
978 bt_common_color_bold(),
979 plugins_count,
980 bt_common_color_reset());
981
982 for (i = 0; i < plugins_count; i++) {
983 int j;
984 struct bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i);
290725f7
PP
985
986 component_classes_count =
987 bt_plugin_get_component_class_count(plugin);
22e22462
PP
988 printf("\n");
989 print_plugin_info(plugin);
290725f7
PP
990
991 if (component_classes_count == 0) {
992 printf(" %sComponent classes%s: (None)\n",
993 bt_common_color_bold(),
994 bt_common_color_reset());
995 } else {
996 printf(" %sComponent classes%s:\n",
997 bt_common_color_bold(),
998 bt_common_color_reset());
999 }
1000
1001 for (j = 0; j < component_classes_count; j++) {
1002 struct bt_component_class *comp_class =
1003 bt_plugin_get_component_class(plugin, j);
1004 const char *comp_class_name =
1005 bt_component_class_get_name(comp_class);
1006 const char *comp_class_description =
1007 bt_component_class_get_description(comp_class);
1008 enum bt_component_class_type type =
1009 bt_component_class_get_type(comp_class);
1010
22e22462
PP
1011 printf(" ");
1012 print_plugin_comp_cls_opt(stdout,
1013 bt_plugin_get_name(plugin), comp_class_name,
1014 type);
290725f7
PP
1015
1016 if (comp_class_description) {
1017 printf(": %s", comp_class_description);
1018 }
1019
1020 printf("\n");
1021 bt_put(comp_class);
1022 }
1023 }
1024
1025end:
1026 return ret;
1027}
1028
db0f160a
PP
1029static int cmd_print_lttng_live_sessions(struct bt_config *cfg)
1030{
1031 printf("TODO\n");
1032 return -1;
1033}
1034
1035static int cmd_print_ctf_metadata(struct bt_config *cfg)
05a67631
PP
1036{
1037 int ret = 0;
1038 struct bt_component_class *comp_cls = NULL;
05a67631 1039 struct bt_value *results = NULL;
05a67631
PP
1040 struct bt_value *params = NULL;
1041 struct bt_value *metadata_text_value = NULL;
1042 const char *metadata_text = NULL;
db0f160a
PP
1043 static const char * const plugin_name = "ctf";
1044 static const char * const comp_cls_name = "fs";
1045 static const enum bt_component_class_type comp_cls_type =
1046 BT_COMPONENT_CLASS_TYPE_SOURCE;
1047
1048 assert(cfg->cmd_data.print_ctf_metadata.path);
1049 comp_cls = find_component_class(plugin_name, comp_cls_name,
1050 comp_cls_type);
05a67631
PP
1051 if (!comp_cls) {
1052 fprintf(stderr, "%s%sCannot find component class %s",
1053 bt_common_color_bold(),
1054 bt_common_color_fg_red(),
1055 bt_common_color_reset());
db0f160a
PP
1056 print_plugin_comp_cls_opt(stderr, plugin_name,
1057 comp_cls_name, comp_cls_type);
05a67631
PP
1058 fprintf(stderr, "\n");
1059 ret = -1;
1060 goto end;
1061 }
1062
05a67631
PP
1063 params = bt_value_map_create();
1064 if (!params) {
1065 ret = -1;
1066 goto end;
1067 }
1068
db0f160a
PP
1069 ret = bt_value_map_insert_string(params, "path",
1070 cfg->cmd_data.print_ctf_metadata.path->str);
05a67631
PP
1071 if (ret) {
1072 ret = -1;
1073 goto end;
1074 }
1075
a67681c1 1076 results = bt_component_class_query(comp_cls, "metadata-info",
05a67631
PP
1077 params);
1078 if (!results) {
1079 ret = -1;
a67681c1 1080 fprintf(stderr, "%s%sFailed to request metadata info%s\n",
05a67631
PP
1081 bt_common_color_bold(),
1082 bt_common_color_fg_red(),
1083 bt_common_color_reset());
1084 goto end;
1085 }
1086
1087 metadata_text_value = bt_value_map_get(results, "text");
1088 if (!metadata_text_value) {
1089 ret = -1;
1090 goto end;
1091 }
1092
1093 ret = bt_value_string_get(metadata_text_value, &metadata_text);
1094 assert(ret == 0);
1095 printf("%s\n", metadata_text);
1096
1097end:
1098 bt_put(results);
05a67631
PP
1099 bt_put(params);
1100 bt_put(metadata_text_value);
1101 bt_put(comp_cls);
05a67631
PP
1102 return 0;
1103}
1104
db0f160a 1105static int cmd_run(struct bt_config *cfg)
290725f7
PP
1106{
1107 int ret = 0;
1108 struct bt_component_class *source_class = NULL;
1109 struct bt_component_class *sink_class = NULL;
1110 struct bt_component *source = NULL, *sink = NULL;
1111 struct bt_value *source_params = NULL, *sink_params = NULL;
290725f7 1112 struct bt_config_component *source_cfg = NULL, *sink_cfg = NULL;
61ddbc8a 1113 struct bt_graph *graph = NULL;
290725f7 1114
db0f160a 1115 ret = load_all_plugins(cfg->plugin_paths);
05a67631 1116 if (ret) {
05a67631
PP
1117 goto end;
1118 }
1119
290725f7 1120 /* TODO handle more than 1 source and 1 sink. */
db0f160a
PP
1121 if (cfg->cmd_data.run.sources->len != 1 ||
1122 cfg->cmd_data.run.sinks->len != 1) {
ebba3338 1123 fprintf(stderr, "Only one source and one sink component class are supported. Aborting...\n");
98ecef32
MD
1124 ret = -1;
1125 goto end;
33bceaf8
JG
1126 }
1127
db0f160a 1128 source_cfg = bt_config_get_component(cfg->cmd_data.run.sources, 0);
e5bc7f81 1129 source_params = bt_get(source_cfg->params);
33b34c43 1130 source_class = find_component_class(source_cfg->plugin_name->str,
db0f160a 1131 source_cfg->comp_cls_name->str,
d3e4dcd8 1132 BT_COMPONENT_CLASS_TYPE_SOURCE);
56a1cced 1133 if (!source_class) {
87796884
PP
1134 fprintf(stderr, "Could not find ");
1135 print_plugin_comp_cls_opt(stderr, source_cfg->plugin_name->str,
db0f160a 1136 source_cfg->comp_cls_name->str, BT_COMPONENT_CLASS_TYPE_SOURCE);
87796884 1137 fprintf(stderr, ". Aborting...\n");
56a1cced
JG
1138 ret = -1;
1139 goto end;
1140 }
7c7c0433 1141
db0f160a 1142 sink_cfg = bt_config_get_component(cfg->cmd_data.run.sinks, 0);
e5bc7f81 1143 sink_params = bt_get(sink_cfg->params);
33b34c43 1144 sink_class = find_component_class(sink_cfg->plugin_name->str,
db0f160a 1145 sink_cfg->comp_cls_name->str,
d3e4dcd8 1146 BT_COMPONENT_CLASS_TYPE_SINK);
7c7c0433 1147 if (!sink_class) {
87796884
PP
1148 fprintf(stderr, "Could not find ");
1149 print_plugin_comp_cls_opt(stderr, sink_cfg->plugin_name->str,
db0f160a 1150 sink_cfg->comp_cls_name->str, BT_COMPONENT_CLASS_TYPE_SINK);
87796884 1151 fprintf(stderr, ". Aborting...\n");
7c7c0433
JG
1152 ret = -1;
1153 goto end;
1154 }
1155
61ddbc8a
JG
1156 graph = bt_graph_create();
1157 if (!graph) {
1158 ret = -1;
1159 goto end;
1160 }
1161
e5bc7f81 1162 source = bt_component_create(source_class, "source", source_params);
56a1cced 1163 if (!source) {
e5bc7f81 1164 fprintf(stderr, "Failed to instantiate selected source component. Aborting...\n");
c42c79ea
PP
1165 ret = -1;
1166 goto end;
1167 }
56a1cced 1168
e5bc7f81 1169 sink = bt_component_create(sink_class, "sink", sink_params);
7c7c0433 1170 if (!sink) {
e5bc7f81 1171 fprintf(stderr, "Failed to instantiate selected output component. Aborting...\n");
7c7c0433 1172 ret = -1;
2e339de1
JG
1173 goto end;
1174 }
1175
61ddbc8a 1176 ret = connect_source_sink(graph, source, source_cfg, sink);
6c2f3ee5 1177 if (ret) {
290725f7 1178 ret = -1;
fec2a9f2
JG
1179 goto end;
1180 }
78586d8a 1181
fec2a9f2 1182 while (true) {
61ddbc8a
JG
1183 enum bt_graph_status graph_status;
1184
72b913fb 1185 graph_status = bt_graph_run(graph);
61ddbc8a
JG
1186 switch (graph_status) {
1187 case BT_GRAPH_STATUS_AGAIN:
fec2a9f2
JG
1188 /* Wait for an arbitraty 500 ms. */
1189 usleep(500000);
78586d8a 1190 break;
fec2a9f2
JG
1191 case BT_COMPONENT_STATUS_END:
1192 goto end;
1193 default:
1194 fprintf(stderr, "Sink component returned an error, aborting...\n");
1195 ret = -1;
1196 goto end;
78586d8a 1197 }
fec2a9f2 1198 }
290725f7 1199
11e1d048 1200end:
61ddbc8a
JG
1201 bt_put(sink_class);
1202 bt_put(source_class);
1203 bt_put(source);
1204 bt_put(sink);
1205 bt_put(source_params);
1206 bt_put(sink_params);
1207 bt_put(sink_cfg);
1208 bt_put(source_cfg);
1209 bt_put(graph);
290725f7
PP
1210 return ret;
1211}
1212
1213static void warn_command_name_and_directory_clash(struct bt_config *cfg)
1214{
1215 if (!cfg->command_name) {
1216 return;
1217 }
1218
1219 if (g_file_test(cfg->command_name,
1220 G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
1221 fprintf(stderr, "\nNOTE: The `%s` command was executed. If you meant to convert a\n",
1222 cfg->command_name);
1223 fprintf(stderr, "trace located in the local `%s` directory, please use:\n",
1224 cfg->command_name);
1225 fprintf(stderr, "\n");
1226 fprintf(stderr, " babeltrace convert %s [OPTIONS]\n",
1227 cfg->command_name);
1228 }
1229}
1230
1231int main(int argc, const char **argv)
1232{
1233 int ret;
1234 int retcode;
1235 struct bt_config *cfg;
1236
1237 init_loaded_plugins_array();
1238 cfg = bt_config_from_args_with_defaults(argc, argv, &retcode);
1239
1240 if (retcode < 0) {
1241 /* Quit without errors; typically usage/version */
1242 retcode = 0;
1243 goto end;
1244 }
1245
1246 if (retcode > 0) {
1247 goto end;
1248 }
1249
1250 if (!cfg) {
1251 fprintf(stderr, "Failed to create Babeltrace configuration\n");
db0f160a 1252 retcode = 1;
290725f7
PP
1253 goto end;
1254 }
1255
1256 babeltrace_debug = cfg->debug;
1257 babeltrace_verbose = cfg->verbose;
1258 print_cfg(cfg);
1259
db0f160a
PP
1260 if (cfg->command_needs_plugins) {
1261 ret = load_all_plugins(cfg->plugin_paths);
1262 if (ret) {
1263 retcode = 1;
1264 goto end;
1265 }
1266 }
1267
290725f7 1268 switch (cfg->command) {
db0f160a
PP
1269 case BT_CONFIG_COMMAND_RUN:
1270 ret = cmd_run(cfg);
290725f7
PP
1271 break;
1272 case BT_CONFIG_COMMAND_LIST_PLUGINS:
1273 ret = cmd_list_plugins(cfg);
1274 break;
22e22462
PP
1275 case BT_CONFIG_COMMAND_HELP:
1276 ret = cmd_help(cfg);
1277 break;
a67681c1
PP
1278 case BT_CONFIG_COMMAND_QUERY:
1279 ret = cmd_query(cfg);
63ce0e1d 1280 break;
db0f160a
PP
1281 case BT_CONFIG_COMMAND_PRINT_CTF_METADATA:
1282 ret = cmd_print_ctf_metadata(cfg);
1283 break;
1284 case BT_CONFIG_COMMAND_PRINT_LTTNG_LIVE_SESSIONS:
1285 ret = cmd_print_lttng_live_sessions(cfg);
1286 break;
290725f7
PP
1287 default:
1288 assert(false);
1289 }
1290
1291 warn_command_name_and_directory_clash(cfg);
1292 retcode = ret ? 1 : 0;
1293
1294end:
1295 BT_PUT(cfg);
33b34c43 1296 fini_loaded_plugins_array();
290725f7 1297 return retcode;
4c8bfb7e 1298}
This page took 0.111422 seconds and 4 git commands to generate.