From 4faa486ee5d007a43cf46e5b24ccf53bc9d7ef05 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Tue, 31 Aug 2004 09:49:56 +0000 Subject: [PATCH] - New capability for MCA parameters to be read from files. Order of resolution is now (effectively): - read from MPI keyval (if associated) - read from command line - read from environment - read from file More capabilities will be added shortly for developers to programatically set MCA parameter values - Create [empty but commented] system-wide MCA param file that gets installed at $sysconf/openmpi-mca-params.conf (i.e., $prefix/etc/openmpi-mca-params.conf) - The following files are opened and read (in order): 1. $sysconf/openmpi-mca-params.conf 2. $HOME/.openmpi/mca-params.conf Specifically, the values in 2) will override the values in 1) (so users can override system-wide defaults. - Update MCA string params to allow for "~/" in the middle to be expanded to the user's home directory. - Added to default value of MCA parameter component_path to be: $pkglibdir:$HOME/.openmpi/components $pkglibdir is typically $prefix/lib/openmpi. So now both of these directories will be searched for components at run time (in all Open MPI executables, including ompi_info). Note that this is an MCA parameter, so it, too, can be changed at run-time. - Updated all docs to match this behavior -- some is \internal, so it doesn't show unless you tell doxygen to generate internal docs (which is not the default) - update ompi_info to handle new behavior; ompi_info --param now shows the *current* default value (i.e., it will look in the environment and/or files to find out what the default values are -- so if you change a value in $HOME/.openmpi/mca-params.conf, it should be reflected in "ompi_info --param all all") - updated bunches of doxygen docs to match - this diff is slightly artifically large -- some of the changes are converstions to 4 space tabs (I re-indented my own code that previously used 2 space tabs) This commit was SVN r2408. --- etc/Makefile.am | 4 +- etc/openmpi-mca-params.conf | 27 + src/mca/base/Makefile.am | 19 +- src/mca/base/mca_base_component_find.c | 26 +- src/mca/base/mca_base_open.c | 10 +- src/mca/base/mca_base_param.c | 516 ++++++++++++++++---- src/mca/base/mca_base_param.h | 457 +++++++++-------- src/mca/base/mca_base_param_internal.h | 144 ++++-- src/mca/base/mca_base_parse_paramfile.c | 142 ++++++ src/mca/base/mca_base_parse_paramfile_lex.h | 51 ++ src/mca/base/mca_base_parse_paramfile_lex.l | 54 ++ src/mca/base/paramparse.c | 32 ++ src/tools/ompi_info/components.cc | 5 +- src/tools/ompi_info/param.cc | 43 +- 14 files changed, 1154 insertions(+), 376 deletions(-) create mode 100644 etc/openmpi-mca-params.conf create mode 100644 src/mca/base/mca_base_parse_paramfile.c create mode 100644 src/mca/base/mca_base_parse_paramfile_lex.h create mode 100644 src/mca/base/mca_base_parse_paramfile_lex.l create mode 100644 src/mca/base/paramparse.c diff --git a/etc/Makefile.am b/etc/Makefile.am index dd3e4c04bf..a8986f5544 100644 --- a/etc/Makefile.am +++ b/etc/Makefile.am @@ -4,4 +4,6 @@ include $(top_srcdir)/config/Makefile.options -# Placeholder for things to come... +EXTRA_DIST = $(sysconf_DATA) + +sysconf_DATA = openmpi-mca-params.conf diff --git a/etc/openmpi-mca-params.conf b/etc/openmpi-mca-params.conf new file mode 100644 index 0000000000..8f834e187c --- /dev/null +++ b/etc/openmpi-mca-params.conf @@ -0,0 +1,27 @@ +# +# $HEADER$ +# + +# This is the system-wide MCA parameters defaults file. It is +# typically installed in $sysconf/openmpi-mca-params.txt. This file +# can be used to set system-wide default MCA parameters for all users. +# Of course, users can override these values if they want, but this +# file is an excellent location for setting system-specific MCA +# parameters for those users who don't know / care enough to +# investigate the proper values for them. + +# The format is straightforward: one per line, mca_param_name = +# rvalue. Quoting is ignored (so if you use quotes or escape +# characters, they'll be included as part of the value). For example: + +# Disable run-time MPI parameter checking +# mpi_param_check = 0 + +# Note that the value "~/" will be expanded to the current user's home +# directory. For example: + +# Change component loading path +# component_path = /usr/local/lib/openmpi:~/my_openmpi_components + +# See "ompi_info --param all all" for a full listing of Open MPI MCA +# parameters available and their default values. diff --git a/src/mca/base/Makefile.am b/src/mca/base/Makefile.am index a37bdaf475..da510c4b45 100644 --- a/src/mca/base/Makefile.am +++ b/src/mca/base/Makefile.am @@ -7,7 +7,11 @@ include $(top_srcdir)/config/Makefile.options # Need this so that the base knows where to load dynamic components from # (by default) -AM_CPPFLAGS = -DOMPI_PKGLIBDIR=\"$(pkglibdir)\" +AM_CPPFLAGS = \ + -DOMPI_PKGLIBDIR=\"$(pkglibdir)\" \ + -DOMPI_SYSCONFDIR=\"$(sysconfdir)\" +AM_LFLAGS = -Pmca_base_yy +LEX_OUTPUT_ROOT = lex.mca_base_yy noinst_LTLIBRARIES = libmca_base.la @@ -19,7 +23,14 @@ headers = \ mca_base_msgbuf.h \ mca_base_msgbuf_internal.h \ mca_base_param.h \ - mca_base_param_internal.h + mca_base_param_internal.h \ + mca_base_parse_paramfile_lex.h + +# Test program -- to be removed + +noinst_PROGRAMS = paramparse +paramparse_SOURCES = paramparse.c +paramparse_LDADD = libmca_base.la # Library @@ -37,7 +48,9 @@ libmca_base_la_SOURCES = \ mca_base_module_exchange.c \ mca_base_msgbuf.c \ mca_base_open.c \ - mca_base_param.c + mca_base_param.c \ + mca_base_parse_paramfile.c \ + mca_base_parse_paramfile_lex.l # Conditionally install the header files diff --git a/src/mca/base/mca_base_component_find.c b/src/mca/base/mca_base_component_find.c index 9b9b1b4522..3883fda75d 100644 --- a/src/mca/base/mca_base_component_find.c +++ b/src/mca/base/mca_base_component_find.c @@ -181,16 +181,18 @@ static void find_dyn_components(const char *path, const char *type_name, OBJ_CONSTRUCT(&found_files, ompi_list_t); dir = path_to_use; - do { - end = strchr(dir, ':'); - if (NULL != end) { - *end = '\0'; - } - if (0 != lt_dlforeachfile(dir, save_filename, ¶ms)) { - break; - } - dir = end + 1; - } while (NULL != end); + if (NULL != dir) { + do { + end = strchr(dir, ':'); + if (NULL != end) { + *end = '\0'; + } + if (0 != lt_dlforeachfile(dir, save_filename, ¶ms)) { + break; + } + dir = end + 1; + } while (NULL != end); + } /* Iterate through all the filenames that we found. Since one component may [try to] call another to be loaded, only try to load @@ -221,8 +223,10 @@ static void find_dyn_components(const char *path, const char *type_name, if (NULL != param) { free(param); } + if (NULL != path_to_use) { + free(path_to_use); + } OBJ_DESTRUCT(&found_files); - free(path_to_use); } diff --git a/src/mca/base/mca_base_open.c b/src/mca/base/mca_base_open.c index 401fa9bc70..1099ae0490 100644 --- a/src/mca/base/mca_base_open.c +++ b/src/mca/base/mca_base_open.c @@ -9,6 +9,7 @@ #include #include "util/output.h" +#include "util/printf.h" #include "mca/mca.h" #include "mca/base/base.h" @@ -41,11 +42,17 @@ int mca_base_open(void) return OMPI_SUCCESS; } + /* Setup the parameter system */ + + mca_base_param_init(); + /* Register some params */ + asprintf(&value, "%s:~/.openmpi/components", OMPI_PKGLIBDIR); mca_base_param_component_path = mca_base_param_register_string("base", NULL, "component_path", - "component_path", OMPI_PKGLIBDIR); + "component_path", value); + free(value); param_index = mca_base_param_register_string("base", NULL, "verbose", "verbose", NULL); @@ -55,6 +62,7 @@ int mca_base_open(void) memset(&lds, 0, sizeof(lds)); if (NULL != value) { parse_verbose(value, &lds); + free(value); } else { set_defaults(&lds); } diff --git a/src/mca/base/mca_base_param.c b/src/mca/base/mca_base_param.c index f61c731bc5..e3c28403ab 100644 --- a/src/mca/base/mca_base_param.c +++ b/src/mca/base/mca_base_param.c @@ -12,6 +12,8 @@ #include "class/ompi_value_array.h" #include "class/ompi_hash_table.h" #include "attribute/attribute.h" +#include "util/printf.h" +#include "util/argv.h" #include "mca/mca.h" #include "mca/base/mca_base_param.h" #include "mca/base/mca_base_param_internal.h" @@ -25,27 +27,45 @@ * in ompi_info will provide an extern to see this variable. */ ompi_value_array_t mca_base_params; +ompi_list_t mca_base_param_file_values; /* * local variables */ -static char *mca_prefix = "OMPI_MCA_"; +static const char *mca_prefix = "OMPI_MCA_"; +static char *home = NULL; static bool initialized = false; /* * local functions */ +static int read_files(char *file_list); static int param_register(const char *type_name, const char *component_name, const char *param_name, const char *mca_param_name, mca_base_param_type_t type, - mca_base_param_storage_t *default_value); + mca_base_param_storage_t *default_value, + mca_base_param_storage_t *file_value, + mca_base_param_storage_t *override_value); static bool param_lookup(int index, mca_base_param_storage_t *storage, ompi_hash_table_t *attrs); +static bool lookup_keyvals(mca_base_param_t *param, + mca_base_param_storage_t *storage, + ompi_hash_table_t *attrs); +static bool lookup_env(mca_base_param_t *param, + mca_base_param_storage_t *storage); +static bool lookup_file(mca_base_param_t *param, + mca_base_param_storage_t *storage); +static bool lookup_default(mca_base_param_t *param, + mca_base_param_storage_t *storage); +static bool set(mca_base_param_type_t type, + mca_base_param_storage_t *dest, mca_base_param_storage_t *src); static void param_constructor(mca_base_param_t *p); static void param_destructor(mca_base_param_t *p); +static void fv_constructor(mca_base_param_file_value_t *p); +static void fv_destructor(mca_base_param_file_value_t *p); /* @@ -53,6 +73,57 @@ static void param_destructor(mca_base_param_t *p); */ OBJ_CLASS_INSTANCE(mca_base_param_t, ompi_object_t, param_constructor, param_destructor); +OBJ_CLASS_INSTANCE(mca_base_param_file_value_t, ompi_list_item_t, + fv_constructor, fv_destructor); + + + +/* + * Set it up + */ +int mca_base_param_init(void) +{ + int id; + char *files; + + if (!initialized) { + + /* Init the value array for the param storage */ + + OBJ_CONSTRUCT(&mca_base_params, ompi_value_array_t); + ompi_value_array_init(&mca_base_params, sizeof(mca_base_param_t)); + + /* Init the file param value list */ + + OBJ_CONSTRUCT(&mca_base_param_file_values, ompi_list_t); + + /* Set this before we register the parameter, below */ + + initialized = true; + + /* We may need this later */ + + home = getenv("HOME"); + + /* Initialize a parameter that says where MCA param files can + be found */ + + asprintf(&files, + "~/.openmpi/mca-params.conf:%s/openmpi-mca-params.conf", + OMPI_SYSCONFDIR); + id = mca_base_param_register_string("base", NULL, "param_files", + "param_files", files); + free(files); + + /* Read in MCA parameters from files */ + + mca_base_param_lookup_string(id, &files); + read_files(files); + free(files); + } + + return OMPI_SUCCESS; +} /* @@ -68,7 +139,7 @@ int mca_base_param_register_int(const char *type_name, storage.intval = default_value; return param_register(type_name, component_name, param_name, mca_param_name, - MCA_BASE_PARAM_TYPE_INT, &storage); + MCA_BASE_PARAM_TYPE_INT, &storage, NULL, NULL); } @@ -88,7 +159,7 @@ int mca_base_param_register_string(const char *type_name, storage.stringval = NULL; } return param_register(type_name, component_name, param_name, mca_param_name, - MCA_BASE_PARAM_TYPE_STRING, &storage); + MCA_BASE_PARAM_TYPE_STRING, &storage, NULL, NULL); } @@ -121,6 +192,7 @@ int mca_base_param_kv_associate(int index, int keyval) return OMPI_SUCCESS; } + /* * Look up an integer MCA parameter. */ @@ -152,6 +224,14 @@ int mca_base_param_kv_lookup_int(int index, ompi_hash_table_t *attrs, } +/* + * Set an integer parameter + */ +#if 0 +#error JMS: Need to figure out what to do here +#endif + + /* * Look up a string MCA parameter. */ @@ -183,6 +263,14 @@ int mca_base_param_kv_lookup_string(int index, ompi_hash_table_t *attrs, } +/* + * Set an string parameter + */ +#if 0 +#error JMS: Need to figure out what to do here +#endif + + /* * Find the index for an MCA parameter based on its names. */ @@ -230,31 +318,62 @@ int mca_base_param_find(const char *type_name, const char *component_name, */ int mca_base_param_finalize(void) { - mca_base_param_t *array; + ompi_list_item_t *item; + mca_base_param_t *array; - if (initialized) { + if (initialized) { - /* This is slow, but effective :-) */ + /* This is slow, but effective :-) */ - array = OMPI_VALUE_ARRAY_GET_BASE(&mca_base_params, mca_base_param_t); - while (0 < ompi_value_array_get_size(&mca_base_params)) { - OBJ_DESTRUCT(&array[0]); - ompi_value_array_remove_item(&mca_base_params, 0); + array = OMPI_VALUE_ARRAY_GET_BASE(&mca_base_params, mca_base_param_t); + while (ompi_value_array_get_size(&mca_base_params) > 0) { + OBJ_DESTRUCT(&array[0]); + ompi_value_array_remove_item(&mca_base_params, 0); + } + OBJ_DESTRUCT(&mca_base_params); + + for (item = ompi_list_remove_first(&mca_base_param_file_values); + NULL != item; + item = ompi_list_remove_first(&mca_base_param_file_values)) { + OBJ_RELEASE(item); + } + OBJ_DESTRUCT(&mca_base_param_file_values); + initialized = false; } - OBJ_DESTRUCT(&mca_base_params); - initialized = false; - } - return OMPI_SUCCESS; + /* All done */ + + return OMPI_SUCCESS; } /*************************************************************************/ +static int read_files(char *file_list) +{ + int i; + char **files; + + /* Iterate through all the files passed in -- read them in reverse + order so that we preserve unix/shell path-like semantics (i.e., + the entries farthest to the left get precedence) */ + + files = ompi_argv_split(file_list, ':'); + for (i = ompi_argv_count(files) - 1; i >= 0; --i) { + mca_base_parse_paramfile(files[i]); + } + ompi_argv_free(files); + + return OMPI_SUCCESS; +} + + static int param_register(const char *type_name, const char *component_name, const char *param_name, const char *mca_param_name, mca_base_param_type_t type, - mca_base_param_storage_t *default_value) + mca_base_param_storage_t *default_value, + mca_base_param_storage_t *file_value, + mca_base_param_storage_t *override_value) { int ret; size_t i, len; @@ -263,9 +382,7 @@ static int param_register(const char *type_name, const char *component_name, /* Initialize the array if it has never been initialized */ if (!initialized) { - OBJ_CONSTRUCT(&mca_base_params, ompi_value_array_t); - ompi_value_array_init(&mca_base_params, sizeof(mca_base_param_t)); - initialized = true; + mca_base_param_init(); } /* Error check */ @@ -370,6 +487,34 @@ static int param_register(const char *type_name, const char *component_name, memset(¶m.mbp_default_value, 0, sizeof(param.mbp_default_value)); } + /* Figure out the file value; zero it out if a file is not + provided */ + + if (NULL != file_value) { + if (MCA_BASE_PARAM_TYPE_STRING == param.mbp_type && + NULL != file_value->stringval) { + param.mbp_file_value.stringval = strdup(file_value->stringval); + } else { + param.mbp_file_value = *file_value; + } + } else { + memset(¶m.mbp_file_value, 0, sizeof(param.mbp_file_value)); + } + + /* Figure out the override value; zero it out if a override is not + provided */ + + if (NULL != override_value) { + if (MCA_BASE_PARAM_TYPE_STRING == param.mbp_type && + NULL != override_value->stringval) { + param.mbp_override_value.stringval = strdup(override_value->stringval); + } else { + param.mbp_override_value = *override_value; + } + } else { + memset(¶m.mbp_override_value, 0, sizeof(param.mbp_override_value)); + } + /* See if this entry is already in the array */ len = ompi_value_array_get_size(&mca_base_params); @@ -380,9 +525,16 @@ static int param_register(const char *type_name, const char *component_name, /* We found an entry with the same param name. Free the old value (if it was a string */ - if (MCA_BASE_PARAM_TYPE_STRING == array[i].mbp_type && - NULL != array[i].mbp_default_value.stringval) { - free(array[i].mbp_default_value.stringval); + if (MCA_BASE_PARAM_TYPE_STRING == array[i].mbp_type) { + if (NULL != array[i].mbp_default_value.stringval) { + free(array[i].mbp_default_value.stringval); + } + if (NULL != array[i].mbp_file_value.stringval) { + free(array[i].mbp_file_value.stringval); + } + if (NULL != array[i].mbp_override_value.stringval) { + free(array[i].mbp_override_value.stringval); + } } /* Now put in the new value */ @@ -394,9 +546,25 @@ static int param_register(const char *type_name, const char *component_name, } else { array[i].mbp_default_value.stringval = NULL; } + if (NULL != param.mbp_file_value.stringval) { + array[i].mbp_file_value.stringval = + strdup(param.mbp_file_value.stringval); + } else { + array[i].mbp_file_value.stringval = NULL; + } + if (NULL != param.mbp_override_value.stringval) { + array[i].mbp_override_value.stringval = + strdup(param.mbp_override_value.stringval); + } else { + array[i].mbp_override_value.stringval = NULL; + } } else { array[i].mbp_default_value.intval = param.mbp_default_value.intval; + array[i].mbp_file_value.intval = + param.mbp_file_value.intval; + array[i].mbp_override_value.intval = + param.mbp_override_value.intval; } /* Just in case we changed type */ @@ -422,43 +590,89 @@ static int param_register(const char *type_name, const char *component_name, /* - * Lookup a parameter + * Lookup a parameter in multiple places */ static bool param_lookup(int index, mca_base_param_storage_t *storage, ompi_hash_table_t *attrs) { - size_t size; - char *env; + size_t size; + mca_base_param_t *array; + char *p, *q; + + /* Lookup the index and see if it's valid */ + + if (!initialized) { + return false; + } + size = ompi_value_array_get_size(&mca_base_params); + if (index > size) { + return false; + } + array = OMPI_VALUE_ARRAY_GET_BASE(&mca_base_params, mca_base_param_t); + + /* Ensure that MCA param has a good type */ + + if (MCA_BASE_PARAM_TYPE_INT != array[index].mbp_type && + MCA_BASE_PARAM_TYPE_STRING != array[index].mbp_type) { + return false; + } + + /* Check all the places that the param may be hiding, in priority + order */ + + if (lookup_keyvals(&array[index], storage, attrs) || + lookup_env(&array[index], storage) || + lookup_file(&array[index], storage) || + lookup_default(&array[index], storage)) { + + /* If we're returning a string, replace all instances of "~/" + with the user's home directory */ + + if (MCA_BASE_PARAM_TYPE_STRING == array[index].mbp_type && + NULL != storage->stringval) { + if (0 == strncmp(storage->stringval, "~/", 2)) { + asprintf(&p, "%s/%s", home, storage->stringval + 2); + free(storage->stringval); + storage->stringval = p; + } + + p = strstr(storage->stringval, ":~/"); + while (NULL != p) { + *p = '\0'; + asprintf(&q, "%s:%s%s", storage->stringval, home, p + 2); + free(storage->stringval); + storage->stringval = q; + p = strstr(storage->stringval, ":~/"); + } + } + + return true; + } + + /* Didn't find it. Doh! */ + + return false; +} + + +/* + * Lookup a param in the set of attributes/keyvals + */ +static bool lookup_keyvals(mca_base_param_t *param, + mca_base_param_storage_t *storage, + ompi_hash_table_t *attrs) +{ int err, flag; - mca_base_param_t *array; - - /* Lookup the index and see if it's valid */ - - if (!initialized) { - return false; - } - if (ompi_value_array_get_size(&mca_base_params) < index) { - return false; - } - size = ompi_value_array_get_size(&mca_base_params); - array = OMPI_VALUE_ARRAY_GET_BASE(&mca_base_params, mca_base_param_t); - - /* Ensure that MCA param has a good type */ - - if (MCA_BASE_PARAM_TYPE_INT != array[index].mbp_type && - MCA_BASE_PARAM_TYPE_STRING != array[index].mbp_type) { - return false; - } /* If this param has a keyval and we were provided with a hash table, look it up and see if we can find a value */ - if (-1 != array[index].mbp_keyval) { + if (-1 != param->mbp_keyval) { /* Use the stringval member of the union because it's definitely big enough to handle both (int) and (char*) */ - err = ompi_attr_get(attrs, array[index].mbp_keyval, + err = ompi_attr_get(attrs, param->mbp_keyval, &storage->stringval, &flag); if (OMPI_SUCCESS == err && 1 == flag) { @@ -466,7 +680,7 @@ static bool param_lookup(int index, mca_base_param_storage_t *storage, must grab the lower sizeof(int) bytes from the (char*) in stringval, in case sizeof(int) != sizeof(char*). */ - if (MCA_BASE_PARAM_TYPE_INT == array[index].mbp_type) { + if (MCA_BASE_PARAM_TYPE_INT == param->mbp_type) { storage->intval = *((int *) (storage->stringval + sizeof(void *) - sizeof(int))); } @@ -478,42 +692,122 @@ static bool param_lookup(int index, mca_base_param_storage_t *storage, } } - /* We either don't have a keyval or didn't find it. So look in the - environment. */ + /* Either this param has not keyval or we didn't find the keyval */ - if (NULL != array[index].mbp_env_var_name && - NULL != (env = getenv(array[index].mbp_env_var_name))) { - if (MCA_BASE_PARAM_TYPE_INT == array[index].mbp_type) { + return false; +} + + +/* + * Lookup a param in the environment + */ +static bool lookup_env(mca_base_param_t *param, + mca_base_param_storage_t *storage) +{ + char *env; + + if (NULL != param->mbp_env_var_name && + NULL != (env = getenv(param->mbp_env_var_name))) { + if (MCA_BASE_PARAM_TYPE_INT == param->mbp_type) { storage->intval = atoi(env); - } else if (MCA_BASE_PARAM_TYPE_STRING == array[index].mbp_type) { + } else if (MCA_BASE_PARAM_TYPE_STRING == param->mbp_type) { storage->stringval = strdup(env); } return true; } - /* Didn't find it; use the default value. */ + /* Didn't find it */ - switch (array[index].mbp_type) { - case MCA_BASE_PARAM_TYPE_INT: - storage->intval = array[index].mbp_default_value.intval; - break; + return false; +} - case MCA_BASE_PARAM_TYPE_STRING: - if (NULL != array[index].mbp_default_value.stringval) { - storage->stringval = strdup(array[index].mbp_default_value.stringval); - } else { - storage->stringval = NULL; + +/* + * Lookup a param in the files + */ +static bool lookup_file(mca_base_param_t *param, + mca_base_param_storage_t *storage) +{ + ompi_list_item_t *item; + mca_base_param_file_value_t *fv; + + /* See if we previously found a match from a file. If so, just + return that */ + + if (param->mbp_file_value_set) { + return set(param->mbp_type, storage, ¶m->mbp_file_value); + } + + /* Scan through the list of values read in from files and try to + find a match. If we do, cache it on the param (for future + lookups) and save it in the storage. */ + + for (item = ompi_list_get_first(&mca_base_param_file_values); + ompi_list_get_end(&mca_base_param_file_values) != item; + item = ompi_list_get_next(item)) { + fv = (mca_base_param_file_value_t *) item; + if (0 == strcmp(fv->mbpfv_param, param->mbp_full_name)) { + if (MCA_BASE_PARAM_TYPE_INT == param->mbp_type) { + if (NULL != fv->mbpfv_value) { + param->mbp_file_value.intval = atoi(fv->mbpfv_value); + } else { + param->mbp_file_value.intval = 0; + } + } else { + param->mbp_file_value.stringval = fv->mbpfv_value; + fv->mbpfv_value = NULL; + } + param->mbp_file_value_set = true; + + /* Since this is now cached on the param, we might as well + remove it from the list and make future file lookups + faster */ + + ompi_list_remove_item(&mca_base_param_file_values, + (ompi_list_item_t *) fv); + OBJ_RELEASE(fv); + + return set(param->mbp_type, storage, ¶m->mbp_file_value); + } } - break; - default: return false; - } +} - /* All done */ - return true; +/* + * Return the default value for a param + */ +static bool lookup_default(mca_base_param_t *param, + mca_base_param_storage_t *storage) +{ + return set(param->mbp_type, storage, ¶m->mbp_default_value); +} + + +static bool set(mca_base_param_type_t type, + mca_base_param_storage_t *dest, mca_base_param_storage_t *src) +{ + switch (type) { + case MCA_BASE_PARAM_TYPE_INT: + dest->intval = src->intval; + break; + + case MCA_BASE_PARAM_TYPE_STRING: + if (NULL != src->stringval) { + dest->stringval = strdup(src->stringval); + } else { + dest->stringval = NULL; + } + break; + + default: + return false; + break; + } + + return true; } @@ -522,16 +816,21 @@ static bool param_lookup(int index, mca_base_param_storage_t *storage, */ static void param_constructor(mca_base_param_t *p) { - p->mbp_type = MCA_BASE_PARAM_TYPE_MAX; + p->mbp_type = MCA_BASE_PARAM_TYPE_MAX; - p->mbp_type_name = NULL; - p->mbp_component_name = NULL; - p->mbp_param_name = NULL; - p->mbp_full_name = NULL; + p->mbp_type_name = NULL; + p->mbp_component_name = NULL; + p->mbp_param_name = NULL; + p->mbp_full_name = NULL; - p->mbp_keyval = -1; - p->mbp_env_var_name = NULL; - p->mbp_default_value.stringval = NULL; + p->mbp_keyval = -1; + p->mbp_env_var_name = NULL; + + p->mbp_default_value.stringval = NULL; + p->mbp_file_value_set = false; + p->mbp_file_value.stringval = NULL; + p->mbp_override_value_set = false; + p->mbp_override_value.stringval = NULL; } @@ -540,23 +839,50 @@ static void param_constructor(mca_base_param_t *p) */ static void param_destructor(mca_base_param_t *p) { - if (NULL != p->mbp_type_name) { - free(p->mbp_type_name); - } - if (NULL != p->mbp_component_name) { - free(p->mbp_component_name); - } - if (NULL != p->mbp_param_name) { - free(p->mbp_param_name); - } - if (NULL != p->mbp_env_var_name) { - free(p->mbp_env_var_name); - } - if (NULL != p->mbp_full_name) { - free(p->mbp_full_name); - } - if (MCA_BASE_PARAM_TYPE_STRING == p->mbp_type && - NULL != p->mbp_default_value.stringval) { - free(p->mbp_default_value.stringval); - } + if (NULL != p->mbp_type_name) { + free(p->mbp_type_name); + } + if (NULL != p->mbp_component_name) { + free(p->mbp_component_name); + } + if (NULL != p->mbp_param_name) { + free(p->mbp_param_name); + } + if (NULL != p->mbp_env_var_name) { + free(p->mbp_env_var_name); + } + if (NULL != p->mbp_full_name) { + free(p->mbp_full_name); + } + if (MCA_BASE_PARAM_TYPE_STRING == p->mbp_type) { + if (NULL != p->mbp_default_value.stringval) { + free(p->mbp_default_value.stringval); + } + if (p->mbp_file_value_set && + NULL != p->mbp_file_value.stringval) { + free(p->mbp_file_value.stringval); + } + if (p->mbp_override_value_set && + NULL != p->mbp_override_value.stringval) { + free(p->mbp_override_value.stringval); + } + } +} + + +static void fv_constructor(mca_base_param_file_value_t *f) +{ + f->mbpfv_param = NULL; + f->mbpfv_value = NULL; +} + + +static void fv_destructor(mca_base_param_file_value_t *f) +{ + if (NULL != f->mbpfv_param) { + free(f->mbpfv_param); + } + if (NULL != f->mbpfv_value) { + free(f->mbpfv_value); + } } diff --git a/src/mca/base/mca_base_param.h b/src/mca/base/mca_base_param.h index 9c03c6eff1..75f574ebf6 100644 --- a/src/mca/base/mca_base_param.h +++ b/src/mca/base/mca_base_param.h @@ -20,6 +20,21 @@ * -# Lookup an attribute parameter on a specific index and * communicator / datatype / window. * + * MCA parameters can be defined in multiple different places. As + * such, parameters are \em resolved to find their value. The order + * of resolution is as follows: + * + * - An "override" location that is only available to be set via the + * mca_base_param API. + * - If the parameter has an MPI attribute keyval associated with it, + * see if there is a value assigned that can be used. + * - Look for an environment variable corresponding to the MCA + * parameter. + * - See if a file contains the MCA parameter (MCA parameter files are + * read only once -- when the first time any mca_param_t function is + * invoked). + * - If nothing else was found, use the parameter's default value. + * * Note that there is a second header file (mca_base_param_internal.h) * that contains several internal type delcarations for the parameter * system. The internal file is only used within the parameter system @@ -40,227 +55,239 @@ #if defined(c_plusplus) || defined(__cplusplus) extern "C" { #endif - /** - * Register an integer MCA parameter. - * - * @param type_name[in] The MCA type (string). - * @param component_name[in] The name of the component (string). - * @param param_name[in] The name of the parameter being registered - * (string). - * @param mca_param_name[in] Optional parameter to override the - * user-visible name of this parameter (string). - * @param default_value[in] The value that is used for this - * parameter if the user does not supply one. - * - * @retval OMPI_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 component. - * - * The default resulting MCA parameter name is - * {type_name}[_{component_name}][_{param_name}]. - * - * {component_name} is only included if it is non-NULL. All - * components an should include their name; component frameworks - * should pass "base". It is only permissible for the MCA base - * itself to pass NULL for the component_name. - * - * Likewise, {param_name} is also only included if it is non-NULL. - * Components and frameworks can pass NULL for this parameter if - * they wish. - * - * In most cases, mca_param_name should be NULL, in which case the - * user-visible name of this parameter will be the default form (as - * described above). Only in rare cases is it necessary (or - * advisable) to override the default name -- its use is strongly - * discouraged. - * - * It is permissable to register a (type_name, component_name, - * param_name) triple more than once; the same index value will be - * returned, but the default value will be changed to reflect the - * last registration. - */ - int mca_base_param_register_int(const char *type_name, - const char *component_name, - const char *param_name, - const char *mca_param_name, - int default_value); + /** + * Initialize the MCA parameter system. + * + * @retval OMPI_SUCCESS + * + * This function initalizes the MCA parameter system. It is + * invoked internally (by mca_base_open()) and is only documented + * here for completeness. + */ + int mca_base_param_init(void); - /** - * Register a string MCA parameter. - * - * @param type_name[in] The MCA type (string). - * @param component_name[in] The name of the component (string). - * @param param_name[in] The name of the parameter being registered - * (string). - * @param mca_param_name[in] Optional parameter to override the - * user-visible name of this parameter (string). - * @param default_value[in] The value that is used for this - * parameter if the user does not supply one. - * - * @retval OMPI_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 is identical to mca_base_param_register_int() - * except that you are registering a string parameter with an - * associated string default value (which is allowed to be NULL). - * See mca_base_param_register_int() for all other details. - */ - int mca_base_param_register_string(const char *type_name, - const char *component_name, - const char *param_name, - const char *mca_param_name, - const char *default_value); + /** + * Register an integer MCA parameter. + * + * @param type_name[in] The MCA type (string). + * @param component_name[in] The name of the component (string). + * @param param_name[in] The name of the parameter being registered + * (string). + * @param mca_param_name[in] Optional parameter to override the + * user-visible name of this parameter (string). + * @param default_value[in] The value that is used for this + * parameter if the user does not supply one. + * + * @retval OMPI_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 component. + * + * The default resulting MCA parameter name is + * {type_name}[_{component_name}][_{param_name}]. + * + * {component_name} is only included if it is non-NULL. All + * components an should include their name; component frameworks + * should pass "base". It is only permissible for the MCA base + * itself to pass NULL for the component_name. + * + * Likewise, {param_name} is also only included if it is non-NULL. + * Components and frameworks can pass NULL for this parameter if + * they wish. + * + * In most cases, mca_param_name should be NULL, in which case the + * user-visible name of this parameter will be the default form (as + * described above). Only in rare cases is it necessary (or + * advisable) to override the default name -- its use is strongly + * discouraged. + * + * It is permissable to register a (type_name, component_name, + * param_name) triple more than once; the same index value will be + * returned, but the default value will be changed to reflect the + * last registration. + */ + int mca_base_param_register_int(const char *type_name, + const char *component_name, + const char *param_name, + const char *mca_param_name, + int default_value); + + /** + * Register a string MCA parameter. + * + * @param type_name[in] The MCA type (string). + * @param component_name[in] The name of the component (string). + * @param param_name[in] The name of the parameter being registered + * (string). + * @param mca_param_name[in] Optional parameter to override the + * user-visible name of this parameter (string). + * @param default_value[in] The value that is used for this + * parameter if the user does not supply one. + * + * @retval OMPI_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 is identical to mca_base_param_register_int() + * except that you are registering a string parameter with an + * associated string default value (which is allowed to be NULL). + * See mca_base_param_register_int() for all other details. + */ + int mca_base_param_register_string(const char *type_name, + const char *component_name, + const char *param_name, + const char *mca_param_name, + const char *default_value); - /** - * Associate a communicator/datatype/window keyval with an MCA - * parameter. - * - * @param index The index of the parameter to use. - * @param keyval The keyval to associate it with. - * - * @returns OMPI_SUCCESS Upon success. - * @returns OMPI_ERROR If the index value is invalid. - * - * For an index value that was previously returned by - * mca_base_param_register_int() or - * mca_base_param_register_string(), the corresponding MCA parameter - * can be associated with a communicator, datatype, or window - * attribute keyval. - * - * After using this function, you can use any of the four lookup - * functions (mca_base_param_lookup_int(), - * mca_base_param_lookup_string(), mca_base_param_kv_lookup_int(), - * and mca_base_param_kv_lookup_string()), but only the "kv" - * versions will cross reference and attempt to find parameter - * values on attributes. - */ - int mca_base_param_kv_associate(int index, int keyval); + /** + * Associate a communicator/datatype/window keyval with an MCA + * parameter. + * + * @param index The index of the parameter to use. + * @param keyval The keyval to associate it with. + * + * @returns OMPI_SUCCESS Upon success. + * @returns OMPI_ERROR If the index value is invalid. + * + * For an index value that was previously returned by + * mca_base_param_register_int() or + * mca_base_param_register_string(), the corresponding MCA parameter + * can be associated with a communicator, datatype, or window + * attribute keyval. + * + * After using this function, you can use any of the four lookup + * functions (mca_base_param_lookup_int(), + * mca_base_param_lookup_string(), mca_base_param_kv_lookup_int(), + * and mca_base_param_kv_lookup_string()), but only the "kv" + * versions will cross reference and attempt to find parameter + * values on attributes. + */ + int mca_base_param_kv_associate(int index, int keyval); - /** - * 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 OMPI_ERROR Upon failure. The contents of value are - * undefined. - * @retvalue OMPI_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); + /** + * 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 OMPI_ERROR Upon failure. The contents of value are + * undefined. + * @retvalue OMPI_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); + + /** + * Look up an integer MCA parameter, to include looking in + * attributes. + * + * @param index Index previous returned from + * mca_base_param_register_int(). + * @param attr Object containing attributes to be searched. + * @param value Pointer to int where the parameter value will + * be stored. + * + * @retvalue OMPI_ERROR Upon failure. The contents of value are + * undefined. + * @retvalue OMPI_SUCCESS Upon success. value will be filled with the + * parameter's current value. + * + * This function is identical to mca_base_param_lookup_int() except + * that it looks in attributes \em first to find the parameter + * value. The function mca_base_param_kv_associate() must have been + * called first to associate a keyval with the index. + */ + int mca_base_param_kv_lookup_int(int index, + struct ompi_hash_table_t *attrs, + int *value); + + /** + * 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 OMPI_ERROR Upon failure. The contents of value are + * undefined. + * @retvalue OMPI_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); - /** - * Look up an integer MCA parameter, to include looking in - * attributes. - * - * @param index Index previous returned from - * mca_base_param_register_int(). - * @param attr Object containing attributes to be searched. - * @param value Pointer to int where the parameter value will - * be stored. - * - * @retvalue OMPI_ERROR Upon failure. The contents of value are - * undefined. - * @retvalue OMPI_SUCCESS Upon success. value will be filled with the - * parameter's current value. - * - * This function is identical to mca_base_param_lookup_int() except - * that it looks in attributes \em first to find the parameter - * value. The function mca_base_param_kv_associate() must have been - * called first to associate a keyval with the index. - */ - int mca_base_param_kv_lookup_int(int index, struct ompi_hash_table_t *attrs, - int *value); + /** + * Look up a string MCA parameter, to include looking in attributes. + * + * @param index[in] Index previous returned from + * mca_base_param_register_string(). + * @param attr[in] Object containing attributes to be searched. + * @param value[out] Pointer to (char *) where the parameter value + * will be stored. + * + * @retvalue OMPI_ERROR Upon failure. The contents of value are + * undefined. + * @retvalue OMPI_SUCCESS Upon success. value will be filled with the + * parameter's current value. + * + * This function is identical to mca_base_param_lookup_string() + * except that it looks in attributes \em first to find the + * parameter value. The function mca_base_param_kv_associate() must + * have been called first to associate a keyval with the index. + */ + int mca_base_param_kv_lookup_string(int index, + struct ompi_hash_table_t *attrs, + char **value); - /** - * 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 OMPI_ERROR Upon failure. The contents of value are - * undefined. - * @retvalue OMPI_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); - - /** - * Look up a string MCA parameter, to include looking in attributes. - * - * @param index[in] Index previous returned from - * mca_base_param_register_string(). - * @param attr[in] Object containing attributes to be searched. - * @param value[out] Pointer to (char *) where the parameter value - * will be stored. - * - * @retvalue OMPI_ERROR Upon failure. The contents of value are - * undefined. - * @retvalue OMPI_SUCCESS Upon success. value will be filled with the - * parameter's current value. - * - * This function is identical to mca_base_param_lookup_string() - * except that it looks in attributes \em first to find the - * parameter value. The function mca_base_param_kv_associate() must - * have been called first to associate a keyval with the index. - */ - int mca_base_param_kv_lookup_string(int index, - struct ompi_hash_table_t *attrs, - char **value); - - /** - * Find the index for an MCA parameter based on its names. - * - * @param type_name Name of the type containing the parameter. - * @param component_name Name of the component containing the parameter. - * @param param_name Name of the parameter. - * - * @retval OMPI_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 component -- 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, const char *component, - const char *param); - - /** - * Shut down the MCA parameter system (normally only invoked by the - * MCA framework itself). - * - * @returns OMPI_SUCCESS This function never fails. - * - * This function shuts down the MCA parameter repository 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); + /** + * Find the index for an MCA parameter based on its names. + * + * @param type_name Name of the type containing the parameter. + * @param component_name Name of the component containing the parameter. + * @param param_name Name of the parameter. + * + * @retval OMPI_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 component -- 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, const char *component, + const char *param); + /** + * Shut down the MCA parameter system (normally only invoked by the + * MCA framework itself). + * + * @returns OMPI_SUCCESS This function never fails. + * + * This function shuts down the MCA parameter repository 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); + #if defined(c_plusplus) || defined(__cplusplus) } #endif diff --git a/src/mca/base/mca_base_param_internal.h b/src/mca/base/mca_base_param_internal.h index fe869a0d7a..5dad9d52ed 100644 --- a/src/mca/base/mca_base_param_internal.h +++ b/src/mca/base/mca_base_param_internal.h @@ -2,10 +2,17 @@ * $HEADER$ */ -/** @file This is the private declarations for the MCA parameter - * system. This file is internal to the MCA parameter system and - * should not need to be used by any other elements in Open MPI except - * the special case of the ompi_info command. +/** + * @file + * + * This is the private declarations for the MCA parameter system. + * This file is internal to the MCA parameter system and should not + * need to be used by any other elements in Open MPI except the + * special case of the ompi_info command. + * + * All the rest of the doxygen documentation in this file is marked as + * "internal" and won't show up unless you specifically tell doxygen + * to generate internal documentation (by default, it is skipped). */ #ifndef OMPI_MCA_BASE_PARAM_INTERNAL_H @@ -14,70 +21,139 @@ #include "mpi.h" #include "class/ompi_object.h" +#include "class/ompi_list.h" #include "class/ompi_hash_table.h" /** + * \internal + * * Types for MCA parameters. */ typedef union { - int intval; - /**< Integer value */ - char *stringval; - /**< String value */ + /** Integer value */ + int intval; + /** String value */ + char *stringval; } mca_base_param_storage_t; /** + * \internal + * * The following types are really in this public .h file so that * ompi_info can see them. No one else should use them! */ typedef enum { - MCA_BASE_PARAM_TYPE_INT, - /**< The parameter is of type integer. */ - MCA_BASE_PARAM_TYPE_STRING, - /**< The parameter is of type string. */ - - MCA_BASE_PARAM_TYPE_MAX - /**< Maximum parameter type. */ + /** The parameter is of type integer. */ + MCA_BASE_PARAM_TYPE_INT, + /** The parameter is of type string. */ + MCA_BASE_PARAM_TYPE_STRING, + + /** Maximum parameter type. */ + MCA_BASE_PARAM_TYPE_MAX } mca_base_param_type_t; /** + * \internal + * * Entry for holding the information about an MCA parameter and its * default value. */ struct mca_base_param_t { - ompi_object_t mbp_super; - /**< Allow this to be an OMPI OBJ */ + /** Allow this to be an OMPI OBJ */ + ompi_object_t mbp_super; - mca_base_param_type_t mbp_type; - /**< Enum indicating the type of the parameter (integer or string) */ - char *mbp_type_name; - /**< String of the type name, or NULL */ - char *mbp_component_name; - /**< String of the component name */ - char *mbp_param_name; - /**< String of the parameter name */ - char *mbp_full_name; - /**< Full parameter name, in case it is not - __ */ + /** Enum indicating the type of the parameter (integer or string) */ + mca_base_param_type_t mbp_type; + /** String of the type name, or NULL */ + char *mbp_type_name; + /** String of the component name */ + char *mbp_component_name; + /** String of the parameter name */ + char *mbp_param_name; + /** Full parameter name, in case it is not + __ */ + char *mbp_full_name; - int mbp_keyval; - /**< Keyval value for MPI attribute parameters */ - char *mbp_env_var_name; - /**< Environment variable name */ + /** Keyval value for MPI attribute parameters */ + int mbp_keyval; + /** Environment variable name */ + char *mbp_env_var_name; - mca_base_param_storage_t mbp_default_value; - /**< Default value of the parameter */ + /** Default value of the parameter */ + mca_base_param_storage_t mbp_default_value; + + /** Whether or not we have a file value */ + bool mbp_file_value_set; + /** Value of the parameter found in a file */ + mca_base_param_storage_t mbp_file_value; + + /** Whether or not we have an override value */ + bool mbp_override_value_set; + /** Value of the parameter override set via API */ + mca_base_param_storage_t mbp_override_value; }; /** + * \internal + * * Convenience typedef. */ typedef struct mca_base_param_t mca_base_param_t; /** + * \internal + * * Object delcataion for mca_base_param_t */ OBJ_CLASS_DECLARATION(mca_base_param_t); +/** + * \internal + * + * Structure for holding param names and values read in from files. + */ +struct mca_base_param_file_value_t { + /** Allow this to be an OMPI OBJ */ + ompi_list_item_t super; + + /** Parameter name */ + char *mbpfv_param; + /** Parameter value */ + char *mbpfv_value; +}; +/** + * \internal + * + * Convenience typedef + */ +typedef struct mca_base_param_file_value_t mca_base_param_file_value_t; + +/** + * Object declaration for mca_base_param_file_value_t + */ +OBJ_CLASS_DECLARATION(mca_base_param_file_value_t); + + +/** + * \internal + * + * Global list of params and values read in from MCA parameter files + */ +extern ompi_list_t mca_base_param_file_values; + + +#if defined(c_plusplus) || defined(__cplusplus) +extern "C" { +#endif + /** + * \internal + * + * Parse a parameter file. + */ + int mca_base_parse_paramfile(const char *paramfile); +#if defined(c_plusplus) || defined(__cplusplus) +} +#endif + #endif /* OMPI_MCA_BASE_PARAM_INTERNAL_H */ diff --git a/src/mca/base/mca_base_parse_paramfile.c b/src/mca/base/mca_base_parse_paramfile.c new file mode 100644 index 0000000000..904f6e4fd2 --- /dev/null +++ b/src/mca/base/mca_base_parse_paramfile.c @@ -0,0 +1,142 @@ +/* + * $HEADER$ + */ + +#include "ompi_config.h" + +#include + +#include "class/ompi_list.h" +#include "util/output.h" +#include "mca/mca.h" +#include "mca/base/base.h" +#include "mca/base/mca_base_param_internal.h" +#include "mca/base/mca_base_parse_paramfile_lex.h" + + +static int parse_line(void); +static void save_value(char *name, char *value); +static void parse_error(void); + + +int mca_base_parse_paramfile(const char *paramfile) +{ + int val; + + /* Open the parameter file */ + + mca_base_yyin = fopen(paramfile, "r"); + if (NULL == mca_base_yyin) { + return OMPI_ERR_NOT_FOUND; + } + + mca_base_parse_done = false; + while (!mca_base_parse_done) { + val = mca_base_yylex(); + switch (val) { + case MCA_BASE_PARSE_DONE: + /* This will also set mca_base_parse_done to true, so just + break here */ + break; + + case MCA_BASE_PARSE_NEWLINE: + /* blank line! ignore it */ + break; + + case MCA_BASE_PARSE_SINGLE_WORD: + parse_line(); + break; + + default: + /* anything else is an error */ + parse_error(); + break; + } + } + fclose(mca_base_yyin); + + return OMPI_SUCCESS; +} + + +static int parse_line(void) +{ + int val; + char *name; + + /* Save the parameter name */ + + name = strdup(mca_base_yytext); + + /* The first thing we have to see is an "=" */ + + val = mca_base_yylex(); + if (mca_base_parse_done || MCA_BASE_PARSE_EQUAL != val) { + parse_error(); + free(name); + return OMPI_ERROR; + } + + /* Next we get the value */ + + val = mca_base_yylex(); + if (MCA_BASE_PARSE_SINGLE_WORD == val || + MCA_BASE_PARSE_VALUE == val) { + save_value(name, mca_base_yytext); + return OMPI_SUCCESS; + } + + /* Did we get an EOL or EOF? */ + + else if (MCA_BASE_PARSE_DONE == val || + MCA_BASE_PARSE_NEWLINE == val) { + save_value(name, NULL); + return OMPI_SUCCESS; + } + + /* Nope -- we got something unexpected. Bonk! */ + + parse_error(); + free(name); + return OMPI_ERROR; +} + + +static void save_value(char *name, char *value) +{ + ompi_list_item_t *item; + mca_base_param_file_value_t *fv; + + /* First traverse through the list and ensure that we don't + already have a param of this name. If we do, just replace the + value. */ + + for (item = ompi_list_get_first(&mca_base_param_file_values); + ompi_list_get_end(&mca_base_param_file_values) != item; + item = ompi_list_get_next(item)) { + fv = (mca_base_param_file_value_t *) item; + if (0 == strcmp(name, fv->mbpfv_param)) { + free(name); + free(fv->mbpfv_value); + fv->mbpfv_value = strdup(value); + return; + } + } + + /* We didn't already have the param, so append it to the list */ + + fv = OBJ_NEW(mca_base_param_file_value_t); + if (NULL != fv) { + fv->mbpfv_param = name; + fv->mbpfv_value = strdup(value); + ompi_list_append(&mca_base_param_file_values, (ompi_list_item_t*) fv); + } +} + + +static void parse_error(void) +{ + /* JMS need better error/warning message here */ + ompi_output(0, "paramfile: error reading file at line %d, %s\n", + mca_base_yynewlines, mca_base_yytext); +} diff --git a/src/mca/base/mca_base_parse_paramfile_lex.h b/src/mca/base/mca_base_parse_paramfile_lex.h new file mode 100644 index 0000000000..36a3d2bf79 --- /dev/null +++ b/src/mca/base/mca_base_parse_paramfile_lex.h @@ -0,0 +1,51 @@ +/* -*- C -*- + * + * $HEADER$ + */ + +#ifndef MCA_BASE_PARSE_PARAMFILE_LEX_H_ +#define MCA_BASE_PARSE_PARAMFILE_LEX_H_ + +#include "ompi_config.h" + +#ifdef malloc +#undef malloc +#endif +#ifdef realloc +#undef realloc +#endif +#ifdef free +#undef free +#endif + +#include + +extern int mca_base_yylex(void); + +extern FILE *mca_base_yyin; +extern bool mca_base_parse_done; +extern char *mca_base_yytext; +extern int mca_base_yynewlines; + +/* + * Make lex-generated files not issue compiler warnings + */ +#define YY_STACK_USED 0 +#define YY_ALWAYS_INTERACTIVE 0 +#define YY_NEVER_INTERACTIVE 0 +#define YY_MAIN 0 +#define YY_NO_UNPUT 1 + +enum { + MCA_BASE_PARSE_DONE, + MCA_BASE_PARSE_ERROR, + + MCA_BASE_PARSE_NEWLINE, + MCA_BASE_PARSE_EQUAL, + MCA_BASE_PARSE_SINGLE_WORD, + MCA_BASE_PARSE_VALUE, + + MCA_BASE_PARSE_MAX +}; + +#endif diff --git a/src/mca/base/mca_base_parse_paramfile_lex.l b/src/mca/base/mca_base_parse_paramfile_lex.l new file mode 100644 index 0000000000..d4d64e56ff --- /dev/null +++ b/src/mca/base/mca_base_parse_paramfile_lex.l @@ -0,0 +1,54 @@ +%{ /* -*- C -*- */ + +#include +#include "mca/base/mca_base_parse_paramfile_lex.h" + +/* + * local functions + */ +static int mca_base_yyerror(void); +static int mca_base_yywrap(void); + +/* + * global variables + */ +int mca_base_yynewlines = 1; +bool mca_base_parse_done = false; +char *mca_base_string = NULL; + +%} + +WHITE [\f\t\v ] +CHAR [A-Za-z0-9_\-\.] + +%x VALUE + +%% + +{WHITE}*\n { mca_base_yynewlines++; return MCA_BASE_PARSE_NEWLINE; } +#.*\n { mca_base_yynewlines++; return MCA_BASE_PARSE_NEWLINE; } + +{WHITE}*"="{WHITE}* { BEGIN(VALUE); return MCA_BASE_PARSE_EQUAL; } +{WHITE}+ ; /* whitespace */ +{CHAR}+ { return MCA_BASE_PARSE_SINGLE_WORD; } + +{WHITE}*\n { BEGIN(INITIAL); } +[^\n]*[^\t \n]/[\t ]*\n { return MCA_BASE_PARSE_VALUE; } + +. { return MCA_BASE_PARSE_ERROR; } + +%% + + +static int mca_base_yyerror(void) +{ + printf("%d: Invalid input (%s)\n", mca_base_yynewlines, mca_base_yytext); + return MCA_BASE_PARSE_ERROR; +} + + +static int mca_base_yywrap(void) +{ + mca_base_parse_done = true; + return 1; +} diff --git a/src/mca/base/paramparse.c b/src/mca/base/paramparse.c new file mode 100644 index 0000000000..5fc293ea1f --- /dev/null +++ b/src/mca/base/paramparse.c @@ -0,0 +1,32 @@ +/* -*- C -*- + * + * $HEADER$ + * + */ + +#include "mca/base/base.h" +#include "mca/base/mca_base_parse_paramfile_lex.h" + +#include +#include + +extern int mca_base_yylex(void); +extern FILE *mca_base_yyin; + +int main(int argc, char *argv[]) +{ + int ret; + + if (argc != 2) { + printf("usage: %s \n", argv[0]); + exit(1); + } + + mca_base_yyin = fopen(argv[1], "r"); + while (!mca_base_parse_done) { + ret = mca_base_yylex(); + printf("%d: [%s]\n", ret, mca_base_yytext); + } + + return 0; +} diff --git a/src/tools/ompi_info/components.cc b/src/tools/ompi_info/components.cc index 246dcfe9c0..f0b8bf0f8f 100644 --- a/src/tools/ompi_info/components.cc +++ b/src/tools/ompi_info/components.cc @@ -85,13 +85,16 @@ void ompi_info::open_components() } } + // Open up the MCA + + mca_base_open(); + // Register the MPI layer's MCA parameters ompi_mpi_register_params(); // Find / open all components - mca_base_open(); component_map["base"] = NULL; mca_allocator_base_open(); diff --git a/src/tools/ompi_info/param.cc b/src/tools/ompi_info/param.cc index a819c549f4..fe413e120a 100644 --- a/src/tools/ompi_info/param.cc +++ b/src/tools/ompi_info/param.cc @@ -12,6 +12,7 @@ #include #include "class/ompi_value_array.h" +#include "util/printf.h" #include "mca/base/mca_base_param.h" #include "mca/base/mca_base_param_internal.h" #include "tools/ompi_info/ompi_info.h" @@ -100,9 +101,10 @@ void ompi_info::show_mca_params(const string& type, const string& component, const string& param) { size_t i, size; - char *default_value_string, temp[BUFSIZ]; + char *value_string, empty[] = "\0"; string message, content; mca_base_param_t *item; + int value_int; size = ompi_value_array_get_size(&mca_base_params); if (0 == size) { @@ -118,20 +120,25 @@ void ompi_info::show_mca_params(const string& type, const string& component, component == item->mbp_component_name)) { if (param == param_all || param == item->mbp_param_name) { - // Make a string for the default value + // Make a string for the default value. Invoke a lookup + // because it may transform the string ("~/" -> "/") or get the value from the + // environment, a file, etc. - temp[0] = '\0'; - if (item->mbp_type == MCA_BASE_PARAM_TYPE_STRING) { - if (item->mbp_default_value.stringval != NULL) - default_value_string = item->mbp_default_value.stringval; - else - default_value_string = temp; + if (MCA_BASE_PARAM_TYPE_STRING == item->mbp_type) { + mca_base_param_lookup_string(i, &value_string); + + // Can't let the string be NULL because we assign it to a + // std::string, below + + if (NULL == value_string) { + value_string = empty; + } } else { - default_value_string = temp; - snprintf(default_value_string, BUFSIZ, "%d", - item->mbp_default_value.intval); + mca_base_param_lookup_int(i, &value_int); + asprintf(&value_string, "%d", value_int); } - content = default_value_string; + content = value_string; // Build up the strings to output. @@ -148,11 +155,11 @@ void ompi_info::show_mca_params(const string& type, const string& component, content += (item->mbp_env_var_name != NULL) ? "\" (default: " : "\" (value: "; - if (strlen(default_value_string) == 0) + if (strlen(value_string) == 0) content += ")"; else { content += "\""; - content += default_value_string; + content += value_string; content += "\")"; } @@ -175,10 +182,16 @@ void ompi_info::show_mca_params(const string& type, const string& component, message += item->mbp_full_name; - content = default_value_string; + content = value_string; out(message, message, content); } + + // If we allocated the string, then free it + + if (value_string != empty) { + free(value_string); + } } } }