Make bitfield.h C++-friendly
[babeltrace.git] / src / autodisc / autodisc.c
CommitLineData
73760435
SM
1/*
2 * Copyright (c) 2019 EfficiOS Inc. and Linux Foundation
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#define BT_LOG_TAG "CLI-CFG-SRC-AUTO-DISC"
97010665
SM
24#define BT_LOG_OUTPUT_LEVEL log_level
25#include "logging/log.h"
73760435 26
97010665 27#include "autodisc.h"
73760435
SM
28#include "common/common.h"
29
97010665
SM
30#define BT_AUTODISC_LOG_AND_APPEND(_lvl, _fmt, ...) \
31 do { \
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__); \
35 } while (0)
36
37#define BT_AUTODISC_LOGE_APPEND_CAUSE(_fmt, ...) \
38 BT_AUTODISC_LOG_AND_APPEND(BT_LOG_ERROR, _fmt, ##__VA_ARGS__)
39
73760435
SM
40/* Finalize and free a `struct auto_source_discovery_result`. */
41
42static
43void auto_source_discovery_result_destroy(struct auto_source_discovery_result *res)
44{
45 if (res) {
46 g_free(res->group);
47 bt_value_put_ref(res->inputs);
45bab744 48 bt_value_put_ref(res->original_input_indices);
73760435
SM
49 g_free(res);
50 }
51}
52
53/* Allocate and initialize a `struct auto_source_discovery_result`. */
54
55static
56struct auto_source_discovery_result *auto_source_discovery_result_create(
57 const char *plugin_name, const char *source_cc_name,
97010665 58 const char *group, bt_logging_level log_level)
73760435
SM
59{
60 struct auto_source_discovery_result *res;
61
62 res = g_new0(struct auto_source_discovery_result, 1);
63 if (!res) {
97010665 64 BT_AUTODISC_LOGE_APPEND_CAUSE(
73760435
SM
65 "Failed to allocate a auto_source_discovery_result structure.");
66 goto error;
67 }
68
69 res->plugin_name = plugin_name;
70 res->source_cc_name = source_cc_name;
71 res->group = g_strdup(group);
72 if (group && !res->group) {
97010665 73 BT_AUTODISC_LOGE_APPEND_CAUSE("Failed to allocate a string.");
73760435
SM
74 goto error;
75 }
76
77 res->inputs = bt_value_array_create();
78 if (!res->inputs) {
97010665 79 BT_AUTODISC_LOGE_APPEND_CAUSE("Failed to allocate an array value.");
73760435
SM
80 goto error;
81 }
82
1ead9076
SM
83 res->original_input_indices = bt_value_array_create();
84 if (!res->original_input_indices) {
97010665 85 BT_AUTODISC_LOGE_APPEND_CAUSE("Failed to allocate an array value.");
1ead9076
SM
86 goto error;
87 }
88
73760435
SM
89 goto end;
90error:
91 auto_source_discovery_result_destroy(res);
cc611878 92 res = NULL;
73760435
SM
93
94end:
95 return res;
96}
97
98/* Finalize a `struct auto_source_discovery`. */
99
100void auto_source_discovery_fini(struct auto_source_discovery *auto_disc)
101{
102 if (auto_disc->results) {
103 g_ptr_array_free(auto_disc->results, TRUE);
104 }
105}
106
107/* Initialize an already allocated `struct auto_source_discovery`. */
108
109int auto_source_discovery_init(struct auto_source_discovery *auto_disc)
110{
111 int status;
112
113 auto_disc->results = g_ptr_array_new_with_free_func(
114 (GDestroyNotify) auto_source_discovery_result_destroy);
115
116 if (!auto_disc->results) {
117 goto error;
118 }
119
120 status = 0;
121 goto end;
122
123error:
124 auto_source_discovery_fini(auto_disc);
125 status = -1;
126
127end:
128
129 return status;
130}
131
1ead9076
SM
132static
133const bt_value *borrow_array_value_last_element_const(const bt_value *array)
134{
393729a6 135 uint64_t last_index = bt_value_array_get_length(array) - 1;
1ead9076
SM
136
137 return bt_value_array_borrow_element_by_index_const(array, last_index);
138}
139
73760435
SM
140/*
141 * Assign `input` to source component class `source_cc_name` of plugin
142 * `plugin_name`, in the group with key `group`.
143 */
144
145static
146int auto_source_discovery_add(struct auto_source_discovery *auto_disc,
147 const char *plugin_name,
148 const char *source_cc_name,
149 const char *group,
1ead9076 150 const char *input,
97010665
SM
151 uint64_t original_input_index,
152 bt_logging_level log_level)
73760435
SM
153{
154 int status;
155 bt_value_array_append_element_status append_status;
156 guint len;
157 guint i;
158 struct auto_source_discovery_result *res = NULL;
1ead9076 159 bool append_index;
73760435
SM
160
161 len = auto_disc->results->len;
162 i = len;
163
164 if (group) {
165 for (i = 0; i < len; i++) {
166 res = g_ptr_array_index(auto_disc->results, i);
167
168 if (strcmp(res->plugin_name, plugin_name) != 0) {
169 continue;
170 }
171
172 if (strcmp(res->source_cc_name, source_cc_name) != 0) {
173 continue;
174 }
175
176 if (g_strcmp0(res->group, group) != 0) {
177 continue;
178 }
179
180 break;
181 }
182 }
183
184 if (i == len) {
185 /* Add a new result entry. */
186 res = auto_source_discovery_result_create(plugin_name,
97010665 187 source_cc_name, group, log_level);
73760435
SM
188 if (!res) {
189 goto error;
190 }
191
192 g_ptr_array_add(auto_disc->results, res);
193 }
194
195 append_status = bt_value_array_append_string_element(res->inputs, input);
196 if (append_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) {
97010665 197 BT_AUTODISC_LOGE_APPEND_CAUSE("Failed to append a string value.");
73760435
SM
198 goto error;
199 }
200
1ead9076
SM
201 /*
202 * Append `original_input_index` to `original_input_indices` if not
203 * there already. We process the `inputs` array in order, so if it is
204 * present, it has to be the last element.
205 */
206 if (bt_value_array_is_empty(res->original_input_indices)) {
207 append_index = true;
208 } else {
209 const bt_value *last_index_value;
210 uint64_t last_index;
211
212 last_index_value =
213 borrow_array_value_last_element_const(res->original_input_indices);
214 last_index = bt_value_integer_unsigned_get(last_index_value);
215
216 BT_ASSERT(last_index <= original_input_index);
217
218 append_index = (last_index != original_input_index);
219 }
220
221 if (append_index) {
222 append_status = bt_value_array_append_unsigned_integer_element(
223 res->original_input_indices, original_input_index);
224
225 if (append_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) {
97010665 226 BT_AUTODISC_LOGE_APPEND_CAUSE("Failed to append an unsigned integer value.");
1ead9076
SM
227 goto error;
228 }
229 }
73760435
SM
230
231 status = 0;
232 goto end;
233
234error:
235 status = -1;
236
237end:
238 return status;
239}
240
241static
242int convert_weight_value(const bt_value *weight_value, double *weight,
243 const char *plugin_name, const char *source_cc_name,
97010665
SM
244 const char *input, const char *input_type,
245 bt_logging_level log_level)
73760435
SM
246{
247 enum bt_value_type weight_value_type;
248 int status;
249
250 weight_value_type = bt_value_get_type(weight_value);
251
252 if (weight_value_type == BT_VALUE_TYPE_REAL) {
253 *weight = bt_value_real_get(weight_value);
254 } else if (weight_value_type == BT_VALUE_TYPE_SIGNED_INTEGER) {
255 /* Accept signed integer as a convenience for "return 0" or "return 1" in Python. */
256 *weight = bt_value_integer_signed_get(weight_value);
257 } else {
1a29b831 258 BT_LOGW("babeltrace.support-info query: unexpected type for weight: "
73760435
SM
259 "component-class-name=source.%s.%s, input=%s, input-type=%s, "
260 "expected-entry-type=%s, actual-entry-type=%s",
261 plugin_name, source_cc_name, input, input_type,
262 bt_common_value_type_string(BT_VALUE_TYPE_REAL),
263 bt_common_value_type_string(bt_value_get_type(weight_value)));
264 goto error;
265 }
266
267 if (*weight < 0.0 || *weight > 1.0) {
1a29b831 268 BT_LOGW("babeltrace.support-info query: weight value is out of range [0.0, 1.0]: "
73760435
SM
269 "component-class-name=source.%s.%s, input=%s, input-type=%s, "
270 "weight=%f",
271 plugin_name, source_cc_name, input, input_type, *weight);
272 goto error;
273 }
274
275 status = 0;
276 goto end;
277
278error:
279 status = -1;
280
281end:
282 return status;
283}
284
97010665
SM
285static
286bt_query_executor_query_status simple_query(const bt_component_class *comp_cls,
287 const char *obj, const bt_value *params,
288 bt_logging_level log_level, const bt_value **result)
289{
290 bt_query_executor_query_status status;
291 bt_query_executor_set_logging_level_status set_logging_level_status;
292 bt_query_executor *query_exec;
293
294 query_exec = bt_query_executor_create(comp_cls, obj, params);
295 if (!query_exec) {
296 BT_AUTODISC_LOGE_APPEND_CAUSE("Cannot create a query executor.");
297 status = BT_QUERY_EXECUTOR_QUERY_STATUS_MEMORY_ERROR;
298 goto end;
299 }
300
301 set_logging_level_status = bt_query_executor_set_logging_level(query_exec, log_level);
302 if (set_logging_level_status != BT_QUERY_EXECUTOR_SET_LOGGING_LEVEL_STATUS_OK) {
303 BT_AUTODISC_LOGE_APPEND_CAUSE(
304 "Cannot set query executor's logging level: "
305 "log-level=%s",
306 bt_common_logging_level_string(log_level));
307 status = (int) set_logging_level_status;
308 goto end;
309 }
310
311 status = bt_query_executor_query(query_exec, result);
312
313end:
314 bt_query_executor_put_ref(query_exec);
315
316 return status;
317}
318
319
73760435
SM
320/*
321 * Query all known source components to see if any of them can handle `input`
322 * as the given `type`(arbitrary string, directory or file).
323 *
324 * If `plugin_restrict` is non-NULL, only query source component classes provided
325 * by the plugin with that name.
326 *
327 * If `component_class_restrict` is non-NULL, only query source component classes
328 * with that name.
329 *
330 * Return:
331 *
332 * - > 0 on success, if no source component class has reported that it handles `input`
333 * - 0 on success, if a source component class has reported that it handles `input`
334 * - < 0 on failure (e.g. memory error)
335 */
336static
337int support_info_query_all_sources(const char *input,
1ead9076
SM
338 const char *input_type,
339 uint64_t original_input_index,
97010665 340 const bt_plugin **plugins,
1ead9076 341 size_t plugin_count,
73760435
SM
342 const char *component_class_restrict,
343 enum bt_logging_level log_level,
344 struct auto_source_discovery *auto_disc)
345{
346 bt_value_map_insert_entry_status insert_status;
347 bt_value *query_params = NULL;
348 int status;
349 size_t i_plugins;
350 const struct bt_value *query_result = NULL;
351 struct {
352 const bt_component_class_source *source;
353 const bt_plugin *plugin;
354 const bt_value *group;
355 double weigth;
356 } winner = { NULL, NULL, NULL, 0 };
357
358 query_params = bt_value_map_create();
359 if (!query_params) {
97010665 360 BT_AUTODISC_LOGE_APPEND_CAUSE("Failed to allocate a map value.");
73760435
SM
361 goto error;
362 }
363
364 insert_status = bt_value_map_insert_string_entry(query_params, "input", input);
365 if (insert_status != BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK) {
97010665 366 BT_AUTODISC_LOGE_APPEND_CAUSE("Failed to insert a map entry.");
73760435
SM
367 goto error;
368 }
369
370 insert_status = bt_value_map_insert_string_entry(query_params, "type", input_type);
371 if (insert_status != BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK) {
97010665 372 BT_AUTODISC_LOGE_APPEND_CAUSE("Failed to insert a map entry.");
73760435
SM
373 goto error;
374 }
375
376 for (i_plugins = 0; i_plugins < plugin_count; i_plugins++) {
377 const bt_plugin *plugin;
378 const char *plugin_name;
379 uint64_t source_count;
380 uint64_t i_sources;
381
97010665 382 plugin = plugins[i_plugins];
73760435
SM
383 plugin_name = bt_plugin_get_name(plugin);
384
73760435
SM
385 source_count = bt_plugin_get_source_component_class_count(plugin);
386
387 for (i_sources = 0; i_sources < source_count; i_sources++) {
388 const bt_component_class_source *source_cc;
389 const bt_component_class *cc;
390 const char *source_cc_name;
391 bt_query_executor_query_status query_status;
392
393 source_cc = bt_plugin_borrow_source_component_class_by_index_const(plugin, i_sources);
394 cc = bt_component_class_source_as_component_class_const(source_cc);
395 source_cc_name = bt_component_class_get_name(cc);
396
397 /*
398 * If the search is restricted to a specific component class, only consider the
399 * component classes with that name.
400 */
401 if (component_class_restrict && strcmp(component_class_restrict, source_cc_name) != 0) {
402 continue;
403 }
404
1a29b831 405 BT_LOGD("babeltrace.support-info query: before: component-class-name=source.%s.%s, input=%s, "
73760435
SM
406 "type=%s", plugin_name, source_cc_name, input, input_type);
407
408 BT_VALUE_PUT_REF_AND_RESET(query_result);
97010665
SM
409 query_status = simple_query(cc, "babeltrace.support-info",
410 query_params, log_level, &query_result);
73760435
SM
411
412 if (query_status == BT_QUERY_EXECUTOR_QUERY_STATUS_OK) {
413 double weight;
414 const bt_value *group_value = NULL;
415 enum bt_value_type query_result_type;
416
417 BT_ASSERT(query_result);
418
419 query_result_type = bt_value_get_type(query_result);
420
421 if (query_result_type == BT_VALUE_TYPE_REAL || query_result_type == BT_VALUE_TYPE_SIGNED_INTEGER) {
97010665 422 if (convert_weight_value(query_result, &weight, plugin_name, source_cc_name, input, input_type, log_level) != 0) {
73760435
SM
423 /* convert_weight_value has already warned. */
424 continue;
425 }
426 } else if (query_result_type == BT_VALUE_TYPE_MAP) {
427 const bt_value *weight_value;
428
429 if (!bt_value_map_has_entry(query_result, "weight")) {
1a29b831 430 BT_LOGW("babeltrace.support-info query: result is missing `weight` entry: "
73760435
SM
431 "component-class-name=source.%s.%s, input=%s, input-type=%s",
432 bt_plugin_get_name(plugin),
433 bt_component_class_get_name(cc), input,
434 input_type);
435 continue;
436 }
437
438 weight_value = bt_value_map_borrow_entry_value_const(query_result, "weight");
439 BT_ASSERT(weight_value);
440
97010665 441 if (convert_weight_value(weight_value, &weight, plugin_name, source_cc_name, input, input_type, log_level) != 0) {
73760435
SM
442 /* convert_weight_value has already warned. */
443 continue;
444 }
445
446 if (bt_value_map_has_entry(query_result, "group")) {
447 enum bt_value_type group_value_type;
448
449 group_value = bt_value_map_borrow_entry_value_const(query_result, "group");
450 BT_ASSERT(group_value);
451
452 group_value_type = bt_value_get_type(group_value);
453
454 if (group_value_type == BT_VALUE_TYPE_NULL) {
455 /* Do as if no value was passed. */
456 group_value = NULL;
457 } else if (bt_value_get_type(group_value) != BT_VALUE_TYPE_STRING) {
1a29b831 458 BT_LOGW("babeltrace.support-info query: unexpected type for entry `group`: "
73760435
SM
459 "component-class-name=source.%s.%s, input=%s, input-type=%s, "
460 "expected-entry-type=%s,%s, actual-entry-type=%s",
461 bt_plugin_get_name(plugin),
462 bt_component_class_get_name(cc), input,
463 input_type,
464 bt_common_value_type_string(BT_VALUE_TYPE_NULL),
465 bt_common_value_type_string(BT_VALUE_TYPE_STRING),
466 bt_common_value_type_string(bt_value_get_type(group_value)));
467 continue;
468 }
469 }
470 } else {
1a29b831 471 BT_LOGW("babeltrace.support-info query: unexpected result type: "
73760435
SM
472 "component-class-name=source.%s.%s, input=%s, input-type=%s, "
473 "expected-types=%s,%s,%s, actual-type=%s",
474 bt_plugin_get_name(plugin),
475 bt_component_class_get_name(cc), input,
476 input_type,
477 bt_common_value_type_string(BT_VALUE_TYPE_REAL),
478 bt_common_value_type_string(BT_VALUE_TYPE_MAP),
479 bt_common_value_type_string(BT_VALUE_TYPE_SIGNED_INTEGER),
480 bt_common_value_type_string(bt_value_get_type(query_result)));
481 continue;
482 }
483
1a29b831 484 BT_LOGD("babeltrace.support-info query: success: component-class-name=source.%s.%s, input=%s, "
73760435
SM
485 "type=%s, weight=%f\n",
486 bt_plugin_get_name(plugin), bt_component_class_get_name(cc), input,
487 input_type, weight);
488
489 if (weight > winner.weigth) {
490 winner.source = source_cc;
491 winner.plugin = plugin;
492
493 bt_value_put_ref(winner.group);
494 winner.group = group_value;
495 bt_value_get_ref(winner.group);
496
497 winner.weigth = weight;
498 }
499 } else if (query_status == BT_QUERY_EXECUTOR_QUERY_STATUS_ERROR) {
97010665 500 BT_AUTODISC_LOGE_APPEND_CAUSE("babeltrace.support-info query failed.");
73760435
SM
501 goto error;
502 } else if (query_status == BT_QUERY_EXECUTOR_QUERY_STATUS_MEMORY_ERROR) {
97010665 503 BT_AUTODISC_LOGE_APPEND_CAUSE("Memory error.");
73760435
SM
504 goto error;
505 } else {
1a29b831 506 BT_LOGD("babeltrace.support-info query: failure: component-class-name=source.%s.%s, input=%s, "
73760435
SM
507 "type=%s, status=%s\n",
508 bt_plugin_get_name(plugin), bt_component_class_get_name(cc), input,
509 input_type,
510 bt_common_func_status_string(query_status));
511 }
512 }
513 }
514
515 if (winner.source) {
516 const char *source_name;
517 const char *plugin_name;
518 const char *group;
519
520 source_name = bt_component_class_get_name(
521 bt_component_class_source_as_component_class_const(winner.source));
522 plugin_name = bt_plugin_get_name(winner.plugin);
523 group = winner.group ? bt_value_string_get(winner.group) : NULL;
524
525 BT_LOGI("Input %s is awarded to component class source.%s.%s with weight %f",
526 input, plugin_name, source_name, winner.weigth);
527
1ead9076 528 status = auto_source_discovery_add(auto_disc, plugin_name,
97010665 529 source_name, group, input, original_input_index, log_level);
73760435
SM
530 if (status != 0) {
531 goto error;
532 }
533 } else {
534 BT_LOGI("Input %s (%s) was not recognized by any source component class.",
535 input, input_type);
536 status = 1;
537 }
538
539 goto end;
540
541error:
542 status = -1;
543
544end:
545 bt_value_put_ref(query_result);
546 bt_value_put_ref(query_params);
547 bt_value_put_ref(winner.group);
548
549 return status;
550}
551
552/*
553 * Look for a source component class that recognizes `input` as an arbitrary
554 * string.
555 *
556 * Same return value semantic as `support_info_query_all_sources`.
557 */
558
559static
560int auto_discover_source_for_input_as_string(const char *input,
1ead9076 561 uint64_t original_input_index,
97010665
SM
562 const bt_plugin **plugins,
563 size_t plugin_count,
73760435
SM
564 const char *component_class_restrict,
565 enum bt_logging_level log_level,
566 struct auto_source_discovery *auto_disc)
567{
568 return support_info_query_all_sources(input, "string",
97010665 569 original_input_index, plugins, plugin_count,
1ead9076 570 component_class_restrict, log_level, auto_disc);
73760435
SM
571}
572
573static
574int auto_discover_source_for_input_as_dir_or_file_rec(GString *input,
1ead9076 575 uint64_t original_input_index,
97010665
SM
576 const bt_plugin **plugins,
577 size_t plugin_count,
73760435
SM
578 const char *component_class_restrict,
579 enum bt_logging_level log_level,
580 struct auto_source_discovery *auto_disc)
581{
582 int status;
583 GError *error = NULL;
584
585 if (g_file_test(input->str, G_FILE_TEST_IS_REGULAR)) {
586 /* It's a file. */
587 status = support_info_query_all_sources(input->str,
97010665
SM
588 "file", original_input_index, plugins, plugin_count,
589 component_class_restrict, log_level, auto_disc);
73760435
SM
590 } else if (g_file_test(input->str, G_FILE_TEST_IS_DIR)) {
591 GDir *dir;
592 const gchar *dirent;
593 gsize saved_input_len;
594 int dir_status = 1;
595
596 /* It's a directory. */
597 status = support_info_query_all_sources(input->str,
97010665
SM
598 "directory", original_input_index, plugins,
599 plugin_count, component_class_restrict, log_level,
73760435
SM
600 auto_disc);
601
602 if (status < 0) {
603 /* Fatal error. */
604 goto error;
605 } else if (status == 0) {
606 /*
607 * A component class claimed this input as a directory,
608 * don't recurse.
609 */
610 goto end;
611 }
612
613 dir = g_dir_open(input->str, 0, &error);
614 if (!dir) {
615 const char *fmt = "Failed to open directory %s: %s";
616 BT_LOGW(fmt, input->str, error->message);
617
d847ef86 618 if (error->code == G_FILE_ERROR_ACCES) {
73760435
SM
619 /* This is not a fatal error, we just skip it. */
620 status = 1;
621 goto end;
622 } else {
97010665 623 BT_AUTODISC_LOGE_APPEND_CAUSE(fmt, input->str,
73760435
SM
624 error->message);
625 goto error;
626 }
627 }
628
629 saved_input_len = input->len;
630
631 do {
632 errno = 0;
633 dirent = g_dir_read_name(dir);
634 if (dirent) {
635 g_string_append_c_inline(input, G_DIR_SEPARATOR);
636 g_string_append(input, dirent);
637
638 status = auto_discover_source_for_input_as_dir_or_file_rec(
97010665
SM
639 input, original_input_index, plugins, plugin_count,
640 component_class_restrict, log_level, auto_disc);
73760435
SM
641
642 g_string_truncate(input, saved_input_len);
643
644 if (status < 0) {
645 /* Fatal error. */
646 goto error;
647 } else if (status == 0) {
648 dir_status = 0;
649 }
650 } else if (errno != 0) {
651 BT_LOGW_ERRNO("Failed to read directory entry", ": dir=%s", input->str);
652 goto error;
653 }
5084732e 654 } while (dirent);
73760435
SM
655
656 status = dir_status;
657
658 g_dir_close(dir);
659 } else {
660 BT_LOGD("Skipping %s, not a file or directory", input->str);
661 status = 1;
662 }
663
664 goto end;
665
666error:
667 status = -1;
668
669end:
670
671 if (error) {
672 g_error_free(error);
673 }
674
675 return status;
676}
677
678/*
679 * Look for a source component class that recognizes `input` as a directory or
680 * file. If `input` is a directory and is not directly recognized, recurse and
681 * apply the same logic to children nodes.
682 *
683 * Same return value semantic as `support_info_query_all_sources`.
684 */
685
686static
687int auto_discover_source_for_input_as_dir_or_file(const char *input,
1ead9076 688 uint64_t original_input_index,
97010665
SM
689 const bt_plugin **plugins,
690 size_t plugin_count,
73760435
SM
691 const char *component_class_restrict,
692 enum bt_logging_level log_level,
693 struct auto_source_discovery *auto_disc)
694{
695 GString *mutable_input;
696 int status;
697
698 mutable_input = g_string_new(input);
699 if (!mutable_input) {
700 status = -1;
701 goto end;
702 }
703
704 status = auto_discover_source_for_input_as_dir_or_file_rec(
97010665 705 mutable_input, original_input_index, plugins, plugin_count,
73760435
SM
706 component_class_restrict, log_level, auto_disc);
707
708 g_string_free(mutable_input, TRUE);
709end:
710 return status;
711}
712
713int auto_discover_source_components(
73760435 714 const bt_value *inputs,
97010665
SM
715 const bt_plugin **plugins,
716 size_t plugin_count,
73760435
SM
717 const char *component_class_restrict,
718 enum bt_logging_level log_level,
719 struct auto_source_discovery *auto_disc)
720{
721 uint64_t i_inputs, input_count;
722 int status;
73760435 723
393729a6 724 input_count = bt_value_array_get_length(inputs);
73760435 725
73760435
SM
726 for (i_inputs = 0; i_inputs < input_count; i_inputs++) {
727 const bt_value *input_value;
728 const char *input;
729
730 input_value = bt_value_array_borrow_element_by_index_const(inputs, i_inputs);
731 input = bt_value_string_get(input_value);
1ead9076 732 status = auto_discover_source_for_input_as_string(input, i_inputs,
97010665 733 plugins, plugin_count, component_class_restrict,
73760435
SM
734 log_level, auto_disc);
735 if (status < 0) {
736 /* Fatal error. */
737 goto end;
738 } else if (status == 0) {
739 /* A component class has claimed this input as an arbitrary string. */
740 continue;
741 }
742
743 status = auto_discover_source_for_input_as_dir_or_file(input,
97010665 744 i_inputs, plugins, plugin_count,
1ead9076 745 component_class_restrict, log_level, auto_disc);
73760435
SM
746 if (status < 0) {
747 /* Fatal error. */
748 goto end;
749 } else if (status == 0) {
750 /*
751 * This input (or something under it) was recognized.
752 */
753 continue;
754 }
755
756 BT_LOGW("No trace was found based on input `%s`.", input);
757 }
758
759 status = 0;
760end:
73760435
SM
761 return status;
762}
This page took 0.055977 seconds and 4 git commands to generate.