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