bt2: test query info API
[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,
321 const char *name, enum bt_component_class_type *type)
322{
323 struct bt_config_component *comp;
324
325 comp = find_component_in_array(cfg->cmd_data.convert.sources, name);
326 if (comp) {
327 *type = BT_COMPONENT_CLASS_TYPE_SOURCE;
328 goto end;
329 }
330
331 comp = find_component_in_array(cfg->cmd_data.convert.filters, name);
332 if (comp) {
333 *type = BT_COMPONENT_CLASS_TYPE_FILTER;
334 goto end;
335 }
336
337 comp = find_component_in_array(cfg->cmd_data.convert.sinks, name);
338 if (comp) {
339 *type = BT_COMPONENT_CLASS_TYPE_SINK;
340 goto end;
341 }
342
343end:
344 return comp;
345}
346
347static int validate_all_endpoints_exist(struct bt_config *cfg, char *error_buf,
348 size_t error_buf_size)
349{
350 size_t i;
351 int ret = 0;
352
353 for (i = 0; i < cfg->cmd_data.convert.connections->len; i++) {
354 struct bt_config_connection *connection =
355 g_ptr_array_index(cfg->cmd_data.convert.connections, i);
356 struct bt_config_component *comp;
357 enum bt_component_class_type type;
358
359 comp = find_component(cfg, connection->src_instance_name->str,
360 &type);
361 bt_put(comp);
362 if (!comp) {
363 comp = find_component(cfg,
364 connection->dst_instance_name->str, &type);
365 bt_put(comp);
366 if (!comp) {
367 snprintf(error_buf, error_buf_size,
368 "Invalid connection: cannot find component `%s`:\n %s\n",
369 connection->dst_instance_name->str,
370 connection->arg->str);
371 ret = -1;
372 goto end;
373 }
374 }
375 }
376
377end:
378 return ret;
379}
380
381static int validate_connection_directions(struct bt_config *cfg,
382 char *error_buf, size_t error_buf_size)
383{
384 size_t i;
385 int ret = 0;
386 struct bt_config_component *src_comp = NULL;
387 struct bt_config_component *dst_comp = NULL;
388
389 for (i = 0; i < cfg->cmd_data.convert.connections->len; i++) {
390 struct bt_config_connection *connection =
391 g_ptr_array_index(cfg->cmd_data.convert.connections, i);
392 enum bt_component_class_type src_type;
393 enum bt_component_class_type dst_type;
394
395 src_comp = find_component(cfg,
396 connection->src_instance_name->str, &src_type);
397 assert(src_comp);
398 dst_comp = find_component(cfg,
399 connection->dst_instance_name->str, &dst_type);
400 assert(dst_comp);
401
402 if (src_type == BT_COMPONENT_CLASS_TYPE_SOURCE) {
403 if (dst_type != BT_COMPONENT_CLASS_TYPE_FILTER &&
404 dst_type != BT_COMPONENT_CLASS_TYPE_SINK) {
405 snprintf(error_buf, error_buf_size,
406 "Invalid connection: source component `%s` not connected to filter or sink component:\n %s\n",
407 connection->src_instance_name->str,
408 connection->arg->str);
409 ret = -1;
410 goto end;
411 }
412 } else if (src_type == BT_COMPONENT_CLASS_TYPE_FILTER) {
413 if (dst_type != BT_COMPONENT_CLASS_TYPE_FILTER &&
414 dst_type != BT_COMPONENT_CLASS_TYPE_SINK) {
415 snprintf(error_buf, error_buf_size,
416 "Invalid connection: filter component `%s` not connected to filter or sink component:\n %s\n",
417 connection->src_instance_name->str,
418 connection->arg->str);
419 ret = -1;
420 goto end;
421 }
422 } else {
423 snprintf(error_buf, error_buf_size,
424 "Invalid connection: cannot connect sink component `%s` to component `%s`:\n %s\n",
425 connection->src_instance_name->str,
426 connection->dst_instance_name->str,
427 connection->arg->str);
428 ret = -1;
429 goto end;
430 }
431
432 BT_PUT(src_comp);
433 BT_PUT(dst_comp);
434 }
435
436end:
437 bt_put(src_comp);
438 bt_put(dst_comp);
439 return ret;
440}
441
442static int validate_self_connections(struct bt_config *cfg, char *error_buf,
443 size_t error_buf_size)
444{
445 size_t i;
446 int ret = 0;
447
448 for (i = 0; i < cfg->cmd_data.convert.connections->len; i++) {
449 struct bt_config_connection *connection =
450 g_ptr_array_index(cfg->cmd_data.convert.connections, i);
451
452 if (strcmp(connection->src_instance_name->str,
453 connection->dst_instance_name->str) == 0) {
454 snprintf(error_buf, error_buf_size,
455 "Invalid connection: component `%s` is connected to itself:\n %s\n",
456 connection->src_instance_name->str,
457 connection->arg->str);
458 ret = -1;
459 goto end;
460 }
461 }
462
463end:
464 return ret;
465}
466
467static int validate_all_components_connected_in_array(GPtrArray *comps,
468 struct bt_value *connected_components,
469 char *error_buf, size_t error_buf_size)
470{
471 int ret = 0;
472 size_t i;
473
474 for (i = 0; i < comps->len; i++) {
475 struct bt_config_component *comp = g_ptr_array_index(comps, i);
476
477 if (!bt_value_map_has_key(connected_components,
478 comp->instance_name->str)) {
479 snprintf(error_buf, error_buf_size,
480 "Component `%s` is not connected\n",
481 comp->instance_name->str);
482 ret = -1;
483 goto end;
484 }
485 }
486
487end:
488 return ret;
489}
490
491static int validate_all_components_connected(struct bt_config *cfg,
492 char *error_buf, size_t error_buf_size)
493{
494 size_t i;
495 int ret = 0;
496 struct bt_value *connected_components = bt_value_map_create();
497
498 if (!connected_components) {
499 ret = -1;
500 goto end;
501 }
502
503 for (i = 0; i < cfg->cmd_data.convert.connections->len; i++) {
504 struct bt_config_connection *connection =
505 g_ptr_array_index(cfg->cmd_data.convert.connections, i);
506
507 ret = bt_value_map_insert(connected_components,
508 connection->src_instance_name->str, bt_value_null);
509 if (ret) {
510 goto end;
511 }
512
513 ret = bt_value_map_insert(connected_components,
514 connection->dst_instance_name->str, bt_value_null);
515 if (ret) {
516 goto end;
517 }
518 }
519
520 ret = validate_all_components_connected_in_array(
521 cfg->cmd_data.convert.sources, 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.filters, connected_components,
529 error_buf, error_buf_size);
530 if (ret) {
531 goto end;
532 }
533
534 ret = validate_all_components_connected_in_array(
535 cfg->cmd_data.convert.sinks, connected_components,
536 error_buf, error_buf_size);
537 if (ret) {
538 goto end;
539 }
540
541end:
542 bt_put(connected_components);
543 return ret;
544}
545
546static int validate_no_duplicate_connection(struct bt_config *cfg,
547 char *error_buf, size_t error_buf_size)
548{
549 size_t i;
550 int ret = 0;
551 struct bt_value *flat_connection_names = bt_value_map_create();
552 GString *flat_connection_name = NULL;
553
554 if (!flat_connection_names) {
555 ret = -1;
556 goto end;
557 }
558
559 flat_connection_name = g_string_new(NULL);
560 if (!flat_connection_name) {
561 ret = -1;
562 goto end;
563 }
564
565 for (i = 0; i < cfg->cmd_data.convert.connections->len; i++) {
566 struct bt_config_connection *connection =
567 g_ptr_array_index(cfg->cmd_data.convert.connections, i);
568
569 g_string_printf(flat_connection_name, "%s.%s:%s.%s",
570 connection->src_instance_name->str,
571 connection->src_port_name->str,
572 connection->dst_instance_name->str,
573 connection->dst_port_name->str);
574
575 if (bt_value_map_has_key(flat_connection_names,
576 flat_connection_name->str)) {
577 snprintf(error_buf, error_buf_size,
578 "Duplicate connection:\n %s\n",
579 connection->arg->str);
580 ret = -1;
581 goto end;
582 }
583
584 ret = bt_value_map_insert(flat_connection_names,
585 flat_connection_name->str, bt_value_null);
586 if (ret) {
587 goto end;
588 }
589 }
590
591end:
592 bt_put(flat_connection_names);
593
594 if (flat_connection_name) {
595 g_string_free(flat_connection_name, TRUE);
596 }
597
598 return ret;
599}
600
601static int validate_connections(struct bt_config *cfg, char *error_buf,
602 size_t error_buf_size)
603{
604 int ret;
605
606 ret = validate_all_endpoints_exist(cfg, error_buf, error_buf_size);
607 if (ret) {
608 goto end;
609 }
610
611 ret = validate_connection_directions(cfg, error_buf, error_buf_size);
612 if (ret) {
613 goto end;
614 }
615
616 ret = validate_self_connections(cfg, error_buf, error_buf_size);
617 if (ret) {
618 goto end;
619 }
620
621 ret = validate_all_components_connected(cfg, error_buf, error_buf_size);
622 if (ret) {
623 goto end;
624 }
625
626 ret = validate_no_duplicate_connection(cfg, error_buf, error_buf_size);
627 if (ret) {
628 goto end;
629 }
630
631end:
632 return ret;
633}
634
635static bool component_name_exists_in_array(GPtrArray *comps, const char *name)
636{
637 size_t i;
638 bool exists = false;
639
640 for (i = 0; i < comps->len; i++) {
641 struct bt_config_component *comp = g_ptr_array_index(comps, i);
642
643 if (comp->instance_name->len > 0) {
644 if (strcmp(comp->instance_name->str, name) == 0) {
645 exists = true;
646 break;
647 }
648 }
649 }
650
651 return exists;
652}
653
654static bool component_name_exists_at_all(struct bt_config *cfg,
655 const char *name)
656{
657 return component_name_exists_in_array(cfg->cmd_data.convert.sources,
658 name) || component_name_exists_in_array(
659 cfg->cmd_data.convert.filters, name) ||
660 component_name_exists_in_array(
661 cfg->cmd_data.convert.sinks, name);
662}
663
664static int auto_name_component(struct bt_config *cfg, const char *prefix,
665 struct bt_config_component *comp)
666{
667 int ret = 0;
668 unsigned int i = 0;
669 GString *new_name;
670
671 assert(comp->instance_name->len == 0);
672 new_name = g_string_new(NULL);
673 if (!new_name) {
674 ret = -1;
675 goto end;
676 }
677
678 do {
679 g_string_printf(new_name, "%s-%s.%s-%d", prefix,
680 comp->plugin_name->str, comp->component_name->str, i);
681 i++;
682 } while (component_name_exists_at_all(cfg, new_name->str));
683
684 g_string_assign(comp->instance_name, new_name->str);
685
686end:
687 if (new_name) {
688 g_string_free(new_name, TRUE);
689 }
690
691 return ret;
692}
693
694static int auto_name_components_in_array(struct bt_config *cfg,
695 GPtrArray *comps, const char *prefix)
696{
697 int ret = 0;
698 size_t i;
699
700 for (i = 0; i < comps->len; i++) {
701 struct bt_config_component *comp = g_ptr_array_index(comps, i);
702
703 if (comp->instance_name->len == 0) {
704 ret = auto_name_component(cfg, prefix, comp);
705 if (ret) {
706 goto end;
707 }
708 }
709 }
710
711end:
712 return ret;
713}
714
715static int auto_name_components(struct bt_config *cfg)
716{
717 int ret;
718
719 ret = auto_name_components_in_array(cfg, cfg->cmd_data.convert.sources,
720 "source");
721 if (ret) {
722 goto end;
723 }
724
725 ret = auto_name_components_in_array(cfg, cfg->cmd_data.convert.filters,
726 "filter");
727 if (ret) {
728 goto end;
729 }
730
731 ret = auto_name_components_in_array(cfg, cfg->cmd_data.convert.sinks,
732 "sink");
733 if (ret) {
734 goto end;
735 }
736
737end:
738 return ret;
739}
740
741static int auto_connect(struct bt_config *cfg)
742{
743 int ret = 0;
744 struct bt_config_component *muxer_cfg_comp = NULL;
745 size_t i;
746 const char *last_filter_comp_name;
747
748 /* Make sure all components have a unique instance name */
749 ret = auto_name_components(cfg);
750 if (ret) {
751 goto error;
752 }
753
754 /* Add an implicit muxer filter */
755 muxer_cfg_comp = bt_config_component_from_arg("utils.muxer");
756 if (!muxer_cfg_comp) {
757 goto error;
758 }
759
760 auto_name_component(cfg, "filter", muxer_cfg_comp);
761 g_ptr_array_add(cfg->cmd_data.convert.filters, bt_get(muxer_cfg_comp));
762
763 /* Connect all sources to this mux */
764 for (i = 0; i < cfg->cmd_data.convert.sources->len; i++) {
765 struct bt_config_component *comp =
766 g_ptr_array_index(cfg->cmd_data.convert.sources, i);
767 struct bt_config_connection *cfg_connection =
768 bt_config_connection_create_full(
769 comp->instance_name->str, "",
770 muxer_cfg_comp->instance_name->str, "",
771 "(auto)");
772
773 if (!cfg_connection) {
774 goto error;
775 }
776
777 g_ptr_array_add(cfg->cmd_data.convert.connections,
778 cfg_connection);
779 }
780
781 /* Connect this mux to the filter components, in order */
782 last_filter_comp_name = muxer_cfg_comp->instance_name->str;
783
784 for (i = 0; i < cfg->cmd_data.convert.filters->len - 1; i++) {
785 struct bt_config_component *comp =
786 g_ptr_array_index(cfg->cmd_data.convert.filters, i);
787 struct bt_config_connection *cfg_connection;
788
789 cfg_connection = bt_config_connection_create_full(
790 last_filter_comp_name, "",
791 comp->instance_name->str, "",
792 "(auto)");
793
794 if (!cfg_connection) {
795 goto error;
796 }
797
798 g_ptr_array_add(cfg->cmd_data.convert.connections,
799 cfg_connection);
800 last_filter_comp_name = comp->instance_name->str;
801 }
802
803 /* Connect the last filter component to all sink components */
804 for (i = 0; i < cfg->cmd_data.convert.sinks->len; i++) {
805 struct bt_config_component *comp =
806 g_ptr_array_index(cfg->cmd_data.convert.sinks, i);
807 struct bt_config_connection *cfg_connection =
808 bt_config_connection_create_full(
809 last_filter_comp_name, "",
810 comp->instance_name->str, "",
811 "(auto)");
812
813 if (!cfg_connection) {
814 goto error;
815 }
816
817 g_ptr_array_add(cfg->cmd_data.convert.connections,
818 cfg_connection);
819 }
820
821 goto end;
822
823error:
824 ret = -1;
825
826end:
827 bt_put(muxer_cfg_comp);
828 return ret;
829}
830
831int bt_config_create_connections(struct bt_config *cfg,
832 struct bt_value *connection_args,
833 char *error_buf, size_t error_buf_size)
834{
835 int ret;
836 size_t i;
837
838 if (bt_value_array_is_empty(connection_args)) {
839 /* No explicit connections: do automatic connection */
840 ret = auto_connect(cfg);
841 if (ret) {
842 goto error;
843 }
844 }
845
846 if (!all_named(cfg)) {
847 snprintf(error_buf, error_buf_size, "At least one connection (--connect) specified, but not all component\ninstances are named (use --name)\n");
848 goto error;
849 }
850
851 for (i = 0; i < bt_value_array_size(connection_args); i++) {
852 struct bt_value *arg_value =
853 bt_value_array_get(connection_args, i);
854 const char *arg;
855 struct bt_config_connection *cfg_connection;
856
857 ret = bt_value_string_get(arg_value, &arg);
858 BT_PUT(arg_value);
859 assert(ret == 0);
860 cfg_connection = cfg_connection_from_arg(arg);
861 if (!cfg_connection) {
862 snprintf(error_buf, error_buf_size, "Cannot parse --connect option's argument:\n %s\n",
863 arg);
864 goto error;
865 }
866
867 g_ptr_array_add(cfg->cmd_data.convert.connections,
868 cfg_connection);
869 }
870
871
872 ret = validate_connections(cfg, error_buf, error_buf_size);
873 if (ret) {
874 goto error;
875 }
876
877 goto end;
878
879error:
880 ret = -1;
881
882end:
883 return ret;
884}
This page took 0.052655 seconds and 4 git commands to generate.