1
1

Addition of module registration code; initial port to LAMX framework

This commit was SVN r464.
Этот коммит содержится в:
Jeff Squyres 2004-01-17 23:07:40 +00:00
родитель ee58c030ba
Коммит 64b07daedb
11 изменённых файлов: 1863 добавлений и 3 удалений

Просмотреть файл

@ -9,13 +9,23 @@ noinst_LTLIBRARIES = libmca_lam_base.la
# Source code files
headers = \
mca_lam_param.h \
module_exchange.h
mca_base_close.h \
mca_base_module_compare.h \
mca_base_open.h \
mca_base_param.h \
mca_base_module_exchange.h
# Library
libmca_lam_base_la_SOURCES = \
mca_lam_param.c
$(headers) \
mca_base_close.c \
mca_base_cmd_line.c \
mca_base_module_compare.c \
mca_base_module_find.c \
mca_base_module_registry.c \
mca_base_open.c \
mca_base_param.c
# Conditionally install the header files

72
src/mca/lam/base/base.h Обычный файл
Просмотреть файл

@ -0,0 +1,72 @@
/*
* $HEADER$
*/
#ifndef MCA_LAM_BASE_H
#define MCA_LAM_BASE_H
#include "mca/ltdl.h"
/*
* These units are large enough to warrant their own .h files
*/
#include "mca/lam/base/mca_base_param.h"
#include "mca/lam/base/mca_base_module_exchange.h"
/*
* Public variables
*/
extern int mca_base_param_module_path;
/*
* Public functions
*/
#if defined(c_plusplus) || defined(__cplusplus)
extern "C" {
#endif
/* mca_base_open.c */
int mca_base_open(void);
/* mca_base_close.c */
int mca_base_close(void);
/* mca_base_cmd_line.c */
int mca_base_cmd_line_setup(lam_cmd_line_t *cmd);
int mca_base_cmd_line_process_args(lam_cmd_line_t *cmd);
int mca_base_cmd_line_process_arg(const char *param, const char *value);
/* mca_base_module_compare.c */
int mca_base_module_compare(mca_base_module_priority_t *a,
mca_base_module_priority_t *b);
/* mca_base_module_find.c */
int mca_base_module_find(const char *directory, const char *type,
mca_base_module_t *static_modules[],
lam_list_t *found_modules);
/* mca_base_module_register.c */
int mca_base_module_registry_init(void);
int mca_base_module_registry_retain(char *type, lt_dlhandle module_handle,
mca_base_module_t *module_struct);
int mca_base_module_registry_link(const char *src_type,
const char *src_name,
const char *depend_type,
const char *depend_name);
void mca_base_module_registry_release(mca_base_module_t *module);
void mca_base_module_registry_finalize(void);
#if defined(c_plusplus) || defined(__cplusplus)
}
#endif
#endif /* MCA_LAM_BASE_H */

28
src/mca/lam/base/mca_base_close.c Обычный файл
Просмотреть файл

@ -0,0 +1,28 @@
/*
* $HEADER$
*/
#include "lam_config.h"
#include "lam/util/output.h"
#include "mca/mca.h"
#include "mca/lam/base/base.h"
/*
* Main MCA shutdown.
*/
int mca_base_close(void)
{
/* Clear out all the registered MCA params */
mca_base_param_finalize();
/* Close down the module registry */
mca_base_module_registry_finalize();
/* All done */
return LAM_SUCCESS;
}

117
src/mca/lam/base/mca_base_cmd_line.c Обычный файл
Просмотреть файл

@ -0,0 +1,117 @@
/*
* $HEADER$
*/
#include "lam_config.h"
#include <stdio.h>
#include <string.h>
#include "lam/constants.h"
#include "lam/mem/malloc.h"
#include "lam/util/cmd_line.h"
#include "lam/util/argv.h"
#include "mca/lam/base/base.h"
/*
* Private variables
*/
static int mca_param_argc = 0;
static char **mca_param_argv = NULL;
static int mca_value_argc = 0;
static char **mca_value_argv = NULL;
/*
* Add -mca to the possible command line options list
*/
int
mca_base_cmd_line_setup(lam_cmd_line_t *cmd)
{
return lam_cmd_line_set_opt(cmd, "m", "mca", 2,
"General mechanism to pass MCA parameters");
}
/*
* Look for and handle any -mca options on the command line
*/
int
mca_base_cmd_line_process_args(lam_cmd_line_t *cmd)
{
int i, num_insts;
char *buf = 0;
int buflen = 0;
/* If no "-mca" parameters were given, just return */
if (!lam_cmd_line_is_taken(cmd, "mca"))
return LAM_SUCCESS;
/* Otherwise, assemble them into an argc/argv */
num_insts = lam_cmd_line_get_ninsts(cmd, "mca");
for (i = 0; i < num_insts; ++i)
mca_base_cmd_line_process_arg(lam_cmd_line_get_param(cmd, "mca", i, 0),
lam_cmd_line_get_param(cmd, "mca", i, 1));
/* Now put that argc/argv in the environment */
if (NULL == mca_param_argv)
return LAM_SUCCESS;
/* Loop through all the -mca args that we've gotten and make env
vars of the form LAM_MPI_MCA_*=value. This is a memory leak, but
that's how putenv works. :-( */
for (i = 0; NULL != mca_param_argv[i]; ++i) {
buflen = strlen(mca_param_argv[i]) + strlen(mca_value_argv[i]) + 32;
buf = LAM_MALLOC(buflen);
if (NULL == buf)
return LAM_ERR_OUT_OF_RESOURCE;
snprintf(buf, buflen, "LAM_MPI_MCA_%s=%s", mca_param_argv[i],
mca_value_argv[i]);
putenv(buf);
}
return LAM_SUCCESS;
}
/*
* Process a single MCA argument. Done as a separate function so that
* top-level applications can directly invoke this to effect MCA
* command line arguments.
*/
int
mca_base_cmd_line_process_arg(const char *param, const char *value)
{
int i, len;
char *new_str;
/* Look to see if we've already got an -mca argument for the same
param. Check against the list of MCA param's that we've already
saved arguments for. */
for (i = 0; NULL != mca_param_argv && NULL != mca_param_argv[i]; ++i) {
if (0 == strcmp(param, mca_param_argv[i])) {
len = strlen(value) + strlen(mca_param_argv[i]);
new_str = LAM_MALLOC(len);
snprintf(new_str, len, "%s,%s", mca_value_argv[i], value);
LAM_FREE(mca_value_argv[i]);
mca_value_argv[i] = new_str;
return LAM_SUCCESS;
}
}
/* If we didn't already have an value for the same param, save this
one away */
lam_argv_add(&mca_param_argc, &mca_param_argv, param);
lam_argv_add(&mca_value_argc, &mca_value_argv, value);
return LAM_SUCCESS;
}

