379 строки
12 KiB
C
379 строки
12 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$
|
|
*
|
|
* 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/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_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 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(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(40, 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 (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(10, 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(10, 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(include_mode, names, ri->ri_name)) {
|
|
mca_base_component_repository_open (framework, ri);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* OPAL_HAVE_DL_SUPPORT */
|
|
|
|
static bool use_component(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) {
|
|
return true;
|
|
}
|
|
|
|
while ( *req_comp_name != NULL ) {
|
|
if ( strcmp(component_name, *req_comp_name) == 0 ) {
|
|
found = true;
|
|
break;
|
|
}
|
|
req_comp_name++;
|
|
}
|
|
|
|
/*
|
|
* 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;
|
|
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) {
|
|
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)) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
char h[MAXHOSTNAMELEN];
|
|
gethostname(h, sizeof(h));
|
|
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;
|
|
}
|