babeltrace-cfg: put comp. class type within struct bt_config_component
[babeltrace.git] / converter / babeltrace-cfg-connect.c
CommitLineData
ebba3338
PP
1/*
2 * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#include <babeltrace/values.h>
24#include "babeltrace-cfg.h"
25#include "babeltrace-cfg-connect.h"
26
27static bool all_named_in_array(GPtrArray *comps)
28{
29 size_t i;
30 bool all_named = true;
31
32 for (i = 0; i < comps->len; i++) {
33 struct bt_config_component *comp = g_ptr_array_index(comps, i);
34
35 if (comp->instance_name->len == 0) {
36 all_named = false;
37 goto end;
38 }
39 }
40
41end:
42 return all_named;
43}
44
45static bool all_named(struct bt_config *cfg)
46{
47 return all_named_in_array(cfg->cmd_data.convert.sources) &&
48 all_named_in_array(cfg->cmd_data.convert.filters) &&
49 all_named_in_array(cfg->cmd_data.convert.sinks);
50}
51
52void bt_config_connection_destroy(struct bt_config_connection *connection)
53{
54 if (!connection) {
55 return;
56 }
57
58 if (connection->src_instance_name) {
59 g_string_free(connection->src_instance_name, TRUE);
60 }
61
62 if (connection->dst_instance_name) {
63 g_string_free(connection->dst_instance_name, TRUE);
64 }
65
66 if (connection->src_port_name) {
67 g_string_free(connection->src_port_name, TRUE);
68 }
69
70 if (connection->dst_port_name) {
71 g_string_free(connection->dst_port_name, TRUE);
72 }
73
74 if (connection->arg) {
75 g_string_free(connection->arg, TRUE);
76 }
77
78 g_free(connection);
79}
80
81static struct bt_config_connection *bt_config_connection_create(const char *arg)
82{
83 struct bt_config_connection *cfg_connection;
84
85 cfg_connection = g_new0(struct bt_config_connection, 1);
86 if (!cfg_connection) {
87 goto error;
88 }
89
90 cfg_connection->src_instance_name = g_string_new(NULL);
91 if (!cfg_connection->src_instance_name) {
92 goto error;
93 }
94
95 cfg_connection->dst_instance_name = g_string_new(NULL);
96 if (!cfg_connection->dst_instance_name) {
97 goto error;
98 }
99
100 cfg_connection->src_port_name = g_string_new(NULL);
101 if (!cfg_connection->src_port_name) {
102 goto error;
103 }
104
105 cfg_connection->dst_port_name = g_string_new(NULL);
106 if (!cfg_connection->dst_port_name) {
107 goto error;
108 }
109
110 cfg_connection->arg = g_string_new(arg);
111 if (!cfg_connection->arg) {
112 goto error;
113 }
114
115 goto end;
116
117error:
118 g_free(cfg_connection);
119 cfg_connection = NULL;
120
121end:
122 return cfg_connection;
123}
124
125static struct bt_config_connection *bt_config_connection_create_full(
126 const char *src_instance_name, const char *src_port_name,
127 const char *dst_instance_name, const char *dst_port_name,
128 const char *arg)
129{
130 struct bt_config_connection *cfg_connection =
131 bt_config_connection_create(arg);
132
133 if (!cfg_connection) {
134 goto end;
135 }
136
137 g_string_assign(cfg_connection->src_instance_name, src_instance_name);
138 g_string_assign(cfg_connection->dst_instance_name, dst_instance_name);
139 g_string_assign(cfg_connection->src_port_name, src_port_name);
140 g_string_assign(cfg_connection->dst_port_name, dst_port_name);
141
142end:
143 return cfg_connection;
144}
145
146static GScanner *create_connection_arg_scanner(void)
147{
148 GScannerConfig scanner_config = {
149 .cset_skip_characters = " \t\n",
150 .cset_identifier_first = G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "_-",
151 .cset_identifier_nth = G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "_-",
152 .case_sensitive = TRUE,
153 .cpair_comment_single = NULL,
154 .skip_comment_multi = TRUE,
155 .skip_comment_single = TRUE,
156 .scan_comment_multi = FALSE,
157 .scan_identifier = TRUE,
158 .scan_identifier_1char = TRUE,
159 .scan_identifier_NULL = FALSE,
160 .scan_symbols = FALSE,
161 .symbol_2_token = FALSE,
162 .scope_0_fallback = FALSE,
163 .scan_binary = FALSE,
164 .scan_octal = FALSE,
165 .scan_float = FALSE,
166 .scan_hex = FALSE,
167 .scan_hex_dollar = FALSE,
168 .numbers_2_int = FALSE,
169 .int_2_float = FALSE,
170 .store_int64 = FALSE,
171 .scan_string_sq = FALSE,
172 .scan_string_dq = FALSE,
173 .identifier_2_string = FALSE,
174 .char_2_token = TRUE,
175 };
176
177 return g_scanner_new(&scanner_config);
178}
179
180static struct bt_config_connection *cfg_connection_from_arg(const char *arg)
181{
182 struct bt_config_connection *connection = NULL;
183 GScanner *scanner = NULL;
184 enum {
185 EXPECTING_SRC,
186 EXPECTING_SRC_DOT,
187 EXPECTING_SRC_PORT,
188 EXPECTING_COLON,
189 EXPECTING_DST,
190 EXPECTING_DST_DOT,
191 EXPECTING_DST_PORT,
192 DONE,
193 } state = EXPECTING_SRC;
194
195 connection = bt_config_connection_create(arg);
196 if (!connection) {
197 goto error;
198 }
199
200 scanner = create_connection_arg_scanner();
201 if (!scanner) {
202 goto error;
203 }
204
205 g_scanner_input_text(scanner, arg, strlen(arg));
206
207 while (true) {
208 GTokenType token_type = g_scanner_get_next_token(scanner);
209
210 if (token_type == G_TOKEN_EOF) {
211 goto after_scan;
212 }
213
214 switch (state) {
215 case EXPECTING_SRC:
216 if (token_type != G_TOKEN_IDENTIFIER) {
217 goto error;
218 }
219
220 g_string_assign(connection->src_instance_name,
221 scanner->value.v_identifier);
222 state = EXPECTING_SRC_DOT;
223 break;
224 case EXPECTING_SRC_DOT:
225 if (token_type == ':') {
226 state = EXPECTING_DST;
227 break;
228 }
229
230 if (token_type != '.') {
231 goto error;
232 }
233
234 state = EXPECTING_SRC_PORT;
235 break;
236 case EXPECTING_SRC_PORT:
237 if (token_type != G_TOKEN_IDENTIFIER) {
238 goto error;
239 }
240
241 g_string_assign(connection->src_port_name,
242 scanner->value.v_identifier);
243 state = EXPECTING_COLON;
244 break;
245 case EXPECTING_COLON:
246 if (token_type != ':') {
247 goto error;
248 }
249
250 state = EXPECTING_DST;
251 break;
252 case EXPECTING_DST:
253 if (token_type != G_TOKEN_IDENTIFIER) {
254 goto error;
255 }
256
257 g_string_assign(connection->dst_instance_name,
258 scanner->value.v_identifier);
259 state = EXPECTING_DST_DOT;
260 break;
261 case EXPECTING_DST_DOT:
262 if (token_type != '.') {
263 goto error;
264 }
265
266 state = EXPECTING_DST_PORT;
267 break;
268 case EXPECTING_DST_PORT:
269 if (token_type != G_TOKEN_IDENTIFIER) {
270 goto error;
271 }
272
273 g_string_assign(connection->dst_port_name,
274 scanner->value.v_identifier);
275 state = DONE;
276 break;
277 default:
278 goto error;
279 }
280 }
281
282after_scan:
283 if (state != EXPECTING_DST_DOT && state != DONE) {
284 goto error;
285 }
286
287 goto end;
288
289error:
290 bt_config_connection_destroy(connection);
291 connection = NULL;
292
293end:
294 if (scanner) {
295 g_scanner_destroy(scanner);
296 }
297
298 return connection;
299}
300
301static struct bt_config_component *find_component_in_array(GPtrArray *comps,
302 const char *name)
303{
304 size_t i;
305 struct bt_config_component *found_comp = NULL;
306
307 for (i = 0; i < comps->len; i++) {
308 struct bt_config_component *comp = g_ptr_array_index(comps, i);
309
310 if (strcmp(name, comp->instance_name->str) == 0) {
311 found_comp = bt_get(comp);
312 goto end;
313 }
314 }
315
316end:
317 return found_comp;
318}
319
320static struct bt_config_component *find_component(struct bt_config *cfg,
90de159b 321 const char *name)
ebba3338
PP
322{
323 struct bt_config_component *comp;
324
325 comp = find_component_in_array(cfg->cmd_data.convert.sources, name);
326 if (comp) {
ebba3338
PP
327 goto end;
328 }
329
330 comp = find_component_in_array(cfg->cmd_data.convert.filters, name);
331 if (comp) {
ebba3338
PP
332 goto end;
333 }
334
335 comp = find_component_in_array(cfg->cmd_data.convert.sinks, name);
336 if (comp) {
ebba3338
PP
337 goto end;
338 }
339
340end:
341 return comp;
342}
343
344static int validate_all_endpoints_exist(struct bt_config *cfg, char *error_buf,
345 size_t error_buf_size)
346{
347 size_t i;
348 int ret = 0;
349
350 for (i = 0; i < cfg->cmd_data.convert.connections->len; i++) {
351 struct bt_config_connection *connection =
352 g_ptr_array_index(cfg->cmd_data.convert.connections, i);
353 struct bt_config_component *comp;
ebba3338 354
90de159b 355 comp = find_component(cfg, connection->src_instance_name->str);
ebba3338
PP
356 bt_put(comp);
357 if (!comp) {
358 comp = find_component(cfg,
90de159b 359 connection->dst_instance_name->str);
ebba3338
PP
360 bt_put(comp);
361 if (!comp) {
362 snprintf(error_buf, error_buf_size,
363 "Invalid connection: cannot find component `%s`:\n %s\n",
364 connection->dst_instance_name->str,
365 connection->arg->str);
366 ret = -1;
367 goto end;
368 }
369 }
370 }
371
372end:
373 return ret;
374}
375
376static int validate_connection_directions(struct bt_config *cfg,
377 char *error_buf, size_t error_buf_size)
378{
379 size_t i;
380 int ret = 0;
381 struct bt_config_component *src_comp = NULL;
382 struct bt_config_component *dst_comp = NULL;
383
384 for (i = 0; i < cfg->cmd_data.convert.connections->len; i++) {
385 struct bt_config_connection *connection =
386 g_ptr_array_index(cfg->cmd_data.convert.connections, i);
ebba3338
PP
387
388 src_comp = find_component(cfg,
90de159b 389 connection->src_instance_name->str);
ebba3338
PP
390 assert(src_comp);
391 dst_comp = find_component(cfg,
90de159b 392 connection->dst_instance_name->str);
ebba3338
PP
393 assert(dst_comp);
394
90de159b
PP
395 if (src_comp->type == BT_COMPONENT_CLASS_TYPE_SOURCE) {
396 if (dst_comp->type != BT_COMPONENT_CLASS_TYPE_FILTER &&
397 dst_comp->type != BT_COMPONENT_CLASS_TYPE_SINK) {
ebba3338
PP
398 snprintf(error_buf, error_buf_size,
399 "Invalid connection: source component `%s` not connected to filter or sink component:\n %s\n",
400 connection->src_instance_name->str,
401 connection->arg->str);
402 ret = -1;
403 goto end;
404 }
90de159b
PP
405 } else if (src_comp->type == BT_COMPONENT_CLASS_TYPE_FILTER) {
406 if (dst_comp->type != BT_COMPONENT_CLASS_TYPE_FILTER &&
407 dst_comp->type != BT_COMPONENT_CLASS_TYPE_SINK) {
ebba3338
PP
408 snprintf(error_buf, error_buf_size,
409 "Invalid connection: filter component `%s` not connected to filter or sink component:\n %s\n",
410 connection->src_instance_name->str,
411 connection->arg->str);
412 ret = -1;
413 goto end;
414 }
415 } else {
416 snprintf(error_buf, error_buf_size,
417 "Invalid connection: cannot connect sink component `%s` to component `%s`:\n %s\n",
418 connection->src_instance_name->str,
419 connection->dst_instance_name->str,
420 connection->arg->str);
421 ret = -1;
422 goto end;
423 }
424
425 BT_PUT(src_comp);
426 BT_PUT(dst_comp);
427 }
428
429end:
430 bt_put(src_comp);
431 bt_put(dst_comp);
432 return ret;
433}
434
435static int validate_self_connections(struct bt_config *cfg, char *error_buf,
436 size_t error_buf_size)
437{
438 size_t i;
439 int ret = 0;
440
441 for (i = 0; i < cfg->cmd_data.convert.connections->len; i++) {
442 struct bt_config_connection *connection =
443 g_ptr_array_index(cfg->cmd_data.convert.connections, i);
444
445 if (strcmp(connection->src_instance_name->str,
446 connection->dst_instance_name->str) == 0) {
447 snprintf(error_buf, error_buf_size,
448 "Invalid connection: component `%s` is connected to itself:\n %s\n",
449 connection->src_instance_name->str,
450 connection->arg->str);
451 ret = -1;
452 goto end;
453 }
454 }
455
456end:
457 return ret;
458}
459
460static int validate_all_components_connected_in_array(GPtrArray *comps,
461 struct bt_value *connected_components,
462 char *error_buf, size_t error_buf_size)
463{
464 int ret = 0;
465 size_t i;
466
467 for (i = 0; i < comps->len; i++) {
468 struct bt_config_component *comp = g_ptr_array_index(comps, i);
469
470 if (!bt_value_map_has_key(connected_components,
471 comp->instance_name->str)) {
472 snprintf(error_buf, error_buf_size,
473 "Component `%s` is not connected\n",
474 comp->instance_name->str);
475 ret = -1;
476 goto end;
477 }
478 }
479
480end:
481 return ret;
482}
483
484static int validate_all_components_connected(struct bt_config *cfg,
485 char *error_buf, size_t error_buf_size)
486{
487 size_t i;
488 int ret = 0;
489 struct bt_value *connected_components = bt_value_map_create();
490
491 if (!connected_components) {
492 ret = -1;
493 goto end;
494 }
495
496 for (i = 0; i < cfg->cmd_data.convert.connections->len; i++) {
497 struct bt_config_connection *connection =
498 g_ptr_array_index(cfg->cmd_data.convert.connections, i);
499
500 ret = bt_value_map_insert(connected_components,
501 connection->src_instance_name->str, bt_value_null);
502 if (ret) {
503 goto end;
504 }
505
506 ret = bt_value_map_insert(connected_components,
507 connection->dst_instance_name->str, bt_value_null);
508 if (ret) {
509 goto end;
510 }
511 }
512
513 ret = validate_all_components_connected_in_array(
514 cfg->cmd_data.convert.sources, connected_components,
515 error_buf, error_buf_size);
516 if (ret) {
517 goto end;
518 }
519
520 ret = validate_all_components_connected_in_array(
521 cfg->cmd_data.convert.filters, connected_components,
522 error_buf, error_buf_size);
523 if (ret) {
524 goto end;
525 }
526
527 ret = validate_all_components_connected_in_array(
528 cfg->cmd_data.convert.sinks, connected_components,
529 error_buf, error_buf_size);
530 if (ret) {
531 goto end;
532 }
533
534end:
535 bt_put(connected_components);
536 return ret;
537}
538
539static int validate_no_duplicate_connection(struct bt_config *cfg,
540 char *error_buf, size_t error_buf_size)
541{
542 size_t i;
543 int ret = 0;
544 struct bt_value *flat_connection_names = bt_value_map_create();
545 GString *flat_connection_name = NULL;
546
547 if (!flat_connection_names) {
548 ret = -1;
549 goto end;
550 }
551
552 flat_connection_name = g_string_new(NULL);
553 if (!flat_connection_name) {
554 ret = -1;
555 goto end;
556 }
557
558 for (i = 0; i < cfg->cmd_data.convert.connections->len; i++) {
559 struct bt_config_connection *connection =
560 g_ptr_array_index(cfg->cmd_data.convert.connections, i);
561
562 g_string_printf(flat_connection_name, "%s.%s:%s.%s",
563 connection->src_instance_name->str,
564 connection->src_port_name->str,
565 connection->dst_instance_name->str,
566 connection->dst_port_name->str);
567
568 if (bt_value_map_has_key(flat_connection_names,
569 flat_connection_name->str)) {
570 snprintf(error_buf, error_buf_size,
571 "Duplicate connection:\n %s\n",
572 connection->arg->str);
573 ret = -1;
574 goto end;
575 }
576
577 ret = bt_value_map_insert(flat_connection_names,
578 flat_connection_name->str, bt_value_null);
579 if (ret) {
580 goto end;
581 }
582 }
583
584end:
585 bt_put(flat_connection_names);
586
587 if (flat_connection_name) {
588 g_string_free(flat_connection_name, TRUE);
589 }
590
591 return ret;
592}
593
594static int validate_connections(struct bt_config *cfg, char *error_buf,
595 size_t error_buf_size)
596{
597 int ret;
598
599 ret = validate_all_endpoints_exist(cfg, error_buf, error_buf_size);
600 if (ret) {
601 goto end;
602 }
603
604 ret = validate_connection_directions(cfg, error_buf, error_buf_size);
605 if (ret) {
606 goto end;
607 }
608
609 ret = validate_self_connections(cfg, error_buf, error_buf_size);
610 if (ret) {
611 goto end;
612 }
613
614 ret = validate_all_components_connected(cfg, error_buf, error_buf_size);
615 if (ret) {
616 goto end;
617 }
618
619 ret = validate_no_duplicate_connection(cfg, error_buf, error_buf_size);
620 if (ret) {
621 goto end;
622 }
623
624end:
625 return ret;
626}
627
628static bool component_name_exists_in_array(GPtrArray *comps, const char *name)
629{
630 size_t i;
631 bool exists = false;
632
633 for (i = 0; i < comps->len; i++) {
634 struct bt_config_component *comp = g_ptr_array_index(comps, i);
635
636 if (comp->instance_name->len > 0) {
637 if (strcmp(comp->instance_name->str, name) == 0) {
638 exists = true;
639 break;
640 }
641 }
642 }
643
644 return exists;
645}
646
647static bool component_name_exists_at_all(struct bt_config *cfg,
648 const char *name)
649{
650 return component_name_exists_in_array(cfg->cmd_data.convert.sources,
651 name) || component_name_exists_in_array(
652 cfg->cmd_data.convert.filters, name) ||
653 component_name_exists_in_array(
654 cfg->cmd_data.convert.sinks, name);
655}
656
657static int auto_name_component(struct bt_config *cfg, const char *prefix,
658 struct bt_config_component *comp)
659{
660 int ret = 0;
661 unsigned int i = 0;
662 GString *new_name;
663
664 assert(comp->instance_name->len == 0);
665 new_name = g_string_new(NULL);
666 if (!new_name) {
667 ret = -1;
668 goto end;
669 }
670
671 do {
672 g_string_printf(new_name, "%s-%s.%s-%d", prefix,
673 comp->plugin_name->str, comp->component_name->str, i);
674 i++;
675 } while (component_name_exists_at_all(cfg, new_name->str));
676
677 g_string_assign(comp->instance_name, new_name->str);
678
679end:
680 if (new_name) {
681 g_string_free(new_name, TRUE);
682 }
683
684 return ret;
685}
686
687static int auto_name_components_in_array(struct bt_config *cfg,
688 GPtrArray *comps, const char *prefix)
689{
690 int ret = 0;
691 size_t i;
692
693 for (i = 0; i < comps->len; i++) {
694 struct bt_config_component *comp = g_ptr_array_index(comps, i);
695
696 if (comp->instance_name->len == 0) {
697 ret = auto_name_component(cfg, prefix, comp);
698 if (ret) {
699 goto end;
700 }
701 }
702 }
703
704end:
705 return ret;
706}
707
708static int auto_name_components(struct bt_config *cfg)
709{
710 int ret;
711
712 ret = auto_name_components_in_array(cfg, cfg->cmd_data.convert.sources,
713 "source");
714 if (ret) {
715 goto end;
716 }
717
718 ret = auto_name_components_in_array(cfg, cfg->cmd_data.convert.filters,
719 "filter");
720 if (ret) {
721 goto end;
722 }
723
724 ret = auto_name_components_in_array(cfg, cfg->cmd_data.convert.sinks,
725 "sink");
726 if (ret) {
727 goto end;
728 }
729
730end:
731 return ret;
732}
733
734static int auto_connect(struct bt_config *cfg)
735{
736 int ret = 0;
737 struct bt_config_component *muxer_cfg_comp = NULL;
738 size_t i;
739 const char *last_filter_comp_name;
740
741 /* Make sure all components have a unique instance name */
742 ret = auto_name_components(cfg);
743 if (ret) {
744 goto error;
745 }
746
747 /* Add an implicit muxer filter */
90de159b
PP
748 muxer_cfg_comp = bt_config_component_from_arg(
749 BT_COMPONENT_CLASS_TYPE_FILTER, "utils.muxer");
ebba3338
PP
750 if (!muxer_cfg_comp) {
751 goto error;
752 }
753
754 auto_name_component(cfg, "filter", muxer_cfg_comp);
755 g_ptr_array_add(cfg->cmd_data.convert.filters, bt_get(muxer_cfg_comp));
756
757 /* Connect all sources to this mux */
758 for (i = 0; i < cfg->cmd_data.convert.sources->len; i++) {
759 struct bt_config_component *comp =
760 g_ptr_array_index(cfg->cmd_data.convert.sources, i);
761 struct bt_config_connection *cfg_connection =
762 bt_config_connection_create_full(
763 comp->instance_name->str, "",
764 muxer_cfg_comp->instance_name->str, "",
765 "(auto)");
766
767 if (!cfg_connection) {
768 goto error;
769 }
770
771 g_ptr_array_add(cfg->cmd_data.convert.connections,
772 cfg_connection);
773 }
774
775 /* Connect this mux to the filter components, in order */
776 last_filter_comp_name = muxer_cfg_comp->instance_name->str;
777
778 for (i = 0; i < cfg->cmd_data.convert.filters->len - 1; i++) {
779 struct bt_config_component *comp =
780 g_ptr_array_index(cfg->cmd_data.convert.filters, i);
781 struct bt_config_connection *cfg_connection;
782
783 cfg_connection = bt_config_connection_create_full(
784 last_filter_comp_name, "",
785 comp->instance_name->str, "",
786 "(auto)");
787
788 if (!cfg_connection) {
789 goto error;
790 }
791
792 g_ptr_array_add(cfg->cmd_data.convert.connections,
793 cfg_connection);
794 last_filter_comp_name = comp->instance_name->str;
795 }
796
797 /* Connect the last filter component to all sink components */
798 for (i = 0; i < cfg->cmd_data.convert.sinks->len; i++) {
799 struct bt_config_component *comp =
800 g_ptr_array_index(cfg->cmd_data.convert.sinks, i);
801 struct bt_config_connection *cfg_connection =
802 bt_config_connection_create_full(
803 last_filter_comp_name, "",
804 comp->instance_name->str, "",
805 "(auto)");
806
807 if (!cfg_connection) {
808 goto error;
809 }
810
811 g_ptr_array_add(cfg->cmd_data.convert.connections,
812 cfg_connection);
813 }
814
815 goto end;
816
817error:
818 ret = -1;
819
820end:
821 bt_put(muxer_cfg_comp);
822 return ret;
823}
824
825int bt_config_create_connections(struct bt_config *cfg,
826 struct bt_value *connection_args,
827 char *error_buf, size_t error_buf_size)
828{
829 int ret;
830 size_t i;
831
832 if (bt_value_array_is_empty(connection_args)) {
833 /* No explicit connections: do automatic connection */
834 ret = auto_connect(cfg);
835 if (ret) {
836 goto error;
837 }
838 }
839
840 if (!all_named(cfg)) {
841 snprintf(error_buf, error_buf_size, "At least one connection (--connect) specified, but not all component\ninstances are named (use --name)\n");
842 goto error;
843 }
844
845 for (i = 0; i < bt_value_array_size(connection_args); i++) {
846 struct bt_value *arg_value =
847 bt_value_array_get(connection_args, i);
848 const char *arg;
849 struct bt_config_connection *cfg_connection;
850
851 ret = bt_value_string_get(arg_value, &arg);
852 BT_PUT(arg_value);
853 assert(ret == 0);
854 cfg_connection = cfg_connection_from_arg(arg);
855 if (!cfg_connection) {
856 snprintf(error_buf, error_buf_size, "Cannot parse --connect option's argument:\n %s\n",
857 arg);
858 goto error;
859 }
860
861 g_ptr_array_add(cfg->cmd_data.convert.connections,
862 cfg_connection);
863 }
864
865
866 ret = validate_connections(cfg, error_buf, error_buf_size);
867 if (ret) {
868 goto error;
869 }
870
871 goto end;
872
873error:
874 ret = -1;
875
876end:
877 return ret;
878}
This page took 0.054057 seconds and 4 git commands to generate.