9fae5bfdf3
This commit adds support for aliasing component names. A component name alias is created by calling: mca_base_alias_register. The name of the project and framework are optional. The component name and component alias are required. Once an alias is registered all variables registered after the alias creation will have synonyms also registered. For example: ```c mca_base_alias_register("opal", "btl", "vader", "sm", false); ``` would cause all of the variables registered by btl/vader to have aliases that start with btl_sm. Ex: btl_vader_single_copy_mechanism would have the synonym: btl_sm_single_copy_mechanism. If aliases are registered before component filtering the alias can also be used for component selection. For example, if sm is registered as an alias to vader in the btl framework register function then ```--mca btl self,sm``` would be equivalent to ```--mca btl self,vader```. Signed-off-by: Nathan Hjelm <hjelmn@google.com>
417 строки
14 KiB
C
417 строки
14 KiB
C
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
|
|
/*
|
|
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
|
* University Research and Technology
|
|
* Corporation. All rights reserved.
|
|
* Copyright (c) 2004-2007 The University of Tennessee and The University
|
|
* of Tennessee Research Foundation. All rights
|
|
* reserved.
|
|
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
|
* University of Stuttgart. All rights reserved.
|
|
* Copyright (c) 2004-2005 The Regents of the University of California.
|
|
* All rights reserved.
|
|
* Copyright (c) 2008-2015 Cisco Systems, Inc. All rights reserved.
|
|
* Copyright (c) 2008 Sun Microsystems, Inc. All rights reserved.
|
|
* Copyright (c) 2015 Research Organization for Information Science
|
|
* and Technology (RIST). All rights reserved.
|
|
* Copyright (c) 2014-2015 Los Alamos National Security, LLC. All rights
|
|
* reserved.
|
|
* Copyright (c) 2019 Triad National Security, LLC. All rights
|
|
* reserved.
|
|
* Copyright (c) 2020 Google, LLC. All rights reserved.
|
|
* $COPYRIGHT$
|
|
*
|
|
* Additional copyrights may follow
|
|
*
|
|
* $HEADER$
|
|
*/
|
|
|
|
#include "opal_config.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
#include <sys/types.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_STAT_H
|
|
#include <sys/stat.h>
|
|
#endif
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_PARAM_H
|
|
#include <sys/param.h>
|
|
#endif
|
|
#ifdef HAVE_NETDB_H
|
|
#include <netdb.h>
|
|
#endif
|
|
|
|
#include "opal/runtime/opal.h"
|
|
#include "opal/mca/installdirs/installdirs.h"
|
|
#include "opal/util/opal_environ.h"
|
|
#include "opal/util/output.h"
|
|
#include "opal/util/argv.h"
|
|
#include "opal/util/show_help.h"
|
|
#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"
|
|
|
|
#if OPAL_HAVE_DL_SUPPORT
|
|
/*
|
|
* Private functions
|
|
*/
|
|
static void find_dyn_components(const char *path, mca_base_framework_t *framework,
|
|
const char **names, bool include_mode);
|
|
|
|
#endif /* OPAL_HAVE_DL_SUPPORT */
|
|
|
|
static int component_find_check (mca_base_framework_t *framework, char **requested_component_names);
|
|
|
|
/*
|
|
* Dummy structure for casting for open_only logic
|
|
*/
|
|
struct mca_base_open_only_dummy_component_t {
|
|
/** MCA base component */
|
|
mca_base_component_t version;
|
|
/** MCA base data */
|
|
mca_base_component_data_t data;
|
|
};
|
|
typedef struct mca_base_open_only_dummy_component_t mca_base_open_only_dummy_component_t;
|
|
|
|
static char negate[] = "^";
|
|
|
|
static bool use_component(const mca_base_framework_t *framework,
|
|
const bool include_mode,
|
|
const char **requested_component_names,
|
|
const char *component_name);
|
|
|
|
|
|
/*
|
|
* Function to find as many components of a given type as possible. This
|
|
* includes statically-linked in components as well as opening up a
|
|
* directory and looking for shared-library MCA components of the
|
|
* appropriate type (load them if available).
|
|
*
|
|
* Return one consolidated array of (mca_base_component_t*) pointing to all
|
|
* available components.
|
|
*/
|
|
int mca_base_component_find (const char *directory, mca_base_framework_t *framework,
|
|
bool ignore_requested, bool open_dso_components)
|
|
{
|
|
const mca_base_component_t **static_components = framework->framework_static_components;
|
|
char **requested_component_names = NULL;
|
|
mca_base_component_list_item_t *cli;
|
|
bool include_mode = true;
|
|
int ret;
|
|
|
|
if (!ignore_requested) {
|
|
ret = mca_base_component_parse_requested (framework->framework_selection, &include_mode,
|
|
&requested_component_names);
|
|
if (OPAL_SUCCESS != ret) {
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
/* Find all the components that were statically linked in */
|
|
if (static_components) {
|
|
for (int i = 0 ; NULL != static_components[i]; ++i) {
|
|
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);
|
|
if (NULL == cli) {
|
|
ret = OPAL_ERR_OUT_OF_RESOURCE;
|
|
goto component_find_out;
|
|
}
|
|
cli->cli_component = static_components[i];
|
|
opal_list_append(&framework->framework_components, (opal_list_item_t *) cli);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if OPAL_HAVE_DL_SUPPORT
|
|
/* Find any available dynamic components in the specified directory */
|
|
if (open_dso_components && !mca_base_component_disable_dlopen) {
|
|
find_dyn_components(directory, framework, (const char**)requested_component_names,
|
|
include_mode);
|
|
} else {
|
|
opal_output_verbose (MCA_BASE_VERBOSE_INFO, 0,
|
|
"mca: base: component_find: dso loading for %s MCA components disabled",
|
|
framework->framework_name);
|
|
}
|
|
#endif
|
|
|
|
if (include_mode) {
|
|
ret = component_find_check (framework, requested_component_names);
|
|
} else {
|
|
ret = OPAL_SUCCESS;
|
|
}
|
|
|
|
component_find_out:
|
|
|
|
if (NULL != requested_component_names) {
|
|
opal_argv_free(requested_component_names);
|
|
}
|
|
|
|
/* All done */
|
|
|
|
return ret;
|
|
}
|
|
|
|
int mca_base_component_find_finalize(void)
|
|
{
|
|
return OPAL_SUCCESS;
|
|
}
|
|
|
|
int mca_base_components_filter (mca_base_framework_t *framework, uint32_t filter_flags)
|
|
{
|
|
opal_list_t *components = &framework->framework_components;
|
|
int output_id = framework->framework_output;
|
|
mca_base_component_list_item_t *cli, *next;
|
|
char **requested_component_names = NULL;
|
|
bool include_mode, can_use;
|
|
int ret;
|
|
|
|
assert (NULL != components);
|
|
|
|
if (0 == filter_flags && NULL == framework->framework_selection) {
|
|
return OPAL_SUCCESS;
|
|
}
|
|
|
|
ret = mca_base_component_parse_requested (framework->framework_selection, &include_mode,
|
|
&requested_component_names);
|
|
if (OPAL_SUCCESS != ret) {
|
|
return ret;
|
|
}
|
|
|
|
OPAL_LIST_FOREACH_SAFE(cli, next, components, mca_base_component_list_item_t) {
|
|
const mca_base_component_t *component = cli->cli_component;
|
|
mca_base_open_only_dummy_component_t *dummy =
|
|
(mca_base_open_only_dummy_component_t *) cli->cli_component;
|
|
|
|
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) {
|
|
if (can_use && (filter_flags & MCA_BASE_METADATA_PARAM_CHECKPOINT) &&
|
|
!(MCA_BASE_METADATA_PARAM_CHECKPOINT & dummy->data.param_field)) {
|
|
opal_output_verbose (MCA_BASE_VERBOSE_COMPONENT, output_id,
|
|
"mca: base: components_filter: "
|
|
"(%s) Component %s is *NOT* Checkpointable - Disabled",
|
|
component->reserved,
|
|
component->mca_component_name);
|
|
}
|
|
|
|
opal_list_remove_item (components, &cli->super);
|
|
|
|
mca_base_component_unload (component, output_id);
|
|
|
|
OBJ_RELEASE(cli);
|
|
} else if (filter_flags & MCA_BASE_METADATA_PARAM_CHECKPOINT) {
|
|
opal_output_verbose (MCA_BASE_VERBOSE_COMPONENT, output_id,
|
|
"mca: base: components_filter: "
|
|
"(%s) Component %s is Checkpointable",
|
|
component->reserved,
|
|
component->mca_component_name);
|
|
}
|
|
}
|
|
|
|
if (include_mode) {
|
|
ret = component_find_check (framework, requested_component_names);
|
|
} else {
|
|
ret = OPAL_SUCCESS;
|
|
}
|
|
|
|
if (NULL != requested_component_names) {
|
|
opal_argv_free (requested_component_names);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
#if OPAL_HAVE_DL_SUPPORT
|
|
|
|
/*
|
|
* Open up all directories in a given path and search for components of
|
|
* the specified type (and possibly of a given name).
|
|
*
|
|
* Note that we use our own path iteration functionality because we
|
|
* need to look at companion .ompi_info files in the same directory as
|
|
* the library to generate dependencies, etc.
|
|
*/
|
|
static void find_dyn_components(const char *path, mca_base_framework_t *framework,
|
|
const char **names, bool include_mode)
|
|
{
|
|
mca_base_component_repository_item_t *ri;
|
|
opal_list_t *dy_components;
|
|
int ret;
|
|
|
|
if (NULL != path) {
|
|
ret = mca_base_component_repository_add (path);
|
|
if (OPAL_SUCCESS != ret) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
ret = mca_base_component_repository_get_components (framework, &dy_components);
|
|
if (OPAL_SUCCESS != ret) {
|
|
return;
|
|
}
|
|
|
|
/* 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(framework, include_mode, names, ri->ri_name)) {
|
|
mca_base_component_repository_open (framework, ri);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* OPAL_HAVE_DL_SUPPORT */
|
|
|
|
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)
|
|
{
|
|
/*
|
|
* If no selection is specified then we use all components
|
|
* we can find.
|
|
*/
|
|
if (NULL == requested_component_names) {
|
|
return true;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* include_mode found | use
|
|
* --------------------+------
|
|
* 0 0 | true
|
|
* 0 1 | false
|
|
* 1 0 | false
|
|
* 1 1 | true
|
|
*
|
|
* -> inverted xor
|
|
* As xor is a binary operator let's implement it manually before
|
|
* a compiler screws it up.
|
|
*/
|
|
|
|
return (include_mode && found) || !(include_mode || found);
|
|
}
|
|
|
|
/* Ensure that *all* requested components exist. Print a warning
|
|
and abort if they do not. */
|
|
static int component_find_check (mca_base_framework_t *framework, char **requested_component_names)
|
|
{
|
|
opal_list_t *components = &framework->framework_components;
|
|
|
|
if (NULL == requested_component_names) {
|
|
return OPAL_SUCCESS;
|
|
}
|
|
|
|
for (int i = 0 ; requested_component_names[i] ; ++i) {
|
|
bool found = false;
|
|
|
|
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) {
|
|
const char *h;
|
|
h = opal_gethostname();
|
|
opal_show_help("help-mca-base.txt",
|
|
"find-available:not-valid", true,
|
|
h, framework->framework_name, requested_component_names[i]);
|
|
return OPAL_ERR_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
return OPAL_SUCCESS;
|
|
}
|
|
|
|
int mca_base_component_parse_requested (const char *requested, bool *include_mode,
|
|
char ***requested_component_names)
|
|
{
|
|
const char *requested_orig = requested;
|
|
|
|
*requested_component_names = NULL;
|
|
*include_mode = true;
|
|
|
|
/* See if the user requested anything */
|
|
if (NULL == requested || 0 == strlen (requested)) {
|
|
return OPAL_SUCCESS;
|
|
}
|
|
|
|
/* Are we including or excluding? We only allow the negate
|
|
character to be the *first* character of the value (but be nice
|
|
and allow any number of negate characters in the beginning). */
|
|
*include_mode = requested[0] != negate[0];
|
|
|
|
/* skip over all negate symbols at the beginning */
|
|
requested += strspn (requested, negate);
|
|
|
|
/* Double check to ensure that the user did not specify the negate
|
|
character anywhere else in the value. */
|
|
if (NULL != strstr (requested, negate)) {
|
|
opal_show_help("help-mca-base.txt",
|
|
"framework-param:too-many-negates",
|
|
true, requested_orig);
|
|
return OPAL_ERROR;
|
|
}
|
|
|
|
/* Split up the value into individual component names */
|
|
*requested_component_names = opal_argv_split(requested, ',');
|
|
|
|
/* All done */
|
|
return OPAL_SUCCESS;
|
|
}
|