68
src/mca/lam/base/mca_base_module_compare.c Обычный файл
Просмотреть файл

@ -0,0 +1,68 @@
/*
* $HEADER$
*/
#include "lam_config.h"
#include <string.h>
#include "mca/mca.h"
#include "mca/lam/base/base.h"
/*
* Function for comparing two mca_base_module_priorit_t structs so
* that we can build prioritized LIST's of them. This assumed that
* the types of the modules are the same. Sort first by priority,
* second by module name, third by module version.
*
* Note that we acutally want a *reverse* ordering here -- the al_*
* functions will put "smaller" items at the head, and "larger" items
* at the tail. Since we want the highest priority at the head, it
* may help the gentle reader to consider this an inverse comparison.
* :-)
*/
int mca_base_module_compare(mca_base_module_priority_t *a,
mca_base_module_priority_t *b)
{
int val;
/* First, compare the priorties */
if (a->lsm_priority > b->lsm_priority)
return -1;
else if (a->lsm_priority < b->lsm_priority)
return 1;
else {
mca_base_module_t *aa = a->lsm_module;
mca_base_module_t *bb = b->lsm_module;
/* The priorities were equal, so compare the names */
val = strncmp(aa->mca_module_name, bb->mca_module_name,
MCA_BASE_MAX_MODULE_NAME_LEN);
if (val != 0)
return -val;
/* The names were equal, so compare the versions */
if (aa->mca_module_major_version > bb->mca_module_major_version)
return -1;
else if (aa->mca_module_major_version < bb->mca_module_major_version)
return 1;
else if (aa->mca_module_minor_version > bb->mca_module_minor_version)
return -1;
else if (aa->mca_module_minor_version < bb->mca_module_minor_version)
return 1;
else if (aa->mca_module_release_version > bb->mca_module_release_version)
return -1;
else if (aa->mca_module_release_version < bb->mca_module_release_version)
return 1;
}
/* They're equal */
return 0;
}

641
src/mca/lam/base/mca_base_module_find.c Обычный файл
Просмотреть файл

