babeltrace(1): add the query-info command
[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>
33b34c43 32#include <babeltrace/component/component.h>
d71dcf2c
PP
33#include <babeltrace/component/component-source.h>
34#include <babeltrace/component/component-sink.h>
35#include <babeltrace/component/component-filter.h>
33b34c43
PP
36#include <babeltrace/component/component-class.h>
37#include <babeltrace/component/notification/iterator.h>
2e339de1
JG
38#include <babeltrace/ref.h>
39#include <babeltrace/values.h>
34ac0e6c 40#include <stdlib.h>
a44bc4c9 41#include <babeltrace/ctf-ir/metadata.h> /* for clocks */
7f26a816
PP
42#include <popt.h>
43#include <string.h>
44#include <stdio.h>
33b34c43 45#include <glib.h>
c42c79ea 46#include "babeltrace-cfg.h"
ebba3338 47#include "babeltrace-cfg-connect.h"
c1870f57 48#include "default-cfg.h"
34ac0e6c 49
33b34c43
PP
50GPtrArray *loaded_plugins;
51
52static
53void init_loaded_plugins_array(void)
54{
55 loaded_plugins = g_ptr_array_new_full(8, bt_put);
56}
57
58static
59void fini_loaded_plugins_array(void)
60{
61 g_ptr_array_free(loaded_plugins, TRUE);
62}
63
64static
65struct bt_plugin *find_plugin(const char *name)
66{
67 int i;
68 struct bt_plugin *plugin = NULL;
69
70 for (i = 0; i < loaded_plugins->len; i++) {
71 plugin = g_ptr_array_index(loaded_plugins, i);
72
73 if (strcmp(name, bt_plugin_get_name(plugin)) == 0) {
74 break;
75 }
76
77 plugin = NULL;
78 }
79
80 return bt_get(plugin);
81}
82
83static
84struct bt_component_class *find_component_class(const char *plugin_name,
85 const char *comp_class_name,
d3e4dcd8 86 enum bt_component_class_type comp_class_type)
33b34c43
PP
87{
88 struct bt_component_class *comp_class = NULL;
89 struct bt_plugin *plugin = find_plugin(plugin_name);
90
91 if (!plugin) {
92 goto end;
93 }
94
95 comp_class = bt_plugin_get_component_class_by_name_and_type(plugin,
96 comp_class_name, comp_class_type);
97 BT_PUT(plugin);
98end:
99 return comp_class;
100}
6c2f3ee5 101
c42c79ea
PP
102static
103void print_indent(size_t indent)
104{
105 size_t i;
106
107 for (i = 0; i < indent; i++) {
00447e45 108 printf(" ");
c42c79ea
PP
109 }
110}
111
112static
290725f7 113void print_value(struct bt_value *, size_t);
c42c79ea
PP
114
115static
116bool print_map_value(const char *key, struct bt_value *object, void *data)
117{
290725f7
PP
118 size_t *indent = data;
119
120 print_indent(*indent);
121 printf("%s: ", key);
122
123 if (bt_value_is_array(object) &&
124 bt_value_array_is_empty(object)) {
125 printf("[ ]\n");
126 return true;
127 }
128
129 if (bt_value_is_map(object) &&
130 bt_value_map_is_empty(object)) {
131 printf("{ }\n");
132 return true;
133 }
c42c79ea 134
290725f7
PP
135 if (bt_value_is_array(object) ||
136 bt_value_is_map(object)) {
137 printf("\n");
138 }
c42c79ea 139
290725f7 140 print_value(object, *indent + 2);
c42c79ea
PP
141 return true;
142}
143
144static
290725f7 145void print_value(struct bt_value *value, size_t indent)
c42c79ea
PP
146{
147 bool bool_val;
148 int64_t int_val;
149 double dbl_val;
150 const char *str_val;
151 int size;
152 int i;
153
154 if (!value) {
155 return;
156 }
157
c42c79ea
PP
158 switch (bt_value_get_type(value)) {
159 case BT_VALUE_TYPE_NULL:
00447e45 160 printf("null\n");
c42c79ea
PP
161 break;
162 case BT_VALUE_TYPE_BOOL:
163 bt_value_bool_get(value, &bool_val);
290725f7 164 printf("%s\n", bool_val ? "yes" : "no");
c42c79ea
PP
165 break;
166 case BT_VALUE_TYPE_INTEGER:
167 bt_value_integer_get(value, &int_val);
00447e45 168 printf("%" PRId64 "\n", int_val);
c42c79ea
PP
169 break;
170 case BT_VALUE_TYPE_FLOAT:
171 bt_value_float_get(value, &dbl_val);
00447e45 172 printf("%lf\n", dbl_val);
c42c79ea
PP
173 break;
174 case BT_VALUE_TYPE_STRING:
175 bt_value_string_get(value, &str_val);
290725f7 176 printf("%s\n", str_val);
c42c79ea
PP
177 break;
178 case BT_VALUE_TYPE_ARRAY:
179 size = bt_value_array_size(value);
290725f7
PP
180 assert(size >= 0);
181
182 if (size == 0) {
183 print_indent(indent);
184 printf("[ ]\n");
185 break;
186 }
c42c79ea
PP
187
188 for (i = 0; i < size; i++) {
189 struct bt_value *element =
190 bt_value_array_get(value, i);
191
290725f7
PP
192 assert(element);
193 print_indent(indent);
194 printf("- ");
195
196 if (bt_value_is_array(element) &&
197 bt_value_array_is_empty(element)) {
198 printf("[ ]\n");
199 continue;
200 }
201
202 if (bt_value_is_map(element) &&
203 bt_value_map_is_empty(element)) {
204 printf("{ }\n");
205 continue;
206 }
207
208 if (bt_value_is_array(element) ||
209 bt_value_is_map(element)) {
210 printf("\n");
211 }
212
213 print_value(element, indent + 2);
c42c79ea
PP
214 BT_PUT(element);
215 }
c42c79ea
PP
216 break;
217 case BT_VALUE_TYPE_MAP:
218 if (bt_value_map_is_empty(value)) {
290725f7
PP
219 print_indent(indent);
220 printf("{ }\n");
221 break;
c42c79ea
PP
222 }
223
290725f7 224 bt_value_map_foreach(value, print_map_value, &indent);
c42c79ea
PP
225 break;
226 default:
227 assert(false);
228 }
229}
230
231static
232void print_bt_config_component(struct bt_config_component *bt_config_component)
233{
290725f7 234 printf(" %s.%s:\n", bt_config_component->plugin_name->str,
c42c79ea 235 bt_config_component->component_name->str);
3b6cfcc5
PP
236
237 if (bt_config_component->instance_name->len > 0) {
238 printf(" Name: %s\n",
239 bt_config_component->instance_name->str);
240 }
241
290725f7
PP
242 printf(" Parameters:\n");
243 print_value(bt_config_component->params, 8);
c42c79ea
PP
244}
245
246static
247void print_bt_config_components(GPtrArray *array)
248{
249 size_t i;
250
251 for (i = 0; i < array->len; i++) {
252 struct bt_config_component *cfg_component =
e5bc7f81 253 bt_config_get_component(array, i);
c42c79ea
PP
254 print_bt_config_component(cfg_component);
255 BT_PUT(cfg_component);
256 }
257}
258
290725f7
PP
259static
260void print_plugin_paths(struct bt_value *plugin_paths)
261{
262 printf(" Plugin paths:\n");
263 print_value(plugin_paths, 4);
264}
265
266static
267void print_cfg_convert(struct bt_config *cfg)
268{
ebba3338
PP
269 size_t i;
270
290725f7
PP
271 printf(" Force correlate: %s\n",
272 cfg->cmd_data.convert.force_correlate ? "yes" : "no");
273 print_plugin_paths(cfg->cmd_data.convert.plugin_paths);
274 printf(" Source component instances:\n");
275 print_bt_config_components(cfg->cmd_data.convert.sources);
ebba3338
PP
276
277 if (cfg->cmd_data.convert.filters->len > 0) {
278 printf(" Filter component instances:\n");
279 print_bt_config_components(cfg->cmd_data.convert.filters);
280 }
281
290725f7
PP
282 printf(" Sink component instances:\n");
283 print_bt_config_components(cfg->cmd_data.convert.sinks);
ebba3338
PP
284 printf(" Connections:\n");
285
286 for (i = 0; i < cfg->cmd_data.convert.connections->len; i++) {
287 struct bt_config_connection *cfg_connection =
288 g_ptr_array_index(cfg->cmd_data.convert.connections,
289 i);
290
291 printf(" %s%s%s -> %s%s%s\n",
292 cfg_connection->src_instance_name->str,
293 cfg_connection->src_port_name->len > 0 ? "." : "",
294 cfg_connection->src_port_name->str,
295 cfg_connection->dst_instance_name->str,
296 cfg_connection->dst_port_name->len > 0 ? "." : "",
297 cfg_connection->dst_port_name->str);
298 }
290725f7
PP
299}
300
301static
302void print_cfg_list_plugins(struct bt_config *cfg)
303{
304 print_plugin_paths(cfg->cmd_data.list_plugins.plugin_paths);
305}
306
c42c79ea
PP
307static
308void print_cfg(struct bt_config *cfg)
309{
00447e45
PP
310 if (!babeltrace_verbose) {
311 return;
312 }
313
290725f7
PP
314 printf("Configuration:\n");
315 printf(" Debug mode: %s\n", cfg->debug ? "yes" : "no");
316 printf(" Verbose mode: %s\n", cfg->verbose ? "yes" : "no");
317
318 switch (cfg->command) {
319 case BT_CONFIG_COMMAND_CONVERT:
320 print_cfg_convert(cfg);
321 break;
322 case BT_CONFIG_COMMAND_LIST_PLUGINS:
323 print_cfg_list_plugins(cfg);
324 break;
325 default:
326 assert(false);
327 }
c42c79ea
PP
328}
329
6c2f3ee5
JG
330static
331struct bt_component *create_trimmer(struct bt_config_component *source_cfg)
332{
333 struct bt_component *trimmer = NULL;
334 struct bt_component_class *trimmer_class = NULL;
335 struct bt_value *trimmer_params = NULL;
528debdf 336 struct bt_value *value;
6c2f3ee5 337
6c2f3ee5
JG
338 trimmer_params = bt_value_map_create();
339 if (!trimmer_params) {
340 goto end;
341 }
342
528debdf
MD
343 value = bt_value_map_get(source_cfg->params, "begin");
344 if (value) {
6c2f3ee5 345 enum bt_value_status ret;
6c2f3ee5 346
528debdf 347 ret = bt_value_map_insert(trimmer_params, "begin",
6c2f3ee5
JG
348 value);
349 BT_PUT(value);
350 if (ret) {
351 goto end;
352 }
353 }
528debdf
MD
354 value = bt_value_map_get(source_cfg->params, "end");
355 if (value) {
6c2f3ee5 356 enum bt_value_status ret;
6c2f3ee5 357
528debdf
MD
358 ret = bt_value_map_insert(trimmer_params, "end",
359 value);
360 BT_PUT(value);
361 if (ret) {
6c2f3ee5
JG
362 goto end;
363 }
528debdf
MD
364 }
365 value = bt_value_map_get(source_cfg->params, "clock-gmt");
366 if (value) {
367 enum bt_value_status ret;
6c2f3ee5 368
528debdf 369 ret = bt_value_map_insert(trimmer_params, "clock-gmt",
6c2f3ee5
JG
370 value);
371 BT_PUT(value);
372 if (ret) {
373 goto end;
374 }
375 }
376
33b34c43 377 trimmer_class = find_component_class("utils", "trimmer",
d3e4dcd8 378 BT_COMPONENT_CLASS_TYPE_FILTER);
6c2f3ee5
JG
379 if (!trimmer_class) {
380 fprintf(stderr, "Could not find trimmer component class. Aborting...\n");
381 goto end;
382 }
383 trimmer = bt_component_create(trimmer_class, "source_trimmer",
384 trimmer_params);
385 if (!trimmer) {
386 goto end;
387 }
388end:
389 bt_put(trimmer_params);
390 bt_put(trimmer_class);
391 return trimmer;
392}
393
394static
395int connect_source_sink(struct bt_component *source,
396 struct bt_config_component *source_cfg,
397 struct bt_component *sink)
398{
399 int ret = 0;
400 enum bt_component_status sink_status;
401 struct bt_component *trimmer = NULL;
402 struct bt_notification_iterator *source_it = NULL;
403 struct bt_notification_iterator *to_sink_it = NULL;
404
c725abdd 405 source_it = bt_component_source_create_notification_iterator(source);
6c2f3ee5
JG
406 if (!source_it) {
407 fprintf(stderr, "Failed to instantiate source iterator. Aborting...\n");
408 ret = -1;
409 goto end;
410 }
411
528debdf
MD
412 if (bt_value_map_has_key(source_cfg->params, "begin")
413 || bt_value_map_has_key(source_cfg->params, "end")) {
6c2f3ee5
JG
414 /* A trimmer must be inserted in the graph. */
415 enum bt_component_status trimmer_status;
416
417 trimmer = create_trimmer(source_cfg);
418 if (!trimmer) {
419 fprintf(stderr, "Failed to create trimmer component. Aborting...\n");
420 ret = -1;
421 goto end;
422 }
423
424 trimmer_status = bt_component_filter_add_iterator(trimmer,
425 source_it);
426 BT_PUT(source_it);
427 if (trimmer_status != BT_COMPONENT_STATUS_OK) {
428 fprintf(stderr, "Failed to connect source to trimmer. Aborting...\n");
429 ret = -1;
430 goto end;
431 }
432
c725abdd 433 to_sink_it = bt_component_filter_create_notification_iterator(trimmer);
6c2f3ee5
JG
434 if (!to_sink_it) {
435 fprintf(stderr, "Failed to instantiate trimmer iterator. Aborting...\n");
436 ret = -1;
437 goto end;
438 }
439 } else {
440 BT_MOVE(to_sink_it, source_it);
441 }
442
443 sink_status = bt_component_sink_add_iterator(sink, to_sink_it);
444 if (sink_status != BT_COMPONENT_STATUS_OK) {
445 fprintf(stderr, "Failed to connect to sink component. Aborting...\n");
446 ret = -1;
447 goto end;
448 }
449end:
450 bt_put(trimmer);
451 bt_put(source_it);
452 bt_put(to_sink_it);
453 return ret;
454}
455
33b34c43
PP
456static
457void add_to_loaded_plugins(struct bt_plugin **plugins)
98ecef32 458{
33b34c43
PP
459 while (*plugins) {
460 struct bt_plugin *plugin = *plugins;
461 /* Check if it's already loaded (from another path). */
462 struct bt_plugin *loaded_plugin =
463 find_plugin(bt_plugin_get_name(plugin));
464
465 if (loaded_plugin) {
466 printf_verbose("Not loading plugin `%s`: already loaded from `%s`\n",
467 bt_plugin_get_path(plugin),
468 bt_plugin_get_path(loaded_plugin));
469 BT_PUT(loaded_plugin);
470 BT_PUT(plugin);
471 } else {
472 /* Transfer ownership to global array. */
473 g_ptr_array_add(loaded_plugins, plugin);
474 }
475 *(plugins++) = NULL;
476 }
477}
478
479static
290725f7 480int load_dynamic_plugins(struct bt_value *plugin_paths)
33b34c43
PP
481{
482 int nr_paths, i, ret = 0;
98ecef32 483
290725f7 484 nr_paths = bt_value_array_size(plugin_paths);
98ecef32 485 if (nr_paths < 0) {
33b34c43
PP
486 ret = -1;
487 goto end;
98ecef32 488 }
33b34c43 489
98ecef32
MD
490 for (i = 0; i < nr_paths; i++) {
491 struct bt_value *plugin_path_value = NULL;
492 const char *plugin_path;
33b34c43 493 struct bt_plugin **plugins;
98ecef32 494
290725f7 495 plugin_path_value = bt_value_array_get(plugin_paths, i);
98ecef32
MD
496 if (bt_value_string_get(plugin_path_value,
497 &plugin_path)) {
498 BT_PUT(plugin_path_value);
499 continue;
500 }
33b34c43 501
5a3ee633 502 plugins = bt_plugin_create_all_from_dir(plugin_path, false);
33b34c43 503 if (!plugins) {
98ecef32
MD
504 printf_debug("Unable to dynamically load plugins from path %s.\n",
505 plugin_path);
33b34c43
PP
506 BT_PUT(plugin_path_value);
507 continue;
98ecef32 508 }
33b34c43
PP
509
510 add_to_loaded_plugins(plugins);
511 free(plugins);
512
98ecef32
MD
513 BT_PUT(plugin_path_value);
514 }
33b34c43
PP
515end:
516 return ret;
517}
518
519static
520int load_static_plugins(void)
521{
522 int ret = 0;
523 struct bt_plugin **plugins;
524
525 plugins = bt_plugin_create_all_from_static();
526 if (!plugins) {
527 printf_debug("Unable to load static plugins.\n");
528 ret = -1;
529 goto end;
530 }
531
532 add_to_loaded_plugins(plugins);
533 free(plugins);
534end:
535 return ret;
98ecef32
MD
536}
537
290725f7
PP
538static
539const char *component_type_str(enum bt_component_class_type type)
34ac0e6c 540{
290725f7
PP
541 switch (type) {
542 case BT_COMPONENT_CLASS_TYPE_SOURCE:
543 return "source";
544 case BT_COMPONENT_CLASS_TYPE_SINK:
545 return "sink";
546 case BT_COMPONENT_CLASS_TYPE_FILTER:
547 return "filter";
548 case BT_COMPONENT_CLASS_TYPE_UNKNOWN:
549 default:
550 return "unknown";
551 }
552}
c42c79ea 553
290725f7
PP
554static int load_all_plugins(struct bt_value *plugin_paths)
555{
556 int ret = 0;
33b34c43 557
290725f7
PP
558 if (load_dynamic_plugins(plugin_paths)) {
559 fprintf(stderr, "Failed to load dynamic plugins.\n");
560 ret = -1;
c1870f57
JG
561 goto end;
562 }
563
290725f7
PP
564 if (load_static_plugins()) {
565 fprintf(stderr, "Failed to load static plugins.\n");
566 ret = -1;
c1870f57
JG
567 goto end;
568 }
569
290725f7
PP
570end:
571 return ret;
572}
573
22e22462
PP
574static void print_plugin_info(struct bt_plugin *plugin)
575{
576 unsigned int major, minor, patch;
577 const char *extra;
578 enum bt_plugin_status version_status;
579 const char *plugin_name;
580 const char *path;
581 const char *author;
582 const char *license;
583 const char *plugin_description;
584
585 plugin_name = bt_plugin_get_name(plugin);
586 path = bt_plugin_get_path(plugin);
587 author = bt_plugin_get_author(plugin);
588 license = bt_plugin_get_license(plugin);
589 plugin_description = bt_plugin_get_description(plugin);
590 version_status = bt_plugin_get_version(plugin, &major, &minor,
591 &patch, &extra);
592 printf("%s%s%s%s:\n", bt_common_color_bold(),
593 bt_common_color_fg_blue(), plugin_name,
594 bt_common_color_reset());
595 printf(" %sPath%s: %s\n", bt_common_color_bold(),
596 bt_common_color_reset(), path ? path : "(None)");
597
598 if (version_status == BT_PLUGIN_STATUS_OK) {
599 printf(" %sVersion%s: %u.%u.%u",
600 bt_common_color_bold(), bt_common_color_reset(),
601 major, minor, patch);
602
603 if (extra) {
604 printf("%s", extra);
605 }
606
607 printf("\n");
608 }
609
610 printf(" %sDescription%s: %s\n", bt_common_color_bold(),
611 bt_common_color_reset(),
612 plugin_description ? plugin_description : "(None)");
613 printf(" %sAuthor%s: %s\n", bt_common_color_bold(),
614 bt_common_color_reset(), author ? author : "(Unknown)");
615 printf(" %sLicense%s: %s\n", bt_common_color_bold(),
616 bt_common_color_reset(),
617 license ? license : "(Unknown)");
618}
619
620static void print_plugin_comp_cls_opt(FILE *fh, const char *plugin_name,
621 const char *comp_cls_name, enum bt_component_class_type type)
622{
623 fprintf(fh, "%s%s--%s%s %s%s%s.%s%s%s",
624 bt_common_color_bold(),
625 bt_common_color_fg_cyan(),
626 component_type_str(type),
627 bt_common_color_fg_default(),
628 bt_common_color_fg_blue(),
629 plugin_name,
630 bt_common_color_fg_default(),
631 bt_common_color_fg_yellow(),
632 comp_cls_name,
633 bt_common_color_reset());
634}
635
63ce0e1d
PP
636static int cmd_query_info(struct bt_config *cfg)
637{
638 int ret;
639 struct bt_component_class *comp_cls = NULL;
640 struct bt_value *results = NULL;
641
642 ret = load_all_plugins(cfg->cmd_data.list_plugins.plugin_paths);
643 if (ret) {
644 goto end;
645 }
646
647 comp_cls = find_component_class(cfg->cmd_data.query_info.cfg_component->plugin_name->str,
648 cfg->cmd_data.query_info.cfg_component->component_name->str,
649 cfg->cmd_data.query_info.cfg_component->type);
650 if (!comp_cls) {
651 fprintf(stderr, "%s%sCannot find component class %s",
652 bt_common_color_bold(),
653 bt_common_color_fg_red(),
654 bt_common_color_reset());
655 print_plugin_comp_cls_opt(stderr,
656 cfg->cmd_data.query_info.cfg_component->plugin_name->str,
657 cfg->cmd_data.query_info.cfg_component->component_name->str,
658 cfg->cmd_data.query_info.cfg_component->type);
659 fprintf(stderr, "\n");
660 ret = -1;
661 goto end;
662 }
663
664 results = bt_component_class_query_info(comp_cls,
665 cfg->cmd_data.query_info.action->str,
666 cfg->cmd_data.query_info.cfg_component->params);
667 if (!results) {
668 fprintf(stderr, "%s%sFailed to query info to %s",
669 bt_common_color_bold(),
670 bt_common_color_fg_red(),
671 bt_common_color_reset());
672 print_plugin_comp_cls_opt(stderr,
673 cfg->cmd_data.query_info.cfg_component->plugin_name->str,
674 cfg->cmd_data.query_info.cfg_component->component_name->str,
675 cfg->cmd_data.query_info.cfg_component->type);
676 fprintf(stderr, "%s%s with action `%s`%s\n",
677 bt_common_color_bold(),
678 bt_common_color_fg_red(),
679 cfg->cmd_data.query_info.action->str,
680 bt_common_color_reset());
681 ret = -1;
682 goto end;
683 }
684
685 print_value(results, 0);
686
687end:
688 bt_put(comp_cls);
689 bt_put(results);
690 return ret;
691}
692
22e22462
PP
693static int cmd_help(struct bt_config *cfg)
694{
695 int ret;
696 struct bt_plugin *plugin = NULL;
697 size_t i;
698
699 ret = load_all_plugins(cfg->cmd_data.list_plugins.plugin_paths);
700 if (ret) {
701 goto end;
702 }
703
90de159b 704 plugin = find_plugin(cfg->cmd_data.help.cfg_component->plugin_name->str);
22e22462
PP
705 if (!plugin) {
706 fprintf(stderr, "%s%sCannot find plugin %s%s%s\n",
707 bt_common_color_bold(), bt_common_color_fg_red(),
708 bt_common_color_fg_blue(),
90de159b 709 cfg->cmd_data.help.cfg_component->plugin_name->str,
22e22462
PP
710 bt_common_color_reset());
711 ret = -1;
712 goto end;
713 }
714
715 print_plugin_info(plugin);
716 printf(" %sComponent classes%s: %d\n",
717 bt_common_color_bold(),
718 bt_common_color_reset(),
719 bt_plugin_get_component_class_count(plugin));
720
721
90de159b 722 if (cfg->cmd_data.help.cfg_component->type !=
22e22462
PP
723 BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
724 struct bt_component_class *needed_comp_cls =
725 find_component_class(
90de159b
PP
726 cfg->cmd_data.help.cfg_component->plugin_name->str,
727 cfg->cmd_data.help.cfg_component->component_name->str,
728 cfg->cmd_data.help.cfg_component->type);
22e22462
PP
729
730 if (!needed_comp_cls) {
731 fprintf(stderr, "\n%s%sCannot find component class %s",
732 bt_common_color_bold(),
733 bt_common_color_fg_red(),
734 bt_common_color_reset());
735 print_plugin_comp_cls_opt(stderr,
90de159b
PP
736 cfg->cmd_data.help.cfg_component->plugin_name->str,
737 cfg->cmd_data.help.cfg_component->component_name->str,
738 cfg->cmd_data.help.cfg_component->type);
22e22462
PP
739 fprintf(stderr, "\n");
740 ret = -1;
741 goto end;
742 }
743
744 bt_put(needed_comp_cls);
745 }
746
747 for (i = 0; i < bt_plugin_get_component_class_count(plugin); i++) {
748 struct bt_component_class *comp_cls =
749 bt_plugin_get_component_class(plugin, i);
750 const char *comp_class_name =
751 bt_component_class_get_name(comp_cls);
752 const char *comp_class_description =
753 bt_component_class_get_description(comp_cls);
754 const char *comp_class_help =
755 bt_component_class_get_help(comp_cls);
756 enum bt_component_class_type type =
757 bt_component_class_get_type(comp_cls);
758
759 assert(comp_cls);
760
90de159b 761 if (cfg->cmd_data.help.cfg_component->type !=
22e22462 762 BT_COMPONENT_CLASS_TYPE_UNKNOWN) {
90de159b 763 if (strcmp(cfg->cmd_data.help.cfg_component->component_name->str,
22e22462
PP
764 comp_class_name) != 0 &&
765 type ==
90de159b 766 cfg->cmd_data.help.cfg_component->type) {
22e22462
PP
767 bt_put(comp_cls);
768 continue;
769 }
770 }
771
772 printf("\n");
773 print_plugin_comp_cls_opt(stdout,
90de159b 774 cfg->cmd_data.help.cfg_component->plugin_name->str,
22e22462
PP
775 comp_class_name,
776 type);
777 printf("\n");
778 printf(" %sDescription%s: %s\n", bt_common_color_bold(),
779 bt_common_color_reset(),
780 comp_class_description ? comp_class_description : "(None)");
781
782 if (comp_class_help) {
783 printf("\n%s\n", comp_class_help);
784 }
785
786 bt_put(comp_cls);
787 }
788
789end:
790 bt_put(plugin);
791 return ret;
792}
793
290725f7
PP
794static int cmd_list_plugins(struct bt_config *cfg)
795{
796 int ret;
797 int plugins_count, component_classes_count = 0, i;
798
799 ret = load_all_plugins(cfg->cmd_data.list_plugins.plugin_paths);
800 if (ret) {
56a1cced
JG
801 goto end;
802 }
803
22e22462
PP
804 printf("From the following plugin paths:\n\n");
805 print_value(cfg->cmd_data.list_plugins.plugin_paths, 2);
806 printf("\n");
290725f7
PP
807 plugins_count = loaded_plugins->len;
808 if (plugins_count == 0) {
809 fprintf(stderr, "%s%sNo plugins found.%s\n",
810 bt_common_color_bold(), bt_common_color_fg_red(),
811 bt_common_color_reset());
812 fprintf(stderr, "\n");
813 fprintf(stderr, "Please make sure your plugin search path is set correctly. You can use\n");
814 fprintf(stderr, "the --plugin-path command-line option or the BABELTRACE_PLUGIN_PATH\n");
815 fprintf(stderr, "environment variable.\n");
56a1cced
JG
816 ret = -1;
817 goto end;
818 }
819
290725f7
PP
820 for (i = 0; i < plugins_count; i++) {
821 struct bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i);
822
823 component_classes_count += bt_plugin_get_component_class_count(plugin);
824 }
33bceaf8 825
290725f7
PP
826 printf("Found %s%d%s component classes in %s%d%s plugins.\n",
827 bt_common_color_bold(),
828 component_classes_count,
829 bt_common_color_reset(),
830 bt_common_color_bold(),
831 plugins_count,
832 bt_common_color_reset());
833
834 for (i = 0; i < plugins_count; i++) {
835 int j;
836 struct bt_plugin *plugin = g_ptr_array_index(loaded_plugins, i);
290725f7
PP
837
838 component_classes_count =
839 bt_plugin_get_component_class_count(plugin);
22e22462
PP
840 printf("\n");
841 print_plugin_info(plugin);
290725f7
PP
842
843 if (component_classes_count == 0) {
844 printf(" %sComponent classes%s: (None)\n",
845 bt_common_color_bold(),
846 bt_common_color_reset());
847 } else {
848 printf(" %sComponent classes%s:\n",
849 bt_common_color_bold(),
850 bt_common_color_reset());
851 }
852
853 for (j = 0; j < component_classes_count; j++) {
854 struct bt_component_class *comp_class =
855 bt_plugin_get_component_class(plugin, j);
856 const char *comp_class_name =
857 bt_component_class_get_name(comp_class);
858 const char *comp_class_description =
859 bt_component_class_get_description(comp_class);
860 enum bt_component_class_type type =
861 bt_component_class_get_type(comp_class);
862
22e22462
PP
863 printf(" ");
864 print_plugin_comp_cls_opt(stdout,
865 bt_plugin_get_name(plugin), comp_class_name,
866 type);
290725f7
PP
867
868 if (comp_class_description) {
869 printf(": %s", comp_class_description);
870 }
871
872 printf("\n");
873 bt_put(comp_class);
874 }
875 }
876
877end:
878 return ret;
879}
880
881static int cmd_convert(struct bt_config *cfg)
882{
883 int ret = 0;
884 struct bt_component_class *source_class = NULL;
885 struct bt_component_class *sink_class = NULL;
886 struct bt_component *source = NULL, *sink = NULL;
887 struct bt_value *source_params = NULL, *sink_params = NULL;
888 enum bt_component_status sink_status;
889 struct bt_config_component *source_cfg = NULL, *sink_cfg = NULL;
890
891 /* TODO handle more than 1 source and 1 sink. */
892 if (cfg->cmd_data.convert.sources->len != 1 ||
893 cfg->cmd_data.convert.sinks->len != 1) {
ebba3338 894 fprintf(stderr, "Only one source and one sink component class are supported. Aborting...\n");
98ecef32
MD
895 ret = -1;
896 goto end;
33bceaf8
JG
897 }
898
290725f7
PP
899 ret = load_all_plugins(cfg->cmd_data.convert.plugin_paths);
900 if (ret) {
ebba3338 901 fprintf(stderr, "Could not load plugins from configured plugin paths. Aborting...\n");
cba174d5
JG
902 goto end;
903 }
904
290725f7 905 source_cfg = bt_config_get_component(cfg->cmd_data.convert.sources, 0);
e5bc7f81 906 source_params = bt_get(source_cfg->params);
33b34c43
PP
907 source_class = find_component_class(source_cfg->plugin_name->str,
908 source_cfg->component_name->str,
d3e4dcd8 909 BT_COMPONENT_CLASS_TYPE_SOURCE);
56a1cced 910 if (!source_class) {
e5bc7f81
JG
911 fprintf(stderr, "Could not find %s.%s source component class. Aborting...\n",
912 source_cfg->plugin_name->str,
913 source_cfg->component_name->str);
56a1cced
JG
914 ret = -1;
915 goto end;
916 }
7c7c0433 917
290725f7 918 sink_cfg = bt_config_get_component(cfg->cmd_data.convert.sinks, 0);
e5bc7f81 919 sink_params = bt_get(sink_cfg->params);
33b34c43
PP
920 sink_class = find_component_class(sink_cfg->plugin_name->str,
921 sink_cfg->component_name->str,
d3e4dcd8 922 BT_COMPONENT_CLASS_TYPE_SINK);
7c7c0433 923 if (!sink_class) {
e5bc7f81
JG
924 fprintf(stderr, "Could not find %s.%s output component class. Aborting...\n",
925 sink_cfg->plugin_name->str,
926 sink_cfg->component_name->str);
7c7c0433
JG
927 ret = -1;
928 goto end;
929 }
930
e5bc7f81 931 source = bt_component_create(source_class, "source", source_params);
56a1cced 932 if (!source) {
e5bc7f81 933 fprintf(stderr, "Failed to instantiate selected source component. Aborting...\n");
c42c79ea
PP
934 ret = -1;
935 goto end;
936 }
56a1cced 937
e5bc7f81 938 sink = bt_component_create(sink_class, "sink", sink_params);
7c7c0433 939 if (!sink) {
e5bc7f81 940 fprintf(stderr, "Failed to instantiate selected output component. Aborting...\n");
7c7c0433 941 ret = -1;
2e339de1
JG
942 goto end;
943 }
944
6c2f3ee5
JG
945 ret = connect_source_sink(source, source_cfg, sink);
946 if (ret) {
290725f7 947 ret = -1;
fec2a9f2
JG
948 goto end;
949 }
78586d8a 950
fec2a9f2
JG
951 while (true) {
952 sink_status = bt_component_sink_consume(sink);
fec2a9f2
JG
953 switch (sink_status) {
954 case BT_COMPONENT_STATUS_AGAIN:
955 /* Wait for an arbitraty 500 ms. */
956 usleep(500000);
78586d8a 957 break;
fec2a9f2
JG
958 case BT_COMPONENT_STATUS_OK:
959 break;
960 case BT_COMPONENT_STATUS_END:
961 goto end;
962 default:
963 fprintf(stderr, "Sink component returned an error, aborting...\n");
964 ret = -1;
965 goto end;
78586d8a 966 }
fec2a9f2 967 }
290725f7 968
11e1d048 969end:
7c7c0433
JG
970 BT_PUT(sink_class);
971 BT_PUT(source_class);
972 BT_PUT(source);
973 BT_PUT(sink);
974 BT_PUT(source_params);
975 BT_PUT(sink_params);
e5bc7f81
JG
976 BT_PUT(sink_cfg);
977 BT_PUT(source_cfg);
290725f7
PP
978 return ret;
979}
980
981static void warn_command_name_and_directory_clash(struct bt_config *cfg)
982{
983 if (!cfg->command_name) {
984 return;
985 }
986
987 if (g_file_test(cfg->command_name,
988 G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
989 fprintf(stderr, "\nNOTE: The `%s` command was executed. If you meant to convert a\n",
990 cfg->command_name);
991 fprintf(stderr, "trace located in the local `%s` directory, please use:\n",
992 cfg->command_name);
993 fprintf(stderr, "\n");
994 fprintf(stderr, " babeltrace convert %s [OPTIONS]\n",
995 cfg->command_name);
996 }
997}
998
999int main(int argc, const char **argv)
1000{
1001 int ret;
1002 int retcode;
1003 struct bt_config *cfg;
1004
1005 init_loaded_plugins_array();
1006 cfg = bt_config_from_args_with_defaults(argc, argv, &retcode);
1007
1008 if (retcode < 0) {
1009 /* Quit without errors; typically usage/version */
1010 retcode = 0;
1011 goto end;
1012 }
1013
1014 if (retcode > 0) {
1015 goto end;
1016 }
1017
1018 if (!cfg) {
1019 fprintf(stderr, "Failed to create Babeltrace configuration\n");
1020 goto end;
1021 }
1022
1023 babeltrace_debug = cfg->debug;
1024 babeltrace_verbose = cfg->verbose;
1025 print_cfg(cfg);
1026
1027 switch (cfg->command) {
1028 case BT_CONFIG_COMMAND_CONVERT:
1029 ret = cmd_convert(cfg);
1030 break;
1031 case BT_CONFIG_COMMAND_LIST_PLUGINS:
1032 ret = cmd_list_plugins(cfg);
1033 break;
22e22462
PP
1034 case BT_CONFIG_COMMAND_HELP:
1035 ret = cmd_help(cfg);
1036 break;
63ce0e1d
PP
1037 case BT_CONFIG_COMMAND_QUERY_INFO:
1038 ret = cmd_query_info(cfg);
1039 break;
290725f7
PP
1040 default:
1041 assert(false);
1042 }
1043
1044 warn_command_name_and_directory_clash(cfg);
1045 retcode = ret ? 1 : 0;
1046
1047end:
1048 BT_PUT(cfg);
33b34c43 1049 fini_loaded_plugins_array();
290725f7 1050 return retcode;
4c8bfb7e 1051}
This page took 0.088756 seconds and 4 git commands to generate.