diff --git a/opal/mca/base/mca_base_cmd_line.c b/opal/mca/base/mca_base_cmd_line.c index 38197e3ec8..1b272fc727 100644 --- a/opal/mca/base/mca_base_cmd_line.c +++ b/opal/mca/base/mca_base_cmd_line.c @@ -75,6 +75,18 @@ int mca_base_cmd_line_setup(opal_cmd_line_t *cmd) } } + { + opal_cmd_line_init_t entry = + {"mca_base_envar_file_prefix", '\0', "tune", NULL, 1, + NULL, OPAL_CMD_LINE_TYPE_STRING, + "Application profile options file list" + }; + ret = opal_cmd_line_make_opt_mca(cmd, entry); + if (OPAL_SUCCESS != ret) { + return ret; + } + } + return ret; } diff --git a/opal/mca/base/mca_base_parse_paramfile.c b/opal/mca/base/mca_base_parse_paramfile.c index 7535f2bc78..3c7202d702 100644 --- a/opal/mca/base/mca_base_parse_paramfile.c +++ b/opal/mca/base/mca_base_parse_paramfile.c @@ -43,6 +43,11 @@ int mca_base_parse_paramfile(const char *paramfile, opal_list_t *list) return opal_util_keyval_parse(paramfile, save_value); } +int mca_base_internal_env_store(void) +{ + return opal_util_keyval_save_internal_envars(save_value); +} + static void save_value(const char *name, const char *value) { mca_base_var_file_value_t *fv; diff --git a/opal/mca/base/mca_base_var.c b/opal/mca/base/mca_base_var.c index d3b2be7088..67511f3351 100644 --- a/opal/mca/base/mca_base_var.c +++ b/opal/mca/base/mca_base_var.c @@ -60,14 +60,18 @@ static char *cwd = NULL; bool mca_base_var_initialized = false; static char * force_agg_path = NULL; static char *mca_base_var_files = NULL; +static char *mca_base_envar_files = NULL; static char **mca_base_var_file_list = NULL; static char *mca_base_var_override_file = NULL; static char *mca_base_var_file_prefix = NULL; +static char *mca_base_envar_file_prefix = NULL; static char *mca_base_param_file_path = NULL; static char *mca_base_env_list = NULL; static char *mca_base_env_list_sep = ";"; +static char *mca_base_env_list_internal = NULL; static bool mca_base_var_suppress_override_warning = false; static opal_list_t mca_base_var_file_values; +static opal_list_t mca_base_envar_file_values; static opal_list_t mca_base_var_override_values; static int mca_base_var_count = 0; @@ -123,8 +127,8 @@ static const char *info_lvl_strings[] = { /* * local functions */ -static int fixup_files(char **file_list, char * path, bool rel_path_search); -static int read_files (char *file_list, opal_list_t *file_values); +static int fixup_files(char **file_list, char * path, bool rel_path_search, char sep); +static int read_files (char *file_list, opal_list_t *file_values, char sep); static int mca_base_var_cache_files (bool rel_path_search); static int var_set_initial (mca_base_var_t *var); static int var_get (int vari, mca_base_var_t **var_out, bool original); @@ -239,6 +243,7 @@ int mca_base_var_init(void) /* Init the file param value list */ OBJ_CONSTRUCT(&mca_base_var_file_values, opal_list_t); + OBJ_CONSTRUCT(&mca_base_envar_file_values, opal_list_t); OBJ_CONSTRUCT(&mca_base_var_override_values, opal_list_t); OBJ_CONSTRUCT(&mca_base_var_index_hash, opal_hash_table_t); @@ -285,33 +290,27 @@ int mca_base_var_init(void) free(name); } } + + /* Register internal MCA variable mca_base_env_list_internal. It can be set only during + * parsing of amca conf file and contains SHELL env variables specified via -x there. + * Its format is the same as for mca_base_env_list. + */ + (void)mca_base_var_register ("opal", "mca", "base", "env_list_internal", + "Store SHELL env variables from amca conf file", + MCA_BASE_VAR_TYPE_STRING, NULL, 0, MCA_BASE_VAR_FLAG_INTERNAL, OPAL_INFO_LVL_3, + MCA_BASE_VAR_SCOPE_READONLY, &mca_base_env_list_internal); } return OPAL_SUCCESS; } -int mca_base_var_process_env_list(char ***argv) +static void process_env_list(char *env_list, char ***argv, char sep) { int i; char** tokens; char* ptr; char* param, *value; - char sep; - - if (NULL == mca_base_env_list) { - return OPAL_SUCCESS; - } - sep = ';'; - if (NULL != mca_base_env_list_sep) { - if (1 == strlen(mca_base_env_list_sep)) { - sep = mca_base_env_list_sep[0]; - } else { - opal_show_help("help-mca-var.txt", "incorrect-env-list-sep", - true, mca_base_env_list_sep); - return OPAL_SUCCESS; - } - } - tokens = opal_argv_split(mca_base_env_list, (int)sep); + tokens = opal_argv_split(env_list, (int)sep); if (NULL != tokens) { for (i = 0; NULL != tokens[i]; i++) { if (NULL == (ptr = strchr(tokens[i], '='))) { @@ -329,7 +328,7 @@ int mca_base_var_process_env_list(char ***argv) } } else { opal_show_help("help-mca-var.txt", "incorrect-env-list-param", - true, tokens[i], mca_base_env_list); + true, tokens[i], env_list); } } else { param = strdup(tokens[i]); @@ -342,9 +341,59 @@ int mca_base_var_process_env_list(char ***argv) } opal_argv_free(tokens); } +} + +int mca_base_var_process_env_list(char ***argv) +{ + char sep; + sep = ';'; + if (NULL != mca_base_env_list_sep) { + if (1 == strlen(mca_base_env_list_sep)) { + sep = mca_base_env_list_sep[0]; + } else { + opal_show_help("help-mca-var.txt", "incorrect-env-list-sep", + true, mca_base_env_list_sep); + return OPAL_SUCCESS; + } + } + if (NULL != mca_base_env_list) { + process_env_list(mca_base_env_list, argv, sep); + } + return OPAL_SUCCESS; } +int mca_base_var_process_env_list_from_file(char ***argv) +{ + if (NULL != mca_base_env_list_internal) { + process_env_list(mca_base_env_list_internal, argv, ';'); + } + return OPAL_SUCCESS; +} + +static void resolve_relative_paths(char **file_prefix, char *file_path, bool rel_path_search, char **files, char sep) +{ + char *tmp_str; + /* + * Resolve all relative paths. + * the file list returned will contain only absolute paths + */ + if( OPAL_SUCCESS != fixup_files(file_prefix, file_path, rel_path_search, sep) ) { +#if 0 + /* JJH We need to die! */ + abort(); +#else + ; +#endif + } + else { + /* Prepend the files to the search list */ + asprintf(&tmp_str, "%s%c%s", *file_prefix, sep, *files); + free (*files); + *files = tmp_str; + } +} + static int mca_base_var_cache_files(bool rel_path_search) { char *tmp; @@ -381,6 +430,7 @@ static int mca_base_var_cache_files(bool rel_path_search) if (OPAL_SUCCESS != ret) { return ret; } + mca_base_envar_files = strdup(mca_base_var_files); (void) mca_base_var_register_synonym (ret, "opal", "mca", NULL, "param_files", MCA_BASE_VAR_SYN_FLAG_DEPRECATED); @@ -430,6 +480,15 @@ static int mca_base_var_cache_files(bool rel_path_search) return ret; } + mca_base_envar_file_prefix = NULL; + ret = mca_base_var_register ("opal", "mca", "base", "envar_file_prefix", + "Aggregate MCA parameter file set for env variables", + MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0, OPAL_INFO_LVL_3, + MCA_BASE_VAR_SCOPE_READONLY, &mca_base_envar_file_prefix); + if (0 > ret) { + return ret; + } + ret = asprintf(&mca_base_param_file_path, "%s" OPAL_PATH_SEP "amca-param-sets%c%s", opal_install_dirs.opaldatadir, OPAL_ENV_SEP, cwd); if (0 > ret) { @@ -467,32 +526,17 @@ static int mca_base_var_cache_files(bool rel_path_search) } if (NULL != mca_base_var_file_prefix) { - char *tmp_str; - - /* - * Resolve all relative paths. - * the file list returned will contain only absolute paths - */ - if( OPAL_SUCCESS != fixup_files(&mca_base_var_file_prefix, mca_base_param_file_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", mca_base_var_file_prefix, OPAL_ENV_SEP, mca_base_var_files); - free (mca_base_var_files); - mca_base_var_files = tmp_str; - } + resolve_relative_paths(&mca_base_var_file_prefix, mca_base_param_file_path, rel_path_search, &mca_base_var_files, OPAL_ENV_SEP); } + read_files (mca_base_var_files, &mca_base_var_file_values, OPAL_ENV_SEP); - read_files (mca_base_var_files, &mca_base_var_file_values); + if (NULL != mca_base_envar_file_prefix) { + resolve_relative_paths(&mca_base_envar_file_prefix, mca_base_param_file_path, rel_path_search, &mca_base_envar_files, ','); + } + read_files (mca_base_envar_files, &mca_base_envar_file_values, ','); if (0 == access(mca_base_var_override_file, F_OK)) { - read_files (mca_base_var_override_file, &mca_base_var_override_values); + read_files (mca_base_var_override_file, &mca_base_var_override_values, OPAL_ENV_SEP); } return OPAL_SUCCESS; @@ -1064,6 +1108,12 @@ int mca_base_var_finalize(void) } OBJ_DESTRUCT(&mca_base_var_file_values); + while (NULL != + (item = opal_list_remove_first(&mca_base_envar_file_values))) { + OBJ_RELEASE(item); + } + OBJ_DESTRUCT(&mca_base_envar_file_values); + while (NULL != (item = opal_list_remove_first(&mca_base_var_override_values))) { OBJ_RELEASE(item); @@ -1095,7 +1145,7 @@ int mca_base_var_finalize(void) /*************************************************************************/ -static int fixup_files(char **file_list, char * path, bool rel_path_search) { +static int fixup_files(char **file_list, char * path, bool rel_path_search, char sep) { int exit_status = OPAL_SUCCESS; char **files = NULL; char **search_path = NULL; @@ -1105,7 +1155,7 @@ static int fixup_files(char **file_list, char * path, bool rel_path_search) { int count, i, argc = 0; search_path = opal_argv_split(path, OPAL_ENV_SEP); - files = opal_argv_split(*file_list, OPAL_ENV_SEP); + files = opal_argv_split(*file_list, sep); count = opal_argv_count(files); /* Read in reverse order, so we can preserve the original ordering */ @@ -1167,7 +1217,7 @@ static int fixup_files(char **file_list, char * path, bool rel_path_search) { tmp_file = NULL; free(*file_list); - *file_list = opal_argv_join(argv, OPAL_ENV_SEP); + *file_list = opal_argv_join(argv, sep); cleanup: if( NULL != files ) { @@ -1189,7 +1239,7 @@ static int fixup_files(char **file_list, char * path, bool rel_path_search) { return exit_status; } -static int read_files(char *file_list, opal_list_t *file_values) +static int read_files(char *file_list, opal_list_t *file_values, char sep) { int i, count; @@ -1197,13 +1247,15 @@ static int read_files(char *file_list, opal_list_t *file_values) order so that we preserve unix/shell path-like semantics (i.e., the entries farthest to the left get precedence) */ - mca_base_var_file_list = opal_argv_split(file_list, OPAL_ENV_SEP); + mca_base_var_file_list = opal_argv_split(file_list, sep); count = opal_argv_count(mca_base_var_file_list); for (i = count - 1; i >= 0; --i) { mca_base_parse_paramfile(mca_base_var_file_list[i], file_values); } + mca_base_internal_env_store(); + return OPAL_SUCCESS; } @@ -1727,6 +1779,11 @@ static int var_set_initial (mca_base_var_t *var) return ret; } + ret = var_set_from_file (var, &mca_base_envar_file_values); + if (OPAL_ERR_NOT_FOUND != ret) { + return ret; + } + ret = var_set_from_file (var, &mca_base_var_file_values); if (OPAL_ERR_NOT_FOUND != ret) { return ret; diff --git a/opal/mca/base/mca_base_var.h b/opal/mca/base/mca_base_var.h index a927002001..010f4bbf24 100644 --- a/opal/mca/base/mca_base_var.h +++ b/opal/mca/base/mca_base_var.h @@ -727,6 +727,7 @@ OPAL_DECLSPEC int mca_base_var_dump(int vari, char ***out, mca_base_var_dump_typ * their assigned value, to the provided argv */ OPAL_DECLSPEC int mca_base_var_process_env_list(char ***argv); +OPAL_DECLSPEC int mca_base_var_process_env_list_from_file(char ***argv); END_C_DECLS diff --git a/opal/mca/base/mca_base_vari.h b/opal/mca/base/mca_base_vari.h index 5c807ccb97..c847e05cd3 100644 --- a/opal/mca/base/mca_base_vari.h +++ b/opal/mca/base/mca_base_vari.h @@ -145,6 +145,13 @@ OPAL_DECLSPEC int mca_base_var_generate_full_name4 (const char *project, const c const char *component, const char *variable, char **full_name); +/** + * \internal + * + * Call save_value callback for generated internal mca parameter storing env variables + */ +OPAL_DECLSPEC int mca_base_internal_env_store(void); + /** * \internal * diff --git a/opal/util/keyval/keyval_lex.h b/opal/util/keyval/keyval_lex.h index fd300c30ed..9d14d48583 100644 --- a/opal/util/keyval/keyval_lex.h +++ b/opal/util/keyval/keyval_lex.h @@ -61,6 +61,9 @@ enum { OPAL_UTIL_KEYVAL_PARSE_EQUAL, OPAL_UTIL_KEYVAL_PARSE_SINGLE_WORD, OPAL_UTIL_KEYVAL_PARSE_VALUE, + OPAL_UTIL_KEYVAL_PARSE_MCAVAR, + OPAL_UTIL_KEYVAL_PARSE_ENVVAR, + OPAL_UTIL_KEYVAL_PARSE_ENVEQL, OPAL_UTIL_KEYVAL_PARSE_MAX }; diff --git a/opal/util/keyval/keyval_lex.l b/opal/util/keyval/keyval_lex.l index 6c4fcb5244..650a86a265 100644 --- a/opal/util/keyval/keyval_lex.l +++ b/opal/util/keyval/keyval_lex.l @@ -55,6 +55,7 @@ CHAR [A-Za-z0-9_\-\.] %x VALUE %x comment +%x MCA_VALUE %% @@ -78,6 +79,15 @@ CHAR [A-Za-z0-9_\-\.] {WHITE}*\n { BEGIN(INITIAL); return OPAL_UTIL_KEYVAL_PARSE_NEWLINE; } [^\n]*[^\t \n]/[\t ]* { return OPAL_UTIL_KEYVAL_PARSE_VALUE; } +[^\n \t]+ { BEGIN(INITIAL); return OPAL_UTIL_KEYVAL_PARSE_VALUE; } +"'"[^\n]*"'"{WHITE}+ { BEGIN(INITIAL); return OPAL_UTIL_KEYVAL_PARSE_VALUE; } +"\""[^\n]*"\""{WHITE}+ { BEGIN(INITIAL); return OPAL_UTIL_KEYVAL_PARSE_VALUE; } +{WHITE}*\n { BEGIN(INITIAL); BEGIN(INITIAL); return OPAL_UTIL_KEYVAL_PARSE_NEWLINE; } + +"-"?"-mca"{WHITE}+{CHAR}+{WHITE}+ {BEGIN(MCA_VALUE); return OPAL_UTIL_KEYVAL_PARSE_MCAVAR; } +"-"?"-x"{WHITE}+{CHAR}+{WHITE}*"="{WHITE}* {BEGIN(MCA_VALUE); return OPAL_UTIL_KEYVAL_PARSE_ENVEQL; } +"-"?"-x"{WHITE}+{CHAR}+{WHITE}*/[^=] { return OPAL_UTIL_KEYVAL_PARSE_ENVVAR; } + . { return OPAL_UTIL_KEYVAL_PARSE_ERROR; } %% diff --git a/opal/util/keyval_parse.c b/opal/util/keyval_parse.c index 5ad4c4ac07..76f2c5dddc 100644 --- a/opal/util/keyval_parse.c +++ b/opal/util/keyval_parse.c @@ -17,8 +17,12 @@ static size_t key_buffer_len = 0; static opal_mutex_t keyval_mutex; static int parse_line(void); +static int parse_line_new(int first_val); static void parse_error(int num); +static char *env_str = NULL; +static int envsize = 1024; + int opal_util_keyval_parse_init(void) { OBJ_CONSTRUCT(&keyval_mutex, opal_mutex_t); @@ -37,7 +41,6 @@ opal_util_keyval_parse_finalize(void) return OPAL_SUCCESS; } - int opal_util_keyval_parse(const char *filename, opal_keyval_parse_fn_t callback) @@ -76,6 +79,12 @@ opal_util_keyval_parse(const char *filename, parse_line(); break; + case OPAL_UTIL_KEYVAL_PARSE_MCAVAR: + case OPAL_UTIL_KEYVAL_PARSE_ENVVAR: + case OPAL_UTIL_KEYVAL_PARSE_ENVEQL: + parse_line_new(val); + break; + default: /* anything else is an error */ parse_error(1); @@ -156,3 +165,154 @@ static void parse_error(int num) opal_output(0, "keyval parser: error %d reading file %s at line %d:\n %s\n", num, keyval_filename, opal_util_keyval_yynewlines, opal_util_keyval_yytext); } + +int opal_util_keyval_save_internal_envars(opal_keyval_parse_fn_t callback) +{ + if (NULL != env_str && 0 < strlen(env_str)) { + callback("mca_base_env_list_internal", env_str); + free(env_str); + env_str = NULL; + } + return OPAL_SUCCESS; +} + +static int trim_name(char **buffer, const char* prefix, const char* suffix) +{ + char *pchr, *echr, *tmp; + int size; + if (NULL == *buffer) { + return 1; + } + pchr = *buffer; + if (NULL != prefix) { + pchr = strstr(*buffer, prefix); + if (NULL != pchr) { + pchr += strlen(prefix); + } else { + pchr = *buffer; + } + } + /* trim spaces at the beginning */ + while (' ' == *pchr || '\t' == *pchr) { + pchr++; + } + /* trim spaces at the end */ + echr = *buffer+strlen(*buffer)-1; + while (' ' == *echr || '\t' == *echr || '\n' == *echr) { + echr--; + } + echr++; + *echr = '\0'; + if (NULL != suffix) { + if (!strncmp(echr-strlen(suffix), suffix, strlen(suffix))) { + echr -= strlen(suffix)+1; + while (' ' == *echr || '\t' == *echr) { + echr--; + } + echr++; + *echr = '\0'; + } + } + size = strlen(pchr)+1; + tmp = malloc(size); + strncpy(tmp, pchr, size); + *buffer = realloc(*buffer, size); + strncpy(*buffer, tmp, size); + free(tmp); + return 0; +} + +static int save_param_name(const char* prefix, const char* suffix) +{ + if (key_buffer_len < strlen(opal_util_keyval_yytext) + 1) { + char *tmp; + key_buffer_len = strlen(opal_util_keyval_yytext) + 1; + tmp = (char*)realloc(key_buffer, key_buffer_len); + if (NULL == tmp) { + free(key_buffer); + key_buffer_len = 0; + key_buffer = NULL; + return OPAL_ERR_TEMP_OUT_OF_RESOURCE; + } + key_buffer = tmp; + } + + strncpy(key_buffer, opal_util_keyval_yytext, key_buffer_len); + trim_name(&key_buffer, prefix, suffix); + return OPAL_SUCCESS; +} + +static int add_to_env_str(char *var, char *val) +{ + int sz, varsz, valsz; + if (NULL != env_str) { + varsz = (NULL != var) ? strlen(var) : 0; + valsz = (NULL != val) ? strlen(val) : 0; + sz = strlen(env_str)+varsz+valsz+2; + if (envsize <= sz) { + envsize *=2; + env_str = realloc(env_str, envsize); + memset(env_str + strlen(env_str), 0, envsize/2); + } + strcat(env_str, ";"); + } else { + env_str = malloc(envsize); + memset(env_str, 0, envsize); + } + strcat(env_str, var); + if (NULL != val) { + strcat(env_str, "="); + strcat(env_str, val); + } + return 0; +} + +static int parse_line_new(int first_val) +{ + int val; + char *tmp; + + val = first_val; + while (OPAL_UTIL_KEYVAL_PARSE_NEWLINE != val && OPAL_UTIL_KEYVAL_PARSE_DONE != val) { + if (OPAL_UTIL_KEYVAL_PARSE_MCAVAR == val) { + save_param_name("-mca", NULL); + val = opal_util_keyval_yylex(); + if (OPAL_UTIL_KEYVAL_PARSE_VALUE == val) { + if (NULL != opal_util_keyval_yytext) { + tmp = strdup(opal_util_keyval_yytext); + if ('\'' == tmp[0] || '\"' == tmp[0]) { + trim_name(&tmp, "\'", "\'"); + trim_name(&tmp, "\"", "\""); + } + keyval_callback(key_buffer, tmp); + free(tmp); + } + } else { + parse_error(4); + return OPAL_ERROR; + } + } else if (OPAL_UTIL_KEYVAL_PARSE_ENVEQL == val) { + save_param_name("-x", "="); + val = opal_util_keyval_yylex(); + if (OPAL_UTIL_KEYVAL_PARSE_VALUE == val) { + add_to_env_str(key_buffer, opal_util_keyval_yytext); + } else { + parse_error(5); + return OPAL_ERROR; + } + } else if (OPAL_UTIL_KEYVAL_PARSE_ENVVAR == val) { + save_param_name("-x", "="); + add_to_env_str(key_buffer, NULL); + } + val = opal_util_keyval_yylex(); + } + + if (OPAL_UTIL_KEYVAL_PARSE_DONE == val || + OPAL_UTIL_KEYVAL_PARSE_NEWLINE == val) { + return OPAL_SUCCESS; + } + + /* Nope -- we got something unexpected. Bonk! */ + parse_error(6); + return OPAL_ERROR; +} diff --git a/opal/util/keyval_parse.h b/opal/util/keyval_parse.h index 7b0fb1b1f9..e90a6b19fc 100644 --- a/opal/util/keyval_parse.h +++ b/opal/util/keyval_parse.h @@ -50,6 +50,8 @@ OPAL_DECLSPEC int opal_util_keyval_parse_init(void); OPAL_DECLSPEC int opal_util_keyval_parse_finalize(void); +OPAL_DECLSPEC int opal_util_keyval_save_internal_envars(opal_keyval_parse_fn_t callback); + END_C_DECLS #endif diff --git a/orte/mca/plm/base/help-plm-base.txt b/orte/mca/plm/base/help-plm-base.txt index 6f837f0adf..ee3ca276d5 100644 --- a/orte/mca/plm/base/help-plm-base.txt +++ b/orte/mca/plm/base/help-plm-base.txt @@ -148,3 +148,10 @@ Please either specify an absolute path to the file, or check that the file is in your current working directory...and ensure that you have read permissions on the file. +# +[deprecated-amca] +You're using the --am option. Please be advised that this option is deprecated; +you should use --tune instead. The --tune option allows one to specify mca +parameters as well as environment variables from within a file using the same +command line syntax (e.g. -mca var val -mca var "val" -x var=val -x var). +The --am option will be removed in a future release. diff --git a/orte/mca/plm/base/plm_base_launch_support.c b/orte/mca/plm/base/plm_base_launch_support.c index 1f4e5a70f5..9873720daa 100644 --- a/orte/mca/plm/base/plm_base_launch_support.c +++ b/orte/mca/plm/base/plm_base_launch_support.c @@ -1126,7 +1126,7 @@ int orte_plm_base_orted_append_basic_args(int *argc, char ***argv, char *nodes) { char *param = NULL; - const char **tmp_value; + const char **tmp_value, **tmp_value2; int loc_id; char *tmp_force = NULL; int i, j, cnt, rc; @@ -1293,7 +1293,8 @@ int orte_plm_base_orted_append_basic_args(int *argc, char ***argv, */ /* Add the 'prefix' param */ tmp_value = NULL; - loc_id = mca_base_var_find("opal", "mca", "base", "param_file_prefix"); + + loc_id = mca_base_var_find("opal", "mca", "base", "envar_file_prefix"); if (loc_id < 0) { rc = OPAL_ERR_NOT_FOUND; ORTE_ERROR_LOG(rc); @@ -1305,13 +1306,28 @@ int orte_plm_base_orted_append_basic_args(int *argc, char ***argv, return rc; } if( NULL != tmp_value && NULL != tmp_value[0] ) { + /* Could also use the short version '-tune' + * but being verbose has some value + */ + opal_argv_append(argc, argv, "-mca"); + opal_argv_append(argc, argv, "mca_base_envar_file_prefix"); + opal_argv_append(argc, argv, tmp_value[0]); + } + + tmp_value2 = NULL; + loc_id = mca_base_var_find("opal", "mca", "base", "param_file_prefix"); + mca_base_var_get_value(loc_id, &tmp_value2, NULL, NULL); + if( NULL != tmp_value2 && NULL != tmp_value2[0] ) { /* Could also use the short version '-am' * but being verbose has some value */ opal_argv_append(argc, argv, "-"OPAL_MCA_CMD_LINE_ID); opal_argv_append(argc, argv, "mca_base_param_file_prefix"); - opal_argv_append(argc, argv, tmp_value[0]); - + opal_argv_append(argc, argv, tmp_value2[0]); + orte_show_help("help-plm-base.txt", "deprecated-amca", true); + } + + if (NULL != tmp_value && NULL != tmp_value[0] || NULL != tmp_value2 && NULL != tmp_value2[0]) { /* Add the 'path' param */ tmp_value = NULL; loc_id = mca_base_var_find("opal", "mca", "base", "param_file_path"); diff --git a/orte/mca/schizo/ompi/schizo_ompi.c b/orte/mca/schizo/ompi/schizo_ompi.c index bbc9a5f2c3..05ec38c04d 100644 --- a/orte/mca/schizo/ompi/schizo_ompi.c +++ b/orte/mca/schizo/ompi/schizo_ompi.c @@ -186,6 +186,25 @@ static int parse_env(char *personality, opal_setenv("OMPI_MCA_pubsub_orte_server", ompi_server, true, dstenv); } + /* set necessary env variables for external usage from tune conf file*/ + int set_from_file = 0; + vars = NULL; + if (OPAL_SUCCESS == mca_base_var_process_env_list_from_file(&vars) && + NULL != vars) { + for (i=0; NULL != vars[i]; i++) { + value = strchr(vars[i], '='); + /* terminate the name of the param */ + *value = '\0'; + /* step over the equals */ + value++; + /* overwrite any prior entry */ + opal_setenv(vars[i], value, true, dstenv); + /* save it for any comm_spawn'd apps */ + opal_setenv(vars[i], value, true, &orte_forwarded_envars); + } + set_from_file = 1; + opal_argv_free(vars); + } /* Did the user request to export any environment variables on the cmd line? */ env_set_flag = getenv("OMPI_MCA_mca_base_env_list"); if (opal_cmd_line_is_taken(cmd_line, "x")) { @@ -219,23 +238,31 @@ static int parse_env(char *personality, } } } else if (NULL != env_set_flag) { - /* set necessary env variables for external usage */ - vars = NULL; - if (OPAL_SUCCESS == mca_base_var_process_env_list(&vars) && - NULL != vars) { - for (i=0; NULL != vars[i]; i++) { - value = strchr(vars[i], '='); - /* terminate the name of the param */ - *value = '\0'; - /* step over the equals */ - value++; - /* overwrite any prior entry */ - opal_setenv(vars[i], value, true, dstenv); - /* save it for any comm_spawn'd apps */ - opal_setenv(vars[i], value, true, &orte_forwarded_envars); + /* if mca_base_env_list was set, check if some of env vars were set via -x from a conf file. + * If this is the case, error out. + */ + if (!set_from_file) { + /* set necessary env variables for external usage */ + vars = NULL; + if (OPAL_SUCCESS == mca_base_var_process_env_list(&vars) && + NULL != vars) { + for (i=0; NULL != vars[i]; i++) { + value = strchr(vars[i], '='); + /* terminate the name of the param */ + *value = '\0'; + /* step over the equals */ + value++; + /* overwrite any prior entry */ + opal_setenv(vars[i], value, true, dstenv); + /* save it for any comm_spawn'd apps */ + opal_setenv(vars[i], value, true, &orte_forwarded_envars); + } + opal_argv_free(vars); } + } else { + orte_show_help("help-orterun.txt", "orterun:conflict-env-set", false); + return ORTE_ERR_FATAL; } - opal_argv_free(vars); } /* If the user specified --path, store it in the user's app diff --git a/orte/mca/snapc/full/help-orte-snapc-full.txt b/orte/mca/snapc/full/help-orte-snapc-full.txt index 1f58ac9c6d..197e137c04 100644 --- a/orte/mca/snapc/full/help-orte-snapc-full.txt +++ b/orte/mca/snapc/full/help-orte-snapc-full.txt @@ -29,3 +29,9 @@ Warning: Unable to determine the AMCA parameter from the environment. This is the option supplied to mpirun as '-am '. Restart may not be able to correctly determine the correct AMCA/MCA parameters to use when restarting. + +[tune_param_not_found] +Warning: Unable to determine the TUNE parameter from the environment. + This is the option supplied to mpirun as '-tune '. + Restart may not be able to correctly determine the correct TUNE/MCA/ENV + parameters to use when restarting. diff --git a/orte/mca/snapc/full/snapc_full_global.c b/orte/mca/snapc/full/snapc_full_global.c index c12781dfde..87b40750da 100644 --- a/orte/mca/snapc/full/snapc_full_global.c +++ b/orte/mca/snapc/full/snapc_full_global.c @@ -1988,6 +1988,26 @@ static int snapc_full_establish_snapshot_dir(bool empty_metadata) } } + /* + * Save the TUNE parameter used into the metadata file + */ + if( 0 > (idx = mca_base_var_find("opal", "mca", "base", "envar_file_prefix")) ) { + opal_show_help("help-orte-restart.txt", "tune_param_not_found", true); + } + if( 0 < idx ) { + mca_base_var_get_value (idx, &value, NULL, NULL); + + if (*value) { + orte_sstore.set_attr(global_snapshot.ss_handle, + SSTORE_METADATA_GLOBAL_TUNE_PARAM, + *value); + + OPAL_OUTPUT_VERBOSE((10, mca_snapc_full_component.super.output_handle, + "Global) TUNE Parameter Preserved: %s", + *value)); + } + } + return ORTE_SUCCESS; } diff --git a/orte/mca/sstore/base/base.h b/orte/mca/sstore/base/base.h index b462f3d7f2..d21127dc0f 100644 --- a/orte/mca/sstore/base/base.h +++ b/orte/mca/sstore/base/base.h @@ -68,6 +68,7 @@ ORTE_DECLSPEC extern int orte_sstore_context; #define SSTORE_METADATA_LOCAL_SNAP_REF_FMT_STR ("# Local Snapshot Format Reference: ") #define SSTORE_METADATA_GLOBAL_SNAP_SEQ_STR ("# Seq: ") #define SSTORE_METADATA_GLOBAL_AMCA_PARAM_STR ("# AMCA: ") +#define SSTORE_METADATA_GLOBAL_TUNE_PARAM_STR ("# TUNE: ") #define SSTORE_METADATA_INTERNAL_DONE_SEQ_STR ("# Finished Seq: ") #define SSTORE_METADATA_INTERNAL_TIME_STR ("# Timestamp: ") diff --git a/orte/mca/sstore/base/sstore_base_fns.c b/orte/mca/sstore/base/sstore_base_fns.c index 1f03abef2f..f9d16c7456 100644 --- a/orte/mca/sstore/base/sstore_base_fns.c +++ b/orte/mca/sstore/base/sstore_base_fns.c @@ -121,6 +121,7 @@ void orte_sstore_base_global_snapshot_info_construct(orte_sstore_base_global_sna snapshot->basedir = NULL; snapshot->reference = NULL; snapshot->amca_param = NULL; + snapshot->tune_param = NULL; snapshot->metadata_filename = NULL; } @@ -169,6 +170,11 @@ void orte_sstore_base_global_snapshot_info_destruct( orte_sstore_base_global_sna snapshot->amca_param = NULL; } + if( NULL != snapshot->tune_param ) { + free(snapshot->tune_param); + snapshot->tune_param = NULL; + } + if( NULL != snapshot->metadata_filename ) { free(snapshot->metadata_filename); snapshot->metadata_filename = NULL; @@ -335,6 +341,9 @@ int orte_sstore_base_tool_get_attr(orte_sstore_base_handle_t handle, orte_sstore else if( SSTORE_METADATA_GLOBAL_AMCA_PARAM == key ) { *value = strdup(tool_global_snapshot->amca_param); } + else if( SSTORE_METADATA_GLOBAL_TUNE_PARAM == key ) { + *value = strdup(tool_global_snapshot->tune_param); + } else { return ORTE_ERR_NOT_SUPPORTED; } @@ -412,6 +421,9 @@ int orte_sstore_base_convert_key_to_string(orte_sstore_base_key_t key, char **ke case SSTORE_METADATA_GLOBAL_AMCA_PARAM: *key_str = strdup(SSTORE_METADATA_GLOBAL_AMCA_PARAM_STR); break; + case SSTORE_METADATA_GLOBAL_TUNE_PARAM: + *key_str = strdup(SSTORE_METADATA_GLOBAL_TUNE_PARAM_STR); + break; default: *key_str = NULL; break; @@ -452,6 +464,9 @@ int orte_sstore_base_convert_string_to_key(char *key_str, orte_sstore_base_key_t else if( 0 == strncmp(key_str, SSTORE_METADATA_GLOBAL_AMCA_PARAM_STR, strlen(SSTORE_METADATA_GLOBAL_AMCA_PARAM_STR))) { *key = SSTORE_METADATA_GLOBAL_AMCA_PARAM; } + else if( 0 == strncmp(key_str, SSTORE_METADATA_GLOBAL_TUNE_PARAM_STR, strlen(SSTORE_METADATA_GLOBAL_TUNE_PARAM_STR))) { + *key = SSTORE_METADATA_GLOBAL_TUNE_PARAM; + } else { *key = SSTORE_METADATA_MAX; } @@ -654,6 +669,9 @@ int orte_sstore_base_extract_global_metadata(orte_sstore_base_global_snapshot_in else if(0 == strncmp(token, SSTORE_METADATA_GLOBAL_AMCA_PARAM_STR, strlen(SSTORE_METADATA_GLOBAL_AMCA_PARAM_STR))) { global_snapshot->amca_param = strdup(value); } + else if(0 == strncmp(token, SSTORE_METADATA_GLOBAL_TUNE_PARAM_STR, strlen(SSTORE_METADATA_GLOBAL_TUNE_PARAM_STR))) { + global_snapshot->tune_param = strdup(value); + } } while(0 == feof(metadata) ); /* Append the last item */ diff --git a/orte/mca/sstore/sstore.h b/orte/mca/sstore/sstore.h index d1ead7e939..10a1759f17 100644 --- a/orte/mca/sstore/sstore.h +++ b/orte/mca/sstore/sstore.h @@ -91,8 +91,11 @@ typedef uint32_t orte_sstore_base_key_t; * Therefore, it needs to be marked specially. */ #define SSTORE_METADATA_GLOBAL_MIGRATING 22 +/** TUNE Parameter to be preserved for ompi-restart */ +#define SSTORE_METADATA_GLOBAL_TUNE_PARAM 23 + /** */ -#define SSTORE_METADATA_MAX 23 +#define SSTORE_METADATA_MAX 24 /** * Storage handle @@ -160,6 +163,9 @@ struct orte_sstore_base_global_snapshot_info_1_0_0_t { /** AMCA parameter used */ char *amca_param; + /** TUNE parameter used */ + char *tune_param; + /** Internal use only: Cache some information on the structure */ int num_seqs; char ** all_seqs; diff --git a/orte/tools/orte-restart/help-orte-restart.txt b/orte/tools/orte-restart/help-orte-restart.txt index 96fe5afd8f..b87ed62012 100644 --- a/orte/tools/orte-restart/help-orte-restart.txt +++ b/orte/tools/orte-restart/help-orte-restart.txt @@ -70,3 +70,8 @@ Error: The filename (%s) and sequence number (%d) could not be used. Warning: Unable to find the AMCA parameter in the checkpoint metadata. This is the option supplied to mpirun as '-am '. Restart will assume this value to be '%s'. +# +[tune_param_not_found] +Warning: Unable to find the TUNE parameter in the checkpoint metadata. + This is the option supplied to mpirun as '-tune '. Restart will + assume this value to be '%s'. diff --git a/orte/tools/orte-restart/orte-restart.c b/orte/tools/orte-restart/orte-restart.c index 63e1205bab..aec3ec4d21 100644 --- a/orte/tools/orte-restart/orte-restart.c +++ b/orte/tools/orte-restart/orte-restart.c @@ -520,6 +520,7 @@ static int create_appfile(orte_sstore_base_global_snapshot_info_t *snapshot) opal_list_item_t* item = NULL; char *tmp_str = NULL; char *amca_param = NULL; + char *tune_param = NULL; char *reference_fmt_str = NULL; char *location_str = NULL; char *ref_location_fmt_str = NULL; @@ -543,6 +544,10 @@ static int create_appfile(orte_sstore_base_global_snapshot_info_t *snapshot) SSTORE_METADATA_GLOBAL_AMCA_PARAM, &amca_param); + orte_sstore.get_attr(snapshot->ss_handle, + SSTORE_METADATA_GLOBAL_TUNE_PARAM, + &tune_param); + if (NULL == (appfile = fopen(orte_restart_globals.appfile, "w")) ) { exit_status = ORTE_ERROR; goto cleanup; @@ -597,6 +602,13 @@ static int create_appfile(orte_sstore_base_global_snapshot_info_t *snapshot) } fprintf(appfile, "-am %s ", amca_param); + if( NULL == tune_param ) { + tune_param = strdup("ft-enable-cr"); + opal_show_help("help-orte-restart.txt", "tune_param_not_found", true, + tune_param); + } + fprintf(appfile, "-tune %s ", tune_param); + fprintf(appfile, " opal-restart "); /* @@ -642,6 +654,7 @@ static int spawn_children(orte_sstore_base_global_snapshot_info_t *snapshot, pid { int ret, exit_status = ORTE_SUCCESS; char *amca_param = NULL; + char *tune_param = NULL; char **argv = NULL; int argc = 0, i; int status; @@ -650,6 +663,10 @@ static int spawn_children(orte_sstore_base_global_snapshot_info_t *snapshot, pid SSTORE_METADATA_GLOBAL_AMCA_PARAM, &amca_param); + orte_sstore.get_attr(snapshot->ss_handle, + SSTORE_METADATA_GLOBAL_TUNE_PARAM, + &tune_param); + if( ORTE_SUCCESS != (ret = opal_argv_append(&argc, &argv, "mpirun")) ) { exit_status = ret; goto cleanup; @@ -667,6 +684,19 @@ static int spawn_children(orte_sstore_base_global_snapshot_info_t *snapshot, pid exit_status = ret; goto cleanup; } + if( ORTE_SUCCESS != (ret = opal_argv_append(&argc, &argv, "-tune")) ) { + exit_status = ret; + goto cleanup; + } + if( NULL == tune_param ) { + tune_param = strdup("ft-enable-cr"); + opal_show_help("help-orte-restart.txt", "tune_param_not_found", true, + tune_param); + } + if( ORTE_SUCCESS != (ret = opal_argv_append(&argc, &argv, tune_param)) ) { + exit_status = ret; + goto cleanup; + } if( NULL != orte_restart_globals.hostfile ) { if( ORTE_SUCCESS != (ret = opal_argv_append(&argc, &argv, "--default-hostfile")) ) { exit_status = ret; diff --git a/orte/tools/orterun/orterun.1in b/orte/tools/orterun/orterun.1in index 73b3efb035..dd379a1774 100644 --- a/orte/tools/orterun/orterun.1in +++ b/orte/tools/orterun/orterun.1in @@ -482,6 +482,12 @@ the parameter name; \fI\fP is the parameter value. Send arguments to various MCA modules. See the "MCA" section, below. . . +.TP +.B -tune\fR,\fP --tune +Specify a tune file to set arguments for various MCA modules and environment variables. +See the "Setting MCA parameters and environment variables from file" section, below. +. +. . . .P @@ -1390,6 +1396,21 @@ To find the available component types under the MCA architecture, or to find the available parameters for a specific component, use the \fIompi_info\fP command. See the \fIompi_info(1)\fP man page for detailed information on the command. . +. +. +.SS Setting MCA parameters and environment variables from file. +The \fI-tune\fP command line option and its synonym \fI-mca mca_base_envar_file_prefix\fP allows a user +to set mca parameters and environment variables with the syntax described below. +This option requires a single file or list of files separated by "," to follow. +.PP +A valid line in the file may contain zero or many "-x", "-mca", or “--mca” arguments. +The following patterns are supported: -mca var val -mca var "val" -x var=val -x var. +If any argument is duplicated in the file, the last value read will be used. +.PP +MCA parameters and environment specified on the command line have higher precedence than variables specified in the file. +. +. +. .SS Running as root . The Open MPI team strongly advises against executing