diff --git a/opal/mca/base/Makefile.am b/opal/mca/base/Makefile.am index bd6145d354..2e4cd3f2f3 100644 --- a/opal/mca/base/Makefile.am +++ b/opal/mca/base/Makefile.am @@ -10,6 +10,7 @@ # Copyright (c) 2004-2005 The Regents of the University of California. # All rights reserved. # Copyright (c) 2010 Cisco Systems, Inc. All rights reserved. +# Copyright (c) 2020 Google LLC. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -31,6 +32,7 @@ dist_opaldata_DATA = help-mca-base.txt help-mca-var.txt headers = \ base.h \ + mca_base_alias.h \ mca_base_component_repository.h \ mca_base_var.h \ mca_base_pvar.h \ @@ -43,6 +45,7 @@ headers = \ libmca_base_la_SOURCES = \ $(headers) \ + mca_base_alias.c \ mca_base_close.c \ mca_base_cmd_line.c \ mca_base_component_compare.c \ diff --git a/opal/mca/base/mca_base_alias.c b/opal/mca/base/mca_base_alias.c new file mode 100644 index 0000000000..fd1aeef1df --- /dev/null +++ b/opal/mca/base/mca_base_alias.c @@ -0,0 +1,173 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ +/* + * Copyright (c) 2020 Google, LLC. All rights reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "mca_base_alias.h" +#include "opal/class/opal_hash_table.h" +#include "opal/runtime/opal.h" + +static void mca_base_alias_init (mca_base_alias_t *alias) +{ + OBJ_CONSTRUCT(&alias->component_aliases, opal_list_t); +} + +static void mca_base_alias_fini (mca_base_alias_t *alias) +{ + OPAL_LIST_DESTRUCT(&alias->component_aliases); +} + +OBJ_CLASS_INSTANCE(mca_base_alias_t, opal_object_t, mca_base_alias_init, + mca_base_alias_fini); + +static void mca_base_alias_item_init (mca_base_alias_item_t *alias_item) { + alias_item->component_alias = NULL; +} + +static void mca_base_alias_item_fini (mca_base_alias_item_t *alias_item) { + free (alias_item->component_alias); +} + +OBJ_CLASS_INSTANCE(mca_base_alias_item_t, opal_list_item_t, mca_base_alias_item_init, + mca_base_alias_item_fini); + +/* + * local variables + */ +static opal_hash_table_t *alias_hash_table; + +static void mca_base_alias_cleanup (void) +{ + if (!alias_hash_table) { + return; + } + + void *key; + opal_object_t *value; + OPAL_HASH_TABLE_FOREACH_PTR(key, value, alias_hash_table, { + OBJ_RELEASE(value); + }); + + OBJ_RELEASE(alias_hash_table); + alias_hash_table = NULL; +} + +static int mca_base_alias_setup (void) +{ + if (NULL != alias_hash_table) { + return OPAL_SUCCESS; + } + + opal_finalize_register_cleanup (mca_base_alias_cleanup); + + alias_hash_table = OBJ_NEW(opal_hash_table_t); + if (NULL == alias_hash_table) { + return OPAL_ERR_OUT_OF_RESOURCE; + } + + int ret = opal_hash_table_init (alias_hash_table, 32); + if (OPAL_SUCCESS != ret) { + OBJ_RELEASE(alias_hash_table); + alias_hash_table = NULL; + return ret; + } + + return OPAL_SUCCESS; +} + +static char *mca_base_alias_generate_name (const char *project, const char *framework, const char *component_name) +{ + size_t project_length = project ? strlen (project) : 0; + size_t framework_length = framework ? strlen (framework) : 0; + size_t component_name_length = strlen (component_name); + size_t length = project_length + framework_length + component_name_length + 2; + char *tmp = calloc (1, length + 1); + if (NULL == tmp) { + return tmp; + } + + if (project_length) { + strncat (tmp, project, length); + strncat (tmp, "_", 1); + length -= project_length + 1; + } + + if (framework_length) { + strncat (tmp, framework, length); + strncat (tmp, "_", 1); + length -= framework_length + 1; + } + + strncat (tmp, component_name, length); + + return tmp; +} + +static mca_base_alias_t *mca_base_alias_lookup_internal (const char *name) +{ + mca_base_alias_t *alias = NULL; + if (NULL == alias_hash_table) { + return NULL; + } + + (void) opal_hash_table_get_value_ptr (alias_hash_table, name, strlen (name), (void **) &alias); + return alias; +} + +int mca_base_alias_register (const char *project, const char *framework, const char *component_name, + const char *component_alias, uint32_t alias_flags) +{ + if (NULL == component_name) { + return OPAL_ERR_BAD_PARAM; + } + + int ret = mca_base_alias_setup (); + if (OPAL_SUCCESS != ret) { + return ret; + } + + char *name = mca_base_alias_generate_name (project, framework, component_name); + assert (NULL != name); + + mca_base_alias_t *alias = mca_base_alias_lookup_internal (name); + if (NULL == alias) { + alias = OBJ_NEW(mca_base_alias_t); + if (NULL == alias) { + return OPAL_ERR_OUT_OF_RESOURCE; + } + + opal_hash_table_set_value_ptr (alias_hash_table, name, strlen(name), alias); + free (name); + } + + mca_base_alias_item_t *alias_item = OBJ_NEW(mca_base_alias_item_t); + if (NULL == alias_item) { + return OPAL_ERR_OUT_OF_RESOURCE; + } + + alias_item->component_alias = strdup (component_alias); + alias_item->alias_flags = alias_flags; + + opal_list_append (&alias->component_aliases, &alias_item->super); + + return OPAL_SUCCESS; +} + +const mca_base_alias_t *mca_base_alias_lookup(const char *project, const char *framework, const char *component_name) +{ + if (NULL == component_name) { + return NULL; + } + + char *name = mca_base_alias_generate_name (project, framework, component_name); + assert (NULL != name); + const mca_base_alias_t *alias = mca_base_alias_lookup_internal (name); + free (name); + + return alias; +} diff --git a/opal/mca/base/mca_base_alias.h b/opal/mca/base/mca_base_alias.h new file mode 100644 index 0000000000..552464ce6d --- /dev/null +++ b/opal/mca/base/mca_base_alias.h @@ -0,0 +1,86 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ +/* + * Copyright (c) 2020 Google, LLC. All rights reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#ifndef OPAL_MCA_BASE_ALIAS_H +#define OPAL_MCA_BASE_ALIAS_H + +#include "opal_config.h" +#include "opal/class/opal_list.h" + +BEGIN_C_DECLS + +enum mca_base_alias_flags_t { + MCA_BASE_ALIAS_FLAG_NONE = 0, + /** The aliased name has been deprecated. */ + MCA_BASE_ALIAS_FLAG_DEPRECATED = 1, +}; + +typedef enum mca_base_alias_flags_t mca_base_alias_flags_t; + +struct mca_base_alias_item_t { + opal_list_item_t super; + /** Name aias. */ + char *component_alias; + /** Alias flags. */ + uint32_t alias_flags; +}; + +typedef struct mca_base_alias_item_t mca_base_alias_item_t; + +OBJ_CLASS_DECLARATION(mca_base_alias_item_t); + +struct mca_base_alias_t { + opal_object_t super; + /** List of name aliases. */ + opal_list_t component_aliases; +}; + +typedef struct mca_base_alias_t mca_base_alias_t; + +OBJ_CLASS_DECLARATION(mca_base_alias_t); + +/** + * @brief Create a alias for a component name. + * + * @param[in] project Project name (may be NULL) + * @param[in] framework Framework name (may be NULL) + * @param[in] component_name Name of component to alias (may not be NULL) + * @param[in] component_alias Aliased name (may not be NULL) + * @param[in] alias_flags Flags (see mca_base_alias_flags_t) + * + * This function aliases one component name to another. When aliased + * any variable registered with this project, framework, and + * component_name will have synonyms created. For example, if + * opal_btl_vader is aliased to sm then registers a variable + * named btl_vader_flags then a synonym will be created with the + * name btl_sm_flags. If an alias is registered early enough + * (during framework registration for example) then the alias can + * also be used for component selection. In the previous example + * --mca btl vader and --mca btl sm would select the same + * component if the synonym is registered in the btl framework + * registration function. + */ +OPAL_DECLSPEC int mca_base_alias_register (const char *project, const char *framework, + const char *component_name, + const char *component_alias, + uint32_t alias_flags); + +/** + * @brief Check for aliases for a component. + * + * @param[in] project Project name (may be NULL) + * @param[in] frameworek Framework name (may be NULL) + * @param[in] component_name Component name (may not be NULL) + */ +OPAL_DECLSPEC const mca_base_alias_t *mca_base_alias_lookup(const char *project, + const char *framework, + const char *component_name); + +#endif /* OPAL_MCA_BASE_ALIAS_H */ diff --git a/opal/mca/base/mca_base_component_find.c b/opal/mca/base/mca_base_component_find.c index 45d2eff776..477fd3f16c 100644 --- a/opal/mca/base/mca_base_component_find.c +++ b/opal/mca/base/mca_base_component_find.c @@ -18,6 +18,7 @@ * reserved. * Copyright (c) 2019 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2020 Google, LLC. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -56,6 +57,7 @@ #include "opal/class/opal_list.h" #include "opal/mca/mca.h" #include "opal/mca/base/base.h" +#include "opal/mca/base/mca_base_alias.h" #include "opal/mca/base/mca_base_component_repository.h" #include "opal/constants.h" #include "opal/mca/dl/base/base.h" @@ -84,7 +86,8 @@ typedef struct mca_base_open_only_dummy_component_t mca_base_open_only_dummy_com static char negate[] = "^"; -static bool use_component(const bool include_mode, +static bool use_component(const mca_base_framework_t *framework, + const bool include_mode, const char **requested_component_names, const char *component_name); @@ -118,7 +121,7 @@ int mca_base_component_find (const char *directory, mca_base_framework_t *framew /* Find all the components that were statically linked in */ if (static_components) { for (int i = 0 ; NULL != static_components[i]; ++i) { - if ( use_component(include_mode, + if ( use_component(framework, include_mode, (const char**)requested_component_names, static_components[i]->mca_component_name) ) { cli = OBJ_NEW(mca_base_component_list_item_t); @@ -192,7 +195,7 @@ int mca_base_components_filter (mca_base_framework_t *framework, uint32_t filter mca_base_open_only_dummy_component_t *dummy = (mca_base_open_only_dummy_component_t *) cli->cli_component; - can_use = use_component (include_mode, (const char **) requested_component_names, + can_use = use_component (framework, include_mode, (const char **) requested_component_names, cli->cli_component->mca_component_name); if (!can_use || (filter_flags & dummy->data.param_field) != filter_flags) { @@ -263,7 +266,7 @@ static void find_dyn_components(const char *path, mca_base_framework_t *framewor /* Iterate through the repository and find components that can be included */ OPAL_LIST_FOREACH(ri, dy_components, mca_base_component_repository_item_t) { - if (use_component(include_mode, names, ri->ri_name)) { + if (use_component(framework, include_mode, names, ri->ri_name)) { mca_base_component_repository_open (framework, ri); } } @@ -271,27 +274,44 @@ static void find_dyn_components(const char *path, mca_base_framework_t *framewor #endif /* OPAL_HAVE_DL_SUPPORT */ -static bool use_component(const bool include_mode, +static bool component_in_list (const char **requested_component_names, + const char *component_name) +{ + for (int i = 0 ; requested_component_names[i] ; ++i) { + if (strcmp(component_name, requested_component_names[i]) == 0) { + return true; + } + } + + return false; +} + +static bool use_component(const mca_base_framework_t *framework, + const bool include_mode, const char **requested_component_names, const char *component_name) { - bool found = false; - const char **req_comp_name = requested_component_names; - /* * If no selection is specified then we use all components * we can find. */ - if (NULL == req_comp_name) { + if (NULL == requested_component_names) { return true; } - while ( *req_comp_name != NULL ) { - if ( strcmp(component_name, *req_comp_name) == 0 ) { - found = true; - break; + bool found = component_in_list (requested_component_names, component_name); + + if (!found) { + const mca_base_alias_t *alias = mca_base_alias_lookup (framework->framework_project, + framework->framework_name, component_name); + if (alias) { + OPAL_LIST_FOREACH_DECL(alias_item, &alias->component_aliases, mca_base_alias_item_t) { + found = component_in_list (requested_component_names, alias_item->component_alias); + if (found) { + break; + } + } } - req_comp_name++; } /* @@ -315,21 +335,34 @@ static bool use_component(const bool include_mode, static int component_find_check (mca_base_framework_t *framework, char **requested_component_names) { opal_list_t *components = &framework->framework_components; - mca_base_component_list_item_t *cli; if (NULL == requested_component_names) { return OPAL_SUCCESS; } - for (int i = 0; NULL != requested_component_names[i]; ++i) { + for (int i = 0 ; requested_component_names[i] ; ++i) { bool found = false; - OPAL_LIST_FOREACH(cli, components, mca_base_component_list_item_t) { - if (0 == strcmp(requested_component_names[i], - cli->cli_component->mca_component_name)) { + OPAL_LIST_FOREACH_DECL(cli, components, mca_base_component_list_item_t) { + if (0 == strcmp (requested_component_names[i], cli->cli_component->mca_component_name)) { found = true; break; } + + const mca_base_alias_t *alias = mca_base_alias_lookup (framework->framework_project, + framework->framework_name, + cli->cli_component->mca_component_name); + if (alias) { + OPAL_LIST_FOREACH_DECL(alias_item, &alias->component_aliases, mca_base_alias_item_t) { + if (0 == strcmp (requested_component_names[i], alias_item->component_alias)) { + found = true; + break; + } + } + if (found) { + break; + } + } } if (!found) { diff --git a/opal/mca/base/mca_base_var.c b/opal/mca/base/mca_base_var.c index 539ef3d192..c66da5475e 100644 --- a/opal/mca/base/mca_base_var.c +++ b/opal/mca/base/mca_base_var.c @@ -20,6 +20,7 @@ * Copyright (c) 2018 Amazon.com, Inc. or its affiliates. All Rights reserved. * Copyright (c) 2018 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2020 Google, LLC. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -49,6 +50,7 @@ #include "opal/util/argv.h" #include "opal/mca/mca.h" #include "opal/mca/base/mca_base_vari.h" +#include "opal/mca/base/mca_base_alias.h" #include "opal/constants.h" #include "opal/util/output.h" #include "opal/util/opal_environ.h" @@ -1545,12 +1547,33 @@ int mca_base_var_register (const char *project_name, const char *framework_name, mca_base_var_info_lvl_t info_lvl, mca_base_var_scope_t scope, void *storage) { + int ret; /* Only integer variables can have enumerator */ assert (NULL == enumerator || (MCA_BASE_VAR_TYPE_INT == type || MCA_BASE_VAR_TYPE_UNSIGNED_INT == type)); - return register_variable (project_name, framework_name, component_name, - variable_name, description, type, enumerator, - bind, flags, info_lvl, scope, -1, storage); + ret = register_variable (project_name, framework_name, component_name, + variable_name, description, type, enumerator, + bind, flags, info_lvl, scope, -1, storage); + if (OPAL_UNLIKELY(0 > ret)) { + return ret; + } + + /* Register aliases if any exist */ + const mca_base_alias_t *alias = mca_base_alias_lookup (project_name, framework_name, component_name); + if (NULL == alias) { + return ret; + } + + OPAL_LIST_FOREACH_DECL(alias_item, &alias->component_aliases, mca_base_alias_item_t) { + mca_base_var_syn_flag_t flags = 0; + if (alias_item->alias_flags & MCA_BASE_ALIAS_FLAG_DEPRECATED) { + flags = MCA_BASE_VAR_SYN_FLAG_DEPRECATED; + } + (void) mca_base_var_register_synonym (ret, project_name, framework_name, alias_item->component_alias, + variable_name, flags); + } + + return ret; } int mca_base_component_var_register (const mca_base_component_t *component,