@ -0,0 +1,641 @@
/*
* $HEADER$
*/
#include "lam_config.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
/* Ensure to get the right <ltdl.h> */
#include "mca/ltdl.h"
#include "lam/constants.h"
#include "lam/util/output.h"
#include "lam/lfc/list.h"
#include "mca/mca.h"
#include "mca/lam/base/base.h"
/*
* Private types
*/
typedef enum module_status {
UNVISITED,
FAILED_TO_LOAD,
CHECKING_CYCLE,
LOADED,
STATUS_MAX
} module_status_t;
struct module_file_item_t {
lam_list_item_t super;
char type[MCA_BASE_MAX_TYPE_NAME_LEN];
char name[MCA_BASE_MAX_MODULE_NAME_LEN];
char basename[LAM_PATH_MAX];
char filename[LAM_PATH_MAX];
module_status_t status;
};
typedef struct module_file_item_t module_file_item_t;
struct dependency_item_t {
lam_list_item_t super;
module_file_item_t *di_module_file_item;
};
typedef struct dependency_item_t dependency_item_t;
struct ltfn_data_holder_t {
char type[MCA_BASE_MAX_TYPE_NAME_LEN];
char name[MCA_BASE_MAX_MODULE_NAME_LEN];
};
typedef struct ltfn_data_holder_t ltfn_data_holder_t;
/*
* Private functions
*/
static void find_dyn_modules(const char *path, const char *type,
const char *name, lam_list_t *found_modules);
static int save_filename(const char *filename, lt_ptr data);
static int open_module(module_file_item_t *target_file,
lam_list_t *found_modules);
static int check_laminfo(module_file_item_t *target_file,
lam_list_t *dependencies,
lam_list_t *found_modules);
static int check_dependency(char *line, module_file_item_t *target_file,
lam_list_t *dependencies,
lam_list_t *found_modules);
static void free_dependency_list(lam_list_t *dependencies);
/*
* Private variables
*/
static const char *laminfo_suffix = ".laminfo";
static const char *key_dependency = "dependency=";
static const char module_template[] = "mca_%s_";
static lam_list_t found_files;
/*
* Function to find as many modules of a given type as possible. This
* includes statically-linked in modules as well as opening up a
* directory and looking for shared-library MCA modules of the
* appropriate type (load them if available).
*
* Return one consolidated array of (mca_base_module_t*) pointing to all
* available modules.
*/
int mca_base_module_find(const char *directory, const char *type,
mca_base_module_t *static_modules[],
lam_list_t *found_modules)
{
int i;
mca_base_module_list_item_t *item;
/* Find all the modules that were statically linked in */
lam_list_init(found_modules);
for (i = 0; NULL != static_modules[i]; ++i) {
item = LAM_MALLOC(sizeof(mca_base_module_list_item_t));
if (NULL == item) {
return LAM_ERR_OUT_OF_RESOURCE;
}
lam_list_item_init((lam_list_item_t *) item);
item->mli_module = static_modules[i];
lam_list_append(found_modules, (lam_list_item_t *) item);
}
/* Find any available dynamic modules in the specified directory */
find_dyn_modules(directory, type, NULL, found_modules);
/* All done */
return LAM_SUCCESS;
}
/*
* Open up all directories in a given path and search for modules of
* the specified type (and possibly of a given name).
*
* Note that we use our own path iteration functionality (vs. ltdl's
* lt_dladdsearchdir() functionality) because we need to look at
* companion .laminfo files in the same directory as the library to
* generate dependencies, etc. If we use the plain lt_dlopen()
* functionality, we would not get the directory name of the file
* finally opened in recursive dependency traversals.
*/
static void find_dyn_modules(const char *path, const char *type,
const char *name, lam_list_t *found_modules)
{
ltfn_data_holder_t params;
char *path_to_use, *dir, *end;
module_file_item_t *file;
lam_list_item_t *cur;
strcpy(params.type, type);
strcpy(params.name, name);
if (NULL == name) {
lam_output_verbose(0, 40, " looking for all dynamic %s MCA modules",
type, NULL);
} else {
lam_output_verbose(0, 40,
" looking for dynamic %s MCA module named \"%s\"",
type, name, NULL);
}
/* If directory is NULL, iterate over the set of directories
specified by the MCA param mca_base_module_path. If path is not
NULL, then use that as the path. */
if (NULL == path) {
mca_base_param_lookup_string(mca_base_param_module_path, &dir);
path_to_use = strdup(dir);
}
if (NULL == path) {
path_to_use = strdup(path);
}
/* Iterate over all the files in the directories in the path and
make a master array of all the matching filenames that we
find. */
lam_list_init(&found_files);
dir = path_to_use;
do {
end = strchr(dir, ':');
if (NULL != end) {
*end = '\0';
}
if (0 != lt_dlforeachfile(dir, save_filename, &params)) {
break;
}
dir = end + 1;
} while (NULL != end);
/* Iterate through all the filenames that we found. Since one
module 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 = lam_list_get_first(&found_files);
lam_list_get_end(&found_files) != cur;
cur = lam_list_get_next(cur)) {
file = (module_file_item_t *) cur;
if (UNVISITED == file->status)
open_module(file, found_modules);
}
/* So now we have a final list of loaded modules. We can free all
the file information. */
for (cur = lam_list_get_first(&found_files);
lam_list_get_end(&found_files) != cur; ) {
file = (module_file_item_t *) cur;
cur = lam_list_get_next(cur);
LAM_FREE(file);
lam_list_remove_first(&found_files);
}
/* All done */
lam_list_destroy(&found_files);
LAM_FREE(path_to_use);
}
/*
* Given a filename, see if it appears to be of the proper filename
* format. If so, save it in the array so that we can process it
* later.
*/
static int save_filename(const char *filename, lt_ptr data)
{
int len, prefix_len, total_len;
char *prefix;
const char *basename;
module_file_item_t *module_file;
ltfn_data_holder_t *params = (ltfn_data_holder_t *) data;
/* Check to see if the file is named what we expect it to be
named */
len = sizeof(module_template) + strlen(params->type) + 32;
if (NULL != params->name) {
len += strlen(params->name);
}
prefix = LAM_MALLOC(len);
snprintf(prefix, len, module_template, params->type);
prefix_len = strlen(prefix);
if (NULL != params->name) {
strcat(prefix, params->name);
}
total_len = strlen(prefix);
basename = strrchr(filename, '/');
if (NULL == basename) {
basename = filename;
} else {
basename += 1;
}
if (0 != strncmp(basename, prefix, total_len)) {
LAM_FREE(prefix);
return 0;
}
/* Save all the info and put it in the list of found modules */
module_file = LAM_MALLOC(sizeof(module_file_item_t));
if (NULL == module_file) {
return LAM_ERR_OUT_OF_RESOURCE;
}
lam_list_item_init((lam_list_item_t *) module_file);
strcpy(module_file->type, params->type);
strcpy(module_file->name, basename + prefix_len);
strcpy(module_file->basename, basename);
strcpy(module_file->filename, filename);
module_file->status = UNVISITED;
lam_list_append(&found_files, (lam_list_item_t *) module_file);
/* All done */
LAM_FREE(prefix);
return 0;
}
/*
* Open a module, chasing down its dependencies first, if possible.
*/
static int open_module(module_file_item_t *target_file,
lam_list_t *found_modules)
{
int len;
lt_dlhandle module_handle;
mca_base_module_t *module_struct;
char *struct_name;
lam_list_t dependencies;
lam_list_item_t *cur;
mca_base_module_list_item_t *mitem;
dependency_item_t *ditem;
lam_output_verbose(0, 40, " examining dyanmic %s MCA module \"%s\"",
target_file->type, target_file->name, NULL);
lam_output_verbose(0, 40, " %s", target_file->filename, NULL);
/* Was this module already loaded (e.g., via dependency)? */
if (LOADED == target_file->status) {
lam_output_verbose(0, 40, " already loaded (ignored)", NULL);
return LAM_SUCCESS;
}
/* Ensure that this module 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 module.
Hence, returning LAM_ERR_PARAM indicates that the *file* failed
to load, not the module. */
for (cur = lam_list_get_first(found_modules);
lam_list_get_end(found_modules) != cur;
cur = lam_list_get_next(cur)) {
mitem = (mca_base_module_list_item_t *) cur;
if (0 == strcmp(mitem->mli_module->mca_type_name, target_file->type) &&
0 == strcmp(mitem->mli_module->mca_module_name, target_file->name)) {
lam_output_verbose(0, 40, " already loaded (ignored)", NULL);
target_file->status = FAILED_TO_LOAD;
return LAM_ERR_BAD_PARAM;
}
}
/* Look at see if this module has any dependencies. If so, load
them. If we can't load them, then this module must also fail to
load. */
lam_list_init(&dependencies);
if (0 != check_laminfo(target_file, &dependencies, found_modules)) {
target_file->status = FAILED_TO_LOAD;
free_dependency_list(&dependencies);
return LAM_ERR_OUT_OF_RESOURCE;
}
/* Now try to load the module */
module_handle = lt_dlopenext(target_file->filename);
if (NULL == module_handle) {
lam_output_verbose(0, 40, " unable to open: %s (ignored)",
lt_dlerror(), NULL);
target_file->status = FAILED_TO_LOAD;
free_dependency_list(&dependencies);
return LAM_ERR_BAD_PARAM;
}
/* Successfully opened the module; now find the public struct.
Malloc out enough space for it. */
len = strlen(target_file->type) + strlen(target_file->name) + 32;
struct_name = LAM_MALLOC(len);
if (NULL == struct_name) {
lt_dlclose(module_handle);
target_file->status = FAILED_TO_LOAD;
free_dependency_list(&dependencies);
return LAM_ERR_OUT_OF_RESOURCE;
}
snprintf(struct_name, len, "mca_%s_%s_module", target_file->type,
target_file->name);
mitem = LAM_MALLOC(sizeof(mca_base_module_list_item_t));
if (NULL == mitem) {
LAM_FREE(struct_name);
lt_dlclose(module_handle);
target_file->status = FAILED_TO_LOAD;
free_dependency_list(&dependencies);
return LAM_ERR_OUT_OF_RESOURCE;
}
lam_list_item_init((lam_list_item_t *) mitem);
module_struct = lt_dlsym(module_handle, struct_name);
if (NULL == module_struct) {
lam_output_verbose(0, 40, " \"%s\" does not appear to be a valid "
"%s MCA dynamic module (ignored)",
target_file->basename, target_file->type, NULL);
LAM_FREE(mitem);
LAM_FREE(struct_name);
lt_dlclose(module_handle);
target_file->status = FAILED_TO_LOAD;
free_dependency_list(&dependencies);
return LAM_ERR_BAD_PARAM;
}
/* We found the public struct. Save it, and register this module to
be closed later. */
mitem->mli_module = module_struct;
lam_list_append(found_modules, (lam_list_item_t *) mitem);
mca_base_module_registry_retain(target_file->type, module_handle,
module_struct);
/* Now that that's all done, link all the dependencies in to this
module's registry entry */
for (cur = lam_list_remove_first(&dependencies);
NULL != cur;
cur = lam_list_remove_first(&dependencies)) {
ditem = (dependency_item_t *) cur;
mca_base_module_registry_link(target_file->type,
target_file->name,
ditem->di_module_file_item->type,
ditem->di_module_file_item->name);
LAM_FREE(ditem);
}
lam_list_destroy(&dependencies);
lam_output_verbose(0, 40, " opened dynamic %s MCA module \"%s\"",
target_file->type, target_file->name, NULL);
target_file->status = LOADED;
/* All done */
LAM_FREE(struct_name);
return LAM_SUCCESS;
}
/*
* For a given filename, see if there exists a filename.laminfo, which
* lists dependencies that must be loaded before this module is
* loaded. If we find this file, try to load those modules first.
*
* Detect dependency cycles and error out.
*/
static int check_laminfo(module_file_item_t *target_file,
lam_list_t *dependencies, lam_list_t *found_modules)
{
int len;
FILE *fp;
char *depname;
char buffer[BUFSIZ], *p;
/* Form the filename */
len = strlen(target_file->filename) + strlen(laminfo_suffix) + 16;
depname = LAM_MALLOC(len);
if (NULL == depname)
return LAM_ERR_OUT_OF_RESOURCE;
snprintf(depname, len, "%s%s", target_file->filename, laminfo_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"))) {
LAM_FREE(depname);
return 0;
}
/* Otherwise, loop reading the lines in the file and trying to load
them. Return failure upon the first module that fails to
load. */
lam_output_verbose(0, 40, " opening laminfo file: %s", depname, NULL);
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 (LAM_SUCCESS != check_dependency(p + strlen(key_dependency),
target_file, dependencies,
found_modules)) {
fclose(fp);
LAM_FREE(depname);
/* We can leave any successfully loaded dependencies; we might
need them again later. But free the dependency list for
this module, 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 module. So free the dependency
list. */
free_dependency_list(dependencies);
return LAM_ERR_OUT_OF_RESOURCE;
}
}
}
lam_output_verbose(0, 40, " laminfo file closed (%s)",
target_file->basename, NULL);
/* All done -- all depenencies satisfied */
fclose(fp);
LAM_FREE(depname);
return 0;
}
/*
* A DEPENDENCY key was found in the laminfo file. Chase it down: see
* if we've already got such a module loaded, or go try to load it if
* it's not already loaded.
*/
static int check_dependency(char *line, module_file_item_t *target_file,
lam_list_t *dependencies,
lam_list_t *found_modules)
{
bool happiness;
char buffer[BUFSIZ];
char *type, *name;
module_file_item_t *mitem;
dependency_item_t *ditem;
lam_list_item_t *cur;
/* Ensure that this was a valid dependency statement */
type = line;
name = strchr(line, ':');
if (NULL == name)
return LAM_ERR_OUT_OF_RESOURCE;
*name = '\0';
++name;
/* Form the name of the module to compare to */
if (strlen(type) + strlen(name) + 32 >= BUFSIZ) {
target_file->status = FAILED_TO_LOAD;
return LAM_ERR_OUT_OF_RESOURCE;
}
snprintf(buffer, BUFSIZ, module_template, type);
strcat(buffer, name);
/* Traverse down the list of files that we have, and see if we can
find it */
target_file->status = CHECKING_CYCLE;
for (happiness = false, cur = lam_list_get_first(&found_files);
lam_list_get_last(&found_files) != cur;
cur = lam_list_get_next(cur)) {
mitem = (module_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) {
lam_output_verbose(0, 40,
" module depends on itself (ignored dependency)",
NULL);
happiness = true;
break;
}
/* If it's loaded, great -- we're done (no need to check that
dependency sub-tree) */
else if (LOADED == mitem->status) {
lam_output_verbose(0, 40, " dependency has already been loaded (%s)",
mitem->basename, NULL);
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) {
lam_output_verbose(0, 40, " dependency previously failed to load (%s)",
mitem->basename, NULL);
break;
}
/* If we hit a cycle, return badness */
else if (CHECKING_CYCLE == mitem->status) {
lam_output_verbose(0, 40, " found cycle! (%s)",
mitem->basename, NULL);
break;
}
/* Otherwise, this dependency has not been looked at yet. Go try
to load it. */
else if (UNVISITED == mitem->status) {
lam_output_verbose(0, 40, " loading dependency (%s)",
mitem->basename, NULL);
if (LAM_SUCCESS == open_module(target_file, found_modules)) {
happiness = true;
} else {
lam_output_verbose(0, 40, " dependency failed to load (%s)",
mitem->basename, NULL);
}
break;
}
}
/* Did we find the dependency? */
if (!happiness) {
target_file->status = FAILED_TO_LOAD;
return LAM_ERR_BAD_PARAM;
}
/* The dependency loaded properly. Increment its refcount so that
it doesn't get unloaded before we get unloaded. */
ditem = LAM_MALLOC(sizeof(dependency_item_t));
if (NULL == ditem) {
return LAM_ERR_OUT_OF_RESOURCE;
}
cur = (lam_list_item_t *) ditem;
lam_list_item_init(cur);
lam_list_append(dependencies, cur);
/* All done -- all depenencies satisfied */
return LAM_SUCCESS;
}
/*
* Free a dependency list
*/
static void free_dependency_list(lam_list_t *dependencies)
{
lam_list_item_t *item;
for (item = lam_list_remove_first(dependencies);
NULL != item;
item = lam_list_remove_first(dependencies)) {
LAM_FREE(item);
}
lam_list_destroy(dependencies);
}

