Merge pull request #516 from hjelmn/repository_update
RFC: Repository update
Этот коммит содержится в:
Коммит
e794658f2d
@ -145,11 +145,8 @@ OPAL_DECLSPEC char * mca_base_component_to_string(const mca_base_component_t *a)
|
||||
|
||||
/* mca_base_component_find.c */
|
||||
|
||||
OPAL_DECLSPEC int mca_base_component_find(const char *directory, const char *type,
|
||||
const mca_base_component_t *static_components[],
|
||||
const char *requested_components,
|
||||
opal_list_t *found_components,
|
||||
bool open_dso_components);
|
||||
OPAL_DECLSPEC int mca_base_component_find (const char *directory, mca_base_framework_t *framework,
|
||||
bool ignore_requested, bool open_dso_components);
|
||||
|
||||
/**
|
||||
* Parse the requested component string and return an opal_argv of the requested
|
||||
@ -176,8 +173,7 @@ int mca_base_component_parse_requested (const char *requested, bool *include_mod
|
||||
* This function closes and releases any components that do not match the filter_name and
|
||||
* filter flags.
|
||||
*/
|
||||
OPAL_DECLSPEC int mca_base_components_filter (const char *framework_name, opal_list_t *components, int output_id,
|
||||
const char *filter_names, uint32_t filter_flags);
|
||||
OPAL_DECLSPEC int mca_base_components_filter (mca_base_framework_t *framework, uint32_t filter_flags);
|
||||
|
||||
|
||||
|
||||
|
@ -55,75 +55,16 @@
|
||||
#include "opal/constants.h"
|
||||
#include "opal/mca/dl/base/base.h"
|
||||
|
||||
|
||||
#if OPAL_HAVE_DL_SUPPORT
|
||||
/*
|
||||
* Private types; only necessary when we're dlopening components.
|
||||
*/
|
||||
typedef enum component_status {
|
||||
UNVISITED,
|
||||
FAILED_TO_LOAD,
|
||||
CHECKING_CYCLE,
|
||||
LOADED,
|
||||
|
||||
STATUS_MAX
|
||||
} component_status_t;
|
||||
|
||||
struct component_file_item_t {
|
||||
opal_list_item_t super;
|
||||
|
||||
char type[MCA_BASE_MAX_TYPE_NAME_LEN + 1];
|
||||
char name[MCA_BASE_MAX_COMPONENT_NAME_LEN + 1];
|
||||
char basename[OPAL_PATH_MAX + 1];
|
||||
char filename[OPAL_PATH_MAX + 1];
|
||||
component_status_t status;
|
||||
};
|
||||
typedef struct component_file_item_t component_file_item_t;
|
||||
|
||||
static OBJ_CLASS_INSTANCE(component_file_item_t, opal_list_item_t, NULL, NULL);
|
||||
|
||||
struct dependency_item_t {
|
||||
opal_list_item_t super;
|
||||
|
||||
component_file_item_t *di_component_file_item;
|
||||
};
|
||||
typedef struct dependency_item_t dependency_item_t;
|
||||
|
||||
static OBJ_CLASS_INSTANCE(dependency_item_t, opal_list_item_t, NULL, NULL);
|
||||
|
||||
#endif /* OPAL_HAVE_DL_SUPPORT */
|
||||
|
||||
|
||||
#if OPAL_HAVE_DL_SUPPORT
|
||||
/*
|
||||
* Private functions
|
||||
*/
|
||||
static void find_dyn_components(const char *path, const char *type,
|
||||
const char **names, bool include_mode,
|
||||
opal_list_t *found_components);
|
||||
static int save_filename(const char *filename, void *data);
|
||||
static int open_component(component_file_item_t *target_file,
|
||||
opal_list_t *found_components);
|
||||
static int check_opal_info(component_file_item_t *target_file,
|
||||
opal_list_t *dependencies,
|
||||
opal_list_t *found_components);
|
||||
static int check_dependency(char *line, component_file_item_t *target_file,
|
||||
opal_list_t *dependencies,
|
||||
opal_list_t *found_components);
|
||||
static void free_dependency_list(opal_list_t *dependencies);
|
||||
static void find_dyn_components(const char *path, mca_base_framework_t *framework,
|
||||
const char **names, bool include_mode);
|
||||
|
||||
/*
|
||||
* Private variables
|
||||
*/
|
||||
static const char *opal_info_suffix = ".ompi_info";
|
||||
static const char *key_dependency = "dependency=";
|
||||
static const char component_template[] = "mca_%s_";
|
||||
static opal_list_t found_files;
|
||||
static char **found_filenames = NULL;
|
||||
static char *last_path_to_use = NULL;
|
||||
#endif /* OPAL_HAVE_DL_SUPPORT */
|
||||
|
||||
static int component_find_check (const char *framework_name, char **requested_component_names, opal_list_t *components);
|
||||
static int component_find_check (mca_base_framework_t *framework, char **requested_component_names);
|
||||
|
||||
/*
|
||||
* Dummy structure for casting for open_only logic
|
||||
@ -152,55 +93,54 @@ static bool use_component(const bool include_mode,
|
||||
* Return one consolidated array of (mca_base_component_t*) pointing to all
|
||||
* available components.
|
||||
*/
|
||||
int mca_base_component_find(const char *directory, const char *type,
|
||||
const mca_base_component_t *static_components[],
|
||||
const char *requested_components,
|
||||
opal_list_t *found_components,
|
||||
bool open_dso_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;
|
||||
int i, ret;
|
||||
bool include_mode = true;
|
||||
int ret;
|
||||
|
||||
ret = mca_base_component_parse_requested (requested_components, &include_mode,
|
||||
&requested_component_names);
|
||||
if (OPAL_SUCCESS != ret) {
|
||||
return 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 */
|
||||
OBJ_CONSTRUCT(found_components, opal_list_t);
|
||||
for (i = 0; NULL != static_components &&
|
||||
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;
|
||||
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);
|
||||
}
|
||||
cli->cli_component = static_components[i];
|
||||
opal_list_append(found_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, type,
|
||||
(const char**)requested_component_names,
|
||||
include_mode, found_components);
|
||||
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",
|
||||
type);
|
||||
framework->framework_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (include_mode) {
|
||||
ret = component_find_check (type, requested_component_names, found_components);
|
||||
ret = component_find_check (framework, requested_component_names);
|
||||
} else {
|
||||
ret = OPAL_SUCCESS;
|
||||
}
|
||||
@ -218,22 +158,13 @@ component_find_out:
|
||||
|
||||
int mca_base_component_find_finalize(void)
|
||||
{
|
||||
#if OPAL_HAVE_DL_SUPPORT
|
||||
if (NULL != found_filenames) {
|
||||
opal_argv_free(found_filenames);
|
||||
found_filenames = NULL;
|
||||
}
|
||||
if (NULL != last_path_to_use) {
|
||||
free(last_path_to_use);
|
||||
last_path_to_use = NULL;
|
||||
}
|
||||
#endif
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
int mca_base_components_filter (const char *framework_name, opal_list_t *components, int output_id,
|
||||
const char *filter_names, uint32_t filter_flags)
|
||||
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;
|
||||
@ -241,12 +172,12 @@ int mca_base_components_filter (const char *framework_name, opal_list_t *compone
|
||||
|
||||
assert (NULL != components);
|
||||
|
||||
if (0 == filter_flags && NULL == filter_names) {
|
||||
if (0 == filter_flags && NULL == framework->framework_selection) {
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
ret = mca_base_component_parse_requested (filter_names, &include_mode,
|
||||
&requested_component_names);
|
||||
ret = mca_base_component_parse_requested (framework->framework_selection, &include_mode,
|
||||
&requested_component_names);
|
||||
if (OPAL_SUCCESS != ret) {
|
||||
return ret;
|
||||
}
|
||||
@ -284,7 +215,7 @@ int mca_base_components_filter (const char *framework_name, opal_list_t *compone
|
||||
}
|
||||
|
||||
if (include_mode) {
|
||||
ret = component_find_check (framework_name, requested_component_names, components);
|
||||
ret = component_find_check (framework, requested_component_names);
|
||||
} else {
|
||||
ret = OPAL_SUCCESS;
|
||||
}
|
||||
@ -306,625 +237,31 @@ int mca_base_components_filter (const char *framework_name, opal_list_t *compone
|
||||
* 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, const char *type_name,
|
||||
const char **names, bool include_mode,
|
||||
opal_list_t *found_components)
|
||||
static void find_dyn_components(const char *path, mca_base_framework_t *framework,
|
||||
const char **names, bool include_mode)
|
||||
{
|
||||
int i, len;
|
||||
char *path_to_use = NULL, *dir, *end;
|
||||
component_file_item_t *file;
|
||||
opal_list_item_t *cur;
|
||||
char prefix[32 + MCA_BASE_MAX_TYPE_NAME_LEN], *basename;
|
||||
mca_base_component_repository_item_t *ri;
|
||||
opal_list_t *dy_components;
|
||||
int ret;
|
||||
|
||||
/* If path is NULL, iterate over the set of directories specified by
|
||||
the MCA param mca_base_component_path. If path is not NULL, then
|
||||
use that as the path. */
|
||||
|
||||
if (NULL == path) {
|
||||
if (NULL != mca_base_component_path) {
|
||||
path_to_use = strdup (mca_base_component_path);
|
||||
} else {
|
||||
/* If there's no path, then there's nothing to search -- we're
|
||||
done */
|
||||
if (NULL != path) {
|
||||
ret = mca_base_component_repository_add (path);
|
||||
if (OPAL_SUCCESS != ret) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
path_to_use = strdup(path);
|
||||
}
|
||||
if (NULL == path_to_use) {
|
||||
/* out of memory */
|
||||
|
||||
ret = mca_base_component_repository_get_components (framework, &dy_components);
|
||||
if (OPAL_SUCCESS != ret) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we haven't done so already, iterate over all the files in
|
||||
the directories in the path and make a master array of all the
|
||||
matching filenames that we find. Save the filenames in an
|
||||
argv-style array. Re-scan do this if the mca_component_path
|
||||
has changed. */
|
||||
if (NULL == found_filenames ||
|
||||
(NULL != last_path_to_use &&
|
||||
0 != strcmp(path_to_use, last_path_to_use))) {
|
||||
if (NULL != found_filenames) {
|
||||
opal_argv_free(found_filenames);
|
||||
found_filenames = NULL;
|
||||
free(last_path_to_use);
|
||||
last_path_to_use = NULL;
|
||||
}
|
||||
if (NULL == last_path_to_use) {
|
||||
last_path_to_use = strdup(path_to_use);
|
||||
}
|
||||
|
||||
dir = path_to_use;
|
||||
if (NULL != dir) {
|
||||
do {
|
||||
end = strchr(dir, OPAL_ENV_SEP);
|
||||
if (NULL != end) {
|
||||
*end = '\0';
|
||||
}
|
||||
if ((0 == strcmp(dir, "USER_DEFAULT") ||
|
||||
0 == strcmp(dir, "USR_DEFAULT"))
|
||||
&& NULL != mca_base_user_default_path) {
|
||||
if (0 != opal_dl_foreachfile(mca_base_user_default_path,
|
||||
save_filename, NULL)) {
|
||||
break;
|
||||
}
|
||||
} else if (0 == strcmp(dir, "SYS_DEFAULT") ||
|
||||
0 == strcmp(dir, "SYSTEM_DEFAULT")) {
|
||||
if (0 != opal_dl_foreachfile(mca_base_system_default_path,
|
||||
save_filename, NULL)) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (0 != opal_dl_foreachfile(dir, save_filename, NULL)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
dir = end + 1;
|
||||
} while (NULL != end);
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/* Look through the list of found files and find those that match
|
||||
the desired framework name */
|
||||
snprintf(prefix, sizeof(prefix) - 1, component_template, type_name);
|
||||
len = strlen(prefix);
|
||||
OBJ_CONSTRUCT(&found_files, opal_list_t);
|
||||
for (i = 0; NULL != found_filenames && NULL != found_filenames[i]; ++i) {
|
||||
basename = strrchr(found_filenames[i], '/');
|
||||
if (NULL == basename) {
|
||||
basename = found_filenames[i];
|
||||
} else {
|
||||
basename += 1;
|
||||
}
|
||||
|
||||
if (0 != strncmp(basename, prefix, len)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We found a match; save all the relevant details in the
|
||||
found_files list */
|
||||
file = OBJ_NEW(component_file_item_t);
|
||||
if (NULL == file) {
|
||||
free(path_to_use);
|
||||
return;
|
||||
}
|
||||
strncpy(file->type, type_name, MCA_BASE_MAX_TYPE_NAME_LEN);
|
||||
file->type[MCA_BASE_MAX_TYPE_NAME_LEN] = '\0';
|
||||
strncpy(file->name, basename + len, MCA_BASE_MAX_COMPONENT_NAME_LEN);
|
||||
file->name[MCA_BASE_MAX_COMPONENT_NAME_LEN] = '\0';
|
||||
strncpy(file->basename, basename, OPAL_PATH_MAX);
|
||||
file->basename[OPAL_PATH_MAX] = '\0';
|
||||
strncpy(file->filename, found_filenames[i], OPAL_PATH_MAX);
|
||||
file->filename[OPAL_PATH_MAX] = '\0';
|
||||
file->status = UNVISITED;
|
||||
|
||||
opal_list_append(&found_files, (opal_list_item_t *)
|
||||
file);
|
||||
}
|
||||
|
||||
/* Iterate through all the filenames that we found that matched
|
||||
the framework we were looking for. Since one component may
|
||||
[try to] call another to be loaded, only try to load the
|
||||
UNVISITED files. Also, ignore the return code -- basically,
|
||||
give every file one chance to try to load. If they load,
|
||||
great. If not, great. */
|
||||
for (cur = opal_list_get_first(&found_files);
|
||||
opal_list_get_end(&found_files) != cur;
|
||||
cur = opal_list_get_next(cur)) {
|
||||
file = (component_file_item_t *) cur;
|
||||
|
||||
if( UNVISITED == file->status ) {
|
||||
bool op = true;
|
||||
file->status = CHECKING_CYCLE;
|
||||
|
||||
op = use_component(include_mode, names, file->name);
|
||||
if( true == op ) {
|
||||
open_component(file, found_components);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* So now we have a final list of loaded components. We can free all
|
||||
the file information. */
|
||||
for (cur = opal_list_remove_first(&found_files);
|
||||
NULL != cur;
|
||||
cur = opal_list_remove_first(&found_files)) {
|
||||
OBJ_RELEASE(cur);
|
||||
}
|
||||
OBJ_DESTRUCT(&found_files);
|
||||
|
||||
/* All done, now let's cleanup */
|
||||
free(path_to_use);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Blindly save all filenames into an argv-style list. This function
|
||||
* is the callback from lt_dlforeachfile().
|
||||
*/
|
||||
static int save_filename(const char *filename, void *data)
|
||||
{
|
||||
opal_argv_append_nosize(&found_filenames, filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int file_exists(const char *filename, const char *ext)
|
||||
{
|
||||
char *final;
|
||||
struct stat buf;
|
||||
int ret;
|
||||
|
||||
if (NULL != ext) {
|
||||
asprintf(&final, "%s.%s", filename, ext);
|
||||
} else {
|
||||
final = strdup(filename);
|
||||
}
|
||||
if (NULL == final) {
|
||||
return 0;
|
||||
}
|
||||
ret = stat(final, &buf);
|
||||
free(final);
|
||||
return (0 == ret ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Open a component, chasing down its dependencies first, if possible.
|
||||
*/
|
||||
static int open_component(component_file_item_t *target_file,
|
||||
opal_list_t *found_components)
|
||||
{
|
||||
opal_dl_handle_t *component_handle;
|
||||
mca_base_component_t *component_struct;
|
||||
char *struct_name;
|
||||
opal_list_t dependencies;
|
||||
opal_list_item_t *cur;
|
||||
mca_base_component_list_item_t *mitem;
|
||||
dependency_item_t *ditem;
|
||||
size_t len;
|
||||
int vl;
|
||||
|
||||
opal_output_verbose(40, 0, "mca: base: component_find: examining dyanmic %s MCA component \"%s\"",
|
||||
target_file->type, target_file->name);
|
||||
opal_output_verbose(40, 0, "mca: base: component_find: %s", target_file->filename);
|
||||
|
||||
vl = mca_base_component_show_load_errors ? 0 : 40;
|
||||
|
||||
/* Was this component already loaded (e.g., via dependency)? */
|
||||
|
||||
if (LOADED == target_file->status) {
|
||||
opal_output_verbose(40, 0, "mca: base: component_find: already loaded (ignored)");
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* Ensure that this component is not already loaded (should only happen
|
||||
if it was statically loaded). It's an error if it's already
|
||||
loaded because we're evaluating this file -- not this component.
|
||||
Hence, returning OPAL_ERR_PARAM indicates that the *file* failed
|
||||
to load, not the component. */
|
||||
|
||||
for (cur = opal_list_get_first(found_components);
|
||||
opal_list_get_end(found_components) != cur;
|
||||
cur = opal_list_get_next(cur)) {
|
||||
mitem = (mca_base_component_list_item_t *) cur;
|
||||
if (0 == strcmp(mitem->cli_component->mca_type_name, target_file->type) &&
|
||||
0 == strcmp(mitem->cli_component->mca_component_name, target_file->name)) {
|
||||
opal_output_verbose(40, 0, "mca: base: component_find: already loaded (ignored)");
|
||||
target_file->status = FAILED_TO_LOAD;
|
||||
return OPAL_ERR_BAD_PARAM;
|
||||
}
|
||||
}
|
||||
|
||||
/* Look at see if this component has any dependencies. If so, load
|
||||
them. If we can't load them, then this component must also fail to
|
||||
load. */
|
||||
|
||||
OBJ_CONSTRUCT(&dependencies, opal_list_t);
|
||||
if (0 != check_opal_info(target_file, &dependencies, found_components)) {
|
||||
target_file->status = FAILED_TO_LOAD;
|
||||
free_dependency_list(&dependencies);
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
|
||||
/* Now try to load the component */
|
||||
|
||||
char *err_msg;
|
||||
if (OPAL_SUCCESS !=
|
||||
opal_dl_open(target_file->filename, true, false, &component_handle,
|
||||
&err_msg)) {
|
||||
if (NULL != err_msg) {
|
||||
err_msg = strdup(err_msg);
|
||||
} else {
|
||||
err_msg = strdup("opal_dl_open() error message was NULL!");
|
||||
}
|
||||
/* Because libltdl erroneously says "file not found" for any
|
||||
type of error -- which is especially misleading when the file
|
||||
is actually there but cannot be opened for some other reason
|
||||
(e.g., missing symbol) -- do some simple huersitics and if
|
||||
the file [probably] does exist, print a slightly better error
|
||||
message. */
|
||||
if (0 == strcmp("file not found", err_msg) &&
|
||||
(file_exists(target_file->filename, "lo") ||
|
||||
file_exists(target_file->filename, "so") ||
|
||||
file_exists(target_file->filename, "dylib") ||
|
||||
file_exists(target_file->filename, "dll"))) {
|
||||
free(err_msg);
|
||||
err_msg = strdup("perhaps a missing symbol, or compiled for a different version of Open MPI?");
|
||||
}
|
||||
opal_output_verbose(vl, 0, "mca: base: component_find: unable to open %s: %s (ignored)",
|
||||
target_file->filename, err_msg);
|
||||
free(err_msg);
|
||||
target_file->status = FAILED_TO_LOAD;
|
||||
free_dependency_list(&dependencies);
|
||||
return OPAL_ERR_BAD_PARAM;
|
||||
}
|
||||
|
||||
/* Successfully opened the component; now find the public struct.
|
||||
Malloc out enough space for it. */
|
||||
|
||||
len = strlen(target_file->type) + strlen(target_file->name) + 32;
|
||||
struct_name = (char*)malloc(len);
|
||||
if (NULL == struct_name) {
|
||||
opal_dl_close(component_handle);
|
||||
target_file->status = FAILED_TO_LOAD;
|
||||
free_dependency_list(&dependencies);
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
snprintf(struct_name, len, "mca_%s_%s_component", target_file->type,
|
||||
target_file->name);
|
||||
|
||||
mitem = OBJ_NEW(mca_base_component_list_item_t);
|
||||
if (NULL == mitem) {
|
||||
free(struct_name);
|
||||
opal_dl_close(component_handle);
|
||||
target_file->status = FAILED_TO_LOAD;
|
||||
free_dependency_list(&dependencies);
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
|
||||
if (OPAL_SUCCESS != opal_dl_lookup(component_handle, struct_name,
|
||||
(void**) &component_struct, &err_msg) ||
|
||||
NULL == component_struct) {
|
||||
if (NULL == err_msg) {
|
||||
err_msg = "opal_dl_loookup() error message was NULL!";
|
||||
}
|
||||
opal_output_verbose(vl, 0, "mca: base: component_find: \"%s\" does not appear to be a valid "
|
||||
"%s MCA dynamic component (ignored): %s",
|
||||
target_file->basename, target_file->type, err_msg);
|
||||
free(mitem);
|
||||
free(struct_name);
|
||||
opal_dl_close(component_handle);
|
||||
target_file->status = FAILED_TO_LOAD;
|
||||
free_dependency_list(&dependencies);
|
||||
return OPAL_ERR_BAD_PARAM;
|
||||
}
|
||||
|
||||
/* We found the public struct. Make sure its MCA major.minor
|
||||
version is the same as ours. */
|
||||
if (!(MCA_BASE_VERSION_MAJOR == component_struct->mca_major_version &&
|
||||
MCA_BASE_VERSION_MINOR == component_struct->mca_minor_version)) {
|
||||
opal_output_verbose(vl, 0, "mca: base: component_find: %s \"%s\" uses an MCA interface that is not recognized (component MCA v%d.%d.%d != supported MCA v%d.%d.%d) -- ignored",
|
||||
target_file->type, target_file->basename,
|
||||
component_struct->mca_major_version,
|
||||
component_struct->mca_minor_version,
|
||||
component_struct->mca_release_version,
|
||||
MCA_BASE_VERSION_MAJOR,
|
||||
MCA_BASE_VERSION_MINOR,
|
||||
MCA_BASE_VERSION_RELEASE);
|
||||
free(mitem);
|
||||
free(struct_name);
|
||||
opal_dl_close(component_handle);
|
||||
target_file->status = FAILED_TO_LOAD;
|
||||
free_dependency_list(&dependencies);
|
||||
return OPAL_ERR_BAD_PARAM;
|
||||
}
|
||||
|
||||
/* Also check that the component struct framework and component
|
||||
names match the expected names from the filename */
|
||||
if (0 != strcmp(component_struct->mca_type_name, target_file->type) ||
|
||||
0 != strcmp(component_struct->mca_component_name, target_file->name)) {
|
||||
opal_output_verbose(vl, 0, "Component file data does not match filename: %s (%s / %s) != %s %s -- ignored",
|
||||
target_file->filename, target_file->type, target_file->name,
|
||||
component_struct->mca_type_name,
|
||||
component_struct->mca_component_name);
|
||||
free(mitem);
|
||||
free(struct_name);
|
||||
opal_dl_close(component_handle);
|
||||
target_file->status = FAILED_TO_LOAD;
|
||||
free_dependency_list(&dependencies);
|
||||
return OPAL_ERR_BAD_PARAM;
|
||||
}
|
||||
|
||||
/* Alles gut. Save the component struct, and register this
|
||||
component to be closed later. */
|
||||
|
||||
mitem->cli_component = component_struct;
|
||||
opal_list_append(found_components, (opal_list_item_t *) mitem);
|
||||
mca_base_component_repository_retain(target_file->type, component_handle,
|
||||
component_struct);
|
||||
|
||||
/* Now that that's all done, link all the dependencies in to this
|
||||
component's repository entry */
|
||||
|
||||
for (cur = opal_list_remove_first(&dependencies);
|
||||
NULL != cur;
|
||||
cur = opal_list_remove_first(&dependencies)) {
|
||||
ditem = (dependency_item_t *) cur;
|
||||
mca_base_component_repository_link(target_file->type,
|
||||
target_file->name,
|
||||
ditem->di_component_file_item->type,
|
||||
ditem->di_component_file_item->name);
|
||||
OBJ_RELEASE(ditem);
|
||||
}
|
||||
OBJ_DESTRUCT(&dependencies);
|
||||
|
||||
opal_output_verbose(40, 0, "mca: base: component_find: opened dynamic %s MCA component \"%s\"",
|
||||
target_file->type, target_file->name);
|
||||
target_file->status = LOADED;
|
||||
|
||||
/* All done */
|
||||
|
||||
free(struct_name);
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* For a given filename, see if there exists a filename.ompi_info, which
|
||||
* lists dependencies that must be loaded before this component is
|
||||
* loaded. If we find this file, try to load those components first.
|
||||
*
|
||||
* Detect dependency cycles and error out.
|
||||
*/
|
||||
static int check_opal_info(component_file_item_t *target_file,
|
||||
opal_list_t *dependencies,
|
||||
opal_list_t *found_components)
|
||||
{
|
||||
size_t len;
|
||||
FILE *fp;
|
||||
char *depname;
|
||||
char buffer[BUFSIZ], *p;
|
||||
|
||||
/* Form the filename */
|
||||
|
||||
len = strlen(target_file->filename) + strlen(opal_info_suffix) + 16;
|
||||
depname = (char*)malloc(len);
|
||||
if (NULL == depname)
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
snprintf(depname, len, "%s%s", target_file->filename, opal_info_suffix);
|
||||
|
||||
/* Try to open the file. If there's no file, return success (i.e.,
|
||||
there are no dependencies). */
|
||||
|
||||
if (NULL == (fp = fopen(depname, "r"))) {
|
||||
free(depname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Otherwise, loop reading the lines in the file and trying to load
|
||||
them. Return failure upon the first component that fails to
|
||||
load. */
|
||||
|
||||
opal_output_verbose(40, 0, "mca: base: component_find: opening .ompi_info file: %s", depname);
|
||||
while (NULL != fgets(buffer, BUFSIZ, fp)) {
|
||||
|
||||
/* Perl chomp */
|
||||
|
||||
buffer[BUFSIZ - 1] = '\0';
|
||||
len = strlen(buffer);
|
||||
if ('\n' == buffer[len - 1])
|
||||
buffer[len - 1] = '\0';
|
||||
|
||||
/* Ignore emtpy lines and lines beginning with "#" or "//" */
|
||||
|
||||
for (p = buffer; '\0' != p; ++p)
|
||||
if (!isspace(*p))
|
||||
break;
|
||||
|
||||
if ('\0' == *p)
|
||||
continue;
|
||||
else if (*p == '#' || ('/' == *p && '/' == *(p + 1)))
|
||||
continue;
|
||||
|
||||
/* Is it a dependency? */
|
||||
|
||||
else if (0 == strncasecmp(p, key_dependency, strlen(key_dependency))) {
|
||||
if (OPAL_SUCCESS != check_dependency(p + strlen(key_dependency),
|
||||
target_file, dependencies,
|
||||
found_components)) {
|
||||
fclose(fp);
|
||||
free(depname);
|
||||
|
||||
/* We can leave any successfully loaded dependencies; we might
|
||||
need them again later. But free the dependency list for
|
||||
this component, because since [at least] one of them didn't
|
||||
load, we have to pretend like all of them didn't load and
|
||||
disallow loading this component. So free the dependency
|
||||
list. */
|
||||
|
||||
free_dependency_list(dependencies);
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
opal_output_verbose(40, 0, "mca: base: component_find: ompi_info file closed (%s)",
|
||||
target_file->basename);
|
||||
|
||||
/* All done -- all depenencies satisfied */
|
||||
|
||||
fclose(fp);
|
||||
free(depname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* A DEPENDENCY key was found in the ompi_info file. Chase it down: see
|
||||
* if we've already got such a component loaded, or go try to load it if
|
||||
* it's not already loaded.
|
||||
*/
|
||||
static int check_dependency(char *line, component_file_item_t *target_file,
|
||||
opal_list_t *dependencies,
|
||||
opal_list_t *found_components)
|
||||
{
|
||||
bool happiness;
|
||||
char buffer[BUFSIZ];
|
||||
char *type, *name;
|
||||
int len;
|
||||
component_file_item_t *mitem;
|
||||
dependency_item_t *ditem;
|
||||
opal_list_item_t *cur;
|
||||
|
||||
/* Ensure that this was a valid dependency statement */
|
||||
|
||||
type = line;
|
||||
name = strchr(line, OPAL_ENV_SEP);
|
||||
if (NULL == name) {
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
*name = '\0';
|
||||
++name;
|
||||
|
||||
/* Form the name of the component to compare to */
|
||||
|
||||
if (strlen(type) + strlen(name) + 32 >= BUFSIZ) {
|
||||
target_file->status = FAILED_TO_LOAD;
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
snprintf(buffer, BUFSIZ, component_template, type);
|
||||
len = strlen(buffer);
|
||||
strncat(buffer, name, BUFSIZ - len);
|
||||
|
||||
/* Traverse down the list of files that we have, and see if we can
|
||||
find it */
|
||||
|
||||
mitem = NULL;
|
||||
target_file->status = CHECKING_CYCLE;
|
||||
for (happiness = false, cur = opal_list_get_first(&found_files);
|
||||
opal_list_get_end(&found_files) != cur;
|
||||
cur = opal_list_get_next(cur)) {
|
||||
mitem = (component_file_item_t *) cur;
|
||||
|
||||
/* Compare the name to the basename */
|
||||
|
||||
if (0 != strcmp(mitem->basename, buffer))
|
||||
continue;
|
||||
|
||||
/* Catch the bozo dependency on itself */
|
||||
|
||||
else if (mitem == target_file) {
|
||||
opal_output_verbose(40, 0,
|
||||
"mca: base: component_find: component depends on itself (ignored dependency)");
|
||||
happiness = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If it's loaded, great -- we're done (no need to check that
|
||||
dependency sub-tree) */
|
||||
|
||||
else if (LOADED == mitem->status) {
|
||||
opal_output_verbose(40, 0, "mca: base: component_find: dependency has already been loaded (%s)",
|
||||
mitem->basename);
|
||||
happiness = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If it's specifically not loaded (i.e., there was some kind of
|
||||
error when we tried to load it), then we cannot meet the
|
||||
dependencies. */
|
||||
|
||||
else if (FAILED_TO_LOAD == mitem->status) {
|
||||
opal_output_verbose(40, 0, "mca: base: component_find: dependency previously failed to load (%s)",
|
||||
mitem->basename);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we hit a cycle, return badness */
|
||||
|
||||
else if (CHECKING_CYCLE == mitem->status) {
|
||||
opal_output_verbose(40, 0, "mca: base: component_find: found cycle! (%s)",
|
||||
mitem->basename);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Otherwise, this dependency has not been looked at yet. Go try
|
||||
to load it. */
|
||||
|
||||
else if (UNVISITED == mitem->status) {
|
||||
opal_output_verbose(40, 0, "mca: base: component_find: loading dependency (%s)",
|
||||
mitem->basename);
|
||||
if (OPAL_SUCCESS == open_component(target_file, found_components)) {
|
||||
happiness = true;
|
||||
} else {
|
||||
opal_output_verbose(40, 0, "mca: base: component_find: dependency failed to load (%s)",
|
||||
mitem->basename);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Did we find the dependency? */
|
||||
|
||||
if (!happiness) {
|
||||
target_file->status = FAILED_TO_LOAD;
|
||||
return OPAL_ERR_BAD_PARAM;
|
||||
}
|
||||
|
||||
/* The dependency loaded properly. Increment its refcount so that
|
||||
it doesn't get unloaded before we get unloaded. The (NULL !=
|
||||
mitem) check is somewhat redundant -- we won't be here in this
|
||||
function unless there's dependencies to check, but a) it's safer
|
||||
to double check, and b) it fixes a compiler warning. :-) */
|
||||
|
||||
if (NULL != mitem) {
|
||||
ditem = OBJ_NEW(dependency_item_t);
|
||||
if (NULL == ditem) {
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
ditem->di_component_file_item = mitem;
|
||||
opal_list_append(dependencies, (opal_list_item_t*) ditem);
|
||||
}
|
||||
|
||||
/* All done -- all depenencies satisfied */
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Free a dependency list
|
||||
*/
|
||||
static void free_dependency_list(opal_list_t *dependencies)
|
||||
{
|
||||
opal_list_item_t *item;
|
||||
|
||||
for (item = opal_list_remove_first(dependencies);
|
||||
NULL != item;
|
||||
item = opal_list_remove_first(dependencies)) {
|
||||
OBJ_RELEASE(item);
|
||||
}
|
||||
OBJ_DESTRUCT(dependencies);
|
||||
}
|
||||
|
||||
#endif /* OPAL_HAVE_DL_SUPPORT */
|
||||
@ -970,13 +307,16 @@ static bool use_component(const bool include_mode,
|
||||
|
||||
/* Ensure that *all* requested components exist. Print a warning
|
||||
and abort if they do not. */
|
||||
static int component_find_check (const char *framework_name, char **requested_component_names, opal_list_t *components)
|
||||
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;
|
||||
int i;
|
||||
|
||||
for (i = 0; NULL != requested_component_names &&
|
||||
NULL != requested_component_names[i]; ++i) {
|
||||
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) {
|
||||
@ -992,7 +332,7 @@ static int component_find_check (const char *framework_name, char **requested_co
|
||||
gethostname(h, sizeof(h));
|
||||
opal_show_help("help-mca-base.txt",
|
||||
"find-available:not-valid", true,
|
||||
h, framework_name, requested_component_names[i]);
|
||||
h, framework->framework_name, requested_component_names[i]);
|
||||
return OPAL_ERR_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* -*- 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
|
||||
@ -10,6 +11,8 @@
|
||||
* 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) 2015 Los Alamos National Security, LLC. All rights
|
||||
* reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -32,36 +35,18 @@
|
||||
#include "opal/mca/base/mca_base_component_repository.h"
|
||||
#include "opal/mca/dl/base/base.h"
|
||||
#include "opal/constants.h"
|
||||
#include "opal/class/opal_hash_table.h"
|
||||
#include "opal/util/basename.h"
|
||||
|
||||
#if OPAL_HAVE_DL_SUPPORT
|
||||
|
||||
/*
|
||||
* Private types
|
||||
*/
|
||||
struct repository_item_t {
|
||||
opal_list_item_t super;
|
||||
|
||||
char ri_type[MCA_BASE_MAX_TYPE_NAME_LEN + 1];
|
||||
opal_dl_handle_t *ri_dlhandle;
|
||||
const mca_base_component_t *ri_component_struct;
|
||||
opal_list_t ri_dependencies;
|
||||
};
|
||||
typedef struct repository_item_t repository_item_t;
|
||||
static void ri_constructor(opal_object_t *obj);
|
||||
static void ri_destructor(opal_object_t *obj);
|
||||
static OBJ_CLASS_INSTANCE(repository_item_t, opal_list_item_t,
|
||||
ri_constructor, ri_destructor);
|
||||
|
||||
struct dependency_item_t {
|
||||
opal_list_item_t super;
|
||||
|
||||
repository_item_t *di_repository_entry;
|
||||
};
|
||||
typedef struct dependency_item_t dependency_item_t;
|
||||
static void di_constructor(opal_object_t *obj);
|
||||
static void di_destructor(opal_object_t *obj);
|
||||
static OBJ_CLASS_INSTANCE(dependency_item_t, opal_list_item_t,
|
||||
di_constructor, di_destructor);
|
||||
static void ri_constructor(mca_base_component_repository_item_t *ri);
|
||||
static void ri_destructor(mca_base_component_repository_item_t *ri);
|
||||
OBJ_CLASS_INSTANCE(mca_base_component_repository_item_t, opal_list_item_t,
|
||||
ri_constructor, ri_destructor);
|
||||
|
||||
#endif /* OPAL_HAVE_DL_SUPPORT */
|
||||
|
||||
@ -74,17 +59,149 @@ static bool initialized = false;
|
||||
|
||||
#if OPAL_HAVE_DL_SUPPORT
|
||||
|
||||
static opal_list_t repository;
|
||||
static opal_hash_table_t mca_base_component_repository;
|
||||
|
||||
/* two-level macro for stringifying a number */
|
||||
#define STRINGIFYX(x) #x
|
||||
#define STRINGIFY(x) STRINGIFYX(x)
|
||||
|
||||
/*
|
||||
* Private functions
|
||||
*/
|
||||
static repository_item_t *find_component(const char *type, const char *name);
|
||||
static int link_items(repository_item_t *src, repository_item_t *depend);
|
||||
static int process_repository_item (const char *filename, void *data)
|
||||
{
|
||||
char name[MCA_BASE_MAX_COMPONENT_NAME_LEN + 1];
|
||||
char type[MCA_BASE_MAX_TYPE_NAME_LEN + 1];
|
||||
mca_base_component_repository_item_t *ri;
|
||||
opal_list_t *component_list;
|
||||
char *base;
|
||||
int ret;
|
||||
|
||||
base = opal_basename (filename);
|
||||
if (NULL == base) {
|
||||
return OPAL_ERROR;
|
||||
}
|
||||
|
||||
/* check if the plugin has the appropriate prefix */
|
||||
if (0 != strncmp (base, "mca_", 4)) {
|
||||
free (base);
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* read framework and component names. framework names may not include an _
|
||||
* but component names may */
|
||||
ret = sscanf (base, "mca_%" STRINGIFY(MCA_BASE_MAX_TYPE_NAME_LEN) "[^_]_%"
|
||||
STRINGIFY(MCA_BASE_MAX_COMPONENT_NAME_LEN) "s", type, name);
|
||||
if (0 > ret) {
|
||||
/* does not patch the expected template. skip */
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* lookup the associated framework list and create if it doesn't already exist */
|
||||
ret = opal_hash_table_get_value_ptr (&mca_base_component_repository, type,
|
||||
strlen (type), (void **) &component_list);
|
||||
if (OPAL_SUCCESS != ret) {
|
||||
component_list = OBJ_NEW(opal_list_t);
|
||||
if (NULL == component_list) {
|
||||
free (base);
|
||||
/* OOM. nothing to do but fail */
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
|
||||
ret = opal_hash_table_set_value_ptr (&mca_base_component_repository, type,
|
||||
strlen (type), (void *) component_list);
|
||||
if (OPAL_SUCCESS != ret) {
|
||||
free (base);
|
||||
OBJ_RELEASE(component_list);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for duplicate components */
|
||||
OPAL_LIST_FOREACH(ri, component_list, mca_base_component_repository_item_t) {
|
||||
if (0 == strcmp (ri->ri_name, name)) {
|
||||
/* already scanned this component */
|
||||
free (base);
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
ri = OBJ_NEW(mca_base_component_repository_item_t);
|
||||
if (NULL == ri) {
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
|
||||
ri->ri_base = base;
|
||||
|
||||
ri->ri_path = strdup (filename);
|
||||
if (NULL == ri->ri_path) {
|
||||
OBJ_RELEASE(ri);
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
|
||||
/* strncpy does not guarantee a \0 */
|
||||
ri->ri_type[MCA_BASE_MAX_TYPE_NAME_LEN] = '\0';
|
||||
strncpy (ri->ri_type, type, MCA_BASE_MAX_TYPE_NAME_LEN);
|
||||
|
||||
ri->ri_name[MCA_BASE_MAX_TYPE_NAME_LEN] = '\0';
|
||||
strncpy (ri->ri_name, name, MCA_BASE_MAX_COMPONENT_NAME_LEN);
|
||||
|
||||
opal_list_append (component_list, &ri->super);
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
static int file_exists(const char *filename, const char *ext)
|
||||
{
|
||||
char *final;
|
||||
int ret;
|
||||
|
||||
if (NULL == ext) {
|
||||
return access (filename, F_OK) == 0;
|
||||
}
|
||||
|
||||
ret = asprintf(&final, "%s.%s", filename, ext);
|
||||
if (0 > ret || NULL == final) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = access (final, F_OK);
|
||||
free(final);
|
||||
return (0 == ret);
|
||||
}
|
||||
|
||||
#endif /* OPAL_HAVE_DL_SUPPORT */
|
||||
|
||||
int mca_base_component_repository_add (const char *path)
|
||||
{
|
||||
#if OPAL_HAVE_DL_SUPPORT
|
||||
char *path_to_use = NULL, *dir, *ctx;
|
||||
const char sep[] = {OPAL_ENV_SEP, '\0'};
|
||||
|
||||
if (NULL == path) {
|
||||
/* nothing to do */
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
path_to_use = strdup (path);
|
||||
|
||||
dir = strtok_r (path_to_use, sep, &ctx);
|
||||
do {
|
||||
if ((0 == strcmp(dir, "USER_DEFAULT") || 0 == strcmp(dir, "USR_DEFAULT"))
|
||||
&& NULL != mca_base_user_default_path) {
|
||||
dir = mca_base_user_default_path;
|
||||
} else if (0 == strcmp(dir, "SYS_DEFAULT") ||
|
||||
0 == strcmp(dir, "SYSTEM_DEFAULT")) {
|
||||
dir = mca_base_system_default_path;
|
||||
}
|
||||
|
||||
if (0 != opal_dl_foreachfile(dir, process_repository_item, NULL)) {
|
||||
break;
|
||||
}
|
||||
} while (NULL != (dir = strtok_r (NULL, sep, &ctx)));
|
||||
|
||||
#endif /* OPAL_HAVE_DL_SUPPORT */
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the repository
|
||||
@ -105,7 +222,19 @@ int mca_base_component_repository_init(void)
|
||||
}
|
||||
opal_dl_base_select();
|
||||
|
||||
OBJ_CONSTRUCT(&repository, opal_list_t);
|
||||
OBJ_CONSTRUCT(&mca_base_component_repository, opal_hash_table_t);
|
||||
ret = opal_hash_table_init (&mca_base_component_repository, 128);
|
||||
if (OPAL_SUCCESS != ret) {
|
||||
mca_base_framework_close (&opal_dl_base_framework);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mca_base_component_repository_add (mca_base_component_path);
|
||||
if (OPAL_SUCCESS != ret) {
|
||||
OBJ_DESTRUCT(&mca_base_component_repository);
|
||||
mca_base_framework_close (&opal_dl_base_framework);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
initialized = true;
|
||||
@ -116,279 +245,282 @@ int mca_base_component_repository_init(void)
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add a newly-opened dyanmic component to the repository of open
|
||||
* components. The component's type, handle, and public struct are
|
||||
* saved.
|
||||
*/
|
||||
int mca_base_component_repository_retain(char *type,
|
||||
opal_dl_handle_t *component_handle,
|
||||
const mca_base_component_t *component_struct)
|
||||
int mca_base_component_repository_get_components (mca_base_framework_t *framework,
|
||||
opal_list_t **framework_components)
|
||||
{
|
||||
*framework_components = NULL;
|
||||
#if OPAL_HAVE_DL_SUPPORT
|
||||
repository_item_t *ri;
|
||||
|
||||
/* Allocate a new repository item */
|
||||
|
||||
ri = OBJ_NEW(repository_item_t);
|
||||
if (NULL == ri) {
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
|
||||
/* Initialize the repository item */
|
||||
|
||||
strncpy(ri->ri_type, type, MCA_BASE_MAX_TYPE_NAME_LEN);
|
||||
ri->ri_type[MCA_BASE_MAX_TYPE_NAME_LEN] = '\0';
|
||||
ri->ri_dlhandle = component_handle;
|
||||
ri->ri_component_struct = component_struct;
|
||||
|
||||
/* Append the new item to the repository */
|
||||
|
||||
opal_list_append(&repository, (opal_list_item_t *) ri);
|
||||
|
||||
/* All done */
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
#else
|
||||
return OPAL_ERR_NOT_SUPPORTED;
|
||||
return opal_hash_table_get_value_ptr (&mca_base_component_repository, framework->framework_name,
|
||||
strlen (framework->framework_name), (void **) framework_components);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Bump up the refcount on a component
|
||||
*/
|
||||
int mca_base_component_repository_retain_component(const char *type,
|
||||
const char *name)
|
||||
{
|
||||
#if OPAL_HAVE_DL_SUPPORT
|
||||
repository_item_t *ri = find_component(type, name);
|
||||
if (NULL != ri) {
|
||||
OBJ_RETAIN(ri);
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
return OPAL_ERR_NOT_FOUND;
|
||||
#else
|
||||
return OPAL_ERR_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void mca_base_component_repository_release_internal (mca_base_component_repository_item_t *ri) {
|
||||
int group_id;
|
||||
|
||||
/*
|
||||
* Create a dependency from one component entry to another
|
||||
*/
|
||||
int mca_base_component_repository_link(const char *src_type,
|
||||
const char *src_name,
|
||||
const char *depend_type,
|
||||
const char *depend_name)
|
||||
{
|
||||
#if OPAL_HAVE_DL_SUPPORT
|
||||
repository_item_t *src, *depend;
|
||||
group_id = mca_base_var_group_find (NULL, ri->ri_type, ri->ri_name);
|
||||
if (0 <= group_id) {
|
||||
/* ensure all variables are deregistered before we dlclose the component */
|
||||
mca_base_var_group_deregister (group_id);
|
||||
}
|
||||
|
||||
/* Look up the two components */
|
||||
|
||||
src = find_component(src_type, src_name);
|
||||
if (NULL == src) {
|
||||
return OPAL_ERR_BAD_PARAM;
|
||||
}
|
||||
depend = find_component(depend_type, depend_name);
|
||||
if (NULL == depend) {
|
||||
return OPAL_ERR_BAD_PARAM;
|
||||
}
|
||||
|
||||
/* Link them */
|
||||
|
||||
return link_items(src, depend);
|
||||
#else
|
||||
return OPAL_ERR_NOT_SUPPORTED;
|
||||
#endif
|
||||
/* Close the component (and potentially unload it from memory */
|
||||
if (ri->ri_dlhandle) {
|
||||
opal_dl_close(ri->ri_dlhandle);
|
||||
ri->ri_dlhandle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If it's in the repository, close a specified component and remove
|
||||
* it from the repository.
|
||||
*/
|
||||
void mca_base_component_repository_release(const mca_base_component_t *component)
|
||||
{
|
||||
#if OPAL_HAVE_DL_SUPPORT
|
||||
if (initialized) {
|
||||
repository_item_t *ri = find_component(component->mca_type_name,
|
||||
component->mca_component_name);
|
||||
if (NULL != ri) {
|
||||
OBJ_RELEASE(ri);
|
||||
mca_base_component_repository_item_t *ri;
|
||||
opal_list_t *component_list;
|
||||
int ret;
|
||||
|
||||
ret = opal_hash_table_get_value_ptr (&mca_base_component_repository, component->mca_type_name,
|
||||
strlen (component->mca_type_name), (void **) &component_list);
|
||||
if (OPAL_SUCCESS != ret) {
|
||||
/* component does not exist in the repository */
|
||||
return;
|
||||
}
|
||||
|
||||
OPAL_LIST_FOREACH(ri, component_list, mca_base_component_repository_item_t) {
|
||||
if (0 == strcmp (ri->ri_name, component->mca_component_name)) {
|
||||
/* go ahead and dlclose the component if it is open */
|
||||
mca_base_component_repository_release_internal (ri);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int mca_base_component_repository_open (mca_base_framework_t *framework,
|
||||
mca_base_component_repository_item_t *ri)
|
||||
{
|
||||
#if OPAL_HAVE_DL_SUPPORT
|
||||
mca_base_component_t *component_struct;
|
||||
mca_base_component_list_item_t *mitem = NULL;
|
||||
char *struct_name = NULL;
|
||||
int vl, ret;
|
||||
|
||||
opal_output_verbose(40, 0, "mca_base_component_repository_open: examining dynamic %s MCA component \"%s\" at path %s",
|
||||
ri->ri_type, ri->ri_name, ri->ri_path);
|
||||
|
||||
vl = mca_base_component_show_load_errors ? 0 : 40;
|
||||
|
||||
/* Ensure that this component is not already loaded (should only happen
|
||||
if it was statically loaded). It's an error if it's already
|
||||
loaded because we're evaluating this file -- not this component.
|
||||
Hence, returning OPAL_ERR_PARAM indicates that the *file* failed
|
||||
to load, not the component. */
|
||||
|
||||
OPAL_LIST_FOREACH(mitem, &framework->framework_components, mca_base_component_list_item_t) {
|
||||
if (0 == strcmp(mitem->cli_component->mca_component_name, ri->ri_name)) {
|
||||
opal_output_verbose(40, 0, "mca_base_component_repository_open: already loaded (ignored)");
|
||||
return OPAL_ERR_BAD_PARAM;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != ri->ri_dlhandle) {
|
||||
opal_output_verbose(40, 0, "mca_base_component_repository_open: already loaded. returning cached component");
|
||||
mitem = OBJ_NEW(mca_base_component_list_item_t);
|
||||
if (NULL == mitem) {
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
|
||||
mitem->cli_component = ri->ri_component_struct;
|
||||
opal_list_append (&framework->framework_components, &mitem->super);
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
if (0 != strcmp (ri->ri_type, framework->framework_name)) {
|
||||
/* shouldn't happen. attempting to open a component belonging to
|
||||
* another framework. if this happens it is likely a MCA base
|
||||
* bug so assert */
|
||||
assert (0);
|
||||
return OPAL_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* Now try to load the component */
|
||||
|
||||
char *err_msg = NULL;
|
||||
if (OPAL_SUCCESS != opal_dl_open(ri->ri_path, true, false, &ri->ri_dlhandle, &err_msg)) {
|
||||
if (NULL == err_msg) {
|
||||
err_msg = "opal_dl_open() error message was NULL!";
|
||||
}
|
||||
/* Because libltdl erroneously says "file not found" for any
|
||||
type of error -- which is especially misleading when the file
|
||||
is actually there but cannot be opened for some other reason
|
||||
(e.g., missing symbol) -- do some simple huersitics and if
|
||||
the file [probably] does exist, print a slightly better error
|
||||
message. */
|
||||
if (0 == strcasecmp("file not found", err_msg) &&
|
||||
(file_exists(ri->ri_path, "lo") ||
|
||||
file_exists(ri->ri_path, "so") ||
|
||||
file_exists(ri->ri_path, "dylib") ||
|
||||
file_exists(ri->ri_path, "dll"))) {
|
||||
err_msg = "perhaps a missing symbol, or compiled for a different version of Open MPI?";
|
||||
}
|
||||
opal_output_verbose(vl, 0, "mca_base_component_repository_open: unable to open %s: %s (ignored)",
|
||||
ri->ri_base, err_msg);
|
||||
return OPAL_ERR_BAD_PARAM;
|
||||
}
|
||||
|
||||
/* Successfully opened the component; now find the public struct.
|
||||
Malloc out enough space for it. */
|
||||
|
||||
do {
|
||||
ret = asprintf (&struct_name, "mca_%s_%s_component", ri->ri_type, ri->ri_name);
|
||||
if (0 > ret) {
|
||||
ret = OPAL_ERR_OUT_OF_RESOURCE;
|
||||
break;
|
||||
}
|
||||
|
||||
mitem = OBJ_NEW(mca_base_component_list_item_t);
|
||||
if (NULL == mitem) {
|
||||
ret = OPAL_ERR_OUT_OF_RESOURCE;
|
||||
break;
|
||||
}
|
||||
|
||||
err_msg = NULL;
|
||||
ret = opal_dl_lookup(ri->ri_dlhandle, struct_name, (void**) &component_struct, &err_msg);
|
||||
if (OPAL_SUCCESS != ret || NULL == component_struct) {
|
||||
if (NULL == err_msg) {
|
||||
err_msg = "opal_dl_loookup() error message was NULL!";
|
||||
}
|
||||
opal_output_verbose(vl, 0, "mca_base_component_repository_open: \"%s\" does not appear to be a valid "
|
||||
"%s MCA dynamic component (ignored): %s. ret %d", ri->ri_base, ri->ri_type, err_msg, ret);
|
||||
|
||||
ret = OPAL_ERR_BAD_PARAM;
|
||||
break;
|
||||
}
|
||||
|
||||
/* done with the structure name */
|
||||
free (struct_name);
|
||||
|
||||
/* We found the public struct. Make sure its MCA major.minor
|
||||
version is the same as ours. TODO -- add checks for project version (from framework) */
|
||||
if (!(MCA_BASE_VERSION_MAJOR == component_struct->mca_major_version &&
|
||||
MCA_BASE_VERSION_MINOR == component_struct->mca_minor_version)) {
|
||||
opal_output_verbose(vl, 0, "mca_base_component_repository_open: %s \"%s\" uses an MCA interface that is "
|
||||
"not recognized (component MCA v%d.%d.%d != supported MCA v%d.%d.%d) -- ignored",
|
||||
ri->ri_type, ri->ri_path, component_struct->mca_major_version,
|
||||
component_struct->mca_minor_version, component_struct->mca_release_version,
|
||||
MCA_BASE_VERSION_MAJOR, MCA_BASE_VERSION_MINOR, MCA_BASE_VERSION_RELEASE);
|
||||
ret = OPAL_ERR_BAD_PARAM;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Also check that the component struct framework and component
|
||||
names match the expected names from the filename */
|
||||
if (0 != strcmp(component_struct->mca_type_name, ri->ri_type) ||
|
||||
0 != strcmp(component_struct->mca_component_name, ri->ri_name)) {
|
||||
opal_output_verbose(vl, 0, "Component file data does not match filename: %s (%s / %s) != %s %s -- ignored",
|
||||
ri->ri_path, ri->ri_type, ri->ri_name,
|
||||
component_struct->mca_type_name,
|
||||
component_struct->mca_component_name);
|
||||
ret = OPAL_ERR_BAD_PARAM;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Alles gut. Save the component struct, and register this
|
||||
component to be closed later. */
|
||||
|
||||
ri->ri_component_struct = mitem->cli_component = component_struct;
|
||||
opal_list_append(&framework->framework_components, &mitem->super);
|
||||
|
||||
opal_output_verbose(40, 0, "mca_base_component_repository_open: opened dynamic %s MCA component \"%s\"",
|
||||
ri->ri_type, ri->ri_name);
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
} while (0);
|
||||
|
||||
if (mitem) {
|
||||
OBJ_RELEASE(mitem);
|
||||
}
|
||||
|
||||
if (struct_name) {
|
||||
free (struct_name);
|
||||
}
|
||||
|
||||
opal_dl_close (ri->ri_dlhandle);
|
||||
ri->ri_dlhandle = NULL;
|
||||
|
||||
return ret;
|
||||
#else
|
||||
|
||||
/* no dlopen support */
|
||||
return OPAL_ERR_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Finalize the repository -- close everything that's still open.
|
||||
*/
|
||||
void mca_base_component_repository_finalize(void)
|
||||
{
|
||||
#if OPAL_HAVE_DL_SUPPORT
|
||||
repository_item_t *ri, *next;
|
||||
#endif
|
||||
|
||||
if (initialized) {
|
||||
#if OPAL_HAVE_DL_SUPPORT
|
||||
|
||||
/* Have to be slightly careful about this because of dependencies,
|
||||
particularly on OS's where it matters (i.e., closing a
|
||||
component that is depended on by other components actually
|
||||
causes missing symbols because the OS actually does unload it
|
||||
from memory!), such as OS X.
|
||||
|
||||
So instead of just blindly closing everything, we have iterate
|
||||
over the array of open components releasing everything with a
|
||||
refcount of 1 -- skip anything with a refcount of more than 1.
|
||||
Repeat this procedure until either we have nothing open or we
|
||||
made one full pass and no refcounts went to 1 (which is
|
||||
technically an error). */
|
||||
|
||||
do {
|
||||
OPAL_LIST_FOREACH_SAFE(ri, next, &repository, repository_item_t) {
|
||||
OBJ_RELEASE(ri);
|
||||
}
|
||||
} while (opal_list_get_size(&repository) > 0);
|
||||
|
||||
(void) mca_base_framework_close(&opal_dl_base_framework);
|
||||
#endif
|
||||
if (!initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
#if OPAL_HAVE_DL_SUPPORT
|
||||
opal_list_t *component_list;
|
||||
void *node, *key;
|
||||
size_t key_size;
|
||||
int ret;
|
||||
|
||||
ret = opal_hash_table_get_first_key_ptr (&mca_base_component_repository, &key, &key_size,
|
||||
(void **) &component_list, &node);
|
||||
while (OPAL_SUCCESS == ret) {
|
||||
OPAL_LIST_RELEASE(component_list);
|
||||
ret = opal_hash_table_get_next_key_ptr (&mca_base_component_repository, &key,
|
||||
&key_size, (void **) &component_list,
|
||||
node, &node);
|
||||
}
|
||||
|
||||
(void) mca_base_framework_close(&opal_dl_base_framework);
|
||||
OBJ_DESTRUCT(&mca_base_component_repository);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if OPAL_HAVE_DL_SUPPORT
|
||||
|
||||
static repository_item_t *find_component(const char *type, const char *name)
|
||||
{
|
||||
opal_list_item_t *item;
|
||||
repository_item_t *ri;
|
||||
|
||||
for (item = opal_list_get_first(&repository);
|
||||
opal_list_get_end(&repository) != item;
|
||||
item = opal_list_get_next(item)) {
|
||||
ri = (repository_item_t *) item;
|
||||
if (0 == strcmp(ri->ri_type, type) &&
|
||||
0 == strcmp(ri->ri_component_struct->mca_component_name, name)) {
|
||||
return ri;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int link_items(repository_item_t *src, repository_item_t *depend)
|
||||
{
|
||||
dependency_item_t *di;
|
||||
|
||||
/* Bozo check */
|
||||
|
||||
if (NULL == src || NULL == depend) {
|
||||
return OPAL_ERR_BAD_PARAM;
|
||||
}
|
||||
|
||||
/* Make a new depedency item */
|
||||
|
||||
di = OBJ_NEW(dependency_item_t);
|
||||
if (NULL == di) {
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
|
||||
/* Initialize the new dependency item */
|
||||
|
||||
di->di_repository_entry = depend;
|
||||
|
||||
/* Add it to the dependency list on the source repository entry */
|
||||
|
||||
opal_list_append(&src->ri_dependencies, (opal_list_item_t *) di);
|
||||
|
||||
/* Increment the refcount in the dependency */
|
||||
|
||||
OBJ_RETAIN(depend);
|
||||
|
||||
/* All done */
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Basic sentinel values, and construct the inner list
|
||||
*/
|
||||
static void ri_constructor(opal_object_t *obj)
|
||||
static void ri_constructor (mca_base_component_repository_item_t *ri)
|
||||
{
|
||||
repository_item_t *ri = (repository_item_t *) obj;
|
||||
|
||||
memset(ri->ri_type, 0, sizeof(ri->ri_type));
|
||||
ri->ri_dlhandle = NULL;
|
||||
ri->ri_component_struct = NULL;
|
||||
|
||||
OBJ_CONSTRUCT(&ri->ri_dependencies, opal_list_t);
|
||||
memset(ri->ri_type, 0, sizeof(ri->ri_type));
|
||||
ri->ri_dlhandle = NULL;
|
||||
ri->ri_component_struct = NULL;
|
||||
ri->ri_path = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Close a component
|
||||
*/
|
||||
static void ri_destructor(opal_object_t *obj)
|
||||
static void ri_destructor (mca_base_component_repository_item_t *ri)
|
||||
{
|
||||
repository_item_t *ri = (repository_item_t *) obj;
|
||||
opal_list_item_t *item;
|
||||
int group_id;
|
||||
/* dlclose the component if it is still open */
|
||||
mca_base_component_repository_release_internal (ri);
|
||||
|
||||
group_id = mca_base_var_group_find (NULL, ri->ri_type,
|
||||
ri->ri_component_struct->mca_component_name);
|
||||
if (0 <= group_id) {
|
||||
mca_base_var_group_deregister (group_id);
|
||||
}
|
||||
/* It should be obvious, but I'll state it anyway because it bit me
|
||||
during debugging: after the dlclose(), the mca_base_component_t
|
||||
pointer is no longer valid because it has [potentially] been
|
||||
unloaded from memory. So don't try to use it. :-) */
|
||||
|
||||
/* Close the component (and potentially unload it from memory */
|
||||
opal_dl_close(ri->ri_dlhandle);
|
||||
if (ri->ri_path) {
|
||||
free (ri->ri_path);
|
||||
}
|
||||
|
||||
/* It should be obvious, but I'll state it anyway because it bit me
|
||||
during debugging: after the dlclose(), the mca_base_component_t
|
||||
pointer is no longer valid because it has [potentially] been
|
||||
unloaded from memory. So don't try to use it. :-) */
|
||||
|
||||
/* Now go release/close (at a minimum: decrement the refcount) any
|
||||
dependencies of this component */
|
||||
|
||||
while (NULL != (item = opal_list_remove_first(&ri->ri_dependencies))) {
|
||||
OBJ_RELEASE(item);
|
||||
}
|
||||
OBJ_DESTRUCT(&ri->ri_dependencies);
|
||||
opal_list_remove_item(&repository, (opal_list_item_t *) ri);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Basic sentinel values
|
||||
*/
|
||||
static void di_constructor(opal_object_t *obj)
|
||||
{
|
||||
dependency_item_t *di = (dependency_item_t *) obj;
|
||||
|
||||
di->di_repository_entry = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* When a dependency item is released, go release the repository entry
|
||||
* that it points to
|
||||
*/
|
||||
static void di_destructor(opal_object_t *obj)
|
||||
{
|
||||
dependency_item_t *di = (dependency_item_t *) obj;
|
||||
|
||||
OBJ_RELEASE(di->di_repository_entry);
|
||||
if (ri->ri_base) {
|
||||
free (ri->ri_base);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OPAL_HAVE_DL_SUPPORT */
|
||||
|
@ -17,6 +17,19 @@
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file mca_base_component_repository.h
|
||||
*
|
||||
* This file provide the external interface to our base component
|
||||
* module. Most of the components that depend on it, will use the
|
||||
* retain_component() function to increase the reference count on a
|
||||
* particular component (as opposed to the retain() function, which is
|
||||
* internal to the opal/mca/base). But it's convenient to have all
|
||||
* the functions exported from one header file rather than to separate
|
||||
* retain_component() and retain() into two separate header files
|
||||
* (i.e., have a separate header file just for retain()).
|
||||
*/
|
||||
|
||||
#ifndef MCA_BASE_COMPONENT_REPOSITORY_H
|
||||
#define MCA_BASE_COMPONENT_REPOSITORY_H
|
||||
|
||||
@ -26,30 +39,70 @@
|
||||
#include "opal/mca/dl/base/base.h"
|
||||
|
||||
BEGIN_C_DECLS
|
||||
struct mca_base_component_repository_item_t {
|
||||
opal_list_item_t super;
|
||||
|
||||
OPAL_DECLSPEC int mca_base_component_repository_init(void);
|
||||
char ri_type[MCA_BASE_MAX_TYPE_NAME_LEN + 1];
|
||||
char ri_name[MCA_BASE_MAX_COMPONENT_NAME_LEN + 1];
|
||||
|
||||
/* This file provide the external interface to our base component
|
||||
* module. Most of the components that depend on it, will use the
|
||||
* retain_component() function to increase the reference count on a
|
||||
* particular component (as opposed to the retain() function, which is
|
||||
* internal to the opal/mca/base). But it's convenient to have all
|
||||
* the functions exported from one header file rather than to separate
|
||||
* retain_component() and retain() into two separate header files
|
||||
* (i.e., have a separate header file just for retain()).
|
||||
char *ri_path;
|
||||
char *ri_base;
|
||||
|
||||
opal_dl_handle_t *ri_dlhandle;
|
||||
const mca_base_component_t *ri_component_struct;
|
||||
};
|
||||
typedef struct mca_base_component_repository_item_t mca_base_component_repository_item_t;
|
||||
|
||||
OBJ_CLASS_DECLARATION(mca_base_component_repository_item_t);
|
||||
|
||||
/**
|
||||
* @brief initialize the component repository
|
||||
*
|
||||
* This function must be called before any frameworks are registered or
|
||||
* opened. It is responsible for setting up the repository of dynamically
|
||||
* loaded components. The initial search path is taken from the
|
||||
* mca_base_component_path MCA parameter. mca_base_open () is a
|
||||
* prerequisite call as it registers the mca_base_component_path parameter.
|
||||
*/
|
||||
OPAL_DECLSPEC int mca_base_component_repository_retain(char *type,
|
||||
opal_dl_handle_t *component_handle,
|
||||
const mca_base_component_t *component_struct);
|
||||
OPAL_DECLSPEC int mca_base_component_repository_init(void);
|
||||
|
||||
OPAL_DECLSPEC int mca_base_component_repository_retain_component(const char *type,
|
||||
const char *name);
|
||||
OPAL_DECLSPEC int mca_base_component_repository_link(const char *src_type,
|
||||
const char *src_name,
|
||||
const char *depend_type,
|
||||
const char *depend_name);
|
||||
OPAL_DECLSPEC void mca_base_component_repository_release(const mca_base_component_t *component);
|
||||
OPAL_DECLSPEC void mca_base_component_repository_finalize(void);
|
||||
/**
|
||||
* @brief add search path for dynamically loaded components
|
||||
*
|
||||
* @param[in] path delimited list of search paths to add
|
||||
*/
|
||||
OPAL_DECLSPEC int mca_base_component_repository_add (const char *path);
|
||||
|
||||
|
||||
/**
|
||||
* @brief return the list of components that match a given framework
|
||||
*
|
||||
* @param[in] framework framework to match
|
||||
* @param[out] framework_components components that match this framework
|
||||
*
|
||||
* The list returned in {framework_components} is owned by the component
|
||||
* repository and CAN NOT be modified by the caller.
|
||||
*/
|
||||
OPAL_DECLSPEC int mca_base_component_repository_get_components (mca_base_framework_t *framework,
|
||||
opal_list_t **framework_components);
|
||||
|
||||
/**
|
||||
* @brief finalize the mca component repository
|
||||
*/
|
||||
OPAL_DECLSPEC void mca_base_component_repository_finalize(void);
|
||||
|
||||
/**
|
||||
* @brief open the repository item and add it to the framework's component
|
||||
* list
|
||||
*
|
||||
* @param[in] framework framework that matches the component
|
||||
* @param[in] ri dynamic component to open
|
||||
*/
|
||||
int mca_base_component_repository_open (mca_base_framework_t *framework,
|
||||
mca_base_component_repository_item_t *ri);
|
||||
|
||||
|
||||
void mca_base_component_repository_release(const mca_base_component_t *component);
|
||||
|
||||
END_C_DECLS
|
||||
|
||||
|
@ -44,7 +44,7 @@ void mca_base_component_unload (const mca_base_component_t *component, int outpu
|
||||
mca_base_var_group_deregister (ret);
|
||||
}
|
||||
|
||||
mca_base_component_repository_release((mca_base_component_t *) component);
|
||||
mca_base_component_repository_release (component);
|
||||
}
|
||||
|
||||
void mca_base_component_close (const mca_base_component_t *component, int output_id)
|
||||
|
@ -11,7 +11,7 @@
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2008-2012 Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2011-2013 Los Alamos National Security, LLC.
|
||||
* Copyright (c) 2011-2015 Los Alamos National Security, LLC.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2014 Hochschule Esslingen. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
@ -56,11 +56,9 @@ int mca_base_framework_components_open (mca_base_framework_t *framework,
|
||||
{
|
||||
/* Open flags are not used at this time. Suppress compiler warning. */
|
||||
if (flags & MCA_BASE_OPEN_FIND_COMPONENTS) {
|
||||
bool open_dso_components = !(flags & MCA_BASE_OPEN_STATIC_ONLY);
|
||||
/* Find and load requested components */
|
||||
int ret = mca_base_component_find(NULL, framework->framework_name,
|
||||
framework->framework_static_components,
|
||||
framework->framework_selection,
|
||||
&framework->framework_components, true);
|
||||
int ret = mca_base_component_find(NULL, framework, false, open_dso_components);
|
||||
if (OPAL_SUCCESS != ret) {
|
||||
return ret;
|
||||
}
|
||||
@ -70,53 +68,6 @@ int mca_base_framework_components_open (mca_base_framework_t *framework,
|
||||
return open_components (framework);
|
||||
}
|
||||
|
||||
int mca_base_components_open (const char *type_name, int output_id,
|
||||
const mca_base_component_t **static_components,
|
||||
opal_list_t *components_available,
|
||||
bool open_dso_components)
|
||||
{
|
||||
/* create a dummy framework -- this leaks -- i know -- but it is temporary */
|
||||
mca_base_register_flag_t register_flags;
|
||||
mca_base_framework_t *dummy_framework;
|
||||
opal_list_item_t *item;
|
||||
int ret;
|
||||
|
||||
dummy_framework = calloc (1, sizeof(*dummy_framework));
|
||||
|
||||
dummy_framework->framework_static_components = static_components;
|
||||
dummy_framework->framework_output = output_id;
|
||||
dummy_framework->framework_name = strdup(type_name);
|
||||
|
||||
if (open_dso_components) {
|
||||
register_flags = MCA_BASE_REGISTER_STATIC_ONLY;
|
||||
} else {
|
||||
register_flags = MCA_BASE_REGISTER_DEFAULT;
|
||||
}
|
||||
|
||||
ret = mca_base_framework_components_register (dummy_framework, register_flags);
|
||||
if (OPAL_SUCCESS != ret) {
|
||||
free (dummy_framework);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mca_base_framework_components_open (dummy_framework, 0);
|
||||
if (OPAL_SUCCESS != ret) {
|
||||
(void) mca_base_framework_components_close (dummy_framework, NULL);
|
||||
free (dummy_framework);
|
||||
return ret;
|
||||
}
|
||||
|
||||
OBJ_CONSTRUCT(components_available, opal_list_t);
|
||||
|
||||
while (NULL != (item = opal_list_remove_first(&dummy_framework->framework_components))) {
|
||||
opal_list_append(components_available, item);
|
||||
}
|
||||
|
||||
OBJ_DESTRUCT(&dummy_framework->framework_components);
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Traverse the entire list of found components (a list of
|
||||
* mca_base_component_t instances). If the requested_component_names
|
||||
@ -152,16 +103,13 @@ static int open_components(mca_base_framework_t *framework)
|
||||
|
||||
/* If mca_base_framework_register_components was called with the MCA_BASE_COMPONENTS_ALL flag
|
||||
we need to trim down and close any extra components we do not want open */
|
||||
ret = mca_base_components_filter (framework->framework_name, &framework->framework_components,
|
||||
framework->framework_output, framework->framework_selection,
|
||||
open_only_flags);
|
||||
ret = mca_base_components_filter (framework, open_only_flags);
|
||||
if (OPAL_SUCCESS != ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Announce */
|
||||
opal_output_verbose(10, output_id,
|
||||
"mca: base: components_open: opening %s components",
|
||||
opal_output_verbose(10, output_id, "mca: base: components_open: opening %s components",
|
||||
framework->framework_name);
|
||||
|
||||
/* Traverse the list of components */
|
||||
|
@ -11,7 +11,7 @@
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2008-2012 Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2011-2013 Los Alamos National Security, LLC.
|
||||
* Copyright (c) 2011-2015 Los Alamos National Security, LLC.
|
||||
* All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
@ -39,8 +39,7 @@
|
||||
/*
|
||||
* Local functions
|
||||
*/
|
||||
static int register_components(const char *project_name, const char *type_name,
|
||||
int output_id, opal_list_t *src, opal_list_t *dest);
|
||||
static int register_components(mca_base_framework_t *framework);
|
||||
/**
|
||||
* Function for finding and opening either all MCA components, or the
|
||||
* one that was specifically requested via a MCA parameter.
|
||||
@ -50,28 +49,16 @@ int mca_base_framework_components_register (mca_base_framework_t *framework,
|
||||
{
|
||||
bool open_dso_components = !(flags & MCA_BASE_REGISTER_STATIC_ONLY);
|
||||
bool ignore_requested = !!(flags & MCA_BASE_REGISTER_ALL);
|
||||
opal_list_t components_found;
|
||||
int ret;
|
||||
|
||||
/* Find and load requested components */
|
||||
ret = mca_base_component_find(NULL, framework->framework_name,
|
||||
framework->framework_static_components,
|
||||
ignore_requested ? NULL : framework->framework_selection,
|
||||
&components_found, open_dso_components);
|
||||
|
||||
ret = mca_base_component_find(NULL, framework, ignore_requested, open_dso_components);
|
||||
if (OPAL_SUCCESS != ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Register all remaining components */
|
||||
ret = register_components(framework->framework_project, framework->framework_name,
|
||||
framework->framework_output, &components_found,
|
||||
&framework->framework_components);
|
||||
|
||||
OBJ_DESTRUCT(&components_found);
|
||||
|
||||
/* All done */
|
||||
return ret;
|
||||
return register_components(framework);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -81,24 +68,21 @@ int mca_base_framework_components_register (mca_base_framework_t *framework,
|
||||
* components is in the requested_components_array, try to open it.
|
||||
* If it opens, add it to the components_available list.
|
||||
*/
|
||||
static int register_components(const char *project_name, const char *type_name,
|
||||
int output_id, opal_list_t *src, opal_list_t *dest)
|
||||
static int register_components(mca_base_framework_t *framework)
|
||||
{
|
||||
int ret;
|
||||
opal_list_item_t *item;
|
||||
mca_base_component_t *component;
|
||||
mca_base_component_list_item_t *cli;
|
||||
mca_base_component_list_item_t *cli, *next;
|
||||
int output_id = framework->framework_output;
|
||||
|
||||
/* Announce */
|
||||
opal_output_verbose(10, output_id,
|
||||
"mca: base: components_register: registering %s components",
|
||||
type_name);
|
||||
"mca: base: components_register: registering framework %s components",
|
||||
framework->framework_name);
|
||||
|
||||
/* Traverse the list of found components */
|
||||
|
||||
OBJ_CONSTRUCT(dest, opal_list_t);
|
||||
while (NULL != (item = opal_list_remove_first (src))) {
|
||||
cli = (mca_base_component_list_item_t *) item;
|
||||
OPAL_LIST_FOREACH_SAFE(cli, next, &framework->framework_components, mca_base_component_list_item_t) {
|
||||
component = (mca_base_component_t *)cli->cli_component;
|
||||
|
||||
opal_output_verbose(10, output_id,
|
||||
@ -142,7 +126,7 @@ static int register_components(const char *project_name, const char *type_name,
|
||||
component->mca_component_name);
|
||||
}
|
||||
|
||||
mca_base_component_unload (component, output_id);
|
||||
opal_list_remove_item (&framework->framework_components, &cli->super);
|
||||
|
||||
/* Release this list item */
|
||||
OBJ_RELEASE(cli);
|
||||
@ -168,8 +152,6 @@ static int register_components(const char *project_name, const char *type_name,
|
||||
0, MCA_BASE_VAR_FLAG_DEFAULT_ONLY | MCA_BASE_VAR_FLAG_INTERNAL,
|
||||
OPAL_INFO_LVL_9, MCA_BASE_VAR_SCOPE_CONSTANT,
|
||||
&component->mca_component_release_version);
|
||||
|
||||
opal_list_append(dest, item);
|
||||
}
|
||||
|
||||
/* All done */
|
||||
|
@ -65,6 +65,8 @@ int mca_base_framework_register (struct mca_base_framework_t *framework,
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
OBJ_CONSTRUCT(&framework->framework_components, opal_list_t);
|
||||
|
||||
if (framework->framework_flags & MCA_BASE_FRAMEWORK_FLAG_NO_DSO) {
|
||||
flags |= MCA_BASE_REGISTER_STATIC_ONLY;
|
||||
}
|
||||
@ -147,6 +149,10 @@ int mca_base_framework_open (struct mca_base_framework_t *framework,
|
||||
|
||||
if (MCA_BASE_FRAMEWORK_FLAG_NOREGISTER & framework->framework_flags) {
|
||||
flags |= MCA_BASE_OPEN_FIND_COMPONENTS;
|
||||
|
||||
if (MCA_BASE_FRAMEWORK_FLAG_NO_DSO & framework->framework_flags) {
|
||||
flags |= MCA_BASE_OPEN_STATIC_ONLY;
|
||||
}
|
||||
}
|
||||
|
||||
/* lock all of this frameworks's variables */
|
||||
@ -221,6 +227,8 @@ int mca_base_framework_close (struct mca_base_framework_t *framework) {
|
||||
|
||||
framework->framework_flags &= ~(MCA_BASE_FRAMEWORK_FLAG_REGISTERED | MCA_BASE_FRAMEWORK_FLAG_OPEN);
|
||||
|
||||
OBJ_DESTRUCT(&framework->framework_components);
|
||||
|
||||
framework_close_output (framework);
|
||||
|
||||
return ret;
|
||||
|
@ -29,11 +29,13 @@ enum mca_base_register_flag_t {
|
||||
typedef enum mca_base_register_flag_t mca_base_register_flag_t;
|
||||
|
||||
enum mca_base_open_flag_t {
|
||||
MCA_BASE_OPEN_DEFAULT = 0,
|
||||
MCA_BASE_OPEN_DEFAULT = 0,
|
||||
/** Find components in mca_base_components_find. Used by
|
||||
mca_base_framework_open() when NOREGISTER is specified
|
||||
by the framework */
|
||||
MCA_BASE_OPEN_FIND_COMPONENTS = 1
|
||||
MCA_BASE_OPEN_FIND_COMPONENTS = 1,
|
||||
/** Do not open DSO components */
|
||||
MCA_BASE_OPEN_STATIC_ONLY = 2,
|
||||
};
|
||||
|
||||
typedef enum mca_base_open_flag_t mca_base_open_flag_t;
|
||||
|
@ -172,4 +172,4 @@ opal_installdirs_base_close(void)
|
||||
/* Declare the installdirs framework */
|
||||
MCA_BASE_FRAMEWORK_DECLARE(opal, installdirs, NULL, NULL, opal_installdirs_base_open,
|
||||
opal_installdirs_base_close, mca_installdirs_base_static_components,
|
||||
MCA_BASE_FRAMEWORK_FLAG_NOREGISTER);
|
||||
MCA_BASE_FRAMEWORK_FLAG_NOREGISTER | MCA_BASE_FRAMEWORK_FLAG_NO_DSO);
|
||||
|
@ -10,7 +10,7 @@
|
||||
* 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) 2010-2013 Los Alamos National Security, LLC.
|
||||
* Copyright (c) 2010-2015 Los Alamos National Security, LLC.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2013-2015 Intel, Inc. All rights reserved
|
||||
* $COPYRIGHT$
|
||||
@ -163,9 +163,6 @@ opal_finalize(void)
|
||||
/* close the sec framework */
|
||||
(void) mca_base_framework_close(&opal_sec_base_framework);
|
||||
|
||||
/* finalize the mca */
|
||||
mca_base_close();
|
||||
|
||||
/* finalize util code */
|
||||
opal_finalize_util();
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
* Copyright (c) 2007-2012 Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright (c) 2009 Oak Ridge National Labs. All rights reserved.
|
||||
* Copyright (c) 2010-2013 Los Alamos National Security, LLC.
|
||||
* Copyright (c) 2010-2015 Los Alamos National Security, LLC.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2013-2014 Intel, Inc. All rights reserved
|
||||
* Copyright (c) 2015 Research Organization for Information Science
|
||||
@ -354,6 +354,12 @@ opal_init_util(int* pargc, char*** pargv)
|
||||
goto return_error;
|
||||
}
|
||||
|
||||
/* initialize the mca */
|
||||
if (OPAL_SUCCESS != (ret = mca_base_open())) {
|
||||
error = "mca_base_open";
|
||||
goto return_error;
|
||||
}
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
|
||||
return_error:
|
||||
@ -384,12 +390,6 @@ opal_init(int* pargc, char*** pargv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* initialize the mca */
|
||||
if (OPAL_SUCCESS != (ret = mca_base_open())) {
|
||||
error = "mca_base_open";
|
||||
goto return_error;
|
||||
}
|
||||
|
||||
/* open hwloc - since this is a static framework, no
|
||||
* select is required
|
||||
*/
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user