1
1

Merge pull request #4854 from rhc54/topic/update

Update ORTE to support PMIx v3
Этот коммит содержится в:
Ralph Castain 2018-03-02 05:49:29 -08:00 коммит произвёл GitHub
родитель f15d6200af 2f85db9791
Коммит f81828456f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
97 изменённых файлов: 5606 добавлений и 968 удалений

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

@ -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;
}

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

@ -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;
}

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

@ -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);
/*

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

@ -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-2015 Intel, Inc. All rights reserved.
* Copyright (c) 2014-2018 Intel, Inc. All rights reserved.
* Copyright (c) 2015-2017 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* $COPYRIGHT$

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

@ -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-2016 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;

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

@ -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;
}

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

@ -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-2016 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;
}

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

@ -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);

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

@ -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,35 @@ 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) {
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;
}

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

@ -10,7 +10,7 @@
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2010-2012 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$
*
* Additional copyrights may follow
@ -97,7 +97,8 @@ enum {
OPAL_ERR_EVENT_REGISTRATION = (OPAL_ERR_BASE - 66),
OPAL_ERR_HEARTBEAT_ALERT = (OPAL_ERR_BASE - 67),
OPAL_ERR_FILE_ALERT = (OPAL_ERR_BASE - 68),
OPAL_ERR_MODEL_DECLARED = (OPAL_ERR_BASE - 69)
OPAL_ERR_MODEL_DECLARED = (OPAL_ERR_BASE - 69),
OPAL_PMIX_LAUNCH_DIRECTIVE = (OPAL_ERR_BASE - 70)
};
#define OPAL_ERR_MAX (OPAL_ERR_BASE - 100)

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

@ -738,6 +738,35 @@ typedef int (*opal_pmix_base_module_server_push_io_fn_t)(const opal_process_name
opal_pmix_iof_channel_t channel,
unsigned char *data, size_t nbytes);
/* define a callback function for the setup_application API. The returned info
* array is owned by the PMIx server library and will be free'd when the
* provided cbfunc is called. */
typedef void (*opal_pmix_setup_application_cbfunc_t)(int status,
opal_list_t *info,
void *provided_cbdata,
opal_pmix_op_cbfunc_t cbfunc, void *cbdata);
/* Provide a function by which we can request
* any application-specific environmental variables prior to
* launch of an application. For example, network libraries may
* opt to provide security credentials for the application. This
* is defined as a non-blocking operation in case network
* libraries need to perform some action before responding. The
* returned env will be distributed along with the application */
typedef int (*opal_pmix_server_setup_application_fn_t)(opal_jobid_t jobid,
opal_list_t *info,
opal_pmix_setup_application_cbfunc_t cbfunc, void *cbdata);
/* Provide a function by which the local PMIx server can perform
* any application-specific operations prior to spawning local
* clients of a given application. For example, a network library
* might need to setup the local driver for "instant on" addressing.
*/
typedef int (*opal_pmix_server_setup_local_support_fn_t)(opal_jobid_t jobid,
opal_list_t *info,
opal_pmix_op_cbfunc_t cbfunc, void *cbdata);
/************************************************************
* TOOL APIs *
************************************************************/
@ -925,6 +954,8 @@ typedef struct {
opal_pmix_base_module_server_dmodex_request_fn_t server_dmodex_request;
opal_pmix_base_module_server_notify_event_fn_t server_notify_event;
opal_pmix_base_module_server_push_io_fn_t server_iof_push;
opal_pmix_server_setup_application_fn_t server_setup_application;
opal_pmix_server_setup_local_support_fn_t server_setup_local_support;
/* tool APIs */
opal_pmix_base_module_tool_init_fn_t tool_init;
opal_pmix_base_module_tool_fini_fn_t tool_finalize;

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

@ -30,7 +30,7 @@ greek=
# command, or with the date (if "git describe" fails) in the form of
# "date<date>".
repo_rev=gitf47bda5
repo_rev=git36e7e24
# If tarball_version is not empty, it is used as the version string in
# the tarball filename, regardless of all other versions listed in
@ -44,7 +44,7 @@ tarball_version=
# The date when this release was created
date="Feb 19, 2018"
date="Feb 09, 2018"
# The shared library version of each of PMIx's public libraries.
# These versions are maintained in accordance with the "Library

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

@ -626,7 +626,7 @@ AC_DEFUN([PMIX_SETUP_CORE],[
# Darwin doesn't need -lm, as it's a symlink to libSystem.dylib
PMIX_SEARCH_LIBS_CORE([ceil], [m])
AC_CHECK_FUNCS([asprintf snprintf vasprintf vsnprintf strsignal socketpair strncpy_s usleep statfs statvfs getpeereid getpeerucred strnlen posix_fallocate])
AC_CHECK_FUNCS([asprintf snprintf vasprintf vsnprintf strsignal socketpair strncpy_s usleep statfs statvfs getpeereid getpeerucred strnlen posix_fallocate tcgetpgrp])
# On some hosts, htonl is a define, so the AC_CHECK_FUNC will get
# confused. On others, it's in the standard library, but stubbed with

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

@ -1,6 +1,6 @@
# -*- text -*-
#
# Copyright (c) 2015 Intel, Inc. All rights reserved.
# Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow

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

@ -13,7 +13,7 @@
* All rights reserved.
* Copyright (c) 2009-2012 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2011 Oak Ridge National Labs. All rights reserved.
* Copyright (c) 2013-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2013-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2015 Mellanox Technologies, Inc. All rights reserved.
* $COPYRIGHT$
*
@ -41,6 +41,7 @@ typedef struct {
} myquery_data_t;
static volatile bool waiting_for_debugger = true;
static pmix_proc_t myproc;
/* this is a callback function for the PMIx_Query
@ -133,6 +134,11 @@ int main(int argc, char **argv)
size_t nq, n;
myquery_data_t myquery_data;
fprintf(stderr, "I AM HERE\n");
fflush(stderr);
sleep(10);
exit(0);
/* init us - since we were launched by the RM, our connection info
* will have been provided at startup. */
if (PMIX_SUCCESS != (rc = PMIx_tool_init(&myproc, NULL, 0))) {
@ -210,7 +216,7 @@ int main(int argc, char **argv)
n = 0;
fprintf(stderr, "[%s:%u] Hanging around awhile, doing debugger magic\n", myproc.nspace, myproc.rank);
while (n < 5) {
usleep(10);
usleep(1000);
++n;
}

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

@ -567,7 +567,6 @@ PMIX_EXPORT pmix_status_t PMIx_Process_monitor_nb(const pmix_info_t *monitor, pm
PMIX_INFO_DESTRUCT(&_in); \
} while(0)
/* Request a credential from the PMIx server/SMS.
* Input values include:
*
@ -632,6 +631,118 @@ PMIX_EXPORT pmix_status_t PMIx_Validate_credential(const pmix_byte_object_t *cre
const pmix_info_t info[], size_t ninfo,
pmix_validation_cbfunc_t cbfunc, void *cbdata);
/* Define a callback function for delivering forwarded IO to a process
* This function will be called whenever data becomes available, or a
* specified buffering size and/or time has been met. The function
* will be passed the following values:
*
* iofhdlr - the returned registration number of the handler being invoked.
* This is required when deregistering the handler.
*
* channel - a bitmask identifying the channel the data arrived on
*
* source - the nspace/rank of the process that generated the data
*
* payload - pointer to character array containing the data. Note that
* multiple strings may be included, and that the array may
* _not_ be NULL terminated
*
* info - an optional array of info provided by the source containing
* metadata about the payload. This could include PMIX_IOF_COMPLETE
*
* ninfo - number of elements in the optional info array
*/
typedef void (*pmix_iof_cbfunc_t)(size_t iofhdlr, pmix_iof_channel_t channel,
pmix_proc_t *source, char *payload,
pmix_info_t info[], size_t ninfo);
/* Register to receive output forwarded from a remote process.
*
* procs - array of identifiers for sources whose IO is being
* requested. Wildcard rank indicates that all procs
* in the specified nspace are included in the request
*
* nprocs - number of identifiers in the procs array
*
* directives - optional array of attributes to control the
* behavior of the request. For example, this
* might include directives on buffering IO
* before delivery, and/or directives to include
* or exclude any backlogged data
*
* ndirs - number of elements in the directives array
*
* channel - bitmask of IO channels included in the request.
* NOTE: STDIN is not supported as it will always
* be delivered to the stdin file descriptor
*
* cbfunc - function to be called when relevant IO is received
*
* regcbfunc - since registration is async, this is the
* function to be called when registration is
* completed. The function itself will return
* a non-success error if the registration cannot
* be submitted - in this case, the regcbfunc
* will _not_ be called.
*
* cbdata - pointer to object to be returned in regcbfunc
*/
PMIX_EXPORT pmix_status_t PMIx_IOF_pull(const pmix_proc_t procs[], size_t nprocs,
const pmix_info_t directives[], size_t ndirs,
pmix_iof_channel_t channel, pmix_iof_cbfunc_t cbfunc,
pmix_hdlr_reg_cbfunc_t regcbfunc, void *regcbdata);
/* Deregister from output forwarded from a remote process.
*
* iofhdlr - the registration number returned from the
* call to PMIx_IOF_pull
*
* directives - optional array of attributes to control the
* behavior of the request. For example, this
* might include directives regarding what to
* do with any data currently in the IO buffer
* for this process
*
* cbfunc - function to be called when deregistration has
* been completed. Note that any IO to be flushed
* may continue to be received after deregistration
* has completed.
*
* cbdata - pointer to object to be returned in cbfunc
*/
PMIX_EXPORT pmix_status_t PMIx_IOF_deregister(size_t iofhdlr,
const pmix_info_t directives[], size_t ndirs,
pmix_op_cbfunc_t cbfunc, void *cbdata);
/* Push data collected locally (typically from stdin) to
* target recipients.
*
* targets - array of process identifiers to which the data is to be delivered. Note
* that a WILDCARD rank indicates that all procs in the given nspace are
* to receive a copy of the data
*
* ntargets - number of procs in the targets array
*
* directives - optional array of attributes to control the
* behavior of the request. For example, this
* might include directives on buffering IO
* before delivery, and/or directives to include
* or exclude any backlogged data
*
* ndirs - number of elements in the directives array
*
* bo - pointer to a byte object containing the stdin data
*
* cbfunc - callback function when the data has been forwarded
*
* cbdata - object to be returned in cbfunc
*/
PMIX_EXPORT pmix_status_t PMIx_IOF_push(const pmix_proc_t targets[], size_t ntargets,
pmix_byte_object_t *bo,
const pmix_info_t directives[], size_t ndirs,
pmix_op_cbfunc_t cbfunc, void *cbdata);
#if defined(c_plusplus) || defined(__cplusplus)
}

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

@ -147,6 +147,7 @@ typedef uint32_t pmix_rank_t;
#define PMIX_CONNECT_RETRY_DELAY "pmix.tool.retry" // (uint32_t) time in seconds between connection attempts
#define PMIX_TOOL_DO_NOT_CONNECT "pmix.tool.nocon" // (bool) the tool wants to use internal PMIx support, but does
// not want to connect to a PMIx server
// from the specified processes to this tool
/* identification attributes */
#define PMIX_USERID "pmix.euid" // (uint32_t) effective user id
@ -220,7 +221,9 @@ typedef uint32_t pmix_rank_t;
#define PMIX_LOCAL_CPUSETS "pmix.lcpus" // (char*) colon-delimited cpusets of local peers within the specified nspace
#define PMIX_PROC_URI "pmix.puri" // (char*) URI containing contact info for proc
#define PMIX_LOCALITY "pmix.loc" // (uint16_t) relative locality of two procs
#define PMIX_PARENT_ID "pmix.parent" // (pmix_proc_t) process identifier of my parent process
#define PMIX_PARENT_ID "pmix.parent" // (pmix_proc_t*) identifier of the process that called PMIx_Spawn
// to launch this proc's application
/* size info */
#define PMIX_UNIV_SIZE "pmix.univ.size" // (uint32_t) #procs in this nspace
@ -324,7 +327,7 @@ typedef uint32_t pmix_rank_t;
#define PMIX_EVENT_WANT_TERMINATION "pmix.evterm" // (bool) indicates that the handler has determined that the application should be terminated
/* attributes used to describe "spawn" attributes */
/* attributes used to describe "spawn" directives */
#define PMIX_PERSONALITY "pmix.pers" // (char*) name of personality to use
#define PMIX_HOST "pmix.host" // (char*) comma-delimited list of hosts to use for spawned procs
#define PMIX_HOSTFILE "pmix.hostfile" // (char*) hostfile to use for spawned procs
@ -341,10 +344,8 @@ typedef uint32_t pmix_rank_t;
#define PMIX_PRELOAD_BIN "pmix.preloadbin" // (bool) preload binaries
#define PMIX_PRELOAD_FILES "pmix.preloadfiles" // (char*) comma-delimited list of files to pre-position
#define PMIX_NON_PMI "pmix.nonpmi" // (bool) spawned procs will not call PMIx_Init
#define PMIX_STDIN_TGT "pmix.stdin" // (uint32_t) spawned proc rank that is to receive stdin
#define PMIX_FWD_STDIN "pmix.fwd.stdin" // (bool) forward my stdin to the designated proc
#define PMIX_FWD_STDOUT "pmix.fwd.stdout" // (bool) forward stdout from spawned procs to me
#define PMIX_FWD_STDERR "pmix.fwd.stderr" // (bool) forward stderr from spawned procs to me
#define PMIX_STDIN_TGT "pmix.stdin" // (pmix_proc_t) proc that is to receive stdin
// (PMIX_RANK_WILDCARD = all in given nspace)
#define PMIX_DEBUGGER_DAEMONS "pmix.debugger" // (bool) spawned app consists of debugger daemons
#define PMIX_COSPAWN_APP "pmix.cospawn" // (bool) designated app is to be spawned as a disconnected
// job - i.e., not part of the "comm_world" of the job
@ -364,6 +365,11 @@ typedef uint32_t pmix_rank_t;
#define PMIX_JOB_CONTINUOUS "pmix.continuous" // (bool) application is continuous, all failed procs should
// be immediately restarted
#define PMIX_MAX_RESTARTS "pmix.maxrestarts" // (uint32_t) max number of times to restart a job
#define PMIX_FWD_STDIN "pmix.fwd.stdin" // (bool) forward the stdin from this process to the spawned processes
#define PMIX_FWD_STDOUT "pmix.fwd.stdout" // (bool) forward stdout from the spawned processes to this process (typically used by a tool)
#define PMIX_FWD_STDERR "pmix.fwd.stderr" // (bool) forward stderr from the spawned processes to this process (typically used by a tool)
#define PMIX_FWD_STDDIAG "pmix.fwd.stddiag" // (bool) if a diagnostic channel exists, forward any output on it
// from the spawned processes to this process (typically used by a tool)
/* connect attributes */
@ -416,14 +422,24 @@ 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_DEBUG_JOB_DIRECTIVES "pmix.dbg.jdirs" // (pmix_data_array_t) array of job-level directives
#define PMIX_DEBUG_APP_DIRECTIVES "pmix.dbg.adirs" // (pmix_data_array_t) array of app-level directives
/* 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_ADD_ENVAR "pmix.envar.add" // (pmix_envar_t*) add envar, but do not overwrite any 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
@ -495,12 +511,38 @@ typedef uint32_t pmix_rank_t;
// generating the event
/* security attributes */
#define PMIX_CRED_TYPE "pmix.sec.ctype" // when passed in PMIx_Get_credential, a prioritized,
#define PMIX_CRED_TYPE "pmix.sec.ctype" // (char*) when passed in PMIx_Get_credential, a prioritized,
// comma-delimited list of desired credential types for use
// in environments where multiple authentication mechanisms
// may be available. When returned in a callback function, a
// string identifier of the credential type
/* IO Forwarding Attributes */
#define PMIX_IOF_CACHE_SIZE "pmix.iof.csize" // (uint32_t) requested size of the server cache in bytes for each specified channel.
// By default, the server is allowed (but not required) to drop
// all bytes received beyond the max size
#define PMIX_IOF_DROP_OLDEST "pmix.iof.old" // (bool) in an overflow situation, drop the oldest bytes to make room in the cache
#define PMIX_IOF_DROP_NEWEST "pmix.iof.new" // (bool) in an overflow situation, drop any new bytes received until room becomes
// available in the cache (default)
#define PMIX_IOF_BUFFERING_SIZE "pmix.iof.bsize" // (uint32_t) basically controls grouping of IO on the specified channel(s) to
// avoid being called every time a bit of IO arrives. The library
// will execute the callback whenever the specified number of bytes
// becomes available. Any remaining buffered data will be "flushed"
// upon call to deregister the respective channel
#define PMIX_IOF_BUFFERING_TIME "pmix.iof.btime" // (uint32_t) max time in seconds to buffer IO before delivering it. Used in conjunction
// with buffering size, this prevents IO from being held indefinitely
// while waiting for another payload to arrive
#define PMIX_IOF_COMPLETE "pmix.iof.cmp" // (bool) indicates whether or not the specified IO channel has been closed
// by the source
#define PMIX_IOF_PUSH_STDIN "pmix.iof.stdin" // (bool) Used by a tool to request that the PMIx library collect
// the tool's stdin and forward it to the procs specified in
// the PMIx_IOF_push call
/* Attributes for controlling contents of application setup data */
#define PMIX_SETUP_APP_ENVARS "pmix.setup.env" // (bool) harvest and include relevant envars
#define PMIX_SETUP_APP_NONENVARS "pmix.setup.nenv" // (bool) include all non-envar data
#define PMIX_SETUP_APP_ALL "pmix.setup.all" // (bool) include all relevant data
/**** PROCESS STATE DEFINITIONS ****/
typedef uint8_t pmix_proc_state_t;
@ -531,11 +573,13 @@ typedef uint8_t pmix_proc_state_t;
#define PMIX_PROC_STATE_ABORTED_BY_SIG (PMIX_PROC_STATE_ERROR + 4) /* process aborted by signal */
#define PMIX_PROC_STATE_TERM_WO_SYNC (PMIX_PROC_STATE_ERROR + 5) /* process exit'd w/o calling PMIx_Finalize */
#define PMIX_PROC_STATE_COMM_FAILED (PMIX_PROC_STATE_ERROR + 6) /* process communication has failed */
#define PMIX_PROC_STATE_CALLED_ABORT (PMIX_PROC_STATE_ERROR + 7) /* process called "PMIx_Abort" */
#define PMIX_PROC_STATE_MIGRATING (PMIX_PROC_STATE_ERROR + 8) /* process failed and is waiting for resources before restarting */
#define PMIX_PROC_STATE_CANNOT_RESTART (PMIX_PROC_STATE_ERROR + 9) /* process failed and cannot be restarted */
#define PMIX_PROC_STATE_TERM_NON_ZERO (PMIX_PROC_STATE_ERROR + 10) /* process exited with a non-zero status, indicating abnormal */
#define PMIX_PROC_STATE_FAILED_TO_LAUNCH (PMIX_PROC_STATE_ERROR + 11) /* unable to launch process */
#define PMIX_PROC_STATE_SENSOR_BOUND_EXCEEDED (PMIX_PROC_STATE_ERROR + 7) /* process exceeded a sensor limit */
#define PMIX_PROC_STATE_CALLED_ABORT (PMIX_PROC_STATE_ERROR + 8) /* process called "PMIx_Abort" */
#define PMIX_PROC_STATE_HEARTBEAT_FAILED (PMIX_PROC_STATE_ERROR + 9) /* process failed to send heartbeat w/in time limit */
#define PMIX_PROC_STATE_MIGRATING (PMIX_PROC_STATE_ERROR + 10) /* process failed and is waiting for resources before restarting */
#define PMIX_PROC_STATE_CANNOT_RESTART (PMIX_PROC_STATE_ERROR + 11) /* process failed and cannot be restarted */
#define PMIX_PROC_STATE_TERM_NON_ZERO (PMIX_PROC_STATE_ERROR + 12) /* process exited with a non-zero status, indicating abnormal */
#define PMIX_PROC_STATE_FAILED_TO_LAUNCH (PMIX_PROC_STATE_ERROR + 13) /* unable to launch process */
/**** PMIX ERROR CONSTANTS ****/
@ -638,6 +682,7 @@ typedef int pmix_status_t;
#define PMIX_GDS_ACTION_COMPLETE (PMIX_ERR_OP_BASE - 18)
#define PMIX_PROC_HAS_CONNECTED (PMIX_ERR_OP_BASE - 19)
#define PMIX_CONNECT_REQUESTED (PMIX_ERR_OP_BASE - 20)
#define PMIX_LAUNCH_DIRECTIVE (PMIX_ERR_OP_BASE - 21)
/* define a starting point for system error constants so
* we avoid renumbering when making additions */
@ -720,6 +765,9 @@ typedef uint16_t pmix_data_type_t;
#define PMIX_ALLOC_DIRECTIVE 43
/**** DEPRECATED ****/
#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 */
@ -786,11 +834,32 @@ typedef uint8_t pmix_alloc_directive_t;
#define PMIX_ALLOC_EXTERNAL 128
/* define a set of bit-mask flags for specifying IO
* forwarding channels. These can be OR'd together
* to reference multiple channels */
typedef uint16_t pmix_iof_channel_t;
#define PMIX_FWD_NO_CHANNELS 0x0000
#define PMIX_FWD_STDIN_CHANNEL 0x0001
#define PMIX_FWD_STDOUT_CHANNEL 0x0002
#define PMIX_FWD_STDERR_CHANNEL 0x0004
#define PMIX_FWD_STDDIAG_CHANNEL 0x0008
#define PMIX_FWD_ALL_CHANNELS 0x00ff
/**** PMIX BYTE OBJECT ****/
typedef struct pmix_byte_object {
char *bytes;
size_t size;
} pmix_byte_object_t;
#define PMIX_BYTE_OBJECT_CREATE(m, n) \
do { \
(m) = (pmix_byte_object_t*)malloc((n) * sizeof(pmix_byte_object_t)); \
if (NULL != (m)) { \
memset((m), 0, (n)*sizeof(pmix_byte_object_t)); \
} \
} while(0)
#define PMIX_BYTE_OBJECT_CONSTRUCT(m) \
do { \
(m)->bytes = NULL; \
@ -824,6 +893,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 */
@ -940,9 +1065,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) \
@ -980,6 +1105,17 @@ typedef struct pmix_data_array {
size_t size;
void *array;
} pmix_data_array_t;
#define PMIX_DATA_ARRAY_CONSTRUCT(m, n, t) \
do { \
(m)->type = (t); \
(m)->size = (n); \
} while(0)
#define PMIX_DATA_ARRAY_CREATE(m, n, t) \
do { \
(m) = (pmix_data_array_t*)calloc(1, sizeof(pmix_data_array_t)); \
PMIX_DATA_ARRAY_CONSTRUCT((m), (n), (t)); \
} while(0)
typedef struct pmix_info_array {
size_t size;
@ -1026,6 +1162,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;
/********************/
@ -1136,6 +1273,8 @@ typedef struct pmix_value {
} \
free(_p); \
/********************/ \
} else if (PMIX_ENVAR == (m)->type) { \
PMIX_ENVAR_DESTRUCT(&(m)->data.envar); \
} \
} while (0)
@ -1219,16 +1358,20 @@ struct pmix_info_t {
} \
} while (0)
#define PMIX_INFO_LOAD(m, k, v, t) \
do { \
(void)strncpy((m)->key, (k), PMIX_MAX_KEYLEN); \
pmix_value_load(&((m)->value), (v), (t)); \
} while (0)
#define PMIX_INFO_XFER(d, s) \
#define PMIX_INFO_LOAD(m, k, v, t) \
do { \
(void)strncpy((d)->key, (s)->key, PMIX_MAX_KEYLEN); \
(d)->flags = (s)->flags; \
pmix_value_xfer(&(d)->value, &(s)->value); \
if (NULL != (k)) { \
(void)strncpy((m)->key, (k), PMIX_MAX_KEYLEN); \
} \
pmix_value_load(&((m)->value), (v), (t)); \
} while (0)
#define PMIX_INFO_XFER(d, s) \
do { \
if (NULL != (s)->key) { \
(void)strncpy((d)->key, (s)->key, PMIX_MAX_KEYLEN); \
} \
(d)->flags = (s)->flags; \
pmix_value_xfer(&(d)->value, &(s)->value); \
} while(0)
#define PMIX_INFO_REQUIRED(m) \
@ -1249,7 +1392,9 @@ struct pmix_info_t {
(r) = PMIX_ERR_NOMEM; \
break; \
} \
_kv->key = strdup(_info[_n].key); \
if (NULL != _info[_n].key) { \
_kv->key = strdup(_info[_n].key); \
} \
PMIX_VALUE_XFER((r), _kv->value, &_info[_n].value);\
if (PMIX_SUCCESS != (r)) { \
PMIX_RELEASE(_kv); \
@ -1629,14 +1774,19 @@ typedef void (*pmix_notification_fn_t)(size_t evhdlr_registration_id,
pmix_event_notification_cbfunc_fn_t cbfunc,
void *cbdata);
/* define a callback function for calls to PMIx_Register_evhdlr. The
* status indicates if the request was successful or not, evhdlr_ref is
* an integer reference assigned to the event handler by PMIx, this reference
* must be used to deregister the err handler. A ptr to the original
* cbdata is returned. */
typedef void (*pmix_evhdlr_reg_cbfunc_t)(pmix_status_t status,
size_t evhdlr_ref,
void *cbdata);
/* define a callback function for calls to register handlers, e.g., event
* notification and IOF requests
*
* status - PMIX_SUCCESS or an appropriate error constant
*
* refid - reference identifier assigned to the handler by PMIx,
* used to deregister the handler
*
* cbdata - object provided to the registration call
*/
typedef void (*pmix_hdlr_reg_cbfunc_t)(pmix_status_t status,
size_t refid,
void *cbdata);
/* define a callback function for calls to PMIx_Get_nb. The status
* indicates if the requested data was found or not - a pointer to the
@ -1761,7 +1911,7 @@ typedef void (*pmix_validation_cbfunc_t)(pmix_status_t status,
PMIX_EXPORT void PMIx_Register_event_handler(pmix_status_t codes[], size_t ncodes,
pmix_info_t info[], size_t ninfo,
pmix_notification_fn_t evhdlr,
pmix_evhdlr_reg_cbfunc_t cbfunc,
pmix_hdlr_reg_cbfunc_t cbfunc,
void *cbdata);
/* Deregister an event handler
@ -1819,6 +1969,7 @@ PMIX_EXPORT pmix_status_t PMIx_Notify_event(pmix_status_t status,
* - pmix_info_directives_t (PMIX_INFO_DIRECTIVES)
* - pmix_data_type_t (PMIX_DATA_TYPE)
* - pmix_alloc_directive_t (PMIX_ALLOC_DIRECTIVE)
* - pmix_iof_channel_t (PMIX_IOF_CHANNEL)
*/
PMIX_EXPORT const char* PMIx_Error_string(pmix_status_t status);
PMIX_EXPORT const char* PMIx_Proc_state_string(pmix_proc_state_t state);
@ -1828,6 +1979,7 @@ PMIX_EXPORT const char* PMIx_Data_range_string(pmix_data_range_t range);
PMIX_EXPORT const char* PMIx_Info_directives_string(pmix_info_directives_t directives);
PMIX_EXPORT const char* PMIx_Data_type_string(pmix_data_type_t type);
PMIX_EXPORT const char* PMIx_Alloc_directive_string(pmix_alloc_directive_t directive);
PMIX_EXPORT const char* PMIx_IOF_channel_string(pmix_iof_channel_t channel);
/* Get the PMIx version string. Note that the provided string is
* statically defined and must NOT be free'd */

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

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2013-2018 Intel, Inc. All rights reserved.
* Copyright (c) 2015 Artem Y. Polyakov <artpol84@gmail.com>.
* All rights reserved.
* Copyright (c) 2015 Research Organization for Information Science
@ -414,6 +414,74 @@ typedef pmix_status_t (*pmix_server_validate_cred_fn_t)(const pmix_proc_t *proc,
const pmix_info_t directives[], size_t ndirs,
pmix_validation_cbfunc_t cbfunc, void *cbdata);
/* Request the specified IO channels be forwarded from the given array of procs.
* The function shall return PMIX_SUCCESS once the host RM accepts the request for
* processing, or a PMIx error code if the request itself isn't correct or supported.
* The callback function shall be called when the request has been processed,
* returning either PMIX_SUCCESS to indicate that IO shall be forwarded as requested,
* or some appropriate error code if the request has been denied.
*
* NOTE: STDIN is not supported in this call! The forwarding of stdin is a "push"
* process - procs cannot request that it be "pulled" from some other source
*
* procs - array of process identifiers whose IO is being requested.
*
* nprocs - size of the procs array
*
* directives - array of key-value attributes further defining the request. This
* might include directives on buffering and security credentials for
* access to protected channels
*
* ndirs - size of the directives array
*
* channels - bitmask identifying the channels to be forwarded
*
* cbfunc - callback function when the IO forwarding has been setup
*
* cbdata - object to be returned in cbfunc
*
* This call serves as a registration with the host RM for the given IO channels from
* the specified procs - the host RM is expected to ensure that this local PMIx server
* is on the distribution list for the channel/proc combination
*/
typedef pmix_status_t (*pmix_server_iof_fn_t)(const pmix_proc_t procs[], size_t nprocs,
const pmix_info_t directives[], size_t ndirs,
pmix_iof_channel_t channels,
pmix_op_cbfunc_t cbfunc, void *cbdata);
/* Passes stdin to the host RM for transmission to specified recipients. The host RM is
* responsible for forwarding the data to all PMIx servers that host the specified
* target.
*
* source - pointer to the identifier of the process whose stdin is being provided
*
* targets - array of process identifiers to which the data is to be delivered. Note
* that a WILDCARD rank indicates that all procs in the given nspace are
* to receive a copy of the data
*
* ntargets - number of procs in the targets array
*
* directives - array of key-value attributes further defining the request. This
* might include directives on buffering and security credentials for
* access to protected channels
*
* ndirs - size of the directives array
*
* bo - pointer to a byte object containing the stdin data
*
* cbfunc - callback function when the data has been forwarded
*
* cbdata - object to be returned in cbfunc
*
*/
typedef pmix_status_t (*pmix_server_stdin_fn_t)(const pmix_proc_t *source,
const pmix_proc_t targets[], size_t ntargets,
const pmix_info_t directives[], size_t ndirs,
const pmix_byte_object_t *bo,
pmix_op_cbfunc_t cbfunc, void *cbdata);
typedef struct pmix_server_module_2_0_0_t {
/* v1x interfaces */
pmix_server_client_connected_fn_t client_connected;
@ -441,9 +509,11 @@ typedef struct pmix_server_module_2_0_0_t {
/* v3x interfaces */
pmix_server_get_cred_fn_t get_credential;
pmix_server_validate_cred_fn_t validate_credential;
pmix_server_iof_fn_t iof_pull;
pmix_server_stdin_fn_t push_stdin;
} pmix_server_module_t;
/**** SERVER SUPPORT INIT/FINALIZE FUNCTIONS ****/
/**** HOST RM FUNCTIONS FOR INTERFACE TO PMIX SERVER ****/
/* Initialize the server support library, and provide a
* pointer to a pmix_server_module_t structure
@ -611,6 +681,38 @@ PMIX_EXPORT pmix_status_t PMIx_server_setup_local_support(const char nspace[],
pmix_info_t info[], size_t ninfo,
pmix_op_cbfunc_t cbfunc, void *cbdata);
/* Provide a function by which the host RM can pass forwarded IO
* to the local PMIx server for distribution to its clients. The
* PMIx server is responsible for determining which of its clients
* have actually registered for the provided data
*
* Parameters include:
*
* source - the process that provided the data being forwarded
*
* channel - the IOF channel (stdin, stdout, etc.)
*
* bo - a byte object containing the data
*
* info - an optional array of metadata describing the data, including
* attributes such as PMIX_IOF_COMPLETE to indicate that the
* source channel has been closed
*
* ninfo - number of elements in the info array
*
* cbfunc - a callback function to be executed once the provided data
* is no longer required. The host RM is required to retain
* the byte object until the callback is executed, or a
* non-success status is returned by the function
*
* cbdata - object pointer to be returned in the callback function
*/
PMIX_EXPORT pmix_status_t PMIx_server_IOF_deliver(const pmix_proc_t *source,
pmix_iof_channel_t channel,
const pmix_byte_object_t *bo,
const pmix_info_t info[], size_t ninfo,
pmix_op_cbfunc_t cbfunc, void *cbdata);
#if defined(c_plusplus) || defined(__cplusplus)
}
#endif

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

@ -98,6 +98,7 @@ PMIX_EXPORT pmix_status_t PMIx_tool_init(pmix_proc_t *proc,
* operation. */
PMIX_EXPORT pmix_status_t PMIx_tool_finalize(void);
#if defined(c_plusplus) || defined(__cplusplus)
}
#endif

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

@ -44,11 +44,10 @@ static void local_eviction_callback(int fd, short flags, void *arg)
}
int pmix_hotel_init(pmix_hotel_t *h, int num_rooms,
pmix_event_base_t *evbase,
uint32_t eviction_timeout,
int eviction_event_priority,
pmix_hotel_eviction_callback_fn_t evict_callback_fn)
pmix_status_t pmix_hotel_init(pmix_hotel_t *h, int num_rooms,
pmix_event_base_t *evbase,
uint32_t eviction_timeout,
pmix_hotel_eviction_callback_fn_t evict_callback_fn)
{
int i;

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

@ -142,7 +142,6 @@ PMIX_CLASS_DECLARATION(pmix_hotel_t);
* @param evbase Pointer to event base used for eviction timeout
* @param eviction_timeout Max length of a stay at the hotel before
* the eviction callback is invoked (in microseconds)
* @param eviction_event_priority Event lib priority for the eviction timeout
* @param evict_callback_fn Callback function invoked if an occupant
* does not check out before the eviction_timeout.
*
@ -158,11 +157,10 @@ PMIX_CLASS_DECLARATION(pmix_hotel_t);
* @return PMIX_SUCCESS if all initializations were succesful. Otherwise,
* the error indicate what went wrong in the function.
*/
PMIX_EXPORT int pmix_hotel_init(pmix_hotel_t *hotel, int num_rooms,
pmix_event_base_t *evbase,
uint32_t eviction_timeout,
int eviction_event_priority,
pmix_hotel_eviction_callback_fn_t evict_callback_fn);
PMIX_EXPORT pmix_status_t pmix_hotel_init(pmix_hotel_t *hotel, int num_rooms,
pmix_event_base_t *evbase,
uint32_t eviction_timeout,
pmix_hotel_eviction_callback_fn_t evict_callback_fn);
/**
* Check in an occupant to the hotel.
@ -184,9 +182,9 @@ PMIX_EXPORT int pmix_hotel_init(pmix_hotel_t *hotel, int num_rooms,
* @return PMIX_ERR_TEMP_OUT_OF_RESOURCE is the hotel is full. Try
* again later.
*/
static inline int pmix_hotel_checkin(pmix_hotel_t *hotel,
void *occupant,
int *room_num)
static inline pmix_status_t pmix_hotel_checkin(pmix_hotel_t *hotel,
void *occupant,
int *room_num)
{
pmix_hotel_room_t *room;
@ -214,8 +212,8 @@ static inline int pmix_hotel_checkin(pmix_hotel_t *hotel,
* caller *knows* that there is a room available.
*/
static inline void pmix_hotel_checkin_with_res(pmix_hotel_t *hotel,
void *occupant,
int *room_num)
void *occupant,
int *room_num)
{
pmix_hotel_room_t *room;

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

@ -75,6 +75,7 @@ static const char pmix_version_string[] = PMIX_VERSION;
#include "src/mca/preg/preg.h"
#include "src/mca/ptl/base/base.h"
#include "src/include/pmix_globals.h"
#include "src/common/pmix_iof.h"
#include "pmix_client_ops.h"
@ -342,6 +343,53 @@ static void _check_for_notify(pmix_info_t info[], size_t ninfo)
}
}
static void client_iof_handler(struct pmix_peer_t *pr,
pmix_ptl_hdr_t *hdr,
pmix_buffer_t *buf, void *cbdata)
{
pmix_peer_t *peer = (pmix_peer_t*)pr;
pmix_proc_t source;
pmix_iof_channel_t channel;
pmix_byte_object_t bo;
int32_t cnt;
pmix_status_t rc;
pmix_output_verbose(2, pmix_client_globals.iof_output,
"recvd IOF");
/* if the buffer is empty, they are simply closing the channel */
if (0 == buf->bytes_used) {
return;
}
cnt = 1;
PMIX_BFROPS_UNPACK(rc, peer, buf, &source, &cnt, PMIX_PROC);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
return;
}
cnt = 1;
PMIX_BFROPS_UNPACK(rc, peer, buf, &channel, &cnt, PMIX_IOF_CHANNEL);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
return;
}
cnt = 1;
PMIX_BFROPS_UNPACK(rc, peer, buf, &bo, &cnt, PMIX_BYTE_OBJECT);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
return;
}
if (NULL != bo.bytes && 0 < bo.size) {
if (channel & PMIX_FWD_STDOUT_CHANNEL) {
pmix_iof_write_output(&source, channel, &bo, &pmix_client_globals.iof_stdout.wev);
} else {
pmix_iof_write_output(&source, channel, &bo, &pmix_client_globals.iof_stderr.wev);
}
}
PMIX_BYTE_OBJECT_DESTRUCT(&bo);
}
PMIX_EXPORT pmix_status_t PMIx_Init(pmix_proc_t *proc,
pmix_info_t info[], size_t ninfo)
{
@ -358,6 +406,7 @@ PMIX_EXPORT pmix_status_t PMIx_Init(pmix_proc_t *proc,
pmix_lock_t reglock;
size_t n;
bool found;
pmix_ptl_posted_recv_t *rcv;
PMIX_ACQUIRE_THREAD(&pmix_global_lock);
@ -394,6 +443,13 @@ PMIX_EXPORT pmix_status_t PMIx_Init(pmix_proc_t *proc,
PMIX_RELEASE_THREAD(&pmix_global_lock);
return rc;
}
/* setup the IO Forwarding recv */
rcv = PMIX_NEW(pmix_ptl_posted_recv_t);
rcv->tag = PMIX_PTL_TAG_IOF;
rcv->cbfunc = client_iof_handler;
/* add it to the end of the list of recvs */
pmix_list_append(&pmix_ptl_globals.posted_recvs, &rcv->super);
/* setup the globals */
PMIX_CONSTRUCT(&pmix_client_globals.pending_requests, pmix_list_t);
@ -578,7 +634,7 @@ PMIX_EXPORT pmix_status_t PMIx_Init(pmix_proc_t *proc,
}
PMIX_RELEASE_THREAD(&pmix_global_lock);
/* lood for a debugger attach key */
/* look for a debugger attach key */
(void)strncpy(wildcard.nspace, pmix_globals.myid.nspace, PMIX_MAX_NSLEN);
wildcard.rank = PMIX_RANK_WILDCARD;
PMIX_INFO_LOAD(&ginfo, PMIX_OPTIONAL, NULL, PMIX_BOOL);
@ -587,6 +643,7 @@ PMIX_EXPORT pmix_status_t PMIx_Init(pmix_proc_t *proc,
/* if the value was found, then we need to wait for debugger attach here */
/* register for the debugger release notification */
PMIX_CONSTRUCT_LOCK(&reglock);
PMIX_POST_OBJECT(&reglock);
PMIx_Register_event_handler(&code, 1, NULL, 0,
notification_fn, NULL, (void*)&reglock);
/* wait for it to arrive */
@ -1118,11 +1175,27 @@ static void _commitfn(int sd, short args, void *cbdata)
return rc;
}
static void _resolve_peers(int sd, short args, void *cbdata)
{
pmix_cb_t *cb = (pmix_cb_t*)cbdata;
pmix_status_t rc;
cb->status = pmix_preg.resolve_peers(cb->key, cb->pname.nspace,
&cb->procs, &cb->nprocs);
/* post the data so the receiving thread can acquire it */
PMIX_POST_OBJECT(cb);
PMIX_WAKEUP_THREAD(&cb->lock);
}
/* need to thread-shift this request */
PMIX_EXPORT pmix_status_t PMIx_Resolve_peers(const char *nodename,
const char *nspace,
pmix_proc_t **procs, size_t *nprocs)
{
pmix_cb_t *cb;
pmix_status_t rc;
pmix_proc_t proc;
PMIX_ACQUIRE_THREAD(&pmix_global_lock);
if (pmix_globals.init_cntr <= 0) {
PMIX_RELEASE_THREAD(&pmix_global_lock);
@ -1130,16 +1203,71 @@ PMIX_EXPORT pmix_status_t PMIx_Resolve_peers(const char *nodename,
}
PMIX_RELEASE_THREAD(&pmix_global_lock);
/* set default */
*procs = NULL;
*nprocs = 0;
return pmix_preg.resolve_peers(nodename, nspace, procs, nprocs);
cb = PMIX_NEW(pmix_cb_t);
cb->key = (char*)nodename;
cb->pname.nspace = strdup(nspace);
PMIX_THREADSHIFT(cb, _resolve_peers);
/* wait for the result */
PMIX_WAIT_THREAD(&cb->lock);
/* if the nspace wasn't found, then we need to
* ask the server for that info */
if (PMIX_ERR_INVALID_NAMESPACE == cb->status) {
(void)strncpy(proc.nspace, nspace, PMIX_MAX_NSLEN);
proc.rank = PMIX_RANK_WILDCARD;
/* any key will suffice as it will bring down
* the entire data blob */
rc = PMIx_Get(&proc, PMIX_UNIV_SIZE, NULL, 0, NULL);
if (PMIX_SUCCESS != rc) {
PMIX_RELEASE(cb);
return rc;
}
/* retry the fetch */
cb->lock.active = true;
PMIX_THREADSHIFT(cb, _resolve_peers);
PMIX_WAIT_THREAD(&cb->lock);
}
*procs = cb->procs;
*nprocs = cb->nprocs;
rc = cb->status;
PMIX_RELEASE(cb);
return rc;
}
static void _resolve_nodes(int fd, short args, void *cbdata)
{
pmix_cb_t *cb = (pmix_cb_t*)cbdata;
char *regex, **names;
/* get a regular expression describing the PMIX_NODE_MAP */
cb->status = pmix_preg.resolve_nodes(cb->pname.nspace, &regex);
if (PMIX_SUCCESS == cb->status) {
/* parse it into an argv array of names */
cb->status = pmix_preg.parse_nodes(regex, &names);
if (PMIX_SUCCESS == cb->status) {
/* assemble it into a comma-delimited list */
cb->key = pmix_argv_join(names, ',');
pmix_argv_free(names);
} else {
free(regex);
}
}
/* post the data so the receiving thread can acquire it */
PMIX_POST_OBJECT(cb);
PMIX_WAKEUP_THREAD(&cb->lock);
}
/* need to thread-shift this request */
PMIX_EXPORT pmix_status_t PMIx_Resolve_nodes(const char *nspace, char **nodelist)
{
pmix_cb_t *cb;
pmix_status_t rc;
pmix_proc_t proc;
PMIX_ACQUIRE_THREAD(&pmix_global_lock);
if (pmix_globals.init_cntr <= 0) {
PMIX_RELEASE_THREAD(&pmix_global_lock);
@ -1147,8 +1275,35 @@ PMIX_EXPORT pmix_status_t PMIx_Resolve_nodes(const char *nspace, char **nodelist
}
PMIX_RELEASE_THREAD(&pmix_global_lock);
/* set default */
*nodelist = NULL;
cb = PMIX_NEW(pmix_cb_t);
cb->pname.nspace = strdup(nspace);
return pmix_preg.resolve_nodes(nspace, nodelist);
PMIX_THREADSHIFT(cb, _resolve_nodes);
/* wait for the result */
PMIX_WAIT_THREAD(&cb->lock);
/* if the nspace wasn't found, then we need to
* ask the server for that info */
if (PMIX_ERR_INVALID_NAMESPACE == cb->status) {
(void)strncpy(proc.nspace, nspace, PMIX_MAX_NSLEN);
proc.rank = PMIX_RANK_WILDCARD;
/* any key will suffice as it will bring down
* the entire data blob */
rc = PMIx_Get(&proc, PMIX_UNIV_SIZE, NULL, 0, NULL);
if (PMIX_SUCCESS != rc) {
PMIX_RELEASE(cb);
return rc;
}
/* retry the fetch */
cb->lock.active = true;
PMIX_THREADSHIFT(cb, _resolve_nodes);
PMIX_WAIT_THREAD(&cb->lock);
}
/* the string we want is in the key field */
*nodelist = cb->key;
rc = cb->status;
PMIX_RELEASE(cb);
return rc;
}

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

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
* Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -17,6 +17,7 @@
#include "src/class/pmix_list.h"
#include "src/class/pmix_pointer_array.h"
#include "src/include/pmix_globals.h"
#include "src/common/pmix_iof.h"
BEGIN_C_DECLS
@ -42,9 +43,15 @@ typedef struct {
// verbosity for client event operations
int event_output;
int event_verbose;
// verbosity for client iof operations
int iof_output;
int iof_verbose;
// verbosity for basic client functions
int base_output;
int base_verbose;
/* IOF output sinks */
pmix_iof_sink_t iof_stdout;
pmix_iof_sink_t iof_stderr;
} pmix_client_globals_t;
PMIX_EXPORT extern pmix_client_globals_t pmix_client_globals;

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

@ -1,6 +1,6 @@
# -*- makefile -*-
#
# Copyright (c) 2015-2017 Intel, Inc. All rights reserved.
# Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
# Copyright (c) 2016 Cisco Systems, Inc. All rights reserved.
# $COPYRIGHT$
#
@ -15,4 +15,8 @@ sources += \
common/pmix_log.c \
common/pmix_control.c \
common/pmix_data.c \
common/pmix_security.c
common/pmix_security.c \
common/pmix_iof.c
headers += \
common/pmix_iof.h

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

@ -0,0 +1,863 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2014-2018 Intel, Inc. All rights reserved.
* Copyright (c) 2016 Mellanox Technologies, Inc.
* All rights reserved.
* Copyright (c) 2016 IBM Corporation. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include <src/include/pmix_config.h>
#include <src/include/types.h>
#include <src/include/pmix_stdint.h>
#include <src/include/pmix_socket_errno.h>
#include <pmix.h>
#include <pmix_common.h>
#include <pmix_server.h>
#include <pmix_rename.h>
#include "src/threads/threads.h"
#include "src/util/argv.h"
#include "src/util/error.h"
#include "src/util/name_fns.h"
#include "src/util/output.h"
#include "src/mca/bfrops/bfrops.h"
#include "src/mca/ptl/ptl.h"
#include "src/client/pmix_client_ops.h"
#include "src/server/pmix_server_ops.h"
#include "src/include/pmix_globals.h"
static void msgcbfunc(struct pmix_peer_t *peer,
pmix_ptl_hdr_t *hdr,
pmix_buffer_t *buf, void *cbdata)
{
pmix_shift_caddy_t *cd = (pmix_shift_caddy_t*)cbdata;
int32_t m;
pmix_status_t rc, status;
/* unpack the return status */
m=1;
PMIX_BFROPS_UNPACK(rc, peer, buf, &status, &m, PMIX_STATUS);
if (PMIX_SUCCESS == rc && PMIX_SUCCESS == status) {
/* store the request on our list - we are in an event, and
* so this is safe */
pmix_list_append(&pmix_globals.iof_requests, &cd->iofreq->super);
} else if (PMIX_SUCCESS != rc) {
status = rc;
PMIX_RELEASE(cd->iofreq);
}
pmix_output_verbose(2, pmix_client_globals.iof_output,
"pmix:iof_register returned status %s", PMIx_Error_string(status));
if (NULL != cd->cbfunc.opcbfn) {
cd->cbfunc.opcbfn(status, cd->cbdata);
}
PMIX_RELEASE(cd);
}
PMIX_EXPORT pmix_status_t PMIx_IOF_pull(const pmix_proc_t procs[], size_t nprocs,
const pmix_info_t directives[], size_t ndirs,
pmix_iof_channel_t channel, pmix_iof_cbfunc_t cbfunc,
pmix_hdlr_reg_cbfunc_t regcbfunc, void *regcbdata)
{
pmix_shift_caddy_t *cd;
pmix_cmd_t cmd = PMIX_IOF_PULL_CMD;
pmix_buffer_t *msg;
pmix_status_t rc;
PMIX_ACQUIRE_THREAD(&pmix_global_lock);
pmix_output_verbose(2, pmix_client_globals.iof_output,
"pmix:iof_register");
if (pmix_globals.init_cntr <= 0) {
PMIX_RELEASE_THREAD(&pmix_global_lock);
return PMIX_ERR_INIT;
}
/* if we are a server, we cannot do this */
if (PMIX_PROC_IS_SERVER(pmix_globals.mypeer)) {
PMIX_RELEASE_THREAD(&pmix_global_lock);
return PMIX_ERR_NOT_SUPPORTED;
}
/* we don't allow stdin to flow thru this path */
if (PMIX_FWD_STDIN_CHANNEL & channel) {
PMIX_RELEASE_THREAD(&pmix_global_lock);
return PMIX_ERR_NOT_SUPPORTED;
}
/* if we aren't connected, don't attempt to send */
if (!pmix_globals.connected) {
PMIX_RELEASE_THREAD(&pmix_global_lock);
return PMIX_ERR_UNREACH;
}
PMIX_RELEASE_THREAD(&pmix_global_lock);
/* send this request to the server */
cd = PMIX_NEW(pmix_shift_caddy_t);
if (NULL == cd) {
return PMIX_ERR_NOMEM;
}
cd->cbfunc.hdlrregcbfn = regcbfunc;
cd->cbdata = regcbdata;
/* setup the request item */
cd->iofreq = PMIX_NEW(pmix_iof_req_t);
if (NULL == cd->iofreq) {
PMIX_RELEASE(cd);
return PMIX_ERR_NOMEM;
}
/* retain the channels and cbfunc */
cd->iofreq->channels = channel;
cd->iofreq->cbfunc = cbfunc;
/* we don't need the source specifications - only the
* server cares as it will filter against them */
/* setup the registration cmd */
msg = PMIX_NEW(pmix_buffer_t);
if (NULL == msg) {
PMIX_RELEASE(cd->iofreq);
PMIX_RELEASE(cd);
return PMIX_ERR_NOMEM;
}
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
msg, &cmd, 1, PMIX_COMMAND);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto cleanup;
}
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
msg, &nprocs, 1, PMIX_SIZE);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto cleanup;
}
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
msg, procs, nprocs, PMIX_PROC);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto cleanup;
}
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
msg, &ndirs, 1, PMIX_SIZE);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto cleanup;
}
if (0 < ndirs) {
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
msg, directives, ndirs, PMIX_INFO);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto cleanup;
}
}
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
msg, &channel, 1, PMIX_IOF_CHANNEL);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto cleanup;
}
pmix_output_verbose(2, pmix_client_globals.iof_output,
"pmix:iof_request sending to server");
PMIX_PTL_SEND_RECV(rc, pmix_client_globals.myserver,
msg, msgcbfunc, (void*)cd);
cleanup:
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
PMIX_RELEASE(cd->iofreq);
PMIX_RELEASE(cd);
}
return rc;
}
typedef struct {
pmix_op_cbfunc_t cbfunc;
void *cbdata;
} pmix_ltcaddy_t;
static void stdincbfunc(struct pmix_peer_t *peer,
pmix_ptl_hdr_t *hdr,
pmix_buffer_t *buf, void *cbdata)
{
pmix_ltcaddy_t *cd = (pmix_ltcaddy_t*)cbdata;
int cnt;
pmix_status_t rc, status;
/* a zero-byte buffer indicates that this recv is being
* completed due to a lost connection */
if (PMIX_BUFFER_IS_EMPTY(buf)) {
/* release the caller */
if (NULL != cd->cbfunc) {
cd->cbfunc(PMIX_ERR_COMM_FAILURE, cd->cbdata);
}
free(cd);
return;
}
/* unpack the status */
cnt = 1;
PMIX_BFROPS_UNPACK(rc, peer, buf, &status, &cnt, PMIX_STATUS);
if (PMIX_SUCCESS != rc) {
status = rc;
}
if (NULL != cd->cbfunc) {
cd->cbfunc(status, cd->cbdata);
}
free(cd);
}
pmix_status_t PMIx_IOF_push(const pmix_proc_t targets[], size_t ntargets,
pmix_byte_object_t *bo,
const pmix_info_t directives[], size_t ndirs,
pmix_op_cbfunc_t cbfunc, void *cbdata)
{
pmix_buffer_t *msg;
pmix_cmd_t cmd = PMIX_IOF_PUSH_CMD;
pmix_status_t rc;
pmix_ltcaddy_t *cd;
PMIX_ACQUIRE_THREAD(&pmix_global_lock);
if (pmix_globals.init_cntr <= 0) {
PMIX_RELEASE_THREAD(&pmix_global_lock);
return PMIX_ERR_INIT;
}
PMIX_RELEASE_THREAD(&pmix_global_lock);
/* if we are not a server, then we send the provided
* data to our server for processing */
if (!PMIX_PROC_IS_SERVER(pmix_globals.mypeer)) {
msg = PMIX_NEW(pmix_buffer_t);
if (NULL == msg) {
return PMIX_ERR_NOMEM;
}
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
msg, &cmd, 1, PMIX_COMMAND);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
return rc;
}
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
msg, &ntargets, 1, PMIX_SIZE);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
return rc;
}
if (0 < ntargets) {
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
msg, targets, ntargets, PMIX_PROC);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
return rc;
}
}
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
msg, &ndirs, 1, PMIX_SIZE);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
return rc;
}
if (0 < ndirs) {
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
msg, directives, ndirs, PMIX_INFO);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
return rc;
}
}
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
msg, bo, 1, PMIX_BYTE_OBJECT);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
return rc;
}
cd = (pmix_ltcaddy_t*)malloc(sizeof(pmix_ltcaddy_t));
if (NULL == cd) {
PMIX_RELEASE(msg);
rc = PMIX_ERR_NOMEM;
return rc;
}
PMIX_PTL_SEND_RECV(rc, pmix_client_globals.myserver,
msg, stdincbfunc, cd);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
free(cd);
}
return rc;
}
/* if we are a server, just pass the data up to our host */
if (NULL == pmix_host_server.push_stdin) {
return PMIX_ERR_NOT_SUPPORTED;
}
rc = pmix_host_server.push_stdin(&pmix_globals.myid,
targets, ntargets,
directives, ndirs,
bo, cbfunc, cbdata);
return PMIX_SUCCESS;
}
pmix_status_t pmix_iof_write_output(const pmix_proc_t *name,
pmix_iof_channel_t stream,
const pmix_byte_object_t *bo,
pmix_iof_write_event_t *channel)
{
char starttag[PMIX_IOF_BASE_TAG_MAX], endtag[PMIX_IOF_BASE_TAG_MAX], *suffix;
pmix_iof_write_output_t *output;
size_t i;
int j, k, starttaglen, endtaglen, num_buffered;
bool endtagged;
char qprint[10];
PMIX_OUTPUT_VERBOSE((1, pmix_client_globals.iof_output,
"%s write:output setting up to write %lu bytes to %s for %s on fd %d",
PMIX_NAME_PRINT(&pmix_globals.myid),
(unsigned long)bo->size,
PMIx_IOF_channel_string(stream),
PMIX_NAME_PRINT(name),
(NULL == channel) ? -1 : channel->fd));
/* setup output object */
output = PMIX_NEW(pmix_iof_write_output_t);
/* write output data to the corresponding tag */
if (PMIX_FWD_STDIN_CHANNEL & stream) {
/* copy over the data to be written */
if (0 < bo->size) {
/* don't copy 0 bytes - we just need to pass
* the zero bytes so the fd can be closed
* after it writes everything out
*/
memcpy(output->data, bo->bytes, bo->size);
}
output->numbytes = bo->size;
goto process;
} else if (PMIX_FWD_STDOUT_CHANNEL & stream) {
/* write the bytes to stdout */
suffix = "stdout";
} else if (PMIX_FWD_STDERR_CHANNEL & stream) {
/* write the bytes to stderr */
suffix = "stderr";
} else if (PMIX_FWD_STDDIAG_CHANNEL & stream) {
/* write the bytes to stderr */
suffix = "stddiag";
} else {
/* error - this should never happen */
PMIX_ERROR_LOG(PMIX_ERR_VALUE_OUT_OF_BOUNDS);
PMIX_OUTPUT_VERBOSE((1, pmix_client_globals.iof_output,
"%s stream %0x", PMIX_NAME_PRINT(&pmix_globals.myid), stream));
return PMIX_ERR_VALUE_OUT_OF_BOUNDS;
}
/* if this is to be xml tagged, create a tag with the correct syntax - we do not allow
* timestamping of xml output
*/
if (pmix_globals.xml_output) {
snprintf(starttag, PMIX_IOF_BASE_TAG_MAX, "<%s rank=\"%s\">", suffix, PMIX_RANK_PRINT(name->rank));
snprintf(endtag, PMIX_IOF_BASE_TAG_MAX, "</%s>", suffix);
goto construct;
}
/* if we are to timestamp output, start the tag with that */
if (pmix_globals.timestamp_output) {
time_t mytime;
char *cptr;
/* get the timestamp */
time(&mytime);
cptr = ctime(&mytime);
cptr[strlen(cptr)-1] = '\0'; /* remove trailing newline */
if (pmix_globals.tag_output) {
/* if we want it tagged as well, use both */
snprintf(starttag, PMIX_IOF_BASE_TAG_MAX, "%s[%s]<%s>:",
cptr, PMIX_NAME_PRINT(name), suffix);
} else {
/* only use timestamp */
snprintf(starttag, PMIX_IOF_BASE_TAG_MAX, "%s<%s>:", cptr, suffix);
}
/* no endtag for this option */
memset(endtag, '\0', PMIX_IOF_BASE_TAG_MAX);
goto construct;
}
if (pmix_globals.tag_output) {
snprintf(starttag, PMIX_IOF_BASE_TAG_MAX, "[%s]<%s>:",
PMIX_NAME_PRINT(name), suffix);
/* no endtag for this option */
memset(endtag, '\0', PMIX_IOF_BASE_TAG_MAX);
goto construct;
}
/* if we get here, then the data is not to be tagged - just copy it
* and move on to processing
*/
if (0 < bo->size) {
/* don't copy 0 bytes - we just need to pass
* the zero bytes so the fd can be closed
* after it writes everything out
*/
memcpy(output->data, bo->bytes, bo->size);
}
output->numbytes = bo->size;
goto process;
construct:
starttaglen = strlen(starttag);
endtaglen = strlen(endtag);
endtagged = false;
/* start with the tag */
for (j=0, k=0; j < starttaglen && k < PMIX_IOF_BASE_TAGGED_OUT_MAX; j++) {
output->data[k++] = starttag[j];
}
/* cycle through the data looking for <cr>
* and replace those with the tag
*/
for (i=0; i < bo->size && k < PMIX_IOF_BASE_TAGGED_OUT_MAX; i++) {
if (pmix_globals.xml_output) {
if ('&' == bo->bytes[i]) {
if (k+5 >= PMIX_IOF_BASE_TAGGED_OUT_MAX) {
PMIX_ERROR_LOG(PMIX_ERR_OUT_OF_RESOURCE);
goto process;
}
snprintf(qprint, 10, "&amp;");
for (j=0; j < (int)strlen(qprint) && k < PMIX_IOF_BASE_TAGGED_OUT_MAX; j++) {
output->data[k++] = qprint[j];
}
} else if ('<' == bo->bytes[i]) {
if (k+4 >= PMIX_IOF_BASE_TAGGED_OUT_MAX) {
PMIX_ERROR_LOG(PMIX_ERR_OUT_OF_RESOURCE);
goto process;
}
snprintf(qprint, 10, "&lt;");
for (j=0; j < (int)strlen(qprint) && k < PMIX_IOF_BASE_TAGGED_OUT_MAX; j++) {
output->data[k++] = qprint[j];
}
} else if ('>' == bo->bytes[i]) {
if (k+4 >= PMIX_IOF_BASE_TAGGED_OUT_MAX) {
PMIX_ERROR_LOG(PMIX_ERR_OUT_OF_RESOURCE);
goto process;
}
snprintf(qprint, 10, "&gt;");
for (j=0; j < (int)strlen(qprint) && k < PMIX_IOF_BASE_TAGGED_OUT_MAX; j++) {
output->data[k++] = qprint[j];
}
} else if (bo->bytes[i] < 32 || bo->bytes[i] > 127) {
/* this is a non-printable character, so escape it too */
if (k+7 >= PMIX_IOF_BASE_TAGGED_OUT_MAX) {
PMIX_ERROR_LOG(PMIX_ERR_OUT_OF_RESOURCE);
goto process;
}
snprintf(qprint, 10, "&#%03d;", (int)bo->bytes[i]);
for (j=0; j < (int)strlen(qprint) && k < PMIX_IOF_BASE_TAGGED_OUT_MAX; j++) {
output->data[k++] = qprint[j];
}
/* if this was a \n, then we also need to break the line with the end tag */
if ('\n' == bo->bytes[i] && (k+endtaglen+1) < PMIX_IOF_BASE_TAGGED_OUT_MAX) {
/* we need to break the line with the end tag */
for (j=0; j < endtaglen && k < PMIX_IOF_BASE_TAGGED_OUT_MAX-1; j++) {
output->data[k++] = endtag[j];
}
/* move the <cr> over */
output->data[k++] = '\n';
/* if this isn't the end of the data buffer, add a new start tag */
if (i < bo->size-1 && (k+starttaglen) < PMIX_IOF_BASE_TAGGED_OUT_MAX) {
for (j=0; j < starttaglen && k < PMIX_IOF_BASE_TAGGED_OUT_MAX; j++) {
output->data[k++] = starttag[j];
endtagged = false;
}
} else {
endtagged = true;
}
}
} else {
output->data[k++] = bo->bytes[i];
}
} else {
if ('\n' == bo->bytes[i]) {
/* we need to break the line with the end tag */
for (j=0; j < endtaglen && k < PMIX_IOF_BASE_TAGGED_OUT_MAX-1; j++) {
output->data[k++] = endtag[j];
}
/* move the <cr> over */
output->data[k++] = '\n';
/* if this isn't the end of the data buffer, add a new start tag */
if (i < bo->size-1) {
for (j=0; j < starttaglen && k < PMIX_IOF_BASE_TAGGED_OUT_MAX; j++) {
output->data[k++] = starttag[j];
endtagged = false;
}
} else {
endtagged = true;
}
} else {
output->data[k++] = bo->bytes[i];
}
}
}
if (!endtagged && k < PMIX_IOF_BASE_TAGGED_OUT_MAX) {
/* need to add an endtag */
for (j=0; j < endtaglen && k < PMIX_IOF_BASE_TAGGED_OUT_MAX-1; j++) {
output->data[k++] = endtag[j];
}
output->data[k] = '\n';
}
output->numbytes = k;
process:
/* add this data to the write list for this fd */
pmix_list_append(&channel->outputs, &output->super);
/* record how big the buffer is */
num_buffered = pmix_list_get_size(&channel->outputs);
/* is the write event issued? */
if (!channel->pending) {
/* issue it */
PMIX_OUTPUT_VERBOSE((1, pmix_client_globals.iof_output,
"%s write:output adding write event",
PMIX_NAME_PRINT(&pmix_globals.myid)));
PMIX_IOF_SINK_ACTIVATE(channel);
}
return num_buffered;
}
void pmix_iof_static_dump_output(pmix_iof_sink_t *sink)
{
bool dump;
int num_written;
pmix_iof_write_event_t *wev = &sink->wev;
pmix_iof_write_output_t *output;
if (!pmix_list_is_empty(&wev->outputs)) {
dump = false;
/* make one last attempt to write this out */
while (NULL != (output = (pmix_iof_write_output_t*)pmix_list_remove_first(&wev->outputs))) {
if (!dump) {
num_written = write(wev->fd, output->data, output->numbytes);
if (num_written < output->numbytes) {
/* don't retry - just cleanout the list and dump it */
dump = true;
}
}
PMIX_RELEASE(output);
}
}
}
void pmix_iof_write_handler(int _fd, short event, void *cbdata)
{
pmix_iof_sink_t *sink = (pmix_iof_sink_t*)cbdata;
pmix_iof_write_event_t *wev = &sink->wev;
pmix_list_item_t *item;
pmix_iof_write_output_t *output;
int num_written, total_written = 0;
PMIX_ACQUIRE_OBJECT(sink);
PMIX_OUTPUT_VERBOSE((1, pmix_client_globals.iof_output,
"%s write:handler writing data to %d",
PMIX_NAME_PRINT(&pmix_globals.myid),
wev->fd));
while (NULL != (item = pmix_list_remove_first(&wev->outputs))) {
output = (pmix_iof_write_output_t*)item;
if (0 == output->numbytes) {
/* indicates we are to close this stream */
PMIX_RELEASE(sink);
return;
}
num_written = write(wev->fd, output->data, output->numbytes);
if (num_written < 0) {
if (EAGAIN == errno || EINTR == errno) {
/* push this item back on the front of the list */
pmix_list_prepend(&wev->outputs, item);
/* if the list is getting too large, abort */
if (pmix_globals.output_limit < pmix_list_get_size(&wev->outputs)) {
pmix_output(0, "IO Forwarding is running too far behind - something is blocking us from writing");
goto ABORT;
}
/* leave the write event running so it will call us again
* when the fd is ready.
*/
goto NEXT_CALL;
}
/* otherwise, something bad happened so all we can do is abort
* this attempt
*/
PMIX_RELEASE(output);
goto ABORT;
} else if (num_written < output->numbytes) {
/* incomplete write - adjust data to avoid duplicate output */
memmove(output->data, &output->data[num_written], output->numbytes - num_written);
/* adjust the number of bytes remaining to be written */
output->numbytes -= num_written;
/* push this item back on the front of the list */
pmix_list_prepend(&wev->outputs, item);
/* if the list is getting too large, abort */
if (pmix_globals.output_limit < pmix_list_get_size(&wev->outputs)) {
pmix_output(0, "IO Forwarding is running too far behind - something is blocking us from writing");
goto ABORT;
}
/* leave the write event running so it will call us again
* when the fd is ready
*/
goto NEXT_CALL;
}
PMIX_RELEASE(output);
total_written += num_written;
if(wev->always_writable && (PMIX_IOF_SINK_BLOCKSIZE <= total_written)){
/* If this is a regular file it will never tell us it will block
* Write no more than PMIX_IOF_REGULARF_BLOCK at a time allowing
* other fds to progress
*/
goto NEXT_CALL;
}
}
ABORT:
wev->pending = false;
PMIX_POST_OBJECT(wev);
return;
NEXT_CALL:
PMIX_IOF_SINK_ACTIVATE(wev);
}
/* return true if we should read stdin from fd, false otherwise */
bool pmix_iof_stdin_check(int fd)
{
#if defined(HAVE_TCGETPGRP)
if( isatty(fd) && (getpgrp() != tcgetpgrp(fd)) ) {
return false;
}
#endif
return true;
}
void pmix_iof_stdin_cb(int fd, short event, void *cbdata)
{
bool should_process;
pmix_iof_read_event_t *stdinev = (pmix_iof_read_event_t*)cbdata;
PMIX_ACQUIRE_OBJECT(stdinev);
should_process = pmix_iof_stdin_check(0);
if (should_process) {
PMIX_IOF_READ_ACTIVATE(stdinev);
} else {
pmix_event_del(&stdinev->ev);
stdinev->active = false;
PMIX_POST_OBJECT(stdinev);
}
}
static void restart_stdin(int fd, short event, void *cbdata)
{
pmix_iof_read_event_t *tm = (pmix_iof_read_event_t*)cbdata;
PMIX_ACQUIRE_OBJECT(tm);
if (!tm->active) {
PMIX_IOF_READ_ACTIVATE(tm);
}
}
/* this is the read handler for stdin */
void pmix_iof_read_local_handler(int unusedfd, short event, void *cbdata)
{
pmix_iof_read_event_t *rev = (pmix_iof_read_event_t*)cbdata;
unsigned char data[PMIX_IOF_BASE_MSG_MAX];
int32_t numbytes;
int fd;
pmix_status_t rc;
pmix_buffer_t *msg;
pmix_cmd_t cmd = PMIX_IOF_PUSH_CMD;
PMIX_ACQUIRE_OBJECT(rev);
/* As we may use timer events, fd can be bogus (-1)
* use the right one here
*/
fd = fileno(stdin);
/* read up to the fragment size */
memset(data, 0, PMIX_IOF_BASE_MSG_MAX);
numbytes = read(fd, data, sizeof(data));
if (numbytes < 0) {
/* either we have a connection error or it was a non-blocking read */
/* non-blocking, retry */
if (EAGAIN == errno || EINTR == errno) {
PMIX_IOF_READ_ACTIVATE(rev);
return;
}
PMIX_OUTPUT_VERBOSE((1, pmix_client_globals.iof_output,
"%s iof:read handler Error on stdin",
PMIX_NAME_PRINT(&pmix_globals.myid)));
/* Un-recoverable error. Allow the code to flow as usual in order to
* to send the zero bytes message up the stream, and then close the
* file descriptor and delete the event.
*/
numbytes = 0;
}
/* The event has fired, so it's no longer active until we
re-add it */
rev->active = false;
/* pass the data to our PMIx server so it can relay it
* to the host RM for distribution */
msg = PMIX_NEW(pmix_buffer_t);
if (NULL == msg) {
/* don't restart the event - just return */
return;
}
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
msg, &cmd, 1, PMIX_COMMAND);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
goto restart;
}
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
msg, &numbytes, 1, PMIX_INT32);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
goto restart;
}
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
msg, data, numbytes, PMIX_BYTE);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
goto restart;
}
PMIX_PTL_SEND_RECV(rc, pmix_client_globals.myserver,
msg, stdincbfunc, NULL);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
}
restart:
/* if num_bytes was zero, or we read the last piece of the file, then we need to terminate the event */
if (0 == numbytes) {
/* this will also close our stdin file descriptor */
PMIX_RELEASE(rev);
} else {
/* if we are looking at a tty, then we just go ahead and restart the
* read event assuming we are not backgrounded
*/
if (pmix_iof_stdin_check(fd)) {
restart_stdin(fd, 0, rev);
} else {
/* delay for awhile and then restart */
pmix_event_evtimer_set(pmix_globals.evbase,
&rev->ev, restart_stdin, rev);
rev->tv.tv_sec = 0;
rev->tv.tv_usec = 10000;
PMIX_POST_OBJECT(rev);
pmix_event_evtimer_add(&rev->ev, &rev->tv);
}
}
/* nothing more to do */
return;
}
/* class instances */
static void iof_sink_construct(pmix_iof_sink_t* ptr)
{
PMIX_CONSTRUCT(&ptr->wev, pmix_iof_write_event_t);
ptr->xoff = false;
ptr->exclusive = false;
ptr->closed = false;
}
static void iof_sink_destruct(pmix_iof_sink_t* ptr)
{
if (0 <= ptr->wev.fd) {
PMIX_OUTPUT_VERBOSE((20, pmix_client_globals.iof_output,
"%s iof: closing sink for process %s on fd %d",
PMIX_NAME_PRINT(&pmix_globals.myid),
PMIX_NAME_PRINT(&ptr->name), ptr->wev.fd));
PMIX_DESTRUCT(&ptr->wev);
}
}
PMIX_CLASS_INSTANCE(pmix_iof_sink_t,
pmix_list_item_t,
iof_sink_construct,
iof_sink_destruct);
static void iof_read_event_construct(pmix_iof_read_event_t* rev)
{
rev->fd = -1;
rev->active = false;
rev->tv.tv_sec = 0;
rev->tv.tv_usec = 0;
}
static void iof_read_event_destruct(pmix_iof_read_event_t* rev)
{
pmix_event_del(&rev->ev);
if (0 <= rev->fd) {
PMIX_OUTPUT_VERBOSE((20, pmix_client_globals.iof_output,
"%s iof: closing fd %d",
PMIX_NAME_PRINT(&pmix_globals.myid), rev->fd));
close(rev->fd);
rev->fd = -1;
}
}
PMIX_CLASS_INSTANCE(pmix_iof_read_event_t,
pmix_object_t,
iof_read_event_construct,
iof_read_event_destruct);
static void iof_write_event_construct(pmix_iof_write_event_t* wev)
{
wev->pending = false;
wev->always_writable = false;
wev->fd = -1;
PMIX_CONSTRUCT(&wev->outputs, pmix_list_t);
wev->tv.tv_sec = 0;
wev->tv.tv_usec = 0;
}
static void iof_write_event_destruct(pmix_iof_write_event_t* wev)
{
pmix_event_del(&wev->ev);
if (2 < wev->fd) {
PMIX_OUTPUT_VERBOSE((20, pmix_client_globals.iof_output,
"%s iof: closing fd %d for write event",
PMIX_NAME_PRINT(&pmix_globals.myid), wev->fd));
close(wev->fd);
}
PMIX_DESTRUCT(&wev->outputs);
}
PMIX_CLASS_INSTANCE(pmix_iof_write_event_t,
pmix_list_item_t,
iof_write_event_construct,
iof_write_event_destruct);
PMIX_CLASS_INSTANCE(pmix_iof_write_output_t,
pmix_list_item_t,
NULL, NULL);

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

