src.ctf.lttng-live: remove some goto error-handling
[babeltrace.git] / src / autodisc / autodisc.c
index 02bdacc5542e4e26fefc3d2c18402bdfaa6fd153..d171a33dba2edf790e3a443e630608a2add6c951 100644 (file)
@@ -1,42 +1,40 @@
 /*
- * Copyright (c) 2019 EfficiOS Inc. and Linux Foundation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
+ * SPDX-License-Identifier: MIT
  *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * Copyright (c) 2019 EfficiOS Inc. and Linux Foundation
  */
 
 #define BT_LOG_TAG "CLI-CFG-SRC-AUTO-DISC"
-#define BT_LOG_OUTPUT_LEVEL log_level
+#define BT_LOG_OUTPUT_LEVEL ((enum bt_log_level) log_level)
 #include "logging/log.h"
 
+#include <stdbool.h>
+
 #include "autodisc.h"
 #include "common/common.h"
 
 #define BT_AUTODISC_LOG_AND_APPEND(_lvl, _fmt, ...)                            \
-       do {                                                            \
-               BT_LOG_WRITE(_lvl, BT_LOG_TAG, _fmt, ##__VA_ARGS__);    \
-               (void) BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN( \
+       do {                                                                    \
+               BT_LOG_WRITE_PRINTF(_lvl, BT_LOG_TAG, _fmt, ##__VA_ARGS__);     \
+               (void) BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(       \
                        "Source auto-discovery", _fmt, ##__VA_ARGS__);          \
        } while (0)
 
 #define BT_AUTODISC_LOGE_APPEND_CAUSE(_fmt, ...)                               \
        BT_AUTODISC_LOG_AND_APPEND(BT_LOG_ERROR, _fmt, ##__VA_ARGS__)
 
+/*
+ * Define a status enum for inside the auto source discovery code,
+ * as we don't want to return `NO_MATCH` to the caller.
+ */
+typedef enum auto_source_discovery_internal_status {
+       AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_OK                = AUTO_SOURCE_DISCOVERY_STATUS_OK,
+       AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_ERROR             = AUTO_SOURCE_DISCOVERY_STATUS_ERROR,
+       AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_MEMORY_ERROR      = AUTO_SOURCE_DISCOVERY_STATUS_MEMORY_ERROR,
+       AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_INTERRUPTED       = AUTO_SOURCE_DISCOVERY_STATUS_INTERRUPTED,
+       AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_NO_MATCH          = __BT_FUNC_STATUS_NO_MATCH,
+} auto_source_discovery_internal_status;
+
 /* Finalize and free a `struct auto_source_discovery_result`. */
 
 static
@@ -143,7 +141,8 @@ const bt_value *borrow_array_value_last_element_const(const bt_value *array)
  */
 
 static
-int auto_source_discovery_add(struct auto_source_discovery *auto_disc,
+auto_source_discovery_internal_status auto_source_discovery_add(
+               struct auto_source_discovery *auto_disc,
                const char *plugin_name,
                const char *source_cc_name,
                const char *group,
@@ -151,7 +150,7 @@ int auto_source_discovery_add(struct auto_source_discovery *auto_disc,
                uint64_t original_input_index,
                bt_logging_level log_level)
 {
-       int status;
+       auto_source_discovery_internal_status status;
        bt_value_array_append_element_status append_status;
        guint len;
        guint i;
@@ -228,11 +227,11 @@ int auto_source_discovery_add(struct auto_source_discovery *auto_disc,
                }
        }
 
-       status = 0;
+       status = AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_OK;
        goto end;
 
 error:
-       status = -1;
+       status = AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_ERROR;
 
 end:
        return status;
@@ -326,35 +325,36 @@ end:
  *
  * If `component_class_restrict` is non-NULL, only query source component classes
  * with that name.
- *
- * Return:
- *
- * - > 0 on success, if no source component class has reported that it handles `input`
- * -   0 on success, if a source component class has reported that it handles `input`
- * - < 0 on failure (e.g. memory error)
  */
 static
-int support_info_query_all_sources(const char *input,
+auto_source_discovery_internal_status support_info_query_all_sources(
+               const char *input,
                const char *input_type,
                uint64_t original_input_index,
                const bt_plugin **plugins,
                size_t plugin_count,
                const char *component_class_restrict,
                enum bt_logging_level log_level,
-               struct auto_source_discovery *auto_disc)
+               struct auto_source_discovery *auto_disc,
+               const bt_interrupter *interrupter)
 {
        bt_value_map_insert_entry_status insert_status;
        bt_value *query_params = NULL;
-       int status;
+       auto_source_discovery_internal_status status;
        size_t i_plugins;
        const struct bt_value *query_result = NULL;
        struct {
                const bt_component_class_source *source;
                const bt_plugin *plugin;
                const bt_value *group;
-               double weigth;
+               double weight;
        } winner = { NULL, NULL, NULL, 0 };
 
+       if (interrupter && bt_interrupter_is_set(interrupter)) {
+               status = AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_INTERRUPTED;
+               goto end;
+       }
+
        query_params = bt_value_map_create();
        if (!query_params) {
                BT_AUTODISC_LOGE_APPEND_CAUSE("Failed to allocate a map value.");
@@ -444,17 +444,10 @@ int support_info_query_all_sources(const char *input,
                                        }
 
                                        if (bt_value_map_has_entry(query_result, "group")) {
-                                               enum bt_value_type group_value_type;
-
                                                group_value = bt_value_map_borrow_entry_value_const(query_result, "group");
                                                BT_ASSERT(group_value);
 
-                                               group_value_type = bt_value_get_type(group_value);
-
-                                               if (group_value_type == BT_VALUE_TYPE_NULL) {
-                                                       /* Do as if no value was passed. */
-                                                       group_value = NULL;
-                                               } else if (bt_value_get_type(group_value) != BT_VALUE_TYPE_STRING) {
+                                               if (bt_value_get_type(group_value) != BT_VALUE_TYPE_STRING) {
                                                        BT_LOGW("babeltrace.support-info query: unexpected type for entry `group`: "
                                                                "component-class-name=source.%s.%s, input=%s, input-type=%s, "
                                                                "expected-entry-type=%s,%s, actual-entry-type=%s",
@@ -482,11 +475,11 @@ int support_info_query_all_sources(const char *input,
                                }
 
                                BT_LOGD("babeltrace.support-info query: success: component-class-name=source.%s.%s, input=%s, "
-                                       "type=%s, weight=%f\n",
+                                       "type=%s, weight=%f, group=%s\n",
                                        bt_plugin_get_name(plugin), bt_component_class_get_name(cc), input,
-                                       input_type, weight);
+                                       input_type, weight, group_value ? bt_value_string_get(group_value) : "(none)");
 
-                               if (weight > winner.weigth) {
+                               if (weight > winner.weight) {
                                        winner.source = source_cc;
                                        winner.plugin = plugin;
 
@@ -494,7 +487,7 @@ int support_info_query_all_sources(const char *input,
                                        winner.group = group_value;
                                        bt_value_get_ref(winner.group);
 
-                                       winner.weigth = weight;
+                                       winner.weight = weight;
                                }
                        } else if (query_status == BT_QUERY_EXECUTOR_QUERY_STATUS_ERROR) {
                                BT_AUTODISC_LOGE_APPEND_CAUSE("babeltrace.support-info query failed.");
@@ -522,24 +515,24 @@ int support_info_query_all_sources(const char *input,
                plugin_name = bt_plugin_get_name(winner.plugin);
                group = winner.group ? bt_value_string_get(winner.group) : NULL;
 
-               BT_LOGI("Input %s is awarded to component class source.%s.%s with weight %f",
-                       input, plugin_name, source_name, winner.weigth);
+               BT_LOGI("Input awarded: input=%s, type=%s, component-class-name=source.%s.%s, weight=%f, group=%s",
+                       input, input_type, plugin_name, source_name, winner.weight, group ? group : "(none)");
 
                status = auto_source_discovery_add(auto_disc, plugin_name,
                        source_name, group, input, original_input_index, log_level);
-               if (status != 0) {
+               if (status != AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_OK) {
                        goto error;
                }
        } else {
-               BT_LOGI("Input %s (%s) was not recognized by any source component class.",
+               BT_LOGI("Input not recognized: input=%s, type=%s",
                        input, input_type);
-               status = 1;
+               status = AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_NO_MATCH;
        }
 
        goto end;
 
 error:
-       status = -1;
+       status = AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_ERROR;
 
 end:
        bt_value_put_ref(query_result);
@@ -557,73 +550,81 @@ end:
  */
 
 static
-int auto_discover_source_for_input_as_string(const char *input,
+auto_source_discovery_internal_status auto_discover_source_for_input_as_string(
+               const char *input,
                uint64_t original_input_index,
                const bt_plugin **plugins,
                size_t plugin_count,
                const char *component_class_restrict,
                enum bt_logging_level log_level,
-               struct auto_source_discovery *auto_disc)
+               struct auto_source_discovery *auto_disc,
+               const bt_interrupter *interrupter)
 {
        return support_info_query_all_sources(input, "string",
                original_input_index, plugins, plugin_count,
-               component_class_restrict, log_level, auto_disc);
+               component_class_restrict, log_level, auto_disc,
+               interrupter);
 }
 
 static
-int auto_discover_source_for_input_as_dir_or_file_rec(GString *input,
+auto_source_discovery_internal_status auto_discover_source_for_input_as_dir_or_file_rec(
+               GString *input,
                uint64_t original_input_index,
                const bt_plugin **plugins,
                size_t plugin_count,
                const char *component_class_restrict,
                enum bt_logging_level log_level,
-               struct auto_source_discovery *auto_disc)
+               struct auto_source_discovery *auto_disc,
+               const bt_interrupter *interrupter)
 {
-       int status;
+       auto_source_discovery_internal_status status;
        GError *error = NULL;
+       GDir *dir = NULL;
 
        if (g_file_test(input->str, G_FILE_TEST_IS_REGULAR)) {
                /* It's a file. */
                status = support_info_query_all_sources(input->str,
                        "file", original_input_index, plugins, plugin_count,
-                       component_class_restrict, log_level, auto_disc);
+                       component_class_restrict, log_level, auto_disc,
+                       interrupter);
        } else if (g_file_test(input->str, G_FILE_TEST_IS_DIR)) {
-               GDir *dir;
                const gchar *dirent;
                gsize saved_input_len;
-               int dir_status = 1;
+               int dir_status = AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_NO_MATCH;
 
                /* It's a directory. */
                status = support_info_query_all_sources(input->str,
                        "directory", original_input_index, plugins,
                        plugin_count, component_class_restrict, log_level,
-                       auto_disc);
+                       auto_disc, interrupter);
 
                if (status < 0) {
                        /* Fatal error. */
                        goto error;
-               } else if (status == 0) {
+               } else if (status == AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_OK ||
+                               status == AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_INTERRUPTED) {
                        /*
                         * A component class claimed this input as a directory,
-                        * don't recurse.
+                        * don't recurse.  Or, we got interrupted.
                         */
                        goto end;
                }
 
                dir = g_dir_open(input->str, 0, &error);
                if (!dir) {
-                       const char *fmt = "Failed to open directory %s: %s";
-                       BT_LOGW(fmt, input->str, error->message);
+#define BT_FMT "Failed to open directory %s: %s"
+                       BT_LOGW(BT_FMT, input->str, error->message);
 
                        if (error->code == G_FILE_ERROR_ACCES) {
                                /* This is not a fatal error, we just skip it. */
-                               status = 1;
+                               status = AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_NO_MATCH;
                                goto end;
                        } else {
-                               BT_AUTODISC_LOGE_APPEND_CAUSE(fmt, input->str,
+                               BT_AUTODISC_LOGE_APPEND_CAUSE(BT_FMT, input->str,
                                        error->message);
                                goto error;
                        }
+#undef BT_FMT
                }
 
                saved_input_len = input->len;
@@ -637,15 +638,18 @@ int auto_discover_source_for_input_as_dir_or_file_rec(GString *input,
 
                                status = auto_discover_source_for_input_as_dir_or_file_rec(
                                        input, original_input_index, plugins, plugin_count,
-                                       component_class_restrict, log_level, auto_disc);
+                                       component_class_restrict, log_level, auto_disc,
+                                       interrupter);
 
                                g_string_truncate(input, saved_input_len);
 
                                if (status < 0) {
                                        /* Fatal error. */
                                        goto error;
-                               } else if (status == 0) {
-                                       dir_status = 0;
+                               } else if (status == AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_INTERRUPTED) {
+                                       goto end;
+                               } else if (status == AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_OK) {
+                                       dir_status = AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_OK;
                                }
                        } else if (errno != 0) {
                                BT_LOGW_ERRNO("Failed to read directory entry", ": dir=%s", input->str);
@@ -654,19 +658,20 @@ int auto_discover_source_for_input_as_dir_or_file_rec(GString *input,
                } while (dirent);
 
                status = dir_status;
-
-               g_dir_close(dir);
        } else {
                BT_LOGD("Skipping %s, not a file or directory", input->str);
-               status = 1;
+               status = AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_NO_MATCH;
        }
 
        goto end;
 
 error:
-       status = -1;
+       status = AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_ERROR;
 
 end:
+       if (dir) {
+               g_dir_close(dir);
+       }
 
        if (error) {
                g_error_free(error);
@@ -684,42 +689,47 @@ end:
  */
 
 static
-int auto_discover_source_for_input_as_dir_or_file(const char *input,
+auto_source_discovery_internal_status auto_discover_source_for_input_as_dir_or_file(
+               const char *input,
                uint64_t original_input_index,
                const bt_plugin **plugins,
                size_t plugin_count,
                const char *component_class_restrict,
                enum bt_logging_level log_level,
-               struct auto_source_discovery *auto_disc)
+               struct auto_source_discovery *auto_disc,
+               const bt_interrupter *interrupter)
 {
        GString *mutable_input;
-       int status;
+       auto_source_discovery_internal_status status;
 
        mutable_input = g_string_new(input);
        if (!mutable_input) {
-               status = -1;
+               status = AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_ERROR;
                goto end;
        }
 
        status = auto_discover_source_for_input_as_dir_or_file_rec(
                mutable_input, original_input_index, plugins, plugin_count,
-               component_class_restrict, log_level, auto_disc);
+               component_class_restrict, log_level, auto_disc,
+               interrupter);
 
        g_string_free(mutable_input, TRUE);
 end:
        return status;
 }
 
-int auto_discover_source_components(
+auto_source_discovery_status auto_discover_source_components(
                const bt_value *inputs,
                const bt_plugin **plugins,
                size_t plugin_count,
                const char *component_class_restrict,
                enum bt_logging_level log_level,
-               struct auto_source_discovery *auto_disc)
+               struct auto_source_discovery *auto_disc,
+               const bt_interrupter *interrupter)
 {
        uint64_t i_inputs, input_count;
-       int status;
+       auto_source_discovery_internal_status internal_status;
+       auto_source_discovery_status status;
 
        input_count = bt_value_array_get_length(inputs);
 
@@ -729,24 +739,26 @@ int auto_discover_source_components(
 
                input_value = bt_value_array_borrow_element_by_index_const(inputs, i_inputs);
                input = bt_value_string_get(input_value);
-               status = auto_discover_source_for_input_as_string(input, i_inputs,
+               internal_status = auto_discover_source_for_input_as_string(input, i_inputs,
                        plugins, plugin_count, component_class_restrict,
-                       log_level, auto_disc);
-               if (status < 0) {
-                       /* Fatal error. */
+                       log_level, auto_disc, interrupter);
+               if (internal_status < 0 || internal_status == AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_INTERRUPTED) {
+                       /* Fatal error or we got interrupted. */
+                       status = (auto_source_discovery_status) internal_status;
                        goto end;
-               } else if (status == 0) {
+               } else if (internal_status == AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_OK) {
                        /* A component class has claimed this input as an arbitrary string. */
                        continue;
                }
 
-               status = auto_discover_source_for_input_as_dir_or_file(input,
+               internal_status = auto_discover_source_for_input_as_dir_or_file(input,
                        i_inputs, plugins, plugin_count,
-                       component_class_restrict, log_level, auto_disc);
-               if (status < 0) {
-                       /* Fatal error. */
+                       component_class_restrict, log_level, auto_disc, interrupter);
+               if (internal_status < 0 || internal_status == AUTO_SOURCE_DISCOVERY_INTERNAL_STATUS_INTERRUPTED) {
+                       /* Fatal error or we got interrupted. */
+                       status = (auto_source_discovery_status) internal_status;
                        goto end;
-               } else if (status == 0) {
+               } else if (internal_status == 0) {
                        /*
                         * This input (or something under it) was recognized.
                         */
@@ -756,7 +768,7 @@ int auto_discover_source_components(
                BT_LOGW("No trace was found based on input `%s`.", input);
        }
 
-       status = 0;
+       status = AUTO_SOURCE_DISCOVERY_STATUS_OK;
 end:
        return status;
 }
This page took 0.029541 seconds and 4 git commands to generate.