290
src/mca/lam/base/mca_base_module_registry.c Обычный файл
Просмотреть файл

@ -0,0 +1,290 @@
/*
* $HEADER$
*/
#include "lam_config.h"
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
/* Ensure to get the right <ltdl.h> */
#include "mca/ltdl.h"
#include "lam/constants.h"
#include "lam/lfc/list.h"
#include "mca/mca.h"
#include "mca/lam/base/base.h"
/*
* Private types
*/
struct registry_item_t {
lam_list_item_t super;
char ri_type[MCA_BASE_MAX_TYPE_NAME_LEN];
lt_dlhandle ri_dlhandle;
mca_base_module_t *ri_module_struct;
int ri_refcount;
lam_list_t ri_dependencies;
};
typedef struct registry_item_t registry_item_t;
struct dependency_item_t {
lam_list_item_t super;
registry_item_t *di_registry_entry;
};
typedef struct dependency_item_t dependency_item_t;
/*
* Private variables
*/
static bool initialized = false;
static lam_list_t registry;
/*
* Private functions
*/
static registry_item_t *find_module(const char *type, const char *name);
static int link_items(registry_item_t *src, registry_item_t *depend);
static void release_registry_item(registry_item_t *ri);
/*
* Initialize the registry
*/
int mca_base_module_registry_init(void)
{
/* Initialized libltdl */
if (lt_dlinit() != 0)
return LAM_ERR_OUT_OF_RESOURCE;
/* Setup internal structures */
if (!initialized) {
lam_list_init(&registry);
initialized = true;
}
/* All done */
return LAM_SUCCESS;
}
/*
* Add a newly-opened dyanmic module to the registry of open modules.
* The module's type, handle, and public struct are saved.
*/
int mca_base_module_registry_retain(char *type, lt_dlhandle module_handle,
mca_base_module_t *module_struct)
{
registry_item_t *ri;
/* Allocate a new registry item */
ri = LAM_MALLOC(sizeof(registry_item_t));
if (NULL == ri)
return LAM_ERR_OUT_OF_RESOURCE;
/* Initialize the registry item */
lam_list_item_init((lam_list_item_t *) ri);
strcpy(ri->ri_type, type);
ri->ri_dlhandle = module_handle;
ri->ri_module_struct = module_struct;
ri->ri_refcount = 1;
lam_list_init(&ri->ri_dependencies);
/* Append the new item to the registry */
lam_list_append(&registry, (lam_list_item_t *) ri);
/* All done */
return LAM_SUCCESS;
}
/*
* Create a dependency from one module entry to another
*/
int mca_base_module_registry_link(const char *src_type,
const char *src_name,
const char *depend_type,
const char *depend_name)
{
registry_item_t *src, *depend;
/* Look up the two modules */
src = find_module(src_type, src_name);
if (NULL == src)
return LAM_ERR_BAD_PARAM;
depend = find_module(depend_type, depend_name);
if (NULL == depend)
return LAM_ERR_BAD_PARAM;
/* Link them */
return link_items(src, depend);
}
/*
* If it's in the registr, close a specified module and remove it from
* the registry.
*/
void mca_base_module_registry_release(mca_base_module_t *module)
{
registry_item_t *ri = find_module(module->mca_type_name,
module->mca_module_name);
if (NULL != ri)
release_registry_item(ri);
}
/*
* Finalize the registry -- close everything that's still open.
*/
void mca_base_module_registry_finalize(void)
{
lam_list_item_t *item;
registry_item_t *ri;
bool changed;
if (initialized) {
/* Have to be slightly careful about this because of dependencies,
particularly on OS's where it matters (i.e., closing a module
that is depended on by other modules 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 modules 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 {
changed = false;
for (item = lam_list_get_first(&registry);
lam_list_get_last(&registry) != item && changed;
item = lam_list_get_next(item)) {
ri = (registry_item_t *) ri;
if (ri->ri_refcount == 1) {
release_registry_item(ri);
changed = true;
}
}
} while (lam_list_get_size(&registry) > 0 && changed);
lam_list_destroy(&registry);
initialized = false;
}
/* Close down libltdl */
lt_dlexit();
}
static registry_item_t *find_module(const char *type, const char *name)
{
lam_list_item_t *item;
registry_item_t *ri;
for (item = lam_list_get_first(&registry);
lam_list_get_last(&registry) != item;
item = lam_list_get_next(item)) {
ri = (registry_item_t *) ri;
if (0 == strcmp(ri->ri_type, type) &&
0 == strcmp(ri->ri_module_struct->mca_module_name, name))
return ri;
}
/* Not found */
return NULL;
}
static int link_items(registry_item_t *src, registry_item_t *depend)
{
dependency_item_t *di;
/* Bozo check */
if (NULL == src || NULL == depend)
return LAM_ERR_BAD_PARAM;
/* Make a new depedency item */
di = LAM_MALLOC(sizeof(dependency_item_t));
if (NULL == di)
return LAM_ERR_OUT_OF_RESOURCE;
/* Initialize the new dependency item */
lam_list_item_init((lam_list_item_t *) di);
di->di_registry_entry = depend;
/* Add it to the dependency list on the source registry entry */
lam_list_append(&src->ri_dependencies, (lam_list_item_t *) di);
/* Increment the refcount in the dependency */
++src->ri_refcount;
/* All done */
return LAM_SUCCESS;
}
static void release_registry_item(registry_item_t *ri)
{
dependency_item_t *di;
lam_list_item_t *item;
/* Bozo check */
if (NULL == ri)
return;
/* Decrement this module's refcount. If zero, close and free it. */
--ri->ri_refcount;
if (0 == ri->ri_refcount) {
lt_dlclose(ri->ri_dlhandle);
/* Now go release/close (at a minimum: decrement the refcount) any
dependencies of this module */
for (item = lam_list_remove_first(&ri->ri_dependencies);
NULL != item;
item = lam_list_remove_first(&ri->ri_dependencies)) {
di = (dependency_item_t *) item;
--di->di_registry_entry->ri_refcount;
LAM_FREE(di);
}
/* It should be obvious, but I'll state it anyway because it bit
me during debugging: after the dlclose(), the mca_base_module_t
pointer is no longer valid because it has [potentially] been
unloaded from memory. So don't try to use it. :-) */
lam_list_destroy(&di->di_registry_entry->ri_dependencies);
lam_list_remove_item(&registry, (lam_list_item_t *) ri);
LAM_FREE(ri);
}
}

138
src/mca/lam/base/mca_base_open.c Обычный файл
Просмотреть файл

@ -0,0 +1,138 @@
/*
* $HEADER$
*/
#include "lam_config.h"
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include "lam/mem/malloc.h"
#include "lam/util/output.h"
#include "mca/mca.h"
#include "mca/lam/base/base.h"
/*
* Public variables
*/
int mca_base_param_module_path = -1;
/*
* Private functions
*/
static void set_defaults(lam_output_stream_t *lds);
static void parse_verbose(char *e, lam_output_stream_t *lds);
/*
* Main MCA initialization.
*/
int mca_base_open(void)
{
int param_index;
char *value;
lam_output_stream_t lds;
/* Register some params */
param_index = mca_base_param_register_string("base", NULL, "verbose",
"verbose", NULL);
param_index = mca_base_param_register_string("base", NULL, "module_path",
"module_path", NULL);
/* What verbosity level do we want? */
mca_base_param_lookup_string(param_index, &value);
memset(&lds, 0, sizeof(lds));
parse_verbose(value, &lds);
set_defaults(&lds);
lam_output_reopen(0, &lds);
lam_output_verbose(0, 5, " Opening");
/* Open up the module registry */
return mca_base_module_registry_init();
}
/*
* Set sane default values for the lds
*/
static void set_defaults(lam_output_stream_t *lds)
{
/* Load up defaults */
lds->lds_is_debugging = false;
lds->lds_verbose_level = 0;
lds->lds_want_syslog = false;
lds->lds_syslog_priority = LOG_INFO;
lds->lds_syslog_ident = "lam";
lds->lds_want_stdout = false;
lds->lds_want_file = false;
lds->lds_want_file_append = false;
lds->lds_file_suffix = NULL;
lds->lds_file_suffix = "mca.txt";
}
/*
* Parse the value of an environment variable describing verbosity
*/
static void parse_verbose(char *e, lam_output_stream_t *lds)
{
char *edup = strdup(e);
char *ptr = edup, *next;
/* Now parse the environment variable */
while (NULL != ptr && strlen(ptr) > 0) {
next = strchr(ptr, ',');
if (NULL != next)
*next = '\0';
if (0 == strcasecmp(ptr, "syslog"))
lds->lds_want_syslog = true;
else if (strncasecmp(ptr, "syslogpri:", 10) == 0) {
lds->lds_want_syslog = true;
if (strcasecmp(ptr + 10, "notice") == 0)
lds->lds_syslog_priority = LOG_NOTICE;
else if (strcasecmp(ptr + 10, "INFO") == 0)
lds->lds_syslog_priority = LOG_INFO;
else if (strcasecmp(ptr + 10, "DEBUG") == 0)
lds->lds_syslog_priority = LOG_DEBUG;
} else if (strncasecmp(ptr, "syslogid:", 9) == 0) {
lds->lds_want_syslog = true;
lds->lds_syslog_ident = ptr + 9;
}
else if (strcasecmp(ptr, "stdout") == 0)
lds->lds_want_stdout = true;
else if (strcasecmp(ptr, "stderr") == 0)
lds->lds_want_stderr = true;
else if (strcasecmp(ptr, "file") == 0)
lds->lds_want_file = true;
else if (strncasecmp(ptr, "file:", 5) == 0) {
lds->lds_want_file = true;
lds->lds_file_suffix = ptr + 5;
} else if (strcasecmp(ptr, "fileappend") == 0) {
lds->lds_want_file = true;
lds->lds_want_file_append = 1;
} else if (strncasecmp(ptr, "level", 5) == 0) {
lds->lds_verbose_level = 0;
if (ptr[5] == ':')
lds->lds_verbose_level = atoi(ptr + 6);
}
if (NULL == next)
break;
ptr = next + 1;
}
LAM_FREE(edup);
}

496
src/mca/lam/base/mca_base_param.c Обычный файл
Просмотреть файл

@ -0,0 +1,496 @@
/*
* $HEADER$
*/
/** @file **/
#include "lam_config.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "lam/constants.h"
#include "lam/lfc/array.h"
#include "lam/mem/malloc.h"
#include "mca/mca.h"
#include "mca/lam/base/mca_base_param.h"
typedef enum {
MCA_BASE_PARAM_TYPE_INT,
MCA_BASE_PARAM_TYPE_STRING,
MCA_BASE_PARAM_TYPE_MAX
} mca_base_param_type_t;
struct mca_base_param_t {
lam_array_item_t super;
mca_base_param_type_t mbp_type;
char *mbp_type_name;
char *mbp_module_name;
char *mbp_param_name;
char *mbp_full_name;
int mbp_keyval;
char *mbp_env_var_name;
mca_base_param_storage_t mbp_default_value;
};
typedef struct mca_base_param_t mca_base_param_t;
/*
* local variables
*/
static lam_array_t mca_base_params;
static char *mca_prefix = "LAM_MPI_MCA_";
static bool initialized = false;
/*
* local functions
*/
static int param_register(const char *type_name, const char *module_name, const char *param_name,
const char *mca_param_name,
mca_base_param_type_t type,
mca_base_param_storage_t *default_value);
static bool param_lookup(int index, mca_base_param_storage_t *storage);
static int param_compare(const void *a, const void *b);
static void param_free(mca_base_param_t *p);
/**
* Register an integer MCA parameter.
*
* @param type_name The MCA type (string).
* @param module_name The name of the module (string).
* @param param_name The name of the parameter being registered (string).
* @param mca_param_name If NULL, the user-visible name of the
* parameter is {type_name}_{module_name}_{param_name}. If this
* parameter is non-NULL, it is used instead of the default name.
* @param default_value The value that is used for this parameter if
* the user does not supply one.
*
* @retval LAM_ERROR Upon failure to register the parameter.
* @retval index Index value that can be used with
* mca_base_param_lookup_int() to retrieve the value of the parameter.
*
* This function registers an integer MCA parameter and associates it
* with a specific module.
*
* In most cases, mca_param_name should be NULL. Only in rare cases
* is it necessary (or advisable) to override the default name.
*/
int mca_base_param_register_int(const char *type_name, const char *module_name,
const char *param_name,
const char *mca_param_name,
int default_value)
{
mca_base_param_storage_t storage;
storage.intval = default_value;
return param_register(type_name, module_name, param_name, mca_param_name,
MCA_BASE_PARAM_TYPE_INT, &storage);
}
/**
* Register a string MCA parameter.
*
* @param type_name The MCA type (string).
* @param module_name The name of the module (string).
* @param param_name The name of the parameter being registered (string).
* @param mca_param_name If NULL, the user-visible name of the
* parameter is {type_name}_{module_name}_{param_name}. If this
* parameter is non-NULL, it is used instead of the default name.
* @param default_value The value that is used for this parameter if
* the user does not supply one.
*
* @retval LAM_ERROR Upon failure to register the parameter.
* @retval index Index value that can be used with
* mca_base_param_lookup_string() to retrieve the value of the
* parameter.
*
* This function registers an string MCA parameter and associates it
* with a specific module.
*
* In most cases, mca_param_name should be NULL. Only in rare cases
* is it necessary (or advisable) to override the default name.
*/
int mca_base_param_register_string(const char *type_name,
const char *module_name,
const char *param_name,
const char *mca_param_name,
const char *default_value)
{
mca_base_param_storage_t storage;
storage.stringval = strdup(default_value);
return param_register(type_name, module_name, param_name, mca_param_name,
MCA_BASE_PARAM_TYPE_STRING, &storage);
}
/**
* Look up an integer MCA parameter.
*
* @param index Index previous returned from
* mca_base_param_register_int().
* @param value Pointer to int where the parameter value will be
* stored.
*
* @retvalue LAM_ERROR Upon failure. The contents of value are
* undefined.
* @retvalue LAM_SUCCESS Upon success. value will be filled with the
* parameter's current value.
*
* The value of a specific MCA parameter can be looked up using the
* return value from mca_base_param_register_int().
*/
int mca_base_param_lookup_int(int index, int *value)
{
mca_base_param_storage_t storage;
if (param_lookup(index, &storage)) {
*value = storage.intval;
return LAM_SUCCESS;
}
return LAM_ERROR;
}
/**
* Look up a string MCA parameter.
*
* @param index Index previous returned from
* mca_base_param_register_string().
* @param value Pointer to (char *) where the parameter value will be
* stored.
*
* @retvalue LAM_ERROR Upon failure. The contents of value are
* undefined.
* @retvalue LAM_SUCCESS Upon success. value will be filled with the
* parameter's current value.
*
* The value of a specific MCA parameter can be looked up using the
* return value from mca_base_param_register_string().
*/
int mca_base_param_lookup_string(int index, char **value)
{
mca_base_param_storage_t storage;
if (param_lookup(index, &storage)) {
*value = storage.stringval;
return LAM_SUCCESS;
}
return LAM_ERROR;
}
/**
* Find the index for an MCA parameter based on its names.
*
* @param type_name Name of the type containing the parameter.
* @param module_name Name of the module containing the parameter.
* @param param_name Name of the parameter.
*
* @retval LAM_ERROR If the parameter was not found.
* @retval index If the parameter was found.
*
* It is not always convenient to widely propagate a parameter's index
* value, or it may be necessary to look up the parameter from a
* different module -- where it is not possible to have the return
* value from mca_base_param_register_int() or
* mca_base_param_register_string(). This function can be used to
* look up the index of any registered parameter. The returned index
* can be used with mca_base_param_lookup_int() and
* mca_base_param_lookup_string().
*/
int mca_base_param_find(const char *type_name, const char *module_name,
const char *param_name)
{
size_t i, size;
mca_base_param_t **array;
/* Check for bozo cases */
if (!initialized)
return LAM_ERROR;
if (NULL == type_name || NULL == param_name)
return LAM_ERROR;
/* Loop through looking for a parameter of a given
type/module/param */
array = (mca_base_param_t**) lam_arr_get_c_array(&mca_base_params, &size);
for (i = 0; i < size; ++i) {
if (0 == strcmp(type_name, array[i]->mbp_type_name) &&
((NULL == module_name && NULL == array[i]->mbp_module_name) ||
(NULL != module_name && NULL != array[i]->mbp_module_name &&
0 == strcmp(module_name, array[i]->mbp_module_name))) &&
0 == strcmp(param_name, array[i]->mbp_param_name))
return i;
}
/* Didn't find it */
return LAM_ERROR;
}
/**
* Shut down the MCA parameter system (normally only invoked by the
* MCA framework itself).
*
* @returns LAM_SUCCESS This function never fails.
*
* This function shuts down the MCA parameter registry and frees all
* associated memory. No other mca_base_param*() functions can be
* invoked after this function.
*
* This function is normally only invoked by the MCA framework itself
* when the process is shutting down (e.g., during MPI_FINALIZE). It
* is only documented here for completeness.
*/
int mca_base_param_finalize(void)
{
size_t i, size;
mca_base_param_t **array;
if (initialized) {
array = (mca_base_param_t**) lam_arr_get_c_array(&mca_base_params, &size);
for (i = 0; i < size; ++i)
param_free(array[i]);
lam_arr_destroy(&mca_base_params);
initialized = false;
}
return LAM_SUCCESS;
}
/*************************************************************************/
static int param_register(const char *type_name, const char *module_name,
const char *param_name, const char *mca_param_name,
mca_base_param_type_t type,
mca_base_param_storage_t *default_value)
{
size_t i, len;
mca_base_param_t param, **array;
/* Initialize the array if it has never been initialized */
if (!initialized) {
lam_arr_init(&mca_base_params);
initialized = true;
}
/* Create a parameter entry. If a keyval is to be used, it will be
registered elsewhere. We simply assign -1 here. */
param.mbp_type = type;
param.mbp_keyval = -1;
param.mbp_type_name = strdup(type_name);
if (NULL == param.mbp_type_name)
return LAM_ERROR;
if (NULL != module_name) {
param.mbp_module_name = strdup(module_name);
if (NULL == param.mbp_module_name) {
LAM_FREE(param.mbp_type_name);
return LAM_ERROR;
}
} else
param.mbp_module_name = NULL;
if (param_name != NULL) {
param.mbp_param_name = strdup(param_name);
if (NULL == param.mbp_param_name) {
LAM_FREE(param.mbp_type_name);
LAM_FREE(param.mbp_module_name);
return LAM_ERROR;
}
} else
param.mbp_param_name = NULL;
/* The full parameter name may have been specified by the caller.
If it was, use that (only for backwards compatability).
Otherwise, derive it from the type, module, and parameter
name. */
param.mbp_env_var_name = NULL;
if (MCA_BASE_PARAM_INFO != mca_param_name && NULL != mca_param_name) {
param.mbp_full_name = strdup(mca_param_name);
} else {
len = 16 + strlen(type_name);
if (NULL != module_name)
len += strlen(module_name);
if (NULL != param_name)
len += strlen(param_name);
param.mbp_full_name = LAM_MALLOC(len);
if (NULL != param.mbp_full_name) {
LAM_FREE(param.mbp_type_name);
LAM_FREE(param.mbp_module_name);
LAM_FREE(param.mbp_param_name);
return LAM_ERROR;
}
strncpy(param.mbp_full_name, type_name, len);
if (NULL != module_name) {
strcat(param.mbp_full_name, "_");
strcat(param.mbp_full_name, module_name);
}
if (NULL != param_name) {
strcat(param.mbp_full_name, "_");
strcat(param.mbp_full_name, param_name);
}
}
/* If mca_param_name isn't MCA_BASE_PARAM_INFO, then it's a
lookup-able value. So amcagn the environment variable name as
well. */
if (MCA_BASE_PARAM_INFO != mca_param_name) {
len = strlen(param.mbp_full_name) + strlen(mca_prefix) + 16;
param.mbp_env_var_name = LAM_MALLOC(len);
if (NULL == param.mbp_env_var_name) {
LAM_FREE(param.mbp_full_name);
LAM_FREE(param.mbp_type_name);
LAM_FREE(param.mbp_module_name);
LAM_FREE(param.mbp_param_name);
return LAM_ERROR;
}
snprintf(param.mbp_env_var_name, len, "%s%s", mca_prefix,
param.mbp_full_name);
}
/* Figure out the default value */
if (NULL != default_value) {
if (MCA_BASE_PARAM_TYPE_STRING == param.mbp_type &&
NULL != default_value->stringval)
param.mbp_default_value.stringval = strdup(default_value->stringval);
else
param.mbp_default_value = *default_value;
} else
memset(&param.mbp_default_value, 0, sizeof(param.mbp_default_value));
/* See if this entry is already in the Array */
array = (mca_base_param_t**) lam_arr_get_c_array(&mca_base_params, &len);
for (i = 0; i < len; ++i)
if (param_compare(&param, array[i]) == 0) {
/* Copy in the new default value to the old entry */
if (MCA_BASE_PARAM_TYPE_STRING == array[i]->mbp_type &&
NULL != array[i]->mbp_default_value.stringval)
LAM_FREE(array[i]->mbp_default_value.stringval);
if (MCA_BASE_PARAM_TYPE_STRING == param.mbp_type &&
NULL != param.mbp_default_value.stringval)
array[i]->mbp_default_value.stringval =
strdup(param.mbp_default_value.stringval);
param_free(&param);
return i;
}
/* Add it to the array */
if (!lam_arr_append_item(&mca_base_params, (lam_object_t*) &param))
return LAM_ERROR;
return lam_arr_get_size(&mca_base_params) - 1;
}
/*
* DO NOT MODIFY THIS FUNCTION WITHOUT ALSO MODIFYING mca_mpi_param.c!
*
* This function appears in liblam. Because of unix linker semantics,
* it's simply easier to essentially duplicate this function in libmpi
* because in libmpi, we need to lookup on a keyval before looking in
* the environment. The logic is simpler if we just duplicate/alter
* the code in mca_mpi_param.c rather than try to make this a) public,
* and b) more general (to accomodate looking up keyvals while not
* linking to MPI_Comm_get_attr() in libmpi).
*/
static bool param_lookup(int index, mca_base_param_storage_t *storage)
{
size_t size;
char *env;
mca_base_param_t *p;
/* Lookup the index and see if it's valid */
if (!initialized)
return false;
if (lam_arr_get_size(&mca_base_params) < index)
return false;
p = ((mca_base_param_t*) lam_arr_get_c_array(&mca_base_params,
&size)) + index;
/* We either don't have a keyval or didn't find it. So look in the
environment. */
if (NULL != p->mbp_env_var_name &&
NULL != (env = getenv(p->mbp_env_var_name))) {
if (MCA_BASE_PARAM_TYPE_INT == p->mbp_type)
storage->intval = atoi(env);
else if (MCA_BASE_PARAM_TYPE_STRING == p->mbp_type)
storage->stringval = strdup(env);
else
return false;
return true;
}
/* Didn't find it; use the default value. */
switch (p->mbp_type) {
case MCA_BASE_PARAM_TYPE_INT:
storage->intval = p->mbp_default_value.intval;
break;
case MCA_BASE_PARAM_TYPE_STRING:
storage->stringval = p->mbp_default_value.stringval;
break;
default:
return false;
}
/* All done */
return true;
}
static int param_compare(const void *a, const void *b)
{
const mca_base_param_t *aa = (const mca_base_param_t*) a;
const mca_base_param_t *bb = (const mca_base_param_t*) b;
return strcmp(aa->mbp_full_name, bb->mbp_full_name);
}
static void param_free(mca_base_param_t *p)
{
if (NULL != p->mbp_type_name)
LAM_FREE(p->mbp_type_name);
if (NULL != p->mbp_module_name)
LAM_FREE(p->mbp_module_name);
if (NULL != p->mbp_param_name)
LAM_FREE(p->mbp_param_name);
if (NULL != p->mbp_env_var_name)
LAM_FREE(p->mbp_env_var_name);
if (NULL != p->mbp_full_name)
LAM_FREE(p->mbp_full_name);
if (MCA_BASE_PARAM_TYPE_STRING == p->mbp_type &&
NULL != p->mbp_default_value.stringval)
LAM_FREE(p->mbp_default_value.stringval);
}

Просмотреть файл