@ -0,0 +1,197 @@
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2011 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 (c) 2008 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2012-2013 Los Alamos National Security, LLC.
* All rights reserved.
* Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
* Copyright (c) 2017 IBM Corporation. All rights reserved.
* Copyright (c) 2017 Mellanox Technologies. All rights reserved.
* Copyright (c) 2018 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
/**
* @file
*
* I/O Forwarding Service
*/
#ifndef PMIX_IOF_H
#define PMIX_IOF_H
#include <src/include/pmix_config.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
#ifdef HAVE_NET_UIO_H
#include <net/uio.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <signal.h>
#include "src/class/pmix_list.h"
#include "src/include/pmix_globals.h"
#include "src/util/fd.h"
#include "src/common/pmix_iof.h"
BEGIN_C_DECLS
/*
* Maximum size of single msg
*/
#define PMIX_IOF_BASE_MSG_MAX 4096
#define PMIX_IOF_BASE_TAG_MAX 50
#define PMIX_IOF_BASE_TAGGED_OUT_MAX 8192
#define PMIX_IOF_MAX_INPUT_BUFFERS 50
typedef struct {
pmix_list_item_t super;
bool pending;
bool always_writable;
pmix_event_t ev;
struct timeval tv;
int fd;
pmix_list_t outputs;
} pmix_iof_write_event_t;
PMIX_EXPORT PMIX_CLASS_DECLARATION(pmix_iof_write_event_t);
typedef struct {
pmix_list_item_t super;
pmix_proc_t name;
pmix_iof_channel_t tag;
pmix_iof_write_event_t wev;
bool xoff;
bool exclusive;
bool closed;
} pmix_iof_sink_t;
PMIX_EXPORT PMIX_CLASS_DECLARATION(pmix_iof_sink_t);
typedef struct {
pmix_list_item_t super;
char data[PMIX_IOF_BASE_TAGGED_OUT_MAX];
int numbytes;
} pmix_iof_write_output_t;
PMIX_EXPORT PMIX_CLASS_DECLARATION(pmix_iof_write_output_t);
typedef struct {
pmix_object_t super;
pmix_event_t ev;
struct timeval tv;
int fd;
bool active;
bool always_readable;
} pmix_iof_read_event_t;
PMIX_EXPORT PMIX_CLASS_DECLARATION(pmix_iof_read_event_t);
/* Write event macro's */
static inline bool
pmix_iof_fd_always_ready(int fd)
{
return pmix_fd_is_regular(fd) ||
(pmix_fd_is_chardev(fd) && !isatty(fd)) ||
pmix_fd_is_blkdev(fd);
}
#define PMIX_IOF_SINK_BLOCKSIZE (1024)
#define PMIX_IOF_SINK_ACTIVATE(wev) \
do { \
struct timeval *tv = NULL; \
wev->pending = true; \
PMIX_POST_OBJECT(wev); \
if (wev->always_writable) { \
/* Regular is always write ready. Use timer to activate */ \
tv = &wev->tv; \
} \
if (pmix_event_add(&wev->ev, tv)) { \
PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM); \
} \
} while(0);
/* define an output "sink", adding it to the provided
* endpoint list for this proc */
#define PMIX_IOF_SINK_DEFINE(snk, nm, fid, tg, wrthndlr) \
do { \
PMIX_OUTPUT_VERBOSE((1, pmix_client_globals.iof_output, \
"defining endpt: file %s line %d fd %d", \
__FILE__, __LINE__, (fid))); \
PMIX_CONSTRUCT((snk), pmix_iof_sink_t); \
(void)strncpy((snk)->name.nspace, (nm)->nspace, PMIX_MAX_NSLEN); \
(snk)->name.rank = (nm)->rank; \
(snk)->tag = (tg); \
if (0 <= (fid)) { \
(snk)->wev.fd = (fid); \
(snk)->wev.always_writable = \
pmix_iof_fd_always_ready(fid); \
if ((snk)->wev.always_writable) { \
pmix_event_evtimer_set(pmix_globals.evbase, \
&(snk)->wev.ev, wrthndlr, (snk)); \
} else { \
pmix_event_set(pmix_globals.evbase, \
&(snk)->wev.ev, (snk)->wev.fd, \
PMIX_EV_WRITE, \
wrthndlr, (snk)); \
} \
} \
PMIX_POST_OBJECT(snk); \
} while(0);
/* Read event macro's */
#define PMIX_IOF_READ_ADDEV(rev) \
do { \
struct timeval *tv = NULL; \
if ((rev)->always_readable) { \
tv = &(rev)->tv; \
} \
if (pmix_event_add(&(rev)->ev, tv)) { \
PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM); \
} \
} while(0);
#define PMIX_IOF_READ_ACTIVATE(rev) \
do { \
(rev)->active = true; \
PMIX_POST_OBJECT(rev); \
PMIX_IOF_READ_ADDEV(rev); \
} while(0);
PMIX_EXPORT pmix_status_t pmix_iof_flush(void);
PMIX_EXPORT pmix_status_t pmix_iof_write_output(const pmix_proc_t *name,
pmix_iof_channel_t stream,
const pmix_byte_object_t *bo,
pmix_iof_write_event_t *channel);
PMIX_EXPORT void pmix_iof_static_dump_output(pmix_iof_sink_t *sink);
PMIX_EXPORT void pmix_iof_write_handler(int fd, short event, void *cbdata);
PMIX_EXPORT void pmix_iof_stdin_write_handler(int fd, short event, void *cbdata);
PMIX_EXPORT bool pmix_iof_stdin_check(int fd);
PMIX_EXPORT void pmix_iof_stdin_cb(int fd, short event, void *cbdata);
PMIX_EXPORT void pmix_iof_read_local_handler(int fd, short event, void *cbdata);
END_C_DECLS
#endif /* PMIX_IOF_H */

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

