2 * Copyright (c) 2019 EfficiOS Inc. and Linux Foundation
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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
23 #define BT_LOG_TAG "CLI-CFG-SRC-AUTO-DISC"
24 #define BT_LOG_OUTPUT_LEVEL log_level
25 #include "logging/log.h"
28 #include "common/common.h"
30 #define BT_AUTODISC_LOG_AND_APPEND(_lvl, _fmt, ...) \
32 BT_LOG_WRITE(_lvl, BT_LOG_TAG, _fmt, ##__VA_ARGS__); \
33 (void) BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN( \
34 "Source auto-discovery", _fmt, ##__VA_ARGS__); \
37 #define BT_AUTODISC_LOGE_APPEND_CAUSE(_fmt, ...) \
38 BT_AUTODISC_LOG_AND_APPEND(BT_LOG_ERROR, _fmt, ##__VA_ARGS__)
41 * Define a status enum for inside the auto source discovery code,
42 * as we don't want to return `NO_MATCH` to the caller.
44 typedef enum auto_source_discovery_internal_status
{
45 AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_OK
= AUTO_SOURCE_DISCOVERY_STATUS_OK
,
46 AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_ERROR
= AUTO_SOURCE_DISCOVERY_STATUS_ERROR
,
47 AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_MEMORY_ERROR
= AUTO_SOURCE_DISCOVERY_STATUS_MEMORY_ERROR
,
48 AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_INTERRUPTED
= AUTO_SOURCE_DISCOVERY_STATUS_INTERRUPTED
,
49 AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_NO_MATCH
= __BT_FUNC_STATUS_NO_MATCH
,
50 } auto_source_discovery_internal_status
;
52 /* Finalize and free a `struct auto_source_discovery_result`. */
55 void auto_source_discovery_result_destroy(struct auto_source_discovery_result
*res
)
59 bt_value_put_ref(res
->inputs
);
60 bt_value_put_ref(res
->original_input_indices
);
65 /* Allocate and initialize a `struct auto_source_discovery_result`. */
68 struct auto_source_discovery_result
*auto_source_discovery_result_create(
69 const char *plugin_name
, const char *source_cc_name
,
70 const char *group
, bt_logging_level log_level
)
72 struct auto_source_discovery_result
*res
;
74 res
= g_new0(struct auto_source_discovery_result
, 1);
76 BT_AUTODISC_LOGE_APPEND_CAUSE(
77 "Failed to allocate a auto_source_discovery_result structure.");
81 res
->plugin_name
= plugin_name
;
82 res
->source_cc_name
= source_cc_name
;
83 res
->group
= g_strdup(group
);
84 if (group
&& !res
->group
) {
85 BT_AUTODISC_LOGE_APPEND_CAUSE("Failed to allocate a string.");
89 res
->inputs
= bt_value_array_create();
91 BT_AUTODISC_LOGE_APPEND_CAUSE("Failed to allocate an array value.");
95 res
->original_input_indices
= bt_value_array_create();
96 if (!res
->original_input_indices
) {
97 BT_AUTODISC_LOGE_APPEND_CAUSE("Failed to allocate an array value.");
103 auto_source_discovery_result_destroy(res
);
110 /* Finalize a `struct auto_source_discovery`. */
112 void auto_source_discovery_fini(struct auto_source_discovery
*auto_disc
)
114 if (auto_disc
->results
) {
115 g_ptr_array_free(auto_disc
->results
, TRUE
);
119 /* Initialize an already allocated `struct auto_source_discovery`. */
121 int auto_source_discovery_init(struct auto_source_discovery
*auto_disc
)
125 auto_disc
->results
= g_ptr_array_new_with_free_func(
126 (GDestroyNotify
) auto_source_discovery_result_destroy
);
128 if (!auto_disc
->results
) {
136 auto_source_discovery_fini(auto_disc
);
145 const bt_value
*borrow_array_value_last_element_const(const bt_value
*array
)
147 uint64_t last_index
= bt_value_array_get_length(array
) - 1;
149 return bt_value_array_borrow_element_by_index_const(array
, last_index
);
153 * Assign `input` to source component class `source_cc_name` of plugin
154 * `plugin_name`, in the group with key `group`.
158 auto_source_discovery_internal_status
auto_source_discovery_add(
159 struct auto_source_discovery
*auto_disc
,
160 const char *plugin_name
,
161 const char *source_cc_name
,
164 uint64_t original_input_index
,
165 bt_logging_level log_level
)
167 auto_source_discovery_internal_status status
;
168 bt_value_array_append_element_status append_status
;
171 struct auto_source_discovery_result
*res
= NULL
;
174 len
= auto_disc
->results
->len
;
178 for (i
= 0; i
< len
; i
++) {
179 res
= g_ptr_array_index(auto_disc
->results
, i
);
181 if (strcmp(res
->plugin_name
, plugin_name
) != 0) {
185 if (strcmp(res
->source_cc_name
, source_cc_name
) != 0) {
189 if (g_strcmp0(res
->group
, group
) != 0) {
198 /* Add a new result entry. */
199 res
= auto_source_discovery_result_create(plugin_name
,
200 source_cc_name
, group
, log_level
);
205 g_ptr_array_add(auto_disc
->results
, res
);
208 append_status
= bt_value_array_append_string_element(res
->inputs
, input
);
209 if (append_status
!= BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK
) {
210 BT_AUTODISC_LOGE_APPEND_CAUSE("Failed to append a string value.");
215 * Append `original_input_index` to `original_input_indices` if not
216 * there already. We process the `inputs` array in order, so if it is
217 * present, it has to be the last element.
219 if (bt_value_array_is_empty(res
->original_input_indices
)) {
222 const bt_value
*last_index_value
;
226 borrow_array_value_last_element_const(res
->original_input_indices
);
227 last_index
= bt_value_integer_unsigned_get(last_index_value
);
229 BT_ASSERT(last_index
<= original_input_index
);
231 append_index
= (last_index
!= original_input_index
);
235 append_status
= bt_value_array_append_unsigned_integer_element(
236 res
->original_input_indices
, original_input_index
);
238 if (append_status
!= BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK
) {
239 BT_AUTODISC_LOGE_APPEND_CAUSE("Failed to append an unsigned integer value.");
244 status
= AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_OK
;
248 status
= AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_ERROR
;
255 int convert_weight_value(const bt_value
*weight_value
, double *weight
,
256 const char *plugin_name
, const char *source_cc_name
,
257 const char *input
, const char *input_type
,
258 bt_logging_level log_level
)
260 enum bt_value_type weight_value_type
;
263 weight_value_type
= bt_value_get_type(weight_value
);
265 if (weight_value_type
== BT_VALUE_TYPE_REAL
) {
266 *weight
= bt_value_real_get(weight_value
);
267 } else if (weight_value_type
== BT_VALUE_TYPE_SIGNED_INTEGER
) {
268 /* Accept signed integer as a convenience for "return 0" or "return 1" in Python. */
269 *weight
= bt_value_integer_signed_get(weight_value
);
271 BT_LOGW("babeltrace.support-info query: unexpected type for weight: "
272 "component-class-name=source.%s.%s, input=%s, input-type=%s, "
273 "expected-entry-type=%s, actual-entry-type=%s",
274 plugin_name
, source_cc_name
, input
, input_type
,
275 bt_common_value_type_string(BT_VALUE_TYPE_REAL
),
276 bt_common_value_type_string(bt_value_get_type(weight_value
)));
280 if (*weight
< 0.0 || *weight
> 1.0) {
281 BT_LOGW("babeltrace.support-info query: weight value is out of range [0.0, 1.0]: "
282 "component-class-name=source.%s.%s, input=%s, input-type=%s, "
284 plugin_name
, source_cc_name
, input
, input_type
, *weight
);
299 bt_query_executor_query_status
simple_query(const bt_component_class
*comp_cls
,
300 const char *obj
, const bt_value
*params
,
301 bt_logging_level log_level
, const bt_value
**result
)
303 bt_query_executor_query_status status
;
304 bt_query_executor_set_logging_level_status set_logging_level_status
;
305 bt_query_executor
*query_exec
;
307 query_exec
= bt_query_executor_create(comp_cls
, obj
, params
);
309 BT_AUTODISC_LOGE_APPEND_CAUSE("Cannot create a query executor.");
310 status
= BT_QUERY_EXECUTOR_QUERY_STATUS_MEMORY_ERROR
;
314 set_logging_level_status
= bt_query_executor_set_logging_level(query_exec
, log_level
);
315 if (set_logging_level_status
!= BT_QUERY_EXECUTOR_SET_LOGGING_LEVEL_STATUS_OK
) {
316 BT_AUTODISC_LOGE_APPEND_CAUSE(
317 "Cannot set query executor's logging level: "
319 bt_common_logging_level_string(log_level
));
320 status
= (int) set_logging_level_status
;
324 status
= bt_query_executor_query(query_exec
, result
);
327 bt_query_executor_put_ref(query_exec
);
334 * Query all known source components to see if any of them can handle `input`
335 * as the given `type`(arbitrary string, directory or file).
337 * If `plugin_restrict` is non-NULL, only query source component classes provided
338 * by the plugin with that name.
340 * If `component_class_restrict` is non-NULL, only query source component classes
344 auto_source_discovery_internal_status
support_info_query_all_sources(
346 const char *input_type
,
347 uint64_t original_input_index
,
348 const bt_plugin
**plugins
,
350 const char *component_class_restrict
,
351 enum bt_logging_level log_level
,
352 struct auto_source_discovery
*auto_disc
,
353 const bt_interrupter
*interrupter
)
355 bt_value_map_insert_entry_status insert_status
;
356 bt_value
*query_params
= NULL
;
357 auto_source_discovery_internal_status status
;
359 const struct bt_value
*query_result
= NULL
;
361 const bt_component_class_source
*source
;
362 const bt_plugin
*plugin
;
363 const bt_value
*group
;
365 } winner
= { NULL
, NULL
, NULL
, 0 };
367 if (interrupter
&& bt_interrupter_is_set(interrupter
)) {
368 status
= AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_INTERRUPTED
;
372 query_params
= bt_value_map_create();
374 BT_AUTODISC_LOGE_APPEND_CAUSE("Failed to allocate a map value.");
378 insert_status
= bt_value_map_insert_string_entry(query_params
, "input", input
);
379 if (insert_status
!= BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK
) {
380 BT_AUTODISC_LOGE_APPEND_CAUSE("Failed to insert a map entry.");
384 insert_status
= bt_value_map_insert_string_entry(query_params
, "type", input_type
);
385 if (insert_status
!= BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK
) {
386 BT_AUTODISC_LOGE_APPEND_CAUSE("Failed to insert a map entry.");
390 for (i_plugins
= 0; i_plugins
< plugin_count
; i_plugins
++) {
391 const bt_plugin
*plugin
;
392 const char *plugin_name
;
393 uint64_t source_count
;
396 plugin
= plugins
[i_plugins
];
397 plugin_name
= bt_plugin_get_name(plugin
);
399 source_count
= bt_plugin_get_source_component_class_count(plugin
);
401 for (i_sources
= 0; i_sources
< source_count
; i_sources
++) {
402 const bt_component_class_source
*source_cc
;
403 const bt_component_class
*cc
;
404 const char *source_cc_name
;
405 bt_query_executor_query_status query_status
;
407 source_cc
= bt_plugin_borrow_source_component_class_by_index_const(plugin
, i_sources
);
408 cc
= bt_component_class_source_as_component_class_const(source_cc
);
409 source_cc_name
= bt_component_class_get_name(cc
);
412 * If the search is restricted to a specific component class, only consider the
413 * component classes with that name.
415 if (component_class_restrict
&& strcmp(component_class_restrict
, source_cc_name
) != 0) {
419 BT_LOGD("babeltrace.support-info query: before: component-class-name=source.%s.%s, input=%s, "
420 "type=%s", plugin_name
, source_cc_name
, input
, input_type
);
422 BT_VALUE_PUT_REF_AND_RESET(query_result
);
423 query_status
= simple_query(cc
, "babeltrace.support-info",
424 query_params
, log_level
, &query_result
);
426 if (query_status
== BT_QUERY_EXECUTOR_QUERY_STATUS_OK
) {
428 const bt_value
*group_value
= NULL
;
429 enum bt_value_type query_result_type
;
431 BT_ASSERT(query_result
);
433 query_result_type
= bt_value_get_type(query_result
);
435 if (query_result_type
== BT_VALUE_TYPE_REAL
|| query_result_type
== BT_VALUE_TYPE_SIGNED_INTEGER
) {
436 if (convert_weight_value(query_result
, &weight
, plugin_name
, source_cc_name
, input
, input_type
, log_level
) != 0) {
437 /* convert_weight_value has already warned. */
440 } else if (query_result_type
== BT_VALUE_TYPE_MAP
) {
441 const bt_value
*weight_value
;
443 if (!bt_value_map_has_entry(query_result
, "weight")) {
444 BT_LOGW("babeltrace.support-info query: result is missing `weight` entry: "
445 "component-class-name=source.%s.%s, input=%s, input-type=%s",
446 bt_plugin_get_name(plugin
),
447 bt_component_class_get_name(cc
), input
,
452 weight_value
= bt_value_map_borrow_entry_value_const(query_result
, "weight");
453 BT_ASSERT(weight_value
);
455 if (convert_weight_value(weight_value
, &weight
, plugin_name
, source_cc_name
, input
, input_type
, log_level
) != 0) {
456 /* convert_weight_value has already warned. */
460 if (bt_value_map_has_entry(query_result
, "group")) {
461 enum bt_value_type group_value_type
;
463 group_value
= bt_value_map_borrow_entry_value_const(query_result
, "group");
464 BT_ASSERT(group_value
);
466 group_value_type
= bt_value_get_type(group_value
);
468 if (group_value_type
== BT_VALUE_TYPE_NULL
) {
469 /* Do as if no value was passed. */
471 } else if (bt_value_get_type(group_value
) != BT_VALUE_TYPE_STRING
) {
472 BT_LOGW("babeltrace.support-info query: unexpected type for entry `group`: "
473 "component-class-name=source.%s.%s, input=%s, input-type=%s, "
474 "expected-entry-type=%s,%s, actual-entry-type=%s",
475 bt_plugin_get_name(plugin
),
476 bt_component_class_get_name(cc
), input
,
478 bt_common_value_type_string(BT_VALUE_TYPE_NULL
),
479 bt_common_value_type_string(BT_VALUE_TYPE_STRING
),
480 bt_common_value_type_string(bt_value_get_type(group_value
)));
485 BT_LOGW("babeltrace.support-info query: unexpected result type: "
486 "component-class-name=source.%s.%s, input=%s, input-type=%s, "
487 "expected-types=%s,%s,%s, actual-type=%s",
488 bt_plugin_get_name(plugin
),
489 bt_component_class_get_name(cc
), input
,
491 bt_common_value_type_string(BT_VALUE_TYPE_REAL
),
492 bt_common_value_type_string(BT_VALUE_TYPE_MAP
),
493 bt_common_value_type_string(BT_VALUE_TYPE_SIGNED_INTEGER
),
494 bt_common_value_type_string(bt_value_get_type(query_result
)));
498 BT_LOGD("babeltrace.support-info query: success: component-class-name=source.%s.%s, input=%s, "
499 "type=%s, weight=%f, group=%s\n",
500 bt_plugin_get_name(plugin
), bt_component_class_get_name(cc
), input
,
501 input_type
, weight
, group_value
? bt_value_string_get(group_value
) : "(none)");
503 if (weight
> winner
.weigth
) {
504 winner
.source
= source_cc
;
505 winner
.plugin
= plugin
;
507 bt_value_put_ref(winner
.group
);
508 winner
.group
= group_value
;
509 bt_value_get_ref(winner
.group
);
511 winner
.weigth
= weight
;
513 } else if (query_status
== BT_QUERY_EXECUTOR_QUERY_STATUS_ERROR
) {
514 BT_AUTODISC_LOGE_APPEND_CAUSE("babeltrace.support-info query failed.");
516 } else if (query_status
== BT_QUERY_EXECUTOR_QUERY_STATUS_MEMORY_ERROR
) {
517 BT_AUTODISC_LOGE_APPEND_CAUSE("Memory error.");
520 BT_LOGD("babeltrace.support-info query: failure: component-class-name=source.%s.%s, input=%s, "
521 "type=%s, status=%s\n",
522 bt_plugin_get_name(plugin
), bt_component_class_get_name(cc
), input
,
524 bt_common_func_status_string(query_status
));
530 const char *source_name
;
531 const char *plugin_name
;
534 source_name
= bt_component_class_get_name(
535 bt_component_class_source_as_component_class_const(winner
.source
));
536 plugin_name
= bt_plugin_get_name(winner
.plugin
);
537 group
= winner
.group
? bt_value_string_get(winner
.group
) : NULL
;
539 BT_LOGI("Input awarded: input=%s, type=%s, component-class-name=source.%s.%s, weight=%f, group=%s",
540 input
, input_type
, plugin_name
, source_name
, winner
.weigth
, group
? group
: "(none)");
542 status
= auto_source_discovery_add(auto_disc
, plugin_name
,
543 source_name
, group
, input
, original_input_index
, log_level
);
544 if (status
!= AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_OK
) {
548 BT_LOGI("Input not recognized: input=%s, type=%s",
550 status
= AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_NO_MATCH
;
556 status
= AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_ERROR
;
559 bt_value_put_ref(query_result
);
560 bt_value_put_ref(query_params
);
561 bt_value_put_ref(winner
.group
);
567 * Look for a source component class that recognizes `input` as an arbitrary
570 * Same return value semantic as `support_info_query_all_sources`.
574 auto_source_discovery_internal_status
auto_discover_source_for_input_as_string(
576 uint64_t original_input_index
,
577 const bt_plugin
**plugins
,
579 const char *component_class_restrict
,
580 enum bt_logging_level log_level
,
581 struct auto_source_discovery
*auto_disc
,
582 const bt_interrupter
*interrupter
)
584 return support_info_query_all_sources(input
, "string",
585 original_input_index
, plugins
, plugin_count
,
586 component_class_restrict
, log_level
, auto_disc
,
591 auto_source_discovery_internal_status
auto_discover_source_for_input_as_dir_or_file_rec(
593 uint64_t original_input_index
,
594 const bt_plugin
**plugins
,
596 const char *component_class_restrict
,
597 enum bt_logging_level log_level
,
598 struct auto_source_discovery
*auto_disc
,
599 const bt_interrupter
*interrupter
)
601 auto_source_discovery_internal_status status
;
602 GError
*error
= NULL
;
604 if (g_file_test(input
->str
, G_FILE_TEST_IS_REGULAR
)) {
606 status
= support_info_query_all_sources(input
->str
,
607 "file", original_input_index
, plugins
, plugin_count
,
608 component_class_restrict
, log_level
, auto_disc
,
610 } else if (g_file_test(input
->str
, G_FILE_TEST_IS_DIR
)) {
613 gsize saved_input_len
;
614 int dir_status
= AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_NO_MATCH
;
616 /* It's a directory. */
617 status
= support_info_query_all_sources(input
->str
,
618 "directory", original_input_index
, plugins
,
619 plugin_count
, component_class_restrict
, log_level
,
620 auto_disc
, interrupter
);
625 } else if (status
== AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_OK
||
626 status
== AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_INTERRUPTED
) {
628 * A component class claimed this input as a directory,
629 * don't recurse. Or, we got interrupted.
634 dir
= g_dir_open(input
->str
, 0, &error
);
636 const char *fmt
= "Failed to open directory %s: %s";
637 BT_LOGW(fmt
, input
->str
, error
->message
);
639 if (error
->code
== G_FILE_ERROR_ACCES
) {
640 /* This is not a fatal error, we just skip it. */
641 status
= AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_NO_MATCH
;
644 BT_AUTODISC_LOGE_APPEND_CAUSE(fmt
, input
->str
,
650 saved_input_len
= input
->len
;
654 dirent
= g_dir_read_name(dir
);
656 g_string_append_c_inline(input
, G_DIR_SEPARATOR
);
657 g_string_append(input
, dirent
);
659 status
= auto_discover_source_for_input_as_dir_or_file_rec(
660 input
, original_input_index
, plugins
, plugin_count
,
661 component_class_restrict
, log_level
, auto_disc
,
664 g_string_truncate(input
, saved_input_len
);
669 } else if (status
== AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_INTERRUPTED
) {
671 } else if (status
== AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_OK
) {
672 dir_status
= AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_OK
;
674 } else if (errno
!= 0) {
675 BT_LOGW_ERRNO("Failed to read directory entry", ": dir=%s", input
->str
);
684 BT_LOGD("Skipping %s, not a file or directory", input
->str
);
685 status
= AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_NO_MATCH
;
691 status
= AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_ERROR
;
703 * Look for a source component class that recognizes `input` as a directory or
704 * file. If `input` is a directory and is not directly recognized, recurse and
705 * apply the same logic to children nodes.
707 * Same return value semantic as `support_info_query_all_sources`.
711 auto_source_discovery_internal_status
auto_discover_source_for_input_as_dir_or_file(
713 uint64_t original_input_index
,
714 const bt_plugin
**plugins
,
716 const char *component_class_restrict
,
717 enum bt_logging_level log_level
,
718 struct auto_source_discovery
*auto_disc
,
719 const bt_interrupter
*interrupter
)
721 GString
*mutable_input
;
722 auto_source_discovery_internal_status status
;
724 mutable_input
= g_string_new(input
);
725 if (!mutable_input
) {
726 status
= AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_ERROR
;
730 status
= auto_discover_source_for_input_as_dir_or_file_rec(
731 mutable_input
, original_input_index
, plugins
, plugin_count
,
732 component_class_restrict
, log_level
, auto_disc
,
735 g_string_free(mutable_input
, TRUE
);
740 auto_source_discovery_status
auto_discover_source_components(
741 const bt_value
*inputs
,
742 const bt_plugin
**plugins
,
744 const char *component_class_restrict
,
745 enum bt_logging_level log_level
,
746 struct auto_source_discovery
*auto_disc
,
747 const bt_interrupter
*interrupter
)
749 uint64_t i_inputs
, input_count
;
750 auto_source_discovery_internal_status internal_status
;
751 auto_source_discovery_status status
;
753 input_count
= bt_value_array_get_length(inputs
);
755 for (i_inputs
= 0; i_inputs
< input_count
; i_inputs
++) {
756 const bt_value
*input_value
;
759 input_value
= bt_value_array_borrow_element_by_index_const(inputs
, i_inputs
);
760 input
= bt_value_string_get(input_value
);
761 internal_status
= auto_discover_source_for_input_as_string(input
, i_inputs
,
762 plugins
, plugin_count
, component_class_restrict
,
763 log_level
, auto_disc
, interrupter
);
764 if (internal_status
< 0 || internal_status
== AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_INTERRUPTED
) {
765 /* Fatal error or we got interrupted. */
766 status
= (auto_source_discovery_status
) internal_status
;
768 } else if (internal_status
== AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_OK
) {
769 /* A component class has claimed this input as an arbitrary string. */
773 internal_status
= auto_discover_source_for_input_as_dir_or_file(input
,
774 i_inputs
, plugins
, plugin_count
,
775 component_class_restrict
, log_level
, auto_disc
, interrupter
);
776 if (internal_status
< 0 || internal_status
== AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_INTERRUPTED
) {
777 /* Fatal error or we got interrupted. */
778 status
= (auto_source_discovery_status
) internal_status
;
780 } else if (internal_status
== 0) {
782 * This input (or something under it) was recognized.
787 BT_LOGW("No trace was found based on input `%s`.", input
);
790 status
= AUTO_SOURCE_DISCOVERY_STATUS_OK
;