From 723bb87ec6f2413c29d4b1f2e41abf99bed05207 Mon Sep 17 00:00:00 2001 From: Ralph Castain Date: Sat, 17 Feb 2018 18:15:01 -0800 Subject: [PATCH] Implement the PMIx envar support (RFC0022) Signed-off-by: Ralph Castain --- opal/dss/dss_compare.c | 48 ++++++- opal/dss/dss_copy.c | 34 ++++- opal/dss/dss_internal.h | 12 +- opal/dss/dss_open_close.c | 33 ++++- opal/dss/dss_pack.c | 28 +++- opal/dss/dss_print.c | 31 ++++- opal/dss/dss_types.h | 15 ++- opal/dss/dss_unpack.c | 44 +++++- .../pmix/pmix3x/pmix/include/pmix_common.h.in | 83 ++++++++++-- .../pmix3x/pmix/src/mca/bfrops/base/base.h | 10 ++ .../src/mca/bfrops/base/bfrop_base_copy.c | 37 +++++ .../pmix/src/mca/bfrops/base/bfrop_base_fns.c | 104 ++++++++++++++- .../src/mca/bfrops/base/bfrop_base_pack.c | 40 +++++- .../src/mca/bfrops/base/bfrop_base_print.c | 38 ++++++ .../src/mca/bfrops/base/bfrop_base_unpack.c | 48 +++++++ .../pmix/src/mca/bfrops/v3/bfrop_pmix3.c | 8 ++ opal/mca/pmix/pmix3x/pmix3x.c | 24 +++- opal/mca/pmix/pmix_types.h | 16 ++- orte/include/orte/types.h | 3 +- orte/mca/iof/base/iof_base_frame.c | 2 +- orte/mca/schizo/ompi/schizo_ompi.c | 126 +++++++++++++++++- orte/orted/pmix/pmix_server_dyn.c | 31 +++++ orte/util/attr.c | 115 ++++++++++++++-- orte/util/attr.h | 24 +++- 24 files changed, 909 insertions(+), 45 deletions(-) diff --git a/opal/dss/dss_compare.c b/opal/dss/dss_compare.c index 20ae1f0fe7..734306d937 100644 --- a/opal/dss/dss_compare.c +++ b/opal/dss/dss_compare.c @@ -12,7 +12,7 @@ * Copyright (c) 2012 Los Alamos National Security, Inc. All rights reserved. * Copyright (c) 2014-2016 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2014-2016 Intel, Inc. All rights reserved. + * Copyright (c) 2014-2018 Intel, Inc. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -359,6 +359,8 @@ int opal_dss_compare_value(opal_value_t *value1, opal_value_t *value2, opal_data return opal_dss_compare_timeval(&value1->data.tv, &value2->data.tv, type); case OPAL_NAME: return opal_dss_compare_name(&value1->data.name, &value2->data.name, type); + case OPAL_ENVAR: + return opal_dss_compare_envar(&value1->data.envar, &value2->data.envar, type); default: opal_output(0, "COMPARE-OPAL-VALUE: UNSUPPORTED TYPE %d", (int)value1->type); return OPAL_EQUAL; @@ -458,3 +460,47 @@ int opal_dss_compare_status(int *value1, int *value2, opal_data_type_t type) return OPAL_EQUAL; } +int opal_dss_compare_envar(opal_envar_t *value1, opal_envar_t *value2, opal_data_type_t type) +{ + int rc; + + if (NULL != value1->envar) { + if (NULL == value2->envar) { + return OPAL_VALUE1_GREATER; + } + rc = strcmp(value1->envar, value2->envar); + if (rc < 0) { + return OPAL_VALUE2_GREATER; + } else if (0 < rc) { + return OPAL_VALUE1_GREATER; + } + } else if (NULL != value2->envar) { + /* we know value1->envar had to be NULL */ + return OPAL_VALUE2_GREATER; + } + + /* if both are NULL or are equal, then check value */ + if (NULL != value1->value) { + if (NULL == value2->value) { + return OPAL_VALUE1_GREATER; + } + rc = strcmp(value1->value, value2->value); + if (rc < 0) { + return OPAL_VALUE2_GREATER; + } else if (0 < rc) { + return OPAL_VALUE1_GREATER; + } + } else if (NULL != value2->value) { + /* we know value1->value had to be NULL */ + return OPAL_VALUE2_GREATER; + } + + /* finally, check separator */ + if (value1->separator < value2->separator) { + return OPAL_VALUE2_GREATER; + } + if (value2->separator < value1->separator) { + return OPAL_VALUE1_GREATER; + } + return OPAL_EQUAL; +} diff --git a/opal/dss/dss_copy.c b/opal/dss/dss_copy.c index a39798bd46..184897d77e 100644 --- a/opal/dss/dss_copy.c +++ b/opal/dss/dss_copy.c @@ -9,7 +9,7 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. - * Copyright (c) 2014-2016 Intel, Inc. All rights reserved. + * Copyright (c) 2014-2018 Intel, Inc. All rights reserved. * Copyright (c) 2014-2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. * $COPYRIGHT$ @@ -338,6 +338,16 @@ int opal_dss_copy_value(opal_value_t **dest, opal_value_t *src, case OPAL_NAME: memcpy(&p->data.name, &src->data.name, sizeof(opal_process_name_t)); break; + case OPAL_ENVAR: + OBJ_CONSTRUCT(&p->data.envar, opal_envar_t); + if (NULL != src->data.envar.envar) { + p->data.envar.envar = strdup(src->data.envar.envar); + } + if (NULL != src->data.envar.value) { + p->data.envar.value = strdup(src->data.envar.value); + } + p->data.envar.separator = src->data.envar.separator; + break; default: opal_output(0, "COPY-OPAL-VALUE: UNSUPPORTED TYPE %d", (int)src->type); return OPAL_ERROR; @@ -409,3 +419,25 @@ int opal_dss_copy_vpid(opal_vpid_t **dest, opal_vpid_t *src, opal_data_type_t ty return OPAL_SUCCESS; } + +int opal_dss_copy_envar(opal_envar_t **dest, opal_envar_t *src, opal_data_type_t type) +{ + opal_envar_t *val; + + val = OBJ_NEW(opal_envar_t); + if (NULL == val) { + OPAL_ERROR_LOG(OPAL_ERR_OUT_OF_RESOURCE); + return OPAL_ERR_OUT_OF_RESOURCE; + } + + if (NULL != src->envar) { + val->envar = strdup(src->envar); + } + if (NULL != src->value) { + val->value = strdup(src->value); + } + val->separator = src->separator; + *dest = val; + + return OPAL_SUCCESS; +} diff --git a/opal/dss/dss_internal.h b/opal/dss/dss_internal.h index a2514379ce..e4360b23f3 100644 --- a/opal/dss/dss_internal.h +++ b/opal/dss/dss_internal.h @@ -11,7 +11,7 @@ * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * Copyright (c) 2012 Los Alamos National Security, Inc. All rights reserved. - * Copyright (c) 2014-2017 Intel, Inc. All rights reserved. + * Copyright (c) 2014-2018 Intel, Inc. All rights reserved. * Copyright (c) 2014 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2015 Cisco Systems, Inc. All rights reserved. @@ -334,6 +334,8 @@ int opal_dss_pack_vpid(opal_buffer_t *buffer, const void *src, int opal_dss_pack_status(opal_buffer_t *buffer, const void *src, int32_t num_vals, opal_data_type_t type); +int opal_dss_pack_envar(opal_buffer_t *buffer, const void *src, + int32_t num_vals, opal_data_type_t type); /* * Internal unpack functions @@ -407,6 +409,9 @@ int opal_dss_unpack_vpid(opal_buffer_t *buffer, void *dest, int opal_dss_unpack_status(opal_buffer_t *buffer, void *dest, int32_t *num_vals, opal_data_type_t type); +int opal_dss_unpack_envar(opal_buffer_t *buffer, void *dest, + int32_t *num_vals, opal_data_type_t type); + /* * Internal copy functions */ @@ -438,6 +443,8 @@ int opal_dss_copy_jobid(opal_jobid_t **dest, opal_jobid_t *src, opal_data_type_t int opal_dss_copy_vpid(opal_vpid_t **dest, opal_vpid_t *src, opal_data_type_t type); +int opal_dss_copy_envar(opal_envar_t **dest, opal_envar_t *src, opal_data_type_t type); + /* * Internal compare functions @@ -503,6 +510,7 @@ int opal_dss_compare_jobid(opal_jobid_t *value1, opal_data_type_t type); int opal_dss_compare_status(int *value1, int *value2, opal_data_type_t type); +int opal_dss_compare_envar(opal_envar_t *value1, opal_envar_t *value2, opal_data_type_t type); /* * Internal print functions @@ -544,6 +552,8 @@ int opal_dss_print_name(char **output, char *prefix, opal_process_name_t *name, int opal_dss_print_jobid(char **output, char *prefix, opal_process_name_t *src, opal_data_type_t type); int opal_dss_print_vpid(char **output, char *prefix, opal_process_name_t *src, opal_data_type_t type); int opal_dss_print_status(char **output, char *prefix, int *src, opal_data_type_t type); +int opal_dss_print_envar(char **output, char *prefix, + opal_envar_t *src, opal_data_type_t type); /* diff --git a/opal/dss/dss_open_close.c b/opal/dss/dss_open_close.c index 8f0ecaf070..1b7085f8bd 100644 --- a/opal/dss/dss_open_close.c +++ b/opal/dss/dss_open_close.c @@ -11,7 +11,7 @@ * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * Copyright (c) 2012-2013 Los Alamos National Security, Inc. All rights reserved. - * Copyright (c) 2014-2017 Intel, Inc. All rights reserved. + * Copyright (c) 2014-2018 Intel, Inc. All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2017 IBM Corporation. All rights reserved. @@ -232,6 +232,26 @@ OBJ_CLASS_INSTANCE(opal_node_stats_t, opal_object_t, opal_node_stats_destruct); +static void opal_envar_construct(opal_envar_t *obj) +{ + obj->envar = NULL; + obj->value = NULL; + obj->separator = '\0'; +} +static void opal_envar_destruct(opal_envar_t *obj) +{ + if (NULL != obj->envar) { + free(obj->envar); + } + if (NULL != obj->value) { + free(obj->value); + } +} +OBJ_CLASS_INSTANCE(opal_envar_t, + opal_list_item_t, + opal_envar_construct, + opal_envar_destruct); + int opal_dss_register_vars (void) { mca_base_var_enum_t *new_enum; @@ -624,6 +644,17 @@ int opal_dss_open(void) "OPAL_STATUS", &tmp))) { return rc; } + + tmp = OPAL_ENVAR; + if (OPAL_SUCCESS != (rc = opal_dss.register_type(opal_dss_pack_envar, + opal_dss_unpack_envar, + (opal_dss_copy_fn_t)opal_dss_copy_envar, + (opal_dss_compare_fn_t)opal_dss_compare_envar, + (opal_dss_print_fn_t)opal_dss_print_envar, + OPAL_DSS_UNSTRUCTURED, + "OPAL_ENVAR", &tmp))) { + return rc; + } /* All done */ opal_dss_initialized = true; diff --git a/opal/dss/dss_pack.c b/opal/dss/dss_pack.c index 87a7573a03..fce1185082 100644 --- a/opal/dss/dss_pack.c +++ b/opal/dss/dss_pack.c @@ -10,7 +10,7 @@ * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * Copyright (c) 2011-2013 Cisco Systems, Inc. All rights reserved. - * Copyright (c) 2014-2017 Intel, Inc. All rights reserved. + * Copyright (c) 2014-2018 Intel, Inc. All rights reserved. * Copyright (c) 2014 Research Organization for Information Science * and Technology (RIST). All rights reserved. * $COPYRIGHT$ @@ -836,6 +836,11 @@ int opal_dss_pack_value(opal_buffer_t *buffer, const void *src, return ret; } break; + case OPAL_ENVAR: + if (OPAL_SUCCESS != (ret = opal_dss_pack_buffer(buffer, &ptr[i]->data.envar, 1, OPAL_ENVAR))) { + return ret; + } + break; default: opal_output(0, "PACK-OPAL-VALUE: UNSUPPORTED TYPE %d FOR KEY %s", (int)ptr[i]->type, ptr[i]->key); return OPAL_ERROR; @@ -981,3 +986,24 @@ int opal_dss_pack_status(opal_buffer_t *buffer, const void *src, return ret; } + +int opal_dss_pack_envar(opal_buffer_t *buffer, const void *src, + int32_t num_vals, opal_data_type_t type) +{ + int ret; + int32_t n; + opal_envar_t **ptr = (opal_envar_t**)src; + + for (n=0; n < num_vals; n++) { + if (OPAL_SUCCESS != (ret = opal_dss_pack_string(buffer, &ptr[n]->envar, 1, OPAL_STRING))) { + return ret; + } + if (OPAL_SUCCESS != (ret = opal_dss_pack_string(buffer, &ptr[n]->value, 1, OPAL_STRING))) { + return ret; + } + if (OPAL_SUCCESS != (ret = opal_dss_pack_byte(buffer, &ptr[n]->separator, 1, OPAL_BYTE))) { + return ret; + } + } + return OPAL_SUCCESS; +} diff --git a/opal/dss/dss_print.c b/opal/dss/dss_print.c index ef7b31cdc2..8009c3f2c1 100644 --- a/opal/dss/dss_print.c +++ b/opal/dss/dss_print.c @@ -10,7 +10,7 @@ * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * Copyright (c) 2012 Los Alamos National Security, Inc. All rights reserved. - * Copyright (c) 2014-2017 Intel, Inc. All rights reserved. + * Copyright (c) 2014-2018 Intel, Inc. All rights reserved. * Copyright (c) 2014 Research Organization for Information Science * and Technology (RIST). All rights reserved. * $COPYRIGHT$ @@ -806,6 +806,13 @@ int opal_dss_print_value(char **output, char *prefix, opal_value_t *src, opal_da case OPAL_PTR: asprintf(output, "%sOPAL_VALUE: Data type: OPAL_PTR\tKey: %s", prefx, src->key); break; + case OPAL_ENVAR: + asprintf(output, "%sOPAL_VALUE: Data type: OPAL_ENVAR\tKey: %s\tName: %s\tValue: %s\tSeparator: %c", + prefx, src->key, + (NULL == src->data.envar.envar) ? "NULL" : src->data.envar.envar, + (NULL == src->data.envar.value) ? "NULL" : src->data.envar.value, + ('\0' == src->data.envar.separator) ? ' ' : src->data.envar.separator); + break; default: asprintf(output, "%sOPAL_VALUE: Data type: UNKNOWN\tKey: %s\tValue: UNPRINTABLE", prefx, src->key); @@ -895,3 +902,25 @@ int opal_dss_print_status(char **output, char *prefix, asprintf(output, "%sData type: OPAL_STATUS\tValue: %s", prefx, opal_strerror(*src)); return OPAL_SUCCESS; } + + +int opal_dss_print_envar(char **output, char *prefix, + opal_envar_t *src, opal_data_type_t type) +{ + char *prefx = " "; + + /* deal with NULL prefix */ + if (NULL != prefix) prefx = prefix; + + /* if src is NULL, just print data type and return */ + if (NULL == src) { + asprintf(output, "%sData type: OPAL_ENVAR\tValue: NULL pointer", prefx); + return OPAL_SUCCESS; + } + + asprintf(output, "%sOPAL_VALUE: Data type: OPAL_ENVAR\tName: %s\tValue: %s\tSeparator: %c", + prefx, (NULL == src->envar) ? "NULL" : src->envar, + (NULL == src->value) ? "NULL" : src->value, + ('\0' == src->separator) ? ' ' : src->separator); + return OPAL_SUCCESS; +} diff --git a/opal/dss/dss_types.h b/opal/dss/dss_types.h index 23d2f08dca..47da99da6c 100644 --- a/opal/dss/dss_types.h +++ b/opal/dss/dss_types.h @@ -15,7 +15,7 @@ * reserved. * Copyright (c) 2014-2016 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2014-2016 Intel, Inc. All rights reserved. + * Copyright (c) 2014-2018 Intel, Inc. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -107,6 +107,7 @@ typedef struct { #define OPAL_INFO_DIRECTIVES (opal_data_type_t) 36 /**< corresponds to PMIx info directives type (uint32_t) */ #define OPAL_PROC_STATE (opal_data_type_t) 37 /**< corresponds to PMIx proc state type (uint8_t) */ #define OPAL_PROC_INFO (opal_data_type_t) 38 /**< corresponds to PMIx proc_info type */ +#define OPAL_ENVAR (opal_data_type_t) 39 /**< corresponds to PMIx envar type */ /* OPAL Dynamic */ #define OPAL_DSS_ID_DYNAMIC (opal_data_type_t) 100 @@ -131,7 +132,16 @@ typedef struct { opal_status_t exit_code; opal_proc_state_t state; } opal_proc_info_t; -OBJ_CLASS_DECLARATION(opal_proc_info_t); +OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_proc_info_t); + +/* defaine a struct for envar directives */ +typedef struct { + opal_list_item_t super; + char *envar; + char *value; + char separator; +} opal_envar_t; +OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_envar_t); /* Data value object */ typedef struct { @@ -163,6 +173,7 @@ typedef struct { opal_process_name_t name; opal_proc_info_t pinfo; void *ptr; // never packed or passed anywhere + opal_envar_t envar; } data; } opal_value_t; OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_value_t); diff --git a/opal/dss/dss_unpack.c b/opal/dss/dss_unpack.c index 212851bb94..237f3a037d 100644 --- a/opal/dss/dss_unpack.c +++ b/opal/dss/dss_unpack.c @@ -11,7 +11,7 @@ * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * Copyright (c) 2012-2015 Los Alamos National Security, Inc. All rights reserved. - * Copyright (c) 2014-2017 Intel, Inc. All rights reserved. + * Copyright (c) 2014-2018 Intel, Inc. All rights reserved. * Copyright (c) 2014-2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. * $COPYRIGHT$ @@ -1099,6 +1099,11 @@ int opal_dss_unpack_value(opal_buffer_t *buffer, void *dest, return ret; } break; + case OPAL_ENVAR: + if (OPAL_SUCCESS != (ret = opal_dss_unpack_buffer(buffer, &ptr[i]->data.envar, &m, OPAL_ENVAR))) { + return ret; + } + break; default: opal_output(0, "UNPACK-OPAL-VALUE: UNSUPPORTED TYPE %d FOR KEY %s", (int)ptr[i]->type, ptr[i]->key); return OPAL_ERROR; @@ -1261,3 +1266,40 @@ int opal_dss_unpack_status(opal_buffer_t *buffer, void *dest, return ret; } + + +int opal_dss_unpack_envar(opal_buffer_t *buffer, void *dest, + int32_t *num_vals, opal_data_type_t type) +{ + opal_envar_t **ptr; + int32_t i, n, m; + int ret; + + ptr = (opal_envar_t **) dest; + n = *num_vals; + + for (i = 0; i < n; ++i) { + /* allocate the new object */ + ptr[i] = OBJ_NEW(opal_envar_t); + if (NULL == ptr[i]) { + return OPAL_ERR_OUT_OF_RESOURCE; + } + m=1; + if (OPAL_SUCCESS != (ret = opal_dss_unpack_string(buffer, &ptr[i]->envar, &m, OPAL_STRING))) { + OPAL_ERROR_LOG(ret); + return ret; + } + m=1; + if (OPAL_SUCCESS != (ret = opal_dss_unpack_string(buffer, &ptr[i]->value, &m, OPAL_STRING))) { + OPAL_ERROR_LOG(ret); + return ret; + } + m=1; + if (OPAL_SUCCESS != (ret = opal_dss_unpack_byte(buffer, &ptr[i]->separator, &m, OPAL_BYTE))) { + OPAL_ERROR_LOG(ret); + return ret; + } + } + + return OPAL_SUCCESS; +} diff --git a/opal/mca/pmix/pmix3x/pmix/include/pmix_common.h.in b/opal/mca/pmix/pmix3x/pmix/include/pmix_common.h.in index 0eecfe9549..4f3903b572 100644 --- a/opal/mca/pmix/pmix3x/pmix/include/pmix_common.h.in +++ b/opal/mca/pmix/pmix3x/pmix/include/pmix_common.h.in @@ -422,19 +422,22 @@ typedef uint32_t pmix_rank_t; #define PMIX_DEBUG_WAIT_FOR_NOTIFY "pmix.dbg.notify" // (bool) block at desired point until receiving debugger release notification #define PMIX_DEBUG_JOB "pmix.dbg.job" // (char*) nspace of the job to be debugged - the RM/PMIx server are #define PMIX_DEBUG_WAITING_FOR_NOTIFY "pmix.dbg.waiting" // (bool) job to be debugged is waiting for a release -#define PMIX_PREPEND_LD_PRELOAD "pmix.prepend.preload" // (char*) prepend the named library to any existing - // LD_PRELOAD directive -#define PMIX_APPEND_LD_PRELOAD "pmix.append.preload" // (char*) append the named library to any existing - // LD_PRELOAD directive /* Resource Manager identification */ #define PMIX_RM_NAME "pmix.rm.name" // (char*) string name of the resource manager #define PMIX_RM_VERSION "pmix.rm.version" // (char*) RM version string -/* attributes for setting envars */ -#define PMIX_SET_ENVAR "pmix.set.envar" // (char*) string "key=value" value shall be put into the environment -#define PMIX_UNSET_ENVAR "pmix.unset.envar" // (char*) unset envar specified in string +/* environmental variable operation attributes */ +#define PMIX_SET_ENVAR "pmix.envar.set" // (pmix_envar_t*) set the envar to the given value, + // overwriting any pre-existing one +#define PMIX_UNSET_ENVAR "pmix.envar.unset" // (char*) unset the envar, if present +#define PMIX_PREPEND_ENVAR "pmix.envar.prepnd" // (pmix_envar_t*) prepend the given value to the + // specified envar using the separator + // character, creating the envar if it doesn't already exist +#define PMIX_APPEND_ENVAR "pmix.envar.appnd" // (pmix_envar_t*) append the given value to the specified + // envar using the separator character, + // creating the envar if it doesn't already exist /* attributes relating to allocations */ #define PMIX_ALLOC_ID "pmix.alloc.id" // (char*) provide a string identifier for this allocation request @@ -753,6 +756,7 @@ typedef uint16_t pmix_data_type_t; #define PMIX_INFO_ARRAY 44 /**** ****/ #define PMIX_IOF_CHANNEL 45 +#define PMIX_ENVAR 46 /********************/ /* define a boundary for implementers so they can add their own data types */ @@ -878,6 +882,62 @@ typedef struct pmix_byte_object { } while(0) +/**** PMIX ENVAR STRUCT ****/ +/* Provide a structure for specifying environment variable modifications + * Standard environment variables (e.g., PATH, LD_LIBRARY_PATH, and LD_PRELOAD) + * take multiple arguments separated by delimiters. Unfortunately, the delimiters + * depend upon the variable itself - some use semi-colons, some colons, etc. Thus, + * the operation requires not only the name of the variable to be modified and + * the value to be inserted, but also the separator to be used when composing + * the aggregate value + */ +typedef struct { + char *envar; + char *value; + char separator; +} pmix_envar_t; + +#define PMIX_ENVAR_CREATE(m, n) \ + do { \ + (m) = (pmix_envar_t*)calloc((n) , sizeof(pmix_envar_t)); \ + } while (0) +#define PMIX_ENVAR_FREE(m, n) \ + do { \ + size_t _k; \ + if (NULL != (m)) { \ + for (_k=0; _k < (n); _k++) { \ + PMIX_ENVAR_DESTRUCT(&(m)[_k]); \ + } \ + free((m)); \ + } \ + } while (0) +#define PMIX_ENVAR_CONSTRUCT(m) \ + do { \ + (m)->envar = NULL; \ + (m)->value = NULL; \ + (m)->separator = '\0'; \ + } while(0) +#define PMIX_ENVAR_DESTRUCT(m) \ + do { \ + if (NULL != (m)->envar) { \ + free((m)->envar); \ + } \ + if (NULL != (m)->value) { \ + free((m)->value); \ + } \ + } while(0) +#define PMIX_ENVAR_LOAD(m, e, v, s) \ + do { \ + if (NULL != (e)) { \ + (m)->envar = strdup(e); \ + } \ + if (NULL != (v)) { \ + (m)->value = strdup(v); \ + } \ + (m)->separator = (s); \ + } while(0) + + /**** PMIX DATA BUFFER ****/ typedef struct pmix_data_buffer { /** Start of my memory */ @@ -994,9 +1054,9 @@ typedef struct pmix_proc_info { (m) = (pmix_proc_info_t*)calloc((n) , sizeof(pmix_proc_info_t)); \ } while (0) -#define PMIX_PROC_INFO_RELEASE(m) \ - do { \ - PMIX_PROC_INFO_FREE((m)); \ +#define PMIX_PROC_INFO_RELEASE(m) \ + do { \ + PMIX_PROC_INFO_FREE((m), 1); \ } while (0) #define PMIX_PROC_INFO_CONSTRUCT(m) \ @@ -1080,6 +1140,7 @@ typedef struct pmix_value { pmix_data_array_t *darray; void *ptr; pmix_alloc_directive_t adir; + pmix_envar_t envar; /**** DEPRECATED ****/ pmix_info_array_t *array; /********************/ @@ -1190,6 +1251,8 @@ typedef struct pmix_value { } \ free(_p); \ /********************/ \ + } else if (PMIX_ENVAR == (m)->type) { \ + PMIX_ENVAR_DESTRUCT(&(m)->data.envar); \ } \ } while (0) diff --git a/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/base.h b/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/base.h index 471db6b951..18154ec1c3 100644 --- a/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/base.h +++ b/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/base.h @@ -381,6 +381,8 @@ PMIX_EXPORT pmix_status_t pmix_bfrops_base_pack_alloc_directive(pmix_buffer_t *b int32_t num_vals, pmix_data_type_t type); PMIX_EXPORT pmix_status_t pmix_bfrops_base_pack_iof_channel(pmix_buffer_t *buffer, const void *src, int32_t num_vals, pmix_data_type_t type); +PMIX_EXPORT pmix_status_t pmix_bfrops_base_pack_envar(pmix_buffer_t *buffer, const void *src, + int32_t num_vals, pmix_data_type_t type); /* * "Standard" unpack functions @@ -470,6 +472,8 @@ PMIX_EXPORT pmix_status_t pmix_bfrops_base_unpack_alloc_directive(pmix_buffer_t int32_t *num_vals, pmix_data_type_t type); PMIX_EXPORT pmix_status_t pmix_bfrops_base_unpack_iof_channel(pmix_buffer_t *buffer, void *dest, int32_t *num_vals, pmix_data_type_t type); +PMIX_EXPORT pmix_status_t pmix_bfrops_base_unpack_envar(pmix_buffer_t *buffer, void *dest, + int32_t *num_vals, pmix_data_type_t type); /**** DEPRECATED ****/ PMIX_EXPORT pmix_status_t pmix_bfrops_base_unpack_array(pmix_buffer_t *buffer, void *dest, int32_t *num_vals, pmix_data_type_t type); @@ -531,6 +535,9 @@ PMIX_EXPORT pmix_status_t pmix_bfrops_base_copy_darray(pmix_data_array_t **dest, PMIX_EXPORT pmix_status_t pmix_bfrops_base_copy_query(pmix_query_t **dest, pmix_query_t *src, pmix_data_type_t type); +PMIX_EXPORT pmix_status_t pmix_bfrops_base_copy_envar(pmix_envar_t **dest, + pmix_envar_t *src, + pmix_data_type_t type); /**** DEPRECATED ****/ PMIX_EXPORT pmix_status_t pmix_bfrops_base_copy_array(pmix_info_array_t **dest, pmix_info_array_t *src, @@ -644,6 +651,9 @@ PMIX_EXPORT pmix_status_t pmix_bfrops_base_print_alloc_directive(char **output, PMIX_EXPORT pmix_status_t pmix_bfrops_base_print_iof_channel(char **output, char *prefix, pmix_iof_channel_t *src, pmix_data_type_t type); +PMIX_EXPORT pmix_status_t pmix_bfrops_base_print_envar(char **output, char *prefix, + pmix_envar_t *src, + pmix_data_type_t type); /* * Common helper functions diff --git a/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_copy.c b/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_copy.c index d2e2ab5415..9c2f9e92f3 100644 --- a/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_copy.c +++ b/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_copy.c @@ -403,6 +403,7 @@ pmix_status_t pmix_bfrops_base_copy_darray(pmix_data_array_t **dest, pmix_modex_data_t *pm, *sm; pmix_proc_info_t *pi, *si; pmix_query_t *pq, *sq; + pmix_envar_t *pe, *se; p = (pmix_data_array_t*)calloc(1, sizeof(pmix_data_array_t)); if (NULL == p) { @@ -823,6 +824,24 @@ pmix_status_t pmix_bfrops_base_copy_darray(pmix_data_array_t **dest, } } break; + case PMIX_ENVAR: + PMIX_ENVAR_CREATE(p->array, src->size); + if (NULL == p->array) { + free(p); + return PMIX_ERR_NOMEM; + } + pe = (pmix_envar_t*)p->array; + se = (pmix_envar_t*)src->array; + for (n=0; n < src->size; n++) { + if (NULL != se[n].envar) { + pe[n].envar = strdup(se[n].envar); + } + if (NULL != se[n].value) { + pe[n].value = strdup(se[n].value); + } + pe[n].separator = se[n].separator; + } + break; default: free(p); return PMIX_ERR_UNKNOWN_DATA_TYPE; @@ -877,3 +896,21 @@ pmix_status_t pmix_bfrops_base_copy_array(pmix_info_array_t **dest, return PMIX_SUCCESS; } /*******************/ + +pmix_status_t pmix_bfrops_base_copy_envar(pmix_envar_t **dest, + pmix_envar_t *src, + pmix_data_type_t type) +{ + *dest = (pmix_envar_t*)malloc(sizeof(pmix_envar_t)); + if (NULL == (*dest)) { + return PMIX_ERR_NOMEM; + } + if (NULL != src->envar) { + (*dest)->envar = strdup(src->envar); + } + if (NULL != src->value) { + (*dest)->value = strdup(src->value); + } + (*dest)->separator = src->separator; + return PMIX_SUCCESS; +} diff --git a/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_fns.c b/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_fns.c index 5abf19c1e8..c6e8797f7d 100644 --- a/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_fns.c +++ b/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_fns.c @@ -49,6 +49,7 @@ void pmix_bfrops_base_value_load(pmix_value_t *v, const void *data, { pmix_byte_object_t *bo; pmix_proc_info_t *pi; + pmix_envar_t *envar; v->type = type; if (NULL == data) { @@ -174,6 +175,16 @@ void pmix_bfrops_base_value_load(pmix_value_t *v, const void *data, case PMIX_POINTER: memcpy(&(v->data.ptr), data, sizeof(void*)); break; + case PMIX_ENVAR: + envar = (pmix_envar_t*)data; + if (NULL != envar->envar) { + v->data.envar.envar = strdup(envar->envar); + } + if (NULL != envar->value) { + v->data.envar.value = strdup(envar->value); + } + v->data.envar.separator = envar->separator; + break; default: /* silence warnings */ break; @@ -187,6 +198,7 @@ pmix_status_t pmix_bfrops_base_value_unload(pmix_value_t *kv, size_t *sz) { pmix_status_t rc; + pmix_envar_t *envar; rc = PMIX_SUCCESS; if (NULL == data || @@ -304,6 +316,21 @@ pmix_status_t pmix_bfrops_base_value_unload(pmix_value_t *kv, memcpy(*data, &(kv->data.ptr), sizeof(void*)); *sz = sizeof(void*); break; + case PMIX_ENVAR: + PMIX_ENVAR_CREATE(envar, 1); + if (NULL == envar) { + return PMIX_ERR_NOMEM; + } + if (NULL != kv->data.envar.envar) { + envar->envar = strdup(kv->data.envar.envar); + } + if (NULL != kv->data.envar.value) { + envar->value = strdup(kv->data.envar.value); + } + envar->separator = kv->data.envar.separator; + *data = envar; + *sz = sizeof(pmix_envar_t); + break; default: /* silence warnings */ rc = PMIX_ERROR; @@ -398,16 +425,58 @@ pmix_value_cmp_t pmix_bfrops_base_value_cmp(pmix_value_t *p, } break; case PMIX_COMPRESSED_STRING: - if (p->data.bo.size != p1->data.bo.size) { - return false; + if (p->data.bo.size > p1->data.bo.size) { + return PMIX_VALUE2_GREATER; } else { - return true; + return PMIX_VALUE1_GREATER; } + break; case PMIX_STATUS: if (p->data.status == p1->data.status) { rc = PMIX_EQUAL; } break; + case PMIX_ENVAR: + if (NULL != p->data.envar.envar) { + if (NULL == p1->data.envar.envar) { + return PMIX_VALUE1_GREATER; + } + rc = strcmp(p->data.envar.envar, p1->data.envar.envar); + if (rc < 0) { + return PMIX_VALUE2_GREATER; + } else if (0 < rc) { + return PMIX_VALUE1_GREATER; + } + } else if (NULL != p1->data.envar.envar) { + /* we know value1->envar had to be NULL */ + return PMIX_VALUE2_GREATER; + } + + /* if both are NULL or are equal, then check value */ + if (NULL != p->data.envar.value) { + if (NULL == p1->data.envar.value) { + return PMIX_VALUE1_GREATER; + } + rc = strcmp(p->data.envar.value, p1->data.envar.value); + if (rc < 0) { + return PMIX_VALUE2_GREATER; + } else if (0 < rc) { + return PMIX_VALUE1_GREATER; + } + } else if (NULL != p1->data.envar.value) { + /* we know value1->value had to be NULL */ + return PMIX_VALUE2_GREATER; + } + + /* finally, check separator */ + if (p->data.envar.separator < p1->data.envar.separator) { + return PMIX_VALUE2_GREATER; + } + if (p1->data.envar.separator < p->data.envar.separator) { + return PMIX_VALUE1_GREATER; + } + rc = PMIX_EQUAL; + break; default: pmix_output(0, "COMPARE-PMIX-VALUE: UNSUPPORTED TYPE %d", (int)p->type); } @@ -431,6 +500,7 @@ pmix_status_t pmix_bfrops_base_value_xfer(pmix_value_t *p, pmix_modex_data_t *pm, *sm; pmix_proc_info_t *pi, *si; pmix_query_t *pq, *sq; + pmix_envar_t *pe, *se; /* copy the right field */ p->type = src->type; @@ -926,6 +996,23 @@ pmix_status_t pmix_bfrops_base_value_xfer(pmix_value_t *p, } } break; + case PMIX_ENVAR: + PMIX_ENVAR_CREATE(p->data.darray->array, src->data.darray->size); + if (NULL == p->data.darray->array) { + return PMIX_ERR_NOMEM; + } + pe = (pmix_envar_t*)p->data.darray->array; + se = (pmix_envar_t*)src->data.darray->array; + for (n=0; n < src->data.darray->size; n++) { + if (NULL != se[n].envar) { + pe[n].envar = strdup(se[n].envar); + } + if (NULL != se[n].value) { + pe[n].value = strdup(se[n].value); + } + pe[n].separator = se[n].separator; + } + break; default: return PMIX_ERR_UNKNOWN_DATA_TYPE; } @@ -933,6 +1020,17 @@ pmix_status_t pmix_bfrops_base_value_xfer(pmix_value_t *p, case PMIX_POINTER: memcpy(&p->data.ptr, &src->data.ptr, sizeof(void*)); break; + case PMIX_ENVAR: + PMIX_ENVAR_CONSTRUCT(&p->data.envar); + if (NULL != src->data.envar.envar) { + p->data.envar.envar = strdup(src->data.envar.envar); + } + if (NULL != src->data.envar.value) { + p->data.envar.value = strdup(src->data.envar.value); + } + p->data.envar.separator = src->data.envar.separator; + break; + /**** DEPRECATED ****/ case PMIX_INFO_ARRAY: p->data.array->size = src->data.array->size; diff --git a/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_pack.c b/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_pack.c index 28e08f8910..d5dda0cbb8 100644 --- a/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_pack.c +++ b/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_pack.c @@ -1000,6 +1000,12 @@ pmix_status_t pmix_bfrops_base_pack_darray(pmix_buffer_t *buffer, const void *sr return ret; } break; + case PMIX_ENVAR: + if (PMIX_SUCCESS != (ret = pmix_bfrops_base_pack_envar(buffer, p[i].array, p[i].size, PMIX_ENVAR))) { + return ret; + } + break; + /**** DEPRECATED ****/ case PMIX_INFO_ARRAY: if (PMIX_SUCCESS != (ret = pmix_bfrops_base_pack_array(buffer, p[i].array, p[i].size, PMIX_INFO_ARRAY))) { @@ -1223,6 +1229,12 @@ pmix_status_t pmix_bfrops_base_pack_val(pmix_buffer_t *buffer, return ret; } break; + case PMIX_ENVAR: + if (PMIX_SUCCESS != (ret = pmix_bfrops_base_pack_envar(buffer, &p->data.envar, 1, PMIX_ENVAR))) { + return ret; + } + break; + /**** DEPRECATED ****/ case PMIX_INFO_ARRAY: if (PMIX_SUCCESS != (ret = pmix_bfrops_base_pack_array(buffer, p->data.array, 1, PMIX_INFO_ARRAY))) { @@ -1271,8 +1283,32 @@ pmix_status_t pmix_bfrops_base_pack_array(pmix_buffer_t *buffer, const void *src return PMIX_SUCCESS; } -PMIX_EXPORT pmix_status_t pmix_bfrops_base_pack_iof_channel(pmix_buffer_t *buffer, const void *src, - int32_t num_vals, pmix_data_type_t type) +pmix_status_t pmix_bfrops_base_pack_iof_channel(pmix_buffer_t *buffer, const void *src, + int32_t num_vals, pmix_data_type_t type) +{ + return pmix_bfrops_base_pack_int16(buffer, src, num_vals, PMIX_UINT16); +} + +pmix_status_t pmix_bfrops_base_pack_envar(pmix_buffer_t *buffer, const void *src, + int32_t num_vals, pmix_data_type_t type) { + pmix_envar_t *ptr = (pmix_envar_t*)src; + int32_t i; + pmix_status_t ret; + + for (i=0; i < num_vals; ++i) { + /* pack the name */ + if (PMIX_SUCCESS != (ret = pmix_bfrops_base_pack_string(buffer, &ptr[i].envar, 1, PMIX_STRING))) { + return ret; + } + /* pack the value */ + if (PMIX_SUCCESS != (ret = pmix_bfrops_base_pack_string(buffer, &ptr[i].value, 1, PMIX_STRING))) { + return ret; + } + /* pack the separator */ + if (PMIX_SUCCESS != (ret = pmix_bfrops_base_pack_byte(buffer, &ptr[i].separator, 1, PMIX_BYTE))) { + return ret; + } + } return pmix_bfrops_base_pack_int16(buffer, src, num_vals, PMIX_UINT16); } diff --git a/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_print.c b/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_print.c index f411bd6823..9447e2df81 100644 --- a/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_print.c +++ b/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_print.c @@ -1014,6 +1014,13 @@ int pmix_bfrops_base_print_status(char **output, char *prefix, rc = asprintf(output, "%sPMIX_VALUE: Data type: DATA_ARRAY\tARRAY SIZE: %ld", prefx, (long)src->data.darray->size); break; + case PMIX_ENVAR: + rc = asprintf(output, "%sPMIX_VALUE: Data type: PMIX_ENVAR\tName: %s\tValue: %s\tSeparator: %c", + prefx, (NULL == src->data.envar.envar) ? "NULL" : src->data.envar.envar, + (NULL == src->data.envar.value) ? "NULL" : src->data.envar.value, + src->data.envar.separator); + break; + /**** DEPRECATED ****/ case PMIX_INFO_ARRAY: rc = asprintf(output, "%sPMIX_VALUE: Data type: INFO_ARRAY\tARRAY SIZE: %ld", @@ -1665,6 +1672,37 @@ pmix_status_t pmix_bfrops_base_print_iof_channel(char **output, char *prefix, } } +pmix_status_t pmix_bfrops_base_print_envar(char **output, char *prefix, + pmix_envar_t *src, + pmix_data_type_t type) +{ + char *prefx; + int ret; + + /* deal with NULL prefix */ + if (NULL == prefix) { + if (0 > asprintf(&prefx, " ")) { + return PMIX_ERR_NOMEM; + } + } else { + prefx = prefix; + } + + ret = asprintf(output, "%sData type: PMIX_ENVAR\tName: %s\tValue: %s\tSeparator: %c", + prefx, (NULL == src->envar) ? "NULL" : src->envar, + (NULL == src->value) ? "NULL" : src->value, + ('\0' == src->separator) ? ' ' : src->separator); + if (prefx != prefix) { + free(prefx); + } + + if (0 > ret) { + return PMIX_ERR_OUT_OF_RESOURCE; + } else { + return PMIX_SUCCESS; + } +} + /**** DEPRECATED ****/ pmix_status_t pmix_bfrops_base_print_array(char **output, char *prefix, diff --git a/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_unpack.c b/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_unpack.c index 87c7547b98..670697eae5 100644 --- a/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_unpack.c +++ b/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/base/bfrop_base_unpack.c @@ -758,6 +758,11 @@ pmix_status_t pmix_bfrops_base_unpack_val(pmix_buffer_t *buffer, return ret; } break; + case PMIX_ENVAR: + if (PMIX_SUCCESS != (ret = pmix_bfrops_base_unpack_envar(buffer, val->data.darray, &m, PMIX_ENVAR))) { + return ret; + } + break; /**** DEPRECATED ****/ case PMIX_INFO_ARRAY: /* this field is now a pointer, so we must allocate storage for it */ @@ -1524,6 +1529,15 @@ pmix_status_t pmix_bfrops_base_unpack_darray(pmix_buffer_t *buffer, void *dest, return ret; } break; + case PMIX_ENVAR: + ptr[i].array = (pmix_envar_t*)malloc(m * sizeof(pmix_envar_t)); + if (NULL == ptr[i].array) { + return PMIX_ERR_NOMEM; + } + if (PMIX_SUCCESS != (ret = pmix_bfrops_base_unpack_envar(buffer, ptr[i].array, &m, ptr[i].type))) { + return ret; + } + break; /**** DEPRECATED ****/ case PMIX_INFO_ARRAY: ptr[i].array = (pmix_info_array_t*)malloc(m * sizeof(pmix_info_array_t)); @@ -1609,6 +1623,40 @@ pmix_status_t pmix_bfrops_base_unpack_iof_channel(pmix_buffer_t *buffer, void *d return pmix_bfrops_base_unpack_int16(buffer, dest, num_vals, PMIX_UINT16); } +pmix_status_t pmix_bfrops_base_unpack_envar(pmix_buffer_t *buffer, void *dest, + int32_t *num_vals, pmix_data_type_t type) +{ + pmix_envar_t *ptr; + int32_t i, n, m; + pmix_status_t ret; + + pmix_output_verbose(20, pmix_bfrops_base_framework.framework_output, + "pmix_bfrop_unpack: %d envars", *num_vals); + + ptr = (pmix_envar_t *) dest; + n = *num_vals; + + for (i = 0; i < n; ++i) { + PMIX_ENVAR_CONSTRUCT(&ptr[i]); + /* unpack the name */ + m=1; + if (PMIX_SUCCESS != (ret = pmix_bfrops_base_unpack_string(buffer, &ptr[i].envar, &m, PMIX_STRING))) { + return ret; + } + /* unpack the value */ + m=1; + if (PMIX_SUCCESS != (ret = pmix_bfrops_base_unpack_string(buffer, &ptr[i].value, &m, PMIX_STRING))) { + return ret; + } + /* unpack the separator */ + m=1; + if (PMIX_SUCCESS != (ret = pmix_bfrops_base_unpack_byte(buffer, &ptr[i].separator, &m, PMIX_BYTE))) { + return ret; + } + } + return PMIX_SUCCESS; +} + /**** DEPRECATED ****/ pmix_status_t pmix_bfrops_base_unpack_array(pmix_buffer_t *buffer, void *dest, int32_t *num_vals, pmix_data_type_t type) diff --git a/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/v3/bfrop_pmix3.c b/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/v3/bfrop_pmix3.c index c1fa8277c9..e55a1ccbb8 100644 --- a/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/v3/bfrop_pmix3.c +++ b/opal/mca/pmix/pmix3x/pmix/src/mca/bfrops/v3/bfrop_pmix3.c @@ -380,6 +380,14 @@ static pmix_status_t init(void) pmix_bfrops_base_print_iof_channel, &mca_bfrops_v3_component.types); + PMIX_REGISTER_TYPE("PMIX_ENVAR", + PMIX_ENVAR, + pmix_bfrops_base_pack_envar, + pmix_bfrops_base_unpack_envar, + pmix_bfrops_base_copy_envar, + pmix_bfrops_base_print_envar, + &mca_bfrops_v3_component.types); + /**** DEPRECATED ****/ PMIX_REGISTER_TYPE("PMIX_INFO_ARRAY", PMIX_INFO_ARRAY, pmix_bfrops_base_pack_array, diff --git a/opal/mca/pmix/pmix3x/pmix3x.c b/opal/mca/pmix/pmix3x/pmix3x.c index 04e58c2da0..6d4ffde4dd 100644 --- a/opal/mca/pmix/pmix3x/pmix3x.c +++ b/opal/mca/pmix/pmix3x/pmix3x.c @@ -910,6 +910,17 @@ void pmix3x_value_load(pmix_value_t *v, v->data.darray->array = NULL; } break; + case OPAL_ENVAR: + v->type = PMIX_ENVAR; + PMIX_ENVAR_CONSTRUCT(&v->data.envar); + if (NULL != kv->data.envar.envar) { + v->data.envar.envar = strdup(kv->data.envar.envar); + } + if (NULL != kv->data.envar.value) { + v->data.envar.value = strdup(kv->data.envar.value); + } + v->data.envar.separator = kv->data.envar.separator; + break; default: /* silence warnings */ break; @@ -917,7 +928,7 @@ void pmix3x_value_load(pmix_value_t *v, } int pmix3x_value_unload(opal_value_t *kv, - const pmix_value_t *v) + const pmix_value_t *v) { int rc=OPAL_SUCCESS; bool found; @@ -1092,6 +1103,17 @@ int pmix3x_value_unload(opal_value_t *kv, } } break; + case PMIX_ENVAR: + kv->type = OPAL_ENVAR; + OBJ_CONSTRUCT(&kv->data.envar, opal_envar_t); + if (NULL != v->data.envar.envar) { + kv->data.envar.envar = strdup(v->data.envar.envar); + } + if (NULL != v->data.envar.value) { + kv->data.envar.value = strdup(v->data.envar.value); + } + kv->data.envar.separator = v->data.envar.separator; + break; default: /* silence warnings */ rc = OPAL_ERROR; diff --git a/opal/mca/pmix/pmix_types.h b/opal/mca/pmix/pmix_types.h index b76f0ddb3c..8dc4d0b026 100644 --- a/opal/mca/pmix/pmix_types.h +++ b/opal/mca/pmix/pmix_types.h @@ -278,6 +278,17 @@ BEGIN_C_DECLS #define OPAL_PMIX_MAX_RESTARTS "pmix.maxrestarts" // (uint32_t) max number of times to restart a job +/* environmental variable operation attributes */ +#define OPAL_PMIX_SET_ENVAR "pmix.envar.set" // (pmix_envar_t*) set the envar to the given value, + // overwriting any pre-existing one +#define OPAL_PMIX_UNSET_ENVAR "pmix.envar.unset" // (char*) unset the envar, if present +#define OPAL_PMIX_PREPEND_ENVAR "pmix.envar.prepnd" // (pmix_envar_t*) prepend the given value to the + // specified envar using the separator + // character, creating the envar if it doesn't already exist +#define OPAL_PMIX_APPEND_ENVAR "pmix.envar.appnd" // (pmix_envar_t*) append the given value to the specified + // envar using the separator character, + // creating the envar if it doesn't already exist + /* query attributes */ #define OPAL_PMIX_QUERY_NAMESPACES "pmix.qry.ns" // (char*) request a comma-delimited list of active nspaces #define OPAL_PMIX_QUERY_JOB_STATUS "pmix.qry.jst" // (pmix_status_t) status of a specified currently executing job @@ -325,11 +336,6 @@ BEGIN_C_DECLS #define OPAL_PMIX_RM_VERSION "pmix.rm.version" // (char*) RM version string -/* attributes for setting envars */ -#define OPAL_PMIX_SET_ENVAR "pmix.set.envar" // (char*) string "key=value" value shall be put into the environment -#define OPAL_PMIX_UNSET_ENVAR "pmix.unset.envar" // (char*) unset envar specified in string - - /* attributes relating to allocations */ #define OPAL_PMIX_ALLOC_ID "pmix.alloc.id" // (char*) provide a string identifier for this allocation request // which can later be used to query status of the request diff --git a/orte/include/orte/types.h b/orte/include/orte/types.h index 2f9306c33b..59865ed61b 100644 --- a/orte/include/orte/types.h +++ b/orte/include/orte/types.h @@ -9,7 +9,7 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. - * Copyright (c) 2014 Intel, Inc. All rights reserved. + * Copyright (c) 2014-2018 Intel, Inc. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -144,6 +144,7 @@ typedef struct { orte_vpid_t vpid; orte_jobid_t jobid; opal_process_name_t name; + opal_envar_t envar; } data; } orte_attribute_t; OPAL_DECLSPEC OBJ_CLASS_DECLARATION(orte_attribute_t); diff --git a/orte/mca/iof/base/iof_base_frame.c b/orte/mca/iof/base/iof_base_frame.c index 91bd4ffc5e..3e6584fd78 100644 --- a/orte/mca/iof/base/iof_base_frame.c +++ b/orte/mca/iof/base/iof_base_frame.c @@ -109,7 +109,7 @@ static int orte_iof_base_close(void) */ static int orte_iof_base_open(mca_base_open_flag_t flags) { - int rc, xmlfd; + int xmlfd; /* daemons do not need to do this as they do not write out stdout/err */ if (!ORTE_PROC_IS_DAEMON) { diff --git a/orte/mca/schizo/ompi/schizo_ompi.c b/orte/mca/schizo/ompi/schizo_ompi.c index 81bfeca490..219f5050f1 100644 --- a/orte/mca/schizo/ompi/schizo_ompi.c +++ b/orte/mca/schizo/ompi/schizo_ompi.c @@ -799,14 +799,16 @@ static int setup_fork(orte_job_t *jdata, orte_app_context_t *app) { int i; - char *param; + char *param, *p2, *saveptr; bool oversubscribed; orte_node_t *node; char **envcpy, **nps, **firstranks; char *npstring, *firstrankstring; char *num_app_ctx; bool takeus = false; + bool exists; orte_app_context_t* tmp_app; + orte_attribute_t *attr; opal_output_verbose(1, orte_schizo_base_framework.framework_output, "%s schizo:ompi: setup_fork", @@ -1043,6 +1045,128 @@ static int setup_fork(orte_job_t *jdata, free(num_app_ctx); free(firstrankstring); free(npstring); + + /* now process any envar attributes - we begin with the job-level + * ones as the app-specific ones can override them. We have to + * process them in the order they were given to ensure we wind + * up in the desired final state */ + OPAL_LIST_FOREACH(attr, &jdata->attributes, orte_attribute_t) { + if (ORTE_JOB_SET_ENVAR == attr->key) { + opal_setenv(attr->data.envar.envar, attr->data.envar.value, true, &app->env); + } else if (ORTE_JOB_UNSET_ENVAR == attr->key) { + opal_unsetenv(attr->data.string, &app->env); + } else if (ORTE_JOB_PREPEND_ENVAR == attr->key) { + /* see if the envar already exists */ + exists = false; + for (i=0; NULL != app->env[i]; i++) { + saveptr = strchr(app->env[i], '='); // cannot be NULL + *saveptr = '\0'; + if (0 == strcmp(app->env[i], attr->data.envar.envar)) { + /* we have the var - prepend it */ + param = saveptr; + ++param; // move past where the '=' sign was + (void)asprintf(&p2, "%s%c%s", attr->data.envar.value, + attr->data.envar.separator, param); + *saveptr = '='; // restore the current envar setting + opal_setenv(attr->data.envar.envar, p2, true, &app->env); + free(p2); + exists = true; + break; + } else { + *saveptr = '='; // restore the current envar setting + } + } + if (!exists) { + /* just insert it */ + opal_setenv(attr->data.envar.envar, attr->data.envar.value, true, &app->env); + } + } else if (ORTE_JOB_APPEND_ENVAR == attr->key) { + /* see if the envar already exists */ + exists = false; + for (i=0; NULL != app->env[i]; i++) { + saveptr = strchr(app->env[i], '='); // cannot be NULL + *saveptr = '\0'; + if (0 == strcmp(app->env[i], attr->data.envar.envar)) { + /* we have the var - prepend it */ + param = saveptr; + ++param; // move past where the '=' sign was + (void)asprintf(&p2, "%s%c%s", param, attr->data.envar.separator, + attr->data.envar.value); + *saveptr = '='; // restore the current envar setting + opal_setenv(attr->data.envar.envar, p2, true, &app->env); + free(p2); + exists = true; + break; + } else { + *saveptr = '='; // restore the current envar setting + } + } + if (!exists) { + /* just insert it */ + opal_setenv(attr->data.envar.envar, attr->data.envar.value, true, &app->env); + } + } + } + + /* now do the same thing for any app-level attributes */ + OPAL_LIST_FOREACH(attr, &app->attributes, orte_attribute_t) { + if (ORTE_APP_SET_ENVAR == attr->key) { + opal_setenv(attr->data.envar.envar, attr->data.envar.value, true, &app->env); + } else if (ORTE_APP_UNSET_ENVAR == attr->key) { + opal_unsetenv(attr->data.string, &app->env); + } else if (ORTE_APP_PREPEND_ENVAR == attr->key) { + /* see if the envar already exists */ + exists = false; + for (i=0; NULL != app->env[i]; i++) { + saveptr = strchr(app->env[i], '='); // cannot be NULL + *saveptr = '\0'; + if (0 == strcmp(app->env[i], attr->data.envar.envar)) { + /* we have the var - prepend it */ + param = saveptr; + ++param; // move past where the '=' sign was + (void)asprintf(&p2, "%s%c%s", attr->data.envar.value, + attr->data.envar.separator, param); + *saveptr = '='; // restore the current envar setting + opal_setenv(attr->data.envar.envar, p2, true, &app->env); + free(p2); + exists = true; + break; + } else { + *saveptr = '='; // restore the current envar setting + } + } + if (!exists) { + /* just insert it */ + opal_setenv(attr->data.envar.envar, attr->data.envar.value, true, &app->env); + } + } else if (ORTE_APP_APPEND_ENVAR == attr->key) { + /* see if the envar already exists */ + exists = false; + for (i=0; NULL != app->env[i]; i++) { + saveptr = strchr(app->env[i], '='); // cannot be NULL + *saveptr = '\0'; + if (0 == strcmp(app->env[i], attr->data.envar.envar)) { + /* we have the var - prepend it */ + param = saveptr; + ++param; // move past where the '=' sign was + (void)asprintf(&p2, "%s%c%s", param, attr->data.envar.separator, + attr->data.envar.value); + *saveptr = '='; // restore the current envar setting + opal_setenv(attr->data.envar.envar, p2, true, &app->env); + free(p2); + exists = true; + break; + } else { + *saveptr = '='; // restore the current envar setting + } + } + if (!exists) { + /* just insert it */ + opal_setenv(attr->data.envar.envar, attr->data.envar.value, true, &app->env); + } + } + } + return ORTE_SUCCESS; } diff --git a/orte/orted/pmix/pmix_server_dyn.c b/orte/orted/pmix/pmix_server_dyn.c index e4b9ee5b97..e221816861 100644 --- a/orte/orted/pmix/pmix_server_dyn.c +++ b/orte/orted/pmix/pmix_server_dyn.c @@ -246,6 +246,22 @@ int pmix_server_spawn_fn(opal_process_name_t *requestor, } else if (0 == strcmp(info->key, OPAL_PMIX_PRELOAD_FILES)) { orte_set_attribute(&app->attributes, ORTE_APP_PRELOAD_FILES, ORTE_ATTR_GLOBAL, info->data.string, OPAL_STRING); + + /*** ENVIRONMENTAL VARIABLE DIRECTIVES ***/ + /* there can be multiple of these, so we add them to the attribute list */ + } else if (0 == strcmp(info->key, OPAL_PMIX_SET_ENVAR)) { + orte_add_attribute(&app->attributes, ORTE_APP_SET_ENVAR, + ORTE_ATTR_GLOBAL, &info->data.envar, OPAL_ENVAR); + } else if (0 == strcmp(info->key, OPAL_PMIX_UNSET_ENVAR)) { + orte_add_attribute(&app->attributes, ORTE_APP_UNSET_ENVAR, + ORTE_ATTR_GLOBAL, info->data.string, OPAL_STRING); + } else if (0 == strcmp(info->key, OPAL_PMIX_PREPEND_ENVAR)) { + orte_add_attribute(&app->attributes, ORTE_APP_PREPEND_ENVAR, + ORTE_ATTR_GLOBAL, &info->data.envar, OPAL_ENVAR); + } else if (0 == strcmp(info->key, OPAL_PMIX_APPEND_ENVAR)) { + orte_add_attribute(&app->attributes, ORTE_APP_APPEND_ENVAR, + ORTE_ATTR_GLOBAL, &info->data.envar, OPAL_ENVAR); + } else { /* unrecognized key */ orte_show_help("help-orted.txt", "bad-key", @@ -460,6 +476,21 @@ int pmix_server_spawn_fn(opal_process_name_t *requestor, ORTE_FLAG_SET(jdata, ORTE_JOB_FLAG_DEBUGGER_DAEMON); ORTE_SET_MAPPING_DIRECTIVE(jdata->map->mapping, ORTE_MAPPING_DEBUGGER); + /*** ENVIRONMENTAL VARIABLE DIRECTIVES ***/ + /* there can be multiple of these, so we add them to the attribute list */ + } else if (0 == strcmp(info->key, OPAL_PMIX_SET_ENVAR)) { + orte_add_attribute(&jdata->attributes, ORTE_JOB_SET_ENVAR, + ORTE_ATTR_GLOBAL, &info->data.envar, OPAL_ENVAR); + } else if (0 == strcmp(info->key, OPAL_PMIX_UNSET_ENVAR)) { + orte_add_attribute(&jdata->attributes, ORTE_JOB_UNSET_ENVAR, + ORTE_ATTR_GLOBAL, info->data.string, OPAL_STRING); + } else if (0 == strcmp(info->key, OPAL_PMIX_PREPEND_ENVAR)) { + orte_add_attribute(&jdata->attributes, ORTE_JOB_PREPEND_ENVAR, + ORTE_ATTR_GLOBAL, &info->data.envar, OPAL_ENVAR); + } else if (0 == strcmp(info->key, OPAL_PMIX_APPEND_ENVAR)) { + orte_add_attribute(&jdata->attributes, ORTE_JOB_APPEND_ENVAR, + ORTE_ATTR_GLOBAL, &info->data.envar, OPAL_ENVAR); + /*** DEFAULT - CACHE FOR INCLUSION WITH JOB INFO ***/ } else { /* cache for inclusion with job info at registration */ diff --git a/orte/util/attr.c b/orte/util/attr.c index 19d644bf6a..15e2ae9406 100644 --- a/orte/util/attr.c +++ b/orte/util/attr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017 Intel, Inc. All rights reserved. + * Copyright (c) 2014-2018 Intel, Inc. All rights reserved. * Copyright (c) 2014-2017 Research Organization for Information Science * and Technology (RIST). All rights reserved. * $COPYRIGHT$ @@ -34,12 +34,6 @@ typedef struct { /* all default to NULL */ static orte_attr_converter_t converters[MAX_CONVERTERS]; -static int orte_attr_unload(orte_attribute_t *kv, - void **data, opal_data_type_t type); - -static int orte_attr_load(orte_attribute_t *kv, - void *data, opal_data_type_t type); - bool orte_get_attribute(opal_list_t *attributes, orte_attribute_key_t key, void **data, opal_data_type_t type) @@ -95,6 +89,63 @@ int orte_set_attribute(opal_list_t *attributes, return ORTE_SUCCESS; } +orte_attribute_t* orte_fetch_attribute(opal_list_t *attributes, + orte_attribute_t *prev, + orte_attribute_key_t key) +{ + orte_attribute_t *kv, *end, *next; + + /* if prev is NULL, then find the first attr on the list + * that matches the key */ + if (NULL == prev) { + OPAL_LIST_FOREACH(kv, attributes, orte_attribute_t) { + if (key == kv->key) { + return kv; + } + } + /* if we get, then the key isn't on the list */ + return NULL; + } + + /* if we are at the end of the list, then nothing to do */ + end = (orte_attribute_t*)opal_list_get_end(attributes); + if (prev == end || end == (orte_attribute_t*)opal_list_get_next(&prev->super) || + NULL == opal_list_get_next(&prev->super)) { + return NULL; + } + + /* starting with the next item on the list, search + * for the next attr with the matching key */ + next = (orte_attribute_t*)opal_list_get_next(&prev->super); + while (NULL != next) { + if (next->key == key) { + return next; + } + next = (orte_attribute_t*)opal_list_get_next(&next->super); + } + + /* if we get here, then no matching key was found */ + return NULL; +} + +int orte_add_attribute(opal_list_t *attributes, + orte_attribute_key_t key, bool local, + void *data, opal_data_type_t type) +{ + orte_attribute_t *kv; + int rc; + + kv = OBJ_NEW(orte_attribute_t); + kv->key = key; + kv->local = local; + if (OPAL_SUCCESS != (rc = orte_attr_load(kv, data, type))) { + OBJ_RELEASE(kv); + return rc; + } + opal_list_append(attributes, &kv->super); + return ORTE_SUCCESS; +} + void orte_remove_attribute(opal_list_t *attributes, orte_attribute_key_t key) { orte_attribute_t *kv; @@ -170,6 +221,14 @@ const char *orte_attr_key_to_str(orte_attribute_key_t key) return "APP-PREFIX-DIR"; case ORTE_APP_NO_CACHEDIR: return "ORTE_APP_NO_CACHEDIR"; + case ORTE_APP_SET_ENVAR: + return "ORTE_APP_SET_ENVAR"; + case ORTE_APP_UNSET_ENVAR: + return "ORTE_APP_UNSET_ENVAR"; + case ORTE_APP_PREPEND_ENVAR: + return "ORTE_APP_PREPEND_ENVAR"; + case ORTE_APP_APPEND_ENVAR: + return "ORTE_APP_APPEND_ENVAR"; case ORTE_NODE_USERNAME: return "NODE-USERNAME"; @@ -290,6 +349,14 @@ const char *orte_attr_key_to_str(orte_attribute_key_t key) return "ORTE_JOB_FULLY_DESCRIBED"; case ORTE_JOB_SILENT_TERMINATION: return "ORTE_JOB_SILENT_TERMINATION"; + case ORTE_JOB_SET_ENVAR: + return "ORTE_JOB_SET_ENVAR"; + case ORTE_JOB_UNSET_ENVAR: + return "ORTE_JOB_UNSET_ENVAR"; + case ORTE_JOB_PREPEND_ENVAR: + return "ORTE_JOB_PREPEND_ENVAR"; + case ORTE_JOB_APPEND_ENVAR: + return "ORTE_JOB_APPEND_ENVAR"; case ORTE_PROC_NOBARRIER: return "PROC-NOBARRIER"; @@ -360,11 +427,12 @@ const char *orte_attr_key_to_str(orte_attribute_key_t key) } -static int orte_attr_load(orte_attribute_t *kv, - void *data, opal_data_type_t type) +int orte_attr_load(orte_attribute_t *kv, + void *data, opal_data_type_t type) { opal_byte_object_t *boptr; struct timeval *tv; + opal_envar_t *envar; kv->type = type; if (NULL == data) { @@ -485,6 +553,18 @@ static int orte_attr_load(orte_attribute_t *kv, kv->data.name = *(opal_process_name_t *)data; break; + case OPAL_ENVAR: + OBJ_CONSTRUCT(&kv->data.envar, opal_envar_t); + envar = (opal_envar_t*)data; + if (NULL != envar->envar) { + kv->data.envar.envar = strdup(envar->envar); + } + if (NULL != envar->value) { + kv->data.envar.value = strdup(envar->value); + } + kv->data.envar.separator = envar->separator; + break; + default: OPAL_ERROR_LOG(OPAL_ERR_NOT_SUPPORTED); return OPAL_ERR_NOT_SUPPORTED; @@ -492,10 +572,11 @@ static int orte_attr_load(orte_attribute_t *kv, return OPAL_SUCCESS; } -static int orte_attr_unload(orte_attribute_t *kv, - void **data, opal_data_type_t type) +int orte_attr_unload(orte_attribute_t *kv, + void **data, opal_data_type_t type) { opal_byte_object_t *boptr; + opal_envar_t *envar; if (type != kv->type) { return OPAL_ERR_TYPE_MISMATCH; @@ -603,6 +684,18 @@ static int orte_attr_unload(orte_attribute_t *kv, memcpy(*data, &kv->data.name, sizeof(orte_process_name_t)); break; + case OPAL_ENVAR: + envar = OBJ_NEW(opal_envar_t); + if (NULL != kv->data.envar.envar) { + envar->envar = strdup(kv->data.envar.envar); + } + if (NULL != kv->data.envar.value) { + envar->value = strdup(kv->data.envar.value); + } + envar->separator = kv->data.envar.separator; + *data = envar; + break; + default: OPAL_ERROR_LOG(OPAL_ERR_NOT_SUPPORTED); return OPAL_ERR_NOT_SUPPORTED; diff --git a/orte/util/attr.h b/orte/util/attr.h index b1b9b224ea..dee75a07b4 100644 --- a/orte/util/attr.h +++ b/orte/util/attr.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017 Intel, Inc. All rights reserved. + * Copyright (c) 2014-2018 Intel, Inc. All rights reserved. * Copyright (c) 2016 Research Organization for Information Science * and Technology (RIST). All rights reserved. * $COPYRIGHT$ @@ -47,6 +47,10 @@ typedef uint8_t orte_app_context_flags_t; #define ORTE_APP_MAX_PPN 14 // uint32 - maximum number of procs/node for this app #define ORTE_APP_PREFIX_DIR 15 // string - prefix directory for this app, if override necessary #define ORTE_APP_NO_CACHEDIR 16 // bool - flag that a cache dir is not to be specified for a Singularity container +#define ORTE_APP_SET_ENVAR 17 // opal_envar_t - set the given envar to the specified value +#define ORTE_APP_UNSET_ENVAR 18 // string - name of envar to unset, if present +#define ORTE_APP_PREPEND_ENVAR 19 // opal_envar_t - prepend the specified value to the given envar +#define ORTE_APP_APPEND_ENVAR 20 // opal_envar_t - append the specified value to the given envar #define ORTE_APP_MAX_KEY 100 @@ -146,6 +150,10 @@ typedef uint16_t orte_job_flags_t; #define ORTE_JOB_FULLY_DESCRIBED (ORTE_JOB_START_KEY + 53) // bool - job is fully described in launch msg #define ORTE_JOB_SILENT_TERMINATION (ORTE_JOB_START_KEY + 54) // bool - do not generate an event notification when job // normally terminates +#define ORTE_JOB_SET_ENVAR (ORTE_JOB_START_KEY + 55) // opal_envar_t - set the given envar to the specified value +#define ORTE_JOB_UNSET_ENVAR (ORTE_JOB_START_KEY + 56) // string - name of envar to unset, if present +#define ORTE_JOB_PREPEND_ENVAR (ORTE_JOB_START_KEY + 57) // opal_envar_t - prepend the specified value to the given envar +#define ORTE_JOB_APPEND_ENVAR (ORTE_JOB_START_KEY + 58) // opal_envar_t - append the specified value to the given envar #define ORTE_JOB_MAX_KEY 300 @@ -221,6 +229,20 @@ ORTE_DECLSPEC int orte_set_attribute(opal_list_t *attributes, orte_attribute_key /* Remove the named attribute from a list */ ORTE_DECLSPEC void orte_remove_attribute(opal_list_t *attributes, orte_attribute_key_t key); +ORTE_DECLSPEC orte_attribute_t* orte_fetch_attribute(opal_list_t *attributes, + orte_attribute_t *prev, + orte_attribute_key_t key); + +ORTE_DECLSPEC int orte_add_attribute(opal_list_t *attributes, + orte_attribute_key_t key, bool local, + void *data, opal_data_type_t type); + +ORTE_DECLSPEC int orte_attr_load(orte_attribute_t *kv, + void *data, opal_data_type_t type); + +ORTE_DECLSPEC int orte_attr_unload(orte_attribute_t *kv, + void **data, opal_data_type_t type); + /* * Register a handler for converting attr keys to strings *