@ -63,6 +63,7 @@ static void query_cbfunc(struct pmix_peer_t *peer,
PMIX_BFROPS_UNPACK(rc, peer, buf, &results->status, &cnt, PMIX_STATUS);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
results->status = rc;
goto complete;
}
if (PMIX_SUCCESS != results->status) {
@ -74,6 +75,7 @@ static void query_cbfunc(struct pmix_peer_t *peer,
PMIX_BFROPS_UNPACK(rc, peer, buf, &results->ninfo, &cnt, PMIX_SIZE);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
results->status = rc;
goto complete;
}
if (0 < results->ninfo) {
@ -82,6 +84,7 @@ static void query_cbfunc(struct pmix_peer_t *peer,
PMIX_BFROPS_UNPACK(rc, peer, buf, results->info, &cnt, PMIX_INFO);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
results->status = rc;
goto complete;
}
}

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

@ -71,8 +71,12 @@ PMIX_EXPORT const char* PMIx_Proc_state_string(pmix_proc_state_t state)
return "PROC TERMINATED WITHOUT CALLING PMIx_Finalize";
case PMIX_PROC_STATE_COMM_FAILED:
return "PROC LOST COMMUNICATION";
case PMIX_PROC_STATE_SENSOR_BOUND_EXCEEDED:
return "PROC SENSOR BOUND EXCEEDED";
case PMIX_PROC_STATE_CALLED_ABORT:
return "PROC CALLED PMIx_Abort";
case PMIX_PROC_STATE_HEARTBEAT_FAILED:
return "PROC FAILED TO REPORT HEARTBEAT";
case PMIX_PROC_STATE_MIGRATING:
return "PROC WAITING TO MIGRATE";
case PMIX_PROC_STATE_CANNOT_RESTART:
@ -216,7 +220,42 @@ PMIX_EXPORT const char* pmix_command_string(pmix_cmd_t cmd)
return "JOB CONTROL";
case PMIX_MONITOR_CMD:
return "MONITOR";
case PMIX_IOF_PUSH_CMD:
return "IOF PUSH";
case PMIX_IOF_PULL_CMD:
return "IOF PULL";
default:
return "UNKNOWN";
}
}
/* this is not a thread-safe implementation. To correctly implement this,
* we need to port the thread-safe data code from OPAL and use it here */
static char answer[300];
PMIX_EXPORT const char* PMIx_IOF_channel_string(pmix_iof_channel_t channel)
{
size_t cnt=0;
memset(answer, 0, sizeof(answer));
if (PMIX_FWD_STDIN_CHANNEL & channel) {
strncpy(&answer[cnt], "STDIN ", strlen("STDIN "));
cnt += strlen("STDIN ");
}
if (PMIX_FWD_STDOUT_CHANNEL & channel) {
strncpy(&answer[cnt], "STDOUT ", strlen("STDOUT "));
cnt += strlen("STDOUT ");
}
if (PMIX_FWD_STDERR_CHANNEL & channel) {
strncpy(&answer[cnt], "STDERR ", strlen("STDERR "));
cnt += strlen("STDERR ");
}
if (PMIX_FWD_STDDIAG_CHANNEL & channel) {
strncpy(&answer[cnt], "STDDIAG ", strlen("STDDIAG "));
cnt += strlen("STDDIAG ");
}
if (0 == cnt) {
strncpy(&answer[cnt], "NONE", strlen("NONE"));
}
return answer;
}

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

@ -41,7 +41,7 @@
pmix_info_t *info;
size_t ninfo;
pmix_notification_fn_t evhdlr;
pmix_evhdlr_reg_cbfunc_t evregcbfn;
pmix_hdlr_reg_cbfunc_t evregcbfn;
void *cbdata;
} pmix_rshift_caddy_t;
static void rscon(pmix_rshift_caddy_t *p)
@ -766,7 +766,7 @@ static void reg_event_hdlr(int sd, short args, void *cbdata)
PMIX_EXPORT void PMIx_Register_event_handler(pmix_status_t codes[], size_t ncodes,
pmix_info_t info[], size_t ninfo,
pmix_notification_fn_t event_hdlr,
pmix_evhdlr_reg_cbfunc_t cbfunc,
pmix_hdlr_reg_cbfunc_t cbfunc,
void *cbdata)
{
pmix_rshift_caddy_t *cd;

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

@ -109,6 +109,7 @@ static void nscon(pmix_nspace_t *p)
PMIX_CONSTRUCT(&p->epilog.cleanup_dirs, pmix_list_t);
PMIX_CONSTRUCT(&p->epilog.cleanup_files, pmix_list_t);
PMIX_CONSTRUCT(&p->epilog.ignores, pmix_list_t);
PMIX_CONSTRUCT(&p->setup_data, pmix_list_t);
}
static void nsdes(pmix_nspace_t *p)
{
@ -125,6 +126,7 @@ static void nsdes(pmix_nspace_t *p)
PMIX_LIST_DESTRUCT(&p->epilog.cleanup_dirs);
PMIX_LIST_DESTRUCT(&p->epilog.cleanup_files);
PMIX_LIST_DESTRUCT(&p->epilog.ignores);
PMIX_LIST_DESTRUCT(&p->setup_data);
}
PMIX_EXPORT PMIX_CLASS_INSTANCE(pmix_nspace_t,
pmix_list_item_t,
@ -219,6 +221,24 @@ PMIX_EXPORT PMIX_CLASS_INSTANCE(pmix_peer_t,
pmix_object_t,
pcon, pdes);
static void iofreqcon(pmix_iof_req_t *p)
{
p->peer = NULL;
memset(&p->pname, 0, sizeof(pmix_name_t));
p->channels = PMIX_FWD_NO_CHANNELS;
p->cbfunc = NULL;
}
static void iofreqdes(pmix_iof_req_t *p)
{
if (NULL != p->peer) {
PMIX_RELEASE(p->peer);
}
}
PMIX_EXPORT PMIX_CLASS_INSTANCE(pmix_iof_req_t,
pmix_list_item_t,
iofreqcon, iofreqdes);
static void scon(pmix_shift_caddy_t *p)
{
PMIX_CONSTRUCT_LOCK(&p->lock);
@ -234,6 +254,7 @@ static void scon(pmix_shift_caddy_t *p)
p->directives = NULL;
p->ndirs = 0;
p->evhdlr = NULL;
p->iofreq = NULL;
p->kv = NULL;
p->vptr = NULL;
p->cd = NULL;

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

@ -31,6 +31,7 @@
#endif
#include PMIX_EVENT_HEADER
#include <pmix.h>
#include <pmix_common.h>
#include "src/class/pmix_hash_table.h"
@ -97,6 +98,8 @@ typedef uint8_t pmix_cmd_t;
#define PMIX_MONITOR_CMD 19
#define PMIX_GET_CREDENTIAL_CMD 20
#define PMIX_VALIDATE_CRED_CMD 21
#define PMIX_IOF_PULL_CMD 22
#define PMIX_IOF_PUSH_CMD 23
/* provide a "pretty-print" function for cmds */
const char* pmix_command_string(pmix_cmd_t cmd);
@ -165,6 +168,8 @@ typedef struct {
pmix_personality_t compat;
pmix_epilog_t epilog; // things to do upon termination of all local clients
// from this nspace
pmix_list_t setup_data; // list of pmix_kval_t containing info structs having blobs
// for setting up the local node for this nspace/application
} pmix_nspace_t;
PMIX_CLASS_DECLARATION(pmix_nspace_t);
@ -228,6 +233,17 @@ typedef struct pmix_peer_t {
PMIX_CLASS_DECLARATION(pmix_peer_t);
/* tracker for IOF requests */
typedef struct {
pmix_list_item_t super;
pmix_peer_t *peer;
pmix_name_t pname;
pmix_iof_channel_t channels;
pmix_iof_cbfunc_t cbfunc;
} pmix_iof_req_t;
PMIX_CLASS_DECLARATION(pmix_iof_req_t);
/* caddy for query requests */
typedef struct {
pmix_object_t super;
@ -307,6 +323,7 @@ PMIX_CLASS_DECLARATION(pmix_server_caddy_t);
pmix_info_t *directives;
size_t ndirs;
pmix_notification_fn_t evhdlr;
pmix_iof_req_t *iofreq;
pmix_kval_t *kv;
pmix_value_t *vptr;
pmix_server_caddy_t *cd;
@ -314,9 +331,8 @@ PMIX_CLASS_DECLARATION(pmix_server_caddy_t);
bool enviro;
union {
pmix_release_cbfunc_t relfn;
pmix_evhdlr_reg_cbfunc_t evregcbfn;
pmix_hdlr_reg_cbfunc_t hdlrregcbfn;
pmix_op_cbfunc_t opcbfn;
pmix_evhdlr_reg_cbfunc_t errregcbfn;
} cbfunc;
void *cbdata;
size_t ref;
@ -340,7 +356,7 @@ typedef struct {
pmix_lookup_cbfunc_t lookupfn;
pmix_spawn_cbfunc_t spawnfn;
pmix_connect_cbfunc_t cnctfn;
pmix_evhdlr_reg_cbfunc_t errregfn;
pmix_hdlr_reg_cbfunc_t hdlrregfn;
} cbfunc;
size_t errhandler_ref;
void *cbdata;
@ -414,6 +430,7 @@ typedef struct {
bool commits_pending;
struct timeval event_window;
pmix_list_t cached_events; // events waiting in the window prior to processing
pmix_list_t iof_requests; // list of pmix_iof_req_t IOF requests
pmix_ring_buffer_t notifications; // ring buffer of pending notifications
/* processes also need a place where they can store
* their own internal data - e.g., data provided by
@ -422,6 +439,11 @@ typedef struct {
* interface so that other parts of the process can
* look them up */
pmix_gds_base_module_t *mygds;
/* IOF controls */
bool tag_output;
bool xml_output;
bool timestamp_output;
size_t output_limit;
} pmix_globals_t;
/* provide access to a function to cleanup epilogs */

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

@ -244,6 +244,8 @@ typedef struct event pmix_event_t;
#define pmix_event_assign(x, b, fd, fg, cb, arg) event_assign((x), (b), (fd), (fg), (event_callback_fn) (cb), (arg))
#define pmix_event_set(b, x, fd, fg, cb, arg) event_assign((x), (b), (fd), (fg), (event_callback_fn) (cb), (arg))
#define pmix_event_add(ev, tv) event_add((ev), (tv))
#define pmix_event_del(ev) event_del((ev))
@ -264,5 +266,6 @@ typedef struct event pmix_event_t;
#define pmix_event_evtimer_del(x) pmix_event_del((x))
#define pmix_event_signal_set(b, x, fd, cb, arg) event_assign((x), (b), (fd), EV_SIGNAL|EV_PERSIST, (event_callback_fn) (cb), (arg))
#endif /* PMIX_TYPES_H */

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

@ -379,6 +379,10 @@ PMIX_EXPORT pmix_status_t pmix_bfrops_base_pack_val(pmix_buffer_t *buffer,
pmix_value_t *p);
PMIX_EXPORT pmix_status_t pmix_bfrops_base_pack_alloc_directive(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_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
@ -466,6 +470,10 @@ PMIX_EXPORT pmix_status_t pmix_bfrops_base_unpack_query(pmix_buffer_t *buffer, v
int32_t *num_vals, pmix_data_type_t type);
PMIX_EXPORT pmix_status_t pmix_bfrops_base_unpack_alloc_directive(pmix_buffer_t *buffer, void *dest,
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);
@ -527,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,
@ -637,6 +648,12 @@ PMIX_EXPORT pmix_status_t pmix_bfrops_base_print_rank(char **output, char *prefi
PMIX_EXPORT pmix_status_t pmix_bfrops_base_print_alloc_directive(char **output, char *prefix,
pmix_alloc_directive_t *src,
pmix_data_type_t type);
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

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

@ -113,6 +113,7 @@ pmix_status_t pmix_bfrops_base_std_copy(void **dest, void *src,
case PMIX_INT16:
case PMIX_UINT16:
case PMIX_IOF_CHANNEL:
datasize = 2;
break;
@ -366,18 +367,23 @@ pmix_status_t pmix_bfrops_base_copy_pinfo(pmix_proc_info_t **dest,
pmix_proc_info_t *src,
pmix_data_type_t type)
{
*dest = (pmix_proc_info_t*)malloc(sizeof(pmix_proc_info_t));
(void)strncpy((*dest)->proc.nspace, src->proc.nspace, PMIX_MAX_NSLEN);
(*dest)->proc.rank = src->proc.rank;
pmix_proc_info_t *p;
PMIX_PROC_INFO_CREATE(p, 1);
if (NULL == p) {
return PMIX_ERR_NOMEM;
}
memcpy(&p->proc, &src->proc, sizeof(pmix_proc_t));
if (NULL != src->hostname) {
(*dest)->hostname = strdup(src->hostname);
p->hostname = strdup(src->hostname);
}
if (NULL != src->executable_name) {
(*dest)->executable_name = strdup(src->executable_name);
p->executable_name = strdup(src->executable_name);
}
(*dest)->pid = src->pid;
(*dest)->exit_code = src->exit_code;
(*dest)->state = src->state;
memcpy(&p->pid, &src->pid, sizeof(pid_t));
memcpy(&p->exit_code, &src->exit_code, sizeof(int));
memcpy(&p->state, &src->state, sizeof(pmix_proc_state_t));
*dest = p;
return PMIX_SUCCESS;
}
@ -402,6 +408,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) {
@ -617,7 +624,7 @@ pmix_status_t pmix_bfrops_base_copy_darray(pmix_data_array_t **dest,
p1 = (pmix_info_t*)p->array;
s1 = (pmix_info_t*)src->array;
for (n=0; n < src->size; n++) {
PMIX_INFO_LOAD(&p1[n], s1[n].key, &s1[n].value.data.flag, s1[n].value.type);
PMIX_INFO_XFER(&p1[n], &s1[n]);
}
break;
case PMIX_PDATA:
@ -629,7 +636,7 @@ pmix_status_t pmix_bfrops_base_copy_darray(pmix_data_array_t **dest,
pd = (pmix_pdata_t*)p->array;
sd = (pmix_pdata_t*)src->array;
for (n=0; n < src->size; n++) {
PMIX_PDATA_LOAD(&pd[n], &sd[n].proc, sd[n].key, &sd[n].value.data.flag, sd[n].value.type);
PMIX_PDATA_XFER(&pd[n], &sd[n]);
}
break;
case PMIX_BUFFER:
@ -822,6 +829,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;
@ -876,3 +901,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)
{
PMIX_ENVAR_CREATE(*dest, 1);
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;
}

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

@ -49,6 +49,9 @@ 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;
pmix_data_array_t *darray;
pmix_status_t rc;
v->type = type;
if (NULL == data) {
@ -174,6 +177,24 @@ 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;
case PMIX_DATA_ARRAY:
darray = (pmix_data_array_t*)data;
rc = pmix_bfrops_base_copy_darray(&v->data.darray, darray, PMIX_DATA_ARRAY);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
}
break;
default:
/* silence warnings */
break;
@ -187,6 +208,8 @@ pmix_status_t pmix_bfrops_base_value_unload(pmix_value_t *kv,
size_t *sz)
{
pmix_status_t rc;
pmix_envar_t *envar;
pmix_data_array_t **darray;
rc = PMIX_SUCCESS;
if (NULL == data ||
@ -304,6 +327,26 @@ 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_DATA_ARRAY:
darray = (pmix_data_array_t**)data;
rc = pmix_bfrops_base_copy_darray(darray, kv->data.darray, PMIX_DATA_ARRAY);
*sz = sizeof(pmix_data_array_t);
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 +441,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 +516,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;
@ -544,395 +630,23 @@ pmix_status_t pmix_bfrops_base_value_xfer(pmix_value_t *p,
memcpy(&p->data.state, &src->data.state, sizeof(pmix_proc_state_t));
break;
case PMIX_PROC_INFO:
PMIX_PROC_INFO_CREATE(p->data.pinfo, 1);
if (NULL != src->data.pinfo->hostname) {
p->data.pinfo->hostname = strdup(src->data.pinfo->hostname);
}
if (NULL != src->data.pinfo->executable_name) {
p->data.pinfo->executable_name = strdup(src->data.pinfo->executable_name);
}
memcpy(&p->data.pinfo->pid, &src->data.pinfo->pid, sizeof(pid_t));
memcpy(&p->data.pinfo->exit_code, &src->data.pinfo->exit_code, sizeof(int));
memcpy(&p->data.pinfo->state, &src->data.pinfo->state, sizeof(pmix_proc_state_t));
break;
return pmix_bfrops_base_copy_pinfo(&p->data.pinfo, src->data.pinfo, PMIX_PROC_INFO);
case PMIX_DATA_ARRAY:
p->data.darray = (pmix_data_array_t*)calloc(1, sizeof(pmix_data_array_t));
p->data.darray->type = src->data.darray->type;
p->data.darray->size = src->data.darray->size;
if (0 == p->data.darray->size || NULL == src->data.darray->array) {
p->data.darray->array = NULL;
p->data.darray->size = 0;
break;
}
/* allocate space and do the copy */
switch (src->data.darray->type) {
case PMIX_UINT8:
case PMIX_INT8:
case PMIX_BYTE:
p->data.darray->array = (char*)malloc(src->data.darray->size);
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size);
break;
case PMIX_UINT16:
case PMIX_INT16:
p->data.darray->array = (char*)malloc(src->data.darray->size * sizeof(uint16_t));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(uint16_t));
break;
case PMIX_UINT32:
case PMIX_INT32:
p->data.darray->array = (char*)malloc(src->data.darray->size * sizeof(uint32_t));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(uint32_t));
break;
case PMIX_UINT64:
case PMIX_INT64:
p->data.darray->array = (char*)malloc(src->data.darray->size * sizeof(uint64_t));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(uint64_t));
break;
case PMIX_BOOL:
p->data.darray->array = (char*)malloc(src->data.darray->size * sizeof(bool));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(bool));
break;
case PMIX_SIZE:
p->data.darray->array = (char*)malloc(src->data.darray->size * sizeof(size_t));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(size_t));
break;
case PMIX_PID:
p->data.darray->array = (char*)malloc(src->data.darray->size * sizeof(pid_t));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(pid_t));
break;
case PMIX_STRING:
p->data.darray->array = (char**)malloc(src->data.darray->size * sizeof(char*));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
prarray = (char**)p->data.darray->array;
strarray = (char**)src->data.darray->array;
for (n=0; n < src->data.darray->size; n++) {
if (NULL != strarray[n]) {
prarray[n] = strdup(strarray[n]);
}
}
break;
case PMIX_INT:
case PMIX_UINT:
p->data.darray->array = (char*)malloc(src->data.darray->size * sizeof(int));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(int));
break;
case PMIX_FLOAT:
p->data.darray->array = (char*)malloc(src->data.darray->size * sizeof(float));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(float));
break;
case PMIX_DOUBLE:
p->data.darray->array = (char*)malloc(src->data.darray->size * sizeof(double));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(double));
break;
case PMIX_TIMEVAL:
p->data.darray->array = (struct timeval*)malloc(src->data.darray->size * sizeof(struct timeval));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(struct timeval));
break;
case PMIX_TIME:
p->data.darray->array = (time_t*)malloc(src->data.darray->size * sizeof(time_t));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(time_t));
break;
case PMIX_STATUS:
p->data.darray->array = (pmix_status_t*)malloc(src->data.darray->size * sizeof(pmix_status_t));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(pmix_status_t));
break;
case PMIX_VALUE:
PMIX_VALUE_CREATE(p->data.darray->array, src->data.darray->size);
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
pv = (pmix_value_t*)p->data.darray->array;
sv = (pmix_value_t*)src->data.darray->array;
for (n=0; n < src->data.darray->size; n++) {
if (PMIX_SUCCESS != (rc = pmix_value_xfer(&pv[n], &sv[n]))) {
PMIX_VALUE_FREE(pv, src->data.darray->size);
return rc;
}
}
break;
case PMIX_PROC:
PMIX_PROC_CREATE(p->data.darray->array, src->data.darray->size);
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(pmix_proc_t));
break;
case PMIX_APP:
PMIX_APP_CREATE(p->data.darray->array, src->data.darray->size);
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
pa = (pmix_app_t*)p->data.darray->array;
sa = (pmix_app_t*)src->data.darray->array;
for (n=0; n < src->data.darray->size; n++) {
if (NULL != sa[n].cmd) {
pa[n].cmd = strdup(sa[n].cmd);
}
if (NULL != sa[n].argv) {
pa[n].argv = pmix_argv_copy(sa[n].argv);
}
if (NULL != sa[n].env) {
pa[n].env = pmix_argv_copy(sa[n].env);
}
if (NULL != sa[n].cwd) {
pa[n].cwd = strdup(sa[n].cwd);
}
pa[n].maxprocs = sa[n].maxprocs;
if (0 < sa[n].ninfo && NULL != sa[n].info) {
PMIX_INFO_CREATE(pa[n].info, sa[n].ninfo);
if (NULL == pa[n].info) {
PMIX_APP_FREE(pa, src->data.darray->size);
return PMIX_ERR_NOMEM;
}
pa[n].ninfo = sa[n].ninfo;
for (m=0; m < pa[n].ninfo; m++) {
PMIX_INFO_XFER(&pa[n].info[m], &sa[n].info[m]);
}
}
}
break;
case PMIX_INFO:
PMIX_INFO_CREATE(p->data.darray->array, src->data.darray->size);
p1 = (pmix_info_t*)p->data.darray->array;
s1 = (pmix_info_t*)src->data.darray->array;
for (n=0; n < src->data.darray->size; n++) {
PMIX_INFO_XFER(&p1[n], &s1[n]);
}
break;
case PMIX_PDATA:
PMIX_PDATA_CREATE(p->data.darray->array, src->data.darray->size);
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
pd = (pmix_pdata_t*)p->data.darray->array;
sd = (pmix_pdata_t*)src->data.darray->array;
for (n=0; n < src->data.darray->size; n++) {
PMIX_PDATA_XFER(&pd[n], &sd[n]);
}
break;
case PMIX_BUFFER:
p->data.darray->array = (pmix_buffer_t*)malloc(src->data.darray->size * sizeof(pmix_buffer_t));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
pb = (pmix_buffer_t*)p->data.darray->array;
sb = (pmix_buffer_t*)src->data.darray->array;
for (n=0; n < src->data.darray->size; n++) {
PMIX_CONSTRUCT(&pb[n], pmix_buffer_t);
pmix_bfrops_base_copy_payload(&pb[n], &sb[n]);
}
break;
case PMIX_BYTE_OBJECT:
case PMIX_COMPRESSED_STRING:
p->data.darray->array = (pmix_byte_object_t*)malloc(src->data.darray->size * sizeof(pmix_byte_object_t));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
pbo = (pmix_byte_object_t*)p->data.darray->array;
sbo = (pmix_byte_object_t*)src->data.darray->array;
for (n=0; n < src->data.darray->size; n++) {
if (NULL != sbo[n].bytes && 0 < sbo[n].size) {
pbo[n].size = sbo[n].size;
pbo[n].bytes = (char*)malloc(pbo[n].size);
memcpy(pbo[n].bytes, sbo[n].bytes, pbo[n].size);
} else {
pbo[n].bytes = NULL;
pbo[n].size = 0;
}
}
break;
case PMIX_KVAL:
p->data.darray->array = (pmix_kval_t*)calloc(src->data.darray->size , sizeof(pmix_kval_t));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
pk = (pmix_kval_t*)p->data.darray->array;
sk = (pmix_kval_t*)src->data.darray->array;
for (n=0; n < src->data.darray->size; n++) {
if (NULL != sk[n].key) {
pk[n].key = strdup(sk[n].key);
}
if (NULL != sk[n].value) {
PMIX_VALUE_CREATE(pk[n].value, 1);
if (NULL == pk[n].value) {
free(p->data.darray->array);
return PMIX_ERR_NOMEM;
}
if (PMIX_SUCCESS != (rc = pmix_value_xfer(pk[n].value, sk[n].value))) {
return rc;
}
}
}
break;
case PMIX_MODEX:
PMIX_MODEX_CREATE(p->data.darray->array, src->data.darray->size);
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
pm = (pmix_modex_data_t*)p->data.darray->array;
sm = (pmix_modex_data_t*)src->data.darray->array;
for (n=0; n < src->data.darray->size; n++) {
memcpy(&pm[n], &sm[n], sizeof(pmix_modex_data_t));
if (NULL != sm[n].blob && 0 < sm[n].size) {
pm[n].blob = (uint8_t*)malloc(sm[n].size);
if (NULL == pm[n].blob) {
return PMIX_ERR_NOMEM;
}
memcpy(pm[n].blob, sm[n].blob, sm[n].size);
pm[n].size = sm[n].size;
} else {
pm[n].blob = NULL;
pm[n].size = 0;
}
}
break;
case PMIX_PERSIST:
p->data.darray->array = (pmix_persistence_t*)malloc(src->data.darray->size * sizeof(pmix_persistence_t));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(pmix_persistence_t));
break;
case PMIX_POINTER:
p->data.darray->array = (char**)malloc(src->data.darray->size * sizeof(char*));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
prarray = (char**)p->data.darray->array;
strarray = (char**)src->data.darray->array;
for (n=0; n < src->data.darray->size; n++) {
prarray[n] = strarray[n];
}
break;
case PMIX_SCOPE:
p->data.darray->array = (pmix_scope_t*)malloc(src->data.darray->size * sizeof(pmix_scope_t));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(pmix_scope_t));
break;
case PMIX_DATA_RANGE:
p->data.darray->array = (pmix_data_range_t*)malloc(src->data.darray->size * sizeof(pmix_data_range_t));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(pmix_data_range_t));
break;
case PMIX_COMMAND:
p->data.darray->array = (pmix_cmd_t*)malloc(src->data.darray->size * sizeof(pmix_cmd_t));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(pmix_cmd_t));
break;
case PMIX_INFO_DIRECTIVES:
p->data.darray->array = (pmix_info_directives_t*)malloc(src->data.darray->size * sizeof(pmix_info_directives_t));
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(pmix_info_directives_t));
break;
case PMIX_PROC_INFO:
PMIX_PROC_INFO_CREATE(p->data.darray->array, src->data.darray->size);
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
pi = (pmix_proc_info_t*)p->data.darray->array;
si = (pmix_proc_info_t*)src->data.darray->array;
for (n=0; n < src->data.darray->size; n++) {
memcpy(&pi[n].proc, &si[n].proc, sizeof(pmix_proc_t));
if (NULL != si[n].hostname) {
pi[n].hostname = strdup(si[n].hostname);
} else {
pi[n].hostname = NULL;
}
if (NULL != si[n].executable_name) {
pi[n].executable_name = strdup(si[n].executable_name);
} else {
pi[n].executable_name = NULL;
}
pi[n].pid = si[n].pid;
pi[n].exit_code = si[n].exit_code;
pi[n].state = si[n].state;
}
break;
case PMIX_DATA_ARRAY:
PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
return PMIX_ERR_NOT_SUPPORTED; // don't support iterative arrays
case PMIX_QUERY:
PMIX_QUERY_CREATE(p->data.darray->array, src->data.darray->size);
if (NULL == p->data.darray->array) {
return PMIX_ERR_NOMEM;
}
pq = (pmix_query_t*)p->data.darray->array;
sq = (pmix_query_t*)src->data.darray->array;
for (n=0; n < src->data.darray->size; n++) {
if (NULL != sq[n].keys) {
pq[n].keys = pmix_argv_copy(sq[n].keys);
}
if (NULL != sq[n].qualifiers && 0 < sq[n].nqual) {
PMIX_INFO_CREATE(pq[n].qualifiers, sq[n].nqual);
if (NULL == pq[n].qualifiers) {
PMIX_QUERY_FREE(pq, src->data.darray->size);
return PMIX_ERR_NOMEM;
}
for (m=0; m < sq[n].nqual; m++) {
PMIX_INFO_XFER(&pq[n].qualifiers[m], &sq[n].qualifiers[m]);
}
pq[n].nqual = sq[n].nqual;
} else {
pq[n].qualifiers = NULL;
pq[n].nqual = 0;
}
}
break;
default:
return PMIX_ERR_UNKNOWN_DATA_TYPE;
}
break;
return pmix_bfrops_base_copy_darray(&p->data.darray, src->data.darray, PMIX_DATA_ARRAY);
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;

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

@ -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) 2015-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -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))) {
@ -1270,3 +1282,33 @@ pmix_status_t pmix_bfrops_base_pack_array(pmix_buffer_t *buffer, const void *src
return PMIX_SUCCESS;
}
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_SUCCESS;
}

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

@ -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",
@ -1636,6 +1643,66 @@ pmix_status_t pmix_bfrops_base_print_alloc_directive(char **output, char *prefix
}
}
pmix_status_t pmix_bfrops_base_print_iof_channel(char **output, char *prefix,
pmix_iof_channel_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_IOF_CHANNEL\tValue: %s",
prefx, PMIx_IOF_channel_string(*src));
if (prefx != prefix) {
free(prefx);
}
if (0 > ret) {
return PMIX_ERR_OUT_OF_RESOURCE;
} else {
return PMIX_SUCCESS;
}
}
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,

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

