X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Fcli%2Fbabeltrace2-cfg-cli-args.c;h=e962ff361dfe48370f07ab5d33a0b09750300d02;hb=2459461134ddc04f5eca4251d780c4249d3f4020;hp=617bd51a27d4bbff27aec165bb7f1771a92f75c4;hpb=916d0d910ad5407bc7826505aa05b277f5739a34;p=babeltrace.git diff --git a/src/cli/babeltrace2-cfg-cli-args.c b/src/cli/babeltrace2-cfg-cli-args.c index 617bd51a..e962ff36 100644 --- a/src/cli/babeltrace2-cfg-cli-args.c +++ b/src/cli/babeltrace2-cfg-cli-args.c @@ -881,7 +881,6 @@ enum { OPT_INPUT_FORMAT, OPT_LIST, OPT_LOG_LEVEL, - OPT_NAME, OPT_NAMES, OPT_NO_DELTA, OPT_OMIT_HOME_PLUGIN_PATH, @@ -889,7 +888,6 @@ enum { OPT_OUTPUT, OPT_OUTPUT_FORMAT, OPT_PARAMS, - OPT_PATH, OPT_PLUGIN_PATH, OPT_RESET_BASE_PARAMS, OPT_RETRY_DURATION, @@ -897,7 +895,6 @@ enum { OPT_RUN_ARGS_0, OPT_STREAM_INTERSECTION, OPT_TIMERANGE, - OPT_URL, OPT_VERBOSE, OPT_VERSION, }; @@ -1416,7 +1413,7 @@ struct bt_config *bt_config_help_from_args(int argc, const char *argv[], { int ret, i; struct bt_config *cfg = NULL; - const char *leftover = NULL; + const char *non_opt = NULL; char *plugin_name = NULL, *comp_cls_name = NULL; struct bt_argpar_parse_ret argpar_parse_ret; @@ -1481,18 +1478,18 @@ struct bt_config *bt_config_help_from_args(int argc, const char *argv[], struct bt_argpar_item_non_opt *argpar_item_non_opt = (struct bt_argpar_item_non_opt *) argpar_item; - if (leftover) { + if (non_opt) { BT_CLI_LOGE_APPEND_CAUSE("Extraneous command-line argument specified to `help` command: `%s`.", argpar_item_non_opt->arg); goto error; } - leftover = argpar_item_non_opt->arg; + non_opt = argpar_item_non_opt->arg; } } - if (leftover) { - plugin_comp_cls_names(leftover, NULL, + if (non_opt) { + plugin_comp_cls_names(non_opt, NULL, &plugin_name, &comp_cls_name, &cfg->cmd_data.help.cfg_component->type); if (plugin_name && comp_cls_name) { @@ -1507,7 +1504,7 @@ struct bt_config *bt_config_help_from_args(int argc, const char *argv[], /* Fall back to plugin help */ g_string_assign( cfg->cmd_data.help.cfg_component->plugin_name, - leftover); + non_opt); } } else { print_help_usage(stdout); @@ -1670,8 +1667,9 @@ struct bt_config *bt_config_query_from_args(int argc, const char *argv[], = (struct bt_argpar_item_non_opt *) argpar_item; /* - * We need exactly two leftover arguments which are the - * mandatory component class specification and query object. + * We need exactly two non-option arguments + * which are the mandatory component class + * specification and query object. */ if (!component_class_spec) { component_class_spec = argpar_item_non_opt->arg; @@ -1877,19 +1875,15 @@ void print_run_usage(FILE *fp) fprintf(fp, " for all the following components until\n"); fprintf(fp, " --reset-base-params is encountered\n"); fprintf(fp, " (see the expected format of PARAMS below)\n"); - fprintf(fp, " -c, --component=[NAME:]TYPE.PLUGIN.CLS\n"); + fprintf(fp, " -c, --component=NAME:TYPE.PLUGIN.CLS\n"); fprintf(fp, " Instantiate the component class CLS of type\n"); fprintf(fp, " TYPE (`source`, `filter`, or `sink`) found\n"); fprintf(fp, " in the plugin PLUGIN, add it to the graph,\n"); - fprintf(fp, " and optionally name it NAME (you can also\n"); - fprintf(fp, " specify the name with --name)\n"); + fprintf(fp, " and name it NAME"); fprintf(fp, " -x, --connect=CONNECTION Connect two created components (see the\n"); fprintf(fp, " expected format of CONNECTION below)\n"); fprintf(fp, " -l, --log-level=LVL Set the log level of the current component to LVL\n"); fprintf(fp, " (`N`, `V`, `D`, `I`, `W`, `E`, or `F`)\n"); - fprintf(fp, " -n, --name=NAME Set the name of the current component\n"); - fprintf(fp, " to NAME (must be unique amongst all the\n"); - fprintf(fp, " names of the created components)\n"); fprintf(fp, " --omit-home-plugin-path Omit home plugins from plugin search path\n"); fprintf(fp, " (~/.local/lib/babeltrace2/plugins)\n"); fprintf(fp, " --omit-system-plugin-path Omit system plugins from plugin search path\n"); @@ -1914,8 +1908,8 @@ void print_run_usage(FILE *fp) fprintf(fp, "\n"); fprintf(fp, "UPSTREAM and DOWNSTREAM are names of the upstream and downstream\n"); fprintf(fp, "components to connect together. You must escape the following characters\n\n"); - fprintf(fp, "with `\\`: `\\`, `.`, and `:`. You can set the name of the current\n"); - fprintf(fp, "component with the --name option.\n"); + fprintf(fp, "with `\\`: `\\`, `.`, and `:`. You must set the name of the current\n"); + fprintf(fp, "component using the NAME prefix of the --component option.\n"); fprintf(fp, "\n"); fprintf(fp, "UPSTREAM-PORT and DOWNSTREAM-PORT are optional globbing patterns to\n"); fprintf(fp, "identify the upstream and downstream ports to use for the connection.\n"); @@ -1957,8 +1951,6 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], const bt_value *initial_plugin_paths, int default_log_level) { struct bt_config_component *cur_cfg_comp = NULL; - enum bt_config_component_dest cur_cfg_comp_dest = - BT_CONFIG_COMPONENT_DEST_UNKNOWN; bt_value *cur_base_params = NULL; int ret = 0; struct bt_config *cfg = NULL; @@ -1977,7 +1969,6 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], { OPT_CONNECT, 'x', "connect", true }, { OPT_HELP, 'h', "help", false }, { OPT_LOG_LEVEL, 'l', "log-level", true }, - { OPT_NAME, 'n', "name", true }, { OPT_OMIT_HOME_PLUGIN_PATH, '\0', "omit-home-plugin-path", false }, { OPT_OMIT_SYSTEM_PLUGIN_PATH, '\0', "omit-system-plugin-path", false }, { OPT_PARAMS, 'p', "params", true }, @@ -2054,7 +2045,7 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], struct bt_argpar_item_opt *argpar_item_opt; const char *arg; - /* This command does not accept leftover arguments. */ + /* This command does not accept non-option arguments.*/ if (argpar_item->type == BT_ARGPAR_ITEM_TYPE_NON_OPT) { struct bt_argpar_item_non_opt *argpar_nonopt_item = (struct bt_argpar_item_non_opt *) argpar_item; @@ -2082,18 +2073,9 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], break; case OPT_COMPONENT: { - enum bt_config_component_dest new_dest; - - if (cur_cfg_comp) { - ret = add_run_cfg_comp_check_name(cfg, - cur_cfg_comp, cur_cfg_comp_dest, - instance_names); - BT_OBJECT_PUT_REF_AND_RESET(cur_cfg_comp); - if (ret) { - goto error; - } - } + enum bt_config_component_dest dest; + BT_OBJECT_PUT_REF_AND_RESET(cur_cfg_comp); cur_cfg_comp = bt_config_component_from_arg(arg, default_log_level); if (!cur_cfg_comp) { @@ -2104,13 +2086,13 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], switch (cur_cfg_comp->type) { case BT_COMPONENT_CLASS_TYPE_SOURCE: - new_dest = BT_CONFIG_COMPONENT_DEST_SOURCE; + dest = BT_CONFIG_COMPONENT_DEST_SOURCE; break; case BT_COMPONENT_CLASS_TYPE_FILTER: - new_dest = BT_CONFIG_COMPONENT_DEST_FILTER; + dest = BT_CONFIG_COMPONENT_DEST_FILTER; break; case BT_COMPONENT_CLASS_TYPE_SINK: - new_dest = BT_CONFIG_COMPONENT_DEST_SINK; + dest = BT_CONFIG_COMPONENT_DEST_SINK; break; default: abort(); @@ -2124,7 +2106,13 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], goto error; } - cur_cfg_comp_dest = new_dest; + ret = add_run_cfg_comp_check_name(cfg, + cur_cfg_comp, dest, + instance_names); + if (ret) { + goto error; + } + break; } case OPT_PARAMS: @@ -2157,15 +2145,6 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], BT_OBJECT_MOVE_REF(cur_cfg_comp->params, params_to_set); break; } - case OPT_NAME: - if (!cur_cfg_comp) { - BT_CLI_LOGE_APPEND_CAUSE("Cannot set the name of unavailable component:\n %s", - arg); - goto error; - } - - g_string_assign(cur_cfg_comp->instance_name, arg); - break; case OPT_LOG_LEVEL: if (!cur_cfg_comp) { BT_CLI_LOGE_APPEND_CAUSE("Cannot set the log level of unavailable component:\n %s", @@ -2239,15 +2218,7 @@ struct bt_config *bt_config_run_from_args(int argc, const char *argv[], } } - /* Add current component */ - if (cur_cfg_comp) { - ret = add_run_cfg_comp_check_name(cfg, cur_cfg_comp, - cur_cfg_comp_dest, instance_names); - BT_OBJECT_PUT_REF_AND_RESET(cur_cfg_comp); - if (ret) { - goto error; - } - } + BT_OBJECT_PUT_REF_AND_RESET(cur_cfg_comp); if (cfg->cmd_data.run.sources->len == 0) { BT_CLI_LOGE_APPEND_CAUSE("Incomplete graph: no source component."); @@ -2348,21 +2319,15 @@ void print_convert_usage(FILE *fp) fprintf(fp, " TYPE (`source`, `filter`, or `sink`) found\n"); fprintf(fp, " in the plugin PLUGIN, add it to the\n"); fprintf(fp, " conversion graph, and optionally name it\n"); - fprintf(fp, " NAME (you can also specify the name with\n"); - fprintf(fp, " --name)\n"); + fprintf(fp, " NAME\n"); fprintf(fp, " -l, --log-level=LVL Set the log level of the current component to LVL\n"); fprintf(fp, " (`N`, `V`, `D`, `I`, `W`, `E`, or `F`)\n"); - fprintf(fp, " --name=NAME Set the name of the current component\n"); - fprintf(fp, " to NAME (must be unique amongst all the\n"); - fprintf(fp, " names of the created components)\n"); fprintf(fp, " --omit-home-plugin-path Omit home plugins from plugin search path\n"); fprintf(fp, " (~/.local/lib/babeltrace2/plugins)\n"); fprintf(fp, " --omit-system-plugin-path Omit system plugins from plugin search path\n"); fprintf(fp, " -p, --params=PARAMS Add initialization parameters PARAMS to the\n"); fprintf(fp, " current component (see the expected format\n"); fprintf(fp, " of PARAMS below)\n"); - fprintf(fp, " -P, --path=PATH Set the `path` string parameter of the\n"); - fprintf(fp, " current component to PATH\n"); fprintf(fp, " --plugin-path=PATH[:PATH]... Add PATH to the list of paths from which\n"); fprintf(fp, " dynamic plugins can be loaded\n"); fprintf(fp, " --retry-duration=DUR When babeltrace2(1) needs to retry to run\n"); @@ -2377,8 +2342,6 @@ void print_convert_usage(FILE *fp) fprintf(fp, " formatted for `xargs -0`, and quit\n"); fprintf(fp, " --stream-intersection Only process events when all streams\n"); fprintf(fp, " are active\n"); - fprintf(fp, " -u, --url=URL Set the `url` string parameter of the\n"); - fprintf(fp, " current component to URL\n"); fprintf(fp, " -h, --help Show this help and quit\n"); fprintf(fp, "\n"); fprintf(fp, "Implicit `source.ctf.fs` component options:\n"); @@ -2494,7 +2457,6 @@ const struct bt_argpar_opt_descr convert_options[] = { { OPT_HELP, 'h', "help", false }, { OPT_INPUT_FORMAT, 'i', "input-format", true }, { OPT_LOG_LEVEL, 'l', "log-level", true }, - { OPT_NAME, '\0', "name", true }, { OPT_NAMES, 'n', "names", true }, { OPT_DEBUG_INFO, '\0', "debug-info", false }, { OPT_NO_DELTA, '\0', "no-delta", false }, @@ -2503,14 +2465,12 @@ const struct bt_argpar_opt_descr convert_options[] = { { OPT_OUTPUT, 'w', "output", true }, { OPT_OUTPUT_FORMAT, 'o', "output-format", true }, { OPT_PARAMS, 'p', "params", true }, - { OPT_PATH, 'P', "path", true }, { OPT_PLUGIN_PATH, '\0', "plugin-path", true }, { OPT_RETRY_DURATION, '\0', "retry-duration", true }, { OPT_RUN_ARGS, '\0', "run-args", false }, { OPT_RUN_ARGS_0, '\0', "run-args-0", false }, { OPT_STREAM_INTERSECTION, '\0', "stream-intersection", false }, { OPT_TIMERANGE, '\0', "timerange", true }, - { OPT_URL, 'u', "url", true }, { OPT_VERBOSE, 'v', "verbose", false }, BT_ARGPAR_OPT_DESCR_SENTINEL }; @@ -2603,27 +2563,31 @@ int append_run_args_for_implicit_component( { int ret = 0; size_t i; + GString *component_arg_for_run = NULL; if (!impl_args->exists) { goto end; } - if (bt_value_array_append_string_element(run_args, "--component")) { + component_arg_for_run = g_string_new(NULL); + if (!component_arg_for_run) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } - if (bt_value_array_append_string_element(run_args, impl_args->comp_arg->str)) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + /* Build the full `name:type.plugin.cls`. */ + BT_ASSERT(!strchr(impl_args->name_arg->str, '\\')); + BT_ASSERT(!strchr(impl_args->name_arg->str, ':')); + g_string_printf(component_arg_for_run, "%s:%s", + impl_args->name_arg->str, impl_args->comp_arg->str); - if (bt_value_array_append_string_element(run_args, "--name")) { + if (bt_value_array_append_string_element(run_args, "--component")) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } - if (bt_value_array_append_string_element(run_args, impl_args->name_arg->str)) { + if (bt_value_array_append_string_element(run_args, + component_arg_for_run->str)) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } @@ -2667,6 +2631,10 @@ error: ret = -1; end: + if (component_arg_for_run) { + g_string_free(component_arg_for_run, TRUE); + } + return ret; } @@ -2991,103 +2959,6 @@ int append_implicit_component_extra_param(struct implicit_component_args *args, return append_string_parameter_to_args(args->extra_params, key, value); } -static -int convert_append_name_param(enum bt_config_component_dest dest, - GString *cur_name, GString *cur_name_prefix, - bt_value *run_args, - bt_value *all_names, - GList **source_names, GList **filter_names, - GList **sink_names) -{ - int ret = 0; - - if (cur_name_prefix->len > 0) { - /* We're after a --component option */ - GString *name = NULL; - bool append_name_opt = false; - - if (cur_name->len == 0) { - /* - * No explicit name was provided for the user - * component. - */ - name = get_component_auto_name(cur_name_prefix->str, - all_names); - append_name_opt = true; - } else { - /* - * An explicit name was provided for the user - * component. - */ - if (bt_value_map_has_entry(all_names, - cur_name->str)) { - BT_CLI_LOGE_APPEND_CAUSE("Duplicate component instance name:\n %s", - cur_name->str); - goto error; - } - - name = g_string_new(cur_name->str); - } - - if (!name) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } - - /* - * Remember this name globally, for the uniqueness of - * all component names. - */ - if (bt_value_map_insert_entry(all_names, name->str, bt_value_null)) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } - - /* - * Append the --name option if necessary. - */ - if (append_name_opt) { - if (bt_value_array_append_string_element(run_args, "--name")) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } - - if (bt_value_array_append_string_element(run_args, name->str)) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } - } - - /* - * Remember this name specifically for the type of the - * component. This is to create connection arguments. - */ - switch (dest) { - case BT_CONFIG_COMPONENT_DEST_SOURCE: - *source_names = g_list_append(*source_names, name); - break; - case BT_CONFIG_COMPONENT_DEST_FILTER: - *filter_names = g_list_append(*filter_names, name); - break; - case BT_CONFIG_COMPONENT_DEST_SINK: - *sink_names = g_list_append(*sink_names, name); - break; - default: - abort(); - } - - g_string_assign(cur_name_prefix, ""); - } - - goto end; - -error: - ret = -1; - -end: - return ret; -} - /* * Escapes `.`, `:`, and `\` of `input` with `\`. */ @@ -3305,13 +3176,27 @@ end: } /* - * Create `struct implicit_component_args` structures for each of the source - * components we identified. Add them to `component_args`. + * Create `struct implicit_component_args` structures for each of the + * source components we identified. Add them to `component_args`. + * + * `non_opt_params` is an array where each element is an array of + * strings containing all the arguments to `--params` that apply to the + * non-option argument at the same index. For example, if, for a + * non-option argument, the following `--params` options applied: + * + * --params=a=2 --params=b=3,c=4 + * + * its entry in `non_opt_params` would contain + * + * ["a=2", "b=3,c=4"] */ static -void create_implicit_component_args_from_auto_discovered_sources( - const struct auto_source_discovery *auto_disc, GPtrArray *component_args) +int create_implicit_component_args_from_auto_discovered_sources( + const struct auto_source_discovery *auto_disc, + const bt_value *non_opt_params, + const bt_value *non_opt_loglevels, + GPtrArray *component_args) { gchar *cc_name = NULL; struct implicit_component_args *comp = NULL; @@ -3323,36 +3208,123 @@ void create_implicit_component_args_from_auto_discovered_sources( for (i = 0; i < len; i++) { struct auto_source_discovery_result *res = g_ptr_array_index(auto_disc->results, i); + uint64_t orig_indices_i, orig_indices_count; g_free(cc_name); cc_name = g_strdup_printf("source.%s.%s", res->plugin_name, res->source_cc_name); if (!cc_name) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto end; + goto error; } comp = create_implicit_component_args(cc_name); if (!comp) { - goto end; + goto error; + } + + /* + * Append parameters and log levels of all the + * non-option arguments that contributed to this + * component instance coming into existence. + */ + orig_indices_count = bt_value_array_get_size(res->original_input_indices); + for (orig_indices_i = 0; orig_indices_i < orig_indices_count; orig_indices_i++) { + const bt_value *orig_idx_value = + bt_value_array_borrow_element_by_index( + res->original_input_indices, orig_indices_i); + uint64_t orig_idx = bt_value_integer_unsigned_get(orig_idx_value); + const bt_value *params_array = + bt_value_array_borrow_element_by_index_const( + non_opt_params, orig_idx); + uint64_t params_i, params_count; + const bt_value *loglevel_value; + + params_count = bt_value_array_get_size(params_array); + for (params_i = 0; params_i < params_count; params_i++) { + const bt_value *params_value = + bt_value_array_borrow_element_by_index_const( + params_array, params_i); + const char *params = bt_value_string_get(params_value); + bt_value_array_append_element_status append_status; + + append_status = bt_value_array_append_string_element( + comp->extra_params, "--params"); + if (append_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) { + BT_CLI_LOGE_APPEND_CAUSE("Failed to append array element."); + goto error; + } + + append_status = bt_value_array_append_string_element( + comp->extra_params, params); + if (append_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) { + BT_CLI_LOGE_APPEND_CAUSE("Failed to append array element."); + goto error; + } + } + + loglevel_value = bt_value_array_borrow_element_by_index_const( + non_opt_loglevels, orig_idx); + if (bt_value_get_type(loglevel_value) == BT_VALUE_TYPE_STRING) { + const char *loglevel = bt_value_string_get(loglevel_value); + bt_value_array_append_element_status append_status; + + append_status = bt_value_array_append_string_element( + comp->extra_params, "--log-level"); + if (append_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) { + BT_CLI_LOGE_APPEND_CAUSE("Failed to append array element."); + goto error; + } + + append_status = bt_value_array_append_string_element( + comp->extra_params, loglevel); + if (append_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) { + BT_CLI_LOGE_APPEND_CAUSE("Failed to append array element."); + goto error; + } + } } status = append_parameter_to_args(comp->extra_params, "inputs", res->inputs); if (status != 0) { - goto end; + goto error; } g_ptr_array_add(component_args, comp); comp = NULL; } + status = 0; + goto end; + +error: + status = -1; + end: g_free(cc_name); if (comp) { destroy_implicit_component_args(comp); } + + return status; } +/* + * As we iterate the arguments to the convert command, this tracks what is the + * type of the current item, to which some contextual options (e.g. --params) + * apply to. + */ +enum convert_current_item_type { + /* There is no current item. */ + CONVERT_CURRENT_ITEM_TYPE_NONE, + + /* Current item is a component. */ + CONVERT_CURRENT_ITEM_TYPE_COMPONENT, + + /* Current item is a non-option argument. */ + CONVERT_CURRENT_ITEM_TYPE_NON_OPT, +}; + /* * Creates a Babeltrace config object from the arguments of a convert * command. @@ -3365,8 +3337,8 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], bool force_omit_home_plugin_path, const bt_value *initial_plugin_paths, int *default_log_level) { - enum bt_config_component_dest cur_comp_dest = - BT_CONFIG_COMPONENT_DEST_UNKNOWN; + enum convert_current_item_type current_item_type = + CONVERT_CURRENT_ITEM_TYPE_NONE; int ret = 0; struct bt_config *cfg = NULL; bool got_input_format_opt = false; @@ -3374,8 +3346,6 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], bool trimmer_has_begin = false; bool trimmer_has_end = false; bool stream_intersection_mode = false; - GString *cur_name = NULL; - GString *cur_name_prefix = NULL; bool print_run_args = false; bool print_run_args_0 = false; bool print_ctf_metadata = false; @@ -3384,7 +3354,9 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], GList *source_names = NULL; GList *filter_names = NULL; GList *sink_names = NULL; - bt_value *leftovers = NULL; + bt_value *non_opts = NULL; + bt_value *non_opt_params = NULL; + bt_value *non_opt_loglevels = NULL; struct implicit_component_args implicit_ctf_output_args = { 0 }; struct implicit_component_args implicit_lttng_live_args = { 0 }; struct implicit_component_args implicit_dummy_args = { 0 }; @@ -3400,6 +3372,8 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], struct auto_source_discovery auto_disc = { NULL }; GString *auto_disc_comp_name = NULL; struct bt_argpar_parse_ret argpar_parse_ret = { 0 }; + GString *name_gstr = NULL; + GString *component_arg_for_run = NULL; /* * Array of `struct implicit_component_args *` created for the sources @@ -3474,25 +3448,31 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], goto error; } - cur_name = g_string_new(NULL); - if (!cur_name) { + component_arg_for_run = g_string_new(NULL); + if (!component_arg_for_run) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } - cur_name_prefix = g_string_new(NULL); - if (!cur_name_prefix) { + ret = append_env_var_plugin_paths(plugin_paths); + if (ret) { + goto error; + } + + non_opts = bt_value_array_create(); + if (!non_opts) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } - ret = append_env_var_plugin_paths(plugin_paths); - if (ret) { + non_opt_params = bt_value_array_create(); + if (!non_opt_params) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } - leftovers = bt_value_array_create(); - if (!leftovers) { + non_opt_loglevels = bt_value_array_create(); + if (!non_opt_loglevels) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } @@ -3518,10 +3498,7 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], * First pass: collect all arguments which need to be passed * as is to the run command. This pass can also add --name * arguments if needed to automatically name unnamed component - * instances. Also it does the following transformations: - * - * --path=PATH -> --params=path="PATH" - * --url=URL -> --params=url="URL" + * instances. * * Also it appends the plugin paths of --plugin-path to * `plugin_paths`. @@ -3550,250 +3527,288 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], char *comp_cls_name = NULL; const char *arg; - if (argpar_item->type != BT_ARGPAR_ITEM_TYPE_OPT) { - continue; - } + if (argpar_item->type == BT_ARGPAR_ITEM_TYPE_OPT) { + argpar_item_opt = (struct bt_argpar_item_opt *) argpar_item; + arg = argpar_item_opt->arg; - argpar_item_opt = (struct bt_argpar_item_opt *) argpar_item; - arg = argpar_item_opt->arg; + switch (argpar_item_opt->descr->id) { + case OPT_COMPONENT: + { + bt_component_class_type type; - switch (argpar_item_opt->descr->id) { - case OPT_COMPONENT: - { - bt_component_class_type type; - const char *type_prefix; + current_item_type = CONVERT_CURRENT_ITEM_TYPE_COMPONENT; - /* Append current component's name if needed */ - ret = convert_append_name_param(cur_comp_dest, cur_name, - cur_name_prefix, run_args, all_names, - &source_names, &filter_names, &sink_names); - if (ret) { - goto error; - } + /* Parse the argument */ + plugin_comp_cls_names(arg, &name, &plugin_name, + &comp_cls_name, &type); + if (!plugin_name || !comp_cls_name) { + BT_CLI_LOGE_APPEND_CAUSE( + "Invalid format for --component option's argument:\n %s", + arg); + goto error; + } - /* Parse the argument */ - plugin_comp_cls_names(arg, &name, &plugin_name, - &comp_cls_name, &type); - if (!plugin_name || !comp_cls_name) { - BT_CLI_LOGE_APPEND_CAUSE( - "Invalid format for --component option's argument:\n %s", - arg); - goto error; - } + if (name) { + /* + * Name was given by the user, verify it isn't + * taken. + */ + if (bt_value_map_has_entry(all_names, name)) { + BT_CLI_LOGE_APPEND_CAUSE( + "Duplicate component instance name:\n %s", + name); + goto error; + } - if (name) { - g_string_assign(cur_name, name); - } else { - g_string_assign(cur_name, ""); - } + name_gstr = g_string_new(name); + if (!name_gstr) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } - switch (type) { - case BT_COMPONENT_CLASS_TYPE_SOURCE: - cur_comp_dest = BT_CONFIG_COMPONENT_DEST_SOURCE; - type_prefix = "source"; - break; - case BT_COMPONENT_CLASS_TYPE_FILTER: - cur_comp_dest = BT_CONFIG_COMPONENT_DEST_FILTER; - type_prefix = "filter"; - break; - case BT_COMPONENT_CLASS_TYPE_SINK: - cur_comp_dest = BT_CONFIG_COMPONENT_DEST_SINK; - type_prefix = "sink"; - break; - default: - abort(); - } + g_string_assign(component_arg_for_run, arg); + } else { + /* Name not given by user, generate one. */ + name_gstr = get_component_auto_name(arg, all_names); + if (!name_gstr) { + goto error; + } - if (bt_value_array_append_string_element(run_args, - "--component")) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + g_string_printf(component_arg_for_run, "%s:%s", + name_gstr->str, arg); + } - if (bt_value_array_append_string_element(run_args, arg)) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + if (bt_value_array_append_string_element(run_args, + "--component")) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } - g_string_assign(cur_name_prefix, ""); - g_string_append_printf(cur_name_prefix, "%s.%s.%s", - type_prefix, plugin_name, comp_cls_name); - free(name); - free(plugin_name); - free(comp_cls_name); - name = NULL; - plugin_name = NULL; - comp_cls_name = NULL; - break; - } - case OPT_PARAMS: - if (cur_name_prefix->len == 0) { - BT_CLI_LOGE_APPEND_CAUSE("No current component of which to set parameters:\n %s", - arg); - goto error; - } + if (bt_value_array_append_string_element(run_args, + component_arg_for_run->str)) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } - if (bt_value_array_append_string_element(run_args, - "--params")) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + /* + * Remember this name globally, for the uniqueness of + * all component names. + */ + if (bt_value_map_insert_entry(all_names, + name_gstr->str, bt_value_null)) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } - if (bt_value_array_append_string_element(run_args, arg)) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } - break; - case OPT_PATH: - if (cur_name_prefix->len == 0) { - BT_CLI_LOGE_APPEND_CAUSE("No current component of which to set `path` parameter:\n %s", - arg); - goto error; + /* + * Remember this name specifically for the type of the + * component. This is to create connection arguments. + * + * The list takes ownership of `name_gstr`. + */ + switch (type) { + case BT_COMPONENT_CLASS_TYPE_SOURCE: + source_names = g_list_append(source_names, name_gstr); + break; + case BT_COMPONENT_CLASS_TYPE_FILTER: + filter_names = g_list_append(filter_names, name_gstr); + break; + case BT_COMPONENT_CLASS_TYPE_SINK: + sink_names = g_list_append(sink_names, name_gstr); + break; + default: + abort(); + } + name_gstr = NULL; + + free(name); + free(plugin_name); + free(comp_cls_name); + name = NULL; + plugin_name = NULL; + comp_cls_name = NULL; + break; } + case OPT_PARAMS: + if (current_item_type == CONVERT_CURRENT_ITEM_TYPE_COMPONENT) { + /* + * The current item is a component (--component option), + * pass it directly to the run args. + */ + if (bt_value_array_append_string_element(run_args, + "--params")) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } - if (append_string_parameter_to_args(run_args, "path", arg)) { - goto error; - } - break; - case OPT_URL: - if (cur_name_prefix->len == 0) { - BT_CLI_LOGE_APPEND_CAUSE("No current component of which to set `url` parameter:\n %s", - arg); - goto error; - } + if (bt_value_array_append_string_element(run_args, arg)) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } + } else if (current_item_type == CONVERT_CURRENT_ITEM_TYPE_NON_OPT) { + /* + * The current item is a + * non-option argument, record + * it in `non_opt_params`. + */ + bt_value *array; + uint64_t idx = bt_value_array_get_size(non_opt_params) - 1; + array = bt_value_array_borrow_element_by_index(non_opt_params, idx); + bt_value_array_append_string_element(array, arg); + } else { + BT_CLI_LOGE_APPEND_CAUSE( + "No current component (--component option) or non-option argument of which to set parameters:\n %s", + arg); + goto error; + } + break; + case OPT_LOG_LEVEL: + if (current_item_type == CONVERT_CURRENT_ITEM_TYPE_COMPONENT) { + if (bt_value_array_append_string_element(run_args, "--log-level")) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } - if (append_string_parameter_to_args(run_args, "url", arg)) { - goto error; - } - break; - case OPT_NAME: - if (cur_name_prefix->len == 0) { - BT_CLI_LOGE_APPEND_CAUSE("No current component to name:\n %s", - arg); - goto error; - } + if (bt_value_array_append_string_element(run_args, arg)) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } + } else if (current_item_type == CONVERT_CURRENT_ITEM_TYPE_NON_OPT) { + uint64_t idx = bt_value_array_get_size(non_opt_loglevels) - 1; + bt_value *log_level_str_value; - if (bt_value_array_append_string_element(run_args, "--name")) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + log_level_str_value = bt_value_string_create_init(arg); + if (!log_level_str_value) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } - if (bt_value_array_append_string_element(run_args, arg)) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + if (bt_value_array_set_element_by_index(non_opt_loglevels, idx, + log_level_str_value)) { + bt_value_put_ref(log_level_str_value); + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } + } else { + BT_CLI_LOGE_APPEND_CAUSE( + "No current component (--component option) or non-option argument to assign a log level to:\n %s", + arg); + goto error; + } - g_string_assign(cur_name, arg); - break; - case OPT_LOG_LEVEL: - if (cur_name_prefix->len == 0) { - BT_CLI_LOGE_APPEND_CAUSE("No current component to assign a log level to:\n %s", - arg); - goto error; - } + break; + case OPT_OMIT_HOME_PLUGIN_PATH: + force_omit_home_plugin_path = true; - if (bt_value_array_append_string_element(run_args, "--log-level")) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + if (bt_value_array_append_string_element(run_args, + "--omit-home-plugin-path")) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } + break; + case OPT_RETRY_DURATION: + if (bt_value_array_append_string_element(run_args, + "--retry-duration")) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } - if (bt_value_array_append_string_element(run_args, arg)) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + if (bt_value_array_append_string_element(run_args, arg)) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } + break; + case OPT_OMIT_SYSTEM_PLUGIN_PATH: + force_omit_system_plugin_path = true; - break; - case OPT_OMIT_HOME_PLUGIN_PATH: - force_omit_home_plugin_path = true; + if (bt_value_array_append_string_element(run_args, + "--omit-system-plugin-path")) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } + break; + case OPT_PLUGIN_PATH: + if (bt_config_append_plugin_paths_check_setuid_setgid( + plugin_paths, arg)) { + goto error; + } - if (bt_value_array_append_string_element(run_args, - "--omit-home-plugin-path")) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } - break; - case OPT_RETRY_DURATION: - if (bt_value_array_append_string_element(run_args, - "--retry-duration")) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } + if (bt_value_array_append_string_element(run_args, + "--plugin-path")) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } - if (bt_value_array_append_string_element(run_args, arg)) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); + if (bt_value_array_append_string_element(run_args, arg)) { + BT_CLI_LOGE_APPEND_CAUSE_OOM(); + goto error; + } + break; + case OPT_BEGIN: + case OPT_CLOCK_CYCLES: + case OPT_CLOCK_DATE: + case OPT_CLOCK_FORCE_CORRELATE: + case OPT_CLOCK_GMT: + case OPT_CLOCK_OFFSET: + case OPT_CLOCK_OFFSET_NS: + case OPT_CLOCK_SECONDS: + case OPT_COLOR: + case OPT_DEBUG: + case OPT_DEBUG_INFO: + case OPT_DEBUG_INFO_DIR: + case OPT_DEBUG_INFO_FULL_PATH: + case OPT_DEBUG_INFO_TARGET_PREFIX: + case OPT_END: + case OPT_FIELDS: + case OPT_INPUT_FORMAT: + case OPT_NAMES: + case OPT_NO_DELTA: + case OPT_OUTPUT_FORMAT: + case OPT_OUTPUT: + case OPT_RUN_ARGS: + case OPT_RUN_ARGS_0: + case OPT_STREAM_INTERSECTION: + case OPT_TIMERANGE: + case OPT_VERBOSE: + /* Ignore in this pass */ + break; + default: + BT_CLI_LOGE_APPEND_CAUSE("Unknown command-line option specified (option code %d).", + argpar_item_opt->descr->id); goto error; } - break; - case OPT_OMIT_SYSTEM_PLUGIN_PATH: - force_omit_system_plugin_path = true; + } else if (argpar_item->type == BT_ARGPAR_ITEM_TYPE_NON_OPT) { + struct bt_argpar_item_non_opt *argpar_item_non_opt; + bt_value_array_append_element_status append_status; - if (bt_value_array_append_string_element(run_args, - "--omit-system-plugin-path")) { + current_item_type = CONVERT_CURRENT_ITEM_TYPE_NON_OPT; + + argpar_item_non_opt = (struct bt_argpar_item_non_opt *) argpar_item; + + append_status = bt_value_array_append_string_element(non_opts, + argpar_item_non_opt->arg); + if (append_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } - break; - case OPT_PLUGIN_PATH: - if (bt_config_append_plugin_paths_check_setuid_setgid( - plugin_paths, arg)) { - goto error; - } - if (bt_value_array_append_string_element(run_args, - "--plugin-path")) { + append_status = bt_value_array_append_empty_array_element(non_opt_params); + if (append_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } - if (bt_value_array_append_string_element(run_args, arg)) { + append_status = bt_value_array_append_element(non_opt_loglevels, bt_value_null); + if (append_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; } - break; - case OPT_BEGIN: - case OPT_CLOCK_CYCLES: - case OPT_CLOCK_DATE: - case OPT_CLOCK_FORCE_CORRELATE: - case OPT_CLOCK_GMT: - case OPT_CLOCK_OFFSET: - case OPT_CLOCK_OFFSET_NS: - case OPT_CLOCK_SECONDS: - case OPT_COLOR: - case OPT_DEBUG: - case OPT_DEBUG_INFO: - case OPT_DEBUG_INFO_DIR: - case OPT_DEBUG_INFO_FULL_PATH: - case OPT_DEBUG_INFO_TARGET_PREFIX: - case OPT_END: - case OPT_FIELDS: - case OPT_INPUT_FORMAT: - case OPT_NAMES: - case OPT_NO_DELTA: - case OPT_OUTPUT_FORMAT: - case OPT_OUTPUT: - case OPT_RUN_ARGS: - case OPT_RUN_ARGS_0: - case OPT_STREAM_INTERSECTION: - case OPT_TIMERANGE: - case OPT_VERBOSE: - /* Ignore in this pass */ - break; - default: - BT_CLI_LOGE_APPEND_CAUSE("Unknown command-line option specified (option code %d).", - argpar_item_opt->descr->id); - goto error; + } else { + abort(); } } - /* Append current component's name if needed */ - ret = convert_append_name_param(cur_comp_dest, cur_name, - cur_name_prefix, run_args, all_names, &source_names, - &filter_names, &sink_names); - if (ret) { - goto error; - } - /* * Second pass: transform the convert-specific options and * arguments into implicit component instances for the run @@ -4111,35 +4126,16 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], goto error; } - /* Consume and keep leftover arguments */ - for (i = 0; i < argpar_parse_ret.items->len; i++) { - struct bt_argpar_item *argpar_item = - g_ptr_array_index(argpar_parse_ret.items, i); - struct bt_argpar_item_non_opt *argpar_item_non_opt; - - if (argpar_item->type != BT_ARGPAR_ITEM_TYPE_NON_OPT) { - continue; - } - - argpar_item_non_opt = (struct bt_argpar_item_non_opt *) argpar_item; - - if (bt_value_array_append_string_element(leftovers, argpar_item_non_opt->arg) != - BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) { - BT_CLI_LOGE_APPEND_CAUSE_OOM(); - goto error; - } - } - /* Print CTF metadata or print LTTng live sessions */ if (print_ctf_metadata) { - const bt_value *bt_val_leftover; + const bt_value *bt_val_non_opt; - if (bt_value_array_is_empty(leftovers)) { + if (bt_value_array_is_empty(non_opts)) { BT_CLI_LOGE_APPEND_CAUSE("--output-format=ctf-metadata specified without a path."); goto error; } - if (bt_value_array_get_size(leftovers) > 1) { + if (bt_value_array_get_size(non_opts) > 1) { BT_CLI_LOGE_APPEND_CAUSE("Too many paths specified for --output-format=ctf-metadata."); goto error; } @@ -4149,9 +4145,9 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], goto error; } - bt_val_leftover = bt_value_array_borrow_element_by_index_const(leftovers, 0); + bt_val_non_opt = bt_value_array_borrow_element_by_index_const(non_opts, 0); g_string_assign(cfg->cmd_data.print_ctf_metadata.path, - bt_value_string_get(bt_val_leftover)); + bt_value_string_get(bt_val_non_opt)); if (output) { g_string_assign( @@ -4216,19 +4212,19 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], } } - /* Decide where the leftover argument(s) go */ - if (bt_value_array_get_size(leftovers) > 0) { + /* Decide where the non-option argument(s) go */ + if (bt_value_array_get_size(non_opts) > 0) { if (implicit_lttng_live_args.exists) { - const bt_value *bt_val_leftover; + const bt_value *bt_val_non_opt; - if (bt_value_array_get_size(leftovers) > 1) { + if (bt_value_array_get_size(non_opts) > 1) { BT_CLI_LOGE_APPEND_CAUSE("Too many URLs specified for --input-format=lttng-live."); goto error; } - bt_val_leftover = bt_value_array_borrow_element_by_index_const(leftovers, 0); + bt_val_non_opt = bt_value_array_borrow_element_by_index_const(non_opts, 0); lttng_live_url_parts = - bt_common_parse_lttng_live_url(bt_value_string_get(bt_val_leftover), + bt_common_parse_lttng_live_url(bt_value_string_get(bt_val_non_opt), error_buf, sizeof(error_buf)); if (!lttng_live_url_parts.proto) { BT_CLI_LOGE_APPEND_CAUSE("Invalid LTTng live URL format: %s.", @@ -4245,7 +4241,7 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], } g_string_assign(cfg->cmd_data.print_lttng_live_sessions.url, - bt_value_string_get(bt_val_leftover)); + bt_value_string_get(bt_val_non_opt)); if (output) { g_string_assign( @@ -4258,7 +4254,7 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], ret = append_implicit_component_extra_param( &implicit_lttng_live_args, "url", - bt_value_string_get(bt_val_leftover)); + bt_value_string_get(bt_val_non_opt)); if (ret) { goto error; } @@ -4272,7 +4268,7 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], } else { int status; - status = auto_discover_source_components(plugin_paths, leftovers, + status = auto_discover_source_components(plugin_paths, non_opts, auto_source_discovery_restrict_plugin_name, auto_source_discovery_restrict_component_class_name, *default_log_level >= 0 ? *default_log_level : cli_default_log_level, @@ -4282,8 +4278,12 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], goto error; } - create_implicit_component_args_from_auto_discovered_sources( - &auto_disc, discovered_source_args); + status = create_implicit_component_args_from_auto_discovered_sources( + &auto_disc, non_opt_params, non_opt_loglevels, + discovered_source_args); + if (status != 0) { + goto error; + } } } @@ -4316,10 +4316,11 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], } /* - * If the implicit `source.ctf.lttng-live` component exists, make sure - * there's at least one leftover (which is the URL). + * If the implicit `source.ctf.lttng-live` component exists, + * make sure there's at least one non-option argument (which is + * the URL). */ - if (implicit_lttng_live_args.exists && bt_value_array_is_empty(leftovers)) { + if (implicit_lttng_live_args.exists && bt_value_array_is_empty(non_opts)) { BT_CLI_LOGE_APPEND_CAUSE("Missing URL for implicit `%s` component.", implicit_lttng_live_args.comp_arg->str); goto error; @@ -4580,12 +4581,12 @@ end: free(output); - if (cur_name) { - g_string_free(cur_name, TRUE); + if (component_arg_for_run) { + g_string_free(component_arg_for_run, TRUE); } - if (cur_name_prefix) { - g_string_free(cur_name_prefix, TRUE); + if (name_gstr) { + g_string_free(name_gstr, TRUE); } bt_value_put_ref(run_args); @@ -4593,7 +4594,9 @@ end: destroy_glist_of_gstring(source_names); destroy_glist_of_gstring(filter_names); destroy_glist_of_gstring(sink_names); - bt_value_put_ref(leftovers); + bt_value_put_ref(non_opt_params); + bt_value_put_ref(non_opt_loglevels); + bt_value_put_ref(non_opts); finalize_implicit_component_args(&implicit_ctf_output_args); finalize_implicit_component_args(&implicit_lttng_live_args); finalize_implicit_component_args(&implicit_dummy_args);