/* * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. * Copyright (c) 2004-2008 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */ #include "opal_config.h" #include #include #include #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SYS_PARAM_H #include #endif #include "opal/mca/installdirs/installdirs.h" #include "opal/util/os_path.h" #include "opal/util/path.h" #include "opal/class/opal_value_array.h" #include "opal/util/show_help.h" #include "opal/class/opal_hash_table.h" #if 0 /* JMS commented out for now -- see lookup_keyvals() below for an explanation */ #include "ompi/attribute/attribute.h" #endif #include "opal/util/printf.h" #include "opal/util/argv.h" #include "opal/mca/mca.h" #include "opal/mca/base/mca_base_param.h" #include "opal/mca/base/mca_base_param_internal.h" #include "opal/constants.h" #include "opal/util/output.h" #include "opal/util/opal_environ.h" /* * Public variables * * This variable is public, but not advertised in mca_base_param.h. * It's only public so that the file parser can see it. */ opal_list_t mca_base_param_file_values; /* * local variables */ static opal_value_array_t mca_base_params; static const char *mca_prefix = "OMPI_MCA_"; static char *home = NULL; static char *cwd = NULL; static bool initialized = false; static char * force_agg_path = NULL; /* * local functions */ #if defined(__WINDOWS__) static int read_keys_from_registry(HKEY hKey, char *sub_key, char *current_key); #endif /* defined(__WINDOWS__) */ static int fixup_files(char **file_list, char * path, bool rel_path_search); 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 *help_msg, mca_base_param_type_t type, bool internal, bool read_only, mca_base_param_storage_t *default_value, mca_base_param_storage_t *file_value, mca_base_param_storage_t *override_value, mca_base_param_storage_t *current_value); static bool param_lookup(size_t index, mca_base_param_storage_t *storage, opal_hash_table_t *attrs); static bool param_set_override(size_t index, mca_base_param_storage_t *storage, mca_base_param_type_t type); static bool lookup_override(mca_base_param_t *param, mca_base_param_storage_t *storage); static bool lookup_keyvals(mca_base_param_t *param, mca_base_param_storage_t *storage, opal_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); static void info_constructor(mca_base_param_info_t *p); static void info_destructor(mca_base_param_info_t *p); /* * Make the class instance for mca_base_param_t */ OBJ_CLASS_INSTANCE(mca_base_param_t, opal_object_t, param_constructor, param_destructor); OBJ_CLASS_INSTANCE(mca_base_param_file_value_t, opal_list_item_t, fv_constructor, fv_destructor); OBJ_CLASS_INSTANCE(mca_base_param_info_t, opal_list_item_t, info_constructor, info_destructor); /* * Set it up */ int mca_base_param_init(void) { if (!initialized) { /* Init the value array for the param storage */ OBJ_CONSTRUCT(&mca_base_params, opal_value_array_t); opal_value_array_init(&mca_base_params, sizeof(mca_base_param_t)); /* Init the file param value list */ OBJ_CONSTRUCT(&mca_base_param_file_values, opal_list_t); /* Set this before we register the parameter, below */ initialized = true; mca_base_param_recache_files(false); } return OPAL_SUCCESS; } int mca_base_param_recache_files(bool rel_path_search) { int id; char *files, *new_files = NULL, *new_agg_files = NULL; char * new_agg_path = NULL, *agg_default_path = NULL; /* We may need this later */ home = (char*)opal_home_directory(); if(NULL == cwd) { cwd = (char *) malloc(sizeof(char) * MAXPATHLEN); if( NULL == (cwd = getcwd(cwd, MAXPATHLEN) )) { opal_output(0, "Error: Unable to get the current working directory\n"); cwd = strdup("."); } } asprintf(&files, "%s"OPAL_PATH_SEP".openmpi"OPAL_PATH_SEP"mca-params.conf%c%s"OPAL_PATH_SEP"openmpi-mca-params.conf", home, OPAL_ENV_SEP, opal_install_dirs.sysconfdir); /* Initialize a parameter that says where MCA param files can be found */ id = mca_base_param_reg_string_name("mca", "param_files", "Path for MCA configuration files containing default parameter values", false, false, files, &new_files); /* Aggregate MCA parameter files * A prefix search path to look up aggregate MCA parameter file * requests that do not specify an absolute path */ id = mca_base_param_reg_string_name("mca", "base_param_file_prefix", "Aggregate MCA parameter file sets", false, false, NULL, &new_agg_files); asprintf(&agg_default_path, "%s"OPAL_PATH_SEP"amca-param-sets%c%s", opal_install_dirs.pkgdatadir, OPAL_ENV_SEP, cwd); id = mca_base_param_reg_string_name("mca", "base_param_file_path", "Aggregate MCA parameter Search path", false, false, agg_default_path, &new_agg_path); id = mca_base_param_reg_string_name("mca", "base_param_file_path_force", "Forced Aggregate MCA parameter Search path", false, false, NULL, &force_agg_path); if( NULL != force_agg_path ) { char *tmp_str = NULL; if( NULL == new_agg_path ) { new_agg_path = strdup(force_agg_path); } else { tmp_str = strdup(new_agg_path); free(new_agg_path); asprintf(&new_agg_path, "%s%c%s", force_agg_path, OPAL_ENV_SEP, tmp_str); free(tmp_str); } } if( NULL != new_agg_files ) { char *tmp_str = NULL; /* * Resolve all relative paths. * the file list returned will contain only absolute paths */ if( OPAL_SUCCESS != fixup_files(&new_agg_files, new_agg_path, rel_path_search) ) { #if 0 /* JJH We need to die! */ abort(); #else ; #endif } else { /* Prepend the files to the search list */ asprintf(&tmp_str, "%s%c%s", new_agg_files, OPAL_ENV_SEP, new_files); free(new_files); new_files = strdup(tmp_str); free(tmp_str); } } read_files(new_files); #if defined(__WINDOWS__) read_keys_from_registry(HKEY_LOCAL_MACHINE, "SOFTWARE\\Open MPI", NULL); read_keys_from_registry(HKEY_CURRENT_USER, "SOFTWARE\\Open MPI", NULL); #endif /* defined(__WINDOWS__) */ free(files); free(new_files); if( NULL != new_agg_files ) { free(new_agg_files); new_agg_files = NULL; } if( NULL != agg_default_path ) { free(agg_default_path); agg_default_path = NULL; } if( NULL != new_agg_path ) { free(new_agg_path); new_agg_path = NULL; } return OPAL_SUCCESS; } /* * Register an integer MCA parameter */ int mca_base_param_reg_int(const mca_base_component_t *component, const char *param_name, const char *help_msg, bool internal, bool read_only, int default_value, int *current_value) { int ret; mca_base_param_storage_t storage; mca_base_param_storage_t lookup; storage.intval = default_value; ret = param_register(component->mca_type_name, component->mca_component_name, param_name, help_msg, MCA_BASE_PARAM_TYPE_INT, internal, read_only, &storage, NULL, NULL, &lookup); if (ret >= 0 && NULL != current_value) { *current_value = lookup.intval; } return ret; } /* * Register an integer MCA parameter that is not associated with a * component */ int mca_base_param_reg_int_name(const char *type, const char *param_name, const char *help_msg, bool internal, bool read_only, int default_value, int *current_value) { int ret; mca_base_param_storage_t storage; mca_base_param_storage_t lookup; storage.intval = default_value; ret = param_register(type, NULL, param_name, help_msg, MCA_BASE_PARAM_TYPE_INT, internal, read_only, &storage, NULL, NULL, &lookup); if (ret >= 0 && NULL != current_value) { *current_value = lookup.intval; } return ret; } /* * Register a string MCA parameter. */ int mca_base_param_reg_string(const mca_base_component_t *component, const char *param_name, const char *help_msg, bool internal, bool read_only, const char *default_value, char **current_value) { int ret; mca_base_param_storage_t storage; mca_base_param_storage_t lookup; if (NULL != default_value) { storage.stringval = (char *) default_value; } else { storage.stringval = NULL; } ret = param_register(component->mca_type_name, component->mca_component_name, param_name, help_msg, MCA_BASE_PARAM_TYPE_STRING, internal, read_only, &storage, NULL, NULL, (NULL != current_value) ? &lookup : NULL); if (ret >= 0 && NULL != current_value) { *current_value = lookup.stringval; } return ret; } /* * Register a string MCA parameter that is not associated with a * component */ int mca_base_param_reg_string_name(const char *type, const char *param_name, const char *help_msg, bool internal, bool read_only, const char *default_value, char **current_value) { int ret; mca_base_param_storage_t storage; mca_base_param_storage_t lookup; if (NULL != default_value) { storage.stringval = (char *) default_value; } else { storage.stringval = NULL; } ret = param_register(type, NULL, param_name, help_msg, MCA_BASE_PARAM_TYPE_STRING, internal, read_only, &storage, NULL, NULL, (NULL != current_value) ? &lookup : NULL); if (ret >= 0 && NULL != current_value) { *current_value = lookup.stringval; } return ret; } /* * Register an integer MCA parameter * (deprecated) */ 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) { int ret; mca_base_param_storage_t storage; storage.intval = default_value; ret = param_register(type_name, component_name, param_name, mca_param_name, MCA_BASE_PARAM_TYPE_INT, false, false, &storage, NULL, NULL, NULL); return ret; } /* * Register a string MCA parameter. * (deprecated) */ 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) { int ret; mca_base_param_storage_t storage; if (NULL != default_value) { storage.stringval = (char *) default_value; } else { storage.stringval = NULL; } ret = param_register(type_name, component_name, param_name, mca_param_name, MCA_BASE_PARAM_TYPE_STRING, false, false, &storage, NULL, NULL, NULL); return ret; } /* * Associate a keyval with a parameter index */ int mca_base_param_kv_associate(int index, int keyval) { size_t len; mca_base_param_t *array; if (!initialized) { return OPAL_ERROR; } len = opal_value_array_get_size(&mca_base_params); if (((size_t) index) > len) { return OPAL_ERROR; } /* We have a valid entry (remember that we never delete MCA parameters, so if the index is >0 and len) { return OPAL_ERROR; } /* We have a valid entry (remember that we never delete MCA parameters, so if the index is >0 and len) { return OPAL_ERROR; } /* We have a valid entry (remember that we never delete MCA parameters, so if the index is >0 and mbpp_index = (int)i; p->mbpp_type_name = array[i].mbp_type_name; p->mbpp_component_name = array[i].mbp_component_name; p->mbpp_param_name = array[i].mbp_param_name; p->mbpp_full_name = array[i].mbp_full_name; p->mbpp_read_only = array[i].mbp_read_only; p->mbpp_type = array[i].mbp_type; p->mbpp_help_msg = array[i].mbp_help_msg; opal_list_append(*info, (opal_list_item_t*) p); } } /* All done */ return OPAL_SUCCESS; } /* * Make an argv-style list of strings suitable for an environment */ int mca_base_param_build_env(char ***env, int *num_env, bool internal) { size_t i, len; mca_base_param_t *array; char *str; mca_base_param_storage_t storage; /* Check for bozo cases */ if (!initialized) { return OPAL_ERROR; } /* Iterate through all the registered parameters */ len = opal_value_array_get_size(&mca_base_params); array = OPAL_VALUE_ARRAY_GET_BASE(&mca_base_params, mca_base_param_t); for (i = 0; i < len; ++i) { /* Don't output read-only values */ if (array[i].mbp_read_only) { continue; } if (array[i].mbp_internal == internal || internal) { if (param_lookup(i, &storage, NULL)) { if (MCA_BASE_PARAM_TYPE_INT == array[i].mbp_type) { asprintf(&str, "%s=%d", array[i].mbp_env_var_name, storage.intval); opal_argv_append(num_env, env, str); free(str); } else if (MCA_BASE_PARAM_TYPE_STRING == array[i].mbp_type) { if (NULL != storage.stringval) { asprintf(&str, "%s=%s", array[i].mbp_env_var_name, storage.stringval); free(storage.stringval); opal_argv_append(num_env, env, str); free(str); } } else { goto cleanup; } } else { goto cleanup; } } } /* All done */ return OPAL_SUCCESS; /* Error condition */ cleanup: if (*num_env > 0) { opal_argv_free(*env); *num_env = 0; *env = NULL; } return OPAL_ERR_NOT_FOUND; } /* * Free a list -- and all associated memory -- that was previously * returned from mca_base_param_dump() */ int mca_base_param_dump_release(opal_list_t *info) { opal_list_item_t *item; for (item = opal_list_remove_first(info); NULL != item; item = opal_list_remove_first(info)) { OBJ_RELEASE(item); } OBJ_RELEASE(info); return OPAL_SUCCESS; } /* * Shut down the MCA parameter system (normally only invoked by the * MCA framework itself). */ int mca_base_param_finalize(void) { opal_list_item_t *item; mca_base_param_t *array; if (initialized) { /* This is slow, but effective :-) */ array = OPAL_VALUE_ARRAY_GET_BASE(&mca_base_params, mca_base_param_t); while (opal_value_array_get_size(&mca_base_params) > 0) { OBJ_DESTRUCT(&array[0]); opal_value_array_remove_item(&mca_base_params, 0); } OBJ_DESTRUCT(&mca_base_params); for (item = opal_list_remove_first(&mca_base_param_file_values); NULL != item; item = opal_list_remove_first(&mca_base_param_file_values)) { OBJ_RELEASE(item); } OBJ_DESTRUCT(&mca_base_param_file_values); if( NULL != cwd ) { free(cwd); cwd = NULL; } if( NULL != force_agg_path ) { free(force_agg_path); force_agg_path = NULL; } initialized = false; } /* All done */ return OPAL_SUCCESS; } /*************************************************************************/ static int fixup_files(char **file_list, char * path, bool rel_path_search) { int exit_status = OPAL_SUCCESS; char **files = NULL; char **search_path = NULL; char * tmp_file = NULL; char **argv = NULL; int mode = R_OK; /* The file exists, and we can read it */ int count, i, argc = 0; search_path = opal_argv_split(path, OPAL_ENV_SEP); files = opal_argv_split(*file_list, OPAL_ENV_SEP); count = opal_argv_count(files); /* Read in reverse order, so we can preserve the original ordering */ for (i = 0 ; i < count; ++i) { /* Absolute paths preserved */ if ( opal_path_is_absolute(files[i]) ) { if( NULL == opal_path_access(files[i], NULL, mode) ) { opal_show_help("help-mca-param.txt", "missing-param-file", true, getpid(), files[i], path); exit_status = OPAL_ERROR; goto cleanup; } else { opal_argv_append(&argc, &argv, files[i]); } } /* Resolve all relative paths: * - If filename contains a "/" (e.g., "./foo" or "foo/bar") * - look for it relative to cwd * - if exists, use it * - ow warn/error */ else if (!rel_path_search && NULL != strchr(files[i], OPAL_PATH_SEP[0]) ) { if( NULL != force_agg_path ) { tmp_file = opal_path_access(files[i], force_agg_path, mode); } else { tmp_file = opal_path_access(files[i], cwd, mode); } if( NULL == tmp_file ) { opal_show_help("help-mca-param.txt", "missing-param-file", true, getpid(), files[i], cwd); exit_status = OPAL_ERROR; goto cleanup; } else { opal_argv_append(&argc, &argv, tmp_file); } } /* Resolve all relative paths: * - Use path resolution * - if found and readable, use it * - otherwise, warn/error */ else { if( NULL != (tmp_file = opal_path_find(files[i], search_path, mode, NULL)) ) { opal_argv_append(&argc, &argv, tmp_file); free(tmp_file); tmp_file = NULL; } else { opal_show_help("help-mca-param.txt", "missing-param-file", true, getpid(), files[i], path); exit_status = OPAL_ERROR; goto cleanup; } } } free(*file_list); *file_list = opal_argv_join(argv, OPAL_ENV_SEP); cleanup: if( NULL != files ) { opal_argv_free(files); files = NULL; } if( NULL != argv ) { opal_argv_free(argv); argv = NULL; } if( NULL != search_path ) { opal_argv_free(search_path); search_path = NULL; } if( NULL != tmp_file ) { free(tmp_file); tmp_file = NULL; } return exit_status; } static int read_files(char *file_list) { int i, count; 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 = opal_argv_split(file_list, OPAL_ENV_SEP); count = opal_argv_count(files); for (i = count - 1; i >= 0; --i) { mca_base_parse_paramfile(files[i]); } opal_argv_free(files); return OPAL_SUCCESS; } /** * */ #if defined(__WINDOWS__) #define MAX_KEY_LENGTH 255 #define MAX_VALUE_NAME 16383 static int read_keys_from_registry(HKEY hKey, char *sub_key, char *current_key) { TCHAR achKey[MAX_KEY_LENGTH]; /* buffer for subkey name */ DWORD cbName; /* size of name string */ TCHAR achClass[MAX_PATH] = TEXT(""); /* buffer for class name */ DWORD cchClassName = MAX_PATH; /* size of class string */ DWORD cSubKeys=0; /* number of subkeys */ DWORD cbMaxSubKey; /* longest subkey size */ DWORD cchMaxClass; /* longest class string */ DWORD cValues; /* number of values for key */ DWORD cchMaxValue; /* longest value name */ DWORD cbMaxValueData; /* longest value data */ DWORD cbSecurityDescriptor; /* size of security descriptor */ LPDWORD lpType; LPDWORD word_lpData; TCHAR str_lpData[MAX_VALUE_NAME]; TCHAR *str_key_name, *tmp_key, *type; DWORD dwSize, i, retCode, type_len; TCHAR achValue[MAX_VALUE_NAME]; DWORD cchValue = MAX_VALUE_NAME; HKEY hTestKey; char *sub_sub_key; mca_base_param_storage_t storage, override, lookup; if( !RegOpenKeyEx( hKey, sub_key, 0, KEY_READ, &hTestKey) == ERROR_SUCCESS ) return OPAL_ERROR; /* Get the class name and the value count. */ retCode = RegQueryInfoKey( hTestKey, /* key handle */ achClass, /* buffer for class name */ &cchClassName, /* size of class string */ NULL, /* reserved */ &cSubKeys, /* number of subkeys */ &cbMaxSubKey, /* longest subkey size */ &cchMaxClass, /* longest class string */ &cValues, /* number of values for this key */ &cchMaxValue, /* longest value name */ &cbMaxValueData, /* longest value data */ &cbSecurityDescriptor, /* security descriptor */ NULL ); /* Enumerate the subkeys, until RegEnumKeyEx fails. */ if (cSubKeys) { for (i = 0; i < cSubKeys; i++) { cbName = MAX_KEY_LENGTH; retCode = RegEnumKeyEx(hTestKey, i, achKey, &cbName, NULL, NULL, NULL, NULL); if (retCode == ERROR_SUCCESS) { asprintf(&sub_sub_key, "%s\\%s", sub_key, achKey); if (current_key!=NULL) { asprintf(&tmp_key, "%s", current_key); asprintf(¤t_key, "%s_%s", current_key, achKey); } else { tmp_key = NULL; asprintf(¤t_key, "%s", achKey); } read_keys_from_registry(hKey, sub_sub_key, current_key); free(current_key); if (tmp_key!=NULL) { asprintf(¤t_key, "%s", tmp_key); free(tmp_key); } else current_key = NULL; } } } /* Enumerate the key values. */ if (cValues) { for (i=0, retCode=ERROR_SUCCESS; istringval) { param.mbp_default_value.stringval = strdup(default_value->stringval); } else { param.mbp_default_value = *default_value; } } else { 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; } param.mbp_file_value_set = true; } else { memset(¶m.mbp_file_value, 0, sizeof(param.mbp_file_value)); param.mbp_file_value_set = false; } /* 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; } param.mbp_override_value_set = true; } else { memset(¶m.mbp_override_value, 0, sizeof(param.mbp_override_value)); param.mbp_override_value_set = false; } /* See if this entry is already in the array */ len = opal_value_array_get_size(&mca_base_params); array = OPAL_VALUE_ARRAY_GET_BASE(&mca_base_params, mca_base_param_t); for (i = 0; i < len; ++i) { if (0 == strcmp(param.mbp_full_name, array[i].mbp_full_name)) { /* We found an entry with the same param name. Check to see if we're changing types */ /* Easy case: both are INT */ if (MCA_BASE_PARAM_TYPE_INT == array[i].mbp_type && MCA_BASE_PARAM_TYPE_INT == param.mbp_type) { if (NULL != default_value) { array[i].mbp_default_value.intval = param.mbp_default_value.intval; } if (NULL != file_value) { array[i].mbp_file_value.intval = param.mbp_file_value.intval; array[i].mbp_file_value_set = true; } if (NULL != override_value) { array[i].mbp_override_value.intval = param.mbp_override_value.intval; array[i].mbp_override_value_set = true; } } /* Both are STRING */ else if (MCA_BASE_PARAM_TYPE_STRING == array[i].mbp_type && MCA_BASE_PARAM_TYPE_STRING == param.mbp_type) { if (NULL != default_value) { if (NULL != array[i].mbp_default_value.stringval) { free(array[i].mbp_default_value.stringval); array[i].mbp_default_value.stringval = NULL; } if (NULL != param.mbp_default_value.stringval) { array[i].mbp_default_value.stringval = strdup(param.mbp_default_value.stringval); } } if (NULL != file_value) { if (NULL != array[i].mbp_file_value.stringval) { free(array[i].mbp_file_value.stringval); array[i].mbp_file_value.stringval = NULL; } if (NULL != param.mbp_file_value.stringval) { array[i].mbp_file_value.stringval = strdup(param.mbp_file_value.stringval); } array[i].mbp_file_value_set = true; } if (NULL != override_value) { if (NULL != array[i].mbp_override_value.stringval) { free(array[i].mbp_override_value.stringval); array[i].mbp_override_value.stringval = NULL; } if (NULL != param.mbp_override_value.stringval) { array[i].mbp_override_value.stringval = strdup(param.mbp_override_value.stringval); } array[i].mbp_override_value_set = true; } } /* Original is INT, new is STRING */ else if (MCA_BASE_PARAM_TYPE_INT == array[i].mbp_type && MCA_BASE_PARAM_TYPE_STRING == param.mbp_type) { if (NULL != default_value && NULL != param.mbp_default_value.stringval) { array[i].mbp_default_value.stringval = strdup(param.mbp_default_value.stringval); } if (NULL != file_value && NULL != param.mbp_file_value.stringval) { array[i].mbp_file_value.stringval = strdup(param.mbp_file_value.stringval); array[i].mbp_file_value_set = true; } if (NULL != override_value && NULL != param.mbp_override_value.stringval) { array[i].mbp_override_value.stringval = strdup(param.mbp_override_value.stringval); array[i].mbp_override_value_set = true; } array[i].mbp_type = param.mbp_type; } /* Original is STRING, new is INT */ else if (MCA_BASE_PARAM_TYPE_STRING == array[i].mbp_type && MCA_BASE_PARAM_TYPE_INT == param.mbp_type) { if (NULL != default_value) { if (NULL != array[i].mbp_default_value.stringval) { free(array[i].mbp_default_value.stringval); } array[i].mbp_default_value.intval = param.mbp_default_value.intval; } if (NULL != file_value) { if (NULL != array[i].mbp_file_value.stringval) { free(array[i].mbp_file_value.stringval); } array[i].mbp_file_value.intval = param.mbp_file_value.intval; array[i].mbp_file_value_set = true; } if (NULL != override_value) { if (NULL != array[i].mbp_override_value.stringval) { free(array[i].mbp_override_value.stringval); } array[i].mbp_override_value.intval = param.mbp_override_value.intval; array[i].mbp_override_value_set = true; } array[i].mbp_type = param.mbp_type; } /* Now delete the newly-created entry (since we just saved the value in the old entry) */ OBJ_DESTRUCT(¶m); /* Finally, if we have a lookup value, look it up */ if (NULL != current_value) { if (!param_lookup(i, current_value, NULL)) { return OPAL_ERR_NOT_FOUND; } } /* Return the new index */ return (int)i; } } /* Add it to the array */ if (OPAL_SUCCESS != (ret = opal_value_array_append_item(&mca_base_params, ¶m))) { return ret; } ret = (int)opal_value_array_get_size(&mca_base_params) - 1; /* Finally, if we have a lookup value, look it up */ if (NULL != current_value) { if (!param_lookup(ret, current_value, NULL)) { return OPAL_ERR_NOT_FOUND; } } /* All done */ return ret; } /* * Set an override */ static bool param_set_override(size_t index, mca_base_param_storage_t *storage, mca_base_param_type_t type) { size_t size; mca_base_param_t *array; /* Lookup the index and see if it's valid */ if (!initialized) { return false; } size = opal_value_array_get_size(&mca_base_params); if (index > size) { return false; } array = OPAL_VALUE_ARRAY_GET_BASE(&mca_base_params, mca_base_param_t); if (MCA_BASE_PARAM_TYPE_INT == type) { array[index].mbp_override_value.intval = storage->intval; } else if (MCA_BASE_PARAM_TYPE_STRING == type) { if (NULL != storage->stringval) { array[index].mbp_override_value.stringval = strdup(storage->stringval); } else { array[index].mbp_override_value.stringval = NULL; } } array[index].mbp_override_value_set = true; return true; } /* * Lookup a parameter in multiple places */ static bool param_lookup(size_t index, mca_base_param_storage_t *storage, opal_hash_table_t *attrs) { size_t size; mca_base_param_t *array; char *p, *q; bool found; /* Lookup the index and see if it's valid */ if (!initialized) { return false; } size = opal_value_array_get_size(&mca_base_params); if (index > size) { return false; } array = OPAL_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 -- but if read_only is true, then only look at the default location. */ if (array[index].mbp_read_only) { if (lookup_override(&array[index], storage) || lookup_keyvals(&array[index], storage, attrs) || lookup_env(&array[index], storage) || lookup_file(&array[index], storage)) { opal_show_help("help-mca-param.txt", "read-only-param-set", true, array[index].mbp_full_name); } found = lookup_default(&array[index], storage); } else { found = (lookup_override(&array[index], storage) || lookup_keyvals(&array[index], storage, attrs) || lookup_env(&array[index], storage) || lookup_file(&array[index], storage) || lookup_default(&array[index], storage)); } if (found) { /* 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)) { if( NULL == home ) { asprintf(&p, "%s", storage->stringval + 2); } else { p = opal_os_path( false, home, storage->stringval + 2, NULL ); } free(storage->stringval); storage->stringval = p; } p = strstr(storage->stringval, ":~/"); while (NULL != p) { *p = '\0'; if( NULL == home ) { asprintf(&q, "%s:%s", storage->stringval, p + 2); } else { 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 overrides section */ static bool lookup_override(mca_base_param_t *param, mca_base_param_storage_t *storage) { if (param->mbp_override_value_set) { if (MCA_BASE_PARAM_TYPE_INT == param->mbp_type) { storage->intval = param->mbp_override_value.intval; } else if (MCA_BASE_PARAM_TYPE_STRING == param->mbp_type) { storage->stringval = strdup(param->mbp_override_value.stringval); } return true; } /* Don't have an override */ 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, opal_hash_table_t *attrs) { #if 1 /* JMS: Comment this out for now, because it drags in all of libmpi. This is undesirable for programs like mpirun, etc. Need a better solution for this -- perhaps a registration kind of thing...? */ return false; #else int err, flag; /* 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 != 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, param->mbp_keyval, &storage->stringval, &flag); if (OPAL_SUCCESS == err && 1 == flag) { /* Because of alignment weirdness between (void*) and int, we must grab the lower sizeof(int) bytes from the (char*) in stringval, in case sizeof(int) != sizeof(char*). */ if (MCA_BASE_PARAM_TYPE_INT == param->mbp_type) { storage->intval = *((int *) (storage->stringval + sizeof(void *) - sizeof(int))); } /* Nothing to do for string -- we already have the value loaded in the right place */ return true; } } /* Either this param has not keyval or we didn't find the keyval */ return false; #endif } /* * 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 = (int)strtol(env,(char**)NULL,0); } else if (MCA_BASE_PARAM_TYPE_STRING == param->mbp_type) { storage->stringval = strdup(env); } return true; } /* Didn't find it */ return false; } /* * Lookup a param in the files */ static bool lookup_file(mca_base_param_t *param, mca_base_param_storage_t *storage) { opal_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 = opal_list_get_first(&mca_base_param_file_values); opal_list_get_end(&mca_base_param_file_values) != item; item = opal_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 = (int)strtol(fv->mbpfv_value,(char**)NULL,0); } 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 */ opal_list_remove_item(&mca_base_param_file_values, (opal_list_item_t *) fv); OBJ_RELEASE(fv); return set(param->mbp_type, storage, ¶m->mbp_file_value); } } return false; } /* * 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; } /* * Create an empty param container */ static void param_constructor(mca_base_param_t *p) { p->mbp_type = MCA_BASE_PARAM_TYPE_MAX; p->mbp_internal = false; p->mbp_read_only = false; p->mbp_type_name = NULL; p->mbp_component_name = NULL; p->mbp_param_name = NULL; p->mbp_full_name = NULL; p->mbp_help_msg = 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; } /* * Free all the contents of a param container */ 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 (NULL != p->mbp_help_msg) { free(p->mbp_help_msg); } 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); } } param_constructor(p); } 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); } fv_constructor(f); } static void info_constructor(mca_base_param_info_t *p) { p->mbpp_index = -1; p->mbpp_type = MCA_BASE_PARAM_TYPE_MAX; p->mbpp_type_name = NULL; p->mbpp_component_name = NULL; p->mbpp_param_name = NULL; p->mbpp_full_name = NULL; p->mbpp_read_only = false; p->mbpp_help_msg = NULL; } static void info_destructor(mca_base_param_info_t *p) { /* No need to free any of the strings -- the pointers were copied by value from their corresponding parameter registration */ info_constructor(p); }