@ -111,6 +111,7 @@ pmix_status_t pmix_bfrops_base_unpack(pmix_pointer_array_t *regtypes,
}
if (PMIX_INT32 != local_type) { /* if the length wasn't first, then error */
*num_vals = 0;
PMIX_ERROR_LOG(PMIX_ERR_UNPACK_FAILURE);
return PMIX_ERR_UNPACK_FAILURE;
}
}
@ -753,8 +754,13 @@ pmix_status_t pmix_bfrops_base_unpack_val(pmix_buffer_t *buffer,
return ret;
}
break;
case PMIX_QUERY:
if (PMIX_SUCCESS != (ret = pmix_bfrops_base_unpack_query(buffer, val->data.darray, &m, PMIX_QUERY))) {
case PMIX_ALLOC_DIRECTIVE:
if (PMIX_SUCCESS != (ret = pmix_bfrops_base_unpack_alloc_directive(buffer, &val->data.adir, &m, PMIX_ALLOC_DIRECTIVE))) {
return ret;
}
break;
case PMIX_ENVAR:
if (PMIX_SUCCESS != (ret = pmix_bfrops_base_unpack_envar(buffer, &val->data.envar, &m, PMIX_ENVAR))) {
return ret;
}
break;
@ -1524,6 +1530,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));
@ -1603,6 +1618,45 @@ pmix_status_t pmix_bfrops_base_unpack_alloc_directive(pmix_buffer_t *buffer, voi
return pmix_bfrops_base_unpack_byte(buffer, dest, num_vals, PMIX_UINT8);
}
pmix_status_t pmix_bfrops_base_unpack_iof_channel(pmix_buffer_t *buffer, void *dest,
int32_t *num_vals, pmix_data_type_t type)
{
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,

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

@ -333,7 +333,8 @@ static pmix_status_t store_map(pmix_hash_table_t *ht,
}
/* store the comma-delimited list of nodes hosting
* procs in this nspace */
* procs in this nspace in case someone using PMIx v2
* requests it */
kp2 = PMIX_NEW(pmix_kval_t);
kp2->key = strdup(PMIX_NODE_LIST);
kp2->value = (pmix_value_t*)malloc(sizeof(pmix_value_t));
@ -397,6 +398,19 @@ pmix_status_t hash_cache_job_info(struct pmix_nspace_t *ns,
ht = &trk->internal;
for (n=0; n < ninfo; n++) {
if (0 == strcmp(info[n].key, PMIX_NODE_MAP)) {
/* store the node map itself since that is
* what v3 uses */
kp2 = PMIX_NEW(pmix_kval_t);
kp2->key = strdup(PMIX_NODE_MAP);
kp2->value = (pmix_value_t*)malloc(sizeof(pmix_value_t));
kp2->value->type = PMIX_STRING;
kp2->value->data.string = strdup(info[n].value.data.string);
if (PMIX_SUCCESS != (rc = pmix_hash_store(ht, PMIX_RANK_WILDCARD, kp2))) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(kp2);
return rc;
}
/* parse the regex to get the argv array of node names */
if (PMIX_SUCCESS != (rc = pmix_preg.parse_nodes(info[n].value.data.string, &nodes))) {
PMIX_ERROR_LOG(rc);

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

@ -78,7 +78,9 @@ typedef struct pmix_pnet_globals_t pmix_pnet_globals_t;
PMIX_EXPORT extern pmix_pnet_globals_t pmix_pnet_globals;
PMIX_EXPORT pmix_status_t pmix_pnet_base_setup_app(char *nspace, pmix_list_t *ilist);
PMIX_EXPORT pmix_status_t pmix_pnet_base_setup_app(char *nspace,
pmix_info_t info[], size_t ninfo,
pmix_list_t *ilist);
PMIX_EXPORT pmix_status_t pmix_pnet_base_setup_local_network(char *nspace,
pmix_info_t info[],
size_t ninfo);

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

@ -18,27 +18,58 @@
#include "src/class/pmix_list.h"
#include "src/util/error.h"
#include "src/server/pmix_server_ops.h"
#include "src/mca/pnet/base/base.h"
pmix_status_t pmix_pnet_base_setup_app(char *nspace, pmix_list_t *ilist)
/* NOTE: a tool (e.g., prun) may call this function to
* harvest local envars for inclusion in a call to
* PMIx_Spawn */
pmix_status_t pmix_pnet_base_setup_app(char *nspace,
pmix_info_t info[], size_t ninfo,
pmix_list_t *ilist)
{
pmix_pnet_base_active_module_t *active;
pmix_status_t rc;
pmix_nspace_t *nptr, *ns;
if (!pmix_pnet_globals.initialized) {
return PMIX_ERR_INIT;
}
pmix_output_verbose(2, pmix_pnet_base_framework.framework_output,
"pnet: setup_app called");
/* protect against bozo inputs */
if (NULL == nspace || NULL == ilist) {
return PMIX_ERR_BAD_PARAM;
}
nptr = NULL;
if (PMIX_PROC_IS_SERVER(pmix_globals.mypeer)) {
/* find this nspace - note that it may not have
* been registered yet */
PMIX_LIST_FOREACH(ns, &pmix_server_globals.nspaces, pmix_nspace_t) {
if (0 == strcmp(ns->nspace, nspace)) {
nptr = ns;
break;
}
}
if (NULL == nptr) {
/* add it */
nptr = PMIX_NEW(pmix_nspace_t);
if (NULL == nptr) {
return PMIX_ERR_NOMEM;
}
nptr->nspace = strdup(nspace);
pmix_list_append(&pmix_server_globals.nspaces, &nptr->super);
}
}
PMIX_LIST_FOREACH(active, &pmix_pnet_globals.actives, pmix_pnet_base_active_module_t) {
if (NULL != active->module->setup_app) {
if (PMIX_SUCCESS != (rc = active->module->setup_app(nspace, ilist))) {
if (PMIX_SUCCESS != (rc = active->module->setup_app(nptr, info, ninfo, ilist))) {
return rc;
}
}
@ -47,25 +78,48 @@ pmix_status_t pmix_pnet_base_setup_app(char *nspace, pmix_list_t *ilist)
return PMIX_SUCCESS;
}
/* can only be called by a server */
pmix_status_t pmix_pnet_base_setup_local_network(char *nspace,
pmix_info_t info[],
size_t ninfo)
{
pmix_pnet_base_active_module_t *active;
pmix_status_t rc;
pmix_nspace_t *nptr, *ns;
if (!pmix_pnet_globals.initialized) {
return PMIX_ERR_INIT;
}
pmix_output_verbose(2, pmix_pnet_base_framework.framework_output,
"pnet: setup_local_network called");
/* protect against bozo inputs */
if (NULL == nspace) {
return PMIX_ERR_BAD_PARAM;
}
/* find this proc's nspace object */
nptr = NULL;
PMIX_LIST_FOREACH(ns, &pmix_server_globals.nspaces, pmix_nspace_t) {
if (0 == strcmp(ns->nspace, nspace)) {
nptr = ns;
break;
}
}
if (NULL == nptr) {
/* add it */
nptr = PMIX_NEW(pmix_nspace_t);
if (NULL == nptr) {
return PMIX_ERR_NOMEM;
}
nptr->nspace = strdup(nspace);
pmix_list_append(&pmix_server_globals.nspaces, &nptr->super);
}
PMIX_LIST_FOREACH(active, &pmix_pnet_globals.actives, pmix_pnet_base_active_module_t) {
if (NULL != active->module->setup_local_network) {
if (PMIX_SUCCESS != (rc = active->module->setup_local_network(nspace, info, ninfo))) {
if (PMIX_SUCCESS != (rc = active->module->setup_local_network(nptr, info, ninfo))) {
return rc;
}
}
@ -74,23 +128,43 @@ pmix_status_t pmix_pnet_base_setup_local_network(char *nspace,
return PMIX_SUCCESS;
}
pmix_status_t pmix_pnet_base_setup_fork(const pmix_proc_t *peer, char ***env)
/* can only be called by a server */
pmix_status_t pmix_pnet_base_setup_fork(const pmix_proc_t *proc, char ***env)
{
pmix_pnet_base_active_module_t *active;
pmix_status_t rc;
pmix_nspace_t *nptr, *ns;
if (!pmix_pnet_globals.initialized) {
return PMIX_ERR_INIT;
}
/* protect against bozo inputs */
if (NULL == peer || NULL == env) {
if (NULL == proc || NULL == env) {
return PMIX_ERR_BAD_PARAM;
}
/* find this proc's nspace object */
nptr = NULL;
PMIX_LIST_FOREACH(ns, &pmix_server_globals.nspaces, pmix_nspace_t) {
if (0 == strcmp(ns->nspace, proc->nspace)) {
nptr = ns;
break;
}
}
if (NULL == nptr) {
/* add it */
nptr = PMIX_NEW(pmix_nspace_t);
if (NULL == nptr) {
return PMIX_ERR_NOMEM;
}
nptr->nspace = strdup(proc->nspace);
pmix_list_append(&pmix_server_globals.nspaces, &nptr->super);
}
PMIX_LIST_FOREACH(active, &pmix_pnet_globals.actives, pmix_pnet_base_active_module_t) {
if (NULL != active->module->setup_fork) {
if (PMIX_SUCCESS != (rc = active->module->setup_fork(peer, env))) {
if (PMIX_SUCCESS != (rc = active->module->setup_fork(nptr, env))) {
return rc;
}
}

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

@ -45,7 +45,7 @@
/* Instantiate the global vars */
pmix_pnet_globals_t pmix_pnet_globals = {{{0}}};
pmix_pnet_module_t pmix_pnet = {
pmix_pnet_API_module_t pmix_pnet = {
.setup_app = pmix_pnet_base_setup_app,
.setup_local_network = pmix_pnet_base_setup_local_network,
.setup_fork = pmix_pnet_base_setup_fork,

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

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
* Copyright (c) 2016 IBM Corporation. All rights reserved.
*
* $COPYRIGHT$
@ -37,17 +37,21 @@
#include "src/util/error.h"
#include "src/util/output.h"
#include "src/util/pmix_environ.h"
#include "src/mca/preg/preg.h"
#include "src/mca/pnet/pnet.h"
#include "src/mca/pnet/base/base.h"
#include "pnet_opa.h"
static pmix_status_t opa_init(void);
static void opa_finalize(void);
static pmix_status_t setup_app(char *nspace, pmix_list_t *ilist);
static pmix_status_t setup_local_network(char *nspace,
static pmix_status_t setup_app(pmix_nspace_t *nptr,
pmix_info_t info[], size_t ninfo,
pmix_list_t *ilist);
static pmix_status_t setup_local_network(pmix_nspace_t *nptr,
pmix_info_t info[],
size_t ninfo);
static pmix_status_t setup_fork(const pmix_proc_t *peer, char ***env);
static pmix_status_t setup_fork(pmix_nspace_t *nptr, char ***env);
static void child_finalized(pmix_peer_t *peer);
static void local_app_finalized(char *nspace);
@ -63,14 +67,14 @@ pmix_pnet_module_t pmix_opa_module = {
static pmix_status_t opa_init(void)
{
pmix_output_verbose(2, pmix_globals.debug_output,
pmix_output_verbose(2, pmix_pnet_base_framework.framework_output,
"pnet: opa init");
return PMIX_SUCCESS;
}
static void opa_finalize(void)
{
pmix_output_verbose(2, pmix_globals.debug_output,
pmix_output_verbose(2, pmix_pnet_base_framework.framework_output,
"pnet: opa finalize");
}
@ -157,75 +161,190 @@ static char* transports_print(uint64_t *unique_key)
return string_key;
}
static pmix_status_t setup_app(char *nspace, pmix_list_t *ilist)
/* NOTE: if there is any binary data to be transferred, then
* this function MUST pack it for transport as the host will
* not know how to do so */
static pmix_status_t setup_app(pmix_nspace_t *nptr,
pmix_info_t info[], size_t ninfo,
pmix_list_t *ilist)
{
uint64_t unique_key[2];
char *string_key, *cs_env;
int fd_rand;
size_t bytes_read;
pmix_kval_t *kv;
size_t n, bytes_read, len;
pmix_kval_t *kv, *next;
int i, j;
bool envars, seckeys;
/* put the number here - or else create an appropriate string. this just needs to
* eventually be a string variable
*/
if(-1 == (fd_rand = open("/dev/urandom", O_RDONLY))) {
transports_use_rand(unique_key);
if (NULL == info) {
envars = true;
seckeys = true;
} else {
bytes_read = read(fd_rand, (char *) unique_key, 16);
if(bytes_read != 16) {
transports_use_rand(unique_key);
envars = false;
seckeys = false;
for (n=0; n < ninfo; n++) {
if (0 == strncmp(info[n].key, PMIX_SETUP_APP_ENVARS, PMIX_MAX_KEYLEN)) {
envars = PMIX_INFO_TRUE(&info[n]);
} else if (0 == strncmp(info[n].key, PMIX_SETUP_APP_ALL, PMIX_MAX_KEYLEN)) {
envars = PMIX_INFO_TRUE(&info[n]);
seckeys = PMIX_INFO_TRUE(&info[n]);
} else if (0 == strncmp(info[n].key, PMIX_SETUP_APP_NONENVARS, PMIX_MAX_KEYLEN)) {
seckeys = PMIX_INFO_TRUE(&info[n]);
}
}
close(fd_rand);
}
if (NULL == (string_key = transports_print(unique_key))) {
PMIX_ERROR_LOG(PMIX_ERR_OUT_OF_RESOURCE);
return PMIX_ERR_OUT_OF_RESOURCE;
if (seckeys) {
/* put the number here - or else create an appropriate string. this just needs to
* eventually be a string variable
*/
if(-1 == (fd_rand = open("/dev/urandom", O_RDONLY))) {
transports_use_rand(unique_key);
} else {
bytes_read = read(fd_rand, (char *) unique_key, 16);
if(bytes_read != 16) {
transports_use_rand(unique_key);
}
close(fd_rand);
}
if (NULL == (string_key = transports_print(unique_key))) {
PMIX_ERROR_LOG(PMIX_ERR_OUT_OF_RESOURCE);
return PMIX_ERR_OUT_OF_RESOURCE;
}
if (PMIX_SUCCESS != pmix_mca_base_var_env_name("opa_precondition_transports", &cs_env)) {
PMIX_ERROR_LOG(PMIX_ERR_OUT_OF_RESOURCE);
free(string_key);
return PMIX_ERR_OUT_OF_RESOURCE;
}
kv = PMIX_NEW(pmix_kval_t);
if (NULL == kv) {
free(string_key);
free(cs_env);
return PMIX_ERR_OUT_OF_RESOURCE;
}
kv->key = strdup(PMIX_SET_ENVAR);
kv->value = (pmix_value_t*)malloc(sizeof(pmix_value_t));
if (NULL == kv->value) {
free(string_key);
free(cs_env);
PMIX_RELEASE(kv);
return PMIX_ERR_OUT_OF_RESOURCE;
}
kv->value->type = PMIX_ENVAR;
PMIX_ENVAR_LOAD(&kv->value->data.envar, cs_env, string_key, ':');
pmix_list_append(ilist, &kv->super);
free(cs_env);
free(string_key);
}
if (PMIX_SUCCESS != pmix_mca_base_var_env_name("pmix_precondition_transports", &cs_env)) {
PMIX_ERROR_LOG(PMIX_ERR_OUT_OF_RESOURCE);
free(string_key);
return PMIX_ERR_OUT_OF_RESOURCE;
if (envars) {
/* harvest envars to pass along */
if (NULL != mca_pnet_opa_component.include) {
for (j=0; NULL != mca_pnet_opa_component.include[j]; j++) {
len = strlen(mca_pnet_opa_component.include[j]);
if ('*' == mca_pnet_opa_component.include[j][len-1]) {
--len;
}
for (i = 0; NULL != environ[i]; ++i) {
if (0 == strncmp(environ[i], mca_pnet_opa_component.include[j], len)) {
cs_env = strdup(environ[i]);
kv = PMIX_NEW(pmix_kval_t);
if (NULL == kv) {
return PMIX_ERR_OUT_OF_RESOURCE;
}
kv->key = strdup(PMIX_SET_ENVAR);
kv->value = (pmix_value_t*)malloc(sizeof(pmix_value_t));
if (NULL == kv->value) {
PMIX_RELEASE(kv);
return PMIX_ERR_OUT_OF_RESOURCE;
}
kv->value->type = PMIX_ENVAR;
string_key = strchr(cs_env, '=');
*string_key = '\0';
++string_key;
PMIX_ENVAR_LOAD(&kv->value->data.envar, cs_env, string_key, ':');
pmix_list_append(ilist, &kv->super);
free(cs_env);
}
}
}
}
/* now check the exclusions and remove any that match */
if (NULL != mca_pnet_opa_component.exclude) {
for (j=0; NULL != mca_pnet_opa_component.exclude[j]; j++) {
len = strlen(mca_pnet_opa_component.exclude[j]);
if ('*' == mca_pnet_opa_component.exclude[j][len-1]) {
--len;
}
PMIX_LIST_FOREACH_SAFE(kv, next, ilist, pmix_kval_t) {
if (0 == strncmp(kv->value->data.envar.envar, mca_pnet_opa_component.exclude[j], len)) {
pmix_list_remove_item(ilist, &kv->super);
PMIX_RELEASE(kv);
}
}
}
}
}
kv = PMIX_NEW(pmix_kval_t);
if (NULL == kv) {
free(string_key);
free(cs_env);
return PMIX_ERR_OUT_OF_RESOURCE;
}
kv->key = strdup(PMIX_SET_ENVAR);
kv->value = (pmix_value_t*)malloc(sizeof(pmix_value_t));
if (NULL == kv->value) {
free(string_key);
free(cs_env);
PMIX_RELEASE(kv);
return PMIX_ERR_OUT_OF_RESOURCE;
}
kv->value->type = PMIX_STRING;
if (0 > asprintf(&kv->value->data.string, "%s=%s", cs_env, string_key)) {
free(string_key);
free(cs_env);
PMIX_RELEASE(kv);
return PMIX_ERR_OUT_OF_RESOURCE;
}
pmix_list_append(ilist, &kv->super);
free(cs_env);
free(string_key);
return PMIX_SUCCESS;
}
static pmix_status_t setup_local_network(char *nspace,
static pmix_status_t setup_local_network(pmix_nspace_t *nptr,
pmix_info_t info[],
size_t ninfo)
{
size_t n;
pmix_status_t rc;
pmix_kval_t *kv;
char *nodestring, **nodes;
pmix_proc_t *procs;
size_t nprocs;
if (NULL != info) {
for (n=0; n < ninfo; n++) {
if (0 == strncmp(info[n].key, PMIX_PNET_OPA_BLOB, PMIX_MAX_KEYLEN)) {
/* the byte object contains a packed blob that needs to be
* cached until we determine we have local procs for this
* nspace, and then delivered to the local OPA driver when
* we have a means for doing so */
kv = PMIX_NEW(pmix_kval_t);
if (NULL == kv) {
return PMIX_ERR_NOMEM;
}
kv->key = strdup(info[n].key);
kv->value = (pmix_value_t*)malloc(sizeof(pmix_value_t));
if (NULL == kv->value) {
PMIX_RELEASE(kv);
return PMIX_ERR_NOMEM;
}
pmix_value_xfer(kv->value, &info[n].value);
pmix_list_append(&nptr->setup_data, &kv->super);
}
}
}
return PMIX_SUCCESS;
}
static pmix_status_t setup_fork(const pmix_proc_t *peer, char ***env)
static pmix_status_t setup_fork(pmix_nspace_t *nptr, char ***env)
{
pmix_kval_t *kv, *next;
/* if there are any cached nspace prep blobs, execute them,
* ensuring that we only do so once per nspace - note that
* we don't expect to find any envars here, though we could
* have included some if we needed to set them per-client */
PMIX_LIST_FOREACH_SAFE(kv, next, &nptr->setup_data, pmix_kval_t) {
if (0 == strcmp(kv->key, PMIX_PNET_OPA_BLOB)) {
pmix_list_remove_item(&nptr->setup_data, &kv->super);
/* deliver to the local lib */
PMIX_RELEASE(kv);
}
}
return PMIX_SUCCESS;
}

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

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2016 Intel, Inc. All rights reserved.
* Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
*
* $COPYRIGHT$
*
@ -18,10 +18,19 @@
BEGIN_C_DECLS
typedef struct {
pmix_pnet_base_component_t super;
char **include;
char **exclude;
} pmix_pnet_opa_component_t;
/* the component must be visible data for the linker to find it */
PMIX_EXPORT extern pmix_pnet_base_component_t mca_pnet_opa_component;
PMIX_EXPORT extern pmix_pnet_opa_component_t mca_pnet_opa_component;
extern pmix_pnet_module_t pmix_opa_module;
/* define a key for any blob we need to send in a launch msg */
#define PMIX_PNET_OPA_BLOB "pmix.pnet.opa.blob"
END_C_DECLS
#endif

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

@ -12,7 +12,7 @@
* All rights reserved.
* Copyright (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2016 Intel, Inc. All rights reserved.
* Copyright (c) 2016-2018 Intel, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -29,48 +29,85 @@
#include <src/include/pmix_config.h>
#include "pmix_common.h"
#include "src/util/argv.h"
#include "src/mca/pnet/pnet.h"
#include "pnet_opa.h"
static pmix_status_t component_open(void);
static pmix_status_t component_close(void);
static pmix_status_t component_query(pmix_mca_base_module_t **module, int *priority);
static pmix_status_t component_register(void);
/*
* Instantiate the public struct with all of our public information
* and pointers to our public functions in it
*/
pmix_pnet_base_component_t mca_pnet_opa_component = {
.base = {
PMIX_PNET_BASE_VERSION_1_0_0,
pmix_pnet_opa_component_t mca_pnet_opa_component = {
.super = {
.base = {
PMIX_PNET_BASE_VERSION_1_0_0,
/* Component name and version */
.pmix_mca_component_name = "opa",
PMIX_MCA_BASE_MAKE_VERSION(component,
PMIX_MAJOR_VERSION,
PMIX_MINOR_VERSION,
PMIX_RELEASE_VERSION),
/* Component name and version */
.pmix_mca_component_name = "opa",
PMIX_MCA_BASE_MAKE_VERSION(component,
PMIX_MAJOR_VERSION,
PMIX_MINOR_VERSION,
PMIX_RELEASE_VERSION),
/* Component open and close functions */
.pmix_mca_open_component = component_open,
.pmix_mca_close_component = component_close,
.pmix_mca_query_component = component_query,
/* Component open and close functions */
.pmix_mca_open_component = component_open,
.pmix_mca_close_component = component_close,
.pmix_mca_register_component_params = component_register,
.pmix_mca_query_component = component_query,
},
.data = {
/* The component is checkpoint ready */
PMIX_MCA_BASE_METADATA_PARAM_CHECKPOINT
}
},
.data = {
/* The component is checkpoint ready */
PMIX_MCA_BASE_METADATA_PARAM_CHECKPOINT
}
.include = NULL,
.exclude = NULL
};
static char *includeparam;
static char *excludeparam;
static int component_open(void)
static pmix_status_t component_register(void)
{
pmix_mca_base_component_t *component = &mca_pnet_opa_component.super.base;
includeparam = "HFI_*,PSM2_*";
(void)pmix_mca_base_component_var_register(component, "include_envars",
"Comma-delimited list of envars to harvest (\'*\' and \'?\' supported)",
PMIX_MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0,
PMIX_INFO_LVL_2,
PMIX_MCA_BASE_VAR_SCOPE_LOCAL,
&includeparam);
if (NULL != includeparam) {
mca_pnet_opa_component.include = pmix_argv_split(includeparam, ',');
}
excludeparam = NULL;
(void)pmix_mca_base_component_var_register(component, "exclude_envars",
"Comma-delimited list of envars to exclude (\'*\' and \'?\' supported)",
PMIX_MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0,
PMIX_INFO_LVL_2,
PMIX_MCA_BASE_VAR_SCOPE_LOCAL,
&excludeparam);
if (NULL != excludeparam) {
mca_pnet_opa_component.exclude = pmix_argv_split(excludeparam, ',');
}
return PMIX_SUCCESS;
}
static pmix_status_t component_open(void)
{
return PMIX_SUCCESS;
}
static int component_query(pmix_mca_base_module_t **module, int *priority)
static pmix_status_t component_query(pmix_mca_base_module_t **module, int *priority)
{
*priority = 10;
*module = (pmix_mca_base_module_t *)&pmix_opa_module;
@ -78,7 +115,7 @@ static int component_query(pmix_mca_base_module_t **module, int *priority)
}
static int component_close(void)
static pmix_status_t component_close(void)
{
return PMIX_SUCCESS;
}

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

@ -56,13 +56,15 @@ typedef void (*pmix_pnet_base_module_fini_fn_t)(void);
* tokens required for application processes to communicate with
* each other
*/
typedef pmix_status_t (*pmix_pnet_base_module_setup_app_fn_t)(char *nspace, pmix_list_t *ilist);
typedef pmix_status_t (*pmix_pnet_base_module_setup_app_fn_t)(pmix_nspace_t *nptr,
pmix_info_t info[], size_t ninfo,
pmix_list_t *ilist);
/**
* Give the local network library an opportunity to setup address information
* for the application by passing in the layout type and a regex describing
* the layout */
typedef pmix_status_t (*pmix_pnet_base_module_setup_local_net_fn_t)(char *nspace,
typedef pmix_status_t (*pmix_pnet_base_module_setup_local_net_fn_t)(pmix_nspace_t *nptr,
pmix_info_t info[],
size_t ninfo);
@ -70,7 +72,7 @@ typedef pmix_status_t (*pmix_pnet_base_module_setup_local_net_fn_t)(char *nspace
* Give the local network library an opportunity to add any envars to the
* environment of a local application process prior to fork/exec
*/
typedef pmix_status_t (*pmix_pnet_base_module_setup_fork_fn_t)(const pmix_proc_t *peer, char ***env);
typedef pmix_status_t (*pmix_pnet_base_module_setup_fork_fn_t)(pmix_nspace_t *nptr, char ***env);
/**
* Provide an opportunity for the local network library to cleanup when a
@ -99,8 +101,51 @@ typedef struct {
pmix_pnet_base_module_local_app_finalized_fn_t local_app_finalized;
} pmix_pnet_module_t;
/* define a few API versions of the functions */
/**
* Provide an opportunity for the network to define values that
* are to be passed to an application. This can include security
* tokens required for application processes to communicate with
* each other
*/
typedef pmix_status_t (*pmix_pnet_base_API_setup_app_fn_t)(char *nspace,
pmix_info_t info[], size_t ninfo,
pmix_list_t *ilist);
/**
* Give the local network library an opportunity to setup address information
* for the application by passing in the layout type and a regex describing
* the layout */
typedef pmix_status_t (*pmix_pnet_base_API_setup_local_net_fn_t)(char *nspace,
pmix_info_t info[],
size_t ninfo);
/**
* Give the local network library an opportunity to add any envars to the
* environment of a local application process prior to fork/exec
*/
typedef pmix_status_t (*pmix_pnet_base_API_setup_fork_fn_t)(const pmix_proc_t *peer, char ***env);
/**
* Base structure for a PNET API
*/
typedef struct {
char *name;
/* init/finalize */
pmix_pnet_base_module_init_fn_t init;
pmix_pnet_base_module_fini_fn_t finalize;
pmix_pnet_base_API_setup_app_fn_t setup_app;
pmix_pnet_base_API_setup_local_net_fn_t setup_local_network;
pmix_pnet_base_API_setup_fork_fn_t setup_fork;
pmix_pnet_base_module_child_finalized_fn_t child_finalized;
pmix_pnet_base_module_local_app_finalized_fn_t local_app_finalized;
} pmix_pnet_API_module_t;
/* declare the global APIs */
PMIX_EXPORT extern pmix_pnet_module_t pmix_pnet;
PMIX_EXPORT extern pmix_pnet_API_module_t pmix_pnet;
/*
* the standard component data structure

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

@ -0,0 +1,52 @@
# -*- makefile -*-
#
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
# University Research and Technology
# Corporation. All rights reserved.
# Copyright (c) 2004-2005 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 (c) 2012 Los Alamos National Security, Inc. All rights reserved.
# Copyright (c) 2013-2018 Intel, Inc. All rights reserved.
# Copyright (c) 2017 Research Organization for Information Science
# and Technology (RIST). All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
headers = pnet_test.h
sources = \
pnet_test_component.c \
pnet_test.c
# Make the output library in this directory, and name it either
# mca_<type>_<name>.la (for DSO builds) or libmca_<type>_<name>.la
# (for static builds).
if MCA_BUILD_pmix_pnet_test_DSO
lib =
lib_sources =
component = mca_pnet_test.la
component_sources = $(headers) $(sources)
else
lib = libmca_pnet_test.la
lib_sources = $(headers) $(sources)
component =
component_sources =
endif
mcacomponentdir = $(pmixlibdir)
mcacomponent_LTLIBRARIES = $(component)
mca_pnet_test_la_SOURCES = $(component_sources)
mca_pnet_test_la_LDFLAGS = -module -avoid-version
noinst_LTLIBRARIES = $(lib)
libmca_pnet_test_la_SOURCES = $(lib_sources)
libmca_pnet_test_la_LDFLAGS = -module -avoid-version

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

@ -0,0 +1,221 @@
/*
* Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
* Copyright (c) 2016 IBM Corporation. All rights reserved.
*
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include <src/include/pmix_config.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#include <time.h>
#include <pmix_common.h>
#include "src/mca/base/pmix_mca_base_var.h"
#include "src/include/pmix_socket_errno.h"
#include "src/include/pmix_globals.h"
#include "src/class/pmix_list.h"
#include "src/util/alfg.h"
#include "src/util/argv.h"
#include "src/util/error.h"
#include "src/util/output.h"
#include "src/util/pmix_environ.h"
#include "src/mca/preg/preg.h"
#include "src/mca/pnet/pnet.h"
#include "src/mca/pnet/base/base.h"
#include "pnet_test.h"
static pmix_status_t test_init(void);
static void test_finalize(void);
static pmix_status_t setup_app(pmix_nspace_t *nptr,
pmix_info_t info[], size_t ninfo,
pmix_list_t *ilist);
static pmix_status_t setup_local_network(pmix_nspace_t *nptr,
pmix_info_t info[],
size_t ninfo);
static pmix_status_t setup_fork(pmix_nspace_t *nptr, char ***env);
static void child_finalized(pmix_peer_t *peer);
static void local_app_finalized(char *nspace);
pmix_pnet_module_t pmix_test_module = {
.init = test_init,
.finalize = test_finalize,
.setup_app = setup_app,
.setup_local_network = setup_local_network,
.setup_fork = setup_fork,
.child_finalized = child_finalized,
.local_app_finalized = local_app_finalized
};
static pmix_status_t test_init(void)
{
pmix_output_verbose(2, pmix_pnet_base_framework.framework_output,
"pnet: test init");
return PMIX_SUCCESS;
}
static void test_finalize(void)
{
pmix_output_verbose(2, pmix_pnet_base_framework.framework_output,
"pnet: test finalize");
}
/* NOTE: if there is any binary data to be transferred, then
* this function MUST pack it for transport as the host will
* not know how to do so */
static pmix_status_t setup_app(pmix_nspace_t *nptr,
pmix_info_t info[], size_t ninfo,
pmix_list_t *ilist)
{
uint64_t unique_key[2];
char *string_key, *cs_env;
int fd_rand;
size_t n, bytes_read, len;
pmix_kval_t *kv, *next;
int i, j;
bool envars, seckeys;
if (NULL == info) {
envars = true;
seckeys = true;
} else {
envars = false;
seckeys = false;
for (n=0; n < ninfo; n++) {
if (0 == strncmp(info[n].key, PMIX_SETUP_APP_ENVARS, PMIX_MAX_KEYLEN)) {
envars = PMIX_INFO_TRUE(&info[n]);
} else if (0 == strncmp(info[n].key, PMIX_SETUP_APP_ALL, PMIX_MAX_KEYLEN)) {
envars = PMIX_INFO_TRUE(&info[n]);
seckeys = PMIX_INFO_TRUE(&info[n]);
} else if (0 == strncmp(info[n].key, PMIX_SETUP_APP_NONENVARS, PMIX_MAX_KEYLEN)) {
seckeys = PMIX_INFO_TRUE(&info[n]);
}
}
}
if (seckeys) {
kv = PMIX_NEW(pmix_kval_t);
if (NULL == kv) {
return PMIX_ERR_NOMEM;
}
kv->key = strdup(PMIX_SET_ENVAR);
kv->value = (pmix_value_t*)malloc(sizeof(pmix_value_t));
if (NULL == kv->value) {
PMIX_RELEASE(kv);
return PMIX_ERR_NOMEM;
}
kv->value->type = PMIX_ENVAR;
PMIX_ENVAR_LOAD(&kv->value->data.envar, "PMIX_TEST_SECKEY", "1", ':');
pmix_list_append(ilist, &kv->super);
}
if (envars) {
kv = PMIX_NEW(pmix_kval_t);
if (NULL == kv) {
return PMIX_ERR_NOMEM;
}
kv->key = strdup(PMIX_SET_ENVAR);
kv->value = (pmix_value_t*)malloc(sizeof(pmix_value_t));
if (NULL == kv->value) {
PMIX_RELEASE(kv);
return PMIX_ERR_NOMEM;
}
kv->value->type = PMIX_ENVAR;
PMIX_ENVAR_LOAD(&kv->value->data.envar, "PMIX_TEST_ENVAR", "1", ':');
pmix_list_append(ilist, &kv->super);
}
/* provide a blob so setup_local_network will get called */
kv = PMIX_NEW(pmix_kval_t);
if (NULL == kv) {
return PMIX_ERR_NOMEM;
}
kv->key = strdup("pmix-pnet-test-blob");
kv->value = (pmix_value_t*)malloc(sizeof(pmix_value_t));
if (NULL == kv->value) {
PMIX_RELEASE(kv);
return PMIX_ERR_NOMEM;
}
kv->value->type = PMIX_STRING;
kv->value->data.string = strdup("foobar");
pmix_list_append(ilist, &kv->super);
return PMIX_SUCCESS;
}
static pmix_status_t setup_local_network(pmix_nspace_t *nptr,
pmix_info_t info[],
size_t ninfo)
{
size_t n, m;
pmix_status_t rc;
pmix_kval_t *kv;
char *nodestring, **nodes;
pmix_proc_t *procs;
size_t nprocs;
/* get the list of nodes in this job - returns a regex */
pmix_output(0, "pnet:setup_local_network NSPACE %s", (NULL == nptr) ? "NULL" : nptr->nspace);
pmix_preg.resolve_nodes(nptr->nspace, &nodestring);
if (NULL == nodestring) {
return PMIX_SUCCESS;
}
pmix_preg.parse_nodes(nodestring, &nodes); // get an argv array of node names
pmix_output(0, "pnet:setup_local_network NODES %s", (NULL == nodes) ? "NULL" : "NON-NULL");
if (NULL == nodes) {
free(nodestring);
return PMIX_SUCCESS;
}
for (n=0; NULL != nodes[n]; n++) {
pmix_output(0, "pnet:setup_local_network NODE: %s", nodes[n]);
}
for (n=0; NULL != nodes[n]; n++) {
/* get an array of pmix_proc_t containing the names of the procs on that node */
pmix_preg.resolve_peers(nodes[n], nptr->nspace, &procs, &nprocs);
if (NULL == procs) {
continue;
}
for (m=0; m < nprocs; m++) {
pmix_output(0, "pnet:setup_local_network NODE %s: peer %s:%d", nodes[n], procs[m].nspace, procs[m].rank);
}
/* do stuff */
free(procs);
}
return PMIX_SUCCESS;
}
static pmix_status_t setup_fork(pmix_nspace_t *nptr, char ***env)
{
return PMIX_SUCCESS;
}
static void child_finalized(pmix_peer_t *peer)
{
}
static void local_app_finalized(char *nspace)
{
}

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

@ -0,0 +1,36 @@
/*
* Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
*
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef PMIX_PNET_test_H
#define PMIX_PNET_test_H
#include <src/include/pmix_config.h>
#include "src/mca/pnet/pnet.h"
BEGIN_C_DECLS
typedef struct {
pmix_pnet_base_component_t super;
char **include;
char **exclude;
} pmix_pnet_test_component_t;
/* the component must be visible data for the linker to find it */
PMIX_EXPORT extern pmix_pnet_test_component_t mca_pnet_test_component;
extern pmix_pnet_module_t pmix_test_module;
/* define a key for any blob we need to send in a launch msg */
#define PMIX_PNET_TEST_BLOB "pmix.pnet.test.blob"
END_C_DECLS
#endif

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

@ -0,0 +1,101 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2004-2008 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 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 (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2016-2018 Intel, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*
* These symbols are in a file by themselves to provide nice linker
* semantics. Since linkers generally pull in symbols by object
* files, keeping these symbols as the only symbols in this file
* prevents utility programs such as "ompi_info" from having to import
* entire components just to query their version and parameters.
*/
#include <src/include/pmix_config.h>
#include "pmix_common.h"
#include "src/util/argv.h"
#include "src/mca/pnet/pnet.h"
#include "pnet_test.h"
static pmix_status_t component_open(void);
static pmix_status_t component_close(void);
static pmix_status_t component_query(pmix_mca_base_module_t **module, int *priority);
/*
* Instantiate the public struct with all of our public information
* and pointers to our public functions in it
*/
pmix_pnet_test_component_t mca_pnet_test_component = {
.super = {
.base = {
PMIX_PNET_BASE_VERSION_1_0_0,
/* Component name and version */
.pmix_mca_component_name = "test",
PMIX_MCA_BASE_MAKE_VERSION(component,
PMIX_MAJOR_VERSION,
PMIX_MINOR_VERSION,
PMIX_RELEASE_VERSION),
/* Component open and close functions */
.pmix_mca_open_component = component_open,
.pmix_mca_close_component = component_close,
.pmix_mca_query_component = component_query,
},
.data = {
/* The component is checkpoint ready */
PMIX_MCA_BASE_METADATA_PARAM_CHECKPOINT
}
},
.include = NULL,
.exclude = NULL
};
static pmix_status_t component_open(void)
{
int index;
const pmix_mca_base_var_storage_t *value=NULL;
/* we only allow ourselves to be considered IF the user
* specifically requested so */
if (0 > (index = pmix_mca_base_var_find("pmix", "pnet", NULL, NULL))) {
return PMIX_ERROR;
}
pmix_mca_base_var_get_value(index, &value, NULL, NULL);
if (NULL != value && NULL != value->stringval && '\0' != value->stringval[0]) {
if (NULL != strstr(value->stringval, "test")) {
return PMIX_SUCCESS;
}
}
return PMIX_ERROR;
}
static pmix_status_t component_query(pmix_mca_base_module_t **module, int *priority)
{
*priority = 0;
*module = (pmix_mca_base_module_t *)&pmix_test_module;
return PMIX_SUCCESS;
}
static pmix_status_t component_close(void)
{
return PMIX_SUCCESS;
}

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

@ -501,27 +501,32 @@ static pmix_status_t parse_procs(const char *regexp,
return rc;
}
static void _resolve_peers(int sd, short args, void *cbdata)
static pmix_status_t resolve_peers(const char *nodename,
const char *nspace,
pmix_proc_t **procs, size_t *nprocs)
{
pmix_cb_t *cb = (pmix_cb_t*)cbdata;
pmix_cb_t cb;
pmix_status_t rc;
pmix_kval_t *kv;
pmix_proc_t proc;
char **ptr;
pmix_info_t *info;
pmix_proc_t *procs;
size_t ninfo, nprocs, n, j;
pmix_proc_t *p=NULL;
size_t ninfo, np=0, n, j;
PMIX_CONSTRUCT(&cb, pmix_cb_t);
cb.key = strdup(nodename);
/* this data isn't going anywhere, so we don't require a copy */
cb->copy = false;
cb.copy = false;
/* scope is irrelevant as the info we seek must be local */
cb->scope = PMIX_SCOPE_UNDEF;
cb.scope = PMIX_SCOPE_UNDEF;
/* let the proc point to the nspace */
(void)strncpy(proc.nspace, cb->pname.nspace, PMIX_MAX_NSLEN);
(void)strncpy(proc.nspace, nspace, PMIX_MAX_NSLEN);
proc.rank = PMIX_RANK_WILDCARD;
cb->proc = &proc;
cb.proc = &proc;
PMIX_GDS_FETCH_KV(rc, pmix_client_globals.myserver, cb);
PMIX_GDS_FETCH_KV(rc, pmix_client_globals.myserver, &cb);
if (PMIX_SUCCESS != rc) {
if (PMIX_ERR_INVALID_NAMESPACE != rc) {
PMIX_ERROR_LOG(rc);
@ -529,12 +534,12 @@ static void _resolve_peers(int sd, short args, void *cbdata)
goto complete;
}
/* should just be the one value on the list */
if (1 != pmix_list_get_size(&cb->kvs)) {
if (1 != pmix_list_get_size(&cb.kvs)) {
PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM);
rc = PMIX_ERR_BAD_PARAM;
goto complete;
}
kv = (pmix_kval_t*)pmix_list_get_first(&cb->kvs);
kv = (pmix_kval_t*)pmix_list_get_first(&cb.kvs);
/* the hostname used as a key with wildcard rank will return
* a pmix_data_array_t of pmix_info_t structs */
if (NULL == kv->value ||
@ -552,184 +557,103 @@ static void _resolve_peers(int sd, short args, void *cbdata)
if (0 == strncmp(info[n].key, PMIX_LOCAL_PEERS, PMIX_MAX_KEYLEN)) {
/* split the string */
ptr = pmix_argv_split(info[n].value.data.string, ',');
nprocs = pmix_argv_count(ptr);
PMIX_PROC_CREATE(procs, nprocs);
if (NULL == procs) {
np = pmix_argv_count(ptr);
PMIX_PROC_CREATE(p, np);
if (NULL == p) {
rc = PMIX_ERR_NOMEM;
pmix_argv_free(ptr);
goto complete;
}
for (j=0; j < nprocs; j++) {
(void)strncpy(procs[j].nspace, cb->pname.nspace, PMIX_MAX_NSLEN);
procs[j].rank = strtoul(ptr[j], NULL, 10);
for (j=0; j < np; j++) {
(void)strncpy(p[j].nspace, nspace, PMIX_MAX_NSLEN);
p[j].rank = strtoul(ptr[j], NULL, 10);
}
cb->procs = procs;
cb->nprocs = nprocs;
rc = PMIX_SUCCESS;
pmix_argv_free(ptr);
goto complete;
break;
}
}
complete:
cb->status = rc;
if (NULL != cb->info) {
PMIX_INFO_FREE(cb->info, cb->ninfo);
if (NULL != cb.info) {
PMIX_INFO_FREE(cb.info, cb.ninfo);
}
cb->pstatus = rc;
/* post the data so the receiving thread can acquire it */
PMIX_POST_OBJECT(cb);
PMIX_WAKEUP_THREAD(&cb->lock);
return;
}
static pmix_status_t resolve_peers(const char *nodename,
const char *nspace,
pmix_proc_t **procs, size_t *nprocs)
{
pmix_cb_t *cb;
pmix_status_t rc;
pmix_proc_t proc;
cb = PMIX_NEW(pmix_cb_t);
cb->key = (char*)nodename;
cb->pname.nspace = strdup(nspace);
PMIX_THREADSHIFT(cb, _resolve_peers);
/* wait for the result */
PMIX_WAIT_THREAD(&cb->lock);
/* if the nspace wasn't found, then we need to
* ask the server for that info */
if (PMIX_ERR_INVALID_NAMESPACE == cb->status) {
(void)strncpy(proc.nspace, nspace, PMIX_MAX_NSLEN);
proc.rank = PMIX_RANK_WILDCARD;
/* any key will suffice as it will bring down
* the entire data blob */
rc = PMIx_Get(&proc, PMIX_UNIV_SIZE, NULL, 0, NULL);
if (PMIX_SUCCESS != rc) {
PMIX_RELEASE(cb);
return rc;
}
/* retry the fetch */
cb->lock.active = true;
PMIX_THREADSHIFT(cb, _resolve_peers);
PMIX_WAIT_THREAD(&cb->lock);
if (NULL != cb.key) {
free(cb.key);
cb.key = NULL;
}
*procs = cb->procs;
*nprocs = cb->nprocs;
PMIX_DESTRUCT(&cb);
*procs = p;
*nprocs = np;
rc = cb->status;
PMIX_RELEASE(cb);
return rc;
}
static void _resolve_nodes(int sd, short args, void *cbdata)
{
pmix_cb_t *cb = (pmix_cb_t*)cbdata;
pmix_status_t rc;
pmix_kval_t *kv;
pmix_proc_t proc;
/* create a pmix_info_t so we can pass the nspace
* into the fetch as a qualifier */
PMIX_INFO_CREATE(cb->info, 1);
if (NULL == cb->info) {
cb->status = PMIX_ERR_NOMEM;
PMIX_POST_OBJECT(cb);
PMIX_WAKEUP_THREAD(&cb->lock);
return;
}
cb->ninfo = 1;
PMIX_INFO_LOAD(&cb->info[0], PMIX_NSPACE, cb->pname.nspace, PMIX_STRING);
/* tell the GDS what we want */
cb->key = PMIX_NODE_LIST;
/* this data isn't going anywhere, so we don't require a copy */
cb->copy = false;
/* scope is irrelevant as the info we seek must be local */
cb->scope = PMIX_SCOPE_UNDEF;
/* put the nspace in the proc field */
(void)strncpy(proc.nspace, cb->pname.nspace, PMIX_MAX_NSLEN);
/* the info will be associated with PMIX_RANK_WILDCARD */
proc.rank = PMIX_RANK_WILDCARD;
cb->proc = &proc;
PMIX_GDS_FETCH_KV(rc, pmix_client_globals.myserver, cb);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto complete;
}
/* should just be the one value on the list */
if (1 != pmix_list_get_size(&cb->kvs)) {
PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM);
rc = PMIX_ERR_BAD_PARAM;
goto complete;
}
kv = (pmix_kval_t*)pmix_list_get_first(&cb->kvs);
/* the PMIX_NODE_LIST key is supposed to return a comma-delimited
* string of nodes in this - check that it did */
if (NULL == kv->value ||
PMIX_STRING != kv->value->type) {
PMIX_ERROR_LOG(PMIX_ERR_DATA_VALUE_NOT_FOUND);
rc = PMIX_ERR_DATA_VALUE_NOT_FOUND;
goto complete;
}
/* return the string */
if (NULL != kv->value->data.string) {
cb->key = strdup(kv->value->data.string);
}
complete:
cb->status = rc;
if (NULL != cb->info) {
PMIX_INFO_FREE(cb->info, cb->ninfo);
}
/* post the data so the receiving thread can acquire it */
PMIX_POST_OBJECT(cb);
PMIX_WAKEUP_THREAD(&cb->lock);
return;
}
static pmix_status_t resolve_nodes(const char *nspace,
char **nodelist)
{
pmix_cb_t *cb;
pmix_cb_t cb;
pmix_status_t rc;
pmix_kval_t *kv;
pmix_proc_t proc;
cb = PMIX_NEW(pmix_cb_t);
cb->pname.nspace = strdup(nspace);
PMIX_CONSTRUCT(&cb, pmix_cb_t);
PMIX_THREADSHIFT(cb, _resolve_nodes);
/* setup default answer */
*nodelist = NULL;
/* wait for the result */
PMIX_WAIT_THREAD(&cb->lock);
/* if the nspace wasn't found, then we need to
* ask the server for that info */
if (PMIX_ERR_INVALID_NAMESPACE == cb->status) {
(void)strncpy(proc.nspace, nspace, PMIX_MAX_NSLEN);
proc.rank = PMIX_RANK_WILDCARD;
/* any key will suffice as it will bring down
* the entire data blob */
rc = PMIx_Get(&proc, PMIX_UNIV_SIZE, NULL, 0, NULL);
if (PMIX_SUCCESS != rc) {
PMIX_RELEASE(cb);
return rc;
}
/* retry the fetch */
cb->lock.active = true;
PMIX_THREADSHIFT(cb, _resolve_nodes);
PMIX_WAIT_THREAD(&cb->lock);
/* create a pmix_info_t so we can pass the nspace
* into the fetch as a qualifier */
PMIX_INFO_CREATE(cb.info, 1);
if (NULL == cb.info) {
PMIX_DESTRUCT(&cb);
return PMIX_ERR_NOMEM;
}
/* the string we want is in the key field */
*nodelist = cb->key;
cb.ninfo = 1;
PMIX_INFO_LOAD(&cb.info[0], PMIX_NSPACE, nspace, PMIX_STRING);
rc = cb->status;
PMIX_RELEASE(cb);
/* tell the GDS what we want */
cb.key = PMIX_NODE_MAP;
/* this data isn't going anywhere, so we don't require a copy */
cb.copy = false;
/* scope is irrelevant as the info we seek must be local */
cb.scope = PMIX_SCOPE_UNDEF;
/* put the nspace in the proc field */
(void)strncpy(proc.nspace, nspace, PMIX_MAX_NSLEN);
/* the info will be associated with PMIX_RANK_WILDCARD */
proc.rank = PMIX_RANK_WILDCARD;
cb.proc = &proc;
PMIX_GDS_FETCH_KV(rc, pmix_client_globals.myserver, &cb);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto complete;
}
/* should just be the one value on the list */
if (1 != pmix_list_get_size(&cb.kvs)) {
PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM);
rc = PMIX_ERR_BAD_PARAM;
goto complete;
}
kv = (pmix_kval_t*)pmix_list_get_first(&cb.kvs);
/* the PMIX_NODE_MAP key is supposed to return
* a regex string - check that it did */
if (NULL == kv->value ||
PMIX_STRING != kv->value->type) {
PMIX_ERROR_LOG(PMIX_ERR_DATA_VALUE_NOT_FOUND);
rc = PMIX_ERR_DATA_VALUE_NOT_FOUND;
goto complete;
}
/* return the string */
if (NULL != kv->value->data.string) {
*nodelist = strdup(kv->value->data.string);
}
complete:
if (NULL != cb.info) {
PMIX_INFO_FREE(cb.info, cb.ninfo);
}
return rc;
}
static pmix_status_t pmix_regex_extract_nodes(char *regexp, char ***names)

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

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
* Copyright (c) 2016 IBM Corporation. All rights reserved.
* Copyright (c) 2017 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
@ -100,6 +100,7 @@ static pmix_status_t create_cred(struct pmix_peer_t *peer,
}
}
if (!takeus) {
PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
return PMIX_ERR_NOT_SUPPORTED;
}
}
@ -124,6 +125,7 @@ static pmix_status_t create_cred(struct pmix_peer_t *peer,
goto complete;
} else {
/* unrecognized protocol */
PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
return PMIX_ERR_NOT_SUPPORTED;
}

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

@ -89,6 +89,7 @@ typedef uint32_t pmix_ptl_tag_t;
* within the system */
#define PMIX_PTL_TAG_NOTIFY 0
#define PMIX_PTL_TAG_HEARTBEAT 1
#define PMIX_PTL_TAG_IOF 2
/* define the start of dynamic tags that are
* assigned for send/recv operations */

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

@ -12,7 +12,7 @@
* Copyright (c) 2008-2015 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2010-2015 Los Alamos National Security, LLC.
* All rights reserved.
* Copyright (c) 2013-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2013-2018 Intel, Inc. All rights reserved.
* Copyright (c) 2016 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* $COPYRIGHT$
@ -115,6 +115,7 @@ void pmix_rte_finalize(void)
PMIX_DESTRUCT(&pmix_globals.events);
PMIX_LIST_DESTRUCT(&pmix_globals.cached_events);
PMIX_DESTRUCT(&pmix_globals.notifications);
PMIX_LIST_DESTRUCT(&pmix_globals.iof_requests);
/* now safe to release the event base */
if (!pmix_globals.external_evbase) {

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

@ -15,7 +15,7 @@
* Copyright (c) 2009 Oak Ridge National Labs. All rights reserved.
* Copyright (c) 2010-2015 Los Alamos National Security, LLC.
* All rights reserved.
* Copyright (c) 2013-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2013-2018 Intel, Inc. All rights reserved.
* Copyright (c) 2015 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* $COPYRIGHT$
@ -159,6 +159,8 @@ int pmix_rte_init(pmix_proc_type_t type,
/* construct the global notification ring buffer */
PMIX_CONSTRUCT(&pmix_globals.notifications, pmix_ring_buffer_t);
pmix_ring_buffer_init(&pmix_globals.notifications, 256);
/* and setup the iof request tracking list */
PMIX_CONSTRUCT(&pmix_globals.iof_requests, pmix_list_t);
/* Setup client verbosities as all procs are allowed to
* access client APIs */
@ -198,6 +200,12 @@ int pmix_rte_init(pmix_proc_type_t type,
pmix_output_set_verbosity(pmix_client_globals.event_output,
pmix_client_globals.event_verbose);
}
if (0 < pmix_client_globals.iof_verbose) {
/* set default output */
pmix_client_globals.iof_output = pmix_output_open(NULL);
pmix_output_set_verbosity(pmix_client_globals.iof_output,
pmix_client_globals.iof_verbose);
}
/* get our effective id's */
pmix_globals.uid = geteuid();

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

@ -21,7 +21,7 @@
* and Technology (RIST). All rights reserved.
* Copyright (c) 2015 Mellanox Technologies, Inc.
* All rights reserved.
* Copyright (c) 2016-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2016-2018 Intel, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -95,105 +95,152 @@ pmix_status_t pmix_register_params(void)
}
(void) pmix_mca_base_var_register ("pmix", "pmix", NULL, "event_caching_window",
"Time (in seconds) to aggregate events before reporting them - this "
"suppresses event cascades when processes abnormally terminate",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_event_caching_window);
"Time (in seconds) to aggregate events before reporting them - this "
"suppresses event cascades when processes abnormally terminate",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_event_caching_window);
(void) pmix_mca_base_var_register ("pmix", "pmix", NULL, "suppress_missing_data_warning",
"Suppress warning that PMIx is missing job-level data that "
"is supposed to be provided by the host RM.",
PMIX_MCA_BASE_VAR_TYPE_BOOL, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_suppress_missing_data_warning);
"Suppress warning that PMIx is missing job-level data that "
"is supposed to be provided by the host RM.",
PMIX_MCA_BASE_VAR_TYPE_BOOL, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_suppress_missing_data_warning);
/**** CLIENT: VERBOSE OUTPUT PARAMS ****/
(void) pmix_mca_base_var_register ("pmix", "pmix", "client", "get_verbose",
"Verbosity for client get operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_client_globals.get_verbose);
"Verbosity for client get operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_client_globals.get_verbose);
(void) pmix_mca_base_var_register ("pmix", "pmix", "client", "connect_verbose",
"Verbosity for client connect operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_client_globals.connect_verbose);
"Verbosity for client connect operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_client_globals.connect_verbose);
(void) pmix_mca_base_var_register ("pmix", "pmix", "client", "fence_verbose",
"Verbosity for client fence operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_client_globals.fence_verbose);
"Verbosity for client fence operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_client_globals.fence_verbose);
(void) pmix_mca_base_var_register ("pmix", "pmix", "client", "pub_verbose",
"Verbosity for client publish, lookup, and unpublish operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_client_globals.pub_verbose);
"Verbosity for client publish, lookup, and unpublish operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_client_globals.pub_verbose);
(void) pmix_mca_base_var_register ("pmix", "pmix", "client", "spawn_verbose",
"Verbosity for client spawn operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_client_globals.spawn_verbose);
"Verbosity for client spawn operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_client_globals.spawn_verbose);
(void) pmix_mca_base_var_register ("pmix", "pmix", "client", "event_verbose",
"Verbosity for eventt spawn operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_client_globals.event_verbose);
"Verbosity for client event notifications",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_client_globals.event_verbose);
(void) pmix_mca_base_var_register ("pmix", "pmix", "client", "iof_verbose",
"Verbosity for client iof operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_client_globals.iof_verbose);
(void) pmix_mca_base_var_register ("pmix", "pmix", "client", "base_verbose",
"Verbosity for basic client operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_client_globals.base_verbose);
"Verbosity for basic client operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_client_globals.base_verbose);
/**** SERVER: VERBOSE OUTPUT PARAMS ****/
(void) pmix_mca_base_var_register ("pmix", "pmix", "server", "get_verbose",
"Verbosity for server get operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_server_globals.get_verbose);
"Verbosity for server get operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_server_globals.get_verbose);
(void) pmix_mca_base_var_register ("pmix", "pmix", "server", "connect_verbose",
"Verbosity for server connect operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_server_globals.connect_verbose);
"Verbosity for server connect operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_server_globals.connect_verbose);
(void) pmix_mca_base_var_register ("pmix", "pmix", "server", "fence_verbose",
"Verbosity for server fence operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_server_globals.fence_verbose);
"Verbosity for server fence operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_server_globals.fence_verbose);
(void) pmix_mca_base_var_register ("pmix", "pmix", "server", "pub_verbose",
"Verbosity for server publish, lookup, and unpublish operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_server_globals.pub_verbose);
"Verbosity for server publish, lookup, and unpublish operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_server_globals.pub_verbose);
(void) pmix_mca_base_var_register ("pmix", "pmix", "server", "spawn_verbose",
"Verbosity for server spawn operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_server_globals.spawn_verbose);
"Verbosity for server spawn operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_server_globals.spawn_verbose);
(void) pmix_mca_base_var_register ("pmix", "pmix", "server", "event_verbose",
"Verbosity for server event operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_server_globals.event_verbose);
"Verbosity for server event operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_server_globals.event_verbose);
(void) pmix_mca_base_var_register ("pmix", "pmix", "server", "iof_verbose",
"Verbosity for server iof operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_server_globals.iof_verbose);
(void) pmix_mca_base_var_register ("pmix", "pmix", "server", "base_verbose",
"Verbosity for basic server operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_server_globals.base_verbose);
"Verbosity for basic server operations",
PMIX_MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
PMIX_INFO_LVL_1, PMIX_MCA_BASE_VAR_SCOPE_ALL,
&pmix_server_globals.base_verbose);
/* check for maximum number of pending output messages */
pmix_globals.output_limit = (size_t) INT_MAX;
(void) pmix_mca_base_var_register("pmix", "iof", NULL, "output_limit",
"Maximum backlog of output messages [default: unlimited]",
PMIX_MCA_BASE_VAR_TYPE_SIZE_T, NULL, 0, 0,
PMIX_INFO_LVL_9,
PMIX_MCA_BASE_VAR_SCOPE_READONLY,
&pmix_globals.output_limit);
pmix_globals.xml_output = false;
(void) pmix_mca_base_var_register ("pmix", "iof", NULL, "xml_output",
"Display all output in XML format (default: false)",
PMIX_MCA_BASE_VAR_TYPE_BOOL, NULL, 0, 0,
PMIX_INFO_LVL_9, PMIX_MCA_BASE_VAR_SCOPE_READONLY,
&pmix_globals.xml_output);
/* whether to tag output */
/* if we requested xml output, be sure to tag the output as well */
pmix_globals.tag_output = pmix_globals.xml_output;
(void) pmix_mca_base_var_register ("pmix", "iof", NULL, "tag_output",
"Tag all output with [job,rank] (default: false)",
PMIX_MCA_BASE_VAR_TYPE_BOOL, NULL, 0, 0,
PMIX_INFO_LVL_9, PMIX_MCA_BASE_VAR_SCOPE_READONLY,
&pmix_globals.tag_output);
if (pmix_globals.xml_output) {
pmix_globals.tag_output = true;
}
/* whether to timestamp output */
pmix_globals.timestamp_output = false;
(void) pmix_mca_base_var_register ("pmix", "iof", NULL, "timestamp_output",
"Timestamp all application process output (default: false)",
PMIX_MCA_BASE_VAR_TYPE_BOOL, NULL, 0, 0,
PMIX_INFO_LVL_9, PMIX_MCA_BASE_VAR_SCOPE_READONLY,
&pmix_globals.timestamp_output);
return PMIX_SUCCESS;
}

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

@ -53,6 +53,7 @@
#include "src/util/argv.h"
#include "src/util/error.h"
#include "src/util/name_fns.h"
#include "src/util/output.h"
#include "src/util/pmix_environ.h"
#include "src/util/show_help.h"
@ -87,6 +88,14 @@ static void server_message_handler(struct pmix_peer_t *pr,
pmix_ptl_hdr_t *hdr,
pmix_buffer_t *buf, void *cbdata);
static void iof_eviction_cbfunc(struct pmix_hotel_t *hotel,
int room_num,
void *occupant)
{
pmix_setup_caddy_t *cache = (pmix_setup_caddy_t*)occupant;
PMIX_RELEASE(cache);
}
PMIX_EXPORT pmix_status_t PMIx_server_init(pmix_server_module_t *module,
pmix_info_t info[], size_t ninfo)
{
@ -129,6 +138,15 @@ PMIX_EXPORT pmix_status_t PMIx_server_init(pmix_server_module_t *module,
PMIX_CONSTRUCT(&pmix_server_globals.events, pmix_list_t);
PMIX_CONSTRUCT(&pmix_server_globals.local_reqs, pmix_list_t);
PMIX_CONSTRUCT(&pmix_server_globals.nspaces, pmix_list_t);
PMIX_CONSTRUCT(&pmix_server_globals.iof, pmix_hotel_t);
rc = pmix_hotel_init(&pmix_server_globals.iof, PMIX_IOF_HOTEL_SIZE,
pmix_globals.evbase, PMIX_IOF_MAX_STAY,
iof_eviction_cbfunc);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE_THREAD(&pmix_global_lock);
return rc;
}
pmix_output_verbose(2, pmix_server_globals.base_output,
"pmix:server init called");
@ -170,6 +188,12 @@ PMIX_EXPORT pmix_status_t PMIx_server_init(pmix_server_module_t *module,
pmix_output_set_verbosity(pmix_server_globals.event_output,
pmix_server_globals.event_verbose);
}
if (0 < pmix_server_globals.iof_verbose) {
/* set default output */
pmix_server_globals.iof_output = pmix_output_open(NULL);
pmix_output_set_verbosity(pmix_server_globals.iof_output,
pmix_server_globals.iof_verbose);
}
/* setup the base verbosity */
if (0 < pmix_server_globals.base_verbose) {
/* set default output */
@ -347,6 +371,7 @@ PMIX_EXPORT pmix_status_t PMIx_server_finalize(void)
int i;
pmix_peer_t *peer;
pmix_nspace_t *ns;
pmix_setup_caddy_t *cd;
PMIX_ACQUIRE_THREAD(&pmix_global_lock);
if (pmix_globals.init_cntr <= 0) {
@ -374,6 +399,14 @@ PMIX_EXPORT pmix_status_t PMIx_server_finalize(void)
pmix_ptl_base_stop_listening();
/* cleanout any IOF */
for (i=0; i < PMIX_IOF_HOTEL_SIZE; i++) {
pmix_hotel_checkout_and_return_occupant(&pmix_server_globals.iof, i, (void**)&cd);
if (NULL != cd) {
PMIX_RELEASE(cd);
}
}
PMIX_DESTRUCT(&pmix_server_globals.iof);
for (i=0; i < pmix_server_globals.clients.size; i++) {
if (NULL != (peer = (pmix_peer_t*)pmix_pointer_array_get_item(&pmix_server_globals.clients, i))) {
/* ensure that we do the specified cleanup - if this is an
@ -1298,19 +1331,20 @@ static void _setup_op(pmix_status_t rc, void *cbdata)
static void _setup_app(int sd, short args, void *cbdata)
{
pmix_setup_caddy_t *cd = (pmix_setup_caddy_t*)cbdata;
pmix_buffer_t buffer;
pmix_byte_object_t blob;
pmix_setup_caddy_t *fcd = NULL;
pmix_status_t rc;
pmix_list_t ilist;
pmix_kval_t *kv;
size_t n;
PMIX_ACQUIRE_OBJECT(cd);
PMIX_CONSTRUCT(&ilist, pmix_list_t);
/* pass to the network libraries */
if (PMIX_SUCCESS != (rc = pmix_pnet.setup_app(cd->nspace, &ilist))) {
if (PMIX_SUCCESS != (rc = pmix_pnet.setup_app(cd->nspace,
cd->info, cd->ninfo,
&ilist))) {
goto depart;
}
@ -1322,29 +1356,20 @@ static void _setup_app(int sd, short args, void *cbdata)
goto depart;
}
/* if anything came back, construct the blob */
if (0 < pmix_list_get_size(&ilist)) {
PMIX_CONSTRUCT(&buffer, pmix_buffer_t);
PMIX_LIST_FOREACH(kv, &ilist, pmix_kval_t) {
PMIX_BFROPS_PACK(rc, pmix_globals.mypeer, &buffer, kv, 1, PMIX_KVAL);
if (PMIX_SUCCESS != rc) {
PMIX_RELEASE(fcd);
fcd = NULL;
goto depart;
}
}
PMIX_INFO_CREATE(fcd->info, 1);
/* if anything came back, construct an info array */
if (0 < (fcd->ninfo = pmix_list_get_size(&ilist))) {
PMIX_INFO_CREATE(fcd->info, fcd->ninfo);
if (NULL == fcd->info) {
rc = PMIX_ERR_NOMEM;
PMIX_RELEASE(fcd);
fcd = NULL;
goto depart;
}
fcd->ninfo = 1;
PMIX_BYTE_OBJECT_CONSTRUCT(&blob);
PMIX_BYTE_OBJECT_LOAD(&blob, buffer.base_ptr, buffer.bytes_used);
PMIX_DESTRUCT(&buffer);
PMIX_INFO_LOAD(&fcd->info[0], PMIX_PNET_SETUP_APP, &blob, PMIX_BYTE_OBJECT);
PMIX_BYTE_OBJECT_DESTRUCT(&blob);
n = 0;
PMIX_LIST_FOREACH(kv, &ilist, pmix_kval_t) {
(void)strncpy(fcd->info[n].key, kv->key, PMIX_MAX_KEYLEN);
pmix_value_xfer(&fcd->info[n].value, kv->value);
++n;
}
}
depart:
@ -1446,6 +1471,148 @@ pmix_status_t PMIx_server_setup_local_support(const char nspace[],
return PMIX_SUCCESS;
}
static void _iofdeliver(int sd, short args, void *cbdata)
{
pmix_setup_caddy_t *cd = (pmix_setup_caddy_t*)cbdata;
pmix_iof_req_t *req;
pmix_status_t rc;
pmix_buffer_t *msg;
bool found = false;
bool cached = false;
int ignore;
pmix_output_verbose(2, pmix_server_globals.iof_output,
"PMIX:SERVER delivering IOF");
/* cycle across our list of IOF requestors and see who wants
* this channel from this source */
PMIX_LIST_FOREACH(req, &pmix_globals.iof_requests, pmix_iof_req_t) {
/* if the channel wasn't included, then ignore it */
if (!(cd->channels & req->channels)) {
continue;
}
/* if the source matches the request, then forward this along */
if (0 != strncmp(cd->procs->nspace, req->pname.nspace, PMIX_MAX_NSLEN) ||
(PMIX_RANK_WILDCARD != req->pname.rank && cd->procs->rank != req->pname.rank)) {
continue;
}
found = true;
/* setup the msg */
if (NULL == (msg = PMIX_NEW(pmix_buffer_t))) {
PMIX_ERROR_LOG(PMIX_ERR_OUT_OF_RESOURCE);
rc = PMIX_ERR_OUT_OF_RESOURCE;
break;
}
/* provide the source */
PMIX_BFROPS_PACK(rc, req->peer, msg, cd->procs, 1, PMIX_PROC);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
break;
}
/* provide the channel */
PMIX_BFROPS_PACK(rc, req->peer, msg, &cd->channels, 1, PMIX_IOF_CHANNEL);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
break;
}
/* pack the data */
PMIX_BFROPS_PACK(rc, req->peer, msg, cd->bo, 1, PMIX_BYTE_OBJECT);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
break;
}
/* send it to the requestor */
PMIX_PTL_SEND_ONEWAY(rc, req->peer, msg, PMIX_PTL_TAG_IOF);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
}
}
/* if nobody has registered for this yet, then cache it */
if (!found) {
/* add this output to our hotel so it is cached until someone
* registers to receive it */
if (PMIX_SUCCESS != (rc = pmix_hotel_checkin(&pmix_server_globals.iof, cd, &ignore))) {
/* we can't cache it for some reason */
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(cd);
return;
}
cached = true;
}
if (NULL != cd->opcbfunc) {
cd->opcbfunc(rc, cd->cbdata);
}
if (!cached) {
if (NULL != cd->info) {
PMIX_INFO_FREE(cd->info, cd->ninfo);
}
PMIX_PROC_FREE(cd->procs, 1);
PMIX_BYTE_OBJECT_FREE(cd->bo, 1);
PMIX_RELEASE(cd);
}
}
pmix_status_t PMIx_server_IOF_deliver(const pmix_proc_t *source,
pmix_iof_channel_t channel,
const pmix_byte_object_t *bo,
const pmix_info_t info[], size_t ninfo,
pmix_op_cbfunc_t cbfunc, void *cbdata)
{
pmix_setup_caddy_t *cd;
size_t n;
/* need to threadshift this request */
cd = PMIX_NEW(pmix_setup_caddy_t);
if (NULL == cd) {
return PMIX_ERR_NOMEM;
}
/* unfortunately, we need to copy the input because we
* might have to cache it for later delivery */
PMIX_PROC_CREATE(cd->procs, 1);
if (NULL == cd->procs) {
PMIX_RELEASE(cd);
return PMIX_ERR_NOMEM;
}
(void)strncpy(cd->procs[0].nspace, source->nspace, PMIX_MAX_NSLEN);
cd->procs[0].rank = source->rank;
cd->channels = channel;
PMIX_BYTE_OBJECT_CREATE(cd->bo, 1);
if (NULL == cd->bo) {
PMIX_RELEASE(cd);
return PMIX_ERR_NOMEM;
}
cd->bo[0].bytes = (char*)malloc(bo->size);
if (NULL == cd->bo[0].bytes) {
PMIX_BYTE_OBJECT_FREE(cd->bo, 1);
PMIX_RELEASE(cd);
return PMIX_ERR_NOMEM;
}
memcpy(cd->bo[0].bytes, bo->bytes, bo->size);
cd->bo[0].size = bo->size;
if (0 < ninfo) {
PMIX_INFO_CREATE(cd->info, ninfo);
if (NULL == cd->info) {
PMIX_BYTE_OBJECT_FREE(cd->bo, 1);
PMIX_RELEASE(cd);
return PMIX_ERR_NOMEM;
}
cd->ninfo = ninfo;
for (n=0; n < ninfo; n++) {
PMIX_INFO_XFER(&cd->info[n], (pmix_info_t*)&info[n]);
}
}
cd->opcbfunc = cbfunc;
cd->cbdata = cbdata;
PMIX_THREADSHIFT(cd, _iofdeliver);
return PMIX_SUCCESS;
}
/**** THE FOLLOWING CALLBACK FUNCTIONS ARE USED BY THE HOST SERVER ****
**** THEY THEREFORE CAN OCCUR IN EITHER THE HOST SERVER'S THREAD ****
@ -2357,6 +2524,69 @@ static void validate_cbfunc(pmix_status_t status,
}
static void _iofreg(int sd, short args, void *cbdata)
{
pmix_setup_caddy_t *cd = (pmix_setup_caddy_t*)cbdata;
pmix_server_caddy_t *scd = (pmix_server_caddy_t*)cd->cbdata;
pmix_buffer_t *reply;
pmix_status_t rc;
PMIX_ACQUIRE_OBJECT(cd);
/* setup the reply to the requestor */
reply = PMIX_NEW(pmix_buffer_t);
if (NULL == reply) {
PMIX_ERROR_LOG(PMIX_ERR_NOMEM);
rc = PMIX_ERR_NOMEM;
goto cleanup;
}
/* start with the status */
PMIX_BFROPS_PACK(rc, scd->peer, reply, &cd->status, 1, PMIX_STATUS);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(reply);
goto cleanup;
}
/* was the request a success? */
if (PMIX_SUCCESS != cd->status) {
/* find and remove the tracker(s) */
}
pmix_output_verbose(2, pmix_server_globals.iof_output,
"server:_iofreg reply being sent to %s:%u",
scd->peer->info->pname.nspace, scd->peer->info->pname.rank);
PMIX_SERVER_QUEUE_REPLY(scd->peer, scd->hdr.tag, reply);
cleanup:
/* release the cached info */
if (NULL != cd->procs) {
PMIX_PROC_FREE(cd->procs, cd->nprocs);
}
PMIX_INFO_FREE(cd->info, cd->ninfo);
/* we are done */
PMIX_RELEASE(cd);
}
static void iof_cbfunc(pmix_status_t status,
void *cbdata)
{
pmix_setup_caddy_t *cd = (pmix_setup_caddy_t*)cbdata;
pmix_output_verbose(2, pmix_server_globals.iof_output,
"server:iof_cbfunc called with status %d",
status);
if (NULL == cd) {
/* nothing to do */
return;
}
cd->status = status;
/* need to thread-shift this callback as it accesses global data */
PMIX_THREADSHIFT(cd, _iofreg);
}
/* the switchyard is the primary message handling function. It's purpose
* is to take incoming commands (packed into a buffer), unpack them,
* and then call the corresponding host server's function to execute
@ -2608,6 +2838,18 @@ static pmix_status_t server_switchyard(pmix_peer_t *peer, uint32_t tag,
return rc;
}
if (PMIX_IOF_PULL_CMD == cmd) {
PMIX_GDS_CADDY(cd, peer, tag);
rc = pmix_server_iofreg(peer, buf, iof_cbfunc, cd);
return rc;
}
if (PMIX_IOF_PUSH_CMD == cmd) {
PMIX_GDS_CADDY(cd, peer, tag);
rc = pmix_server_iofstdin(peer, buf, op_cbfunc, cd);
return rc;
}
return PMIX_ERR_NOT_SUPPORTED;
}

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

@ -48,6 +48,7 @@
#endif
#include PMIX_EVENT_HEADER
#include "src/class/pmix_hotel.h"
#include "src/class/pmix_list.h"
#include "src/mca/bfrops/bfrops.h"
#include "src/util/argv.h"
@ -1025,7 +1026,76 @@ static void spcbfunc(pmix_status_t status,
char nspace[], void *cbdata)
{
pmix_setup_caddy_t *cd = (pmix_setup_caddy_t*)cbdata;
pmix_iof_req_t *req;
pmix_setup_caddy_t *occupant;
int i;
pmix_buffer_t *msg;
pmix_status_t rc;
/* if it was successful, and there are IOF requests, then
* register them now */
if (PMIX_SUCCESS == status && PMIX_FWD_NO_CHANNELS != cd->channels) {
/* record the request */
req = PMIX_NEW(pmix_iof_req_t);
if (NULL != req) {
PMIX_RETAIN(cd->peer);
req->peer = cd->peer;
req->pname.nspace = strdup(nspace);
req->pname.rank = PMIX_RANK_WILDCARD;
req->channels = cd->channels;
pmix_list_append(&pmix_globals.iof_requests, &req->super);
}
/* process any cached IO */
for (i=0; i < PMIX_IOF_HOTEL_SIZE; i++) {
pmix_hotel_knock(&pmix_server_globals.iof, PMIX_IOF_HOTEL_SIZE-i-1, (void**)&occupant);
if (NULL != occupant) {
if (!(occupant->channels & req->channels)) {
continue;
}
/* if the source matches the request, then forward this along */
if (0 != strncmp(occupant->procs->nspace, req->pname.nspace, PMIX_MAX_NSLEN) ||
(PMIX_RANK_WILDCARD != req->pname.rank && occupant->procs->rank != req->pname.rank)) {
continue;
}
/* setup the msg */
if (NULL == (msg = PMIX_NEW(pmix_buffer_t))) {
PMIX_ERROR_LOG(PMIX_ERR_OUT_OF_RESOURCE);
rc = PMIX_ERR_OUT_OF_RESOURCE;
break;
}
/* provide the source */
PMIX_BFROPS_PACK(rc, req->peer, msg, occupant->procs, 1, PMIX_PROC);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
break;
}
/* provide the channel */
PMIX_BFROPS_PACK(rc, req->peer, msg, &occupant->channels, 1, PMIX_IOF_CHANNEL);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
break;
}
/* pack the data */
PMIX_BFROPS_PACK(rc, req->peer, msg, occupant->bo, 1, PMIX_BYTE_OBJECT);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
break;
}
/* send it to the requestor */
PMIX_PTL_SEND_ONEWAY(rc, req->peer, msg, PMIX_PTL_TAG_IOF);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
}
/* remove it from the hotel since it has now been forwarded */
pmix_hotel_checkout(&pmix_server_globals.iof, PMIX_IOF_HOTEL_SIZE-i-1);
PMIX_RELEASE(occupant);
}
}
}
/* cleanup the caddy */
if (NULL != cd->info) {
PMIX_INFO_FREE(cd->info, cd->ninfo);
@ -1048,7 +1118,8 @@ pmix_status_t pmix_server_spawn(pmix_peer_t *peer,
int32_t cnt;
pmix_status_t rc;
pmix_proc_t proc;
size_t ninfo;
size_t ninfo, n;
bool stdout_found = false, stderr_found = false, stddiag_found = false;
pmix_output_verbose(2, pmix_server_globals.spawn_output,
"recvd SPAWN");
@ -1063,6 +1134,8 @@ pmix_status_t pmix_server_spawn(pmix_peer_t *peer,
if (NULL == cd) {
return PMIX_ERR_NOMEM;
}
PMIX_RETAIN(peer);
cd->peer = peer;
cd->spcbfunc = cbfunc;
cd->cbdata = cbdata;
@ -1091,10 +1164,48 @@ pmix_status_t pmix_server_spawn(pmix_peer_t *peer,
PMIX_ERROR_LOG(rc);
goto cleanup;
}
/* run a quick check of the directives to see if any IOF
* requests were included so we can set that up now - helps
* to catch any early output */
cd->channels = PMIX_FWD_NO_CHANNELS;
for (n=0; n < cd->ninfo; n++) {
if (0 == strncmp(cd->info[n].key, PMIX_FWD_STDIN, PMIX_MAX_KEYLEN)) {
stdout_found = true;
if (PMIX_INFO_TRUE(&cd->info[n])) {
cd->channels |= PMIX_FWD_STDIN_CHANNEL;
}
} else if (0 == strncmp(cd->info[n].key, PMIX_FWD_STDOUT, PMIX_MAX_KEYLEN)) {
if (PMIX_INFO_TRUE(&cd->info[n])) {
cd->channels |= PMIX_FWD_STDOUT_CHANNEL;
}
} else if (0 == strncmp(cd->info[n].key, PMIX_FWD_STDERR, PMIX_MAX_KEYLEN)) {
stderr_found = true;
if (PMIX_INFO_TRUE(&cd->info[n])) {
cd->channels |= PMIX_FWD_STDERR_CHANNEL;
}
} else if (0 == strncmp(cd->info[n].key, PMIX_FWD_STDDIAG, PMIX_MAX_KEYLEN)) {
stddiag_found = true;
if (PMIX_INFO_TRUE(&cd->info[n])) {
cd->channels |= PMIX_FWD_STDDIAG_CHANNEL;
}
}
}
/* we will construct any required iof request tracker upon completion of the spawn */
}
/* add the directive to the end */
if (PMIX_PROC_IS_TOOL(peer)) {
PMIX_INFO_LOAD(&cd->info[ninfo], PMIX_REQUESTOR_IS_TOOL, NULL, PMIX_BOOL);
/* if the requestor is a tool, we default to forwarding all
* output IO channels */
if (!stdout_found) {
cd->channels |= PMIX_FWD_STDOUT_CHANNEL;
}
if (!stderr_found) {
cd->channels |= PMIX_FWD_STDERR_CHANNEL;
}
if (!stddiag_found) {
cd->channels |= PMIX_FWD_STDDIAG_CHANNEL;
}
} else {
PMIX_INFO_LOAD(&cd->info[ninfo], PMIX_REQUESTOR_IS_CLIENT, NULL, PMIX_BOOL);
}
@ -2542,6 +2653,296 @@ pmix_status_t pmix_server_validate_credential(pmix_peer_t *peer,
return rc;
}
pmix_status_t pmix_server_iofreg(pmix_peer_t *peer,
pmix_buffer_t *buf,
pmix_op_cbfunc_t cbfunc,
void *cbdata)
{
int32_t cnt;
pmix_status_t rc;
pmix_setup_caddy_t *cd;
pmix_iof_req_t *req;
bool notify, match;
size_t n;
int i;
pmix_setup_caddy_t *occupant;
pmix_buffer_t *msg;
pmix_output_verbose(2, pmix_server_globals.iof_output,
"recvd IOF PULL request from client");
if (NULL == pmix_host_server.iof_pull) {
return PMIX_ERR_NOT_SUPPORTED;
}
cd = PMIX_NEW(pmix_setup_caddy_t);
if (NULL == cd) {
return PMIX_ERR_NOMEM;
}
cd->cbdata = cbdata; // this is the pmix_server_caddy_t
/* unpack the number of procs */
cnt = 1;
PMIX_BFROPS_UNPACK(rc, peer, buf, &cd->nprocs, &cnt, PMIX_SIZE);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto exit;
}
/* unpack the procs */
if (0 < cd->nprocs) {
PMIX_PROC_CREATE(cd->procs, cd->nprocs);
cnt = cd->nprocs;
PMIX_BFROPS_UNPACK(rc, peer, buf, cd->procs, &cnt, PMIX_PROC);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto exit;
}
}
/* unpack the number of directives */
cnt = 1;
PMIX_BFROPS_UNPACK(rc, peer, buf, &cd->ninfo, &cnt, PMIX_SIZE);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto exit;
}
/* unpack the directives */
if (0 < cd->ninfo) {
PMIX_INFO_CREATE(cd->info, cd->ninfo);
cnt = cd->ninfo;
PMIX_BFROPS_UNPACK(rc, peer, buf, cd->info, &cnt, PMIX_INFO);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto exit;
}
}
/* unpack the channels */
cnt = 1;
PMIX_BFROPS_UNPACK(rc, peer, buf, &cd->channels, &cnt, PMIX_IOF_CHANNEL);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto exit;
}
/* check to see if we have already registered this source/channel combination */
notify = false;
for (n=0; n < cd->nprocs; n++) {
match = false;
PMIX_LIST_FOREACH(req, &pmix_globals.iof_requests, pmix_iof_req_t) {
/* is this request from the same peer? */
if (peer != req->peer) {
continue;
}
/* do we already have this source for this peer? */
if (0 == strncmp(cd->procs[n].nspace, req->pname.nspace, PMIX_MAX_NSLEN) &&
(PMIX_RANK_WILDCARD == req->pname.rank || cd->procs[n].rank == req->pname.rank)) {
match = true;
if ((req->channels & cd->channels) != cd->channels) {
/* this is a channel update */
req->channels |= cd->channels;
/* we need to notify the host */
notify = true;
}
break;
}
}
/* if we didn't find the matching entry, then add it */
if (!match) {
/* record the request */
req = PMIX_NEW(pmix_iof_req_t);
if (NULL == req) {
rc = PMIX_ERR_NOMEM;
goto exit;
}
PMIX_RETAIN(peer);
req->peer = peer;
req->pname.nspace = strdup(cd->procs[n].nspace);
req->pname.rank = cd->procs[n].rank;
req->channels = cd->channels;
pmix_list_append(&pmix_globals.iof_requests, &req->super);
}
/* process any cached IO */
for (i=0; i < PMIX_IOF_HOTEL_SIZE; i++) {
pmix_hotel_knock(&pmix_server_globals.iof, PMIX_IOF_HOTEL_SIZE-i-1, (void**)&occupant);
if (NULL != occupant) {
if (!(occupant->channels & req->channels)) {
continue;
}
/* if the source matches the request, then forward this along */
if (0 != strncmp(occupant->procs->nspace, req->pname.nspace, PMIX_MAX_NSLEN) ||
(PMIX_RANK_WILDCARD != req->pname.rank && occupant->procs->rank != req->pname.rank)) {
continue;
}
/* setup the msg */
if (NULL == (msg = PMIX_NEW(pmix_buffer_t))) {
PMIX_ERROR_LOG(PMIX_ERR_OUT_OF_RESOURCE);
rc = PMIX_ERR_OUT_OF_RESOURCE;
break;
}
/* provide the source */
PMIX_BFROPS_PACK(rc, req->peer, msg, occupant->procs, 1, PMIX_PROC);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
break;
}
/* provide the channel */
PMIX_BFROPS_PACK(rc, req->peer, msg, &occupant->channels, 1, PMIX_IOF_CHANNEL);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
break;
}
/* pack the data */
PMIX_BFROPS_PACK(rc, req->peer, msg, occupant->bo, 1, PMIX_BYTE_OBJECT);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
break;
}
/* send it to the requestor */
PMIX_PTL_SEND_ONEWAY(rc, req->peer, msg, PMIX_PTL_TAG_IOF);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
}
/* remove it from the hotel since it has now been forwarded */
pmix_hotel_checkout(&pmix_server_globals.iof, PMIX_IOF_HOTEL_SIZE-i-1);
PMIX_RELEASE(occupant);
}
}
}
if (notify) {
/* ask the host to execute the request */
if (PMIX_SUCCESS != (rc = pmix_host_server.iof_pull(cd->procs, cd->nprocs,
cd->info, cd->ninfo,
cd->channels,
cbfunc, cd))) {
goto exit;
}
}
return PMIX_SUCCESS;
exit:
PMIX_RELEASE(cd);
return rc;
}
static void stdcbfunc(pmix_status_t status, void *cbdata)
{
pmix_setup_caddy_t *cd = (pmix_setup_caddy_t*)cbdata;
if (NULL != cd->opcbfunc) {
cd->opcbfunc(status, cd->cbdata);
}
if (NULL != cd->procs) {
PMIX_PROC_FREE(cd->procs, cd->nprocs);
}
if (NULL != cd->info) {
PMIX_INFO_FREE(cd->info, cd->ninfo);
}
if (NULL != cd->bo) {
PMIX_BYTE_OBJECT_FREE(cd->bo, 1);
}
PMIX_RELEASE(cd);
}
pmix_status_t pmix_server_iofstdin(pmix_peer_t *peer,
pmix_buffer_t *buf,
pmix_op_cbfunc_t cbfunc,
void *cbdata)
{
int32_t cnt;
pmix_status_t rc;
pmix_proc_t source;
pmix_setup_caddy_t *cd;
pmix_output_verbose(2, pmix_server_globals.iof_output,
"recvd stdin IOF data from tool");
if (NULL == pmix_host_server.push_stdin) {
return PMIX_ERR_NOT_SUPPORTED;
}
cd = PMIX_NEW(pmix_setup_caddy_t);
if (NULL == cd) {
return PMIX_ERR_NOMEM;
}
cd->opcbfunc = cbfunc;
cd->cbdata = cbdata;
/* unpack the number of targets */
cnt = 1;
PMIX_BFROPS_UNPACK(rc, peer, buf, &cd->nprocs, &cnt, PMIX_SIZE);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto error;
}
if (0 < cd->nprocs) {
PMIX_PROC_CREATE(cd->procs, cd->nprocs);
if (NULL == cd->procs) {
rc = PMIX_ERR_NOMEM;
goto error;
}
cnt = cd->nprocs;
PMIX_BFROPS_UNPACK(rc, peer, buf, cd->procs, &cnt, PMIX_PROC);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto error;
}
}
/* unpack the number of directives */
cnt = 1;
PMIX_BFROPS_UNPACK(rc, peer, buf, &cd->ninfo, &cnt, PMIX_SIZE);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto error;
}
if (0 < cd->ninfo) {
PMIX_INFO_CREATE(cd->info, cd->ninfo);
if (NULL == cd->info) {
rc = PMIX_ERR_NOMEM;
goto error;
}
cnt = cd->ninfo;
PMIX_BFROPS_UNPACK(rc, peer, buf, cd->info, &cnt, PMIX_INFO);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto error;
}
}
/* unpack the data */
PMIX_BYTE_OBJECT_CREATE(cd->bo, 1);
if (NULL == cd->bo) {
rc = PMIX_ERR_NOMEM;
goto error;
}
cnt = 1;
PMIX_BFROPS_UNPACK(rc, peer, buf, cd->bo, &cnt, PMIX_BYTE_OBJECT);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto error;
}
/* pass the data to the host */
(void)strncpy(source.nspace, peer->nptr->nspace, PMIX_MAX_NSLEN);
source.rank = peer->info->pname.rank;
if (PMIX_SUCCESS != (rc = pmix_host_server.push_stdin(&source, cd->procs, cd->nprocs,
cd->info, cd->ninfo, cd->bo,
stdcbfunc, cd))) {
goto error;
}
return PMIX_SUCCESS;
error:
PMIX_RELEASE(cd);
return rc;
}
/***** INSTANCE SERVER LIBRARY CLASSES *****/
static void tcon(pmix_server_trkr_t *t)
{
@ -2603,6 +3004,7 @@ PMIX_CLASS_INSTANCE(pmix_server_caddy_t,
static void scadcon(pmix_setup_caddy_t *p)
{
p->peer = NULL;
memset(&p->proc, 0, sizeof(pmix_proc_t));
PMIX_CONSTRUCT_LOCK(&p->lock);
p->nspace = NULL;
@ -2615,6 +3017,8 @@ static void scadcon(pmix_setup_caddy_t *p)
p->info = NULL;
p->ninfo = 0;
p->keys = NULL;
p->channels = PMIX_FWD_NO_CHANNELS;
p->bo = NULL;
p->cbfunc = NULL;
p->opcbfunc = NULL;
p->setupcbfunc = NULL;
@ -2624,6 +3028,9 @@ static void scadcon(pmix_setup_caddy_t *p)
}
static void scaddes(pmix_setup_caddy_t *p)
{
if (NULL != p->peer) {
PMIX_RELEASE(p->peer);
}
PMIX_DESTRUCT_LOCK(&p->lock);
}
PMIX_EXPORT PMIX_CLASS_INSTANCE(pmix_setup_caddy_t,

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

@ -18,12 +18,15 @@
#include "src/include/types.h"
#include <pmix_common.h>
#include <src/class/pmix_ring_buffer.h>
#include <src/class/pmix_hotel.h>
#include <pmix_server.h>
#include "src/threads/threads.h"
#include "src/include/pmix_globals.h"
#include "src/util/hash.h"
#define PMIX_IOF_HOTEL_SIZE 256
#define PMIX_IOF_MAX_STAY 300000000
typedef struct {
pmix_object_t super;
pmix_event_t ev;
@ -35,6 +38,7 @@ typedef struct {
pmix_object_t super;
pmix_event_t ev;
pmix_lock_t lock;
pmix_peer_t *peer;
char *nspace;
pmix_status_t status;
pmix_status_t *codes;
@ -51,6 +55,8 @@ typedef struct {
char **keys;
pmix_app_t *apps;
size_t napps;
pmix_iof_channel_t channels;
pmix_byte_object_t *bo;
pmix_op_cbfunc_t opcbfunc;
pmix_dmodex_response_fn_t cbfunc;
pmix_setup_application_cbfunc_t setupcbfunc;
@ -96,7 +102,7 @@ PMIX_CLASS_DECLARATION(pmix_peer_events_info_t);
typedef struct {
pmix_list_item_t super;
pmix_list_t peers; // list of pmix_prevents_info_t
pmix_list_t peers; // list of pmix_peer_events_info_t
int code;
} pmix_regevents_info_t;
PMIX_CLASS_DECLARATION(pmix_regevents_info_t);
@ -109,6 +115,7 @@ typedef struct {
pmix_list_t local_reqs; // list of pmix_dmdx_local_t awaiting arrival of data from local neighbours
pmix_list_t gdata; // cache of data given to me for passing to all clients
pmix_list_t events; // list of pmix_regevents_info_t registered events
pmix_hotel_t iof; // IO to be forwarded to clients
bool tool_connections_allowed;
// verbosity for server get operations
int get_output;
@ -128,6 +135,9 @@ typedef struct {
// verbosity for server event operations
int event_output;
int event_verbose;
// verbosity for server iof operations
int iof_output;
int iof_verbose;
// verbosity for basic server functions
int base_output;
int base_verbose;
@ -256,6 +266,16 @@ pmix_status_t pmix_server_validate_credential(pmix_peer_t *peer,
pmix_validation_cbfunc_t cbfunc,
void *cbdata);
pmix_status_t pmix_server_iofreg(pmix_peer_t *peer,
pmix_buffer_t *buf,
pmix_op_cbfunc_t cbfunc,
void *cbdata);
pmix_status_t pmix_server_iofstdin(pmix_peer_t *peer,
pmix_buffer_t *buf,
pmix_op_cbfunc_t cbfunc,
void *cbdata);
pmix_status_t pmix_server_event_recvd_from_client(pmix_peer_t *peer,
pmix_buffer_t *buf,
pmix_op_cbfunc_t cbfunc,

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

@ -58,8 +58,6 @@
#ident PMIX_VERSION
#endif
extern pmix_client_globals_t pmix_client_globals;
#include "src/class/pmix_list.h"
#include "src/util/argv.h"
#include "src/util/error.h"
@ -69,12 +67,17 @@ extern pmix_client_globals_t pmix_client_globals;
#include "src/runtime/pmix_rte.h"
#include "src/mca/bfrops/base/base.h"
#include "src/mca/gds/base/base.h"
#include "src/mca/ptl/ptl.h"
#include "src/mca/ptl/base/base.h"
#include "src/mca/psec/psec.h"
#include "src/include/pmix_globals.h"
#include "src/common/pmix_iof.h"
#define PMIX_MAX_RETRIES 10
extern pmix_client_globals_t pmix_client_globals;
static pmix_event_t stdinsig;
static pmix_iof_read_event_t stdinev;
static void _notify_complete(pmix_status_t status, void *cbdata)
{
pmix_event_chain_t *chain = (pmix_event_chain_t*)cbdata;
@ -91,7 +94,7 @@ static void pmix_tool_notify_recv(struct pmix_peer_t *peer,
pmix_event_chain_t *chain;
size_t ninfo;
pmix_output_verbose(2, pmix_globals.debug_output,
pmix_output_verbose(2, pmix_client_globals.event_output,
"pmix:tool_notify_recv - processing event");
/* a zero-byte buffer indicates that this recv is being
@ -172,7 +175,7 @@ static void pmix_tool_notify_recv(struct pmix_peer_t *peer,
/* now put the callback object tag in the last element */
PMIX_INFO_LOAD(&chain->info[ninfo], PMIX_EVENT_RETURN_OBJECT, NULL, PMIX_POINTER);
pmix_output_verbose(2, pmix_globals.debug_output,
pmix_output_verbose(2, pmix_client_globals.event_output,
"[%s:%d] pmix:tool_notify_recv - processing event %d, calling errhandler",
pmix_globals.myid.nspace, pmix_globals.myid.rank, chain->status);
@ -181,7 +184,7 @@ static void pmix_tool_notify_recv(struct pmix_peer_t *peer,
error:
/* we always need to return */
pmix_output_verbose(2, pmix_globals.debug_output,
pmix_output_verbose(2, pmix_client_globals.event_output,
"pmix:tool_notify_recv - unpack error status =%d, calling def errhandler", rc);
chain = PMIX_NEW(pmix_event_chain_t);
chain->status = rc;
@ -189,6 +192,53 @@ static void pmix_tool_notify_recv(struct pmix_peer_t *peer,
}
static void tool_iof_handler(struct pmix_peer_t *pr,
pmix_ptl_hdr_t *hdr,
pmix_buffer_t *buf, void *cbdata)
{
pmix_peer_t *peer = (pmix_peer_t*)pr;
pmix_proc_t source;
pmix_iof_channel_t channel;
pmix_byte_object_t bo;
int32_t cnt;
pmix_status_t rc;
pmix_output_verbose(2, pmix_client_globals.iof_output,
"recvd IOF");
/* if the buffer is empty, they are simply closing the channel */
if (0 == buf->bytes_used) {
return;
}
cnt = 1;
PMIX_BFROPS_UNPACK(rc, peer, buf, &source, &cnt, PMIX_PROC);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
return;
}
cnt = 1;
PMIX_BFROPS_UNPACK(rc, peer, buf, &channel, &cnt, PMIX_IOF_CHANNEL);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
return;
}
cnt = 1;
PMIX_BFROPS_UNPACK(rc, peer, buf, &bo, &cnt, PMIX_BYTE_OBJECT);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
return;
}
if (NULL != bo.bytes && 0 < bo.size) {
if (channel & PMIX_FWD_STDOUT_CHANNEL) {
pmix_iof_write_output(&source, channel, &bo, &pmix_client_globals.iof_stdout.wev);
} else {
pmix_iof_write_output(&source, channel, &bo, &pmix_client_globals.iof_stderr.wev);
}
}
PMIX_BYTE_OBJECT_DESTRUCT(&bo);
}
PMIX_EXPORT int PMIx_tool_init(pmix_proc_t *proc,
pmix_info_t info[], size_t ninfo)
{
@ -198,9 +248,12 @@ PMIX_EXPORT int PMIx_tool_init(pmix_proc_t *proc,
bool found, do_not_connect = false;
bool nspace_given = false;
bool rank_given = false;
bool fwd_stdin = false;
pmix_info_t ginfo;
size_t n;
pmix_ptl_posted_recv_t *rcv;
pmix_proc_t wildcard;
int fd;
PMIX_ACQUIRE_THREAD(&pmix_global_lock);
@ -238,6 +291,13 @@ PMIX_EXPORT int PMIx_tool_init(pmix_proc_t *proc,
PMIX_RELEASE_THREAD(&pmix_global_lock);
return rc;
}
/* setup the IO Forwarding recv */
rcv = PMIX_NEW(pmix_ptl_posted_recv_t);
rcv->tag = PMIX_PTL_TAG_IOF;
rcv->cbfunc = tool_iof_handler;
/* add it to the end of the list of recvs */
pmix_list_append(&pmix_ptl_globals.posted_recvs, &rcv->super);
PMIX_CONSTRUCT(&pmix_client_globals.pending_requests, pmix_list_t);
PMIX_CONSTRUCT(&pmix_client_globals.peers, pmix_pointer_array_t);
@ -296,6 +356,9 @@ PMIX_EXPORT int PMIx_tool_init(pmix_proc_t *proc,
} else if (0 == strncmp(info[n].key, PMIX_TOOL_RANK, PMIX_MAX_KEYLEN)) {
pmix_globals.myid.rank = info[n].value.data.rank;
rank_given = true;
} else if (0 == strncmp(info[n].key, PMIX_FWD_STDIN, PMIX_MAX_KEYLEN)) {
/* they want us to forward our stdin to someone */
fwd_stdin = true;
}
}
}
@ -342,6 +405,81 @@ PMIX_EXPORT int PMIx_tool_init(pmix_proc_t *proc,
pmix_globals.mypeer->info->pname.nspace = strdup(proc->nspace);
pmix_globals.mypeer->info->pname.rank = proc->rank;
/* setup IOF */
PMIX_IOF_SINK_DEFINE(&pmix_client_globals.iof_stdout, &pmix_globals.myid,
1, PMIX_FWD_STDOUT_CHANNEL, pmix_iof_write_handler);
PMIX_IOF_SINK_DEFINE(&pmix_client_globals.iof_stderr, &pmix_globals.myid,
2, PMIX_FWD_STDERR_CHANNEL, pmix_iof_write_handler);
if (fwd_stdin) {
/* setup the read - we don't want to set nonblocking on our
* stdio stream. If we do so, we set the file descriptor to
* non-blocking for everyone that has that file descriptor, which
* includes everyone else in our shell pipeline chain. (See
* http://lists.freebsd.org/pipermail/freebsd-hackers/2005-January/009742.html).
* This causes things like "prun -np 1 big_app | cat" to lose
* output, because cat's stdout is then ALSO non-blocking and cat
* isn't built to deal with that case (same with almost all other
* unix text utils).*/
fd = fileno(stdin);
if (isatty(fd)) {
/* We should avoid trying to read from stdin if we
* have a terminal, but are backgrounded. Catch the
* signals that are commonly used when we switch
* between being backgrounded and not. If the
* filedescriptor is not a tty, don't worry about it
* and always stay connected.
*/
pmix_event_signal_set(pmix_globals.evbase, &stdinsig,
SIGCONT, pmix_iof_stdin_cb,
&stdinev);
/* setup a read event to read stdin, but don't activate it yet. The
* dst_name indicates who should receive the stdin. If that recipient
* doesn't do a corresponding pull, however, then the stdin will
* be dropped upon receipt at the local daemon
*/
PMIX_CONSTRUCT(&stdinev, pmix_iof_read_event_t);
stdinev.fd = fd;
stdinev.always_readable = pmix_iof_fd_always_ready(fd);
if (stdinev.always_readable) {
pmix_event_evtimer_set(pmix_globals.evbase,
&stdinev.ev,
pmix_iof_read_local_handler,
&stdinev);
} else {
pmix_event_set(pmix_globals.evbase,
&stdinev.ev, fd,
PMIX_EV_READ,
pmix_iof_read_local_handler, &stdinev);
} \
/* check to see if we want the stdin read event to be
* active - we will always at least define the event,
* but may delay its activation
*/
if (pmix_iof_stdin_check(fd)) {
PMIX_IOF_READ_ACTIVATE(&stdinev);
}
} else {
/* if we are not looking at a tty, just setup a read event
* and activate it
*/
PMIX_CONSTRUCT(&stdinev, pmix_iof_read_event_t);
stdinev.fd = fd;
stdinev.always_readable = pmix_iof_fd_always_ready(fd);
if (stdinev.always_readable) {
pmix_event_evtimer_set(pmix_globals.evbase,
&stdinev.ev,
pmix_iof_read_local_handler,
&stdinev);
} else {
pmix_event_set(pmix_globals.evbase,
&stdinev.ev, fd,
PMIX_EV_READ,
pmix_iof_read_local_handler, &stdinev);
} \
PMIX_IOF_READ_ACTIVATE(&stdinev);
}
}
/* increment our init reference counter */
pmix_globals.init_cntr++;
@ -721,6 +859,12 @@ PMIX_EXPORT pmix_status_t PMIx_tool_finalize(void)
pmix_output_verbose(2, pmix_globals.debug_output,
"pmix:tool finalize called");
/* flush anything that is still trying to be written out */
pmix_iof_static_dump_output(&pmix_client_globals.iof_stdout);
pmix_iof_static_dump_output(&pmix_client_globals.iof_stderr);
PMIX_DESTRUCT(&pmix_client_globals.iof_stdout);
PMIX_DESTRUCT(&pmix_client_globals.iof_stderr);
/* setup a cmd message to notify the PMIx
* server that we are normally terminating */
msg = PMIX_NEW(pmix_buffer_t);

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

@ -1,7 +1,7 @@
/*
* Copyright (c) 2008-2014 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2009 Sandia National Laboratories. All rights reserved.
* Copyright (c) 2014-2016 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$
@ -20,6 +20,12 @@
#endif
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#include "src/util/error.h"
#include "src/util/fd.h"
@ -93,3 +99,31 @@ pmix_status_t pmix_fd_set_cloexec(int fd)
return PMIX_SUCCESS;
}
bool pmix_fd_is_regular(int fd)
{
struct stat buf;
if (fstat(fd, &buf)) {
return false;
}
return S_ISREG(buf.st_mode);
}
bool pmix_fd_is_chardev(int fd)
{
struct stat buf;
if (fstat(fd, &buf)) {
return false;
}
return S_ISCHR(buf.st_mode);
}
bool pmix_fd_is_blkdev(int fd)
{
struct stat buf;
if (fstat(fd, &buf)) {
return false;
}
return S_ISBLK(buf.st_mode);
}

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

@ -1,7 +1,7 @@
/*
* Copyright (c) 2008-2014 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2009 Sandia National Laboratories. All rights reserved.
* Copyright (c) 2014-2016 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.
@ -67,6 +67,37 @@ PMIX_EXPORT pmix_status_t pmix_fd_write(int fd, int len, const void *buffer);
*/
PMIX_EXPORT pmix_status_t pmix_fd_set_cloexec(int fd);
/**
* Convenience function to check if fd point to an accessible regular file.
*
* @param fd File descriptor
*
* @returns true if "fd" points to a regular file.
* @returns false otherwise.
*/
PMIX_EXPORT bool pmix_fd_is_regular(int fd);
/**
* Convenience function to check if fd point to an accessible character device.
*
* @param fd File descriptor
*
* @returns true if "fd" points to a regular file.
* @returns false otherwise.
*/
PMIX_EXPORT bool pmix_fd_is_chardev(int fd);
/**
* Convenience function to check if fd point to an accessible block device.
*
* @param fd File descriptor
*
* @returns true if "fd" points to a regular file.
* @returns false otherwise.
*/
PMIX_EXPORT bool pmix_fd_is_blkdev(int fd);
END_C_DECLS
#endif

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

@ -120,7 +120,9 @@ const opal_pmix_base_module_t opal_pmix_pmix3x_module = {
.server_setup_fork = pmix3x_server_setup_fork,
.server_dmodex_request = pmix3x_server_dmodex,
.server_notify_event = pmix3x_server_notify_event,
.server_iof_push = NULL, //pmix3x_server_iof_push,
.server_iof_push = pmix3x_server_iof_push,
.server_setup_application = pmix3x_server_setup_application,
.server_setup_local_support = pmix3x_server_setup_local_support,
/* tool APIs */
.tool_init = pmix3x_tool_init,
.tool_finalize = pmix3x_tool_fini,
@ -514,6 +516,9 @@ pmix_status_t pmix3x_convert_opalrc(int rc)
case OPAL_ERR_MODEL_DECLARED:
return PMIX_MODEL_DECLARED;
case OPAL_PMIX_LAUNCH_DIRECTIVE:
return PMIX_LAUNCH_DIRECTIVE;
case OPAL_ERROR:
return PMIX_ERROR;
case OPAL_SUCCESS:
@ -607,6 +612,8 @@ int pmix3x_convert_rc(pmix_status_t rc)
case PMIX_MODEL_DECLARED:
return OPAL_ERR_MODEL_DECLARED;
case PMIX_LAUNCH_DIRECTIVE:
return OPAL_PMIX_LAUNCH_DIRECTIVE;
case PMIX_ERROR:
return OPAL_ERROR;
@ -902,7 +909,9 @@ void pmix3x_value_load(pmix_value_t *v,
v->data.darray->array = info;
n=0;
OPAL_LIST_FOREACH(val, list, opal_value_t) {
(void)strncpy(info[n].key, val->key, PMIX_MAX_KEYLEN);
if (NULL != val->key) {
(void)strncpy(info[n].key, val->key, PMIX_MAX_KEYLEN);
}
pmix3x_value_load(&info[n].value, val);
++n;
}
@ -910,6 +919,43 @@ void pmix3x_value_load(pmix_value_t *v,
v->data.darray->array = NULL;
}
break;
case OPAL_PROC_INFO:
v->type = PMIX_PROC_INFO;
PMIX_PROC_INFO_CREATE(v->data.pinfo, 1);
/* see if this job is in our list of known nspaces */
found = false;
OPAL_LIST_FOREACH(job, &mca_pmix_pmix3x_component.jobids, opal_pmix3x_jobid_trkr_t) {
if (job->jobid == kv->data.pinfo.name.jobid) {
(void)strncpy(v->data.pinfo->proc.nspace, job->nspace, PMIX_MAX_NSLEN);
found = true;
break;
}
}
if (!found) {
(void)opal_snprintf_jobid(v->data.pinfo->proc.nspace, PMIX_MAX_NSLEN, kv->data.pinfo.name.jobid);
}
v->data.pinfo->proc.rank = pmix3x_convert_opalrank(kv->data.pinfo.name.vpid);
if (NULL != kv->data.pinfo.hostname) {
v->data.pinfo->hostname = strdup(kv->data.pinfo.hostname);
}
if (NULL != kv->data.pinfo.executable_name) {
v->data.pinfo->executable_name = strdup(kv->data.pinfo.executable_name);
}
v->data.pinfo->pid = kv->data.pinfo.pid;
v->data.pinfo->exit_code = kv->data.pinfo.exit_code;
v->data.pinfo->state = pmix3x_convert_opalstate(kv->data.pinfo.state);
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 +963,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;
@ -1081,7 +1127,9 @@ int pmix3x_value_unload(opal_value_t *kv,
/* handle the various types */
if (PMIX_INFO == v->data.darray->type) {
pmix_info_t *iptr = (pmix_info_t*)v->data.darray->array;
ival->key = strdup(iptr[n].key);
if (NULL != iptr[n].key) {
ival->key = strdup(iptr[n].key);
}
rc = pmix3x_value_unload(ival, &iptr[n].value);
if (OPAL_SUCCESS != rc) {
OPAL_LIST_RELEASE(lt);
@ -1092,6 +1140,48 @@ int pmix3x_value_unload(opal_value_t *kv,
}
}
break;
case PMIX_PROC_INFO:
kv->type = OPAL_PROC_INFO;
if (NULL == v->data.pinfo) {
rc = OPAL_ERR_BAD_PARAM;
break;
}
/* see if this job is in our list of known nspaces */
found = false;
OPAL_LIST_FOREACH(job, &mca_pmix_pmix3x_component.jobids, opal_pmix3x_jobid_trkr_t) {
if (0 == strncmp(job->nspace, v->data.pinfo->proc.nspace, PMIX_MAX_NSLEN)) {
kv->data.pinfo.name.jobid = job->jobid;
found = true;
break;
}
}
if (!found) {
if (OPAL_SUCCESS != (rc = opal_convert_string_to_jobid(&kv->data.pinfo.name.jobid, v->data.pinfo->proc.nspace))) {
return pmix3x_convert_opalrc(rc);
}
}
kv->data.pinfo.name.vpid = pmix3x_convert_rank(v->data.pinfo->proc.rank);
if (NULL != v->data.pinfo->hostname) {
kv->data.pinfo.hostname = strdup(v->data.pinfo->hostname);
}
if (NULL != v->data.pinfo->executable_name) {
kv->data.pinfo.executable_name = strdup(v->data.pinfo->executable_name);
}
kv->data.pinfo.pid = v->data.pinfo->pid;
kv->data.pinfo.exit_code = v->data.pinfo->exit_code;
kv->data.pinfo.state = pmix3x_convert_state(v->data.pinfo->state);
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;
@ -1318,6 +1408,7 @@ static void infocbfunc(pmix_status_t status,
opal_list_append(results, &iptr->super);
iptr->key = strdup(info[n].key);
if (OPAL_SUCCESS != (rc = pmix3x_value_unload(iptr, &info[n].value))) {
OPAL_ERROR_LOG(rc);
OPAL_LIST_RELEASE(results);
results = NULL;
break;
@ -1481,6 +1572,103 @@ opal_pmix_alloc_directive_t pmix3x_convert_allocdir(pmix_alloc_directive_t dir)
}
}
int pmix3x_convert_state(pmix_proc_state_t state)
{
switch(state) {
case PMIX_PROC_STATE_UNDEF:
return 0;
case PMIX_PROC_STATE_PREPPED:
case PMIX_PROC_STATE_LAUNCH_UNDERWAY:
return 1;
case PMIX_PROC_STATE_RESTART:
return 2;
case PMIX_PROC_STATE_TERMINATE:
return 3;
case PMIX_PROC_STATE_RUNNING:
return 4;
case PMIX_PROC_STATE_CONNECTED:
return 5;
case PMIX_PROC_STATE_UNTERMINATED:
return 15;
case PMIX_PROC_STATE_TERMINATED:
return 20;
case PMIX_PROC_STATE_KILLED_BY_CMD:
return 51;
case PMIX_PROC_STATE_ABORTED:
return 52;
case PMIX_PROC_STATE_FAILED_TO_START:
return 53;
case PMIX_PROC_STATE_ABORTED_BY_SIG:
return 54;
case PMIX_PROC_STATE_TERM_WO_SYNC:
return 55;
case PMIX_PROC_STATE_COMM_FAILED:
return 56;
case PMIX_PROC_STATE_SENSOR_BOUND_EXCEEDED:
return 57;
case PMIX_PROC_STATE_CALLED_ABORT:
return 58;
case PMIX_PROC_STATE_HEARTBEAT_FAILED:
return 59;
case PMIX_PROC_STATE_MIGRATING:
return 60;
case PMIX_PROC_STATE_CANNOT_RESTART:
return 61;
case PMIX_PROC_STATE_TERM_NON_ZERO:
return 62;
case PMIX_PROC_STATE_FAILED_TO_LAUNCH:
return 63;
default:
return 0; // undef
}
}
pmix_proc_state_t pmix3x_convert_opalstate(int state)
{
switch(state) {
case 0:
return PMIX_PROC_STATE_UNDEF;
case 1:
return PMIX_PROC_STATE_LAUNCH_UNDERWAY;
case 2:
return PMIX_PROC_STATE_RESTART;
case 3:
return PMIX_PROC_STATE_TERMINATE;
case 4:
return PMIX_PROC_STATE_RUNNING;
case 5:
return PMIX_PROC_STATE_CONNECTED;
case 51:
return PMIX_PROC_STATE_KILLED_BY_CMD;
case 52:
return PMIX_PROC_STATE_ABORTED;
case 53:
return PMIX_PROC_STATE_FAILED_TO_START;
case 54:
return PMIX_PROC_STATE_ABORTED_BY_SIG;
case 55:
return PMIX_PROC_STATE_TERM_WO_SYNC;
case 56:
return PMIX_PROC_STATE_COMM_FAILED;
case 57:
return PMIX_PROC_STATE_SENSOR_BOUND_EXCEEDED;
case 58:
return PMIX_PROC_STATE_CALLED_ABORT;
case 59:
return PMIX_PROC_STATE_HEARTBEAT_FAILED;
case 60:
return PMIX_PROC_STATE_MIGRATING;
case 61:
return PMIX_PROC_STATE_CANNOT_RESTART;
case 62:
return PMIX_PROC_STATE_TERM_NON_ZERO;
case 63:
return PMIX_PROC_STATE_FAILED_TO_LAUNCH;
default:
return PMIX_PROC_STATE_UNDEF;
}
}
/**** INSTANTIATE INTERNAL CLASSES ****/
OBJ_CLASS_INSTANCE(opal_pmix3x_jobid_trkr_t,
opal_list_item_t,

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

@ -109,6 +109,7 @@ typedef struct {
opal_pmix_spawn_cbfunc_t spcbfunc;
opal_pmix_evhandler_reg_cbfunc_t evregcbfunc;
opal_pmix_info_cbfunc_t qcbfunc;
opal_pmix_setup_application_cbfunc_t setupcbfunc;
void *cbdata;
} pmix3x_opcaddy_t;
OBJ_CLASS_DECLARATION(pmix3x_opcaddy_t);
@ -297,11 +298,16 @@ OPAL_MODULE_DECLSPEC int pmix3x_server_notify_event(int status,
opal_list_t *info,
opal_pmix_op_cbfunc_t cbfunc, void *cbdata);
#if 0
OPAL_MODULE_DECLSPEC int pmix3x_server_iof_push(const opal_process_name_t *source,
opal_pmix_iof_channel_t channel,
unsigned char *data, size_t nbytes);
#endif
OPAL_MODULE_DECLSPEC int pmix3x_server_setup_application(opal_jobid_t jobid,
opal_list_t *info,
opal_pmix_setup_application_cbfunc_t cbfunc, void *cbdata);
OPAL_MODULE_DECLSPEC int pmix3x_server_setup_local_support(opal_jobid_t jobid,
opal_list_t *info,
opal_pmix_op_cbfunc_t cbfunc, void *cbdata);
/**** COMPONENT UTILITY FUNCTIONS ****/
OPAL_MODULE_DECLSPEC int opal_pmix_pmix3x_check_evars(void);
@ -336,6 +342,11 @@ OPAL_MODULE_DECLSPEC opal_pmix_alloc_directive_t pmix3x_convert_allocdir(pmix_al
OPAL_MODULE_DECLSPEC char* pmix3x_convert_jobid(opal_jobid_t jobid);
OPAL_MODULE_DECLSPEC int pmix3x_convert_state(pmix_proc_state_t state);
OPAL_MODULE_DECLSPEC pmix_proc_state_t pmix3x_convert_opalstate(int state);
END_C_DECLS
#endif /* MCA_PMIX_EXTERNAL_H */

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

@ -1,6 +1,6 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* 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 (c) 2014-2015 Mellanox Technologies, Inc.
@ -111,6 +111,15 @@ static pmix_status_t server_job_control(const pmix_proc_t *requestor,
const pmix_proc_t targets[], size_t ntargets,
const pmix_info_t directives[], size_t ndirs,
pmix_info_cbfunc_t cbfunc, void *cbdata);
static pmix_status_t server_iof_pull(const pmix_proc_t procs[], size_t nprocs,
const pmix_info_t directives[], size_t ndirs,
pmix_iof_channel_t channels,
pmix_op_cbfunc_t cbfunc, void *cbdata);
static pmix_status_t server_stdin(const pmix_proc_t *source,
const pmix_proc_t targets[], size_t ntargets,
const pmix_info_t directives[], size_t ndirs,
const pmix_byte_object_t *bo,
pmix_op_cbfunc_t cbfunc, void *cbdata);
pmix_server_module_t mymodule = {
.client_connected = server_client_connected_fn,
@ -131,9 +140,11 @@ pmix_server_module_t mymodule = {
.tool_connected = server_tool_connection,
.log = server_log,
.allocate = server_allocate,
.job_control = server_job_control
.job_control = server_job_control,
/* we do not support monitoring, but use the
* PMIx internal monitoring capability */
.iof_pull = server_iof_pull,
.push_stdin = server_stdin
};
opal_pmix_server_module_t *host_module = NULL;
@ -943,6 +954,7 @@ static void info_cbfunc(int status,
OPAL_LIST_FOREACH(kv, info, opal_value_t) {
(void)strncpy(pcaddy->info[n].key, kv->key, PMIX_MAX_KEYLEN);
pmix3x_value_load(&pcaddy->info[n].value, kv);
++n;
}
}
/* we are done with the incoming data */
@ -1001,10 +1013,20 @@ static pmix_status_t server_query(pmix_proc_t *proct,
for (m=0; m < queries[n].nqual; m++) {
oinfo = OBJ_NEW(opal_value_t);
opal_list_append(&q->qualifiers, &oinfo->super);
oinfo->key = strdup(queries[n].qualifiers[m].key);
if (OPAL_SUCCESS != (rc = pmix3x_value_unload(oinfo, &queries[n].qualifiers[m].value))) {
OBJ_RELEASE(opalcaddy);
return pmix3x_convert_opalrc(rc);
if (0 == strcmp(queries[n].qualifiers[m].key, PMIX_NSPACE)) {
/* must convert this to jobid */
oinfo->key = strdup(OPAL_PMIX_PROCID);
if (OPAL_SUCCESS != (rc = opal_convert_string_to_jobid(&oinfo->data.name.jobid, queries[n].qualifiers[m].value.data.string))) {
OBJ_RELEASE(opalcaddy);
return pmix3x_convert_opalrc(rc);
}
} else {
oinfo->key = strdup(queries[n].qualifiers[m].key);
if (OPAL_SUCCESS != (rc = pmix3x_value_unload(oinfo, &queries[n].qualifiers[m].value))) {
OBJ_RELEASE(opalcaddy);
return pmix3x_convert_opalrc(rc);
}
}
}
}
@ -1274,3 +1296,26 @@ static pmix_status_t server_job_control(const pmix_proc_t *proct,
return PMIX_SUCCESS;
}
static pmix_status_t server_iof_pull(const pmix_proc_t procs[], size_t nprocs,
const pmix_info_t directives[], size_t ndirs,
pmix_iof_channel_t channels,
pmix_op_cbfunc_t cbfunc, void *cbdata)
{
if (NULL == host_module || NULL == host_module->iof_pull) {
return PMIX_ERR_NOT_SUPPORTED;
}
return PMIX_ERR_NOT_SUPPORTED;
}
static pmix_status_t server_stdin(const pmix_proc_t *source,
const pmix_proc_t targets[], size_t ntargets,
const pmix_info_t directives[], size_t ndirs,
const pmix_byte_object_t *bo,
pmix_op_cbfunc_t cbfunc, void *cbdata)
{
if (NULL == host_module || NULL == host_module->iof_push) {
return PMIX_ERR_NOT_SUPPORTED;
}
return PMIX_ERR_NOT_SUPPORTED;
}

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

@ -569,7 +569,6 @@ int pmix3x_server_notify_event(int status,
return pmix3x_convert_rc(rc);
}
#if 0
int pmix3x_server_iof_push(const opal_process_name_t *source,
opal_pmix_iof_channel_t channel,
unsigned char *data, size_t nbytes)
@ -622,7 +621,7 @@ int pmix3x_server_iof_push(const opal_process_name_t *source,
/* push the IO */
OPAL_PMIX_CONSTRUCT_LOCK(&lock);
rc = PMIx_IOF_push(&op->p, pchan, &bo, NULL, 0, lkcbfunc, (void*)&lock);
rc = PMIx_server_IOF_deliver(&op->p, pchan, &bo, NULL, 0, lkcbfunc, (void*)&lock);
if (PMIX_SUCCESS != rc) {
ret = pmix3x_convert_rc(rc);
} else {
@ -636,4 +635,156 @@ int pmix3x_server_iof_push(const opal_process_name_t *source,
return ret;
}
#endif
static void final_cleanup(int status, void *cbdata)
{
pmix3x_opalcaddy_t *opalcaddy = (pmix3x_opalcaddy_t*)cbdata;
OBJ_RELEASE(opalcaddy);
}
static void setup_cbfunc(pmix_status_t status,
pmix_info_t info[], size_t ninfo,
void *provided_cbdata,
pmix_op_cbfunc_t cbfunc, void *cbdata)
{
pmix3x_opcaddy_t *op = (pmix3x_opcaddy_t*)provided_cbdata;
pmix3x_opalcaddy_t *opalcaddy;
size_t n;
opal_value_t *iptr;
int rc;
pmix_status_t ret = PMIX_SUCCESS;
/* setup the caddy */
opalcaddy = OBJ_NEW(pmix3x_opalcaddy_t);
rc = pmix3x_convert_rc(status);
if (OPAL_SUCCESS == rc && NULL != info) {
/* need to convert the info array to a list */
for (n=0; n < ninfo; n++) {
iptr = OBJ_NEW(opal_value_t);
opal_list_append(&opalcaddy->info, &iptr->super);
iptr->key = strdup(info[n].key);
if (OPAL_SUCCESS != (rc = pmix3x_value_unload(iptr, &info[n].value))) {
OBJ_RELEASE(opalcaddy);
ret = pmix3x_convert_opalrc(rc);
goto done;
}
}
}
done:
/* release our caller */
if (NULL != cbfunc) {
cbfunc(ret, cbdata);
}
/* pass what we have upstairs */
if (NULL != op->setupcbfunc) {
op->setupcbfunc(rc, &opalcaddy->info, op->cbdata,
final_cleanup, opalcaddy);
}
OBJ_RELEASE(op);
}
int pmix3x_server_setup_application(opal_jobid_t jobid,
opal_list_t *info,
opal_pmix_setup_application_cbfunc_t cbfunc, void *cbdata)
{
opal_value_t *kv;
pmix_info_t *pinfo;
size_t sz, n;
pmix_status_t rc;
pmix3x_opcaddy_t *op;
opal_output_verbose(2, opal_pmix_base_framework.framework_output,
"%s setup application for job %s",
OPAL_NAME_PRINT(OPAL_PROC_MY_NAME),
OPAL_JOBID_PRINT(jobid));
OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
if (0 >= opal_pmix_base.initialized) {
OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
return OPAL_ERR_NOT_INITIALIZED;
}
OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
/* convert the list to an array of pmix_info_t */
if (NULL != info && 0 < (sz = opal_list_get_size(info))) {
PMIX_INFO_CREATE(pinfo, sz);
n = 0;
OPAL_LIST_FOREACH(kv, info, opal_value_t) {
(void)strncpy(pinfo[n].key, kv->key, PMIX_MAX_KEYLEN);
pmix3x_value_load(&pinfo[n].value, kv);
++n;
}
} else {
sz = 0;
pinfo = NULL;
}
/* setup the caddy */
op = OBJ_NEW(pmix3x_opcaddy_t);
op->info = pinfo;
op->sz = sz;
op->setupcbfunc = cbfunc;
op->cbdata = cbdata;
/* convert the jobid */
(void)opal_snprintf_jobid(op->p.nspace, PMIX_MAX_NSLEN, jobid);
rc = PMIx_server_setup_application(op->p.nspace, op->info, op->sz,
setup_cbfunc, op);
if (PMIX_SUCCESS != rc) {
OBJ_RELEASE(op);
}
return pmix3x_convert_rc(rc);
}
int pmix3x_server_setup_local_support(opal_jobid_t jobid,
opal_list_t *info,
opal_pmix_op_cbfunc_t cbfunc, void *cbdata)
{
opal_value_t *kv;
pmix_info_t *pinfo;
size_t sz, n;
pmix_status_t rc;
pmix3x_opcaddy_t *op;
opal_output_verbose(2, opal_pmix_base_framework.framework_output,
"%s setup local support for job %s",
OPAL_NAME_PRINT(OPAL_PROC_MY_NAME),
OPAL_JOBID_PRINT(jobid));
OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
if (0 >= opal_pmix_base.initialized) {
OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
return OPAL_ERR_NOT_INITIALIZED;
}
OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
/* convert the list to an array of pmix_info_t */
if (NULL != info && 0 < (sz = opal_list_get_size(info))) {
PMIX_INFO_CREATE(pinfo, sz);
n = 0;
OPAL_LIST_FOREACH(kv, info, opal_value_t) {
(void)strncpy(pinfo[n].key, kv->key, PMIX_MAX_KEYLEN);
pmix3x_value_load(&pinfo[n].value, kv);
++n;
}
} else {
sz = 0;
pinfo = NULL;
}
/* setup the caddy */
op = OBJ_NEW(pmix3x_opcaddy_t);
op->info = pinfo;
op->sz = sz;
op->opcbfunc = cbfunc;
op->cbdata = cbdata;
/* convert the jobid */
(void)opal_snprintf_jobid(op->p.nspace, PMIX_MAX_NSLEN, jobid);
rc = PMIx_server_setup_local_support(op->p.nspace, op->info, op->sz,
opcbfunc, op);
if (PMIX_SUCCESS != rc) {
OBJ_RELEASE(op);
}
return pmix3x_convert_rc(rc);
}

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

@ -243,10 +243,17 @@ typedef int (*opal_pmix_server_job_control_fn_t)(const opal_process_name_t *requ
/* we do not provide a monitoring capability */
/* Request forwarding of specified IO channels to the local PMIx server
* for distribution to local clients */
typedef int (*opal_pmix_server_iof_pull_fn_t)(opal_list_t *sources,
opal_list_t *directives,
opal_pmix_iof_channel_t channels,
opal_pmix_op_cbfunc_t cbfunc, void *cbdata);
/* Entry point for pushing forwarded IO to clients/tools */
typedef int (*opal_pmix_server_iof_fn_t)(const opal_process_name_t *source,
opal_pmix_iof_channel_t channel,
unsigned char *data, size_t nbytes);
typedef int (*opal_pmix_server_iof_push_fn_t)(const opal_process_name_t *source,
opal_pmix_iof_channel_t channel,
unsigned char *data, size_t nbytes);
typedef struct opal_pmix_server_module_1_0_0_t {
opal_pmix_server_client_connected_fn_t client_connected;
@ -269,6 +276,8 @@ typedef struct opal_pmix_server_module_1_0_0_t {
opal_pmix_server_listener_fn_t listener;
opal_pmix_server_alloc_fn_t allocate;
opal_pmix_server_job_control_fn_t job_control;
opal_pmix_server_iof_pull_fn_t iof_pull;
opal_pmix_server_iof_push_fn_t iof_push;
} opal_pmix_server_module_t;

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

@ -254,9 +254,6 @@ BEGIN_C_DECLS
#define OPAL_PMIX_PRELOAD_FILES "pmix.preloadfiles" // (char*) comma-delimited list of files to pre-position
#define OPAL_PMIX_NON_PMI "pmix.nonpmi" // (bool) spawned procs will not call PMIx_Init
#define OPAL_PMIX_STDIN_TGT "pmix.stdin" // (uint32_t) spawned proc rank that is to receive stdin
#define OPAL_PMIX_FWD_STDIN "pmix.fwd.stdin" // (bool) forward my stdin to the designated proc
#define OPAL_PMIX_FWD_STDOUT "pmix.fwd.stdout" // (bool) forward stdout from spawned procs to me
#define OPAL_PMIX_FWD_STDERR "pmix.fwd.stderr" // (bool) forward stderr from spawned procs to me
#define OPAL_PMIX_DEBUGGER_DAEMONS "pmix.debugger" // (bool) spawned app consists of debugger daemons
#define OPAL_PMIX_COSPAWN_APP "pmix.cospawn" // (bool) designated app is to be spawned as a disconnected
// job - i.e., not part of the "comm_world" of the job
@ -278,6 +275,18 @@ 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_ADD_ENVAR "pmix.envar.add" // (pmix_envar_t*) add envar, but do not overwrite any 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
@ -318,6 +327,8 @@ BEGIN_C_DECLS
#define OPAL_PMIX_DEBUG_WAIT_FOR_NOTIFY "pmix.dbg.notify" // (bool) block at desired point until receiving debugger release notification
#define OPAL_PMIX_DEBUG_JOB "pmix.dbg.job" // (char*) nspace of the job to be debugged - the RM/PMIx server are
#define OPAL_PMIX_DEBUG_WAITING_FOR_NOTIFY "pmix.dbg.waiting" // (bool) job to be debugged is waiting for a release
#define OPAL_PMIX_DEBUG_JOB_DIRECTIVES "pmix.dbg.jdirs" // (opal_list_t*) list of job-level directives
#define OPAL_PMIX_DEBUG_APP_DIRECTIVES "pmix.dbg.adirs" // (opal_list_t*) list of app-level directives
/* Resource Manager identification */
@ -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
@ -392,6 +398,39 @@ BEGIN_C_DECLS
#define OPAL_PMIX_MONITOR_FILE_DROPS "pmix.monitor.fdrop" // (uint32_t) number of file checks that can be missed before taking
// specified action
/* security attributes */
#define OPAL_PMIX_CRED_TYPE "pmix.sec.ctype" // (char*) when passed in PMIx_Get_credential, a prioritized,
// comma-delimited list of desired credential types for use
// in environments where multiple authentication mechanisms
// may be available. When returned in a callback function, a
// string identifier of the credential type
/* IO Forwarding Attributes */
#define OPAL_PMIX_IOF_CACHE_SIZE "pmix.iof.csize" // (uint32_t) requested size of the server cache in bytes for each specified channel.
// By default, the server is allowed (but not required) to drop
// all bytes received beyond the max size
#define OPAL_PMIX_IOF_DROP_OLDEST "pmix.iof.old" // (bool) in an overflow situation, drop the oldest bytes to make room in the cache
#define OPAL_PMIX_IOF_DROP_NEWEST "pmix.iof.new" // (bool) in an overflow situation, drop any new bytes received until room becomes
// available in the cache (default)
#define OPAL_PMIX_IOF_BUFFERING_SIZE "pmix.iof.bsize" // (uint32_t) basically controls grouping of IO on the specified channel(s) to
// avoid being called every time a bit of IO arrives. The library
// will execute the callback whenever the specified number of bytes
// becomes available. Any remaining buffered data will be "flushed"
// upon call to deregister the respective channel
#define OPAL_PMIX_IOF_BUFFERING_TIME "pmix.iof.btime" // (uint32_t) max time in seconds to buffer IO before delivering it. Used in conjunction
// with buffering size, this prevents IO from being held indefinitely
// while waiting for another payload to arrive
#define OPAL_PMIX_IOF_COMPLETE "pmix.iof.cmp" // (bool) indicates whether or not the specified IO channel has been closed
// by the source
#define OPAL_PMIX_IOF_PUSH_STDIN "pmix.iof.stdin" // (bool) Used by a tool to request that the PMIx library collect
// the tool's stdin and forward it to the procs specified in
// the PMIx_IOF_push call
/* Attributes for controlling contents of application setup data */
#define OPAL_PMIX_SETUP_APP_ENVARS "pmix.setup.env" // (bool) harvest and include relevant envars
#define OPAL_PMIX_SETUP_APP_NONENVARS "pmix.setup.nenv" // (bool) include all non-envar data
#define OPAL_PMIX_SETUP_APP_ALL "pmix.setup.all" // (bool) include all relevant data
/* define a scope for data "put" by PMI per the following:
*
@ -495,7 +534,7 @@ OBJ_CLASS_DECLARATION(opal_pmix_modex_data_t);
typedef struct {
opal_list_item_t super;
char **keys;
opal_list_t qualifiers;
opal_list_t qualifiers; // list of opal_value_t
} opal_pmix_query_t;
OBJ_CLASS_DECLARATION(opal_pmix_query_t);

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

@ -15,7 +15,7 @@
* Copyright (c) 2009 Oak Ridge National Labs. All rights reserved.
* Copyright (c) 2010-2015 Los Alamos National Security, LLC.
* All rights reserved.
* Copyright (c) 2013-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2013-2018 Intel, Inc. All rights reserved.
* Copyright (c) 2015-2017 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2017 Amazon.com, Inc. or its affiliates.
@ -305,6 +305,10 @@ opal_err2str(int errnum, const char **errmsg)
case OPAL_ERR_MODEL_DECLARED:
retval = "Model declared";
break;
case OPAL_PMIX_LAUNCH_DIRECTIVE:
retval = "Launch directive";
break;
default:
retval = "UNRECOGNIZED";
}

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

@ -15,6 +15,7 @@
* Copyright (c) 2015-2016 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
*
* Copyright (c) 2018 Intel, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -168,7 +169,7 @@ opal_progress_finalize(void)
return OPAL_SUCCESS;
}
static int opal_progress_events()
static int opal_progress_events(void)
{
int events = 0;

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

@ -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);

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

@ -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) {

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

@ -252,10 +252,13 @@ void orte_iof_hnp_read_local_handler(int fd, short event, void *cbdata)
OPAL_OUTPUT_VERBOSE((1, orte_iof_base_framework.framework_output,
"%s sending data of size %d via PMIx to tool %s",
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), (int)numbytes,
ORTE_NAME_PRINT(&sink->daemon));
rc = opal_pmix.server_iof_push(&proct->name, rev->tag, data, numbytes));
if (ORTE_SUCCESS != rc) {
ORTE_ERROR_LOG(rc);
ORTE_NAME_PRINT(&sink->daemon)));
/* don't pass down zero byte blobs */
if (0 < numbytes) {
rc = opal_pmix.server_iof_push(&proct->name, rev->tag, data, numbytes);
if (ORTE_SUCCESS != rc) {
ORTE_ERROR_LOG(rc);
}
}
} else {
OPAL_OUTPUT_VERBOSE((1, orte_iof_base_framework.framework_output,

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

@ -250,9 +250,12 @@ void orte_iof_hnp_recv(int status, orte_process_name_t* sender,
sink->name.vpid == origin.vpid)) {
/* send the data to the tool */
if (NULL != opal_pmix.server_iof_push) {
rc = opal_pmix.server_iof_push(&proct->name, stream, data, numbytes);
if (ORTE_SUCCESS != rc) {
ORTE_ERROR_LOG(rc);
/* don't pass along zero byte blobs */
if (0 < numbytes) {
rc = opal_pmix.server_iof_push(&proct->name, stream, data, numbytes);
if (ORTE_SUCCESS != rc) {
ORTE_ERROR_LOG(rc);
}
}
} else {
orte_iof_hnp_send_data_to_endpoint(&sink->daemon, &origin, stream, data, numbytes);

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

@ -56,7 +56,7 @@
#include "opal/mca/hwloc/hwloc-internal.h"
#include "opal/mca/shmem/base/base.h"
#include "opal/mca/pstat/pstat.h"
#include "opal/mca/pmix/pmix.h"
#include "opal/mca/pmix/base/base.h"
#include "orte/mca/errmgr/errmgr.h"
#include "orte/mca/rml/rml.h"
@ -100,6 +100,39 @@
#include "orte/mca/odls/base/base.h"
#include "orte/mca/odls/base/odls_private.h"
static void setup_cbfunc(int status,
opal_list_t *info,
void *provided_cbdata,
opal_pmix_op_cbfunc_t cbfunc, void *cbdata)
{
orte_job_t *jdata = (orte_job_t*)provided_cbdata;
opal_value_t *kv;
opal_buffer_t cache, *bptr;
int rc;
OBJ_CONSTRUCT(&cache, opal_buffer_t);
if (NULL != info) {
/* cycle across the provided info */
OPAL_LIST_FOREACH(kv, info, opal_value_t) {
if (OPAL_SUCCESS != (rc = opal_dss.pack(&cache, &kv, 1, OPAL_VALUE))) {
ORTE_ERROR_LOG(rc);
}
}
}
/* add the results */
bptr = &cache;
opal_dss.pack(&jdata->launch_msg, &bptr, 1, OPAL_BUFFER);
OBJ_DESTRUCT(&cache);
/* release our caller */
if (NULL != cbfunc) {
cbfunc(rc, cbdata);
}
/* move to next stage */
ORTE_ACTIVATE_JOB_STATE(jdata, ORTE_JOB_STATE_SEND_LAUNCH_MSG);
}
/* IT IS CRITICAL THAT ANY CHANGE IN THE ORDER OF THE INFO PACKED IN
* THIS FUNCTION BE REFLECTED IN THE CONSTRUCT_CHILD_LIST PARSER BELOW
*/
@ -350,7 +383,18 @@ int orte_odls_base_default_get_add_procs_data(opal_buffer_t *buffer,
free(nidmap);
}
/* compute and pack the regex of ppn */
/* get any application prep info */
if (NULL != opal_pmix.server_setup_application) {
/* we don't want to block here because it could
* take some indeterminate time to get the info */
if (OPAL_SUCCESS != (rc = opal_pmix.server_setup_application(jdata->jobid, NULL, setup_cbfunc, jdata))) {
ORTE_ERROR_LOG(rc);
}
return rc;
}
/* move to next stage */
ORTE_ACTIVATE_JOB_STATE(jdata, ORTE_JOB_STATE_SEND_LAUNCH_MSG);
return ORTE_SUCCESS;
}
@ -362,6 +406,12 @@ static void fm_release(void *cbdata)
OBJ_RELEASE(bptr);
}
static void ls_cbunc(int status, void *cbdata)
{
opal_pmix_lock_t *lock = (opal_pmix_lock_t*)cbdata;
OPAL_PMIX_WAKEUP_THREAD(lock);
}
int orte_odls_base_default_construct_child_list(opal_buffer_t *buffer,
orte_jobid_t *job)
{
@ -376,6 +426,9 @@ int orte_odls_base_default_construct_child_list(opal_buffer_t *buffer,
orte_app_context_t *app;
int8_t flag;
char *ppn;
opal_value_t *kv;
opal_list_t local_support, cache;
opal_pmix_lock_t lock;
OPAL_OUTPUT_VERBOSE((5, orte_odls_base_framework.framework_output,
"%s odls:constructing child list",
@ -385,6 +438,8 @@ int orte_odls_base_default_construct_child_list(opal_buffer_t *buffer,
*job = ORTE_JOBID_INVALID;
/* get the daemon job object */
daemons = orte_get_job_data_object(ORTE_PROC_MY_NAME->jobid);
OPAL_PMIX_CONSTRUCT_LOCK(&lock);
OBJ_CONSTRUCT(&local_support, opal_list_t);
/* unpack the flag to see if new daemons were launched */
cnt=1;
@ -504,17 +559,18 @@ int orte_odls_base_default_construct_child_list(opal_buffer_t *buffer,
}
}
/* extract the ppn regex */
cnt = 1;
if (OPAL_SUCCESS != (rc = opal_dss.unpack(buffer, &ppn, &cnt, OPAL_STRING))) {
ORTE_ERROR_LOG(rc);
goto REPORT_ERROR;
}
/* if the job is fully described, then mpirun will have computed
* and sent us the complete array of procs in the orte_job_t, so we
* don't need to do anything more here */
if (!orte_get_attribute(&jdata->attributes, ORTE_JOB_FULLY_DESCRIBED, NULL, OPAL_BOOL)) {
if (!ORTE_PROC_IS_HNP) {
/* extract the ppn regex */
cnt = 1;
if (OPAL_SUCCESS != (rc = opal_dss.unpack(buffer, &ppn, &cnt, OPAL_STRING))) {
ORTE_ERROR_LOG(rc);
goto REPORT_ERROR;
}
/* populate the node array of the job map and the proc array of
* the job object so we know how many procs are on each node */
if (ORTE_SUCCESS != (rc = orte_regx.parse_ppn(jdata, ppn))) {
@ -522,10 +578,10 @@ int orte_odls_base_default_construct_child_list(opal_buffer_t *buffer,
free(ppn);
goto REPORT_ERROR;
}
free(ppn);
/* now assign locations to the procs */
if (ORTE_SUCCESS != (rc = orte_rmaps_base_assign_locations(jdata))) {
ORTE_ERROR_LOG(rc);
free(ppn);
goto REPORT_ERROR;
}
}
@ -533,14 +589,63 @@ int orte_odls_base_default_construct_child_list(opal_buffer_t *buffer,
* to the jdata->procs array */
if (ORTE_SUCCESS != (rc = orte_rmaps_base_compute_vpids(jdata))) {
ORTE_ERROR_LOG(rc);
free(ppn);
goto REPORT_ERROR;
}
/* and finally, compute the local and node ranks */
if (ORTE_SUCCESS != (rc = orte_rmaps_base_compute_local_ranks(jdata))) {
ORTE_ERROR_LOG(rc);
free(ppn);
goto REPORT_ERROR;
}
}
free(ppn);
/* unpack the buffer containing any application setup info - there
* might not be any, so it isn't an error if we don't find things */
cnt=1;
rc = opal_dss.unpack(buffer, &bptr, &cnt, OPAL_BUFFER);
if (OPAL_SUCCESS == rc) {
/* there was setup data - process it */
cnt=1;
OBJ_CONSTRUCT(&cache, opal_list_t);
while (ORTE_SUCCESS == (rc = opal_dss.unpack(bptr, &kv, &cnt, OPAL_VALUE))) {
/* if this is an envar operation, cache it in reverse order
* so that the order the user provided is preserved */
if (0 == strcmp(kv->key, OPAL_PMIX_SET_ENVAR) ||
0 == strcmp(kv->key, OPAL_PMIX_ADD_ENVAR) ||
0 == strcmp(kv->key, OPAL_PMIX_UNSET_ENVAR) ||
0 == strcmp(kv->key, OPAL_PMIX_PREPEND_ENVAR) ||
0 == strcmp(kv->key, OPAL_PMIX_APPEND_ENVAR)) {
opal_list_prepend(&cache, &kv->super);
} else {
/* need to pass it to pmix.setup_local_support */
opal_list_append(&local_support, &kv->super);
}
}
OBJ_RELEASE(bptr);
/* add any cache'd values to the front of the job attributes */
while (NULL != (kv = (opal_value_t*)opal_list_remove_first(&cache))) {
if (0 == strcmp(kv->key, OPAL_PMIX_SET_ENVAR)) {
orte_prepend_attribute(&jdata->attributes, ORTE_JOB_SET_ENVAR,
ORTE_ATTR_GLOBAL, &kv->data.envar, OPAL_ENVAR);
} else if (0 == strcmp(kv->key, OPAL_PMIX_ADD_ENVAR)) {
orte_prepend_attribute(&jdata->attributes, ORTE_JOB_ADD_ENVAR,
ORTE_ATTR_GLOBAL, &kv->data.envar, OPAL_ENVAR);
} else if (0 == strcmp(kv->key, OPAL_PMIX_UNSET_ENVAR)) {
orte_prepend_attribute(&jdata->attributes, ORTE_JOB_UNSET_ENVAR,
ORTE_ATTR_GLOBAL, kv->data.string, OPAL_STRING);
} else if (0 == strcmp(kv->key, OPAL_PMIX_PREPEND_ENVAR)) {
orte_prepend_attribute(&jdata->attributes, ORTE_JOB_PREPEND_ENVAR,
ORTE_ATTR_GLOBAL, &kv->data.envar, OPAL_ENVAR);
} else if (0 == strcmp(kv->key, OPAL_PMIX_APPEND_ENVAR)) {
orte_prepend_attribute(&jdata->attributes, ORTE_JOB_APPEND_ENVAR,
ORTE_ATTR_GLOBAL, &kv->data.envar, OPAL_ENVAR);
}
OBJ_RELEASE(kv);
}
OPAL_LIST_DESTRUCT(&cache);
}
/* now that the node array in the job map and jdata are completely filled out,.
* we need to "wireup" the procs to their nodes so other utilities can
@ -636,6 +741,27 @@ int orte_odls_base_default_construct_child_list(opal_buffer_t *buffer,
orte_rmaps_base_display_map(jdata);
}
/* register this job with the PMIx server - need to wait until after we
* have computed the #local_procs before calling the function */
if (ORTE_SUCCESS != (rc = orte_pmix_server_register_nspace(jdata, false))) {
ORTE_ERROR_LOG(rc);
goto REPORT_ERROR;
}
/* if we have local support setup info, then execute it here - we
* have to do so AFTER we register the nspace so the PMIx server
* has the nspace info it needs */
if (0 < opal_list_get_size(&local_support) &&
NULL != opal_pmix.server_setup_local_support) {
if (OPAL_SUCCESS != (rc = opal_pmix.server_setup_local_support(jdata->jobid, &local_support,
ls_cbunc, &lock))) {
ORTE_ERROR_LOG(rc);
goto REPORT_ERROR;
}
} else {
lock.active = false; // we won't get a callback
}
/* if we have a file map, then we need to load it */
if (orte_get_attribute(&jdata->attributes, ORTE_JOB_FILE_MAPS, (void**)&bptr, OPAL_BUFFER)) {
if (NULL != orte_dfs.load_file_maps) {
@ -648,13 +774,6 @@ int orte_odls_base_default_construct_child_list(opal_buffer_t *buffer,
/* load any controls into the job */
orte_rtc.assign(jdata);
/* register this job with the PMIx server - need to wait until after we
* have computed the #local_procs before calling the function */
if (ORTE_SUCCESS != (rc = orte_pmix_server_register_nspace(jdata, false))) {
ORTE_ERROR_LOG(rc);
goto REPORT_ERROR;
}
/* spin up the spawn threads */
orte_odls_base_start_threads(jdata);
@ -663,9 +782,15 @@ int orte_odls_base_default_construct_child_list(opal_buffer_t *buffer,
* proc structures. For the HNP, the proc structs will
* remain in the orte_job_t array */
/* wait here until the local support has been setup */
OPAL_PMIX_WAIT_THREAD(&lock);
OPAL_PMIX_DESTRUCT_LOCK(&lock);
OPAL_LIST_DESTRUCT(&local_support);
return ORTE_SUCCESS;
REPORT_ERROR:
OPAL_PMIX_DESTRUCT_LOCK(&lock);
OPAL_LIST_DESTRUCT(&local_support);
/* we have to report an error back to the HNP so we don't just
* hang. Although there shouldn't be any errors once this is
* all debugged, it is still good practice to have a way

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

@ -10,7 +10,7 @@
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2013 Los Alamos National Security, LLC. All rights reserved.
* Copyright (c) 2015-2016 Intel, Inc. All rights reserved.
* Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -63,6 +63,7 @@ ORTE_DECLSPEC void orte_plm_base_daemons_launched(int fd, short args, void *cbda
ORTE_DECLSPEC void orte_plm_base_vm_ready(int fd, short args, void *cbdata);
ORTE_DECLSPEC void orte_plm_base_mapping_complete(int fd, short args, void *cbdata);
ORTE_DECLSPEC void orte_plm_base_launch_apps(int fd, short args, void *cbdata);
ORTE_DECLSPEC void orte_plm_base_send_launch_msg(int fd, short args, void *cbdata);
ORTE_DECLSPEC void orte_plm_base_post_launch(int fd, short args, void *cbdata);
ORTE_DECLSPEC void orte_plm_base_registered(int fd, short args, void *cbdata);

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

@ -503,13 +503,10 @@ static void timer_cb(int fd, short event, void *cbdata)
void orte_plm_base_launch_apps(int fd, short args, void *cbdata)
{
orte_state_caddy_t *caddy = (orte_state_caddy_t*)cbdata;
orte_job_t *jdata;
orte_daemon_cmd_flag_t command;
opal_buffer_t *buffer;
int rc;
orte_state_caddy_t *caddy = (orte_state_caddy_t*)cbdata;
orte_timer_t *timer;
orte_grpcomm_signature_t *sig;
ORTE_ACQUIRE_OBJECT(caddy);
@ -529,45 +526,60 @@ void orte_plm_base_launch_apps(int fd, short args, void *cbdata)
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
ORTE_JOBID_PRINT(jdata->jobid)));
/* setup the buffer */
buffer = OBJ_NEW(opal_buffer_t);
/* pack the appropriate add_local_procs command */
if (orte_get_attribute(&jdata->attributes, ORTE_JOB_FIXED_DVM, NULL, OPAL_BOOL)) {
command = ORTE_DAEMON_DVM_ADD_PROCS;
} else {
command = ORTE_DAEMON_ADD_LOCAL_PROCS;
}
if (ORTE_SUCCESS != (rc = opal_dss.pack(buffer, &command, 1, ORTE_DAEMON_CMD))) {
if (ORTE_SUCCESS != (rc = opal_dss.pack(&jdata->launch_msg, &command, 1, ORTE_DAEMON_CMD))) {
ORTE_ERROR_LOG(rc);
OBJ_RELEASE(buffer);
ORTE_FORCED_TERMINATE(ORTE_ERROR_DEFAULT_EXIT_CODE);
OBJ_RELEASE(caddy);
return;
}
/* get the local launcher's required data */
if (ORTE_SUCCESS != (rc = orte_odls.get_add_procs_data(buffer, jdata->jobid))) {
if (ORTE_SUCCESS != (rc = orte_odls.get_add_procs_data(&jdata->launch_msg, jdata->jobid))) {
ORTE_ERROR_LOG(rc);
ORTE_FORCED_TERMINATE(ORTE_ERROR_DEFAULT_EXIT_CODE);
OBJ_RELEASE(caddy);
return;
}
OBJ_RELEASE(caddy);
return;
}
void orte_plm_base_send_launch_msg(int fd, short args, void *cbdata)
{
orte_state_caddy_t *caddy = (orte_state_caddy_t*)cbdata;
orte_timer_t *timer;
orte_grpcomm_signature_t *sig;
orte_job_t *jdata;
int rc;
/* convenience */
jdata = caddy->jdata;
OPAL_OUTPUT_VERBOSE((5, orte_plm_base_framework.framework_output,
"%s plm:base:send launch msg for job %s",
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
ORTE_JOBID_PRINT(jdata->jobid)));
/* if we don't want to launch the apps, now is the time to leave */
if (orte_do_not_launch) {
bool compressed;
uint8_t *cmpdata;
size_t cmplen;
/* report the size of the launch message */
compressed = orte_util_compress_block((uint8_t*)buffer->base_ptr, buffer->bytes_used,
compressed = orte_util_compress_block((uint8_t*)jdata->launch_msg.base_ptr,
jdata->launch_msg.bytes_used,
&cmpdata, &cmplen);
if (compressed) {
opal_output(0, "LAUNCH MSG RAW SIZE: %d COMPRESSED SIZE: %d",
(int)buffer->bytes_used, (int)cmplen);
(int)jdata->launch_msg.bytes_used, (int)cmplen);
free(cmpdata);
} else {
opal_output(0, "LAUNCH MSG RAW SIZE: %d", (int)buffer->bytes_used);
opal_output(0, "LAUNCH MSG RAW SIZE: %d", (int)jdata->launch_msg.bytes_used);
}
orte_never_launched = true;
ORTE_FORCED_TERMINATE(0);
@ -581,15 +593,15 @@ void orte_plm_base_launch_apps(int fd, short args, void *cbdata)
sig->signature[0].jobid = ORTE_PROC_MY_NAME->jobid;
sig->signature[0].vpid = ORTE_VPID_WILDCARD;
sig->sz = 1;
if (ORTE_SUCCESS != (rc = orte_grpcomm.xcast(sig, ORTE_RML_TAG_DAEMON, buffer))) {
if (ORTE_SUCCESS != (rc = orte_grpcomm.xcast(sig, ORTE_RML_TAG_DAEMON, &jdata->launch_msg))) {
ORTE_ERROR_LOG(rc);
OBJ_RELEASE(buffer);
OBJ_RELEASE(sig);
ORTE_FORCED_TERMINATE(ORTE_ERROR_DEFAULT_EXIT_CODE);
OBJ_RELEASE(caddy);
return;
}
OBJ_RELEASE(buffer);
OBJ_DESTRUCT(&jdata->launch_msg);
OBJ_CONSTRUCT(&jdata->launch_msg, opal_buffer_t);
/* maintain accounting */
OBJ_RELEASE(sig);

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

@ -12,7 +12,7 @@
* All rights reserved.
* Copyright (c) 2011 Los Alamos National Security, LLC.
* All rights reserved.
* Copyright (c) 2014-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2014-2018 Intel, Inc. All rights reserved.
* Copyright (c) 2017 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* $COPYRIGHT$
@ -39,6 +39,7 @@
#include "opal/dss/dss.h"
#include "opal/threads/threads.h"
#include "opal/util/argv.h"
#include "opal/util/opal_environ.h"
#include "orte/constants.h"
#include "orte/types.h"

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

@ -11,7 +11,7 @@
* All rights reserved.
* Copyright (c) 2011-2013 Los Alamos National Security, LLC.
* All rights reserved.
* Copyright (c) 2017 Intel, Inc. All rights reserved.
* Copyright (c) 2017-2018 Intel, Inc. All rights reserved.
* Copyright (c) 2017 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* $COPYRIGHT$

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

@ -11,7 +11,7 @@
* All rights reserved.
* Copyright (c) 2011-2012 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2014-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2014-2018 Intel, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -125,25 +125,26 @@ typedef int32_t orte_job_state_t;
#define ORTE_JOB_STATE_DAEMONS_REPORTED 10 /* all launched daemons have reported */
#define ORTE_JOB_STATE_VM_READY 11 /* the VM is ready for operation */
#define ORTE_JOB_STATE_LAUNCH_APPS 12 /* ready to launch apps */
#define ORTE_JOB_STATE_RUNNING 13 /* all procs have been fork'd */
#define ORTE_JOB_STATE_SUSPENDED 14 /* job has been suspended */
#define ORTE_JOB_STATE_REGISTERED 15 /* all procs registered for sync */
#define ORTE_JOB_STATE_READY_FOR_DEBUGGERS 16 /* job ready for debugger init after spawn */
#define ORTE_JOB_STATE_LOCAL_LAUNCH_COMPLETE 17 /* all local procs have attempted launch */
#define ORTE_JOB_STATE_DEBUGGER_DETACH 18 /* a debugger has detached */
#define ORTE_JOB_STATE_SEND_LAUNCH_MSG 13 /* send launch msg to daemons */
#define ORTE_JOB_STATE_RUNNING 14 /* all procs have been fork'd */
#define ORTE_JOB_STATE_SUSPENDED 15 /* job has been suspended */
#define ORTE_JOB_STATE_REGISTERED 16 /* all procs registered for sync */
#define ORTE_JOB_STATE_READY_FOR_DEBUGGERS 17 /* job ready for debugger init after spawn */
#define ORTE_JOB_STATE_LOCAL_LAUNCH_COMPLETE 18 /* all local procs have attempted launch */
#define ORTE_JOB_STATE_DEBUGGER_DETACH 19 /* a debugger has detached */
/*
* Define a "boundary" so we can easily and quickly determine
* if a job is still running or not - any value less than
* this one means that we are not terminated
*/
#define ORTE_JOB_STATE_UNTERMINATED 20
#define ORTE_JOB_STATE_UNTERMINATED 30
#define ORTE_JOB_STATE_TERMINATED 21 /* all processes have terminated and job is no longer running */
#define ORTE_JOB_STATE_ALL_JOBS_COMPLETE 22
#define ORTE_JOB_STATE_DAEMONS_TERMINATED 23
#define ORTE_JOB_STATE_NOTIFY_COMPLETED 24 /* callback to notify when job completes */
#define ORTE_JOB_STATE_NOTIFIED 25
#define ORTE_JOB_STATE_TERMINATED 31 /* all processes have terminated and job is no longer running */
#define ORTE_JOB_STATE_ALL_JOBS_COMPLETE 32
#define ORTE_JOB_STATE_DAEMONS_TERMINATED 33
#define ORTE_JOB_STATE_NOTIFY_COMPLETED 34 /* callback to notify when job completes */
#define ORTE_JOB_STATE_NOTIFIED 35
/* Define a boundary so we can easily and quickly determine
* if a job abnormally terminated - leave a little room

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

@ -1,5 +1,5 @@
#
# Copyright (c) 2016 Intel, Inc. All rights reserved.
# Copyright (c) 2016-2018 Intel, Inc. All rights reserved.
# Copyright (c) 2017 IBM Corporation. All rights reserved.
# $COPYRIGHT$
#
@ -34,4 +34,3 @@ mca_schizo_alps_la_LIBADD = $(top_builddir)/orte/lib@ORTE_LIB_PREFIX@open-rte.la
noinst_LTLIBRARIES = $(component_noinst)
libmca_schizo_alps_la_SOURCES = $(sources)
libmca_schizo_alps_la_LDFLAGS = -module -avoid-version

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

@ -800,14 +800,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",
@ -1050,6 +1052,132 @@ 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_ADD_ENVAR == attr->key) {
opal_setenv(attr->data.envar.envar, attr->data.envar.value, false, &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_ADD_ENVAR == attr->key) {
opal_setenv(attr->data.envar.envar, attr->data.envar.value, false, &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;
}

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

@ -87,6 +87,7 @@ static orte_job_state_t launch_states[] = {
ORTE_JOB_STATE_MAP_COMPLETE,
ORTE_JOB_STATE_SYSTEM_PREP,
ORTE_JOB_STATE_LAUNCH_APPS,
ORTE_JOB_STATE_SEND_LAUNCH_MSG,
ORTE_JOB_STATE_LOCAL_LAUNCH_COMPLETE,
ORTE_JOB_STATE_RUNNING,
ORTE_JOB_STATE_REGISTERED,
@ -108,6 +109,7 @@ static orte_state_cbfunc_t launch_callbacks[] = {
orte_plm_base_mapping_complete,
orte_plm_base_complete_setup,
orte_plm_base_launch_apps,
orte_plm_base_send_launch_msg,
orte_state_base_local_launch_complete,
orte_plm_base_post_launch,
orte_plm_base_registered,

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

@ -1,7 +1,7 @@
/*
* Copyright (c) 2011-2012 Los Alamos National Security, LLC.
* All rights reserved.
* Copyright (c) 2014-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2014-2018 Intel, Inc. All rights reserved.
* Copyright (c) 2017 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* $COPYRIGHT$
@ -82,6 +82,7 @@ static orte_job_state_t launch_states[] = {
ORTE_JOB_STATE_MAP_COMPLETE,
ORTE_JOB_STATE_SYSTEM_PREP,
ORTE_JOB_STATE_LAUNCH_APPS,
ORTE_JOB_STATE_SEND_LAUNCH_MSG,
ORTE_JOB_STATE_LOCAL_LAUNCH_COMPLETE,
ORTE_JOB_STATE_RUNNING,
ORTE_JOB_STATE_REGISTERED,
@ -103,6 +104,7 @@ static orte_state_cbfunc_t launch_callbacks[] = {
orte_plm_base_mapping_complete,
orte_plm_base_complete_setup,
orte_plm_base_launch_apps,
orte_plm_base_send_launch_msg,
orte_state_base_local_launch_complete,
orte_plm_base_post_launch,
orte_plm_base_registered,

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

@ -1,7 +1,7 @@
/*
* Copyright (c) 2011-2012 Los Alamos National Security, LLC.
* All rights reserved.
* Copyright (c) 2014-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2014-2018 Intel, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -80,6 +80,7 @@ static orte_job_state_t launch_states[] = {
ORTE_JOB_STATE_MAP_COMPLETE,
ORTE_JOB_STATE_SYSTEM_PREP,
ORTE_JOB_STATE_LAUNCH_APPS,
ORTE_JOB_STATE_SEND_LAUNCH_MSG,
ORTE_JOB_STATE_LOCAL_LAUNCH_COMPLETE,
ORTE_JOB_STATE_RUNNING,
ORTE_JOB_STATE_REGISTERED,
@ -101,6 +102,7 @@ static orte_state_cbfunc_t launch_callbacks[] = {
map_complete,
orte_plm_base_complete_setup,
orte_plm_base_launch_apps,
orte_plm_base_send_launch_msg,
orte_state_base_local_launch_complete,
orte_plm_base_post_launch,
orte_plm_base_registered,

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

@ -559,7 +559,7 @@ void orte_daemon_recv(int status, orte_process_name_t* sender,
/* look up job data object */
if (NULL == (jdata = orte_get_job_data_object(job))) {
/* we can safely ignore this request as the job
* was already cleaned up */
* was already cleaned up, or it was a tool */
goto CLEANUP;
}

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

@ -246,6 +246,25 @@ 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_ADD_ENVAR)) {
orte_add_attribute(&app->attributes, ORTE_APP_ADD_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 +479,24 @@ 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_ADD_ENVAR)) {
orte_add_attribute(&jdata->attributes, ORTE_JOB_ADD_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 */

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

@ -13,7 +13,7 @@
* All rights reserved.
* Copyright (c) 2009 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2011 Oak Ridge National Labs. All rights reserved.
* Copyright (c) 2013-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2013-2018 Intel, Inc. All rights reserved.
* Copyright (c) 2014-2017 Mellanox Technologies, Inc.
* All rights reserved.
* Copyright (c) 2014 Research Organization for Information Science
@ -465,9 +465,11 @@ static void _query(int sd, short args, void *cbdata)
orte_pmix_server_op_caddy_t *cd = (orte_pmix_server_op_caddy_t*)cbdata;
opal_pmix_query_t *q;
opal_value_t *kv;
orte_jobid_t jobid;
orte_job_t *jdata;
orte_proc_t *proct;
int rc, i, num_replies;
orte_app_context_t *app;
int rc, i, k, num_replies;
opal_list_t *results, targets, *array;
size_t n;
uint32_t key;
@ -683,10 +685,111 @@ static void _query(int sd, short args, void *cbdata)
kv->type = OPAL_STRING;
kv->data.string = strdup(orte_process_info.my_hnp_uri);
opal_list_append(results, &kv->super);
} else if (0 == strcmp(q->keys[n], OPAL_PMIX_QUERY_PROC_TABLE)) {
/* the job they are asking about is in the qualifiers */
jobid = ORTE_JOBID_INVALID;
OPAL_LIST_FOREACH(kv, &q->qualifiers, opal_value_t) {
if (0 == strcmp(kv->key, OPAL_PMIX_PROCID)) {
/* save the id */
jobid = kv->data.name.jobid;
break;
}
}
if (ORTE_JOBID_INVALID == jobid) {
rc = ORTE_ERR_BAD_PARAM;
goto done;
}
/* construct a list of values with opal_proc_info_t
* entries for each proc in the indicated job */
jdata = orte_get_job_data_object(jobid);
if (NULL == jdata) {
rc = ORTE_ERR_NOT_FOUND;
goto done;
}
/* setup the reply */
kv = OBJ_NEW(opal_value_t);
kv->key = strdup(OPAL_PMIX_QUERY_PROC_TABLE);
kv->type = OPAL_PTR;
array = OBJ_NEW(opal_list_t);
kv->data.ptr = array;
opal_list_append(results, &kv->super);
/* cycle thru the job and create an entry for each proc */
for (k=0; k < jdata->procs->size; k++) {
if (NULL == (proct = (orte_proc_t*)opal_pointer_array_get_item(jdata->procs, k))) {
continue;
}
kv = OBJ_NEW(opal_value_t);
kv->type = OPAL_PROC_INFO;
kv->data.pinfo.name.jobid = jobid;
kv->data.pinfo.name.vpid = proct->name.vpid;
if (NULL != proct->node && NULL != proct->node->name) {
kv->data.pinfo.hostname = strdup(proct->node->name);
}
app = (orte_app_context_t*)opal_pointer_array_get_item(jdata->apps, proct->app_idx);
if (NULL != app && NULL != app->app) {
kv->data.pinfo.executable_name = strdup(app->app);
}
kv->data.pinfo.pid = proct->pid;
kv->data.pinfo.exit_code = proct->exit_code;
kv->data.pinfo.state = proct->state;
opal_list_append(array, &kv->super);
}
} else if (0 == strcmp(q->keys[n], OPAL_PMIX_QUERY_LOCAL_PROC_TABLE)) {
/* the job they are asking about is in the qualifiers */
jobid = ORTE_JOBID_INVALID;
OPAL_LIST_FOREACH(kv, &q->qualifiers, opal_value_t) {
if (0 == strcmp(kv->key, OPAL_PMIX_PROCID)) {
/* save the id */
jobid = kv->data.name.jobid;
break;
}
}
if (ORTE_JOBID_INVALID == jobid) {
rc = ORTE_ERR_BAD_PARAM;
goto done;
}
/* construct a list of values with opal_proc_info_t
* entries for each LOCAL proc in the indicated job */
jdata = orte_get_job_data_object(jobid);
if (NULL == jdata) {
rc = ORTE_ERR_NOT_FOUND;
goto done;
}
/* setup the reply */
kv = OBJ_NEW(opal_value_t);
kv->key = strdup(OPAL_PMIX_QUERY_LOCAL_PROC_TABLE);
kv->type = OPAL_PTR;
array = OBJ_NEW(opal_list_t);
kv->data.ptr = array;
opal_list_append(results, &kv->super);
/* cycle thru the job and create an entry for each proc */
for (k=0; k < jdata->procs->size; k++) {
if (NULL == (proct = (orte_proc_t*)opal_pointer_array_get_item(jdata->procs, k))) {
continue;
}
if (ORTE_FLAG_TEST(proct, ORTE_PROC_FLAG_LOCAL)) {
kv = OBJ_NEW(opal_value_t);
kv->type = OPAL_PROC_INFO;
kv->data.pinfo.name.jobid = jobid;
kv->data.pinfo.name.vpid = proct->name.vpid;
if (NULL != proct->node && NULL != proct->node->name) {
kv->data.pinfo.hostname = strdup(proct->node->name);
}
app = (orte_app_context_t*)opal_pointer_array_get_item(jdata->apps, proct->app_idx);
if (NULL != app && NULL != app->app) {
kv->data.pinfo.executable_name = strdup(app->app);
}
kv->data.pinfo.pid = proct->pid;
kv->data.pinfo.exit_code = proct->exit_code;
kv->data.pinfo.state = proct->state;
opal_list_append(array, &kv->super);
}
}
}
}
}
done:
if (0 == opal_list_get_size(results)) {
rc = ORTE_ERR_NOT_FOUND;
} else if (opal_list_get_size(results) < opal_list_get_size(cd->info)) {

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

@ -13,7 +13,7 @@
* All rights reserved.
* Copyright (c) 2009 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2011 Oak Ridge National Labs. All rights reserved.
* Copyright (c) 2013-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2013-2018 Intel, Inc. All rights reserved.
* Copyright (c) 2014 Mellanox Technologies, Inc.
* All rights reserved.
* Copyright (c) 2014-2016 Research Organization for Information Science
@ -77,12 +77,6 @@ int orte_pmix_server_register_nspace(orte_job_t *jdata, bool force)
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
ORTE_JOBID_PRINT(jdata->jobid));
/* if this job has no local procs, then no need to register
* it unless the job info is needed by connecting jobs */
if (!force && 0 == jdata->num_local_procs) {
return ORTE_SUCCESS;
}
/* setup the info list */
info = OBJ_NEW(opal_list_t);
uid = geteuid();

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

@ -12,7 +12,7 @@
* Copyright (c) 2011 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2011-2013 Los Alamos National Security, LLC.
* All rights reserved.
* Copyright (c) 2014-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2014-2018 Intel, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -837,6 +837,12 @@ int orte_dt_pack_attr(opal_buffer_t *buffer, const void *src, int32_t num_vals,
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-ORTE-ATTR: UNSUPPORTED TYPE %d", (int)ptr[i]->type);
return OPAL_ERROR;

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

@ -12,7 +12,7 @@
* Copyright (c) 2011-2017 Cisco Systems, Inc. All rights reserved
* Copyright (c) 2011-2013 Los Alamos National Security, LLC.
* All rights reserved.
* Copyright (c) 2014-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2014-2018 Intel, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -923,6 +923,11 @@ int orte_dt_unpack_attr(opal_buffer_t *buffer, void *dest, int32_t *num_vals,
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, "PACK-ORTE-ATTR: UNSUPPORTED TYPE");

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

@ -13,7 +13,7 @@
* Copyright (c) 2009-2010 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011-2013 Los Alamos National Security, LLC.
* All rights reserved.
* Copyright (c) 2013-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2013-2018 Intel, Inc. All rights reserved.
* Copyright (c) 2014-2018 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2017 IBM Corporation. All rights reserved.
@ -653,6 +653,7 @@ static void orte_job_construct(orte_job_t* job)
ORTE_FLAG_SET(job, ORTE_JOB_FLAG_FORWARD_OUTPUT);
OBJ_CONSTRUCT(&job->attributes, opal_list_t);
OBJ_CONSTRUCT(&job->launch_msg, opal_buffer_t);
}
static void orte_job_destruct(orte_job_t* job)
@ -715,6 +716,8 @@ static void orte_job_destruct(orte_job_t* job)
/* release the attributes */
OPAL_LIST_DESTRUCT(&job->attributes);
OBJ_DESTRUCT(&job->launch_msg);
if (NULL != orte_job_data && ORTE_JOBID_INVALID != job->jobid) {
/* remove the job from the global array */
opal_hash_table_remove_value_uint32(orte_job_data, job->jobid);

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

@ -13,7 +13,7 @@
* Copyright (c) 2007-2017 Cisco Systems, Inc. All rights reserved
* Copyright (c) 2011-2013 Los Alamos National Security, LLC.
* All rights reserved.
* Copyright (c) 2013-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2013-2018 Intel, Inc. All rights reserved.
* Copyright (c) 2017 IBM Corporation. All rights reserved.
* Copyright (c) 2017-2018 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
@ -365,6 +365,8 @@ typedef struct {
orte_job_flags_t flags;
/* attributes */
opal_list_t attributes;
/* launch msg buffer */
opal_buffer_t launch_msg;
} orte_job_t;
ORTE_DECLSPEC OBJ_CLASS_DECLARATION(orte_job_t);

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

@ -89,6 +89,24 @@
/* ensure I can behave like a daemon */
#include "prun.h"
typedef struct {
opal_object_t super;
opal_pmix_lock_t lock;
opal_list_t info;
} myinfo_t;
static void mcon(myinfo_t *p)
{
OPAL_PMIX_CONSTRUCT_LOCK(&p->lock);
OBJ_CONSTRUCT(&p->info, opal_list_t);
}
static void mdes(myinfo_t *p)
{
OPAL_PMIX_DESTRUCT_LOCK(&p->lock);
OPAL_LIST_DESTRUCT(&p->info);
}
static OBJ_CLASS_INSTANCE(myinfo_t, opal_object_t,
mcon, mdes);
static struct {
bool terminate_dvm;
bool system_server_first;
@ -99,6 +117,7 @@ static struct {
static opal_list_t job_info;
static volatile bool active = false;
static orte_jobid_t myjobid = ORTE_JOBID_INVALID;
static myinfo_t myinfo;
static int create_app(int argc, char* argv[],
opal_list_t *jdata,
@ -209,17 +228,70 @@ static void evhandler(int status,
}
}
typedef struct {
opal_pmix_lock_t lock;
opal_list_t list;
} mylock_t;
static void setupcbfunc(int status,
opal_list_t *info,
void *provided_cbdata,
opal_pmix_op_cbfunc_t cbfunc, void *cbdata)
{
mylock_t *mylock = (mylock_t*)provided_cbdata;
opal_value_t *kv;
if (NULL != info) {
/* cycle across the provided info */
while (NULL != (kv = (opal_value_t*)opal_list_remove_first(info))) {
opal_list_append(&mylock->list, &kv->super);
}
}
/* release the caller */
if (NULL != cbfunc) {
cbfunc(OPAL_SUCCESS, cbdata);
}
OPAL_PMIX_WAKEUP_THREAD(&mylock->lock);
}
static void launchhandler(int status,
const opal_process_name_t *source,
opal_list_t *info, opal_list_t *results,
opal_pmix_notification_complete_fn_t cbfunc,
void *cbdata)
{
opal_value_t *p;
/* the info list will include the launch directives, so
* transfer those to the myinfo_t for return to the main thread */
while (NULL != (p = (opal_value_t*)opal_list_remove_first(info))) {
opal_list_append(&myinfo.info, &p->super);
}
/* we _always_ have to execute the evhandler callback or
* else the event progress engine will hang */
if (NULL != cbfunc) {
cbfunc(OPAL_SUCCESS, NULL, NULL, NULL, cbdata);
}
/* now release the thread */
OPAL_PMIX_WAKEUP_THREAD(&myinfo.lock);
}
int prun(int argc, char *argv[])
{
int rc, i;
char *param;
opal_pmix_lock_t lock;
opal_list_t apps;
opal_list_t apps, *lt;
opal_pmix_app_t *app;
opal_value_t *val;
opal_list_t info;
opal_value_t *val, *kv, *kv2;
opal_list_t info, codes;
struct timespec tp = {0, 100000};
mylock_t mylock;
/* init the globals */
memset(&orte_cmd_options, 0, sizeof(orte_cmd_options));
@ -477,7 +549,17 @@ int prun(int argc, char *argv[])
val = OBJ_NEW(opal_value_t);
val->key = strdup(OPAL_PMIX_OUTPUT_TO_FILE);
val->type = OPAL_STRING;
val->data.string = strdup(orte_cmd_options.output_filename);
/* if the given filename isn't an absolute path, then
* convert it to one so the name will be relative to
* the directory where prun was given as that is what
* the user will have seen */
if (!opal_path_is_absolute(orte_cmd_options.output_filename)) {
char cwd[OPAL_PATH_MAX];
getcwd(cwd, sizeof(cwd));
val->data.string = opal_os_path(false, cwd, orte_cmd_options.output_filename, NULL);
} else {
val->data.string = strdup(orte_cmd_options.output_filename);
}
opal_list_append(&job_info, &val->super);
}
/* if we were asked to merge stderr to stdout, mark it so */
@ -633,6 +715,91 @@ int prun(int argc, char *argv[])
opal_list_append(&job_info, &val->super);
}
/* pickup any relevant envars */
if (NULL != opal_pmix.server_setup_application) {
OBJ_CONSTRUCT(&info, opal_list_t);
val = OBJ_NEW(opal_value_t);
val->key = strdup(OPAL_PMIX_SETUP_APP_ENVARS);
val->type = OPAL_BOOL;
val->data.flag = true;
opal_list_append(&info, &val->super);
OPAL_PMIX_CONSTRUCT_LOCK(&mylock.lock);
OBJ_CONSTRUCT(&mylock.list, opal_list_t);
rc = opal_pmix.server_setup_application(ORTE_PROC_MY_NAME->jobid,
&info, setupcbfunc, &mylock);
if (OPAL_SUCCESS != rc) {
OPAL_LIST_DESTRUCT(&info);
OPAL_PMIX_DESTRUCT_LOCK(&mylock.lock);
OBJ_DESTRUCT(&mylock.list);
goto DONE;
}
OPAL_PMIX_WAIT_THREAD(&mylock.lock);
OPAL_PMIX_DESTRUCT_LOCK(&mylock.lock);
/* transfer any returned ENVARS to the job_info */
while (NULL != (val = (opal_value_t*)opal_list_remove_first(&mylock.list))) {
if (0 == strcmp(val->key, OPAL_PMIX_SET_ENVAR) ||
0 == strcmp(val->key, OPAL_PMIX_ADD_ENVAR) ||
0 == strcmp(val->key, OPAL_PMIX_UNSET_ENVAR) ||
0 == strcmp(val->key, OPAL_PMIX_PREPEND_ENVAR) ||
0 == strcmp(val->key, OPAL_PMIX_APPEND_ENVAR)) {
opal_list_append(&job_info, &val->super);
} else {
OBJ_RELEASE(val);
}
}
OPAL_LIST_DESTRUCT(&mylock.list);
}
/* if we were launched by a tool wanting to direct our
* operation, then we need to pause here and give it
* a chance to tell us what we need to do */
if (NULL != (param = getenv("PMIX_LAUNCHER_PAUSE_FOR_TOOL")) &&
0 == strcmp(param, "1")) {
/* register for the PMIX_LAUNCH_DIRECTIVE event */
OPAL_PMIX_CONSTRUCT_LOCK(&lock);
OBJ_CONSTRUCT(&codes, opal_list_t);
val = OBJ_NEW(opal_value_t);
val->key = strdup("foo");
val->type = OPAL_INT;
val->data.integer = OPAL_PMIX_LAUNCH_DIRECTIVE;
opal_list_append(&codes, &val->super);
/* setup the myinfo object to capture the returned
* values - must do so prior to registering in case
* the event has already arrived */
OBJ_CONSTRUCT(&myinfo, myinfo_t);
/* go ahead and register */
opal_pmix.register_evhandler(&codes, NULL, launchhandler, regcbfunc, &lock);
OPAL_PMIX_WAIT_THREAD(&lock);
OPAL_PMIX_DESTRUCT_LOCK(&lock);
OPAL_LIST_DESTRUCT(&codes);
/* now wait for the launch directives to arrive */
OPAL_PMIX_WAIT_THREAD(&myinfo.lock);
/* process the returned directives */
OPAL_LIST_FOREACH(val, &myinfo.info, opal_value_t) {
if (0 == strcmp(val->key, OPAL_PMIX_DEBUG_JOB_DIRECTIVES)) {
/* there will be a pointer to a list containing the directives */
lt = (opal_list_t*)val->data.ptr;
while (NULL != (kv = (opal_value_t*)opal_list_remove_first(lt))) {
opal_output(0, "JOB DIRECTIVE: %s", kv->key);
opal_list_append(&job_info, &kv->super);
}
} else if (0 == strcmp(val->key, OPAL_PMIX_DEBUG_APP_DIRECTIVES)) {
/* there will be a pointer to a list containing the directives */
lt = (opal_list_t*)val->data.ptr;
OPAL_LIST_FOREACH(kv, lt, opal_value_t) {
opal_output(0, "APP DIRECTIVE: %s", kv->key);
OPAL_LIST_FOREACH(app, &apps, opal_pmix_app_t) {
/* the value can only be on one list at a time, so replicate it */
kv2 = OBJ_NEW(opal_value_t);
opal_value_xfer(kv2, kv);
opal_list_append(&app->info, &kv2->super);
}
}
}
}
}
if (OPAL_SUCCESS != (rc = opal_pmix.spawn(&job_info, &apps, &myjobid))) {
opal_output(0, "Job failed to spawn: %s", opal_strerror(rc));
goto DONE;

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

@ -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,81 @@ 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;
}
int orte_prepend_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_prepend(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 +239,16 @@ 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_APP_ADD_ENVAR:
return "ORTE_APP_ADD_ENVAR";
case ORTE_NODE_USERNAME:
return "NODE-USERNAME";
@ -290,6 +369,18 @@ 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_JOB_ADD_ENVAR:
return "ORTE_APP_ADD_ENVAR";
case ORTE_JOB_APP_SETUP_DATA:
return "ORTE_JOB_APP_SETUP_DATA";
case ORTE_PROC_NOBARRIER:
return "PROC-NOBARRIER";
@ -360,11 +451,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 +577,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 +596,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 +708,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;

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

@ -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,11 @@ 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_ADD_ENVAR 21 // opal_envar_t - add envar, do not override pre-existing one
#define ORTE_APP_MAX_KEY 100
@ -146,6 +151,12 @@ 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_ADD_ENVAR (ORTE_JOB_START_KEY + 59) // opal_envar_t - add envar, do not override pre-existing one
#define ORTE_JOB_APP_SETUP_DATA (ORTE_JOB_START_KEY + 60) // opal_byte_object_t - blob containing app setup data
#define ORTE_JOB_MAX_KEY 300
@ -221,6 +232,24 @@ 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_prepend_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
*

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

@ -12,7 +12,7 @@
* Copyright (c) 2010-2016 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2011-2013 Los Alamos National Security, LLC.
* All rights reserved.
* Copyright (c) 2014-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2014-2018 Intel, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -253,6 +253,8 @@ const char *orte_job_state_to_str(orte_job_state_t state)
return "VM READY";
case ORTE_JOB_STATE_LAUNCH_APPS:
return "PENDING APP LAUNCH";
case ORTE_JOB_STATE_SEND_LAUNCH_MSG:
return "SENDING LAUNCH MSG";
case ORTE_JOB_STATE_RUNNING:
return "RUNNING";
case ORTE_JOB_STATE_SUSPENDED: